This commit is contained in:
msincenselee 2018-01-30 14:57:27 +08:00
parent 6a30576598
commit 03987b0011
43 changed files with 941 additions and 389 deletions

117
README.md
View File

@ -9,120 +9,13 @@ Fork版本主要改进如下
可视化python vtMain.py 可视化python vtMain.py
命令行python noUiMain.py 命令行python noUiMain.py
2018年1月升级至py3版本
大佳
QQ/Wechat28888502
# vn.py - 基于python的开源交易平台开发框架 # vn.py - 基于python的开源交易平台开发框架
https://github.com/vnpy/vnpy
---
### 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接口基本覆盖了国内所有常规交易品种股票、期货、期权具体包括
* CTPvn.ctp
* 飞马vn.femas
* LTSvn.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的交易员想要联系作者可以通过知乎私信
--- ---
### License ### License
MIT MIT

View File

@ -7,4 +7,4 @@ conda config --set show_channel_urls yes
conda install -c quantopian ta-lib=0.4.9 conda install -c quantopian ta-lib=0.4.9
:: Install vn.py :: Install vn.py
python setup.py install #python setup.py install

View File

@ -22,5 +22,5 @@ conda config --set show_channel_urls yes
conda install -c quantopian ta-lib=0.4.9 conda install -c quantopian ta-lib=0.4.9
#Install vn.py #Install vn.py
python setup.py install #python setup.py install

View File

@ -26,7 +26,7 @@ from vnpy.trader.vtEvent import *
from vnpy.rpc import RpcServer from vnpy.rpc import RpcServer
from vnpy.trader.vtEngine import MainEngine from vnpy.trader.vtEngine import MainEngine
from vnpy.trader.gateway import ctpGateway 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.util_monitor import *
from vnpy.trader.vtGlobal import globalSetting from vnpy.trader.vtGlobal import globalSetting
from vnpy.trader.util_gpid import * from vnpy.trader.util_gpid import *
@ -35,7 +35,7 @@ from vnpy.trader.app import ctaStrategy,riskManager
AUTO_CONNCET_GW = 'CTP' AUTO_CONNCET_GW = 'CTP'
######################################################################## ########################################################################
class VtServer(RpcServer): class VtServer(RpcServer):
"""vn.trader服务器""" """vn.trader 无界面服务器"""
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def __init__(self, repAddress, pubAddress): def __init__(self, repAddress, pubAddress):
@ -48,8 +48,7 @@ class VtServer(RpcServer):
# gateway 的连接名称在vtEngine.initGateway()里面定义,对应的配置文件是 "连接名称_connect.json" # gateway 的连接名称在vtEngine.initGateway()里面定义,对应的配置文件是 "连接名称_connect.json"
self.gateway_name = AUTO_CONNCET_GW self.gateway_name = AUTO_CONNCET_GW
# 启动的策略实例须在catStrategy/CtaSetting.json 里面定义 [u'S28_RB1001', u'S28_TFT', u'S28_HCRB',u'atr_rsi'] # 启动的策略实例须在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.g_count = 0
self.disconnect_signal = 0 self.disconnect_signal = 0
self.last_dt = datetime.now() self.last_dt = datetime.now()
@ -58,7 +57,7 @@ class VtServer(RpcServer):
ee = EventEngine2() ee = EventEngine2()
# 创建主引擎对象 # 创建主引擎对象
print u'instance mainengine' print( u'instance mainengine')
self.engine = MainEngine(ee) self.engine = MainEngine(ee)
# 添加CTP Gateway,配置文件为 CTP_Post # 添加CTP Gateway,配置文件为 CTP_Post
@ -128,7 +127,7 @@ class VtServer(RpcServer):
self.engine.qryStatus() self.engine.qryStatus()
if dt.hour != self.last_dt.hour: if dt.hour != self.last_dt.hour:
self.last_dt = dt 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)) self.engine.writeLog( u'noUiMain.py checkpoint:{0}'.format(dt))
# 定时断开 # 定时断开
@ -172,21 +171,21 @@ class VtServer(RpcServer):
# self.mainEngine.dbConnect() # self.mainEngine.dbConnect()
# 加载cta的配置 # 加载cta的配置
print u'load cta setting' print( u'load cta setting')
self.engine.ctaEngine.loadSetting() self.engine.ctaEngine.loadSetting()
print u'initialize all strategies' print(u'initialize all strategies')
# 初始化策略,如果多个,则需要逐一初始化多个 # 初始化策略,如果多个,则需要逐一初始化多个
for s in self.strategies: for s in self.strategies:
print 'init trategy {0}'.format(s) print( 'init trategy {0}'.format(s))
self.engine.ctaEngine.initStrategy(s) self.engine.ctaEngine.initStrategy(s)
# 逐一启动策略 # 逐一启动策略
print 'start strategy {0}'.format(s) print( 'start strategy {0}'.format(s))
self.engine.ctaEngine.startStrategy(s) self.engine.ctaEngine.startStrategy(s)
# 指定的连接配置 # 指定的连接配置
if not self.trade_off(): 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.engine.connect(self.gateway_name)
self.connected = True self.connected = True
@ -214,12 +213,12 @@ class VtServer(RpcServer):
self.publish(event.type_.encode('utf-8'), event) self.publish(event.type_.encode('utf-8'), event)
except Exception as ex: 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): def stopServer(self):
"""停止服务器""" """停止服务器"""
print 'stopServer' print( 'stopServer')
# 关闭引擎 # 关闭引擎
self.engine.exit() self.engine.exit()
# 停止服务器线程 # 停止服务器线程
@ -228,7 +227,7 @@ class VtServer(RpcServer):
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def printLog(content): def printLog(content):
"""打印日志""" """打印日志"""
print datetime.now().strftime("%H:%M:%S"), '\t', content print( datetime.now().strftime("%H:%M:%S"), '\t', content)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def runServer(): def runServer():
@ -238,7 +237,7 @@ def runServer():
log_file_name = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), log_file_name = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),
'logs', u'noUiMain.log')) 'logs', u'noUiMain.log'))
except Exception as ex: 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')) log_file_name = os.path.abspath(os.path.join(os.getcwd(), 'logs', u'noUiMain.log'))
setup_logger(filename=log_file_name, debug=False) setup_logger(filename=log_file_name, debug=False)

View File

@ -1,7 +1,7 @@
# encoding: UTF-8 # encoding: UTF-8
from ctaEngine import CtaEngine from vnpy.trader.app.ctaStrategy.ctaEngine import CtaEngine
from uiCtaWidget import CtaEngineManager from vnpy.trader.app.ctaStrategy.uiCtaWidget import CtaEngineManager
appName = 'CtaStrategy' appName = 'CtaStrategy'
appDisplayName = u'CTA策略' appDisplayName = u'CTA策略'

View File

@ -275,7 +275,7 @@ class BacktestingEngine(object):
# 载入json文件 # 载入json文件
fileName = 'mysql_connect.json' fileName = 'mysql_connect.json'
try: try:
f = file(fileName) f = open(fileName,'r',encoding='utf8')
except IOError: except IOError:
self.writeCtaLog(u'回测引擎读取Mysql_connect.json失败') self.writeCtaLog(u'回测引擎读取Mysql_connect.json失败')
return return
@ -1571,7 +1571,7 @@ class BacktestingEngine(object):
self.output(u'开始回放数据') self.output(u'开始回放数据')
import csv import csv
csvfile = file(filename,'rb') csvfile = open(filename,'rb',encoding='utf8')
reader = csv.DictReader((line.replace('\0', '') for line in csvfile), delimiter=",") reader = csv.DictReader((line.replace('\0', '') for line in csvfile), delimiter=",")
last_tradingDay = None last_tradingDay = None
for row in reader: for row in reader:
@ -1610,7 +1610,7 @@ class BacktestingEngine(object):
last_tradingDay = bar.tradingDay last_tradingDay = bar.tradingDay
self.newBar(bar) self.newBar(bar)
self.last_bar = bar
except Exception as ex: except Exception as ex:
self.writeCtaLog(u'{0}:{1}'.format(Exception, ex)) self.writeCtaLog(u'{0}:{1}'.format(Exception, ex))
traceback.print_exc() traceback.print_exc()
@ -1798,8 +1798,9 @@ class BacktestingEngine(object):
self.crossStopOrder() # 再撮合停止单 self.crossStopOrder() # 再撮合停止单
self.strategy.onBar(bar) # 推送K线到策略中 self.strategy.onBar(bar) # 推送K线到策略中
self.__sendOnBarEvent(bar) # 推送K线到事件 self.__sendOnBarEvent(bar) # 推送K线到事件
self.last_bar = bar
#---------------------------------------------------------------------- # ----------------------------------------------------------------------
def newTick(self, tick): def newTick(self, tick):
"""新的Tick""" """新的Tick"""
self.tick = tick self.tick = tick
@ -1808,7 +1809,7 @@ class BacktestingEngine(object):
self.crossStopOrder() self.crossStopOrder()
self.strategy.onTick(tick) self.strategy.onTick(tick)
#---------------------------------------------------------------------- # ----------------------------------------------------------------------
def initStrategy(self, strategyClass, setting=None): def initStrategy(self, strategyClass, setting=None):
""" """
初始化策略 初始化策略
@ -1833,7 +1834,6 @@ class BacktestingEngine(object):
def sendOrder(self, vtSymbol, orderType, price, volume, strategy, priceType=PRICETYPE_LIMITPRICE): def sendOrder(self, vtSymbol, orderType, price, volume, strategy, priceType=PRICETYPE_LIMITPRICE):
"""发单""" """发单"""
self.limitOrderCount += 1 self.limitOrderCount += 1
orderID = str(self.limitOrderCount) orderID = str(self.limitOrderCount)
@ -2110,7 +2110,12 @@ class BacktestingEngine(object):
def loadTick(self, dbName, collectionName, startDate): def loadTick(self, dbName, collectionName, startDate):
"""直接返回初始化数据列表中的Tick""" """直接返回初始化数据列表中的Tick"""
return self.initData 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): def writeCtaLog(self, content):
"""记录日志""" """记录日志"""
@ -2121,12 +2126,7 @@ class BacktestingEngine(object):
if self.logger: if self.logger:
self.logger.info(content) self.logger.info(content)
else: 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.createLogger()
self.logger = setup_logger(
filename=filename,name=self.strategy_name if len(self.strategy_name)>0 else 'strategy'
)
def writeCtaError(self, content): def writeCtaError(self, content):
"""记录异常""" """记录异常"""
@ -3290,7 +3290,7 @@ class BacktestingEngine(object):
'{}_TradeList_{}.csv'.format(s, datetime.now().strftime('%Y%m%d_%H%M')))) '{}_TradeList_{}.csv'.format(s, datetime.now().strftime('%Y%m%d_%H%M'))))
import csv import csv
csvWriteFile = file(csvOutputFile, 'wb') csvWriteFile = open(csvOutputFile, 'wb',encoding='utf8')
fieldnames = ['vtSymbol','OpenTime', 'OpenPrice', 'Direction', 'CloseTime', 'ClosePrice', 'Volume', 'Profit'] fieldnames = ['vtSymbol','OpenTime', 'OpenPrice', 'Direction', 'CloseTime', 'ClosePrice', 'Volume', 'Profit']
writer = csv.DictWriter(f=csvWriteFile, fieldnames=fieldnames, dialect='excel') writer = csv.DictWriter(f=csvWriteFile, fieldnames=fieldnames, dialect='excel')
writer.writeheader() writer.writeheader()
@ -3307,7 +3307,7 @@ class BacktestingEngine(object):
else: else:
csvOutputFile2 = self.daily_report_name 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'] fieldnames = ['date','capital','net', 'maxCapital','rate','longMoney','shortMoney','occupyMoney','occupyRate','longPos','shortPos']
writer2 = csv.DictWriter(f=csvWriteFile2, fieldnames=fieldnames, dialect='excel') writer2 = csv.DictWriter(f=csvWriteFile2, fieldnames=fieldnames, dialect='excel')
writer2.writeheader() writer2.writeheader()
@ -3595,11 +3595,11 @@ class OptimizationSetting(object):
return return
if end < start: if end < start:
print u'参数起始点必须不大于终止点' print( u'参数起始点必须不大于终止点')
return return
if step <= 0: if step <= 0:
print u'参数布进必须大于0' print( u'参数布进必须大于0')
return return
l = [] l = []

