From 6c91951e02706e08116d2e1ab66ad93f6bb27a0e Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Sun, 17 Feb 2019 22:59:01 +0800 Subject: [PATCH] [Add] general functions of VN Trader 1. use json instead of shelve for setting/data storage 2. call original sys.__excepthook__ before showing exception with QMessageBox --- .gitignore | 3 ++ vnpy/app/cta_strategy/engine.py | 47 ++++++++---------- .../strategies/double_ma_strategy.py | 2 +- vnpy/gateway/ctp/ctp_gateway.py | 10 ++-- vnpy/trader/database.py | 6 +-- vnpy/trader/engine.py | 5 +- vnpy/trader/ui/__init__.py | 7 ++- vnpy/trader/ui/ico/forum.ico | Bin 0 -> 67646 bytes vnpy/trader/ui/mainwindow.py | 15 ++++-- vnpy/trader/ui/widget.py | 8 +-- 10 files changed, 58 insertions(+), 45 deletions(-) create mode 100644 vnpy/trader/ui/ico/forum.ico diff --git a/.gitignore b/.gitignore index 7ac72ffe..15d7ed33 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ build dist *.local + +# vn.py +.vntrader \ No newline at end of file diff --git a/vnpy/app/cta_strategy/engine.py b/vnpy/app/cta_strategy/engine.py index 38ed0581..f7a0ce93 100644 --- a/vnpy/app/cta_strategy/engine.py +++ b/vnpy/app/cta_strategy/engine.py @@ -2,7 +2,6 @@ import importlib import os -import shelve import traceback from collections import defaultdict from pathlib import Path @@ -21,7 +20,7 @@ from vnpy.trader.object import ( ) from vnpy.trader.event import EVENT_TICK, EVENT_ORDER, EVENT_TRADE from vnpy.trader.constant import Direction, PriceType, Interval -from vnpy.trader.utility import get_temp_path, load_json, save_json +from vnpy.trader.utility import load_json, save_json from vnpy.trader.database import DbTickData, DbBarData from .base import ( @@ -43,7 +42,7 @@ class CtaEngine(BaseEngine): engine_type = EngineType.LIVE # live trading engine - setting_filename = "cta_strategy_setting.vt" + setting_filename = "cta_strategy_setting.json" data_filename = "cta_strategy_data.json" def __init__(self, main_engine: MainEngine, event_engine: EventEngine): @@ -52,6 +51,7 @@ class CtaEngine(BaseEngine): main_engine, event_engine, "CtaStrategy") self.setting_file = None # setting file object + self.strategy_setting = {} # strategy_name: dict self.strategy_data = {} # strategy_name: dict self.classes = {} # class_name: stategy_class @@ -80,7 +80,7 @@ class CtaEngine(BaseEngine): def close(self): """""" - self.save_strategy_setting() + pass def register_event(self): """""" @@ -410,7 +410,7 @@ class CtaEngine(BaseEngine): def init_strategy(self, strategy_name: str): """ Init a strategy. - """ + """ self.init_queue.put(strategy_name) if not self.init_thread: @@ -612,12 +612,15 @@ class CtaEngine(BaseEngine): """ Load setting file. """ - filepath = str(get_temp_path(self.setting_filename)) - self.setting_file = shelve.open(filepath) + self.strategy_setting = load_json(self.setting_filename) - for tp in list(self.setting_file.values()): - class_name, strategy_name, vt_symbol, setting = tp - self.add_strategy(class_name, strategy_name, vt_symbol, setting) + for strategy_name, strategy_config in self.strategy_setting.items(): + self.add_strategy( + strategy_config["class_name"], + strategy_name, + strategy_config["vt_symbol"], + strategy_config["setting"] + ) def update_strategy_setting(self, strategy_name: str, setting: dict): """ @@ -625,13 +628,12 @@ class CtaEngine(BaseEngine): """ strategy = self.strategies[strategy_name] - self.setting_file[strategy_name] = ( - strategy.__class__.__name__, - strategy_name, - strategy.vt_symbol, - setting, - ) - self.setting_file.sync() + self.strategy_setting[strategy_name] = { + "class_name": strategy.__class__.__name__, + "vt_symbol": strategy.vt_symbol, + "setting": setting, + } + save_json(self.setting_filename, self.strategy_setting) def remove_strategy_setting(self, strategy_name: str): """ @@ -640,15 +642,8 @@ class CtaEngine(BaseEngine): if strategy_name not in self.setting_file: return - self.setting_file.pop(strategy_name) - self.setting_file.sync() - - def save_strategy_setting(self): - """ - Save and close setting file. - """ - if self.setting_file: - self.setting_file.close() + self.strategy_setting.pop(strategy_name) + save_json(self.setting_filename, self.strategy_setting) def put_stop_order_event(self, stop_order: StopOrder): """ diff --git a/vnpy/app/cta_strategy/strategies/double_ma_strategy.py b/vnpy/app/cta_strategy/strategies/double_ma_strategy.py index 1547c408..779bdbad 100644 --- a/vnpy/app/cta_strategy/strategies/double_ma_strategy.py +++ b/vnpy/app/cta_strategy/strategies/double_ma_strategy.py @@ -5,7 +5,7 @@ class DoubleMaStrategy(CtaTemplate): author = "用Python的交易员" fast_window = 10 - slow_window = 20.10 + slow_window = 20 fast_ma = 0.0 slow_ma = 0.0 diff --git a/vnpy/gateway/ctp/ctp_gateway.py b/vnpy/gateway/ctp/ctp_gateway.py index b95e1af0..1129d897 100644 --- a/vnpy/gateway/ctp/ctp_gateway.py +++ b/vnpy/gateway/ctp/ctp_gateway.py @@ -27,7 +27,7 @@ from vnpy.trader.object import ( CancelRequest, SubscribeRequest, ) -from vnpy.trader.utility import get_temp_path +from vnpy.trader.utility import get_folder_path from vnpy.trader.event import EVENT_TIMER @@ -305,8 +305,8 @@ class CtpMdApi(MdApi): # If not connected, then start connection first. if not self.connect_status: - path = get_temp_path(f"{self.gateway_name}_md_" ) - self.createFtdcMdApi(str(path)) + path = get_folder_path(self.gateway_name.lower()) + self.createFtdcMdApi(str(path) + "\\Md") self.registerFront(address) self.init() @@ -1076,8 +1076,8 @@ class CtpTdApi(TdApi): self.product_info = product_info if not self.connect_status: - path = get_temp_path(f"{self.gateway_name}_td_") - self.createFtdcTraderApi(str(path)) + path = get_folder_path(self.gateway_name.lower()) + self.createFtdcTraderApi(str(path) + "\\Td") self.subscribePrivateTopic(0) self.subscribePublicTopic(0) diff --git a/vnpy/trader/database.py b/vnpy/trader/database.py index aa44a79f..87fb3eae 100644 --- a/vnpy/trader/database.py +++ b/vnpy/trader/database.py @@ -4,10 +4,10 @@ from peewee import SqliteDatabase, Model, CharField, DateTimeField, FloatField from .constant import Exchange, Interval from .object import BarData, TickData -from .utility import get_temp_path +from .utility import get_file_path -DB_NAME = "database.vt" -DB = SqliteDatabase(str(get_temp_path(DB_NAME))) +DB_NAME = "database.db" +DB = SqliteDatabase(str(get_file_path(DB_NAME))) class DbBarData(Model): diff --git a/vnpy/trader/engine.py b/vnpy/trader/engine.py index 2eed3ff4..9ba94082 100644 --- a/vnpy/trader/engine.py +++ b/vnpy/trader/engine.py @@ -24,7 +24,7 @@ from .event import ( from .gateway import BaseGateway from .object import CancelRequest, LogData, OrderRequest, SubscribeRequest from .setting import SETTINGS -from .utility import Singleton, get_temp_path +from .utility import Singleton, get_folder_path class MainEngine: @@ -246,7 +246,8 @@ class LogEngine(BaseEngine): """ today_date = datetime.now().strftime("%Y%m%d") filename = f"vt_{today_date}.log" - file_path = get_temp_path(filename) + log_path = get_folder_path("log") + file_path = log_path.joinpath(filename) file_handler = logging.FileHandler( file_path, mode="w", encoding="utf8" diff --git a/vnpy/trader/ui/__init__.py b/vnpy/trader/ui/__init__.py index e88065ae..16f6fcd1 100644 --- a/vnpy/trader/ui/__init__.py +++ b/vnpy/trader/ui/__init__.py @@ -12,7 +12,12 @@ from ..utility import get_icon_path def excepthook(exctype, value, tb): - """异常捕捉钩子""" + """ + Raise exception under debug mode, otherwise + show exception detail with QMessageBox. + """ + sys.__excepthook__(exctype, value, tb) + msg = "".join(traceback.format_exception(exctype, value, tb)) QtWidgets.QMessageBox.critical( None, "Exception", msg, QtWidgets.QMessageBox.Ok diff --git a/vnpy/trader/ui/ico/forum.ico b/vnpy/trader/ui/ico/forum.ico new file mode 100644 index 0000000000000000000000000000000000000000..edfad2b4d998261fa42b5834b328381b7362e193 GIT binary patch literal 67646 zcmeI5O-|cT6ori#&>0}&W(2F}B9U$KY32R~yvgkTTNmbz~3!5TQ;SlLz+jpXhaHyLn;{|Iolr7>`Hx@Sos! zNV|Au5C4$hj*Mjn_EGXzK5W!-rxrba7B>&dk=O;bS@GV%+-v5e;jg&sx~Ja#dJq%; zJNSFge@y(TeZRG@{q)ZNEJA0RGYP_mTnlN6p_k1MrWYzf%U_p9FvF48T7b{#F@)e^UI7GXVeO_#0=S;H&3= zs)-xNx|rkozrOyf*-l-&Un}mJl(0yIKYhS5qY3dR0~Q%bj6WGL%s_(t$$&uy66H?@ zCT1XE{$yZ61`_8_21YWF0e>=ZA_JN5KV(2(S4wf&sORfgGUBf@kn*ChftE)> zAK3u^wK}MV14x za$2S5v5C*s=YAbR{ipp}Z!ACXhySD=%=w@5Kj;7CGC=>Q|I`2T%>ebEFMIvk0RHf& z|L2OWuh^#8os!yo?i|GYB*fA};1&o=|qf4=OQ|K-gd{_v;&=bZug!=L$oz8RqY z^JUNcFK_nnhd=#4?+m~n{!7jOKTmofgPr*Nm-GA4m#ly9|ECZB(eR&~GlTLk;2#D5 zU+Qy1R)2G7EDP`tn*W31Ue3i{X9NDr@gJ+j|FIqZ@K+ho*RfdaJeXx(wp1^m{+)9V zf4jO#rQg6G{!6uM?~gNyDW)cm1Aq8){&&g% z=YP)sCM`Fped+&Bwa@uK@7jky{5k*Uoq^c-Uo-!Angi^Dn$TGcM)AKR1J)V1wy->? zyD0Yb0K0RT(f@x73c46fn*sX3^c_*hvJ4CxHVvfCD&y z12}*KIDi8PaUg&$F zE1^rFi@tsq`bp?Vq4z@H3tb6a3SG3i>QeSHo>J&ew)>ydzv{ZT{io2kLjMrDl6u=e zUbPl_CG@4x7eb#4eb!~5@wY0Z-X2!8+t)&`guWE|Lg)^9d%SJ{t?mYJ(5;`f&|9I` zLa)%u>Z(g)hJL8%^`5`fDypxxH#tQg0<&uTxIf53>UFby-)-ME`l-{64E^RGd@