This commit is contained in:
msincenselee 2018-09-22 19:22:25 +08:00
parent 22180cf239
commit 17d908ab56
16 changed files with 1150 additions and 230 deletions

View File

@ -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

View File

@ -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):

View File

@ -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
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------

View File

@ -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

View File

@ -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')

View File

@ -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)

View File

@ -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):

View File

@ -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()

View File

@ -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()

View File

@ -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' # 人民币

View File

@ -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' # 人民币

View File

@ -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()

View File

@ -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')

View File

@ -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:

View File

@ -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)