View File

@ -5,7 +5,7 @@
''' '''
from __future__ import division from __future__ import division
print 'load ctaBase.py' print( 'load ctaBase.py')
# 常量定义 # 常量定义
# CTA引擎中涉及到的交易方向类型 # CTA引擎中涉及到的交易方向类型

View File

@ -20,7 +20,7 @@
''' '''
print 'load ctaEngine.py' print( 'load ctaEngine.py')
import json import json
import os import os
import traceback import traceback
@ -100,6 +100,9 @@ class CtaEngine(object):
self.registerEvent() self.registerEvent()
self.logger = None self.logger = None
self.createLogger()
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def sendOrder(self, vtSymbol, orderType, price, volume, strategy,priceType=PRICETYPE_LIMITPRICE): def sendOrder(self, vtSymbol, orderType, price, volume, strategy,priceType=PRICETYPE_LIMITPRICE):
"""发单""" """发单"""
@ -585,8 +588,12 @@ class CtaEngine(object):
if self.logger: if self.logger:
self.logger.info(content) self.logger.info(content)
else: else:
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), '..','..','logs', 'ctaEngine')) self.createLogger()
self.logger = setup_logger(filename=filename, name='ctaEngine')
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): def writeCtaError(self,content):
"""快速发出CTA模块错误日志事件""" """快速发出CTA模块错误日志事件"""
@ -699,7 +706,7 @@ class CtaEngine(object):
# 5.调用主引擎的订阅接口 # 5.调用主引擎的订阅接口
self.mainEngine.subscribe(req, contract.gatewayName) self.mainEngine.subscribe(req, contract.gatewayName)
else: 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.writeCtaLog(u'交易合约{}无法找到,添加到待订阅列表'.format (symbol))
self.pendingSubcribeSymbols[symbol]=strategy self.pendingSubcribeSymbols[symbol]=strategy

View File

@ -80,8 +80,7 @@ class CtaGrid(object):
j['closeStatus'] = self.closeStatus # 平仓状态 j['closeStatus'] = self.closeStatus # 平仓状态
j['lockGrids'] = self.lockGrids # 对锁的网格 j['lockGrids'] = self.lockGrids # 对锁的网格
j['reuse'] = self.reuse # 是否重用 j['reuse'] = self.reuse # 是否重用
j['type'] = self.reuse # 是否重用
j['type'] = self.type # 类型
j['openPrices'] = self.openPrices # 套利中,两腿的开仓价格 j['openPrices'] = self.openPrices # 套利中,两腿的开仓价格
j['snapshot'] = self.snapshot # 切片数据 j['snapshot'] = self.snapshot # 切片数据
@ -847,7 +846,7 @@ class CtaGridTrade(object):
return [] return []
try: try:
f = file(jsonFileName) f = open(jsonFileName,'rb',encoding='utf8')
except IOError: except IOError:
self.writeCtaLog(u'读取网格出错,请检查') self.writeCtaLog(u'读取网格出错,请检查')
return [] return []

View File

