update
This commit is contained in:
parent
22180cf239
commit
17d908ab56
@ -26,7 +26,8 @@ class arbTemplate(object):
|
|||||||
base_symbol = EMPTY_STRING # 交易主货币 btc
|
base_symbol = EMPTY_STRING # 交易主货币 btc
|
||||||
quote_symbol = EMPTY_STRING # 基准货币 usdt
|
quote_symbol = EMPTY_STRING # 基准货币 usdt
|
||||||
spot_symbol = EMPTY_STRING # 现货交易所币对 btc_usdt
|
spot_symbol = EMPTY_STRING # 现货交易所币对 btc_usdt
|
||||||
future_symbol = EMPTY_STRING # 期货合约 btc:next_week:10
|
future_symbol = EMPTY_STRING # 期货合约 btc:next_week:10
|
||||||
|
future_net_symbol = EMPTY_STRING # 合约账号内的期货合约净仓symbol btc.[future]
|
||||||
Leg1Symbol = EMPTY_STRING # 带交易所信息的symbol,如: btc_usdt.OKEX
|
Leg1Symbol = EMPTY_STRING # 带交易所信息的symbol,如: btc_usdt.OKEX
|
||||||
Leg2Symbol = EMPTY_STRING # 带交易所信息的symbol,如: btc:next_week:10.OKEX
|
Leg2Symbol = EMPTY_STRING # 带交易所信息的symbol,如: btc:next_week:10.OKEX
|
||||||
exchange = EMPTY_STRING
|
exchange = EMPTY_STRING
|
||||||
@ -46,6 +47,7 @@ class arbTemplate(object):
|
|||||||
'quote_symbol',
|
'quote_symbol',
|
||||||
'spot_symbol',
|
'spot_symbol',
|
||||||
'future_symbol',
|
'future_symbol',
|
||||||
|
'future_net_symbol',
|
||||||
'Leg1Symbol',
|
'Leg1Symbol',
|
||||||
'Leg2Symbol',
|
'Leg2Symbol',
|
||||||
'exchange',
|
'exchange',
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -56,7 +56,7 @@ ENGINETYPE_TRADING = 'trading' # 实盘
|
|||||||
|
|
||||||
|
|
||||||
# CTA引擎中涉及的数据类定义
|
# CTA引擎中涉及的数据类定义
|
||||||
from vnpy.trader.vtConstant import *
|
from vnpy.trader.vtConstant import EMPTY_STRING,EMPTY_UNICODE,EMPTY_FLOAT,EMPTY_INT,COLOR_EQUAL
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
class StopOrder(object):
|
class StopOrder(object):
|
||||||
|
@ -266,10 +266,10 @@ class CtaEngine(object):
|
|||||||
self.writeCtaLog(msg)
|
self.writeCtaLog(msg)
|
||||||
|
|
||||||
# 发送微信
|
# 发送微信
|
||||||
try:
|
#try:
|
||||||
sendWeChatMsg(msg, target=self.ctaEngine.mainEngine.gatewayDetailList[0]['gatewayName'])
|
# sendWeChatMsg(msg, target=self.mainEngine.gatewayDetailList[0]['gatewayName'])
|
||||||
except:
|
#except:
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
return vtOrderID
|
return vtOrderID
|
||||||
|
|
||||||
@ -294,11 +294,11 @@ class CtaEngine(object):
|
|||||||
self.mainEngine.cancelOrder(req, order.gatewayName)
|
self.mainEngine.cancelOrder(req, order.gatewayName)
|
||||||
|
|
||||||
# 发送微信
|
# 发送微信
|
||||||
try:
|
#try:
|
||||||
msg = u'发送撤单指令,%s, %s,%s' % (order.symbol, order.orderID, order.gatewayName)
|
# msg = u'发送撤单指令,%s, %s,%s' % (order.symbol, order.orderID, order.gatewayName)
|
||||||
sendWeChatMsg(msg, target=self.ctaEngine.mainEngine.gatewayDetailList[0]['gatewayName'])
|
# sendWeChatMsg(msg, target=self.mainEngine.gatewayDetailList[0]['gatewayName'])
|
||||||
except:
|
#except:
|
||||||
pass
|
# pass
|
||||||
else:
|
else:
|
||||||
if order.status == STATUS_ALLTRADED:
|
if order.status == STATUS_ALLTRADED:
|
||||||
self.writeCtaLog(u'委托单({0}已执行,无法撤销'.format(vtOrderID))
|
self.writeCtaLog(u'委托单({0}已执行,无法撤销'.format(vtOrderID))
|
||||||
@ -343,11 +343,11 @@ class CtaEngine(object):
|
|||||||
self.mainEngine.cancelOrder(req, order.gatewayName)
|
self.mainEngine.cancelOrder(req, order.gatewayName)
|
||||||
|
|
||||||
# 发送微信
|
# 发送微信
|
||||||
try:
|
#try:
|
||||||
msg = u'撤销所有单,{}'.format(symbol)
|
# msg = u'撤销所有单,{}'.format(symbol)
|
||||||
sendWeChatMsg(msg, target=self.ctaEngine.mainEngine.gatewayDetailList[0]['gatewayName'])
|
# sendWeChatMsg(msg, target=self.mainEngine.gatewayDetailList[0]['gatewayName'])
|
||||||
except:
|
#except:
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def sendStopOrder(self, vtSymbol, orderType, price, volume, strategy):
|
def sendStopOrder(self, vtSymbol, orderType, price, volume, strategy):
|
||||||
@ -388,10 +388,10 @@ class CtaEngine(object):
|
|||||||
self.writeCtaLog(msg)
|
self.writeCtaLog(msg)
|
||||||
|
|
||||||
# 发送微信
|
# 发送微信
|
||||||
try:
|
#try:#
|
||||||
sendWeChatMsg(msg, target=self.ctaEngine.mainEngine.gatewayDetailList[0]['gatewayName'])
|
# sendWeChatMsg(msg, target=self.mainEngine.gatewayDetailList[0]['gatewayName'])
|
||||||
except:
|
#except:
|
||||||
pass
|
# pass
|
||||||
return stopOrderID
|
return stopOrderID
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
@ -408,19 +408,19 @@ class CtaEngine(object):
|
|||||||
self.writeCtaLog(u'撤销停止单:{0}成功.'.format(stopOrderID))
|
self.writeCtaLog(u'撤销停止单:{0}成功.'.format(stopOrderID))
|
||||||
|
|
||||||
# 发送微信
|
# 发送微信
|
||||||
try:
|
#try:
|
||||||
sendWeChatMsg(u'撤销停止单:{0}成功.'.format(stopOrderID), target=self.ctaEngine.mainEngine.gatewayDetailList[0]['gatewayName'])
|
# sendWeChatMsg(u'撤销停止单:{0}成功.'.format(stopOrderID), target=self.mainEngine.gatewayDetailList[0]['gatewayName'])
|
||||||
except:
|
#except:
|
||||||
pass
|
# pass
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.writeCtaLog(u'撤销停止单:{0}失败,不存在Id.'.format(stopOrderID))
|
self.writeCtaLog(u'撤销停止单:{0}失败,不存在Id.'.format(stopOrderID))
|
||||||
|
|
||||||
# 发送微信
|
# 发送微信
|
||||||
try:
|
#try:
|
||||||
sendWeChatMsg(u'撤销停止单:{0}失败,不存在Id.'.format(stopOrderID), target=self.ctaEngine.mainEngine.gatewayDetailList[0]['gatewayName'])
|
# sendWeChatMsg(u'撤销停止单:{0}失败,不存在Id.'.format(stopOrderID), target=self.mainEngine.gatewayDetailList[0]['gatewayName'])
|
||||||
except:
|
#except:
|
||||||
pass
|
# pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@ -9,5 +9,5 @@ from vnpy.trader.app.ctaStrategy.language.chinese import text
|
|||||||
|
|
||||||
# 是否要使用英文
|
# 是否要使用英文
|
||||||
from vnpy.trader.vtGlobal import globalSetting
|
from vnpy.trader.vtGlobal import globalSetting
|
||||||
if globalSetting['language'] == 'english':
|
if len(globalSetting) > 0 and globalSetting['language'] == 'english':
|
||||||
from vnpy.trader.app.ctaStrategy.language.english import text
|
from vnpy.trader.app.ctaStrategy.language.english import text
|
@ -1,20 +1,42 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
'''
|
'''
|
||||||
动态载入所有的策略类
|
动态载入所有的策略类,先从vnpy/trader/app/ctaStrategy/strategy下加载,其次,从工作目录下strategy加载。
|
||||||
|
如果重复,工作目录的strategy优先。
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
# 用来保存策略类的字典
|
# 用来保存策略类的字典
|
||||||
STRATEGY_CLASS = {}
|
STRATEGY_CLASS = {}
|
||||||
|
|
||||||
# 获取目录路径
|
# ----------------------------------------------------------------------
|
||||||
|
def loadStrategyModule(moduleName):
|
||||||
|
"""使用importlib动态载入模块"""
|
||||||
|
try:
|
||||||
|
print('loading {0}'.format(moduleName))
|
||||||
|
module = importlib.import_module(moduleName)
|
||||||
|
|
||||||
|
# 遍历模块下的对象,只有名称中包含'Strategy'的才是策略类
|
||||||
|
for k in dir(module):
|
||||||
|
if 'Strategy' in k:
|
||||||
|
print('adding {} into STRATEGY_CLASS'.format(k))
|
||||||
|
v = module.__getattribute__(k)
|
||||||
|
if k in STRATEGY_CLASS:
|
||||||
|
print('Replace strategy {} with {}'.format(k,moduleName))
|
||||||
|
STRATEGY_CLASS[k] = v
|
||||||
|
except Exception as ex:
|
||||||
|
print('-' * 20)
|
||||||
|
print('Failed to import strategy file %s:' % moduleName)
|
||||||
|
print('Exception:{},{}'.format(str(ex),traceback.format_exc()))
|
||||||
|
|
||||||
|
# 获取目录路径
|
||||||
path = os.path.abspath(os.path.dirname(__file__))
|
path = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
print ('init {0}'.format(path))
|
print('init strategies from {}'.format(path))
|
||||||
|
|
||||||
# 遍历strategy目录下的文件
|
# 遍历strategy目录下的文件
|
||||||
for root, subdirs, files in os.walk(path):
|
for root, subdirs, files in os.walk(path):
|
||||||
@ -23,19 +45,20 @@ for root, subdirs, files in os.walk(path):
|
|||||||
if 'strategy' in name and '.pyc' not in name:
|
if 'strategy' in name and '.pyc' not in name:
|
||||||
# 模块名称需要上前缀
|
# 模块名称需要上前缀
|
||||||
moduleName = 'vnpy.trader.app.ctaStrategy.strategy.' + name.replace('.py', '')
|
moduleName = 'vnpy.trader.app.ctaStrategy.strategy.' + name.replace('.py', '')
|
||||||
print ('loading {0}'.format(moduleName))
|
loadStrategyModule(moduleName)
|
||||||
try:
|
|
||||||
# 使用importlib动态载入模块
|
|
||||||
module = importlib.import_module(moduleName)
|
|
||||||
except Exception as ex:
|
|
||||||
print ('load fail,excepion:{0}'.format(ex))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 遍历模块下的对象,只有名称中包含'Strategy'的才是策略类
|
|
||||||
for k in dir(module):
|
|
||||||
if 'Strategy' in k:
|
|
||||||
print ('adding {0} into STRATEGY_CLASS'.format(k))
|
|
||||||
v = module.__getattribute__(k)
|
|
||||||
STRATEGY_CLASS[k] = v
|
|
||||||
|
|
||||||
print( 'finished load strategy modules')
|
# 遍历工作目录下的文件
|
||||||
|
#stratey_working_path = os.path.abspath(os.path.join(os.getcwd(), 'strategy'))
|
||||||
|
#
|
||||||
|
#if os.path.exists(stratey_working_path):
|
||||||
|
# print('init strategies from {}'.format(stratey_working_path))
|
||||||
|
# for root, subdirs, files in os.walk(stratey_working_path):
|
||||||
|
# for name in files:
|
||||||
|
# # 只有文件名中包含strategy且非.pyc的文件,才是策略文件
|
||||||
|
# if 'strategy' in name and '.pyc' not in name:
|
||||||
|
# # 模块名称无需前缀
|
||||||
|
# moduleName = name.replace('.py', '')
|
||||||
|
# loadStrategyModule(moduleName)
|
||||||
|
#
|
||||||
|
print('finished load strategy modules')
|
||||||
|
@ -496,7 +496,7 @@ class SniperAlgo(StAlgoTemplate):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def cancelAllOrders(self):
|
def cancelAllOrders(self):
|
||||||
"""撤销全部委托"""
|
"""撤销全部委托"""
|
||||||
for orderList in self.legOrderDict.values():
|
for orderList in list(self.legOrderDict.values()):
|
||||||
for vtOrderID in orderList:
|
for vtOrderID in orderList:
|
||||||
self.algoEngine.cancelOrder(vtOrderID)
|
self.algoEngine.cancelOrder(vtOrderID)
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ class StDataEngine(object):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def getAllSpreads(self):
|
def getAllSpreads(self):
|
||||||
"""获取所有的价差"""
|
"""获取所有的价差"""
|
||||||
return self.spreadDict.values()
|
return list(self.spreadDict.values())
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -343,7 +343,7 @@ class StAlgoEngine(object):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def processTimerEvent(self, event):
|
def processTimerEvent(self, event):
|
||||||
""""""
|
""""""
|
||||||
for algo in self.algoDict.values():
|
for algo in list(self.algoDict.values()):
|
||||||
algo.updateTimer()
|
algo.updateTimer()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -450,7 +450,7 @@ class StAlgoEngine(object):
|
|||||||
def saveSetting(self):
|
def saveSetting(self):
|
||||||
"""保存算法配置"""
|
"""保存算法配置"""
|
||||||
setting = {}
|
setting = {}
|
||||||
for algo in self.algoDict.values():
|
for algo in list(self.algoDict.values()):
|
||||||
setting[algo.spreadName] = algo.getAlgoParams()
|
setting[algo.spreadName] = algo.getAlgoParams()
|
||||||
|
|
||||||
f = shelve.open(self.algoFilePath)
|
f = shelve.open(self.algoFilePath)
|
||||||
@ -478,7 +478,7 @@ class StAlgoEngine(object):
|
|||||||
if not setting:
|
if not setting:
|
||||||
return
|
return
|
||||||
|
|
||||||
for algo in self.algoDict.values():
|
for algo in list(self.algoDict.values()):
|
||||||
if algo.spreadName in setting:
|
if algo.spreadName in setting:
|
||||||
d = setting[algo.spreadName]
|
d = setting[algo.spreadName]
|
||||||
algo.setAlgoParams(d)
|
algo.setAlgoParams(d)
|
||||||
@ -486,7 +486,7 @@ class StAlgoEngine(object):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def stopAll(self):
|
def stopAll(self):
|
||||||
"""停止全部算法"""
|
"""停止全部算法"""
|
||||||
for algo in self.algoDict.values():
|
for algo in list(self.algoDict.values()):
|
||||||
algo.stop()
|
algo.stop()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -506,7 +506,7 @@ class StAlgoEngine(object):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def getAllAlgoParams(self):
|
def getAllAlgoParams(self):
|
||||||
"""获取所有算法的参数"""
|
"""获取所有算法的参数"""
|
||||||
return [algo.getAlgoParams() for algo in self.algoDict.values()]
|
return [algo.getAlgoParams() for algo in list(self.algoDict.values())]
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def setAlgoBuyPrice(self, spreadName, buyPrice):
|
def setAlgoBuyPrice(self, spreadName, buyPrice):
|
||||||
|
@ -429,7 +429,7 @@ class StAlgoManager(QtWidgets.QTableWidget):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def stopAll(self):
|
def stopAll(self):
|
||||||
"""停止所有算法"""
|
"""停止所有算法"""
|
||||||
for button in self.buttonActiveDict.values():
|
for button in list(self.buttonActiveDict.values()):
|
||||||
button.stop()
|
button.stop()
|
||||||
|
|
||||||
|
|
||||||
|
@ -383,10 +383,10 @@ class CtpMdApi(MdApi):
|
|||||||
def onRtnDepthMarketData(self, data):
|
def onRtnDepthMarketData(self, data):
|
||||||
"""行情推送"""
|
"""行情推送"""
|
||||||
# 忽略成交量为0的无效单合约tick数据
|
# 忽略成交量为0的无效单合约tick数据
|
||||||
if not data['Volume'] and '&' not in data['InstrumentID']:
|
#if not data['Volume'] and '&' not in data['InstrumentID']:
|
||||||
self.writeLog(u'忽略成交量为0的无效单合约tick数据:')
|
# self.writeLog(u'忽略成交量为0的无效单合约tick数据:')
|
||||||
self.writeLog(data)
|
# self.writeLog(data)
|
||||||
return
|
# return
|
||||||
|
|
||||||
if not self.connectionStatus:
|
if not self.connectionStatus:
|
||||||
self.connectionStatus = True
|
self.connectionStatus = True
|
||||||
@ -407,11 +407,19 @@ class CtpMdApi(MdApi):
|
|||||||
#tick.time = '.'.join([data['UpdateTime'], str(data['UpdateMillisec']/100)])
|
#tick.time = '.'.join([data['UpdateTime'], str(data['UpdateMillisec']/100)])
|
||||||
# =》 Python 3
|
# =》 Python 3
|
||||||
tick.time = '.'.join([data['UpdateTime'], str(data['UpdateMillisec'])])
|
tick.time = '.'.join([data['UpdateTime'], str(data['UpdateMillisec'])])
|
||||||
tick.date = data['TradingDay']
|
# 上期所和郑商所可以直接使用,大商所需要转换
|
||||||
|
tick.date = data['ActionDay']
|
||||||
|
# 大商所日期转换
|
||||||
|
if tick.exchange is EXCHANGE_DCE:
|
||||||
|
tick.date = datetime.now().strftime('%Y%m%d')
|
||||||
|
|
||||||
|
#tick.date = data['TradingDay']
|
||||||
|
|
||||||
# add by Incense Lee
|
# add by Incense Lee
|
||||||
tick.tradingDay = data['TradingDay']
|
tick.tradingDay = data['TradingDay']
|
||||||
|
if len(tick.tradingDay) == 8:
|
||||||
|
tradingDay = tick.tradingDay
|
||||||
|
tick.tradingDay = "{}-{}-{}".format(tradingDay[:4], tradingDay[4:6], tradingDay[6:])
|
||||||
# 先根据交易日期,生成时间
|
# 先根据交易日期,生成时间
|
||||||
tick.datetime = datetime.strptime(tick.date + ' ' + tick.time, '%Y%m%d %H:%M:%S.%f')
|
tick.datetime = datetime.strptime(tick.date + ' ' + tick.time, '%Y%m%d %H:%M:%S.%f')
|
||||||
# 修正时间
|
# 修正时间
|
||||||
@ -429,6 +437,8 @@ class CtpMdApi(MdApi):
|
|||||||
tick.datetime = tick.datetime + timedelta(days=2)
|
tick.datetime = tick.datetime + timedelta(days=2)
|
||||||
tick.date = tick.datetime.strftime('%Y-%m-%d')
|
tick.date = tick.datetime.strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
tick.date = tick.datetime.strftime('%Y-%m-%d')
|
||||||
|
|
||||||
tick.openPrice = data['OpenPrice']
|
tick.openPrice = data['OpenPrice']
|
||||||
tick.highPrice = data['HighestPrice']
|
tick.highPrice = data['HighestPrice']
|
||||||
tick.lowPrice = data['LowestPrice']
|
tick.lowPrice = data['LowestPrice']
|
||||||
@ -1437,7 +1447,7 @@ class CtpTdApi(TdApi):
|
|||||||
""""""
|
""""""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def connect(self, userID, password, brokerID, address, authCode, userProductInfo):
|
def connect(self, userID, password, brokerID, address, authCode, userProductInfo):
|
||||||
"""初始化连接"""
|
"""初始化连接"""
|
||||||
self.userID = userID # 账号
|
self.userID = userID # 账号
|
||||||
@ -1472,7 +1482,7 @@ class CtpTdApi(TdApi):
|
|||||||
elif not self.loginStatus:
|
elif not self.loginStatus:
|
||||||
self.login()
|
self.login()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def login(self):
|
def login(self):
|
||||||
"""连接服务器"""
|
"""连接服务器"""
|
||||||
# 如果填入了用户名密码等,则登录
|
# 如果填入了用户名密码等,则登录
|
||||||
@ -1484,7 +1494,7 @@ class CtpTdApi(TdApi):
|
|||||||
self.reqID += 1
|
self.reqID += 1
|
||||||
self.reqUserLogin(req, self.reqID)
|
self.reqUserLogin(req, self.reqID)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def authenticate(self):
|
def authenticate(self):
|
||||||
"""申请验证"""
|
"""申请验证"""
|
||||||
if self.userID and self.brokerID and self.authCode and self.userProductInfo:
|
if self.userID and self.brokerID and self.authCode and self.userProductInfo:
|
||||||
@ -1496,13 +1506,13 @@ class CtpTdApi(TdApi):
|
|||||||
self.reqID +=1
|
self.reqID +=1
|
||||||
self.reqAuthenticate(req, self.reqID)
|
self.reqAuthenticate(req, self.reqID)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def qryAccount(self):
|
def qryAccount(self):
|
||||||
"""查询账户"""
|
"""查询账户"""
|
||||||
self.reqID += 1
|
self.reqID += 1
|
||||||
self.reqQryTradingAccount({}, self.reqID)
|
self.reqQryTradingAccount({}, self.reqID)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def qryPosition(self):
|
def qryPosition(self):
|
||||||
"""查询持仓"""
|
"""查询持仓"""
|
||||||
self.reqID += 1
|
self.reqID += 1
|
||||||
@ -1511,7 +1521,7 @@ class CtpTdApi(TdApi):
|
|||||||
req['InvestorID'] = self.userID
|
req['InvestorID'] = self.userID
|
||||||
self.reqQryInvestorPosition(req, self.reqID)
|
self.reqQryInvestorPosition(req, self.reqID)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def sendOrder(self, orderReq):
|
def sendOrder(self, orderReq):
|
||||||
"""发单"""
|
"""发单"""
|
||||||
self.reqID += 1
|
self.reqID += 1
|
||||||
@ -1562,7 +1572,7 @@ class CtpTdApi(TdApi):
|
|||||||
vtOrderID = '.'.join([self.gatewayName, str(self.orderRef)])
|
vtOrderID = '.'.join([self.gatewayName, str(self.orderRef)])
|
||||||
return vtOrderID
|
return vtOrderID
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def cancelOrder(self, cancelOrderReq):
|
def cancelOrder(self, cancelOrderReq):
|
||||||
"""撤单"""
|
"""撤单"""
|
||||||
self.reqID += 1
|
self.reqID += 1
|
||||||
@ -1581,12 +1591,12 @@ class CtpTdApi(TdApi):
|
|||||||
|
|
||||||
self.reqOrderAction(req, self.reqID)
|
self.reqOrderAction(req, self.reqID)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def close(self):
|
def close(self):
|
||||||
"""关闭"""
|
"""关闭"""
|
||||||
self.exit()
|
self.exit()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def writeLog(self, content):
|
def writeLog(self, content):
|
||||||
"""发出日志"""
|
"""发出日志"""
|
||||||
log = VtLogData()
|
log = VtLogData()
|
||||||
|
@ -72,14 +72,21 @@ EXCHANGE_IDEALPRO = 'IDEALPRO' # IB外汇ECN
|
|||||||
EXCHANGE_CME = 'CME' # CME交易所
|
EXCHANGE_CME = 'CME' # CME交易所
|
||||||
EXCHANGE_ICE = 'ICE' # ICE交易所
|
EXCHANGE_ICE = 'ICE' # ICE交易所
|
||||||
|
|
||||||
|
|
||||||
EXCHANGE_OANDA = 'OANDA' # OANDA外汇做市商
|
EXCHANGE_OANDA = 'OANDA' # OANDA外汇做市商
|
||||||
|
|
||||||
|
|
||||||
EXCHANGE_OKCOIN = 'OKCOIN' # OKCOIN比特币交易所
|
EXCHANGE_OKCOIN = 'OKCOIN' # OKCOIN比特币交易所
|
||||||
EXCHANGE_HUOBI = 'HUOBI' # 火币比特币交易所
|
EXCHANGE_HUOBI = 'HUOBI' # 火币比特币交易所
|
||||||
EXCHANGE_LHANG = 'LHANG' # 链行比特币交易所
|
EXCHANGE_LHANG = 'LHANG' # 链行比特币交易所
|
||||||
EXCHANGE_OKEX = 'OKEX' # OKEX比特币交易所
|
EXCHANGE_OKEX = 'OKEX' # OKEX比特币交易所
|
||||||
EXCHANGE_BINANCE = 'BINANCE' # 币安比特币交易所
|
EXCHANGE_BINANCE = 'BINANCE' # 币安比特币交易所
|
||||||
EXCHANGE_GATEIO = 'GATEIO' # gate.io比特币交易所
|
EXCHANGE_GATEIO = 'GATEIO' # gate.io比特币交易所
|
||||||
EXCHANGE_FCOIN = 'FCOIN' # fcoin.com 比特币交易所
|
EXCHANGE_BITFINEX = "BITFINEX" # Bitfinex比特币交易所
|
||||||
|
EXCHANGE_BITMEX = 'BITMEX' # BitMEX比特币交易所
|
||||||
|
EXCHANGE_FCOIN = 'FCOIN' # FCoin比特币交易所
|
||||||
|
EXCHANGE_BIGONE = 'BIGONE' # BigOne比特币交易所
|
||||||
|
|
||||||
# 货币类型
|
# 货币类型
|
||||||
CURRENCY_USD = 'USD' # 美元
|
CURRENCY_USD = 'USD' # 美元
|
||||||
CURRENCY_CNY = 'CNY' # 人民币
|
CURRENCY_CNY = 'CNY' # 人民币
|
||||||
|
@ -80,7 +80,11 @@ EXCHANGE_LHANG = 'LHANG' # 链行比特币交易所
|
|||||||
EXCHANGE_OKEX = 'OKEX' # OKEX比特币交易所
|
EXCHANGE_OKEX = 'OKEX' # OKEX比特币交易所
|
||||||
EXCHANGE_BINANCE = 'BINANCE' # 币安比特币交易所
|
EXCHANGE_BINANCE = 'BINANCE' # 币安比特币交易所
|
||||||
EXCHANGE_GATEIO = 'GATEIO' # gate.io比特币交易所
|
EXCHANGE_GATEIO = 'GATEIO' # gate.io比特币交易所
|
||||||
EXCHANGE_FCOIN = 'FCOIN' # fcoin.com 比特币交易所
|
EXCHANGE_BITFINEX = "BITFINEX" # Bitfinex比特币交易所
|
||||||
|
EXCHANGE_BITMEX = 'BITMEX' # BitMEX比特币交易所
|
||||||
|
EXCHANGE_FCOIN = 'FCOIN' # FCoin比特币交易所
|
||||||
|
EXCHANGE_BIGONE = 'BIGONE' # BigOne比特币交易所
|
||||||
|
|
||||||
# 货币类型
|
# 货币类型
|
||||||
CURRENCY_USD = 'USD' # 美元
|
CURRENCY_USD = 'USD' # 美元
|
||||||
CURRENCY_CNY = 'CNY' # 人民币
|
CURRENCY_CNY = 'CNY' # 人民币
|
||||||
|
@ -26,7 +26,7 @@ class GridKline(QtWidgets.QWidget):
|
|||||||
self.parent = parent
|
self.parent = parent
|
||||||
super(GridKline, self).__init__(parent)
|
super(GridKline, self).__init__(parent)
|
||||||
|
|
||||||
self.periods = ['m30', 'h1', 'h2', 'd']
|
self.periods = ['m30', 'h1', 'h2','d']
|
||||||
self.kline_dict = {}
|
self.kline_dict = {}
|
||||||
|
|
||||||
self.initUI()
|
self.initUI()
|
||||||
@ -71,19 +71,23 @@ class GridKline(QtWidgets.QWidget):
|
|||||||
df = df.set_index(pd.DatetimeIndex(df['datetime']))
|
df = df.set_index(pd.DatetimeIndex(df['datetime']))
|
||||||
canvas.loadData(df, main_indicators=['ma5', 'ma10', 'ma18'], sub_indicators=['sk', 'sd'])
|
canvas.loadData(df, main_indicators=['ma5', 'ma10', 'ma18'], sub_indicators=['sk', 'sd'])
|
||||||
|
|
||||||
# 载入 回测引擎生成的成交记录
|
|
||||||
trade_list_file = 'TradeList.csv'
|
trade_list_file = 'TradeList.csv'
|
||||||
if os.path.exists(trade_list_file):
|
if os.path.exists(trade_list_file):
|
||||||
df_trade = pd.read_csv(trade_list_file)
|
df_trade = pd.read_csv(trade_list_file)
|
||||||
self.kline_dict['h1'].add_signals(df_trade)
|
self.kline_dict['h1'].add_signals(df_trade)
|
||||||
|
|
||||||
# 载入策略生成的交易事务过程
|
|
||||||
tns_file = 'tns.csv'
|
tns_file = 'tns.csv'
|
||||||
if os.path.exists(tns_file):
|
if os.path.exists(tns_file):
|
||||||
df_tns = pd.read_csv(tns_file)
|
df_tns = pd.read_csv(tns_file)
|
||||||
self.kline_dict['h2'].add_trans_df(df_tns)
|
self.kline_dict['h2'].add_trans_df(df_tns)
|
||||||
self.kline_dict['d'].add_trans_df(df_tns)
|
self.kline_dict['d'].add_trans_df(df_tns)
|
||||||
|
|
||||||
|
markup_file = 'dist.csv'
|
||||||
|
if os.path.exists(markup_file):
|
||||||
|
df_markup = pd.read_csv(markup_file)
|
||||||
|
df_markup = df_markup[['datetime', 'price', 'operation']]
|
||||||
|
df_markup.rename(columns={'operation': 'markup'}, inplace=True)
|
||||||
|
self.kline_dict['m30'].add_markups(df_markup=df_markup, include_list=['balance'], exclude_list=['buy', 'short', 'sell', 'cover'])
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
import smtplib
|
import smtplib
|
||||||
from threading import *
|
from threading import Lock,Thread
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# 创建一个带附件的实例
|
# 创建一个带附件的实例
|
||||||
@ -15,6 +15,23 @@ global maillock
|
|||||||
maillock = Lock()
|
maillock = Lock()
|
||||||
|
|
||||||
|
|
||||||
|
#用于发送邮件的邮箱列表
|
||||||
|
senders_list = [('xxx010@163.com','xxxx'),
|
||||||
|
('xxx013@163.com','xxxx'),
|
||||||
|
('xxx014@163.com','xxxx'),
|
||||||
|
('xxx015@163.com','xxxx'),
|
||||||
|
('xxx016@163.com','xxxx'),
|
||||||
|
('xxx017@163.com','xxxx'),
|
||||||
|
('xxx018@163.com','xxxx'),
|
||||||
|
('xxx019@163.com','xxxx'),
|
||||||
|
('xxx020@163.com','xxxx'),
|
||||||
|
('xxx021@163.com','xxxx'),
|
||||||
|
('xxx022@163.com','xxxx'),
|
||||||
|
('xxx023@163.com','xxxx'),
|
||||||
|
('xxx024@163.com','xxxx'),
|
||||||
|
('xxx025@163.com','xxxx'),
|
||||||
|
('xxx026@163.com','xxxx'),
|
||||||
|
('xxx027@163.com','xxxx')]
|
||||||
class mail_thread(Thread):
|
class mail_thread(Thread):
|
||||||
def __init__(self, to_list, subject, msgcontent, attachlist):
|
def __init__(self, to_list, subject, msgcontent, attachlist):
|
||||||
super(mail_thread, self).__init__(name="mail_thread")
|
super(mail_thread, self).__init__(name="mail_thread")
|
||||||
@ -36,6 +53,16 @@ class mail_thread(Thread):
|
|||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
print("lock acquire %s" % time.ctime())
|
print("lock acquire %s" % time.ctime())
|
||||||
|
|
||||||
|
random_limit = len(senders_list) - 1
|
||||||
|
if random_limit != 0:
|
||||||
|
index = random.randint(0, random_limit)
|
||||||
|
self.mailfrom, self.mailpwd = senders_list[index]
|
||||||
|
|
||||||
|
if len(self.mailfrom)==0 or len(self.mailpwd) == 0:
|
||||||
|
print("sendmail user/pwd error!")
|
||||||
|
self.lock.release()
|
||||||
|
return
|
||||||
|
|
||||||
msg = MIMEMultipart()
|
msg = MIMEMultipart()
|
||||||
# 文本肉容
|
# 文本肉容
|
||||||
content = MIMEText(self.msgcontent, _subtype='plain', _charset='gb2312')
|
content = MIMEText(self.msgcontent, _subtype='plain', _charset='gb2312')
|
||||||
|
@ -7,7 +7,7 @@ from collections import OrderedDict
|
|||||||
import os,sys
|
import os,sys
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient, ASCENDING
|
||||||
from pymongo.errors import ConnectionFailure,AutoReconnect
|
from pymongo.errors import ConnectionFailure,AutoReconnect
|
||||||
#import vnpy.trader.mongo_proxy
|
#import vnpy.trader.mongo_proxy
|
||||||
|
|
||||||
@ -26,7 +26,11 @@ import psutil
|
|||||||
try:
|
try:
|
||||||
from .util_mail import *
|
from .util_mail import *
|
||||||
except:
|
except:
|
||||||
print('import util_mail fail')
|
print('import util_mail fail',file=sys.stderr)
|
||||||
|
try:
|
||||||
|
from .util_wechat import *
|
||||||
|
except:
|
||||||
|
print('import util_wechat fail',file=sys.stderr)
|
||||||
|
|
||||||
LOG_DB_NAME = 'vt_logger'
|
LOG_DB_NAME = 'vt_logger'
|
||||||
|
|
||||||
@ -147,16 +151,16 @@ class MainEngine(object):
|
|||||||
|
|
||||||
def checkGatewayStatus(self,gatewayName):
|
def checkGatewayStatus(self,gatewayName):
|
||||||
"""check gateway connect status"""
|
"""check gateway connect status"""
|
||||||
|
# 借用检查网关状态来持久化合约数据
|
||||||
|
self.save_contract_counter += 1
|
||||||
|
if self.save_contract_counter > 60 and self.dataEngine is not None:
|
||||||
|
self.writeLog(u'保存持久化合约数据')
|
||||||
|
self.dataEngine.saveContracts()
|
||||||
|
self.save_contract_counter = 0
|
||||||
|
|
||||||
if gatewayName in self.gatewayDict:
|
if gatewayName in self.gatewayDict:
|
||||||
gateway = self.gatewayDict[gatewayName]
|
gateway = self.gatewayDict[gatewayName]
|
||||||
|
|
||||||
# 借用检查网关状态来持久化合约数据
|
|
||||||
self.save_contract_counter += 1
|
|
||||||
if self.save_contract_counter > 60 and self.dataEngine is not None:
|
|
||||||
|
|
||||||
self.dataEngine.saveContracts()
|
|
||||||
self.save_contract_counter = 0
|
|
||||||
|
|
||||||
return gateway.checkStatus()
|
return gateway.checkStatus()
|
||||||
else:
|
else:
|
||||||
self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName))
|
self.writeLog(text.GATEWAY_NOT_EXIST.format(gateway=gatewayName))
|
||||||
@ -372,11 +376,22 @@ class MainEngine(object):
|
|||||||
# 写入本地log日志
|
# 写入本地log日志
|
||||||
if self.logger is not None:
|
if self.logger is not None:
|
||||||
self.logger.error(content)
|
self.logger.error(content)
|
||||||
|
print('{}'.format(datetime.now()),file=sys.stderr)
|
||||||
print(content, file=sys.stderr)
|
print(content, file=sys.stderr)
|
||||||
else:
|
else:
|
||||||
print(content, file=sys.stderr)
|
print(content, file=sys.stderr)
|
||||||
self.createLogger()
|
self.createLogger()
|
||||||
|
|
||||||
|
# 发出邮件/微信
|
||||||
|
#try:
|
||||||
|
# if len(self.gatewayDetailList) > 0:
|
||||||
|
# target = self.gatewayDetailList[0]['gatewayName']
|
||||||
|
# else:
|
||||||
|
# target = WECHAT_GROUP["DEBUG_01"]
|
||||||
|
# sendWeChatMsg(content, target=target, level=WECHAT_LEVEL_ERROR)
|
||||||
|
#except Exception as ex:
|
||||||
|
# print(u'send wechat exception:{}'.format(str(ex)),file=sys.stderr)
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def writeWarning(self, content):
|
def writeWarning(self, content):
|
||||||
"""快速发出告警日志事件"""
|
"""快速发出告警日志事件"""
|
||||||
@ -399,6 +414,16 @@ class MainEngine(object):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# 发出微信
|
||||||
|
#try:
|
||||||
|
# if len(self.gatewayDetailList) > 0:
|
||||||
|
# target = self.gatewayDetailList[0]['gatewayName']
|
||||||
|
# else:
|
||||||
|
# target = WECHAT_GROUP["DEBUG_01"]
|
||||||
|
# sendWeChatMsg(content, target=target, level=WECHAT_LEVEL_WARNING)
|
||||||
|
#except Exception as ex:
|
||||||
|
# print(u'send wechat exception:{}'.format(str(ex)), file=sys.stderr)
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def writeNotification(self, content):
|
def writeNotification(self, content):
|
||||||
"""快速发出通知日志事件"""
|
"""快速发出通知日志事件"""
|
||||||
@ -414,6 +439,16 @@ class MainEngine(object):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# 发出微信
|
||||||
|
# try:
|
||||||
|
# if len(self.gatewayDetailList) > 0:
|
||||||
|
# target = self.gatewayDetailList[0]['gatewayName']
|
||||||
|
# else:
|
||||||
|
# target = WECHAT_GROUP["DEBUG_01"]
|
||||||
|
# sendWeChatMsg(content, target=target, level=WECHAT_LEVEL_INFO)
|
||||||
|
# except Exception as ex:
|
||||||
|
# print(u'send wechat exception:{}'.format(str(ex)), file=sys.stderr)
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def writeCritical(self, content):
|
def writeCritical(self, content):
|
||||||
"""快速发出严重错误日志事件"""
|
"""快速发出严重错误日志事件"""
|
||||||
@ -427,6 +462,7 @@ class MainEngine(object):
|
|||||||
# 写入本地log日志
|
# 写入本地log日志
|
||||||
if self.logger:
|
if self.logger:
|
||||||
self.logger.critical(content)
|
self.logger.critical(content)
|
||||||
|
print('{}'.format(datetime.now()), file=sys.stderr)
|
||||||
print(content, file=sys.stderr)
|
print(content, file=sys.stderr)
|
||||||
else:
|
else:
|
||||||
print(content, file=sys.stderr)
|
print(content, file=sys.stderr)
|
||||||
@ -438,6 +474,16 @@ class MainEngine(object):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
## 发出微信
|
||||||
|
#try:
|
||||||
|
# # if len(self.gatewayDetailList) > 0:
|
||||||
|
# target = self.gatewayDetailList[0]['gatewayName']
|
||||||
|
# else:
|
||||||
|
# target = WECHAT_GROUP["DEBUG_01"]
|
||||||
|
# sendWeChatMsg(content, target=target, level=WECHAT_LEVEL_FATAL)
|
||||||
|
#except:
|
||||||
|
# pass
|
||||||
|
#
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def dbConnect(self):
|
def dbConnect(self):
|
||||||
"""连接MongoDB数据库"""
|
"""连接MongoDB数据库"""
|
||||||
@ -527,13 +573,18 @@ class MainEngine(object):
|
|||||||
self.writeError(u'dbInsertMany exception:{}'.format(str(ex)))
|
self.writeError(u'dbInsertMany exception:{}'.format(str(ex)))
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
def dbQuery(self, dbName, collectionName, d):
|
def dbQuery(self, dbName, collectionName, d, sortKey='', sortDirection=ASCENDING):
|
||||||
"""从MongoDB中读取数据,d是查询要求,返回的是数据库查询的指针"""
|
"""从MongoDB中读取数据,d是查询要求,返回的是数据库查询的指针"""
|
||||||
try:
|
try:
|
||||||
if self.dbClient:
|
if self.dbClient:
|
||||||
db = self.dbClient[dbName]
|
db = self.dbClient[dbName]
|
||||||
collection = db[collectionName]
|
collection = db[collectionName]
|
||||||
cursor = collection.find(d)
|
|
||||||
|
if sortKey:
|
||||||
|
cursor = collection.find(d).sort(sortKey, sortDirection) # 对查询出来的数据进行排序
|
||||||
|
else:
|
||||||
|
cursor = collection.find(d)
|
||||||
|
|
||||||
if cursor:
|
if cursor:
|
||||||
return list(cursor)
|
return list(cursor)
|
||||||
else:
|
else:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
import time,os
|
import time,os,sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from vnpy.trader.vtEvent import *
|
from vnpy.trader.vtEvent import *
|
||||||
@ -98,10 +98,11 @@ class VtGateway(object):
|
|||||||
event1.dict_['data'] = error
|
event1.dict_['data'] = error
|
||||||
self.eventEngine.put(event1)
|
self.eventEngine.put(event1)
|
||||||
|
|
||||||
logMsg = u'{0}:[{1}]:{2}'.format(error.gatewayName, error.errorID,error.errorMsg )
|
logMsg = u'{} {}:[{}]:{}'.format(datetime.now(), error.gatewayName, error.errorID,error.errorMsg )
|
||||||
# 写入本地log日志
|
# 写入本地log日志
|
||||||
if self.logger:
|
if self.logger:
|
||||||
self.logger.info(logMsg)
|
self.logger.error(logMsg)
|
||||||
|
print(logMsg,file=sys.stderr)
|
||||||
else:
|
else:
|
||||||
self.createLogger()
|
self.createLogger()
|
||||||
|
|
||||||
@ -205,12 +206,9 @@ class VtGateway(object):
|
|||||||
error.errorMsg = content
|
error.errorMsg = content
|
||||||
self.onError(error)
|
self.onError(error)
|
||||||
|
|
||||||
|
# 输出到错误管道
|
||||||
|
print(u'{}:{} {}'.format(datetime.now(),self.gatewayName,content),file=sys.stderr)
|
||||||
|
|
||||||
if self.logger:
|
if self.logger:
|
||||||
self.logger.error(content)
|
self.logger.error(content)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user