diff --git a/install.bat b/install.bat index 3a3adf09..1e3c6227 100644 --- a/install.bat +++ b/install.bat @@ -5,6 +5,7 @@ pip install -r requirements.txt conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --set show_channel_urls yes conda install -c quantopian ta-lib=0.4.9 +conda install -c conda-forge python-snappy :: Install vn.py python setup.py install \ No newline at end of file diff --git a/install.sh b/install.sh index 27fd9235..fde32554 100755 --- a/install.sh +++ b/install.sh @@ -24,6 +24,7 @@ pip install -r requirements.txt conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --set show_channel_urls yes conda install -c quantopian ta-lib=0.4.9 +conda install -c conda-forge python-snappy #Install vn.py python setup.py install diff --git a/vnpy/trader/app/optionMaster/omEngine.py b/vnpy/trader/app/optionMaster/omEngine.py index 2e2e789c..d3aa6a41 100644 --- a/vnpy/trader/app/optionMaster/omEngine.py +++ b/vnpy/trader/app/optionMaster/omEngine.py @@ -9,7 +9,7 @@ from collections import OrderedDict from vnpy.event import Event from vnpy.trader.vtEvent import (EVENT_TICK, EVENT_TRADE, EVENT_CONTRACT, - EVENT_ORDER) + EVENT_ORDER, EVENT_TIMER) from vnpy.trader.vtFunction import getTempPath, getJsonPath from vnpy.trader.vtObject import (VtLogData, VtSubscribeReq, VtOrderReq, VtCancelOrderReq) @@ -22,6 +22,7 @@ from vnpy.pricing import black, bs, crr from .omBase import (OmOption, OmUnderlying, OmChain, OmPortfolio, EVENT_OM_LOG, OM_DB_NAME) +from .strategy import STRATEGY_CLASS @@ -225,6 +226,8 @@ class OmEngine(object): ######################################################################## class OmStrategyEngine(object): """策略引擎""" + settingFileName = 'OM_setting.json' + settingfilePath = getJsonPath(settingFileName, __file__) #---------------------------------------------------------------------- def __init__(self, omEngine, eventEngine): @@ -238,6 +241,8 @@ class OmStrategyEngine(object): self.strategyDict = {} # name: strategy self.symbolStrategyDict = {} # vtSymbol:strategy list self.orderStrategyDict= {} # vtOrderID: strategy + + self.registerEvent() #---------------------------------------------------------------------- def registerEvent(self): @@ -245,6 +250,7 @@ class OmStrategyEngine(object): self.eventEngine.register(EVENT_TICK, self.processTickEvent) self.eventEngine.register(EVENT_TRADE, self.processTradeEvent) self.eventEngine.register(EVENT_ORDER, self.processOrdervent) + self.eventEngine.register(EVENT_TIMER, self.processTimerEvent) #---------------------------------------------------------------------- def writeLog(self, content): @@ -293,11 +299,53 @@ class OmStrategyEngine(object): strategy = self.orderStrategyDict.get(order.vtOrderID, None) if strategy: self.callStrategyFunc(strategy, strategy.onOrder, order) + + #---------------------------------------------------------------------- + def processTimerEvent(self, event): + """处理定时事件""" + for strategy in self.strategyDict.values(): + self.callStrategyFunc(strategy, strategy.onTimer) #---------------------------------------------------------------------- def loadSetting(self): """加载配置""" self.portfolio = self.omEngine.portfolio + + with open(self.settingfilePath) as f: + l = json.load(f) + + for setting in l: + self.loadStrategy(setting) + + #---------------------------------------------------------------------- + def loadStrategy(self, setting): + """加载策略""" + try: + name = setting['name'] + className = setting['className'] + except Exception: + msg = traceback.format_exc() + self.writeLog(u'载入策略出错:%s' %msg) + return + + # 获取策略类 + strategyClass = STRATEGY_CLASS.get(className, None) + if not strategyClass: + self.writeLog(u'找不到策略类:%s' %className) + return + + # 防止策略重名 + if name in self.strategyDict: + self.writeLog(u'策略实例重名:%s' %name) + else: + # 创建策略实例 + strategy = strategyClass(self, setting) + self.strategyDict[name] = strategy + + # 保存Tick映射关系 + for vtSymbol in strategy.vtSymbols: + l = self.symbolStrategyDict.setdefault(vtSymbol, []) + l.append(strategy) #---------------------------------------------------------------------- def initStrategy(self, name): diff --git a/vnpy/trader/app/optionMaster/omStrategy.py b/vnpy/trader/app/optionMaster/omStrategy.py index f5c6a784..12778ebc 100644 --- a/vnpy/trader/app/optionMaster/omStrategy.py +++ b/vnpy/trader/app/optionMaster/omStrategy.py @@ -7,17 +7,36 @@ from vnpy.trader.vtConstant import (DIRECTION_LONG, DIRECTION_SHORT, ######################################################################## class OmStrategyTemplate(object): """策略模板""" + className = 'OmStrategyTemplate' + author = EMPTY_UNICODE + name = EMPTY_UNICODE # 策略实例名称 + vtSymbols = [] # 交易的合约vt系统代码 + + inited = False # 是否进行了初始化 + trading = False # 是否启动交易,由引擎管理 + + # 参数列表,保存了参数的名称 + paramList = ['name', + 'className', + 'author', + 'vtSymbols'] + + # 变量列表,保存了变量的名称 + varList = ['inited', + 'trading'] #---------------------------------------------------------------------- - def __init__(self, engine): + def __init__(self, engine, setting): """Constructor""" self.engine = engine - self.name = '' - - self.inited = False - self.trading = False + self.vtSymbols = [] + # 设置策略的参数 + for key in self.paramList: + if key in setting: + self.__setattr__(key, setting[key]) + #---------------------------------------------------------------------- def onInit(self): """初始化""" @@ -47,7 +66,12 @@ class OmStrategyTemplate(object): def onOrder(self, order): """委托推送""" raise NotImplementedError - + + #---------------------------------------------------------------------- + def onTimer(self, order): + """定时推送""" + raise NotImplementedError + #---------------------------------------------------------------------- def cancelOrder(self, vtOrderID): """撤单""" diff --git a/vnpy/trader/app/optionMaster/strategy/__init__.py b/vnpy/trader/app/optionMaster/strategy/__init__.py new file mode 100644 index 00000000..5e349490 --- /dev/null +++ b/vnpy/trader/app/optionMaster/strategy/__init__.py @@ -0,0 +1,50 @@ +# encoding: UTF-8 + +''' +动态载入所有的策略类 +''' + +import os +import importlib +import traceback + +# 用来保存策略类的字典 +STRATEGY_CLASS = {} + +#---------------------------------------------------------------------- +def loadStrategyModule(moduleName): + """使用importlib动态载入模块""" + try: + module = importlib.import_module(moduleName) + + # 遍历模块下的对象,只有名称中包含'Strategy'的才是策略类 + for k in dir(module): + if 'Strategy' in k: + v = module.__getattribute__(k) + STRATEGY_CLASS[k] = v + except: + print ('-' * 20) + print ('Failed to import strategy file %s:' %moduleName) + traceback.print_exc() + + +# 遍历strategy目录下的文件 +path = os.path.abspath(os.path.dirname(__file__)) +for root, subdirs, files in os.walk(path): + for name in files: + # 只有文件名中包含strategy且非.pyc的文件,才是策略文件 + if 'omStrategy' in name and '.pyc' not in name: + # 模块名称需要模块路径前缀 + moduleName = 'vnpy.trader.app.optionMaster.strategy.' + name.replace('.py', '') + loadStrategyModule(moduleName) + + +# 遍历工作目录下的文件 +workingPath = os.getcwd() +for root, subdirs, files in os.walk(workingPath): + for name in files: + # 只有文件名中包含strategy且非.pyc的文件,才是策略文件 + if 'omStrategy' in name and '.pyc' not in name: + # 模块名称无需前缀 + moduleName = name.replace('.py', '') + loadStrategyModule(moduleName)