@ -96,9 +96,9 @@ class HistoryDataEngine(object):
self.dbClient[SETTING_DB_NAME]['FuturesSymbol'].update_one(flt, {'$set':symbolDict}, self.dbClient[SETTING_DB_NAME]['FuturesSymbol'].update_one(flt, {'$set':symbolDict},
upsert=True) upsert=True)
print u'期货合约代码下载完成' print( u'期货合约代码下载完成')
else: else:
print u'期货合约代码下载失败' print( u'期货合约代码下载失败')
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def downloadFuturesDailyBar(self, symbol): def downloadFuturesDailyBar(self, symbol):
@ -106,7 +106,7 @@ class HistoryDataEngine(object):
下载期货合约的日行情symbol是合约代码 下载期货合约的日行情symbol是合约代码
若最后四位为0000如IF0000代表下载连续合约 若最后四位为0000如IF0000代表下载连续合约
""" """
print u'开始下载%s日行情' %symbol print( u'开始下载%s日行情' %symbol)
# 查询数据库中已有数据的最后日期 # 查询数据库中已有数据的最后日期
cl = self.dbClient[DAILY_DB_NAME][symbol] cl = self.dbClient[DAILY_DB_NAME][symbol]
@ -158,24 +158,24 @@ class HistoryDataEngine(object):
bar.volume = d.get('turnoverVol', 0) bar.volume = d.get('turnoverVol', 0)
bar.openInterest = d.get('openInt', 0) bar.openInterest = d.get('openInt', 0)
except KeyError: except KeyError:
print d print( d)
flt = {'datetime': bar.datetime} flt = {'datetime': bar.datetime}
self.dbClient[DAILY_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True) self.dbClient[DAILY_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True)
print u'%s下载完成' %symbol print( u'%s下载完成' %symbol)
else: else:
print u'找不到合约%s' %symbol print( u'找不到合约%s' %symbol)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def downloadAllFuturesDailyBar(self): def downloadAllFuturesDailyBar(self):
"""下载所有期货的主力合约日行情""" """下载所有期货的主力合约日行情"""
start = time() start = time()
print u'开始下载所有期货的主力合约日行情' print( u'开始下载所有期货的主力合约日行情')
productSymbolSet = self.readFuturesProductSymbol() productSymbolSet = self.readFuturesProductSymbol()
print u'代码列表读取成功,产品代码:%s' %productSymbolSet print( u'代码列表读取成功,产品代码:%s' %productSymbolSet)
# 这里也测试了线程池,但可能由于下载函数中涉及较多的数据格 # 这里也测试了线程池,但可能由于下载函数中涉及较多的数据格
# 式转换CPU开销较大多线程效率并无显著改变。 # 式转换CPU开销较大多线程效率并无显著改变。
@ -187,12 +187,12 @@ class HistoryDataEngine(object):
for productSymbol in productSymbolSet: for productSymbol in productSymbolSet:
self.downloadFuturesDailyBar(productSymbol+'0000') self.downloadFuturesDailyBar(productSymbol+'0000')
print u'所有期货的主力合约日行情已经全部下载完成, 耗时%s' %(time()-start) print( u'所有期货的主力合约日行情已经全部下载完成, 耗时%s' %(time()-start))
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def downloadFuturesIntradayBar(self, symbol): def downloadFuturesIntradayBar(self, symbol):
"""下载期货的日内分钟行情""" """下载期货的日内分钟行情"""
print u'开始下载%s日内分钟行情' %symbol print( u'开始下载%s日内分钟行情' %symbol)
# 日内分钟行情只有具体合约 # 日内分钟行情只有具体合约
path = 'api/market/getFutureBarRTIntraDay.json' path = 'api/market/getFutureBarRTIntraDay.json'
@ -226,14 +226,14 @@ class HistoryDataEngine(object):
bar.volume = d.get('totalVolume', 0) bar.volume = d.get('totalVolume', 0)
bar.openInterest = 0 bar.openInterest = 0
except KeyError: except KeyError:
print d print( d)
flt = {'datetime': bar.datetime} flt = {'datetime': bar.datetime}
self.dbClient[MINUTE_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True) self.dbClient[MINUTE_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True)
print u'%s下载完成' %symbol print( u'%s下载完成' %symbol)
else: else:
print u'找不到合约%s' %symbol print( u'找不到合约%s' %symbol )
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def downloadEquitySymbol(self, tradeDate=''): def downloadEquitySymbol(self, tradeDate=''):
@ -260,16 +260,16 @@ class HistoryDataEngine(object):
self.dbClient[SETTING_DB_NAME]['EquitySymbol'].update_one(flt, {'$set':symbolDict}, self.dbClient[SETTING_DB_NAME]['EquitySymbol'].update_one(flt, {'$set':symbolDict},
upsert=True) upsert=True)
print u'股票代码下载完成' print( u'股票代码下载完成')
else: else:
print u'股票代码下载失败' print( u'股票代码下载失败')
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def downloadEquityDailyBar(self, symbol): def downloadEquityDailyBar(self, symbol):
""" """
下载股票的日行情symbol是股票代码 下载股票的日行情symbol是股票代码
""" """
print u'开始下载%s日行情' %symbol print( u'开始下载%s日行情' %symbol)
# 查询数据库中已有数据的最后日期 # 查询数据库中已有数据的最后日期
cl = self.dbClient[DAILY_DB_NAME][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.datetime = datetime.strptime(bar.date, '%Y%m%d')
bar.volume = d.get('turnoverVol', 0) bar.volume = d.get('turnoverVol', 0)
except KeyError: except KeyError:
print d print( d)
flt = {'datetime': bar.datetime} flt = {'datetime': bar.datetime}
self.dbClient[DAILY_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True) self.dbClient[DAILY_DB_NAME][symbol].update_one(flt, {'$set':bar.__dict__}, upsert=True)
print u'%s下载完成' %symbol print( u'%s下载完成' %symbol)
else: else:
print u'找不到合约%s' %symbol print( u'找不到合约%s' %symbol )
@ -326,7 +326,7 @@ def loadMcCsv(fileName, dbName, symbol):
import csv import csv
start = time() start = time()
print u'开始读取CSV文件%s中的数据插入到%s%s' %(fileName, dbName, symbol) print( u'开始读取CSV文件%s中的数据插入到%s%s' %(fileName, dbName, symbol))
# 锁定集合,并创建索引 # 锁定集合,并创建索引
host, port = loadMongoSetting() host, port = loadMongoSetting()
@ -336,7 +336,8 @@ def loadMcCsv(fileName, dbName, symbol):
collection.ensure_index([('datetime', pymongo.ASCENDING)], unique=True) 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: for d in reader:
bar = CtaBarData() bar = CtaBarData()
bar.vtSymbol = symbol bar.vtSymbol = symbol
@ -352,9 +353,9 @@ def loadMcCsv(fileName, dbName, symbol):
flt = {'datetime': bar.datetime} flt = {'datetime': bar.datetime}
collection.update_one(flt, {'$set':bar.__dict__}, upsert=True) 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__': if __name__ == '__main__':
## 简单的测试脚本可以写在这里 ## 简单的测试脚本可以写在这里

View File

@ -31,9 +31,9 @@ class DatayesClient(object):
def loadSetting(self): def loadSetting(self):
"""载入配置""" """载入配置"""
try: try:
f = file(FILENAME) f = open(FILENAME,'rb',encoding='utf8')
except IOError: except IOError:
print u'%s无法打开配置文件' % self.name print( u'%s无法打开配置文件' % self.name)
return return
setting = json.load(f) setting = json.load(f)
@ -42,28 +42,28 @@ class DatayesClient(object):
self.version = str(setting['version']) self.version = str(setting['version'])
self.token = str(setting['token']) self.token = str(setting['token'])
except KeyError: except KeyError:
print u'%s配置文件字段缺失' % self.name print( u'%s配置文件字段缺失' % self.name)
return return
self.header['Connection'] = 'keep_alive' self.header['Connection'] = 'keep_alive'
self.header['Authorization'] = 'Bearer ' + self.token self.header['Authorization'] = 'Bearer ' + self.token
self.settingLoaded = True self.settingLoaded = True
print u'%s配置载入完成' % self.name print( u'%s配置载入完成' % self.name)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def downloadData(self, path, params): def downloadData(self, path, params):
"""下载数据""" """下载数据"""
if not self.settingLoaded: if not self.settingLoaded:
print u'%s配置未载入' % self.name print( u'%s配置未载入' % self.name)
return None return None
else: else:
url = '/'.join([self.domain, self.version, path]) url = '/'.join([self.domain, self.version, path])
r = requests.get(url=url, headers=self.header, params=params) r = requests.get(url=url, headers=self.header, params=params)
if r.status_code != HTTP_OK: 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 return None
else: else:
result = r.json() result = r.json()
@ -71,9 +71,9 @@ class DatayesClient(object):
return result['data'] return result['data']
else: else:
if 'retMsg' in result: if 'retMsg' in result:
print u'%s查询失败,返回信息%s' %(self.name, result['retMsg']) print(u'%s查询失败,返回信息%s' %(self.name, result['retMsg']))
elif 'message' in result: elif 'message' in result:
print u'%s查询失败,返回信息%s' %(self.name, result['message']) print( u'%s查询失败,返回信息%s' %(self.name, result['message']))
return None return None

View File

@ -5,9 +5,9 @@ import os
import traceback import traceback
# 默认设置 # 默认设置
from chinese import text from vnpy.trader.app.ctaStrategy.language.chinese import text
# 是否要使用英文 # 是否要使用英文
from vnpy.trader.vtGlobal import globalSetting from vnpy.trader.vtGlobal import globalSetting
if globalSetting['language'] == 'english': if globalSetting['language'] == 'english':
from english import text from vnpy.trader.app.ctaStrategy.language.english import text

View File

@ -48,7 +48,7 @@ class CtaValueMonitor(QtWidgets.QTableWidget):
# 新增数据 # 新增数据
col = 0 col = 0
for k, v in data.items(): for k, v in data.items():
cell = QtWidgets.QTableWidgetItem(unicode(v)) cell = QtWidgets.QTableWidgetItem(v)
self.keyCellDict[k] = cell self.keyCellDict[k] = cell
self.setItem(0, col, cell) self.setItem(0, col, cell)
col += 1 col += 1
@ -58,7 +58,7 @@ class CtaValueMonitor(QtWidgets.QTableWidget):
# 更新数据 # 更新数据
for k, v in data.items(): for k, v in data.items():
cell = self.keyCellDict[k] cell = self.keyCellDict[k]
cell.setText(unicode(v)) cell.setText(v)
#cell.setBackgroundColor() #cell.setBackgroundColor()

View File

@ -5,12 +5,12 @@
''' '''
from vnpy.trader.vtConstant import DIRECTION_LONG, DIRECTION_SHORT 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.vtEvent import *
from vnpy.trader.app.ctaStrategy.ctaGridTrade 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.setFrameShape(self.HLine)
self.setFrameShadow(self.Sunken) self.setFrameShadow(self.Sunken)
class SpreadTradeManager(QtGui.QWidget): class SpreadTradeManager(QtWidgets.QWidget):
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def __init__(self, ctaEngine, eventEngine, parent=None): def __init__(self, ctaEngine, eventEngine, parent=None):
super(SpreadTradeManager, self).__init__(parent) super(SpreadTradeManager, self).__init__(parent)
@ -38,15 +38,15 @@ class SpreadTradeManager(QtGui.QWidget):
self.setWindowTitle(u'套利交易') self.setWindowTitle(u'套利交易')
# 连接运行中的套利测试(策略名称[下拉菜单],连接按钮) # 连接运行中的套利测试(策略名称[下拉菜单],连接按钮)
self.btnSwitchConnectStatus = QtGui.QPushButton(u'套利策略未连接') self.btnSwitchConnectStatus = QtWidgets.QPushButton(u'套利策略未连接')
self.btnSwitchConnectStatus.clicked.connect(self.btnSwitchClick) self.btnSwitchConnectStatus.clicked.connect(self.btnSwitchClick)
Label = QtGui.QLabel Label = QtWidgets.QLabel
grid = QtGui.QGridLayout() grid = QtWidgets.QGridLayout()
grid.addWidget(Label(u'状态'), 0, 0) grid.addWidget(Label(u'状态'), 0, 0)
grid.addWidget(self.btnSwitchConnectStatus, 0, 1) grid.addWidget(self.btnSwitchConnectStatus, 0, 1)
self.spreadStraty = QtGui.QComboBox() self.spreadStraty = QtWidgets.QComboBox()
self.strategy_name_list = self.ctaEngine.strategyDict.keys() self.strategy_name_list = self.ctaEngine.strategyDict.keys()
self.spreadStraty.addItems(self.strategy_name_list) self.spreadStraty.addItems(self.strategy_name_list)
@ -57,11 +57,11 @@ class SpreadTradeManager(QtGui.QWidget):
# 网格信息+操作(新增,删除,更新) # 网格信息+操作(新增,删除,更新)
grid.addWidget(Label(u'方向'), 2, 0) grid.addWidget(Label(u'方向'), 2, 0)
self.gridDirection = QtGui.QComboBox() self.gridDirection = QtWidgets.QComboBox()
self.gridDirection.addItems(self.directionList) self.gridDirection.addItems(self.directionList)
grid.addWidget(self.gridDirection, 2, 1) grid.addWidget(self.gridDirection, 2, 1)
self.spinOpenPrice = QtGui.QDoubleSpinBox() self.spinOpenPrice = QtWidgets.QDoubleSpinBox()
self.spinOpenPrice.setDecimals(4) self.spinOpenPrice.setDecimals(4)
self.spinOpenPrice.setMinimum(-10000) # 原来是0为支持套利改为-10000 self.spinOpenPrice.setMinimum(-10000) # 原来是0为支持套利改为-10000
self.spinOpenPrice.setMaximum(100000) self.spinOpenPrice.setMaximum(100000)
@ -70,7 +70,7 @@ class SpreadTradeManager(QtGui.QWidget):
grid.addWidget(Label(u'开仓价'), 3, 0) grid.addWidget(Label(u'开仓价'), 3, 0)
grid.addWidget(self.spinOpenPrice, 3, 1) grid.addWidget(self.spinOpenPrice, 3, 1)
self.spinClosePrice = QtGui.QDoubleSpinBox() self.spinClosePrice = QtWidgets.QDoubleSpinBox()
self.spinClosePrice.setDecimals(4) self.spinClosePrice.setDecimals(4)
self.spinClosePrice.setMinimum(-10000) # 原来是0为支持套利改为-10000 self.spinClosePrice.setMinimum(-10000) # 原来是0为支持套利改为-10000
self.spinClosePrice.setMaximum(100000) self.spinClosePrice.setMaximum(100000)
@ -78,57 +78,60 @@ class SpreadTradeManager(QtGui.QWidget):
grid.addWidget(Label(u'平仓价'), 4, 0) grid.addWidget(Label(u'平仓价'), 4, 0)
grid.addWidget(self.spinClosePrice, 4, 1) grid.addWidget(self.spinClosePrice, 4, 1)
self.spinOrderVolume = QtGui.QSpinBox() self.spinOrderVolume = QtWidgets.QSpinBox()
self.spinOrderVolume.setMinimum(0) self.spinOrderVolume.setMinimum(0)
self.spinOrderVolume.setMaximum(1000) self.spinOrderVolume.setMaximum(1000)
grid.addWidget(Label(u'委托数量'), 5, 0) grid.addWidget(Label(u'委托数量'), 5, 0)
grid.addWidget(self.spinOrderVolume, 5, 1) grid.addWidget(self.spinOrderVolume, 5, 1)
self.spinTradedVolume = QtGui.QSpinBox() self.spinTradedVolume = QtWidgets.QSpinBox()
self.spinTradedVolume.setMinimum(0) self.spinTradedVolume.setMinimum(0)
self.spinTradedVolume.setMaximum(1000) self.spinTradedVolume.setMaximum(1000)
grid.addWidget(Label(u'成交数量'), 6, 0) grid.addWidget(Label(u'成交数量'), 6, 0)
grid.addWidget(self.spinTradedVolume, 6, 1) grid.addWidget(self.spinTradedVolume, 6, 1)
self.openStatus = QtGui.QCheckBox(u'') # 开仓状态 self.openStatus = QtWidgets.QCheckBox(u'') # 开仓状态
grid.addWidget(Label(u'开仓状态'), 7, 0) grid.addWidget(Label(u'开仓状态'), 7, 0)
grid.addWidget(self.openStatus, 7, 1) grid.addWidget(self.openStatus, 7, 1)
self.orderStatus = QtGui.QCheckBox(u'') # 委托状态 self.orderStatus = QtWidgets.QCheckBox(u'') # 委托状态
grid.addWidget(Label(u'委托状态'), 8, 0) grid.addWidget(Label(u'委托状态'), 8, 0)
grid.addWidget(self.orderStatus, 8, 1) grid.addWidget(self.orderStatus, 8, 1)
self.closeStatus = QtGui.QCheckBox(u'') # 平仓状态 self.closeStatus = QtWidgets.QCheckBox(u'') # 平仓状态
grid.addWidget(Label(u'平仓状态'), 9, 0) grid.addWidget(Label(u'平仓状态'), 9, 0)
grid.addWidget(self.closeStatus, 9, 1) 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) btnAddGrid.clicked.connect(self.btnAddGridClick)
btnUpdateGrid = QtGui.QPushButton(u'更新') btnUpdateGrid = QtWidgets.QPushButton(u'更新')
btnUpdateGrid.clicked.connect(self.btnUpdateGridClick) btnUpdateGrid.clicked.connect(self.btnUpdateGridClick)
btnRemoveGrid = QtGui.QPushButton(u'删除') btnRemoveGrid = QtWidgets.QPushButton(u'删除')
btnRemoveGrid.clicked.connect(self.btnRemoveGridClick) btnRemoveGrid.clicked.connect(self.btnRemoveGridClick)
btnRemoveAll = QtGui.QPushButton(u'全删除') btnRemoveAll = QtWidgets.QPushButton(u'全删除')
btnRemoveAll.clicked.connect(self.btnRemoveAllClick) btnRemoveAll.clicked.connect(self.btnRemoveAllClick)
hbox = QtGui.QHBoxLayout() hbox = QtWidgets.QHBoxLayout()
hbox.addWidget(btnAddGrid) hbox.addWidget(btnAddGrid)
hbox.addWidget(btnUpdateGrid) hbox.addWidget(btnUpdateGrid)
hbox.addStretch() hbox.addStretch()
hbox.addWidget(btnRemoveGrid) hbox.addWidget(btnRemoveGrid)
hbox.addWidget(btnRemoveAll) hbox.addWidget(btnRemoveAll)
vbox = QtGui.QVBoxLayout() vbox = QtWidgets.QVBoxLayout()
vbox.addLayout(grid) vbox.addLayout(grid)
vbox.addLayout(hbox) vbox.addLayout(hbox)
# 状态信息(通过定时器,显示 上网格清单,下网格清单) # 状态信息(通过定时器,显示 上网格清单,下网格清单)
#日志监控 #日志监控
self.logMsgs = QtGui.QTextEdit() self.logMsgs = QtWidgets.QTextEdit()
self.logMsgs.setReadOnly(True) self.logMsgs.setReadOnly(True)
self.logMsgs.setMaximumHeight(200) self.logMsgs.setMaximumHeight(200)
vbox.addWidget(self.logMsgs) vbox.addWidget(self.logMsgs)
@ -141,7 +144,7 @@ class SpreadTradeManager(QtGui.QWidget):
self.log(u'没有连接CTA引擎') self.log(u'没有连接CTA引擎')
return return
strategy_name = unicode(self.spreadStraty.currentText()) strategy_name = self.spreadStraty.currentText()
if strategy_name is None or len(strategy_name) == 0: if strategy_name is None or len(strategy_name) == 0:
if len(self.strategy_name_list)==0: if len(self.strategy_name_list)==0:
@ -171,7 +174,7 @@ class SpreadTradeManager(QtGui.QWidget):
self.log(u'没有连接策略') self.log(u'没有连接策略')
return return
direction = unicode(self.gridDirection.currentText()) direction = self.gridDirection.currentText()
if direction is None or len(direction) ==0: if direction is None or len(direction) ==0:
self.log(u'先选择方向') self.log(u'先选择方向')
return return
@ -188,6 +191,8 @@ class SpreadTradeManager(QtGui.QWidget):
closeprice=close_price, closeprice=close_price,
volume=order_volume) volume=order_volume)
grid.reuse = self.reuseStatus.isChecked()
if direction == DIRECTION_LONG: if direction == DIRECTION_LONG:
self.strategy.gt.dnGrids.append(grid) self.strategy.gt.dnGrids.append(grid)
@ -215,7 +220,7 @@ class SpreadTradeManager(QtGui.QWidget):
self.log(u'没有连接策略') self.log(u'没有连接策略')
return return
direction = unicode(self.gridDirection.currentText()) direction = self.gridDirection.currentText()
if direction is None or len(direction) == 0: if direction is None or len(direction) == 0:
self.log(u'先选择方向'); self.log(u'先选择方向');
return return
@ -233,6 +238,7 @@ class SpreadTradeManager(QtGui.QWidget):
self.openStatus.setChecked(grid.openStatus) self.openStatus.setChecked(grid.openStatus)
self.orderStatus.setChecked(grid.orderStatus) self.orderStatus.setChecked(grid.orderStatus)
self.closeStatus.setChecked(grid.closeStatus) self.closeStatus.setChecked(grid.closeStatus)
self.reuseStatus.setChecked(grid.reuse)
def btnUpdateGridClick(self): def btnUpdateGridClick(self):
"""更新网格""" """更新网格"""
@ -244,7 +250,7 @@ class SpreadTradeManager(QtGui.QWidget):
self.log(u'没有连接策略') self.log(u'没有连接策略')
return return
direction = unicode(self.gridDirection.currentText()) direction = self.gridDirection.currentText()
if direction is None or len(direction) ==0: if direction is None or len(direction) ==0:
self.log(u'先选择方向') self.log(u'先选择方向')
return return
@ -256,12 +262,14 @@ class SpreadTradeManager(QtGui.QWidget):
self.log(u'没有找到{0}方向的网格:{1}'.format(direction,open_price)) self.log(u'没有找到{0}方向的网格:{1}'.format(direction,open_price))
return return
grid.openPrice = open_price
grid.closePrice = self.spinClosePrice.value() grid.closePrice = self.spinClosePrice.value()
grid.volume = self.spinOrderVolume.value() grid.volume = self.spinOrderVolume.value()
grid.tradedVolume = self.spinTradedVolume.value() grid.tradedVolume = self.spinTradedVolume.value()
grid.openStatus = self.openStatus.isChecked() grid.openStatus = self.openStatus.isChecked()
grid.orderStatus = self.orderStatus.isChecked() grid.orderStatus = self.orderStatus.isChecked()
grid.closeStatus = self.closeStatus.isChecked() grid.closeStatus = self.closeStatus.isChecked()
grid.reuse = self.reuseStatus.isChecked()
self.strategy.gt.save(direction=direction) self.strategy.gt.save(direction=direction)
self.strategy.recheckPositions = True self.strategy.recheckPositions = True
@ -277,16 +285,33 @@ class SpreadTradeManager(QtGui.QWidget):
self.log(u'没有连接策略') self.log(u'没有连接策略')
return return
direction = unicode(self.gridDirection.currentText())
direction = self.gridDirection.currentText()
if direction is None or len(direction) == 0: if direction is None or len(direction) == 0:
self.log(u'先选择方向') self.log(u'先选择方向')
return return
open_price = self.spinOpenPrice.value() open_price = self.spinOpenPrice.value()
self.strategy.gt.removeGrids(direction=direction, priceline=open_price) if (direction == DIRECTION_LONG and len(self.strategy.gt.dnGrids) < 2) or \
self.strategy.gt.save(direction=direction) (direction == DIRECTION_SHORT and len(self.strategy.gt.upGrids) < 2):
self.log(u'成功移除{0}方向的网格:{1}'.format(direction,open_price)) self.log(u'{0}方向的网格只有一个,不能删除'.format(direction))
self.displayGrids() 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): def btnRemoveAllClick(self):
"""删除所有网格""" """删除所有网格"""
@ -298,17 +323,19 @@ class SpreadTradeManager(QtGui.QWidget):
self.log(u'没有连接策略') self.log(u'没有连接策略')
return return
direction = unicode(self.gridDirection.currentText()) direction = self.gridDirection.currentText()
if direction is None or len(direction) == 0: if direction is None or len(direction) == 0:
self.log(u'先选择方向') self.log(u'先选择方向')
return return
if direction == DIRECTION_LONG: if direction == DIRECTION_LONG:
self.strategy.gt.dnGrids = [] self.strategy.gt.dnGrids = self.strategy.gt.dnGrids [-1:]
self.strategy.gt.save(direction=direction) self.strategy.gt.save(direction=direction)
self.log(u'成功移除{0}方向的网格,只保留最后一个'.format(direction))
else: else:
self.strategy.gt.upGrids=[] self.strategy.gt.upGrids = self.strategy.gt.dnGrids [-1:]
self.strategy.gt.save(direction=direction) self.strategy.gt.save(direction=direction)
self.log(u'成功移除{0}方向的网格,只保留最后一个'.format(direction))
self.displayGrids() self.displayGrids()

