=>Py3.5
This commit is contained in:
parent
6a30576598
commit
03987b0011
117
README.md
117
README.md
@ -9,120 +9,13 @@ Fork版本主要改进如下:
|
||||
可视化:python vtMain.py
|
||||
命令行:python noUiMain.py
|
||||
|
||||
2018年1月,升级至py3版本
|
||||
|
||||
大佳
|
||||
QQ/Wechat:28888502
|
||||
|
||||
# vn.py - 基于python的开源交易平台开发框架
|
||||
|
||||
---
|
||||
### Quick Start
|
||||
|
||||
对于大部分用户来说,无需自行编译API接口,可以直接使用vn.trader进行交易和策略开发:
|
||||
|
||||
1. 准备一台Windows 7 64位系统的电脑
|
||||
|
||||
2. 安装[Anaconda](http://www.continuum.io/downloads):下载Python 2.7 32位版本,**注意必须是32位**
|
||||
|
||||
3. 安装[MongoDB](https://www.mongodb.org/downloads#production):下载Windows 64-bit 2008 R2+版本
|
||||
|
||||
4. 安装pymongo:在cmd中运行pip install pymongo
|
||||
|
||||
5. 参考[这里](http://jingyan.baidu.com/article/6b97984dbeef881ca2b0bf3e.html),将MongoDB注册为Windows服务并启动
|
||||
|
||||
6. 安装[Visual C++ Redistributable Packages for VS2013](https://www.microsoft.com/en-gb/download/details.aspx?id=40784),中英文随意
|
||||
|
||||
6. 在本页面选择Download ZIP下载项目代码,并解压到C:\vnpy
|
||||
|
||||
7. 在[SimNow](http://simnow.com.cn/)注册CTP仿真账号,记下你的**账号、密码、经纪商编号**,然后下载快期查询你的**交易和行情服务器地址**
|
||||
|
||||
8. 把C:\vnpy\vn.trader\ctpGateway\CTP_connect.json中的账号、密码、服务器等修改为上一步注册完成后你的信息(注意使用专门的编程编辑器,如Sublime Text等,防止json编码出错)
|
||||
|
||||
9. 双击运行C:\vnpy\vn.trader\vtMain.py,开始交易!
|
||||
|
||||
对于想研究API封装的用户,可以参考[vnpy.org](http://vnpy.org)上面的教程一步步操作。
|
||||
|
||||
其他作者建议使用的软件工具:
|
||||
* [WingIDE](http://wingware.com/):非常好用的Python集成开发环境(作者就是用它写的vn.py)
|
||||
|
||||
* [Robomongo](https://robomongo.org/):MongoDB的图形化客户端,方便监控和修改数据
|
||||
|
||||
* [Sublime Text](http://www.sublimetext.com/):针对编程的文本编辑器,当然你也可以使用Vim或者Emacs
|
||||
|
||||
* [PyQtGraph](http://www.pyqtgraph.org/):适用于开发实时更新数据的图表,如Tick图、K线图、期权波动率曲线等(Matplotlib渲染开销太大,用于实盘绘图可能拖慢整个程序)
|
||||
|
||||
* [Visual Studio 2013](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx):这个就不多说了(作者编译API封装用的是2013版本)
|
||||
|
||||
---
|
||||
### 2016年vn.py项目计划
|
||||
|
||||
首先要感谢所有vn.py用户,是你们的热情让vn.py项目在2015年从最初单纯的交易API接口Python封装一步步成长为现在较为全面的交易程序开发框架。
|
||||
|
||||
截止2016年2月15日,vn.py项目在Github上收获了583个Star和362个Fork,且已有6位贡献者提交了代码。项目的用户包括:私募基金,证券自营、资管,期货公司,高校的金融研究院系,个人投资者等,机构用户加起来至少20多家(和作者交流过的)。
|
||||
|
||||
**总结一下项目当前取得的进展**
|
||||
|
||||
1. 较为丰富的Python交易和数据API接口,基本覆盖了国内所有常规交易品种(股票、期货、期权),具体包括:
|
||||
|
||||
* CTP(vn.ctp)
|
||||
|
||||
* 飞马(vn.femas)
|
||||
|
||||
* LTS(vn.lts)
|
||||
|
||||
* 金仕达黄金(vn.ksgold)
|
||||
|
||||
* 金仕达期权(vn.ksotp)
|
||||
|
||||
* 通联数据(vn.datayes)
|
||||
|
||||
2. 简洁易用的事件驱动引擎(vn.event),作为事件驱动型交易程序的核心
|
||||
|
||||
3. 针对如何使用API和事件驱动引擎开发交易程序的示例(vn.demo)
|
||||
|
||||
4. 开箱即用的实盘交易平台vn.trader(相比之下vn.demo仅建议学习用),整合了多种交易接口,并针对具体策略算法和功能开发提供了简洁易用的API,功能应用举例:
|
||||
|
||||
* 同时登录多个交易接口,在一套界面上监控多种市场的行情和多种资产账户的资金、持仓、委托、成交情况
|
||||
|
||||
* 支持跨市场套利(CTP期货和LTS证券)、境内外套利(CTP期货和IB外盘)、多市场数据整合实时预测走势(CTP的股指期货数据、IB的外盘A50数据、Wind的行业指数数据)等策略应用
|
||||
|
||||
* CTA策略引擎模块,在保持易用性的同时,允许用户针对CTA类策略运行过程中委托的报撤行为进行细粒度控制(降低交易滑点、实现高频策略)
|
||||
|
||||
5. [官网](http://vnpy.org)和[知乎专栏](http://zhuanlan.zhihu.com/vn-py),内容目前主要是《Python量化交易平台开发教程系列》,以及vn.py项目进展的更新
|
||||
|
||||
6. 官方交流QQ群262656087,管理较严格(定期清除长期潜水的成员)
|
||||
|
||||
**展望一下项目2016年的计划**
|
||||
|
||||
代码方面:
|
||||
|
||||
1. 完善飞创、易盛等相对小众接口的添加,这块将由社区驱动,作者主要负责代码检查和管理
|
||||
|
||||
2. 整理vn.py项目中API的具体版本号,保证封装接口的对应,这点已经有多位用户提起过,项目初期没有做详细记录所以很多API的版本号一时都较难对上
|
||||
|
||||
3. Linux上API的编译以及vn.trader支持
|
||||
|
||||
4. 基于VirtualBox的vn.py开发环境镜像,解决部分用户反映项目初期不知该如何搭建开发环境的问题,这个镜像会由官方长期维护下去
|
||||
|
||||
文章方面:
|
||||
|
||||
1.作者自己作为交易员的成长经历(这一年来收到好多人关于如何成为Quant、建议看什么书、怎么选学校等类似的问题,与其零散的回答不如介绍下自己的一些经历给大家参考可能更有帮助)
|
||||
|
||||
2. vn.trader的使用教程(目前基本除了代码里的注释什么都没有...)
|
||||
|
||||
3. 将ta-lib(技术分析)和quantlib(金融工程和量化)整合到vn.trader中应用的教程,解决目前策略开发过程中技术指标和量化函数缺乏的问题
|
||||
|
||||
4. 一套关于开发基于股指交易ETF期权的CTA策略的教程(股指期货短时间内还看不到恢复的希望,咱得另谋出路)
|
||||
|
||||
社区方面:
|
||||
|
||||
1. 重新建设官方网站,目前使用的是托管在Github Pages上的Hexo静态博客,一来功能比较有限,二来有些用户反映Github时不时会被墙,考虑基于Flask重建一个托管在国内的官网
|
||||
|
||||
2. 有用户提出建设互动性更强的网站作为交流平台(如论坛或者知乎Q&A类似的模式),这点在考虑中,主要制约因素是作者参与的时间,可能考虑和更多的资深用户合作是个好主意?
|
||||
|
||||
**最后,2016年,Happy Trading!!!**
|
||||
|
||||
---
|
||||
### 联系作者
|
||||
作者知乎名:用python的交易员,想要联系作者可以通过知乎私信
|
||||
|
||||
https://github.com/vnpy/vnpy
|
||||
---
|
||||
### License
|
||||
MIT
|
||||
|
@ -7,4 +7,4 @@ conda config --set show_channel_urls yes
|
||||
conda install -c quantopian ta-lib=0.4.9
|
||||
|
||||
:: Install vn.py
|
||||
python setup.py install
|
||||
#python setup.py install
|
@ -22,5 +22,5 @@ conda config --set show_channel_urls yes
|
||||
conda install -c quantopian ta-lib=0.4.9
|
||||
|
||||
#Install vn.py
|
||||
python setup.py install
|
||||
#python setup.py install
|
||||
|
||||
|
@ -26,7 +26,7 @@ from vnpy.trader.vtEvent import *
|
||||
from vnpy.rpc import RpcServer
|
||||
from vnpy.trader.vtEngine import MainEngine
|
||||
from vnpy.trader.gateway import ctpGateway
|
||||
from vnpy.trader.setup_logger import setup_logger
|
||||
from vnpy.trader.setup_logger import setup_logger,get_logger
|
||||
from vnpy.trader.util_monitor import *
|
||||
from vnpy.trader.vtGlobal import globalSetting
|
||||
from vnpy.trader.util_gpid import *
|
||||
@ -35,7 +35,7 @@ from vnpy.trader.app import ctaStrategy,riskManager
|
||||
AUTO_CONNCET_GW = 'CTP'
|
||||
########################################################################
|
||||
class VtServer(RpcServer):
|
||||
"""vn.trader服务器"""
|
||||
"""vn.trader 无界面服务器"""
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def __init__(self, repAddress, pubAddress):
|
||||
@ -48,8 +48,7 @@ class VtServer(RpcServer):
|
||||
# gateway 的连接名称,在vtEngine.initGateway()里面定义,对应的配置文件是 "连接名称_connect.json",
|
||||
self.gateway_name = AUTO_CONNCET_GW
|
||||
# 启动的策略实例,须在catStrategy/CtaSetting.json 里面定义 [u'S28_RB1001', u'S28_TFT', u'S28_HCRB',u'atr_rsi']
|
||||
self.strategies = []
|
||||
|
||||
self.strategies = [u'S30_RB0510', u'S30_HCRB05']
|
||||
self.g_count = 0
|
||||
self.disconnect_signal = 0
|
||||
self.last_dt = datetime.now()
|
||||
@ -58,7 +57,7 @@ class VtServer(RpcServer):
|
||||
ee = EventEngine2()
|
||||
|
||||
# 创建主引擎对象
|
||||
print u'instance mainengine'
|
||||
print( u'instance mainengine')
|
||||
self.engine = MainEngine(ee)
|
||||
|
||||
# 添加CTP Gateway,配置文件为 CTP_Post
|
||||
@ -128,7 +127,7 @@ class VtServer(RpcServer):
|
||||
self.engine.qryStatus()
|
||||
if dt.hour != self.last_dt.hour:
|
||||
self.last_dt = dt
|
||||
print u'noUiMain.py checkpoint:{0}'.format(dt)
|
||||
print(u'noUiMain.py checkpoint:{0}'.format(dt))
|
||||
self.engine.writeLog( u'noUiMain.py checkpoint:{0}'.format(dt))
|
||||
|
||||
# 定时断开
|
||||
@ -172,21 +171,21 @@ class VtServer(RpcServer):
|
||||
# self.mainEngine.dbConnect()
|
||||
|
||||
# 加载cta的配置
|
||||
print u'load cta setting'
|
||||
print( u'load cta setting')
|
||||
self.engine.ctaEngine.loadSetting()
|
||||
|
||||
print u'initialize all strategies'
|
||||
print(u'initialize all strategies')
|
||||
# 初始化策略,如果多个,则需要逐一初始化多个
|
||||
for s in self.strategies:
|
||||
print 'init trategy {0}'.format(s)
|
||||
print( 'init trategy {0}'.format(s))
|
||||
self.engine.ctaEngine.initStrategy(s)
|
||||
# 逐一启动策略
|
||||
print 'start strategy {0}'.format(s)
|
||||
print( 'start strategy {0}'.format(s))
|
||||
self.engine.ctaEngine.startStrategy(s)
|
||||
|
||||
# 指定的连接配置
|
||||
if not self.trade_off():
|
||||
print u'connect gateway:{0}'.format(self.gateway_name)
|
||||
print( u'connect gateway:{0}'.format(self.gateway_name))
|
||||
self.engine.connect(self.gateway_name)
|
||||
self.connected = True
|
||||
|
||||
@ -214,12 +213,12 @@ class VtServer(RpcServer):
|
||||
self.publish(event.type_.encode('utf-8'), event)
|
||||
|
||||
except Exception as ex:
|
||||
print u'event Handler exception:{0}'.format(str(ex))
|
||||
print( u'event Handler exception:{0}'.format(str(ex)))
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def stopServer(self):
|
||||
"""停止服务器"""
|
||||
print 'stopServer'
|
||||
print( 'stopServer')
|
||||
# 关闭引擎
|
||||
self.engine.exit()
|
||||
# 停止服务器线程
|
||||
@ -228,7 +227,7 @@ class VtServer(RpcServer):
|
||||
# ----------------------------------------------------------------------
|
||||
def printLog(content):
|
||||
"""打印日志"""
|
||||
print datetime.now().strftime("%H:%M:%S"), '\t', content
|
||||
print( datetime.now().strftime("%H:%M:%S"), '\t', content)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def runServer():
|
||||
@ -238,7 +237,7 @@ def runServer():
|
||||
log_file_name = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
'logs', u'noUiMain.log'))
|
||||
except Exception as ex:
|
||||
print u'Use local dict:{0}'.format(os.getcwd())
|
||||
print( u'Use local dict:{0}'.format(os.getcwd()))
|
||||
log_file_name = os.path.abspath(os.path.join(os.getcwd(), 'logs', u'noUiMain.log'))
|
||||
|
||||
setup_logger(filename=log_file_name, debug=False)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
from ctaEngine import CtaEngine
|
||||
from uiCtaWidget import CtaEngineManager
|
||||
from vnpy.trader.app.ctaStrategy.ctaEngine import CtaEngine
|
||||
from vnpy.trader.app.ctaStrategy.uiCtaWidget import CtaEngineManager
|
||||
|
||||
appName = 'CtaStrategy'
|
||||
appDisplayName = u'CTA策略'
|
||||
|
@ -275,7 +275,7 @@ class BacktestingEngine(object):
|
||||
# 载入json文件
|
||||
fileName = 'mysql_connect.json'
|
||||
try:
|
||||
f = file(fileName)
|
||||
f = open(fileName,'r',encoding='utf8')
|
||||
except IOError:
|
||||
self.writeCtaLog(u'回测引擎读取Mysql_connect.json失败')
|
||||
return
|
||||
@ -1571,7 +1571,7 @@ class BacktestingEngine(object):
|
||||
self.output(u'开始回放数据')
|
||||
|
||||
import csv
|
||||
csvfile = file(filename,'rb')
|
||||
csvfile = open(filename,'rb',encoding='utf8')
|
||||
reader = csv.DictReader((line.replace('\0', '') for line in csvfile), delimiter=",")
|
||||
last_tradingDay = None
|
||||
for row in reader:
|
||||
@ -1610,7 +1610,7 @@ class BacktestingEngine(object):
|
||||
last_tradingDay = bar.tradingDay
|
||||
|
||||
self.newBar(bar)
|
||||
self.last_bar = bar
|
||||
|
||||
except Exception as ex:
|
||||
self.writeCtaLog(u'{0}:{1}'.format(Exception, ex))
|
||||
traceback.print_exc()
|
||||
@ -1798,8 +1798,9 @@ class BacktestingEngine(object):
|
||||
self.crossStopOrder() # 再撮合停止单
|
||||
self.strategy.onBar(bar) # 推送K线到策略中
|
||||
self.__sendOnBarEvent(bar) # 推送K线到事件
|
||||
self.last_bar = bar
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def newTick(self, tick):
|
||||
"""新的Tick"""
|
||||
self.tick = tick
|
||||
@ -1808,7 +1809,7 @@ class BacktestingEngine(object):
|
||||
self.crossStopOrder()
|
||||
self.strategy.onTick(tick)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def initStrategy(self, strategyClass, setting=None):
|
||||
"""
|
||||
初始化策略
|
||||
@ -1833,7 +1834,6 @@ class BacktestingEngine(object):
|
||||
def sendOrder(self, vtSymbol, orderType, price, volume, strategy, priceType=PRICETYPE_LIMITPRICE):
|
||||
"""发单"""
|
||||
|
||||
|
||||
self.limitOrderCount += 1
|
||||
orderID = str(self.limitOrderCount)
|
||||
|
||||
@ -2111,6 +2111,11 @@ class BacktestingEngine(object):
|
||||
"""直接返回初始化数据列表中的Tick"""
|
||||
return self.initData
|
||||
|
||||
def createLogger(self, debug=False):
|
||||
filename = os.path.abspath(os.path.join(cta_engine_path, 'TestLogs', '{}'.format(
|
||||
self.strategy_name if len(self.strategy_name) > 0 else 'strategy')))
|
||||
|
||||
self.logger = setup_logger(filename=filename, name=self.strategy_name if len(self.strategy_name) > 0 else 'strategy',debug=debug )
|
||||
#----------------------------------------------------------------------
|
||||
def writeCtaLog(self, content):
|
||||
"""记录日志"""
|
||||
@ -2121,12 +2126,7 @@ class BacktestingEngine(object):
|
||||
if self.logger:
|
||||
self.logger.info(content)
|
||||
else:
|
||||
filename = os.path.abspath(os.path.join(cta_engine_path, 'TestLogs','{}'.format(self.strategy_name if len(self.strategy_name)>0 else 'strategy')))
|
||||
|
||||
self.logger = setup_logger(
|
||||
filename=filename,name=self.strategy_name if len(self.strategy_name)>0 else 'strategy'
|
||||
)
|
||||
|
||||
self.createLogger()
|
||||
|
||||
def writeCtaError(self, content):
|
||||
"""记录异常"""
|
||||
@ -3290,7 +3290,7 @@ class BacktestingEngine(object):
|
||||
'{}_TradeList_{}.csv'.format(s, datetime.now().strftime('%Y%m%d_%H%M'))))
|
||||
|
||||
import csv
|
||||
csvWriteFile = file(csvOutputFile, 'wb')
|
||||
csvWriteFile = open(csvOutputFile, 'wb',encoding='utf8')
|
||||
fieldnames = ['vtSymbol','OpenTime', 'OpenPrice', 'Direction', 'CloseTime', 'ClosePrice', 'Volume', 'Profit']
|
||||
writer = csv.DictWriter(f=csvWriteFile, fieldnames=fieldnames, dialect='excel')
|
||||
writer.writeheader()
|
||||
@ -3307,7 +3307,7 @@ class BacktestingEngine(object):
|
||||
else:
|
||||
csvOutputFile2 = self.daily_report_name
|
||||
|
||||
csvWriteFile2 = file(csvOutputFile2, 'wb')
|
||||
csvWriteFile2 = open(csvOutputFile2, 'wb',encoding='utf8')
|
||||
fieldnames = ['date','capital','net', 'maxCapital','rate','longMoney','shortMoney','occupyMoney','occupyRate','longPos','shortPos']
|
||||
writer2 = csv.DictWriter(f=csvWriteFile2, fieldnames=fieldnames, dialect='excel')
|
||||
writer2.writeheader()
|
||||
@ -3595,11 +3595,11 @@ class OptimizationSetting(object):
|
||||
return
|
||||
|
||||
if end < start:
|
||||
print u'参数起始点必须不大于终止点'
|
||||
print( u'参数起始点必须不大于终止点')
|
||||
return
|
||||
|
||||
if step <= 0:
|
||||
print u'参数布进必须大于0'
|
||||
print( u'参数布进必须大于0')
|
||||
return
|
||||
|
||||
l = []
|
||||
|
@ -5,7 +5,7 @@
|
||||
'''
|
||||
|
||||
from __future__ import division
|
||||
print 'load ctaBase.py'
|
||||
print( 'load ctaBase.py')
|
||||
|
||||
# 常量定义
|
||||
# CTA引擎中涉及到的交易方向类型
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
'''
|
||||
|
||||
print 'load ctaEngine.py'
|
||||
print( 'load ctaEngine.py')
|
||||
import json
|
||||
import os
|
||||
import traceback
|
||||
@ -100,6 +100,9 @@ class CtaEngine(object):
|
||||
self.registerEvent()
|
||||
|
||||
self.logger = None
|
||||
|
||||
self.createLogger()
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def sendOrder(self, vtSymbol, orderType, price, volume, strategy,priceType=PRICETYPE_LIMITPRICE):
|
||||
"""发单"""
|
||||
@ -585,8 +588,12 @@ class CtaEngine(object):
|
||||
if self.logger:
|
||||
self.logger.info(content)
|
||||
else:
|
||||
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), '..','..','logs', 'ctaEngine'))
|
||||
self.logger = setup_logger(filename=filename, name='ctaEngine')
|
||||
self.createLogger()
|
||||
|
||||
def createLogger(self):
|
||||
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'logs', 'ctaEngine'))
|
||||
print( u'create logger:{}'.format(filename))
|
||||
self.logger = setup_logger(filename=filename, name='ctaEngine')
|
||||
|
||||
def writeCtaError(self,content):
|
||||
"""快速发出CTA模块错误日志事件"""
|
||||
@ -699,7 +706,7 @@ class CtaEngine(object):
|
||||
# 5.调用主引擎的订阅接口
|
||||
self.mainEngine.subscribe(req, contract.gatewayName)
|
||||
else:
|
||||
print u'Warning, can not find {0} in contracts'.format(symbol)
|
||||
print( u'Warning, can not find {0} in contracts'.format(symbol))
|
||||
self.writeCtaLog(u'交易合约{}无法找到,添加到待订阅列表'.format (symbol))
|
||||
self.pendingSubcribeSymbols[symbol]=strategy
|
||||
|
||||
|
@ -80,8 +80,7 @@ class CtaGrid(object):
|
||||
j['closeStatus'] = self.closeStatus # 平仓状态
|
||||
j['lockGrids'] = self.lockGrids # 对锁的网格
|
||||
j['reuse'] = self.reuse # 是否重用
|
||||
|
||||
j['type'] = self.type # 类型
|
||||
j['type'] = self.reuse # 是否重用
|
||||
|
||||
j['openPrices'] = self.openPrices # 套利中,两腿的开仓价格
|
||||
j['snapshot'] = self.snapshot # 切片数据
|
||||
@ -847,7 +846,7 @@ class CtaGridTrade(object):
|
||||
return []
|
||||
|
||||
try:
|
||||
f = file(jsonFileName)
|
||||
f = open(jsonFileName,'rb',encoding='utf8')
|
||||
except IOError:
|
||||
self.writeCtaLog(u'读取网格出错,请检查')
|
||||
return []
|
||||
|
@ -96,9 +96,9 @@ class HistoryDataEngine(object):
|
||||
|
||||
self.dbClient[SETTING_DB_NAME]['FuturesSymbol'].update_one(flt, {'$set':symbolDict},
|
||||
upsert=True)
|
||||
print u'期货合约代码下载完成'
|
||||
print( u'期货合约代码下载完成')
|
||||
else:
|
||||
print u'期货合约代码下载失败'
|
||||
print( u'期货合约代码下载失败')
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def downloadFuturesDailyBar(self, symbol):
|
||||
@ -106,7 +106,7 @@ class HistoryDataEngine(object):
|
||||
下载期货合约的日行情,symbol是合约代码,
|
||||
若最后四位为0000(如IF0000),代表下载连续合约。
|
||||
"""
|
||||
print u'开始下载%s日行情' %symbol
|
||||
print( u'开始下载%s日行情' %symbol)
|
||||
|
||||
# 查询数据库中已有数据的最后日期
|
||||
cl = self.dbClient[DAILY_DB_NAME][symbol]
|
||||
@ -158,24 +158,24 @@ class HistoryDataEngine(object):
|
||||
bar.volume = d.get('turnoverVol', 0)
|
||||
bar.openInterest = d.get('openInt', 0)
|
||||
except KeyError:
|
||||
print d
|
||||
print( d)
|
||||
|
||||
flt = {'datetime': bar.datetime}
|
||||
self.dbClient[DAILY_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True)
|
||||
|
||||
print u'%s下载完成' %symbol
|
||||
print( u'%s下载完成' %symbol)
|
||||
else:
|
||||
print u'找不到合约%s' %symbol
|
||||
print( u'找不到合约%s' %symbol)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def downloadAllFuturesDailyBar(self):
|
||||
"""下载所有期货的主力合约日行情"""
|
||||
start = time()
|
||||
print u'开始下载所有期货的主力合约日行情'
|
||||
print( u'开始下载所有期货的主力合约日行情')
|
||||
|
||||
productSymbolSet = self.readFuturesProductSymbol()
|
||||
|
||||
print u'代码列表读取成功,产品代码:%s' %productSymbolSet
|
||||
print( u'代码列表读取成功,产品代码:%s' %productSymbolSet)
|
||||
|
||||
# 这里也测试了线程池,但可能由于下载函数中涉及较多的数据格
|
||||
# 式转换,CPU开销较大,多线程效率并无显著改变。
|
||||
@ -187,12 +187,12 @@ class HistoryDataEngine(object):
|
||||
for productSymbol in productSymbolSet:
|
||||
self.downloadFuturesDailyBar(productSymbol+'0000')
|
||||
|
||||
print u'所有期货的主力合约日行情已经全部下载完成, 耗时%s秒' %(time()-start)
|
||||
print( u'所有期货的主力合约日行情已经全部下载完成, 耗时%s秒' %(time()-start))
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def downloadFuturesIntradayBar(self, symbol):
|
||||
"""下载期货的日内分钟行情"""
|
||||
print u'开始下载%s日内分钟行情' %symbol
|
||||
print( u'开始下载%s日内分钟行情' %symbol)
|
||||
|
||||
# 日内分钟行情只有具体合约
|
||||
path = 'api/market/getFutureBarRTIntraDay.json'
|
||||
@ -226,14 +226,14 @@ class HistoryDataEngine(object):
|
||||
bar.volume = d.get('totalVolume', 0)
|
||||
bar.openInterest = 0
|
||||
except KeyError:
|
||||
print d
|
||||
print( d)
|
||||
|
||||
flt = {'datetime': bar.datetime}
|
||||
self.dbClient[MINUTE_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True)
|
||||
|
||||
print u'%s下载完成' %symbol
|
||||
print( u'%s下载完成' %symbol)
|
||||
else:
|
||||
print u'找不到合约%s' %symbol
|
||||
print( u'找不到合约%s' %symbol )
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def downloadEquitySymbol(self, tradeDate=''):
|
||||
@ -260,16 +260,16 @@ class HistoryDataEngine(object):
|
||||
|
||||
self.dbClient[SETTING_DB_NAME]['EquitySymbol'].update_one(flt, {'$set':symbolDict},
|
||||
upsert=True)
|
||||
print u'股票代码下载完成'
|
||||
print( u'股票代码下载完成')
|
||||
else:
|
||||
print u'股票代码下载失败'
|
||||
print( u'股票代码下载失败')
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def downloadEquityDailyBar(self, symbol):
|
||||
"""
|
||||
下载股票的日行情,symbol是股票代码
|
||||
"""
|
||||
print u'开始下载%s日行情' %symbol
|
||||
print( u'开始下载%s日行情' %symbol)
|
||||
|
||||
# 查询数据库中已有数据的最后日期
|
||||
cl = self.dbClient[DAILY_DB_NAME][symbol]
|
||||
@ -309,14 +309,14 @@ class HistoryDataEngine(object):
|
||||
bar.datetime = datetime.strptime(bar.date, '%Y%m%d')
|
||||
bar.volume = d.get('turnoverVol', 0)
|
||||
except KeyError:
|
||||
print d
|
||||
print( d)
|
||||
|
||||
flt = {'datetime': bar.datetime}
|
||||
self.dbClient[DAILY_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True)
|
||||
|
||||
print u'%s下载完成' %symbol
|
||||
print( u'%s下载完成' %symbol)
|
||||
else:
|
||||
print u'找不到合约%s' %symbol
|
||||
print( u'找不到合约%s' %symbol )
|
||||
|
||||
|
||||
|
||||
@ -326,7 +326,7 @@ def loadMcCsv(fileName, dbName, symbol):
|
||||
import csv
|
||||
|
||||
start = time()
|
||||
print u'开始读取CSV文件%s中的数据插入到%s的%s中' %(fileName, dbName, symbol)
|
||||
print( u'开始读取CSV文件%s中的数据插入到%s的%s中' %(fileName, dbName, symbol))
|
||||
|
||||
# 锁定集合,并创建索引
|
||||
host, port = loadMongoSetting()
|
||||
@ -336,7 +336,8 @@ def loadMcCsv(fileName, dbName, symbol):
|
||||
collection.ensure_index([('datetime', pymongo.ASCENDING)], unique=True)
|
||||
|
||||
# 读取数据和插入到数据库
|
||||
reader = csv.DictReader(file(fileName, 'r'))
|
||||
f = open(fileName,'rb',encoding='utf8')
|
||||
reader = csv.DictReader(f)
|
||||
for d in reader:
|
||||
bar = CtaBarData()
|
||||
bar.vtSymbol = symbol
|
||||
@ -352,9 +353,9 @@ def loadMcCsv(fileName, dbName, symbol):
|
||||
|
||||
flt = {'datetime': bar.datetime}
|
||||
collection.update_one(flt, {'$set':bar.__dict__}, upsert=True)
|
||||
print bar.date, bar.time
|
||||
print( bar.date, bar.time)
|
||||
|
||||
print u'插入完毕,耗时:%s' % (time()-start)
|
||||
print( u'插入完毕,耗时:%s' % (time()-start))
|
||||
|
||||
if __name__ == '__main__':
|
||||
## 简单的测试脚本可以写在这里
|
||||
|
@ -31,9 +31,9 @@ class DatayesClient(object):
|
||||
def loadSetting(self):
|
||||
"""载入配置"""
|
||||
try:
|
||||
f = file(FILENAME)
|
||||
f = open(FILENAME,'rb',encoding='utf8')
|
||||
except IOError:
|
||||
print u'%s无法打开配置文件' % self.name
|
||||
print( u'%s无法打开配置文件' % self.name)
|
||||
return
|
||||
|
||||
setting = json.load(f)
|
||||
@ -42,28 +42,28 @@ class DatayesClient(object):
|
||||
self.version = str(setting['version'])
|
||||
self.token = str(setting['token'])
|
||||
except KeyError:
|
||||
print u'%s配置文件字段缺失' % self.name
|
||||
print( u'%s配置文件字段缺失' % self.name)
|
||||
return
|
||||
|
||||
self.header['Connection'] = 'keep_alive'
|
||||
self.header['Authorization'] = 'Bearer ' + self.token
|
||||
self.settingLoaded = True
|
||||
|
||||
print u'%s配置载入完成' % self.name
|
||||
print( u'%s配置载入完成' % self.name)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def downloadData(self, path, params):
|
||||
"""下载数据"""
|
||||
if not self.settingLoaded:
|
||||
print u'%s配置未载入' % self.name
|
||||
print( u'%s配置未载入' % self.name)
|
||||
return None
|
||||
else:
|
||||
url = '/'.join([self.domain, self.version, path])
|
||||
r = requests.get(url=url, headers=self.header, params=params)
|
||||
|
||||
if r.status_code != HTTP_OK:
|
||||
print u'%shttp请求失败,状态代码%s' %(self.name, r.status_code)
|
||||
print( u'%shttp请求失败,状态代码%s' %(self.name, r.status_code))
|
||||
return None
|
||||
else:
|
||||
result = r.json()
|
||||
@ -71,9 +71,9 @@ class DatayesClient(object):
|
||||
return result['data']
|
||||
else:
|
||||
if 'retMsg' in result:
|
||||
print u'%s查询失败,返回信息%s' %(self.name, result['retMsg'])
|
||||
print(u'%s查询失败,返回信息%s' %(self.name, result['retMsg']))
|
||||
elif 'message' in result:
|
||||
print u'%s查询失败,返回信息%s' %(self.name, result['message'])
|
||||
print( u'%s查询失败,返回信息%s' %(self.name, result['message']))
|
||||
return None
|
||||
|
||||
|
||||
|
@ -5,9 +5,9 @@ import os
|
||||
import traceback
|
||||
|
||||
# 默认设置
|
||||
from chinese import text
|
||||
from vnpy.trader.app.ctaStrategy.language.chinese import text
|
||||
|
||||
# 是否要使用英文
|
||||
from vnpy.trader.vtGlobal import globalSetting
|
||||
if globalSetting['language'] == 'english':
|
||||
from english import text
|
||||
from vnpy.trader.app.ctaStrategy.language.english import text
|
@ -48,7 +48,7 @@ class CtaValueMonitor(QtWidgets.QTableWidget):
|
||||
# 新增数据
|
||||
col = 0
|
||||
for k, v in data.items():
|
||||
cell = QtWidgets.QTableWidgetItem(unicode(v))
|
||||
cell = QtWidgets.QTableWidgetItem(v)
|
||||
self.keyCellDict[k] = cell
|
||||
self.setItem(0, col, cell)
|
||||
col += 1
|
||||
@ -58,7 +58,7 @@ class CtaValueMonitor(QtWidgets.QTableWidget):
|
||||
# 更新数据
|
||||
for k, v in data.items():
|
||||
cell = self.keyCellDict[k]
|
||||
cell.setText(unicode(v))
|
||||
cell.setText(v)
|
||||
|
||||
#cell.setBackgroundColor()
|
||||
|
||||
|
@ -5,12 +5,12 @@
|
||||
'''
|
||||
|
||||
from vnpy.trader.vtConstant import DIRECTION_LONG, DIRECTION_SHORT
|
||||
from vnpy.trader.uiBasicWidget import QtGui, QtCore
|
||||
from vnpy.trader.uiBasicWidget import QtWidgets, QtGui, QtCore
|
||||
from vnpy.trader.vtEvent import *
|
||||
from vnpy.trader.app.ctaStrategy.ctaGridTrade import *
|
||||
|
||||
########################################################################
|
||||
class SplitLine(QtGui.QFrame):
|
||||
class SplitLine(QtWidgets.QFrame):
|
||||
"""水平分割线"""
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
@ -20,7 +20,7 @@ class SplitLine(QtGui.QFrame):
|
||||
self.setFrameShape(self.HLine)
|
||||
self.setFrameShadow(self.Sunken)
|
||||
|
||||
class SpreadTradeManager(QtGui.QWidget):
|
||||
class SpreadTradeManager(QtWidgets.QWidget):
|
||||
# ----------------------------------------------------------------------
|
||||
def __init__(self, ctaEngine, eventEngine, parent=None):
|
||||
super(SpreadTradeManager, self).__init__(parent)
|
||||
@ -38,15 +38,15 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.setWindowTitle(u'套利交易')
|
||||
|
||||
# 连接运行中的套利测试(策略名称[下拉菜单],连接按钮)
|
||||
self.btnSwitchConnectStatus = QtGui.QPushButton(u'套利策略未连接')
|
||||
self.btnSwitchConnectStatus = QtWidgets.QPushButton(u'套利策略未连接')
|
||||
self.btnSwitchConnectStatus.clicked.connect(self.btnSwitchClick)
|
||||
|
||||
Label = QtGui.QLabel
|
||||
grid = QtGui.QGridLayout()
|
||||
Label = QtWidgets.QLabel
|
||||
grid = QtWidgets.QGridLayout()
|
||||
grid.addWidget(Label(u'状态'), 0, 0)
|
||||
grid.addWidget(self.btnSwitchConnectStatus, 0, 1)
|
||||
|
||||
self.spreadStraty = QtGui.QComboBox()
|
||||
self.spreadStraty = QtWidgets.QComboBox()
|
||||
self.strategy_name_list = self.ctaEngine.strategyDict.keys()
|
||||
self.spreadStraty.addItems(self.strategy_name_list)
|
||||
|
||||
@ -57,11 +57,11 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
# 网格信息+操作(新增,删除,更新)
|
||||
|
||||
grid.addWidget(Label(u'方向'), 2, 0)
|
||||
self.gridDirection = QtGui.QComboBox()
|
||||
self.gridDirection = QtWidgets.QComboBox()
|
||||
self.gridDirection.addItems(self.directionList)
|
||||
grid.addWidget(self.gridDirection, 2, 1)
|
||||
|
||||
self.spinOpenPrice = QtGui.QDoubleSpinBox()
|
||||
self.spinOpenPrice = QtWidgets.QDoubleSpinBox()
|
||||
self.spinOpenPrice.setDecimals(4)
|
||||
self.spinOpenPrice.setMinimum(-10000) # 原来是0,为支持套利,改为-10000
|
||||
self.spinOpenPrice.setMaximum(100000)
|
||||
@ -70,7 +70,7 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
grid.addWidget(Label(u'开仓价'), 3, 0)
|
||||
grid.addWidget(self.spinOpenPrice, 3, 1)
|
||||
|
||||
self.spinClosePrice = QtGui.QDoubleSpinBox()
|
||||
self.spinClosePrice = QtWidgets.QDoubleSpinBox()
|
||||
self.spinClosePrice.setDecimals(4)
|
||||
self.spinClosePrice.setMinimum(-10000) # 原来是0,为支持套利,改为-10000
|
||||
self.spinClosePrice.setMaximum(100000)
|
||||
@ -78,57 +78,60 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
grid.addWidget(Label(u'平仓价'), 4, 0)
|
||||
grid.addWidget(self.spinClosePrice, 4, 1)
|
||||
|
||||
self.spinOrderVolume = QtGui.QSpinBox()
|
||||
self.spinOrderVolume = QtWidgets.QSpinBox()
|
||||
self.spinOrderVolume.setMinimum(0)
|
||||
self.spinOrderVolume.setMaximum(1000)
|
||||
|
||||
grid.addWidget(Label(u'委托数量'), 5, 0)
|
||||
grid.addWidget(self.spinOrderVolume, 5, 1)
|
||||
|
||||
self.spinTradedVolume = QtGui.QSpinBox()
|
||||
self.spinTradedVolume = QtWidgets.QSpinBox()
|
||||
self.spinTradedVolume.setMinimum(0)
|
||||
self.spinTradedVolume.setMaximum(1000)
|
||||
|
||||
grid.addWidget(Label(u'成交数量'), 6, 0)
|
||||
grid.addWidget(self.spinTradedVolume, 6, 1)
|
||||
|
||||
self.openStatus = QtGui.QCheckBox(u'') # 开仓状态
|
||||
self.openStatus = QtWidgets.QCheckBox(u'') # 开仓状态
|
||||
grid.addWidget(Label(u'开仓状态'), 7, 0)
|
||||
grid.addWidget(self.openStatus, 7, 1)
|
||||
|
||||
self.orderStatus = QtGui.QCheckBox(u'') # 委托状态
|
||||
self.orderStatus = QtWidgets.QCheckBox(u'') # 委托状态
|
||||
grid.addWidget(Label(u'委托状态'), 8, 0)
|
||||
grid.addWidget(self.orderStatus, 8, 1)
|
||||
|
||||
self.closeStatus = QtGui.QCheckBox(u'') # 平仓状态
|
||||
self.closeStatus = QtWidgets.QCheckBox(u'') # 平仓状态
|
||||
grid.addWidget(Label(u'平仓状态'), 9, 0)
|
||||
grid.addWidget(self.closeStatus, 9, 1)
|
||||
|
||||
btnAddGrid = QtGui.QPushButton(u'增加')
|
||||
self.reuseStatus = QtWidgets.QCheckBox(u'') # 平仓状态
|
||||
grid.addWidget(Label(u'重用网格'), 10, 0)
|
||||
grid.addWidget(self.reuseStatus, 10, 1)
|
||||
|
||||
btnAddGrid = QtWidgets.QPushButton(u'增加')
|
||||
btnAddGrid.clicked.connect(self.btnAddGridClick)
|
||||
btnUpdateGrid = QtGui.QPushButton(u'更新')
|
||||
btnUpdateGrid = QtWidgets.QPushButton(u'更新')
|
||||
btnUpdateGrid.clicked.connect(self.btnUpdateGridClick)
|
||||
btnRemoveGrid = QtGui.QPushButton(u'删除')
|
||||
btnRemoveGrid = QtWidgets.QPushButton(u'删除')
|
||||
btnRemoveGrid.clicked.connect(self.btnRemoveGridClick)
|
||||
btnRemoveAll = QtGui.QPushButton(u'全删除')
|
||||
btnRemoveAll = QtWidgets.QPushButton(u'全删除')
|
||||
btnRemoveAll.clicked.connect(self.btnRemoveAllClick)
|
||||
|
||||
hbox = QtGui.QHBoxLayout()
|
||||
hbox = QtWidgets.QHBoxLayout()
|
||||
hbox.addWidget(btnAddGrid)
|
||||
hbox.addWidget(btnUpdateGrid)
|
||||
hbox.addStretch()
|
||||
hbox.addWidget(btnRemoveGrid)
|
||||
hbox.addWidget(btnRemoveAll)
|
||||
|
||||
vbox = QtGui.QVBoxLayout()
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.addLayout(grid)
|
||||
vbox.addLayout(hbox)
|
||||
|
||||
|
||||
# 状态信息(通过定时器,显示 上网格清单,下网格清单)
|
||||
|
||||
#日志监控
|
||||
self.logMsgs = QtGui.QTextEdit()
|
||||
self.logMsgs = QtWidgets.QTextEdit()
|
||||
self.logMsgs.setReadOnly(True)
|
||||
self.logMsgs.setMaximumHeight(200)
|
||||
vbox.addWidget(self.logMsgs)
|
||||
@ -141,7 +144,7 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.log(u'没有连接CTA引擎')
|
||||
return
|
||||
|
||||
strategy_name = unicode(self.spreadStraty.currentText())
|
||||
strategy_name = self.spreadStraty.currentText()
|
||||
|
||||
if strategy_name is None or len(strategy_name) == 0:
|
||||
if len(self.strategy_name_list)==0:
|
||||
@ -171,7 +174,7 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.log(u'没有连接策略')
|
||||
return
|
||||
|
||||
direction = unicode(self.gridDirection.currentText())
|
||||
direction = self.gridDirection.currentText()
|
||||
if direction is None or len(direction) ==0:
|
||||
self.log(u'先选择方向')
|
||||
return
|
||||
@ -188,6 +191,8 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
closeprice=close_price,
|
||||
volume=order_volume)
|
||||
|
||||
grid.reuse = self.reuseStatus.isChecked()
|
||||
|
||||
if direction == DIRECTION_LONG:
|
||||
self.strategy.gt.dnGrids.append(grid)
|
||||
|
||||
@ -215,7 +220,7 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.log(u'没有连接策略')
|
||||
return
|
||||
|
||||
direction = unicode(self.gridDirection.currentText())
|
||||
direction = self.gridDirection.currentText()
|
||||
if direction is None or len(direction) == 0:
|
||||
self.log(u'先选择方向');
|
||||
return
|
||||
@ -233,6 +238,7 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.openStatus.setChecked(grid.openStatus)
|
||||
self.orderStatus.setChecked(grid.orderStatus)
|
||||
self.closeStatus.setChecked(grid.closeStatus)
|
||||
self.reuseStatus.setChecked(grid.reuse)
|
||||
|
||||
def btnUpdateGridClick(self):
|
||||
"""更新网格"""
|
||||
@ -244,7 +250,7 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.log(u'没有连接策略')
|
||||
return
|
||||
|
||||
direction = unicode(self.gridDirection.currentText())
|
||||
direction = self.gridDirection.currentText()
|
||||
if direction is None or len(direction) ==0:
|
||||
self.log(u'先选择方向')
|
||||
return
|
||||
@ -256,12 +262,14 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.log(u'没有找到{0}方向的网格:{1}'.format(direction,open_price))
|
||||
return
|
||||
|
||||
grid.openPrice = open_price
|
||||
grid.closePrice = self.spinClosePrice.value()
|
||||
grid.volume = self.spinOrderVolume.value()
|
||||
grid.tradedVolume = self.spinTradedVolume.value()
|
||||
grid.openStatus = self.openStatus.isChecked()
|
||||
grid.orderStatus = self.orderStatus.isChecked()
|
||||
grid.closeStatus = self.closeStatus.isChecked()
|
||||
grid.reuse = self.reuseStatus.isChecked()
|
||||
|
||||
self.strategy.gt.save(direction=direction)
|
||||
self.strategy.recheckPositions = True
|
||||
@ -277,16 +285,33 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.log(u'没有连接策略')
|
||||
return
|
||||
|
||||
direction = unicode(self.gridDirection.currentText())
|
||||
|
||||
direction = self.gridDirection.currentText()
|
||||
if direction is None or len(direction) == 0:
|
||||
self.log(u'先选择方向')
|
||||
return
|
||||
|
||||
open_price = self.spinOpenPrice.value()
|
||||
self.strategy.gt.removeGrids(direction=direction, priceline=open_price)
|
||||
self.strategy.gt.save(direction=direction)
|
||||
self.log(u'成功移除{0}方向的网格:{1}'.format(direction,open_price))
|
||||
self.displayGrids()
|
||||
if (direction == DIRECTION_LONG and len(self.strategy.gt.dnGrids) < 2) or \
|
||||
(direction == DIRECTION_SHORT and len(self.strategy.gt.upGrids) < 2):
|
||||
self.log(u'{0}方向的网格只有一个,不能删除'.format(direction))
|
||||
return
|
||||
|
||||
grid = self.strategy.gt.getGrid(direction=direction, openPrice=open_price, t=u'OpenPrice')
|
||||
if grid is None:
|
||||
self.log(u'没有找到{0}方向的网格:{1},删除{1}范围内的非开仓网格'.format(direction, open_price))
|
||||
|
||||
self.strategy.gt.removeGrids(direction=direction, priceline=open_price)
|
||||
self.strategy.gt.save(direction=direction)
|
||||
self.log(u'成功移除{0}方向{1}以内网格'.format(direction, open_price))
|
||||
self.displayGrids()
|
||||
return
|
||||
|
||||
if grid.id is not None:
|
||||
self.strategy.gt.removeGridById(direction=direction,id= grid.id)
|
||||
self.log(u'成功移除{0}方向的网格:{1}'.format(direction, open_price))
|
||||
self.strategy.gt.save(direction=direction)
|
||||
self.displayGrids()
|
||||
|
||||
def btnRemoveAllClick(self):
|
||||
"""删除所有网格"""
|
||||
@ -298,17 +323,19 @@ class SpreadTradeManager(QtGui.QWidget):
|
||||
self.log(u'没有连接策略')
|
||||
return
|
||||
|
||||
direction = unicode(self.gridDirection.currentText())
|
||||
direction = self.gridDirection.currentText()
|
||||
if direction is None or len(direction) == 0:
|
||||
self.log(u'先选择方向')
|
||||
return
|
||||
|
||||
if direction == DIRECTION_LONG:
|
||||
self.strategy.gt.dnGrids = []
|
||||
self.strategy.gt.dnGrids = self.strategy.gt.dnGrids [-1:]
|
||||
self.strategy.gt.save(direction=direction)
|
||||
self.log(u'成功移除{0}方向的网格,只保留最后一个'.format(direction))
|
||||
else:
|
||||
self.strategy.gt.upGrids=[]
|
||||
self.strategy.gt.upGrids = self.strategy.gt.dnGrids [-1:]
|
||||
self.strategy.gt.save(direction=direction)
|
||||
self.log(u'成功移除{0}方向的网格,只保留最后一个'.format(direction))
|
||||
|
||||
self.displayGrids()
|
||||
|
||||
|
@ -4,12 +4,13 @@
|
||||
import os
|
||||
import cPickle
|
||||
import csv
|
||||
import logging
|
||||
import pandas
|
||||
import copy
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from ctaBase import *
|
||||
from vnpy.trader.setup_logger import get_logger
|
||||
|
||||
|
||||
class UtilArbTickLoader(object):
|
||||
"""一个套利tick的数据加载工具类"""
|
||||
@ -23,14 +24,18 @@ class UtilArbTickLoader(object):
|
||||
|
||||
self.symbol = symbol
|
||||
|
||||
self.logger = None
|
||||
|
||||
def writeCtaLog(self, content):
|
||||
"""记录日志"""
|
||||
# log = str(self.dt) + ' ' + content
|
||||
# self.logList.append(log)
|
||||
|
||||
# 写入本地log日志
|
||||
logging.info(content)
|
||||
|
||||
if self.logger:
|
||||
self.logger.info(content)
|
||||
else:
|
||||
self.logger = get_logger()
|
||||
def writeCtaError(self, content):
|
||||
"""记录异常"""
|
||||
self.output(content)
|
||||
@ -38,7 +43,7 @@ class UtilArbTickLoader(object):
|
||||
|
||||
def output(self, content):
|
||||
"""输出内容"""
|
||||
print str(datetime.now()) + "\t" + content
|
||||
print( str(datetime.now()) + "\t" + content)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
@ -68,7 +73,7 @@ class UtilArbTickLoader(object):
|
||||
# 先读取leg2的数据到目录,以日期时间为key
|
||||
leg2Ticks = {}
|
||||
|
||||
leg2CsvReadFile = file(leg2File, 'rb')
|
||||
leg2CsvReadFile = open(leg2File, 'rb',encoding='utf8')
|
||||
#reader = csv.DictReader((line.replace('\0',' ') for line in leg2CsvReadFile), delimiter=",")
|
||||
reader = csv.DictReader(leg2CsvReadFile, delimiter=",")
|
||||
self.writeCtaLog(u'加载{0}'.format(leg2File))
|
||||
@ -118,7 +123,7 @@ class UtilArbTickLoader(object):
|
||||
else:
|
||||
leg2Ticks[dtStr] = tick
|
||||
|
||||
leg1CsvReadFile = file(leg1File, 'rb')
|
||||
leg1CsvReadFile = open(leg1File, 'rb',encoding='utf8')
|
||||
#reader = csv.DictReader((line.replace('\0',' ') for line in leg1CsvReadFile), delimiter=",")
|
||||
reader = csv.DictReader(leg1CsvReadFile, delimiter=",")
|
||||
self.writeCtaLog(u'加载{0}'.format(leg1File))
|
||||
|
@ -11,7 +11,7 @@ import os
|
||||
import copy
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime, timedelta
|
||||
from Queue import Queue
|
||||
from queue import Queue
|
||||
from threading import Thread
|
||||
|
||||
from vnpy.trader.vtEvent import *
|
||||
|
@ -6,12 +6,12 @@
|
||||
|
||||
import json
|
||||
|
||||
from vnpy.trader.uiBasicWidget import QtGui, QtCore
|
||||
from vnpy.trader.uiBasicWidget import QtWidgets, QtGui, QtCore
|
||||
from vnpy.trader.vtEvent import *
|
||||
|
||||
|
||||
########################################################################
|
||||
class TableCell(QtGui.QTableWidgetItem):
|
||||
class TableCell(QtWidgets.QTableWidgetItem):
|
||||
"""居中的单元格"""
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
@ -33,9 +33,9 @@ class TableCell(QtGui.QTableWidgetItem):
|
||||
|
||||
|
||||
########################################################################
|
||||
class DrEngineManager(QtGui.QWidget):
|
||||
class DrEngineManager(QtWidgets.QWidget):
|
||||
"""行情数据记录引擎管理组件"""
|
||||
signal = QtCore.pyqtSignal(type(Event()))
|
||||
signal = QtCore.Signal(type(Event()))
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __init__(self, drEngine, eventEngine, parent=None):
|
||||
@ -55,40 +55,40 @@ class DrEngineManager(QtGui.QWidget):
|
||||
self.setWindowTitle(u'行情数据记录工具')
|
||||
|
||||
# 记录合约配置监控
|
||||
tickLabel = QtGui.QLabel(u'Tick记录')
|
||||
self.tickTable = QtGui.QTableWidget()
|
||||
tickLabel = QtWidgets.QLabel(u'Tick记录')
|
||||
self.tickTable = QtWidgets.QTableWidget()
|
||||
self.tickTable.setColumnCount(2)
|
||||
self.tickTable.verticalHeader().setVisible(False)
|
||||
self.tickTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers)
|
||||
self.tickTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
|
||||
self.tickTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||
self.tickTable.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
|
||||
self.tickTable.setAlternatingRowColors(True)
|
||||
self.tickTable.setHorizontalHeaderLabels([u'合约代码', u'接口'])
|
||||
|
||||
barLabel = QtGui.QLabel(u'Bar记录')
|
||||
self.barTable = QtGui.QTableWidget()
|
||||
barLabel = QtWidgets.QLabel(u'Bar记录')
|
||||
self.barTable = QtWidgets.QTableWidget()
|
||||
self.barTable.setColumnCount(2)
|
||||
self.barTable.verticalHeader().setVisible(False)
|
||||
self.barTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers)
|
||||
self.barTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
|
||||
self.barTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||
self.barTable.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
|
||||
self.barTable.setAlternatingRowColors(True)
|
||||
self.barTable.setHorizontalHeaderLabels([u'合约代码', u'接口'])
|
||||
|
||||
activeLabel = QtGui.QLabel(u'主力合约')
|
||||
self.activeTable = QtGui.QTableWidget()
|
||||
activeLabel = QtWidgets.QLabel(u'主力合约')
|
||||
self.activeTable = QtWidgets.QTableWidget()
|
||||
self.activeTable.setColumnCount(2)
|
||||
self.activeTable.verticalHeader().setVisible(False)
|
||||
self.activeTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers)
|
||||
self.activeTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)
|
||||
self.activeTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
|
||||
self.activeTable.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
|
||||
self.activeTable.setAlternatingRowColors(True)
|
||||
self.activeTable.setHorizontalHeaderLabels([u'主力代码', u'合约代码'])
|
||||
|
||||
# 日志监控
|
||||
self.logMonitor = QtGui.QTextEdit()
|
||||
self.logMonitor = QtWidgets.QTextEdit()
|
||||
self.logMonitor.setReadOnly(True)
|
||||
self.logMonitor.setMinimumHeight(600)
|
||||
|
||||
# 设置布局
|
||||
grid = QtGui.QGridLayout()
|
||||
grid = QtWidgets.QGridLayout()
|
||||
|
||||
grid.addWidget(tickLabel, 0, 0)
|
||||
grid.addWidget(barLabel, 0, 1)
|
||||
@ -97,7 +97,7 @@ class DrEngineManager(QtGui.QWidget):
|
||||
grid.addWidget(self.barTable, 1, 1)
|
||||
grid.addWidget(self.activeTable, 1, 2)
|
||||
|
||||
vbox = QtGui.QVBoxLayout()
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.addLayout(grid)
|
||||
vbox.addWidget(self.logMonitor)
|
||||
self.setLayout(vbox)
|
||||
|
368
vnpy/trader/app/dataRecorder/utlImportTicks.py
Normal file
368
vnpy/trader/app/dataRecorder/utlImportTicks.py
Normal file
@ -0,0 +1,368 @@
|
||||
# encoding: UTF-8
|
||||
# 定义Tick数据的格式
|
||||
# 默认空值
|
||||
EMPTY_STRING = ''
|
||||
EMPTY_UNICODE = u''
|
||||
EMPTY_INT = 0
|
||||
EMPTY_FLOAT = 0.0
|
||||
|
||||
|
||||
class CtaTickData(object):
|
||||
"""Tick数据"""
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def __init__(self):
|
||||
"""Constructor"""
|
||||
self.vtSymbol = EMPTY_STRING # vt系统代码 CF705
|
||||
self.symbol = EMPTY_STRING # 合约代码 CF1705
|
||||
self.exchange = EMPTY_STRING # 交易所代码
|
||||
|
||||
# 成交数据
|
||||
self.lastPrice = EMPTY_FLOAT # 最新成交价
|
||||
self.volume = EMPTY_INT # 最新成交量
|
||||
self.preOpenInterest = EMPTY_INT # 昨持仓量
|
||||
self.openInterest = EMPTY_INT # 持仓量
|
||||
|
||||
self.upperLimit = EMPTY_FLOAT # 涨停价
|
||||
self.lowerLimit = EMPTY_FLOAT # 跌停价
|
||||
|
||||
# tick的时间
|
||||
self.tradingDay = EMPTY_STRING # 交易日期
|
||||
self.date = EMPTY_STRING # 日期
|
||||
self.time = EMPTY_STRING # 时间
|
||||
self.datetime = None # python的datetime时间对象
|
||||
|
||||
# 五档行情
|
||||
self.bidPrice1 = EMPTY_FLOAT
|
||||
self.bidPrice2 = EMPTY_FLOAT
|
||||
self.bidPrice3 = EMPTY_FLOAT
|
||||
self.bidPrice4 = EMPTY_FLOAT
|
||||
self.bidPrice5 = EMPTY_FLOAT
|
||||
|
||||
self.askPrice1 = EMPTY_FLOAT
|
||||
self.askPrice2 = EMPTY_FLOAT
|
||||
self.askPrice3 = EMPTY_FLOAT
|
||||
self.askPrice4 = EMPTY_FLOAT
|
||||
self.askPrice5 = EMPTY_FLOAT
|
||||
|
||||
self.bidVolume1 = EMPTY_INT
|
||||
self.bidVolume2 = EMPTY_INT
|
||||
self.bidVolume3 = EMPTY_INT
|
||||
self.bidVolume4 = EMPTY_INT
|
||||
self.bidVolume5 = EMPTY_INT
|
||||
|
||||
self.askVolume1 = EMPTY_INT
|
||||
self.askVolume2 = EMPTY_INT
|
||||
self.askVolume3 = EMPTY_INT
|
||||
self.askVolume4 = EMPTY_INT
|
||||
self.askVolume5 = EMPTY_INT
|
||||
|
||||
|
||||
from pymongo import MongoClient
|
||||
|
||||
mongodb_host = '192.168.0.202'
|
||||
mongodb_port = 27017
|
||||
mongodb_user = 'vnpy'
|
||||
mongodb_pwd = 'vnpy'
|
||||
|
||||
|
||||
class mongodb_client(object):
|
||||
def __init__(self):
|
||||
self.dbClient = None
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def writeLog(self, content):
|
||||
"""日志"""
|
||||
print( content)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def dbConnect(self):
|
||||
"""连接MongoDB数据库"""
|
||||
if not self.dbClient:
|
||||
|
||||
try:
|
||||
# 设置MongoDB操作的超时时间为0.5秒
|
||||
self.dbClient = MongoClient(mongodb_host, mongodb_port, serverSelectionTimeoutMS=500)
|
||||
|
||||
# 这里使用了ticks这个库来验证用户账号和密码
|
||||
self.dbClient.ticks.authenticate(mongodb_user, mongodb_pwd, mechanism='SCRAM-SHA-1')
|
||||
|
||||
# 调用server_info查询服务器状态,防止服务器异常并未连接成功
|
||||
self.dbClient.server_info()
|
||||
|
||||
self.writeLog(u'MongoDB连接成功')
|
||||
except Exception as ex:
|
||||
self.writeLog(u'MongoDB连接失败{0}'.format(ex))
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def dbInsert(self, dbName, collectionName, d):
|
||||
"""向MongoDB中插入数据,d是具体数据"""
|
||||
if self.dbClient:
|
||||
db = self.dbClient[dbName]
|
||||
collection = db[collectionName]
|
||||
collection.insert(d)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def dbInsertMany(self, dbName, collectionName, dataList):
|
||||
"""向MongoDB中插入Multi数据,dataList是具体数据List"""
|
||||
if self.dbClient:
|
||||
db = self.dbClient[dbName]
|
||||
collection = db.getCollection(collectionName)
|
||||
collection.insertMany(dataList)\
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def dbQuery(self, dbName, collectionName, d):
|
||||
"""从MongoDB中读取数据,d是查询要求,返回的是数据库查询的指针"""
|
||||
if self.dbClient:
|
||||
db = self.dbClient[dbName]
|
||||
collection = db[collectionName]
|
||||
cursor = collection.find(d)
|
||||
return cursor
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from collections import OrderedDict
|
||||
import os
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def load_ticks_from_csv_file(file_name, symbol, trading_day):
|
||||
"""从csv tick文件中UnicodeDictReader读取tick
|
||||
file_name,文件全路径
|
||||
symbol,合约代码,RB01, RBMI 等
|
||||
trading_day,交易日字符串
|
||||
"""
|
||||
# 先读取数据到Dict,以日期时间为key
|
||||
ticks = OrderedDict()
|
||||
|
||||
if not os.path.isfile(file_name):
|
||||
print( u'{0}文件不存在'.format(file_name))
|
||||
return ticks
|
||||
dt = None
|
||||
|
||||
start_time = datetime.now()
|
||||
df = pd.read_csv(file_name, encoding='gbk', parse_dates=False)
|
||||
df.columns = ['date', 'time', 'lastPrice', 'lastVolume', 'totalInterest', 'position',
|
||||
'bidPrice1', 'bidVolume1', 'bidPrice2', 'bidVolume2', 'bidPrice3', 'bidVolume3',
|
||||
'askPrice1', 'askVolume1', 'askPrice2', 'askVolume2', 'askPrice3', 'askVolume3', 'BS']
|
||||
readed_ticks = len(df)
|
||||
|
||||
position = 0
|
||||
|
||||
for i in range(0, len(df)):
|
||||
# 日期, 时间, 成交价, 成交量, 总量, 属性(持仓增减), B1价, B1量, B2价, B2量, B3价, B3量, S1价, S1量, S2价, S2量, S3价, S3量, BS
|
||||
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
||||
row = df.iloc[i].to_dict()
|
||||
tick = CtaTickData()
|
||||
|
||||
tick.vtSymbol = symbol
|
||||
tick.symbol = symbol
|
||||
|
||||
tick.date = row['date']
|
||||
tick.tradingDay = trading_day
|
||||
tick.time = row['time']
|
||||
|
||||
try:
|
||||
tick.datetime = datetime.strptime(tick.date + ' ' + tick.time, '%Y-%m-%d %H:%M:%S')
|
||||
except Exception as ex:
|
||||
print( u'日期转换错误:{0},{1}:{2}'.format(tick.date + ' ' + tick.time, Exception, ex))
|
||||
continue
|
||||
|
||||
tick.date = tick.datetime.strftime('%Y%m%d')
|
||||
# 修正毫秒
|
||||
if tick.datetime.replace(microsecond=0) == dt:
|
||||
# 与上一个tick的时间(去除毫秒后)相同,修改为500毫秒
|
||||
tick.datetime = tick.datetime.replace(microsecond=500)
|
||||
tick.time = tick.datetime.strftime('%H:%M:%S.%f')
|
||||
|
||||
else:
|
||||
tick.datetime = tick.datetime.replace(microsecond=0)
|
||||
tick.time = tick.datetime.strftime('%H:%M:%S.%f')
|
||||
|
||||
dt = tick.datetime
|
||||
|
||||
tick.lastPrice = float(row['lastPrice'])
|
||||
tick.volume = int(float(row['lastVolume']))
|
||||
tick.bidPrice1 = float(row['bidPrice1']) # 叫买价(价格低)
|
||||
tick.bidVolume1 = int(float(row['bidVolume1']))
|
||||
tick.askPrice1 = float(row['askPrice1']) # 叫卖价(价格高)
|
||||
tick.askVolume1 = int(float(row['askVolume1']))
|
||||
|
||||
tick.dayVolume = int(float(row['totalInterest'])) # 当日累计成交量
|
||||
|
||||
position += int(float(row['position'])) # 持仓量
|
||||
tick.openInterest = position # 持仓量
|
||||
|
||||
dtStr = tick.date + ' ' + tick.time
|
||||
|
||||
if dtStr not in ticks:
|
||||
ticks[dtStr] = tick
|
||||
if len(ticks) != readed_ticks:
|
||||
print( u'分析tick对象数量{0}与读取数据数量{1}不一致'.format(len(ticks), readed_ticks))
|
||||
|
||||
print( u'读取{0},共加载{1}条数据,耗时:{2}seconds'.format(file_name, readed_ticks, str(datetime.now() - start_time)))
|
||||
|
||||
return ticks
|
||||
|
||||
import csv
|
||||
|
||||
def load_ticks_from_txt_file(file_name, symbol, trading_day):
|
||||
"""
|
||||
读取中金所txt 格式的tick文件
|
||||
file_name,文件全路径
|
||||
symbol,合约代码,IC1601 等
|
||||
trading_day,交易日字符串
|
||||
返回ctatick对象dict,无内容返回空的dict
|
||||
"""
|
||||
# 先读取数据到Dict,以日期时间为key
|
||||
ticks = OrderedDict()
|
||||
|
||||
if not os.path.isfile(file_name):
|
||||
print( u'{0}文件不存在'.format(file_name))
|
||||
return []
|
||||
|
||||
last_tick_datetime = None
|
||||
# 文件句柄
|
||||
csv_read_file = open(file_name, 'rb',encoding='utf8')
|
||||
|
||||
# 通过csv模块的DictReader,一次性读取所有数据
|
||||
reader = csv.DictReader(csv_read_file, delimiter=",")
|
||||
|
||||
start_time = datetime.now()
|
||||
# 逐行数据处理
|
||||
for row in reader:
|
||||
tick = CtaTickData()
|
||||
# vtSymbol:CF1705, symbol:CF1705
|
||||
tick.vtSymbol = symbol
|
||||
tick.symbol = symbol
|
||||
|
||||
# 日期格式为 '20170120',交易日期,在夜盘时,交易日期为下一交易日
|
||||
tick.date = trading_day
|
||||
tick.tradingDay = tick.date
|
||||
tick.time = row['Time']
|
||||
|
||||
# 转换为datetime格式
|
||||
try:
|
||||
tick.datetime = datetime.strptime(tick.date + ' ' + tick.time, '%Y%m%d %H:%M:%S.%f')
|
||||
except Exception as ex:
|
||||
# 抛弃本tick
|
||||
print( u'日期转换错误:{0},{1}:{2}'.format(tick.date + ' ' + tick.time, Exception, ex))
|
||||
continue
|
||||
|
||||
# 修正毫秒
|
||||
if tick.datetime.replace(microsecond=0) == last_tick_datetime:
|
||||
# 与上一个tick的时间(去除毫秒后)相同,修改为500毫秒
|
||||
tick.datetime = tick.datetime.replace(microsecond=500)
|
||||
tick.time = tick.datetime.strftime('%H:%M:%S.%f')
|
||||
|
||||
else:
|
||||
tick.datetime = tick.datetime.replace(microsecond=0)
|
||||
tick.time = tick.datetime.strftime('%H:%M:%S.%f')
|
||||
|
||||
# 记录最新tick的时间
|
||||
last_tick_datetime = tick.datetime
|
||||
|
||||
tick.lastPrice = float(row['LastPrice']) # 最新价
|
||||
tick.volume = int(float(row['LVolume'])) # 成交量
|
||||
tick.bidPrice1 = float(row['BidPrice']) # 叫买价(价格低)
|
||||
tick.bidVolume1 = int(float(row['BidVolume'])) # 叫买量
|
||||
tick.askPrice1 = float(row['AskPrice']) # 叫卖价(价格高)
|
||||
tick.askVolume1 = int(float(row['AskVolume'])) # 叫卖量
|
||||
|
||||
tick.openInterest = int(float(row['OpenInterest'])) # 持仓量
|
||||
tick.dayVolume = int(float(row['TradeVolume'])) # 当日累计成交量
|
||||
|
||||
dtStr = tick.date + ' ' + tick.time
|
||||
if dtStr not in ticks:
|
||||
ticks[dtStr] = tick
|
||||
|
||||
print( u'读取{0},共加载{1}条数据,耗时:{2}seconds'.format(file_name, len(ticks), str(datetime.now() - start_time)))
|
||||
|
||||
return ticks
|
||||
|
||||
import re
|
||||
|
||||
def import_ticks_from_folder(folder_path):
|
||||
branch_time = datetime.now()
|
||||
for dirpath, folder_names, file_names in os.walk(folder_path):
|
||||
for file_name in file_names:
|
||||
file_path = os.path.join(dirpath, file_name)
|
||||
start_time = datetime.now()
|
||||
# 处理csb格式
|
||||
if file_name.lower().find('.csv') != -1:
|
||||
s = file_name.replace('.csv', '').split('_')
|
||||
if len(s) != 2:
|
||||
print( u'{0} not match format'.format(file_path))
|
||||
continue
|
||||
|
||||
file_symbol = s[0]
|
||||
file_trading_day = s[1]
|
||||
# print('{0} {1}'.format(file_symbol,file_trading_day))
|
||||
if len(file_trading_day) != 8:
|
||||
print( u'{0} trading_day not match format'.format(file_path))
|
||||
continue
|
||||
try:
|
||||
ticks = load_ticks_from_csv_file(file_name=file_path, symbol=file_symbol, trading_day=file_trading_day)
|
||||
|
||||
insert_list = [x.__dict__ for x in ticks.values()]
|
||||
mc.dbInsert(dbName='ticks', collectionName=file_symbol, d=insert_list)
|
||||
print( u'写入完成,共{0}条,耗时:{1}seconds'.format(len(insert_list), str(datetime.now() - start_time)))
|
||||
except Exception as ex:
|
||||
print( u'{0} load ticks and insert exception'.format(file_path))
|
||||
continue
|
||||
|
||||
elif file_name.lower().find('.txt') != -1:
|
||||
|
||||
symbol_name = file_name.replace('.txt', '')
|
||||
if symbol_name.lower().find('survey') != -1:
|
||||
print( '{0} not import'.format(file_name))
|
||||
continue
|
||||
p = re.compile(r"([A-Z]+)[0-9]+", re.I)
|
||||
short_symbol = p.match(symbol_name)
|
||||
if short_symbol is None:
|
||||
print( '{0} not import'.format(file_name))
|
||||
continue
|
||||
short_symbol = short_symbol.group(1)
|
||||
collection_name = short_symbol + symbol_name[-2:]
|
||||
path_list = dirpath.split('/')
|
||||
if path_list[-2] != short_symbol:
|
||||
print( '{0} not import'.format(file_name))
|
||||
continue
|
||||
|
||||
trading_day = path_list[-4] + path_list[-1]
|
||||
|
||||
#print collection_name, trading_day
|
||||
try:
|
||||
ticks = load_ticks_from_txt_file(file_name=file_path, symbol=symbol_name, trading_day=trading_day)
|
||||
insert_list = [x.__dict__ for x in ticks.values()]
|
||||
mc.dbInsert(dbName='ticks', collectionName=collection_name, d=insert_list)
|
||||
print( u'写入完成,共{0}条,耗时:{1}seconds'.format(len(insert_list), str(datetime.now() - start_time)))
|
||||
except Exception as ex:
|
||||
print( u'{0} load ticks and insert exception'.format(file_path))
|
||||
continue
|
||||
print( '完成 {0} ticks ,耗时:{1}seconds'.format(folder_path, str(datetime.now() - branch_time)))
|
||||
|
||||
|
||||
mc=mongodb_client()
|
||||
mc.dbConnect()
|
||||
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201612')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201611')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201610')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201609')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201608')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201607')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201606')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201605')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201604')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201603')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201602')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2016/201601')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2015')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2014')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2013')
|
||||
#import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2012')
|
||||
import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2011')
|
||||
import_ticks_from_folder('/home/ubuntu/Ticks/ZZ/2010')
|
@ -1,7 +1,7 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
from rmEngine import RmEngine
|
||||
from uiRmWidget import RmEngineManager
|
||||
from vnpy.trader.app.riskManager.rmEngine import RmEngine
|
||||
from vnpy.trader.app.riskManager.uiRmWidget import RmEngineManager
|
||||
|
||||
appName = 'RiskManager'
|
||||
appDisplayName = u'风险管理'
|
||||
|
4
vnpy/trader/app/rpcService/RS_setting.json
Normal file
4
vnpy/trader/app/rpcService/RS_setting.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"repAddress": "tcp://*:2014",
|
||||
"pubAddress": "tcp://*:0602"
|
||||
}
|
10
vnpy/trader/app/rpcService/__init__.py
Normal file
10
vnpy/trader/app/rpcService/__init__.py
Normal file
@ -0,0 +1,10 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
from .rsEngine import RsEngine
|
||||
from .uiRsWidget import RsEngineManager
|
||||
|
||||
appName = 'RpcService'
|
||||
appDisplayName = u'RPC服务'
|
||||
appEngine = RsEngine
|
||||
appWidget = RsEngineManager
|
||||
appIco = 'rs.ico'
|
107
vnpy/trader/app/rpcService/rsClient.py
Normal file
107
vnpy/trader/app/rpcService/rsClient.py
Normal file
@ -0,0 +1,107 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
import copy
|
||||
|
||||
from vnpy.rpc import RpcClient
|
||||
|
||||
|
||||
########################################################################
|
||||
class ObjectProxy(object):
|
||||
"""对象代理"""
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __init__(self, nameList, client):
|
||||
"""Constructor"""
|
||||
self.nameList = nameList # 属性名称关系列表
|
||||
self.client = client # RPC客户端
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __getattr__(self, name):
|
||||
"""获取某个不存在的属性"""
|
||||
# 生成属性层级列表
|
||||
newNameList = copy.copy(self.nameList)
|
||||
newNameList.append(name)
|
||||
|
||||
# 创建代理对象
|
||||
proxy = ObjectProxy(newNameList, self.client)
|
||||
|
||||
# 缓存代理对象
|
||||
self.__dict__[name] = proxy
|
||||
|
||||
# 返回
|
||||
return proxy
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __call__(self, *args, **kwargs):
|
||||
"""被当做函数调用时"""
|
||||
d = {}
|
||||
d['nameList'] = self.nameList
|
||||
d['args'] = args
|
||||
d['kwargs'] = kwargs
|
||||
return self.client.call(d)
|
||||
|
||||
|
||||
########################################################################
|
||||
class RsClient(RpcClient):
|
||||
"""RPC服务客户端"""
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __init__(self, reqAddress, subAddress):
|
||||
"""Constructor"""
|
||||
super(RsClient, self).__init__(reqAddress, subAddress)
|
||||
|
||||
self.eventEngine = None
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def callback(self, topic, data):
|
||||
"""事件推送回调函数"""
|
||||
self.eventEngine.put(data) # 直接放入事件引擎中
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def init(self, eventEngine):
|
||||
"""初始化"""
|
||||
self.eventEngine = eventEngine # 绑定事件引擎对象
|
||||
|
||||
self.usePickle() # 使用cPickle序列化
|
||||
self.subscribeTopic('') # 订阅全部主题推送
|
||||
self.start() # 启动
|
||||
|
||||
|
||||
########################################################################
|
||||
class MainEngineProxy(object):
|
||||
"""主引擎代理"""
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __init__(self, eventEngine):
|
||||
"""Constructor"""
|
||||
self.eventEngine = eventEngine
|
||||
self.eventEngine.start(timer=False) # 客户端不启动定时器
|
||||
|
||||
self.client = None
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def init(self, reqAddress, subAddress):
|
||||
"""初始化"""
|
||||
self.client = RsClient(reqAddress, subAddress)
|
||||
self.client.init(self.eventEngine)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __getattr__(self, name):
|
||||
"""获取未知属性"""
|
||||
# 生成属性名称层级列表
|
||||
nameList = [name]
|
||||
|
||||
# 生成属性代理对象
|
||||
proxy = ObjectProxy(nameList, self.client)
|
||||
|
||||
# 缓存属性代理对象,使得后续调用无需新建
|
||||
self.__dict__[name] = proxy
|
||||
|
||||
# 返回属性代理
|
||||
return proxy
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def getApp(self, name):
|
||||
"""获取应用引擎对象"""
|
||||
return self.__getattr__(name)
|
||||
|
93
vnpy/trader/app/rpcService/rsEngine.py
Normal file
93
vnpy/trader/app/rpcService/rsEngine.py
Normal file
@ -0,0 +1,93 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
import json
|
||||
|
||||
from vnpy.trader.vtConstant import EMPTY_STRING
|
||||
|
||||
from vnpy.rpc import RpcServer
|
||||
from vnpy.trader.vtFunction import getJsonPath
|
||||
|
||||
|
||||
########################################################################
|
||||
class RsEngine(object):
|
||||
"""RPC服务引擎"""
|
||||
|
||||
settingFileName = 'RS_setting.json'
|
||||
settingFilePath = getJsonPath(settingFileName, __file__)
|
||||
|
||||
name = u'RPC服务'
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __init__(self, mainEngine, eventEngine):
|
||||
"""Constructor"""
|
||||
self.mainEngine = mainEngine
|
||||
self.eventEngine = eventEngine
|
||||
|
||||
self.server = None # RPC服务对象
|
||||
self.repAddress = EMPTY_STRING # REP地址
|
||||
self.pubAddress = EMPTY_STRING # PUB地址
|
||||
|
||||
self.functionDict = {} # 调用过的函数对象缓存字典
|
||||
|
||||
self.loadSetting()
|
||||
self.registerEvent()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def loadSetting(self):
|
||||
"""读取配置"""
|
||||
with open(self.settingFilePath) as f:
|
||||
d = json.load(f)
|
||||
|
||||
self.repAddress = d['repAddress']
|
||||
self.pubAddress = d['pubAddress']
|
||||
|
||||
self.server = RpcServer(self.repAddress, self.pubAddress)
|
||||
self.server.usePickle()
|
||||
self.server.register(self.call)
|
||||
self.server.start()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def registerEvent(self):
|
||||
"""注册事件监听"""
|
||||
self.eventEngine.registerGeneralHandler(self.processEvent)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def call(self, d):
|
||||
"""调用函数"""
|
||||
nameList = d['nameList'] # 对象属性列表
|
||||
nameTuple = tuple(nameList) # 转化为元组
|
||||
args = d['args'] # 调用参数
|
||||
kwargs = d['kwargs']
|
||||
|
||||
# 如果已经有缓存,则直接调用
|
||||
if nameTuple in self.functionDict:
|
||||
function = self.functionDict[nameTuple]
|
||||
result = function(*args, **kwargs)
|
||||
return result
|
||||
# 逐层寻找函数对象
|
||||
else:
|
||||
# 根对象为主引擎
|
||||
obj = self.mainEngine
|
||||
|
||||
# 逐层寻找对象属性
|
||||
for name in nameTuple:
|
||||
obj = obj.__getattribute__(name)
|
||||
|
||||
# 缓存结果
|
||||
self.functionDict[nameTuple] = obj
|
||||
|
||||
# 调用最终对象
|
||||
result = obj(*args, **kwargs)
|
||||
return result
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def processEvent(self, event):
|
||||
"""处理事件推送"""
|
||||
self.server.publish('', event)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def stop(self):
|
||||
"""停止"""
|
||||
self.server.stop()
|
||||
|
||||
|
30
vnpy/trader/app/rpcService/uiRsWidget.py
Normal file
30
vnpy/trader/app/rpcService/uiRsWidget.py
Normal file
@ -0,0 +1,30 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
from vnpy.trader.uiQt import QtWidgets
|
||||
|
||||
|
||||
########################################################################
|
||||
class RsEngineManager(QtWidgets.QWidget):
|
||||
"""RPC服务组件管理"""
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __init__(self, rsEngine, eventEngine, parent=None):
|
||||
"""Constructor"""
|
||||
super(RsEngineManager, self).__init__(parent)
|
||||
|
||||
self.initUi()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def initUi(self):
|
||||
"""初始化界面"""
|
||||
self.setWindowTitle(u'RPC服务')
|
||||
|
||||
label = QtWidgets.QLabel(u'该模块运行于服务端')
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.addWidget(label)
|
||||
self.setLayout(vbox)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -284,7 +284,7 @@ class StModeComboBox(QtWidgets.QComboBox):
|
||||
#----------------------------------------------------------------------
|
||||
def setMode(self):
|
||||
"""设置模式"""
|
||||
mode = unicode(self.currentText())
|
||||
mode = self.currentText()
|
||||
self.algoEngine.setAlgoMode(self.spreadName, mode)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
@ -6,7 +6,6 @@ import sys
|
||||
import ctypes
|
||||
from datetime import datetime, timedelta, date
|
||||
from time import sleep
|
||||
from threading import Thread
|
||||
|
||||
# 将repostory的目录i,作为根目录,添加到系统环境中。
|
||||
ROOT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..','..'))
|
||||
@ -48,7 +47,7 @@ class NoUiMain(object):
|
||||
ee = EventEngine2()
|
||||
|
||||
# 实例化 主引擎
|
||||
print u'instance mainengine'
|
||||
print(u'instance mainengine')
|
||||
self.mainEngine = MainEngine(ee)
|
||||
|
||||
self.mainEngine.addGateway(ctpGateway, self.gateway_name)
|
||||
@ -58,7 +57,6 @@ class NoUiMain(object):
|
||||
self.mainEngine.addApp(riskManager)
|
||||
|
||||
|
||||
|
||||
def trade_off(self):
|
||||
"""检查现在是否为非交易时间"""
|
||||
now = datetime.now()
|
||||
@ -87,7 +85,7 @@ class NoUiMain(object):
|
||||
dt = datetime.now()
|
||||
if dt.hour != self.last_dt.hour:
|
||||
self.last_dt = dt
|
||||
print u'noUiMain.py checkpoint:{0}'.format(dt)
|
||||
print(u'noUiMain.py checkpoint:{0}'.format(dt))
|
||||
self.mainEngine.writeLog( u'noUiMain.py checkpoint:{0}'.format(dt))
|
||||
|
||||
# 定时断开
|
||||
@ -131,20 +129,20 @@ class NoUiMain(object):
|
||||
#self.mainEngine.dbConnect()
|
||||
|
||||
# 加载cta的配置
|
||||
print u'load cta setting'
|
||||
print(u'load cta setting')
|
||||
self.mainEngine.ctaEngine.loadSetting()
|
||||
|
||||
print u'initialize all strategies'
|
||||
print(u'initialize all strategies')
|
||||
# 初始化策略,如果多个,则需要逐一初始化多个
|
||||
for s in self.strategies:
|
||||
print 'init trategy {0}'.format(s)
|
||||
print( 'init trategy {0}'.format(s))
|
||||
self.mainEngine.ctaEngine.initStrategy(s)
|
||||
# 逐一启动策略
|
||||
print 'start strategy {0}'.format(s)
|
||||
print( 'start strategy {0}'.format(s))
|
||||
self.mainEngine.ctaEngine.startStrategy(s)
|
||||
|
||||
# 指定的连接配置
|
||||
print u'connect gateway:{0}'.format(self.gateway_name)
|
||||
print( u'connect gateway:{0}'.format(self.gateway_name))
|
||||
self.mainEngine.connect(self.gateway_name)
|
||||
self.connected = True
|
||||
|
||||
@ -165,7 +163,7 @@ def run_noui():
|
||||
log_file_name = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
'logs', u'noUiMain.log'))
|
||||
except Exception as ex:
|
||||
print u'Use local dict:{0}'.format(os.getcwd())
|
||||
print( u'Use local dict:{0}'.format(os.getcwd()))
|
||||
log_file_name = os.path.abspath(os.path.join(os.getcwd(), 'logs', u'noUiMain.log'))
|
||||
|
||||
setup_logger(filename=log_file_name, debug=False)
|
||||
|
@ -35,14 +35,14 @@ def _check_gpid(gpid):
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
|
||||
returncode = p.wait()
|
||||
except OSError as e:
|
||||
print 'cant not find shell command ps'
|
||||
print('cant not find shell command ps')
|
||||
exit(1)
|
||||
try:
|
||||
p2 = subprocess.Popen("uniq", stdin=p.stdout, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=False)
|
||||
returncode = p2.wait()
|
||||
except OSError as e:
|
||||
print 'cant not find shell command uniq'
|
||||
print( 'cant not find shell command uniq')
|
||||
exit(1)
|
||||
for i in p2.stdout.readlines():
|
||||
if i.decode().strip() == gpid:
|
||||
@ -115,47 +115,47 @@ def _start():
|
||||
gpid = _status()
|
||||
if _check_stop_time():
|
||||
if gpid:
|
||||
print 'it is not in valid time span, will kill the service[gpid={}]'.format(gpid)
|
||||
print('it is not in valid time span, will kill the service[gpid={}]'.format(gpid))
|
||||
import signal
|
||||
# 杀死进程组
|
||||
os.killpg(int(gpid), signal.SIGKILL)
|
||||
while _status():
|
||||
time.sleep(1)
|
||||
print 'already stop the service[gpid={}]'.format(gpid)
|
||||
print( 'already stop the service[gpid={}]'.format(gpid))
|
||||
try:
|
||||
sendmail.sendmail(subject='{0} killed by service.py'.format(ctp_gateway_name),
|
||||
msgcontent='already stop the service[gpid={}]'.format(gpid))
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
print 'it is not in valid time span, can not start the service'
|
||||
print( 'it is not in valid time span, can not start the service')
|
||||
else:
|
||||
if not gpid:
|
||||
print 'it is in valid time span, will start the service'
|
||||
print( 'it is in valid time span, will start the service')
|
||||
os.popen(program_command)
|
||||
while True:
|
||||
gpid = _status()
|
||||
if gpid:
|
||||
break
|
||||
time.sleep(1)
|
||||
print 'already start the service[gpid={}]'.format(gpid)
|
||||
print( 'already start the service[gpid={}]'.format(gpid))
|
||||
else:
|
||||
print 'it is in valid time span, the service is running...'
|
||||
print( 'it is in valid time span, the service is running...')
|
||||
|
||||
|
||||
def schedule():
|
||||
print '======schedule========'
|
||||
print( '======schedule========')
|
||||
_start()
|
||||
|
||||
|
||||
def status():
|
||||
print '======status========'
|
||||
print( '======status========')
|
||||
|
||||
gpid = _status()
|
||||
if gpid:
|
||||
print 'the service[gpid={}] is running...'.format(gpid)
|
||||
print( 'the service[gpid={}] is running...'.format(gpid))
|
||||
else:
|
||||
print 'the service is not running...'
|
||||
print( 'the service is not running...')
|
||||
|
||||
# operate的可选字符串为:add, del
|
||||
def operate_crontab(operate):
|
||||
@ -178,7 +178,7 @@ def operate_crontab(operate):
|
||||
|
||||
# 追加方式比上面好,能自动判断上行是否有回车
|
||||
os.popen('echo "{}" >> {}'.format(cron_content, tmp_cron_file))
|
||||
print ' add new crontab item: {}'.format(cron_content)
|
||||
print( ' add new crontab item: {}'.format(cron_content))
|
||||
os.popen("crontab {}".format(tmp_cron_file))
|
||||
|
||||
if operate == "del" and exist_flag:
|
||||
@ -186,16 +186,16 @@ def operate_crontab(operate):
|
||||
f.writelines(remain_cron_list)
|
||||
|
||||
os.popen("crontab {}".format(tmp_cron_file))
|
||||
print 'del old crontab item: {}'.format(old_cron_content)
|
||||
print( 'del old crontab item: {}'.format(old_cron_content))
|
||||
|
||||
# os.remove(tmp_cron_file)
|
||||
|
||||
|
||||
def start():
|
||||
print '======start========'
|
||||
print( '======start========')
|
||||
operate_crontab("add")
|
||||
_start()
|
||||
print 'start service done!!!'
|
||||
print( 'start service done!!!')
|
||||
|
||||
|
||||
def _stop():
|
||||
@ -207,26 +207,26 @@ def _stop():
|
||||
os.killpg(int(gpid), signal.SIGKILL)
|
||||
while _status():
|
||||
time.sleep(1)
|
||||
print 'already stop the service[gpid={}]'.format(gpid)
|
||||
print( 'already stop the service[gpid={}]'.format(gpid))
|
||||
try:
|
||||
sendmail.sendmail(subject='{0} stopped by service.py'.format(ctp_gateway_name),msgcontent= 'already stop the service[gpid={}]'.format(gpid))
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
print 'the service is not running...'
|
||||
print( 'the service is not running...')
|
||||
|
||||
|
||||
def stop():
|
||||
print '======stop========'
|
||||
print('======stop========')
|
||||
_stop()
|
||||
print 'stop service done!!!'
|
||||
print( 'stop service done!!!')
|
||||
|
||||
|
||||
def restart():
|
||||
print '======restart========'
|
||||
print( '======restart========')
|
||||
_stop()
|
||||
_start()
|
||||
print 'restart service done!!!'
|
||||
print('restart service done!!!')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@ -245,4 +245,4 @@ if __name__ == '__main__':
|
||||
elif fun == 'schedule':
|
||||
schedule()
|
||||
else:
|
||||
print 'Usage: {} (status|start|stop|restart)'.format(os.path.basename(__file__))
|
||||
print( 'Usage: {} (status|start|stop|restart)'.format(os.path.basename(__file__)))
|
||||
|
@ -252,8 +252,8 @@ class MultiprocessHandler(logging.FileHandler):
|
||||
if not os.path.exists(_dir):
|
||||
os.makedirs(_dir)
|
||||
except Exception:
|
||||
print u"创建文件夹失败"
|
||||
print u"文件夹路径:" + self.filePath
|
||||
print( u"创建文件夹失败")
|
||||
print( u"文件夹路径:" + self.filePath)
|
||||
pass
|
||||
|
||||
if codecs is None:
|
||||
@ -299,9 +299,9 @@ class MultiprocessHandler(logging.FileHandler):
|
||||
self.stream = self._open()
|
||||
#删除多于保留个数的所有日志文件
|
||||
if self.backupCount > 0:
|
||||
print '删除日志'
|
||||
print('删除日志')
|
||||
for s in self.getFilesToDelete():
|
||||
print s
|
||||
print(s)
|
||||
os.remove(s)
|
||||
|
||||
def getFilesToDelete(self):
|
||||
@ -371,12 +371,12 @@ def setup_logger(filename, name=None, debug=False):
|
||||
name = names[-1]
|
||||
|
||||
_logger = logging.getLogger(name)
|
||||
#logger.setLevel(logging.DEBUG)
|
||||
#stream_handler = logging.StreamHandler(sys.stdout)
|
||||
#stream_handler.setLevel(logging.DEBUG)
|
||||
#stream_handler.setFormatter(fmt)
|
||||
|
||||
#_logger = multiprocessing.get_logger()
|
||||
if debug:
|
||||
_logger.setLevel(logging.DEBUG)
|
||||
stream_handler = logging.StreamHandler(sys.stdout)
|
||||
stream_handler.setLevel(logging.DEBUG)
|
||||
stream_handler.setFormatter(fmt)
|
||||
_logger.addHandler(stream_handler)
|
||||
|
||||
_fileHandler = MultiprocessHandler(filename, when='D')
|
||||
if debug:
|
||||
@ -384,7 +384,7 @@ def setup_logger(filename, name=None, debug=False):
|
||||
else:
|
||||
_fileHandler.setLevel(logging.INFO)
|
||||
_fileHandler.setFormatter(fmt)
|
||||
#_logger.addHandler(stream_handler)
|
||||
|
||||
_logger.addHandler(_fileHandler)
|
||||
|
||||
if debug:
|
||||
|
@ -5,11 +5,12 @@ import csv
|
||||
import os
|
||||
import platform
|
||||
from collections import OrderedDict
|
||||
import traceback
|
||||
|
||||
from vnpy.trader.vtEvent import *
|
||||
from vnpy.trader.vtFunction import *
|
||||
from vnpy.trader.vtGateway import *
|
||||
import vtText
|
||||
from vnpy.trader.vtText import text as vtText
|
||||
from vnpy.trader.uiQt import QtWidgets, QtGui, QtCore, BASIC_FONT
|
||||
|
||||
if str(platform.system()) == 'Windows':
|
||||
@ -35,8 +36,10 @@ class BasicCell(QtWidgets.QTableWidgetItem):
|
||||
"""设置内容"""
|
||||
if text == '0' or text == '0.0' or type(text) == type(None):
|
||||
self.setText('')
|
||||
#elif type(text) == type(float):
|
||||
# self.setText(str(text))
|
||||
else:
|
||||
self.setText(text)
|
||||
self.setText(str(text))
|
||||
|
||||
|
||||
########################################################################
|
||||
@ -131,7 +134,7 @@ class BidCell(QtWidgets.QTableWidgetItem):
|
||||
#----------------------------------------------------------------------
|
||||
def setContent(self, text):
|
||||
"""设置内容"""
|
||||
self.setText(text)
|
||||
self.setText(str(text))
|
||||
|
||||
|
||||
########################################################################
|
||||
@ -153,7 +156,7 @@ class AskCell(QtWidgets.QTableWidgetItem):
|
||||
#----------------------------------------------------------------------
|
||||
def setContent(self, text):
|
||||
"""设置内容"""
|
||||
self.setText(text)
|
||||
self.setText(str(text))
|
||||
|
||||
########################################################################
|
||||
class PnlCell(QtWidgets.QTableWidgetItem):
|
||||
@ -283,10 +286,14 @@ class BasicMonitor(QtWidgets.QTableWidget):
|
||||
#----------------------------------------------------------------------
|
||||
def updateEvent(self, event):
|
||||
"""收到事件更新"""
|
||||
data = event.dict_['data']
|
||||
self.updateData(data)
|
||||
try:
|
||||
data = event.dict_['data']
|
||||
self.updateData(data)
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
traceback.print_exc()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def updateData(self, data):
|
||||
"""将数据更新到表格中"""
|
||||
# 如果允许了排序功能,则插入数据前必须关闭,否则插入新的数据会变乱
|
||||
@ -376,11 +383,11 @@ class BasicMonitor(QtWidgets.QTableWidget):
|
||||
|
||||
try:
|
||||
if not os.path.exists(path):
|
||||
with open(unicode(path), 'wb') as f:
|
||||
with open(path, 'wb') as f:
|
||||
writer = csv.writer(f)
|
||||
|
||||
# 保存标签
|
||||
headers = [header.encode('gbk') for header in self.headerList]
|
||||
headers = [header for header in self.headerList]
|
||||
writer.writerow(headers)
|
||||
|
||||
# 保存每行内容
|
||||
@ -389,8 +396,7 @@ class BasicMonitor(QtWidgets.QTableWidget):
|
||||
for column in range(self.columnCount()):
|
||||
item = self.item(row, column)
|
||||
if item is not None:
|
||||
rowdata.append(
|
||||
unicode(item.text()).encode('gbk'))
|
||||
rowdata.append(item.text())
|
||||
else:
|
||||
rowdata.append('')
|
||||
writer.writerow(rowdata)
|
||||
@ -940,10 +946,10 @@ class TradingWidget(QtWidgets.QFrame):
|
||||
"""合约变化"""
|
||||
# 读取组件数据
|
||||
symbol = str(self.lineSymbol.text())
|
||||
exchange = unicode(self.comboExchange.currentText())
|
||||
currency = unicode(self.comboCurrency.currentText())
|
||||
productClass = unicode(self.comboProductClass.currentText())
|
||||
gatewayName = unicode(self.comboGateway.currentText())
|
||||
exchange = self.comboExchange.currentText()
|
||||
currency = self.comboCurrency.currentText()
|
||||
productClass = self.comboProductClass.currentText()
|
||||
gatewayName = self.comboGateway.currentText()
|
||||
|
||||
# 查询合约
|
||||
if exchange:
|
||||
@ -1014,33 +1020,33 @@ class TradingWidget(QtWidgets.QFrame):
|
||||
if tick.vtSymbol == self.symbol:
|
||||
if not self.checkFixed.isChecked():
|
||||
self.spinPrice.setValue(tick.lastPrice)
|
||||
self.labelBidPrice1.setText(str(tick.bidPrice1))
|
||||
self.labelAskPrice1.setText(str(tick.askPrice1))
|
||||
self.labelBidVolume1.setText(str(tick.bidVolume1))
|
||||
self.labelAskVolume1.setText(str(tick.askVolume1))
|
||||
self.labelBidPrice1.setText('{}'.format(tick.bidPrice1))
|
||||
self.labelAskPrice1.setText('{}'.format(tick.askPrice1))
|
||||
self.labelBidVolume1.setText('{}'.format(tick.bidVolume1))
|
||||
self.labelAskVolume1.setText('{}'.format(tick.askVolume1))
|
||||
|
||||
if tick.bidPrice2:
|
||||
self.labelBidPrice2.setText(str(tick.bidPrice2))
|
||||
self.labelBidPrice3.setText(str(tick.bidPrice3))
|
||||
self.labelBidPrice4.setText(str(tick.bidPrice4))
|
||||
self.labelBidPrice5.setText(str(tick.bidPrice5))
|
||||
self.labelBidPrice2.setText('{}'.format(tick.bidPrice2))
|
||||
self.labelBidPrice3.setText('{}'.format(tick.bidPrice3))
|
||||
self.labelBidPrice4.setText('{}'.format(tick.bidPrice4))
|
||||
self.labelBidPrice5.setText('{}'.format(tick.bidPrice5))
|
||||
|
||||
self.labelAskPrice2.setText(str(tick.askPrice2))
|
||||
self.labelAskPrice3.setText(str(tick.askPrice3))
|
||||
self.labelAskPrice4.setText(str(tick.askPrice4))
|
||||
self.labelAskPrice5.setText(str(tick.askPrice5))
|
||||
self.labelAskPrice2.setText('{}'.format(tick.askPrice2))
|
||||
self.labelAskPrice3.setText('{}'.format(tick.askPrice3))
|
||||
self.labelAskPrice4.setText('{}'.format(tick.askPrice4))
|
||||
self.labelAskPrice5.setText('{}'.format(tick.askPrice5))
|
||||
|
||||
self.labelBidVolume2.setText(str(tick.bidVolume2))
|
||||
self.labelBidVolume3.setText(str(tick.bidVolume3))
|
||||
self.labelBidVolume4.setText(str(tick.bidVolume4))
|
||||
self.labelBidVolume5.setText(str(tick.bidVolume5))
|
||||
self.labelBidVolume2.setText('{}'.format(tick.bidVolume2))
|
||||
self.labelBidVolume3.setText('{}'.format(tick.bidVolume3))
|
||||
self.labelBidVolume4.setText('{}'.format(tick.bidVolume4))
|
||||
self.labelBidVolume5.setText('{}'.format(tick.bidVolume5))
|
||||
|
||||
self.labelAskVolume2.setText(str(tick.askVolume2))
|
||||
self.labelAskVolume3.setText(str(tick.askVolume3))
|
||||
self.labelAskVolume4.setText(str(tick.askVolume4))
|
||||
self.labelAskVolume5.setText(str(tick.askVolume5))
|
||||
self.labelAskVolume2.setText('{}'.format(tick.askVolume2))
|
||||
self.labelAskVolume3.setText('{}'.format(tick.askVolume3))
|
||||
self.labelAskVolume4.setText('{}'.format(tick.askVolume4))
|
||||
self.labelAskVolume5.setText('{}'.format(tick.askVolume5))
|
||||
|
||||
self.labelLastPrice.setText(str(tick.lastPrice))
|
||||
self.labelLastPrice.setText('{}'.format(tick.lastPrice))
|
||||
|
||||
if tick.preClosePrice:
|
||||
rt = (tick.lastPrice/tick.preClosePrice)-1
|
||||
@ -1057,10 +1063,10 @@ class TradingWidget(QtWidgets.QFrame):
|
||||
def sendOrder(self):
|
||||
"""发单"""
|
||||
symbol = str(self.lineSymbol.text())
|
||||
exchange = unicode(self.comboExchange.currentText())
|
||||
currency = unicode(self.comboCurrency.currentText())
|
||||
productClass = unicode(self.comboProductClass.currentText())
|
||||
gatewayName = unicode(self.comboGateway.currentText())
|
||||
exchange = self.comboExchange.currentText()
|
||||
currency = self.comboCurrency.currentText()
|
||||
productClass = self.comboProductClass.currentText()
|
||||
gatewayName = self.comboGateway.currentText()
|
||||
|
||||
# 查询合约
|
||||
if exchange:
|
||||
@ -1080,9 +1086,9 @@ class TradingWidget(QtWidgets.QFrame):
|
||||
req.exchange = exchange
|
||||
req.price = self.spinPrice.value()
|
||||
req.volume = self.spinVolume.value()
|
||||
req.direction = unicode(self.comboDirection.currentText())
|
||||
req.priceType = unicode(self.comboPriceType.currentText())
|
||||
req.offset = unicode(self.comboOffset.currentText())
|
||||
req.direction = self.comboDirection.currentText()
|
||||
req.priceType = self.comboPriceType.currentText()
|
||||
req.offset = self.comboOffset.currentText()
|
||||
req.currency = currency
|
||||
req.productClass = productClass
|
||||
|
||||
@ -1353,12 +1359,12 @@ class SettingEditor(QtWidgets.QWidget):
|
||||
filePath = jsonPathDict[self.currentFileName]
|
||||
self.labelPath.setText(filePath)
|
||||
|
||||
with open(filePath) as f:
|
||||
with open(filePath,'rb',encoding='utf8') as f:
|
||||
self.editSetting.clear()
|
||||
|
||||
for line in f:
|
||||
line = line.replace('\n', '') # 移除换行符号
|
||||
line = line.decode('UTF-8')
|
||||
#line = line.decode('UTF-8')
|
||||
self.editSetting.append(line)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@ -1369,9 +1375,9 @@ class SettingEditor(QtWidgets.QWidget):
|
||||
|
||||
filePath = jsonPathDict[self.currentFileName]
|
||||
|
||||
with open(filePath, 'w') as f:
|
||||
with open(filePath, 'wb', encoding='utf8') as f:
|
||||
content = self.editSetting.toPlainText()
|
||||
content = content.encode('UTF-8')
|
||||
#content = content.encode('UTF-8')
|
||||
f.write(content)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
@ -3,7 +3,7 @@ import sys
|
||||
|
||||
# from uiFullMonitorWidget import MonitorWidget
|
||||
# from uiKChartWidget import CandleForm
|
||||
print 'load uiMainWindows.py'
|
||||
print('load uiMainWindows.py')
|
||||
import psutil
|
||||
import traceback
|
||||
|
||||
@ -293,7 +293,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
try:
|
||||
r = self.mainEngine.connect(gatewayName)
|
||||
except:
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print( "Unexpected error:", sys.exc_info()[0])
|
||||
traceback.print_exc()
|
||||
|
||||
if r:
|
||||
@ -334,7 +334,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.widgetDict[appName] = appDetail['appWidget'](appEngine, self.eventEngine)
|
||||
self.widgetDict[appName].show()
|
||||
except:
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print( "Unexpected error:", sys.exc_info()[0])
|
||||
traceback.print_exc()
|
||||
|
||||
return openAppFunction
|
||||
@ -365,7 +365,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.widgetDict['contractM'] = ContractMonitor(self.mainEngine)
|
||||
self.widgetDict['contractM'].show()
|
||||
except :
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print( "Unexpected error:", sys.exc_info()[0])
|
||||
traceback.print_exc()
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@ -378,7 +378,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.widgetDict['settingEditor'] = SettingEditor(self.mainEngine)
|
||||
self.widgetDict['settingEditor'].show()
|
||||
except :
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print( "Unexpected error:", sys.exc_info()[0])
|
||||
traceback.print_exc()
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@ -390,14 +390,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
try:
|
||||
if self.mainEngine.ctaEngine is None:
|
||||
print u'not init Cta Engine'
|
||||
print( u'not init Cta Engine')
|
||||
return
|
||||
|
||||
from vnpy.trader.app.ctaStrategy.uiSpreadTrade import SpreadTradeManager
|
||||
self.widgetDict['spread'] = SpreadTradeManager(self.mainEngine.ctaEngine, self.eventEngine)
|
||||
self.widgetDict['spread'].show()
|
||||
except Exception as ex:
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print( "Unexpected error:", sys.exc_info()[0])
|
||||
traceback.print_exc()
|
||||
return
|
||||
|
||||
|
@ -27,7 +27,7 @@ def createQApp():
|
||||
import qdarkstyle
|
||||
qApp.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
|
||||
except :
|
||||
print "Unexpected error when import darkStyle:", sys.exc_info()[0]
|
||||
print( "Unexpected error when import darkStyle:", sys.exc_info()[0])
|
||||
|
||||
# 设置Windows底部任务栏图标
|
||||
if 'Windows' in platform.uname():
|
||||
|
@ -21,14 +21,14 @@ def _check_gpid(gpid):
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
|
||||
returncode = p.wait()
|
||||
except OSError as e:
|
||||
print u'can not find shell command ps'
|
||||
print( u'can not find shell command ps')
|
||||
exit(1)
|
||||
try:
|
||||
p2 = subprocess.Popen("uniq", stdin=p.stdout, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=False)
|
||||
returncode = p2.wait()
|
||||
except OSError as e:
|
||||
print u'can not find shell command uniq'
|
||||
print(u'can not find shell command uniq')
|
||||
exit(1)
|
||||
for i in p2.stdout.readlines():
|
||||
if i.decode().strip() == gpid:
|
||||
@ -46,7 +46,7 @@ def _status():
|
||||
return None
|
||||
|
||||
if _status():
|
||||
print u'another service is already running...'
|
||||
print( u'another service is already running...')
|
||||
exit(0)
|
||||
|
||||
def _save_gpid():
|
||||
@ -56,7 +56,7 @@ def _save_gpid():
|
||||
gpid = os.getpid()
|
||||
else: # unix
|
||||
gpid = os.getpgrp()
|
||||
print 'gpid={}'.format(gpid)
|
||||
print( 'gpid={}'.format(gpid))
|
||||
|
||||
with open(gpid_file, 'w') as f:
|
||||
f.write(str(gpid))
|
||||
|
@ -72,18 +72,18 @@ class BasicMonitor(object):
|
||||
s = []
|
||||
for header, value in self.headerDict.items():
|
||||
v = getattr(data, header)
|
||||
if isinstance(v, basestring) and not isinstance(v, unicode):
|
||||
try:
|
||||
v = v.decode('gbk')
|
||||
except:
|
||||
v = v.decode('utf8')
|
||||
#if isinstance(v, basestring) and not isinstance(v, unicode):
|
||||
# try:
|
||||
# v = v.decode('gbk')
|
||||
# except:
|
||||
# v = v.decode('utf8')
|
||||
s.append('%s: %s' % (value['chinese'], v))
|
||||
if self.logger is not None:
|
||||
self.logger.info(' '.join(s))
|
||||
|
||||
def createLogger(self, monitor_name):
|
||||
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), 'logs', monitor_name))
|
||||
print u'create logger:{}'.format(filename)
|
||||
print( u'create logger:{}'.format(filename))
|
||||
self.logger = setup_logger(filename=filename, name=monitor_name)
|
||||
|
||||
########################################################################
|
||||
|
@ -1,6 +1,6 @@
|
||||
# encoding: utf-8
|
||||
|
||||
print 'load vtClient.py'
|
||||
print('load vtClient.py')
|
||||
import ctypes
|
||||
import platform
|
||||
import sys
|
||||
@ -9,7 +9,7 @@ from vnpy.rpc import RpcClient
|
||||
from vnpy.trader.app.ctaStrategy.ctaEngine import CtaEngine
|
||||
from vnpy.trader.app.dataRecorder.drEngine import DrEngine
|
||||
from vnpy.trader.app.riskManager.rmEngine import RmEngine
|
||||
from uiMainWindow import *
|
||||
from vnpy.trader.uiMainWindow import *
|
||||
|
||||
# 文件路径名
|
||||
path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
@ -1,6 +1,6 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
print 'laod vtConstant.py'
|
||||
print('laod vtConstant.py')
|
||||
|
||||
# 默认空值
|
||||
EMPTY_STRING = ''
|
||||
|
@ -1,6 +1,6 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
print 'load vtEngine.py'
|
||||
print( 'load vtEngine.py')
|
||||
|
||||
import shelve
|
||||
from collections import OrderedDict
|
||||
@ -273,8 +273,9 @@ class MainEngine(object):
|
||||
return True
|
||||
|
||||
except Exception as ex:
|
||||
print u'vtEngine.disconnect Exception:{0} '.format(str(ex))
|
||||
print( u'vtEngine.disconnect Exception:{0} '.format(str(ex)))
|
||||
return False
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def writeLog(self, content):
|
||||
"""快速发出日志事件"""
|
||||
@ -292,7 +293,7 @@ class MainEngine(object):
|
||||
|
||||
def createLogger(self):
|
||||
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), 'logs', 'vnpy'))
|
||||
print u'create logger:{}'.format(filename)
|
||||
print( u'create logger:{}'.format(filename))
|
||||
self.logger = setup_logger(filename=filename, name='vnpy', debug=True)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@ -308,8 +309,9 @@ class MainEngine(object):
|
||||
if self.logger is not None:
|
||||
self.logger.error(content)
|
||||
else:
|
||||
print content
|
||||
print(content)
|
||||
self.createLogger()
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def writeWarning(self, content):
|
||||
"""快速发出告警日志事件"""
|
||||
@ -323,7 +325,7 @@ class MainEngine(object):
|
||||
if self.logger is not None:
|
||||
self.logger.warning(content)
|
||||
else:
|
||||
print content
|
||||
print( content)
|
||||
self.createLogger()
|
||||
|
||||
# 发出邮件
|
||||
@ -361,7 +363,7 @@ class MainEngine(object):
|
||||
if self.logger:
|
||||
self.logger.critical(content)
|
||||
else:
|
||||
print content
|
||||
print( content)
|
||||
self.createLogger()
|
||||
|
||||
# 发出邮件
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
建议将所有的常量定义放在该文件中,便于检查是否存在重复的现象。
|
||||
'''
|
||||
print 'load vtEvent.py'
|
||||
print( 'load vtEvent.py')
|
||||
|
||||
# 导入基础模块vnpy.event.EventEngine等
|
||||
from vnpy.event import *
|
||||
|
@ -26,7 +26,7 @@ def safeUnicode(value):
|
||||
if abs(d.as_tuple().exponent) > MAX_DECIMAL:
|
||||
value = round(value, ndigits=MAX_DECIMAL)
|
||||
|
||||
return unicode(value)
|
||||
return value
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def loadMongoSetting():
|
||||
|
@ -119,7 +119,7 @@ class VtGateway(object):
|
||||
|
||||
def createLogger(self):
|
||||
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), 'logs', 'Gateway'))
|
||||
print u'create logger:{}'.format(filename)
|
||||
print( u'create logger:{}'.format(filename))
|
||||
self.logger = setup_logger(filename=filename, name='vnpy', debug=True)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
@ -3,7 +3,7 @@
|
||||
"""
|
||||
通过VT_setting.json加载全局配置
|
||||
"""
|
||||
print 'load vtGlobal.py'
|
||||
print('load vtGlobal.py')
|
||||
import os
|
||||
import traceback
|
||||
import json
|
||||
@ -15,7 +15,7 @@ path = os.path.abspath(os.path.dirname(__file__))
|
||||
settingFileName = os.path.join(path, settingFileName)
|
||||
|
||||
try:
|
||||
f = file(settingFileName)
|
||||
globalSetting = json.load(f)
|
||||
with open(settingFileName,'r',encoding="utf8") as f:
|
||||
globalSetting = json.load(f)
|
||||
except:
|
||||
traceback.print_exc()
|
@ -3,8 +3,8 @@
|
||||
|
||||
# 重载sys模块,设置默认字符串编码方式为utf8
|
||||
import sys
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf8')
|
||||
#reload(sys)
|
||||
#sys.setdefaultencoding('utf8')
|
||||
|
||||
import sys
|
||||
import os
|
||||
@ -23,7 +23,7 @@ from vnpy.trader.uiMainWindow import *
|
||||
# 加载底层接口
|
||||
from vnpy.trader.gateway import ctpGateway
|
||||
# 初始化的接口模块,以及其指定的名称,CTP是模块,value,是该模块下的多个连接配置文件,如 CTP_JR_connect.json 'CTP_Prod', 'CTP_JR', , 'CTP_JK', 'CTP_02'
|
||||
init_gateway_names = {'CTP': ['CTP','CTP_YH01', 'CTP_YH02', 'CTP_YHHZQQ','CTP_JR2']}
|
||||
init_gateway_names = {'CTP': ['CTP','CTP_YH01', 'CTP_YH02', 'CTP_YH03','CTP_JK']}
|
||||
|
||||
from vnpy.trader.app import (ctaStrategy, riskManager, spreadTrading)
|
||||
|
||||
@ -53,7 +53,7 @@ def main():
|
||||
|
||||
# 添加Gatway
|
||||
for gw_name in init_gateway_names['CTP']:
|
||||
print 'add {0}'.format(gw_name)
|
||||
print('add {0}'.format(gw_name))
|
||||
mainEngine.addGateway(ctpGateway, gw_name)
|
||||
|
||||
# 添加应用
|
||||
@ -63,9 +63,12 @@ def main():
|
||||
|
||||
mainWindow = MainWindow(mainEngine, ee)
|
||||
mainWindow.showMaximized()
|
||||
|
||||
# 在主线程中启动Qt事件循环
|
||||
sys.exit(qApp.exec_())
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except Exception as ex:
|
||||
print(str(ex))
|
||||
traceback.print_exc()
|
||||
|
@ -37,7 +37,7 @@ class VtServer(RpcServer):
|
||||
self.engine = MainEngine()
|
||||
|
||||
for gw_name in init_gateway_names['CTP']:
|
||||
print 'add {0}'.format(gw_name)
|
||||
print( 'add {0}'.format(gw_name))
|
||||
self.engine.addGateway(ctpGateway, gw_name)
|
||||
|
||||
# 注册主引擎的方法到服务器的RPC函数
|
||||
@ -84,7 +84,7 @@ class VtServer(RpcServer):
|
||||
#----------------------------------------------------------------------
|
||||
def printLog(content):
|
||||
"""打印日志"""
|
||||
print datetime.now().strftime("%H:%M:%S"), '\t', content
|
||||
print( datetime.now().strftime("%H:%M:%S"), '\t', content)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
from language import text
|
||||
from vnpy.trader.language import text
|
||||
|
||||
# 将常量定义添加到vtText.py的局部字典中
|
||||
d = locals()
|
||||
|
Loading…
Reference in New Issue
Block a user