View File

@ -4,12 +4,13 @@
import os import os
import cPickle import cPickle
import csv import csv
import logging
import pandas import pandas
import copy import copy
from datetime import datetime, timedelta from datetime import datetime, timedelta
from ctaBase import * from ctaBase import *
from vnpy.trader.setup_logger import get_logger
class UtilArbTickLoader(object): class UtilArbTickLoader(object):
"""一个套利tick的数据加载工具类""" """一个套利tick的数据加载工具类"""
@ -23,14 +24,18 @@ class UtilArbTickLoader(object):
self.symbol = symbol self.symbol = symbol
self.logger = None
def writeCtaLog(self, content): def writeCtaLog(self, content):
"""记录日志""" """记录日志"""
# log = str(self.dt) + ' ' + content # log = str(self.dt) + ' ' + content
# self.logList.append(log) # self.logList.append(log)
# 写入本地log日志 # 写入本地log日志
logging.info(content) if self.logger:
self.logger.info(content)
else:
self.logger = get_logger()
def writeCtaError(self, content): def writeCtaError(self, content):
"""记录异常""" """记录异常"""
self.output(content) self.output(content)
@ -38,7 +43,7 @@ class UtilArbTickLoader(object):
def output(self, content): 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 # 先读取leg2的数据到目录以日期时间为key
leg2Ticks = {} 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((line.replace('\0',' ') for line in leg2CsvReadFile), delimiter=",")
reader = csv.DictReader(leg2CsvReadFile, delimiter=",") reader = csv.DictReader(leg2CsvReadFile, delimiter=",")
self.writeCtaLog(u'加载{0}'.format(leg2File)) self.writeCtaLog(u'加载{0}'.format(leg2File))
@ -118,7 +123,7 @@ class UtilArbTickLoader(object):
else: else:
leg2Ticks[dtStr] = tick 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((line.replace('\0',' ') for line in leg1CsvReadFile), delimiter=",")
reader = csv.DictReader(leg1CsvReadFile, delimiter=",") reader = csv.DictReader(leg1CsvReadFile, delimiter=",")
self.writeCtaLog(u'加载{0}'.format(leg1File)) self.writeCtaLog(u'加载{0}'.format(leg1File))

View File

@ -11,7 +11,7 @@ import os
import copy import copy
from collections import OrderedDict from collections import OrderedDict
from datetime import datetime, timedelta from datetime import datetime, timedelta
from Queue import Queue from queue import Queue
from threading import Thread from threading import Thread
from vnpy.trader.vtEvent import * from vnpy.trader.vtEvent import *

View File

@ -6,12 +6,12 @@
import json import json
from vnpy.trader.uiBasicWidget import QtGui, QtCore from vnpy.trader.uiBasicWidget import QtWidgets, QtGui, QtCore
from vnpy.trader.vtEvent import * 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): def __init__(self, drEngine, eventEngine, parent=None):
@ -55,40 +55,40 @@ class DrEngineManager(QtGui.QWidget):
self.setWindowTitle(u'行情数据记录工具') self.setWindowTitle(u'行情数据记录工具')
# 记录合约配置监控 # 记录合约配置监控
tickLabel = QtGui.QLabel(u'Tick记录') tickLabel = QtWidgets.QLabel(u'Tick记录')
self.tickTable = QtGui.QTableWidget() self.tickTable = QtWidgets.QTableWidget()
self.tickTable.setColumnCount(2) self.tickTable.setColumnCount(2)
self.tickTable.verticalHeader().setVisible(False) self.tickTable.verticalHeader().setVisible(False)
self.tickTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.tickTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
self.tickTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) self.tickTable.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
self.tickTable.setAlternatingRowColors(True) self.tickTable.setAlternatingRowColors(True)
self.tickTable.setHorizontalHeaderLabels([u'合约代码', u'接口']) self.tickTable.setHorizontalHeaderLabels([u'合约代码', u'接口'])
barLabel = QtGui.QLabel(u'Bar记录') barLabel = QtWidgets.QLabel(u'Bar记录')
self.barTable = QtGui.QTableWidget() self.barTable = QtWidgets.QTableWidget()
self.barTable.setColumnCount(2) self.barTable.setColumnCount(2)
self.barTable.verticalHeader().setVisible(False) self.barTable.verticalHeader().setVisible(False)
self.barTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.barTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
self.barTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) self.barTable.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
self.barTable.setAlternatingRowColors(True) self.barTable.setAlternatingRowColors(True)
self.barTable.setHorizontalHeaderLabels([u'合约代码', u'接口']) self.barTable.setHorizontalHeaderLabels([u'合约代码', u'接口'])
activeLabel = QtGui.QLabel(u'主力合约') activeLabel = QtWidgets.QLabel(u'主力合约')
self.activeTable = QtGui.QTableWidget() self.activeTable = QtWidgets.QTableWidget()
self.activeTable.setColumnCount(2) self.activeTable.setColumnCount(2)
self.activeTable.verticalHeader().setVisible(False) self.activeTable.verticalHeader().setVisible(False)
self.activeTable.setEditTriggers(QtGui.QTableWidget.NoEditTriggers) self.activeTable.setEditTriggers(QtWidgets.QTableWidget.NoEditTriggers)
self.activeTable.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) self.activeTable.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.Stretch)
self.activeTable.setAlternatingRowColors(True) self.activeTable.setAlternatingRowColors(True)
self.activeTable.setHorizontalHeaderLabels([u'主力代码', u'合约代码']) self.activeTable.setHorizontalHeaderLabels([u'主力代码', u'合约代码'])
# 日志监控 # 日志监控
self.logMonitor = QtGui.QTextEdit() self.logMonitor = QtWidgets.QTextEdit()
self.logMonitor.setReadOnly(True) self.logMonitor.setReadOnly(True)
self.logMonitor.setMinimumHeight(600) self.logMonitor.setMinimumHeight(600)
# 设置布局 # 设置布局
grid = QtGui.QGridLayout() grid = QtWidgets.QGridLayout()
grid.addWidget(tickLabel, 0, 0) grid.addWidget(tickLabel, 0, 0)
grid.addWidget(barLabel, 0, 1) grid.addWidget(barLabel, 0, 1)
@ -97,7 +97,7 @@ class DrEngineManager(QtGui.QWidget):
grid.addWidget(self.barTable, 1, 1) grid.addWidget(self.barTable, 1, 1)
grid.addWidget(self.activeTable, 1, 2) grid.addWidget(self.activeTable, 1, 2)
vbox = QtGui.QVBoxLayout() vbox = QtWidgets.QVBoxLayout()
vbox.addLayout(grid) vbox.addLayout(grid)
vbox.addWidget(self.logMonitor) vbox.addWidget(self.logMonitor)
self.setLayout(vbox) self.setLayout(vbox)

View 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()
# vtSymbolCF1705 symbolCF1705
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')

View File

@ -1,7 +1,7 @@
# encoding: UTF-8 # encoding: UTF-8
from rmEngine import RmEngine from vnpy.trader.app.riskManager.rmEngine import RmEngine
from uiRmWidget import RmEngineManager from vnpy.trader.app.riskManager.uiRmWidget import RmEngineManager
appName = 'RiskManager' appName = 'RiskManager'
appDisplayName = u'风险管理' appDisplayName = u'风险管理'

View File

@ -0,0 +1,4 @@
{
"repAddress": "tcp://*:2014",
"pubAddress": "tcp://*:0602"
}

View 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'

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

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

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

View File

@ -284,7 +284,7 @@ class StModeComboBox(QtWidgets.QComboBox):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def setMode(self): def setMode(self):
"""设置模式""" """设置模式"""
mode = unicode(self.currentText()) mode = self.currentText()
self.algoEngine.setAlgoMode(self.spreadName, mode) self.algoEngine.setAlgoMode(self.spreadName, mode)
#---------------------------------------------------------------------- #----------------------------------------------------------------------

View File

@ -6,7 +6,6 @@ import sys
import ctypes import ctypes
from datetime import datetime, timedelta, date from datetime import datetime, timedelta, date
from time import sleep from time import sleep
from threading import Thread
# 将repostory的目录i作为根目录添加到系统环境中。 # 将repostory的目录i作为根目录添加到系统环境中。
ROOT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..','..')) ROOT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..','..'))
@ -48,7 +47,7 @@ class NoUiMain(object):
ee = EventEngine2() ee = EventEngine2()
# 实例化 主引擎 # 实例化 主引擎
print u'instance mainengine' print(u'instance mainengine')
self.mainEngine = MainEngine(ee) self.mainEngine = MainEngine(ee)
self.mainEngine.addGateway(ctpGateway, self.gateway_name) self.mainEngine.addGateway(ctpGateway, self.gateway_name)
@ -58,7 +57,6 @@ class NoUiMain(object):
self.mainEngine.addApp(riskManager) self.mainEngine.addApp(riskManager)
def trade_off(self): def trade_off(self):
"""检查现在是否为非交易时间""" """检查现在是否为非交易时间"""
now = datetime.now() now = datetime.now()
@ -87,7 +85,7 @@ class NoUiMain(object):
dt = datetime.now() dt = datetime.now()
if dt.hour != self.last_dt.hour: if dt.hour != self.last_dt.hour:
self.last_dt = dt 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)) self.mainEngine.writeLog( u'noUiMain.py checkpoint:{0}'.format(dt))
# 定时断开 # 定时断开
@ -131,20 +129,20 @@ class NoUiMain(object):
#self.mainEngine.dbConnect() #self.mainEngine.dbConnect()
# 加载cta的配置 # 加载cta的配置
print u'load cta setting' print(u'load cta setting')
self.mainEngine.ctaEngine.loadSetting() self.mainEngine.ctaEngine.loadSetting()
print u'initialize all strategies' print(u'initialize all strategies')
# 初始化策略,如果多个,则需要逐一初始化多个 # 初始化策略,如果多个,则需要逐一初始化多个
for s in self.strategies: for s in self.strategies:
print 'init trategy {0}'.format(s) print( 'init trategy {0}'.format(s))
self.mainEngine.ctaEngine.initStrategy(s) self.mainEngine.ctaEngine.initStrategy(s)
# 逐一启动策略 # 逐一启动策略
print 'start strategy {0}'.format(s) print( 'start strategy {0}'.format(s))
self.mainEngine.ctaEngine.startStrategy(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.mainEngine.connect(self.gateway_name)
self.connected = True 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__)), log_file_name = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),
'logs', u'noUiMain.log')) 'logs', u'noUiMain.log'))
except Exception as ex: 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')) log_file_name = os.path.abspath(os.path.join(os.getcwd(), 'logs', u'noUiMain.log'))
setup_logger(filename=log_file_name, debug=False) setup_logger(filename=log_file_name, debug=False)

View File

@ -35,14 +35,14 @@ def _check_gpid(gpid):
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
returncode = p.wait() returncode = p.wait()
except OSError as e: except OSError as e:
print 'cant not find shell command ps' print('cant not find shell command ps')
exit(1) exit(1)
try: try:
p2 = subprocess.Popen("uniq", stdin=p.stdout, stdout=subprocess.PIPE, p2 = subprocess.Popen("uniq", stdin=p.stdout, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=False) stderr=subprocess.PIPE, shell=False)
returncode = p2.wait() returncode = p2.wait()
except OSError as e: except OSError as e:
print 'cant not find shell command uniq' print( 'cant not find shell command uniq')
exit(1) exit(1)
for i in p2.stdout.readlines(): for i in p2.stdout.readlines():
if i.decode().strip() == gpid: if i.decode().strip() == gpid:
@ -115,47 +115,47 @@ def _start():
gpid = _status() gpid = _status()
if _check_stop_time(): if _check_stop_time():
if gpid: 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 import signal
# 杀死进程组 # 杀死进程组
os.killpg(int(gpid), signal.SIGKILL) os.killpg(int(gpid), signal.SIGKILL)
while _status(): while _status():
time.sleep(1) time.sleep(1)
print 'already stop the service[gpid={}]'.format(gpid) print( 'already stop the service[gpid={}]'.format(gpid))
try: try:
sendmail.sendmail(subject='{0} killed by service.py'.format(ctp_gateway_name), sendmail.sendmail(subject='{0} killed by service.py'.format(ctp_gateway_name),
msgcontent='already stop the service[gpid={}]'.format(gpid)) msgcontent='already stop the service[gpid={}]'.format(gpid))
except: except:
pass pass
else: 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: else:
if not gpid: 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) os.popen(program_command)
while True: while True:
gpid = _status() gpid = _status()
if gpid: if gpid:
break break
time.sleep(1) time.sleep(1)
print 'already start the service[gpid={}]'.format(gpid) print( 'already start the service[gpid={}]'.format(gpid))
else: 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(): def schedule():
print '======schedule========' print( '======schedule========')
_start() _start()
def status(): def status():
print '======status========' print( '======status========')
gpid = _status() gpid = _status()
if gpid: if gpid:
print 'the service[gpid={}] is running...'.format(gpid) print( 'the service[gpid={}] is running...'.format(gpid))
else: else:
print 'the service is not running...' print( 'the service is not running...')
# operate的可选字符串为add, del # operate的可选字符串为add, del
def operate_crontab(operate): def operate_crontab(operate):
@ -178,7 +178,7 @@ def operate_crontab(operate):
# 追加方式比上面好,能自动判断上行是否有回车 # 追加方式比上面好,能自动判断上行是否有回车
os.popen('echo "{}" >> {}'.format(cron_content, tmp_cron_file)) 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)) os.popen("crontab {}".format(tmp_cron_file))
if operate == "del" and exist_flag: if operate == "del" and exist_flag:
@ -186,16 +186,16 @@ def operate_crontab(operate):
f.writelines(remain_cron_list) f.writelines(remain_cron_list)
os.popen("crontab {}".format(tmp_cron_file)) 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) # os.remove(tmp_cron_file)
def start(): def start():
print '======start========' print( '======start========')
operate_crontab("add") operate_crontab("add")
_start() _start()
print 'start service done!!!' print( 'start service done!!!')
def _stop(): def _stop():
@ -207,26 +207,26 @@ def _stop():
os.killpg(int(gpid), signal.SIGKILL) os.killpg(int(gpid), signal.SIGKILL)
while _status(): while _status():
time.sleep(1) time.sleep(1)
print 'already stop the service[gpid={}]'.format(gpid) print( 'already stop the service[gpid={}]'.format(gpid))
try: try:
sendmail.sendmail(subject='{0} stopped by service.py'.format(ctp_gateway_name),msgcontent= 'already stop the service[gpid={}]'.format(gpid)) sendmail.sendmail(subject='{0} stopped by service.py'.format(ctp_gateway_name),msgcontent= 'already stop the service[gpid={}]'.format(gpid))
except: except:
pass pass
else: else:
print 'the service is not running...' print( 'the service is not running...')
def stop(): def stop():
print '======stop========' print('======stop========')
_stop() _stop()
print 'stop service done!!!' print( 'stop service done!!!')
def restart(): def restart():
print '======restart========' print( '======restart========')
_stop() _stop()
_start() _start()
print 'restart service done!!!' print('restart service done!!!')
if __name__ == '__main__': if __name__ == '__main__':
@ -245,4 +245,4 @@ if __name__ == '__main__':
elif fun == 'schedule': elif fun == 'schedule':
schedule() schedule()
else: else:
print 'Usage: {} (status|start|stop|restart)'.format(os.path.basename(__file__)) print( 'Usage: {} (status|start|stop|restart)'.format(os.path.basename(__file__)))

View File

@ -252,8 +252,8 @@ class MultiprocessHandler(logging.FileHandler):
if not os.path.exists(_dir): if not os.path.exists(_dir):
os.makedirs(_dir) os.makedirs(_dir)
except Exception: except Exception:
print u"创建文件夹失败" print( u"创建文件夹失败")
print u"文件夹路径:" + self.filePath print( u"文件夹路径:" + self.filePath)
pass pass
if codecs is None: if codecs is None:
@ -299,9 +299,9 @@ class MultiprocessHandler(logging.FileHandler):
self.stream = self._open() self.stream = self._open()
#删除多于保留个数的所有日志文件 #删除多于保留个数的所有日志文件
if self.backupCount > 0: if self.backupCount > 0:
print '删除日志' print('删除日志')
for s in self.getFilesToDelete(): for s in self.getFilesToDelete():
print s print(s)
os.remove(s) os.remove(s)
def getFilesToDelete(self): def getFilesToDelete(self):
@ -371,12 +371,12 @@ def setup_logger(filename, name=None, debug=False):
name = names[-1] name = names[-1]
_logger = logging.getLogger(name) _logger = logging.getLogger(name)
#logger.setLevel(logging.DEBUG) if debug:
#stream_handler = logging.StreamHandler(sys.stdout) _logger.setLevel(logging.DEBUG)
#stream_handler.setLevel(logging.DEBUG) stream_handler = logging.StreamHandler(sys.stdout)
#stream_handler.setFormatter(fmt) stream_handler.setLevel(logging.DEBUG)
stream_handler.setFormatter(fmt)
#_logger = multiprocessing.get_logger() _logger.addHandler(stream_handler)
_fileHandler = MultiprocessHandler(filename, when='D') _fileHandler = MultiprocessHandler(filename, when='D')
if debug: if debug:
@ -384,7 +384,7 @@ def setup_logger(filename, name=None, debug=False):
else: else:
_fileHandler.setLevel(logging.INFO) _fileHandler.setLevel(logging.INFO)
_fileHandler.setFormatter(fmt) _fileHandler.setFormatter(fmt)
#_logger.addHandler(stream_handler)
_logger.addHandler(_fileHandler) _logger.addHandler(_fileHandler)
if debug: if debug:

View File

@ -5,11 +5,12 @@ import csv
import os import os
import platform import platform
from collections import OrderedDict from collections import OrderedDict
import traceback
from vnpy.trader.vtEvent import * from vnpy.trader.vtEvent import *
from vnpy.trader.vtFunction import * from vnpy.trader.vtFunction import *
from vnpy.trader.vtGateway 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 from vnpy.trader.uiQt import QtWidgets, QtGui, QtCore, BASIC_FONT
if str(platform.system()) == 'Windows': 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): if text == '0' or text == '0.0' or type(text) == type(None):
self.setText('') self.setText('')
#elif type(text) == type(float):
# self.setText(str(text))
else: else:
self.setText(text) self.setText(str(text))
######################################################################## ########################################################################
@ -131,7 +134,7 @@ class BidCell(QtWidgets.QTableWidgetItem):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def setContent(self, text): def setContent(self, text):
"""设置内容""" """设置内容"""
self.setText(text) self.setText(str(text))
######################################################################## ########################################################################
@ -153,7 +156,7 @@ class AskCell(QtWidgets.QTableWidgetItem):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def setContent(self, text): def setContent(self, text):
"""设置内容""" """设置内容"""
self.setText(text) self.setText(str(text))
######################################################################## ########################################################################
class PnlCell(QtWidgets.QTableWidgetItem): class PnlCell(QtWidgets.QTableWidgetItem):
@ -283,10 +286,14 @@ class BasicMonitor(QtWidgets.QTableWidget):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def updateEvent(self, event): def updateEvent(self, event):
"""收到事件更新""" """收到事件更新"""
data = event.dict_['data'] try:
self.updateData(data) data = event.dict_['data']
self.updateData(data)
except Exception as ex:
print(ex)
traceback.print_exc()
#---------------------------------------------------------------------- # ----------------------------------------------------------------------
def updateData(self, data): def updateData(self, data):
"""将数据更新到表格中""" """将数据更新到表格中"""
# 如果允许了排序功能,则插入数据前必须关闭,否则插入新的数据会变乱 # 如果允许了排序功能,则插入数据前必须关闭,否则插入新的数据会变乱
@ -376,11 +383,11 @@ class BasicMonitor(QtWidgets.QTableWidget):
try: try:
if not os.path.exists(path): if not os.path.exists(path):
with open(unicode(path), 'wb') as f: with open(path, 'wb') as f:
writer = csv.writer(f) writer = csv.writer(f)
# 保存标签 # 保存标签
headers = [header.encode('gbk') for header in self.headerList] headers = [header for header in self.headerList]
writer.writerow(headers) writer.writerow(headers)
# 保存每行内容 # 保存每行内容
@ -389,8 +396,7 @@ class BasicMonitor(QtWidgets.QTableWidget):
for column in range(self.columnCount()): for column in range(self.columnCount()):
item = self.item(row, column) item = self.item(row, column)
if item is not None: if item is not None:
rowdata.append( rowdata.append(item.text())
unicode(item.text()).encode('gbk'))
else: else:
rowdata.append('') rowdata.append('')
writer.writerow(rowdata) writer.writerow(rowdata)
@ -940,10 +946,10 @@ class TradingWidget(QtWidgets.QFrame):
"""合约变化""" """合约变化"""
# 读取组件数据 # 读取组件数据
symbol = str(self.lineSymbol.text()) symbol = str(self.lineSymbol.text())
exchange = unicode(self.comboExchange.currentText()) exchange = self.comboExchange.currentText()
currency = unicode(self.comboCurrency.currentText()) currency = self.comboCurrency.currentText()
productClass = unicode(self.comboProductClass.currentText()) productClass = self.comboProductClass.currentText()
gatewayName = unicode(self.comboGateway.currentText()) gatewayName = self.comboGateway.currentText()
# 查询合约 # 查询合约
if exchange: if exchange:
@ -1014,33 +1020,33 @@ class TradingWidget(QtWidgets.QFrame):
if tick.vtSymbol == self.symbol: if tick.vtSymbol == self.symbol:
if not self.checkFixed.isChecked(): if not self.checkFixed.isChecked():
self.spinPrice.setValue(tick.lastPrice) self.spinPrice.setValue(tick.lastPrice)
self.labelBidPrice1.setText(str(tick.bidPrice1)) self.labelBidPrice1.setText('{}'.format(tick.bidPrice1))
self.labelAskPrice1.setText(str(tick.askPrice1)) self.labelAskPrice1.setText('{}'.format(tick.askPrice1))
self.labelBidVolume1.setText(str(tick.bidVolume1)) self.labelBidVolume1.setText('{}'.format(tick.bidVolume1))
self.labelAskVolume1.setText(str(tick.askVolume1)) self.labelAskVolume1.setText('{}'.format(tick.askVolume1))
if tick.bidPrice2: if tick.bidPrice2:
self.labelBidPrice2.setText(str(tick.bidPrice2)) self.labelBidPrice2.setText('{}'.format(tick.bidPrice2))
self.labelBidPrice3.setText(str(tick.bidPrice3)) self.labelBidPrice3.setText('{}'.format(tick.bidPrice3))
self.labelBidPrice4.setText(str(tick.bidPrice4)) self.labelBidPrice4.setText('{}'.format(tick.bidPrice4))
self.labelBidPrice5.setText(str(tick.bidPrice5)) self.labelBidPrice5.setText('{}'.format(tick.bidPrice5))
self.labelAskPrice2.setText(str(tick.askPrice2)) self.labelAskPrice2.setText('{}'.format(tick.askPrice2))
self.labelAskPrice3.setText(str(tick.askPrice3)) self.labelAskPrice3.setText('{}'.format(tick.askPrice3))
self.labelAskPrice4.setText(str(tick.askPrice4)) self.labelAskPrice4.setText('{}'.format(tick.askPrice4))
self.labelAskPrice5.setText(str(tick.askPrice5)) self.labelAskPrice5.setText('{}'.format(tick.askPrice5))
self.labelBidVolume2.setText(str(tick.bidVolume2)) self.labelBidVolume2.setText('{}'.format(tick.bidVolume2))
self.labelBidVolume3.setText(str(tick.bidVolume3)) self.labelBidVolume3.setText('{}'.format(tick.bidVolume3))
self.labelBidVolume4.setText(str(tick.bidVolume4)) self.labelBidVolume4.setText('{}'.format(tick.bidVolume4))
self.labelBidVolume5.setText(str(tick.bidVolume5)) self.labelBidVolume5.setText('{}'.format(tick.bidVolume5))
self.labelAskVolume2.setText(str(tick.askVolume2)) self.labelAskVolume2.setText('{}'.format(tick.askVolume2))
self.labelAskVolume3.setText(str(tick.askVolume3)) self.labelAskVolume3.setText('{}'.format(tick.askVolume3))
self.labelAskVolume4.setText(str(tick.askVolume4)) self.labelAskVolume4.setText('{}'.format(tick.askVolume4))
self.labelAskVolume5.setText(str(tick.askVolume5)) self.labelAskVolume5.setText('{}'.format(tick.askVolume5))
self.labelLastPrice.setText(str(tick.lastPrice)) self.labelLastPrice.setText('{}'.format(tick.lastPrice))
if tick.preClosePrice: if tick.preClosePrice:
rt = (tick.lastPrice/tick.preClosePrice)-1 rt = (tick.lastPrice/tick.preClosePrice)-1
@ -1057,10 +1063,10 @@ class TradingWidget(QtWidgets.QFrame):
def sendOrder(self): def sendOrder(self):
"""发单""" """发单"""
symbol = str(self.lineSymbol.text()) symbol = str(self.lineSymbol.text())
exchange = unicode(self.comboExchange.currentText()) exchange = self.comboExchange.currentText()
currency = unicode(self.comboCurrency.currentText()) currency = self.comboCurrency.currentText()
productClass = unicode(self.comboProductClass.currentText()) productClass = self.comboProductClass.currentText()
gatewayName = unicode(self.comboGateway.currentText()) gatewayName = self.comboGateway.currentText()
# 查询合约 # 查询合约
if exchange: if exchange:
@ -1080,9 +1086,9 @@ class TradingWidget(QtWidgets.QFrame):
req.exchange = exchange req.exchange = exchange
req.price = self.spinPrice.value() req.price = self.spinPrice.value()
req.volume = self.spinVolume.value() req.volume = self.spinVolume.value()
req.direction = unicode(self.comboDirection.currentText()) req.direction = self.comboDirection.currentText()
req.priceType = unicode(self.comboPriceType.currentText()) req.priceType = self.comboPriceType.currentText()
req.offset = unicode(self.comboOffset.currentText()) req.offset = self.comboOffset.currentText()
req.currency = currency req.currency = currency
req.productClass = productClass req.productClass = productClass
@ -1353,12 +1359,12 @@ class SettingEditor(QtWidgets.QWidget):
filePath = jsonPathDict[self.currentFileName] filePath = jsonPathDict[self.currentFileName]
self.labelPath.setText(filePath) self.labelPath.setText(filePath)
with open(filePath) as f: with open(filePath,'rb',encoding='utf8') as f:
self.editSetting.clear() self.editSetting.clear()
for line in f: for line in f:
line = line.replace('\n', '') # 移除换行符号 line = line.replace('\n', '') # 移除换行符号
line = line.decode('UTF-8') #line = line.decode('UTF-8')
self.editSetting.append(line) self.editSetting.append(line)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
@ -1369,9 +1375,9 @@ class SettingEditor(QtWidgets.QWidget):
filePath = jsonPathDict[self.currentFileName] filePath = jsonPathDict[self.currentFileName]
with open(filePath, 'w') as f: with open(filePath, 'wb', encoding='utf8') as f:
content = self.editSetting.toPlainText() content = self.editSetting.toPlainText()
content = content.encode('UTF-8') #content = content.encode('UTF-8')
f.write(content) f.write(content)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------

View File

@ -3,7 +3,7 @@ import sys
# from uiFullMonitorWidget import MonitorWidget # from uiFullMonitorWidget import MonitorWidget
# from uiKChartWidget import CandleForm # from uiKChartWidget import CandleForm
print 'load uiMainWindows.py' print('load uiMainWindows.py')
import psutil import psutil
import traceback import traceback
@ -293,7 +293,7 @@ class MainWindow(QtWidgets.QMainWindow):
try: try:
r = self.mainEngine.connect(gatewayName) r = self.mainEngine.connect(gatewayName)
except: except:
print "Unexpected error:", sys.exc_info()[0] print( "Unexpected error:", sys.exc_info()[0])
traceback.print_exc() traceback.print_exc()
if r: if r:
@ -334,7 +334,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.widgetDict[appName] = appDetail['appWidget'](appEngine, self.eventEngine) self.widgetDict[appName] = appDetail['appWidget'](appEngine, self.eventEngine)
self.widgetDict[appName].show() self.widgetDict[appName].show()
except: except:
print "Unexpected error:", sys.exc_info()[0] print( "Unexpected error:", sys.exc_info()[0])
traceback.print_exc() traceback.print_exc()
return openAppFunction return openAppFunction
@ -365,7 +365,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.widgetDict['contractM'] = ContractMonitor(self.mainEngine) self.widgetDict['contractM'] = ContractMonitor(self.mainEngine)
self.widgetDict['contractM'].show() self.widgetDict['contractM'].show()
except : except :
print "Unexpected error:", sys.exc_info()[0] print( "Unexpected error:", sys.exc_info()[0])
traceback.print_exc() traceback.print_exc()
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
@ -378,7 +378,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.widgetDict['settingEditor'] = SettingEditor(self.mainEngine) self.widgetDict['settingEditor'] = SettingEditor(self.mainEngine)
self.widgetDict['settingEditor'].show() self.widgetDict['settingEditor'].show()
except : except :
print "Unexpected error:", sys.exc_info()[0] print( "Unexpected error:", sys.exc_info()[0])
traceback.print_exc() traceback.print_exc()
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
@ -390,14 +390,14 @@ class MainWindow(QtWidgets.QMainWindow):
try: try:
if self.mainEngine.ctaEngine is None: if self.mainEngine.ctaEngine is None:
print u'not init Cta Engine' print( u'not init Cta Engine')
return return
from vnpy.trader.app.ctaStrategy.uiSpreadTrade import SpreadTradeManager from vnpy.trader.app.ctaStrategy.uiSpreadTrade import SpreadTradeManager
self.widgetDict['spread'] = SpreadTradeManager(self.mainEngine.ctaEngine, self.eventEngine) self.widgetDict['spread'] = SpreadTradeManager(self.mainEngine.ctaEngine, self.eventEngine)
self.widgetDict['spread'].show() self.widgetDict['spread'].show()
except Exception as ex: except Exception as ex:
print "Unexpected error:", sys.exc_info()[0] print( "Unexpected error:", sys.exc_info()[0])
traceback.print_exc() traceback.print_exc()
return return

View File

@ -27,7 +27,7 @@ def createQApp():
import qdarkstyle import qdarkstyle
qApp.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) qApp.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
except : except :
print "Unexpected error when import darkStyle:", sys.exc_info()[0] print( "Unexpected error when import darkStyle:", sys.exc_info()[0])
# 设置Windows底部任务栏图标 # 设置Windows底部任务栏图标
if 'Windows' in platform.uname(): if 'Windows' in platform.uname():

View File

@ -21,14 +21,14 @@ def _check_gpid(gpid):
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
returncode = p.wait() returncode = p.wait()
except OSError as e: except OSError as e:
print u'can not find shell command ps' print( u'can not find shell command ps')
exit(1) exit(1)
try: try:
p2 = subprocess.Popen("uniq", stdin=p.stdout, stdout=subprocess.PIPE, p2 = subprocess.Popen("uniq", stdin=p.stdout, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=False) stderr=subprocess.PIPE, shell=False)
returncode = p2.wait() returncode = p2.wait()
except OSError as e: except OSError as e:
print u'can not find shell command uniq' print(u'can not find shell command uniq')
exit(1) exit(1)
for i in p2.stdout.readlines(): for i in p2.stdout.readlines():
if i.decode().strip() == gpid: if i.decode().strip() == gpid:
@ -46,7 +46,7 @@ def _status():
return None return None
if _status(): if _status():
print u'another service is already running...' print( u'another service is already running...')
exit(0) exit(0)
def _save_gpid(): def _save_gpid():
@ -56,7 +56,7 @@ def _save_gpid():
gpid = os.getpid() gpid = os.getpid()
else: # unix else: # unix
gpid = os.getpgrp() gpid = os.getpgrp()
print 'gpid={}'.format(gpid) print( 'gpid={}'.format(gpid))
with open(gpid_file, 'w') as f: with open(gpid_file, 'w') as f:
f.write(str(gpid)) f.write(str(gpid))

View File

@ -72,18 +72,18 @@ class BasicMonitor(object):
s = [] s = []
for header, value in self.headerDict.items(): for header, value in self.headerDict.items():
v = getattr(data, header) v = getattr(data, header)
if isinstance(v, basestring) and not isinstance(v, unicode): #if isinstance(v, basestring) and not isinstance(v, unicode):
try: # try:
v = v.decode('gbk') # v = v.decode('gbk')
except: # except:
v = v.decode('utf8') # v = v.decode('utf8')
s.append('%s: %s' % (value['chinese'], v)) s.append('%s: %s' % (value['chinese'], v))
if self.logger is not None: if self.logger is not None:
self.logger.info(' '.join(s)) self.logger.info(' '.join(s))
def createLogger(self, monitor_name): def createLogger(self, monitor_name):
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), 'logs', 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) self.logger = setup_logger(filename=filename, name=monitor_name)
######################################################################## ########################################################################

View File

@ -1,6 +1,6 @@
# encoding: utf-8 # encoding: utf-8
print 'load vtClient.py' print('load vtClient.py')
import ctypes import ctypes
import platform import platform
import sys import sys
@ -9,7 +9,7 @@ from vnpy.rpc import RpcClient
from vnpy.trader.app.ctaStrategy.ctaEngine import CtaEngine from vnpy.trader.app.ctaStrategy.ctaEngine import CtaEngine
from vnpy.trader.app.dataRecorder.drEngine import DrEngine from vnpy.trader.app.dataRecorder.drEngine import DrEngine
from vnpy.trader.app.riskManager.rmEngine import RmEngine from vnpy.trader.app.riskManager.rmEngine import RmEngine
from uiMainWindow import * from vnpy.trader.uiMainWindow import *
# 文件路径名 # 文件路径名
path = os.path.abspath(os.path.dirname(__file__)) path = os.path.abspath(os.path.dirname(__file__))

View File

@ -1,6 +1,6 @@
# encoding: UTF-8 # encoding: UTF-8
print 'laod vtConstant.py' print('laod vtConstant.py')
# 默认空值 # 默认空值
EMPTY_STRING = '' EMPTY_STRING = ''

View File

@ -1,6 +1,6 @@
# encoding: UTF-8 # encoding: UTF-8
print 'load vtEngine.py' print( 'load vtEngine.py')
import shelve import shelve
from collections import OrderedDict from collections import OrderedDict
@ -273,8 +273,9 @@ class MainEngine(object):
return True return True
except Exception as ex: except Exception as ex:
print u'vtEngine.disconnect Exception:{0} '.format(str(ex)) print( u'vtEngine.disconnect Exception:{0} '.format(str(ex)))
return False return False
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def writeLog(self, content): def writeLog(self, content):
"""快速发出日志事件""" """快速发出日志事件"""
@ -292,7 +293,7 @@ class MainEngine(object):
def createLogger(self): def createLogger(self):
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), 'logs', 'vnpy')) 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) self.logger = setup_logger(filename=filename, name='vnpy', debug=True)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
@ -308,8 +309,9 @@ class MainEngine(object):
if self.logger is not None: if self.logger is not None:
self.logger.error(content) self.logger.error(content)
else: else:
print content print(content)
self.createLogger() self.createLogger()
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
def writeWarning(self, content): def writeWarning(self, content):
"""快速发出告警日志事件""" """快速发出告警日志事件"""
@ -323,7 +325,7 @@ class MainEngine(object):
if self.logger is not None: if self.logger is not None:
self.logger.warning(content) self.logger.warning(content)
else: else:
print content print( content)
self.createLogger() self.createLogger()
# 发出邮件 # 发出邮件
@ -361,7 +363,7 @@ class MainEngine(object):
if self.logger: if self.logger:
self.logger.critical(content) self.logger.critical(content)
else: else:
print content print( content)
self.createLogger() self.createLogger()
# 发出邮件 # 发出邮件

View File

@ -10,7 +10,7 @@
建议将所有的常量定义放在该文件中便于检查是否存在重复的现象 建议将所有的常量定义放在该文件中便于检查是否存在重复的现象
''' '''
print 'load vtEvent.py' print( 'load vtEvent.py')
# 导入基础模块vnpy.event.EventEngine等 # 导入基础模块vnpy.event.EventEngine等
from vnpy.event import * from vnpy.event import *

View File

@ -26,7 +26,7 @@ def safeUnicode(value):
if abs(d.as_tuple().exponent) > MAX_DECIMAL: if abs(d.as_tuple().exponent) > MAX_DECIMAL:
value = round(value, ndigits=MAX_DECIMAL) value = round(value, ndigits=MAX_DECIMAL)
return unicode(value) return value
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def loadMongoSetting(): def loadMongoSetting():

View File

@ -119,7 +119,7 @@ class VtGateway(object):
def createLogger(self): def createLogger(self):
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), 'logs', 'Gateway')) 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) self.logger = setup_logger(filename=filename, name='vnpy', debug=True)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------

View File

@ -3,7 +3,7 @@
""" """
通过VT_setting.json加载全局配置 通过VT_setting.json加载全局配置
""" """
print 'load vtGlobal.py' print('load vtGlobal.py')
import os import os
import traceback import traceback
import json import json
@ -15,7 +15,7 @@ path = os.path.abspath(os.path.dirname(__file__))
settingFileName = os.path.join(path, settingFileName) settingFileName = os.path.join(path, settingFileName)
try: try:
f = file(settingFileName) with open(settingFileName,'r',encoding="utf8") as f:
globalSetting = json.load(f) globalSetting = json.load(f)
except: except:
traceback.print_exc() traceback.print_exc()

View File

@ -3,8 +3,8 @@
# 重载sys模块设置默认字符串编码方式为utf8 # 重载sys模块设置默认字符串编码方式为utf8
import sys import sys
reload(sys) #reload(sys)
sys.setdefaultencoding('utf8') #sys.setdefaultencoding('utf8')
import sys import sys
import os import os
@ -23,7 +23,7 @@ from vnpy.trader.uiMainWindow import *
# 加载底层接口 # 加载底层接口
from vnpy.trader.gateway import ctpGateway from vnpy.trader.gateway import ctpGateway
# 初始化的接口模块,以及其指定的名称,CTP是模块value是该模块下的多个连接配置文件,如 CTP_JR_connect.json 'CTP_Prod', 'CTP_JR', , 'CTP_JK', 'CTP_02' # 初始化的接口模块,以及其指定的名称,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) from vnpy.trader.app import (ctaStrategy, riskManager, spreadTrading)
@ -53,7 +53,7 @@ def main():
# 添加Gatway # 添加Gatway
for gw_name in init_gateway_names['CTP']: 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) mainEngine.addGateway(ctpGateway, gw_name)
# 添加应用 # 添加应用
@ -63,9 +63,12 @@ def main():
mainWindow = MainWindow(mainEngine, ee) mainWindow = MainWindow(mainEngine, ee)
mainWindow.showMaximized() mainWindow.showMaximized()
# 在主线程中启动Qt事件循环 # 在主线程中启动Qt事件循环
sys.exit(qApp.exec_()) sys.exit(qApp.exec_())
if __name__ == '__main__': if __name__ == '__main__':
main() try:
main()
except Exception as ex:
print(str(ex))
traceback.print_exc()

View File

@ -37,7 +37,7 @@ class VtServer(RpcServer):
self.engine = MainEngine() self.engine = MainEngine()
for gw_name in init_gateway_names['CTP']: 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) self.engine.addGateway(ctpGateway, gw_name)
# 注册主引擎的方法到服务器的RPC函数 # 注册主引擎的方法到服务器的RPC函数
@ -84,7 +84,7 @@ class VtServer(RpcServer):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def printLog(content): def printLog(content):
"""打印日志""" """打印日志"""
print datetime.now().strftime("%H:%M:%S"), '\t', content print( datetime.now().strftime("%H:%M:%S"), '\t', content)
#---------------------------------------------------------------------- #----------------------------------------------------------------------

View File

@ -1,6 +1,6 @@
# encoding: UTF-8 # encoding: UTF-8
from language import text from vnpy.trader.language import text
# 将常量定义添加到vtText.py的局部字典中 # 将常量定义添加到vtText.py的局部字典中
d = locals() d = locals()