Merge remote-tracking branch 'refs/remotes/vnpy/master'

Conflicts:
	.gitignore
	vn.trader/CTP_connect.json
	vn.trader/ContractData.vt
	vn.trader/LTS_connect.json
	vn.trader/ctaEngine.py
	vn.trader/ctaStrategies.py
	vn.trader/ctaStrategyTemplate.py
	vn.trader/ctpGateway.py
	vn.trader/ltsGateway.py
	vn.trader/uiBasicWidget.py
	vn.trader/uiCtaWidget.py
	vn.trader/uiMainWindow.py
	vn.trader/vtConstant.py
	vn.trader/vtEngine.py
	vn.trader/vtGateway.py
This commit is contained in:
msincenselee 2015-10-19 17:05:00 +08:00
parent 8b5d27f46c
commit 676c4c6d40
24 changed files with 1524 additions and 11 deletions

15
.gitignore vendored
View File

@ -37,8 +37,23 @@ Release/
# 其他文件
*.dump
*.vssettings
<<<<<<< HEAD
vnpy.pyproj.user
.idea/workspace.xml
.idea/.name
.idea/vnpy.iml
*.xml
=======
<<<<<<< HEAD
# 不想同步的
*.local
=======
vn.ctp/build/*
vn.lts/build/*
.idea
>>>>>>> 65aac25731772259bf2d4049e7adbe92750ea01d
>>>>>>> refs/remotes/vnpy/master
*.json
*.json
*.json

74
vn.ctp/CMakeLists.txt Normal file
View File

@ -0,0 +1,74 @@
cmake_minimum_required(VERSION 2.8)
project(vn_ctp_api)
set(CMAKE_BUILD_TYPE "Release")
if (CMAKE_COMPILER_IS_GNUC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++11")
endif ()
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
option(USE_64BITS "comiple 64bits" ON)
if (USE_64BITS)
add_definitions(-DUSE_64BITS)
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
endif()
set(CTPAPI_PATH ctpapi)
include_directories(${CTPAPI_PATH})
set(CTPAPI_LIBRARY )
find_library(CTPAPI_MD_LIBRARY
NAMES thostmduserapi
PATHS ${CTPAPI_PATH})
find_library(CTPAPI_TD_LIBRARY
NAMES thosttraderapi
PATHS ${CTPAPI_PATH})
set (vnctpmd )
set (vnctptd )
option(BUILD_CTP_MD "build ctp md" ON)
if (BUILD_CTP_MD)
add_definitions(-DBUILD_CTP_MD)
set(CTP_MD_PATH vnctpmd/vnctpmd)
include_directories(CTP_MD_PATH)
set(VN_CTP_MD_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/vnctpmd/vnctpmd/vnctpmd.cpp)
add_library(vnctpmd SHARED ${VN_CTP_MD_SOURCE})
endif()
option(BUILD_CTP_TD "build ctp td" ON)
if (BUILD_CTP_TD)
add_definitions(-DBUILD_CTP_MD)
set(CTP_TD_PATH vnctptd/vnctptd)
include_directories(CTP_TD_PATH)
set(VN_CTP_TD_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/vnctptd/vnctptd/vnctptd.cpp)
add_library(vnctptd SHARED ${VN_CTP_TD_SOURCE})
endif()
set(PYTHON_INCLUDE_PATH C:/Python27/include)
set(PYTHON_LIBRARY )
find_library(PYTHON_LIBRARY
NAMES python27
PATHS C:/Python27/libs)
include_directories(${PYTHON_INCLUDE_PATH})
# boostanaconda
set(Boost_USE_STATIC_LIBS ON) #boost
set(Boost_USE_MULTITHREADED ON)
find_package(Boost 1.57.0 COMPONENTS python thread date_time system chrono REQUIRED) # boost否者message(${Boost_LIBRARIES})
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
endif()
target_link_libraries(vnctpmd ${Boost_LIBRARIES} ${PYTHON_LIBRARY} ${CTPAPI_MD_LIBRARY})
set(MD_DLL "${LIBRARY_OUTPUT_PATH}/Release/vnctpmd.dll")
if (EXISTS ${MD_DLL})
file(RENAME ${MD_DLL} ${LIBRARY_OUTPUT_PATH}/Release/vnctpmd.pyd)
endif()
target_link_libraries(vnctptd ${Boost_LIBRARIES} ${PYTHON_LIBRARY} ${CTPAPI_TD_LIBRARY})
set(TD_DLL ${LIBRARY_OUTPUT_PATH}/Release/vnctptd.dll)
if (EXISTS ${TD_DLL})
file(RENAME ${TD_DLL} ${LIBRARY_OUTPUT_PATH}/Release/vnctptd.pyd)
endif()

30
vn.ctp/readme.md Normal file
View File

@ -0,0 +1,30 @@
# 本目录的作用是编译CTP库
---------------------
# 目录说明
------------
## vnctpmd: 编译行情API
# 环境配置
----------
* 建议安装的软件在位数上保持一致比如全都安装32位同时编译32位库
* cmake:安装最新版本的cmake,用于配置编译环境
* [Boost1.57.0](http://sourceforge.net/projects/boost/files/boost/1.57.0/)库:编译的方法可以参考[Boost Getting Started](http://www.boost.org/doc/libs/1_58_0/more/getting_started/)右下角的链接
** 设置环境变量eg: BOOST_ROOT = C:\boost_1_57_0
** 编译32位库还是64位库任意选择
** 需要编译boost python, thread, system, chrono, date_time共5个库若编译全部库则会浪费大量时间和硬盘空间。
** boost python的动态库64bits可能编译不成功需加选项address-model=64。或者编译静态库
* [Anaconda1.9.2](http://repo.continuum.io/archive/index.html): 量化相关包的Python发行版
* 编译工具windows下选择visual studio 2013linux下使用g++。
# 编译过程
-------------
* 在vn.ctp目录下新建文件夹并命名为build, 保存编译的临时文件及库文件
* 打开命令行工具输入cmake-gui .. 则打开cmake配置界面
* 点击configure。
* 点击generate。如果没有错误则配置成功
* 进入build目录双击vn_ctp_api.sln打开解决方案
* 点击编译按钮,建议编译release库

View File

@ -39,8 +39,7 @@ class Config(object):
toke_ = '44ebc0f058981f85382595f9f15f967' + \
'0c7eaf2695de30dd752e8f33e9022baa0'
token = '7c2e59e212dbff90ffd6b382c7afb57' + \
'bc987a99307d382b058af6748f591d723'
token = '575593eb7696aec7339224c0fac2313780d8645f68b77369dcb35f8bcb419a0b'
body = {
'ssl': False,

View File

@ -101,7 +101,7 @@ def test_mktbar_M1_get_interM():
if __name__ == '__main__':
#test_config()
#test_mktbar_D1()
test_mktbar_D1()
#test_bond_D1()
#test_fut_D1()
#test_fund_D1()
@ -116,4 +116,4 @@ if __name__ == '__main__':
#test_mongod_get_all()
#test_mktbar_M1_get_drudgery()
#test_mktbar_M1_get_all()
test_mktbar_M1_get_interM()
#test_mktbar_M1_get_interM()

Binary file not shown.

View File

@ -1414,7 +1414,7 @@ int TdApi::reqOrderInsert(dict req, int nRequestID)
CSecurityFtdcInputOrderField myreq = CSecurityFtdcInputOrderField();
memset(&myreq, 0, sizeof(myreq));
getChar(req, "ContingentCondition", &myreq.ContingentCondition);
getChar(req, "CombOffsetFlag", myreq.CombOffsetFlag);
//getChar(req, "CombOffsetFlag", myreq.CombOffsetFlag);
getChar(req, "UserID", myreq.UserID);
getChar(req, "LimitPrice", myreq.LimitPrice);
getInt(req, "UserForceClose", &myreq.UserForceClose);
@ -1436,6 +1436,19 @@ int TdApi::reqOrderInsert(dict req, int nRequestID)
getInt(req, "RequestID", &myreq.RequestID);
getChar(req, "Direction", &myreq.Direction);
//´¦ÀíCombOffsetFlag
if (req.has_key("CombOffsetFlag"))
{
object o2 = req["CombOffsetFlag"];
extract<string> x2(o2);
if (x2.check())
{
string s2 = x2();
const char *buffer2 = s2.c_str();
myreq.CombOffsetFlag[0] = *buffer2;
}
}
int i = this->api->ReqOrderInsert(&myreq, nRequestID);
return i;
};

View File

@ -0,0 +1,14 @@
{
"Test1": {
"strategyClassName": "TestStrategy",
"vtSymbol": "IF1511"
},
"Test3": {
"strategyClassName": "TestStrategy",
"vtSymbol": "IF1512"
},
"Test2": {
"strategyClassName": "TestStrategy",
"vtSymbol": "IH1511"
}
}

View File

@ -1,7 +1,13 @@
{
"brokerID": "9999",
"tdAddress": "tcp://180.168.146.187:10000",
<<<<<<< HEAD
"password": "19890624",
"mdAddress": "tcp://180.168.212.228:41213",
"userID": "000300"
=======
"password": "simnow申请",
"mdAddress": "tcp://180.168.212.228:41213",
"userID": "simnow申请"
>>>>>>> refs/remotes/vnpy/master
}

View File

@ -0,0 +1,5 @@
{
"host": "localhost",
"port": 7496,
"clientId": 888
}

View File

@ -5,7 +5,13 @@
"mdAddress": "tcp://211.144.195.163:54513",
"productInfo": "LTS-Test",
"authCode": "N3EHKP4CYHZGM9VJ",
<<<<<<< HEAD
"tdPassword": "150601",
"mdPassword": "123",
"userID": "020090002037"
=======
"tdPassword": "华宝证券申请",
"mdPassword": "华宝证券申请",
"userID": "华宝证券申请"
>>>>>>> refs/remotes/vnpy/master
}

View File

@ -6,7 +6,11 @@ from collections import OrderedDict
from eventEngine import *
from vtConstant import *
<<<<<<< HEAD
from vtGateway import VtOrderReq, VtCancelOrderReq
=======
from vtGateway import VtSubscribeReq, VtOrderReq, VtCancelOrderReq, VtLogData
>>>>>>> refs/remotes/vnpy/master
from ctaConstant import *
from ctaStrategies import strategyClassDict
@ -137,6 +141,12 @@ class CtaEngine(object):
self.stopOrderDict = {} # 停止单撤销后不会从本字典中删除
self.workingStopOrderDict = {} # 停止单撤销后会从本字典中删除
<<<<<<< HEAD
=======
# 注册事件监听
self.registerEvent()
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def sendOrder(self, vtSymbol, orderType, price, volume, strategy):
"""发单"""
@ -243,8 +253,14 @@ class CtaEngine(object):
del self.workingStopOrderDict[so.stopOrderID]
#----------------------------------------------------------------------
<<<<<<< HEAD
def procecssTick(self, tick):
"""处理行情推送"""
=======
def procecssTickEvent(self, event):
"""处理行情推送"""
tick = event.dict_['data']
>>>>>>> refs/remotes/vnpy/master
# 收到tick行情后先处理本地停止单检查是否要立即发出
self.processStopOrder(tick)
@ -254,7 +270,12 @@ class CtaEngine(object):
ctaTick = CtaTickData()
d = ctaTick.__dict__
for key in d.keys():
<<<<<<< HEAD
d[key] = tick.__getattribute__(key)
=======
if key != 'datetime':
d[key] = tick.__getattribute__(key)
>>>>>>> refs/remotes/vnpy/master
# 添加datetime字段
ctaTick.datetime = datetime.strptime(' '.join([tick.date, tick.time]), '%Y%m%d %H:%M:%S.%f')
@ -264,15 +285,29 @@ class CtaEngine(object):
strategy.onTick(tick)
#----------------------------------------------------------------------
<<<<<<< HEAD
def processOrder(self, order):
"""处理委托推送"""
=======
def processOrderEvent(self, event):
"""处理委托推送"""
order = event.dict_['data']
>>>>>>> refs/remotes/vnpy/master
if order.vtOrderID in self.orderStrategyDict:
strategy = self.orderStrategyDict[order.vtOrderID]
strategy.onOrder(order)
#----------------------------------------------------------------------
<<<<<<< HEAD
def processTrade(self, trade):
"""处理成交推送"""
=======
def processTradeEvent(self, event):
"""处理成交推送"""
trade = event.dict_['data']
>>>>>>> refs/remotes/vnpy/master
if trade.vtOrderID in self.orderStrategyDict:
strategy = self.orderStrategyDict[order.vtOrderID]
strategy.onTrade(trade)
@ -280,9 +315,15 @@ class CtaEngine(object):
#----------------------------------------------------------------------
def registerEvent(self):
"""注册事件监听"""
<<<<<<< HEAD
self.eventEngine.register(EVENT_TICK, self.procecssTick)
self.eventEngine.register(EVENT_ORDER, self.processOrder)
self.eventEngine.register(EVENT_TRADE, self.processTrade)
=======
self.eventEngine.register(EVENT_TICK, self.procecssTickEvent)
self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def insertData(self, dbName, collectionName, data):
@ -338,7 +379,29 @@ class CtaEngine(object):
"""初始化策略"""
# 防止策略重名
if name not in self.strategyDict:
<<<<<<< HEAD
self.strategyDict[name] = strategyClass(self, paramDict) # 创建策略对象
=======
# 创建策略对象
strategy = strategyClass(self, name, paramDict)
self.strategyDict[name] = strategy
# 保存Tick映射关系
if strategy.vtSymbol in self.tickStrategyDict:
l = self.tickStrategyDict[strategy.vtSymbol]
else:
l = []
self.tickStrategyDict[strategy.vtSymbol] = l
l.append(strategy)
# 订阅合约
contract = self.dataEngine.getContract(strategy.vtSymbol)
if contract:
req = VtSubscribeReq()
req.symbol = contract.symbol
req.exchange = contract.exchange
self.mainEngine.subscribe(req, contract.gatewayName)
>>>>>>> refs/remotes/vnpy/master
else:
self.writeCtaLog(u'存在策略对象重名:' + name)
@ -409,7 +472,11 @@ class CtaEngine(object):
break
#----------------------------------------------------------------------
<<<<<<< HEAD
def getStrategyVarialbe(self, name):
=======
def getStrategyVar(self, name):
>>>>>>> refs/remotes/vnpy/master
"""获取策略当前的变量字典"""
if name in self.strategyDict:
strategy = self.strategyDict[name]
@ -426,11 +493,16 @@ class CtaEngine(object):
return None
#----------------------------------------------------------------------
<<<<<<< HEAD
def getStrategyParameter(self, name):
=======
def getStrategyParam(self, name):
>>>>>>> refs/remotes/vnpy/master
"""获取策略的参数字典"""
if name in self.strategyDict:
strategy = self.strategyDict[name]
d = strategy.__dict__
<<<<<<< HEAD
varDict = OrderedDict()
for key in strategy.paramList:
@ -438,6 +510,15 @@ class CtaEngine(object):
varDict[key] = d[key]
return varDict
=======
paramDict = OrderedDict()
for key in strategy.paramList:
if key in d:
paramDict[key] = d[key]
return paramDict
>>>>>>> refs/remotes/vnpy/master
else:
self.writeCtaLog(u'策略对象不存在:' + name)
return None

View File

@ -4,4 +4,11 @@
在本文件中引入所有希望在系统中使用的策略类
'''
<<<<<<< HEAD
strategyClassDict = {}
=======
from ctaStrategyTemplate import TestStrategy
strategyClassDict = {}
strategyClassDict[u'TestStrategy'] = TestStrategy
>>>>>>> refs/remotes/vnpy/master

View File

@ -1,5 +1,9 @@
# encoding: UTF-8
<<<<<<< HEAD
=======
from vtConstant import *
>>>>>>> refs/remotes/vnpy/master
from ctaConstant import *
@ -13,12 +17,22 @@ class CtaStrategyTemplate(object):
paramList = ['vtSymbol']
# 变量列表,保存了变量的名称
<<<<<<< HEAD
varList = []
#----------------------------------------------------------------------
def __init__(self, ctaEngine, setting=None):
"""Constructor"""
self.ctaEngine = ctaEngine
=======
varList = ['trading']
#----------------------------------------------------------------------
def __init__(self, ctaEngine, name, setting=None):
"""Constructor"""
self.ctaEngine = ctaEngine
self.name = name
>>>>>>> refs/remotes/vnpy/master
self.vtSymbol = EMPTY_STRING # 交易的合约vt系统代码
@ -153,12 +167,86 @@ class CtaStrategyTemplate(object):
d = self.__dict__
for key in self.paramList:
if key in setting:
<<<<<<< HEAD
d[key] = paramDict[key]
=======
d[key] = setting[key]
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def getToday(self):
"""查询当前日期"""
return self.ctaEngine.getToday()
<<<<<<< HEAD
=======
#----------------------------------------------------------------------
def writeCtaLog(self, content):
"""记录CTA日志"""
self.ctaEngine.writeCtaLog(content)
########################################################################
class TestStrategy(CtaStrategyTemplate):
"""测试策略"""
#----------------------------------------------------------------------
def __init__(self, ctaEngine, name, setting=None):
"""Constructor"""
super(TestStrategy, self).__init__(ctaEngine, name, setting)
self.strategyClassName = 'TestStrategy'
self.author = u'用Python的交易员' # 作者
self.pos = EMPTY_INT # 持仓
self.lastPrice = EMPTY_FLOAT # 最新价
# 参数和变量列表设置
self.paramList.append(u'author')
self.varList.append('pos')
self.varList.append('lastPrice')
#----------------------------------------------------------------------
def init(self):
"""初始化策略(必须由用户继承实现)"""
self.writeCtaLog(u'测试策略%s初始化' %self.name)
#----------------------------------------------------------------------
def start(self):
"""启动策略(必须由用户继承实现)"""
self.writeCtaLog(u'测试策略%s启动' %self.name)
#----------------------------------------------------------------------
def stop(self):
"""停止策略(必须由用户继承实现)"""
self.writeCtaLog(u'测试策略%s停止' %self.name)
#----------------------------------------------------------------------
def onTick(self, tick):
"""收到行情TICK推送必须由用户继承实现"""
self.writeCtaLog(u'测试策略%s收到Tick' %self.name)
self.lastPrice = tick.lastPrice
#----------------------------------------------------------------------
def onOrder(self, order):
"""收到委托变化推送(必须由用户继承实现)"""
self.writeCtaLog(u'onOrder不会被调用')
#----------------------------------------------------------------------
def onTrade(self, trade):
"""收到成交推送(必须由用户继承实现)"""
self.writeCtaLog(u'onTrade不会被调用')
#----------------------------------------------------------------------
def onBar(self, bar):
"""收到Bar推送必须由用户继承实现"""
self.writeCtaLog(u'测试策略%s收到Bar' %self.name)
>>>>>>> refs/remotes/vnpy/master

View File

@ -384,7 +384,14 @@ class CtpMdApi(MdApi):
#----------------------------------------------------------------------
def subscribe(self, subscribeReq):
"""订阅合约"""
<<<<<<< HEAD
self.subscribeMarketData(str(subscribeReq.symbol))
=======
# 这里的设计是,如果尚未登录就调用了订阅方法
# 则先保存订阅请求,登录完成后会自动订阅
if self.loginStatus:
self.subscribeMarketData(str(subscribeReq.symbol))
>>>>>>> refs/remotes/vnpy/master
self.subscribedSymbols.add(subscribeReq)
#----------------------------------------------------------------------

608
vn.trader/ibGateway.py Normal file
View File

@ -0,0 +1,608 @@
# encoding: UTF-8
'''
ibpy的gateway接入
注意事项
1. ib api只能获取和操作当前连接后下的单并且每次重启程序后之前下的单子收不到
2. ib api的成交也只会推送当前连接后的成交
3. ib api的持仓和账户更新可以订阅成主推模式因此getAccount和getPosition就用不到了
4. 目前只支持股票和期货交易ib api里期权合约的确定是基于Contract对象的多个字段比较复杂暂时没做
5. 海外市场的交易规则和国内有很多细节上的不同所以一些字段类型的映射可能不合理如果发现问题欢迎指出
'''
import json
from time import sleep, strftime, localtime
from copy import copy
from PyQt4 import QtGui, QtCore
from ib.ext.Contract import Contract
from ib.ext.Order import Order
from ib.ext.EWrapper import EWrapper
from ib.ext.EClientSocket import EClientSocket
from vtGateway import *
# 以下为一些VT类型和CTP类型的映射字典
# 价格类型映射
priceTypeMap = {}
priceTypeMap[PRICETYPE_LIMITPRICE] = 'LMT'
priceTypeMap[PRICETYPE_MARKETPRICE] = 'MKT'
priceTypeMapReverse = {v: k for k, v in priceTypeMap.items()}
# 方向类型映射
directionMap = {}
directionMap[DIRECTION_LONG] = 'BUY'
directionMap[DIRECTION_SHORT] = 'SSHORT'
directionMap[DIRECTION_SELL] = 'SELL'
directionMapReverse = {v: k for k, v in directionMap.items()}
directionMapReverse['BOT'] = DIRECTION_LONG
directionMapReverse['SLD'] = DIRECTION_SHORT
# 交易所类型映射
exchangeMap = {}
exchangeMap[EXCHANGE_SMART] = 'SMART'
exchangeMap[EXCHANGE_GLOBEX] = 'GLOBEX'
exchangeMap[EXCHANGE_IDEALPRO] = 'IDEALPRO'
exchangeMapReverse = {v:k for k,v in exchangeMap.items()}
# 报单状态映射
orderStatusMap = {}
orderStatusMap[STATUS_NOTTRADED] = 'Submitted'
orderStatusMap[STATUS_ALLTRADED] = 'Filled'
orderStatusMap[STATUS_CANCELLED] = 'Cancelled'
orderStatusMapReverse = {v:k for k,v in orderStatusMap.items()}
orderStatusMapReverse['PendingSubmit'] = STATUS_UNKNOWN # 这里未来视乎需求可以拓展vt订单的状态类型
orderStatusMapReverse['PendingCancel'] = STATUS_UNKNOWN
orderStatusMapReverse['PreSubmitted'] = STATUS_UNKNOWN
orderStatusMapReverse['Inactive'] = STATUS_UNKNOWN
# 合约类型映射
productClassMap = {}
productClassMap[PRODUCT_EQUITY] = 'STK'
productClassMap[PRODUCT_FUTURES] = 'FUT'
productClassMap[PRODUCT_OPTION] = 'OPT'
productClassMap[PRODUCT_FOREX] = 'CASH'
# 期权类型映射
optionTypeMap = {}
optionTypeMap[OPTION_CALL] = 'CALL'
optionTypeMap[OPTION_PUT] = 'PUT'
optionTypeMap = {v:k for k,v in optionTypeMap.items()}
# 货币类型映射
currencyMap = {}
currencyMap[CURRENCY_USD] = 'USD'
currencyMap[CURRENCY_CNY] = 'CNY'
currencyMap = {v:k for k,v in currencyMap.items()}
# Tick数据的Field和名称映射
tickFieldMap = {}
tickFieldMap[0] = 'bidVolume1'
tickFieldMap[1] = 'bidPrice1'
tickFieldMap[2] = 'askPrice1'
tickFieldMap[3] = 'askVolume1'
tickFieldMap[4] = 'lastPrice'
tickFieldMap[5] = 'lastVolume'
tickFieldMap[6] = 'highPrice'
tickFieldMap[7] = 'lowPrice'
tickFieldMap[8] = 'volume'
tickFieldMap[14] = 'openPrice'
tickFieldMap[20] = 'openInterest'
# Account数据Key和名称的映射
accountKeyMap = {}
accountKeyMap['NetLiquidationByCurrency'] = 'balance'
accountKeyMap['NetLiquidation'] = 'balance'
accountKeyMap['UnrealizedPnL'] = 'positionProfit'
accountKeyMap['AvailableFunds'] = 'available'
accountKeyMap['MaintMarginReq'] = 'margin'
########################################################################
class IbGateway(VtGateway):
"""IB接口"""
#----------------------------------------------------------------------
def __init__(self, eventEngine, gatewayName='IB'):
"""Constructor"""
super(IbGateway, self).__init__(eventEngine, gatewayName)
self.host = EMPTY_STRING # 连接地址
self.port = EMPTY_INT # 连接端口
self.clientId = EMPTY_INT # 用户编号
self.tickerId = 0 # 订阅行情时的代码编号
self.tickDict = {} # tick快照字典key为tickerIdvalue为VtTickData对象
self.orderId = 0 # 订单编号
self.orderDict = {} # 报单字典key为orderIdvalue为VtOrderData对象
self.accountDict = {} # 账户字典
self.connected = False # 连接状态
self.wrapper = IbWrapper(self) # 回调接口
self.connection = EClientSocket(self.wrapper) # 主动接口
#----------------------------------------------------------------------
def connect(self):
"""连接"""
# 载入json文件
fileName = self.gatewayName + '_connect.json'
try:
f = file(fileName)
except IOError:
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = u'读取连接配置出错,请检查'
self.onLog(log)
return
# 解析json文件
setting = json.load(f)
try:
self.host = str(setting['host'])
self.port = int(setting['port'])
self.clientId = int(setting['clientId'])
except KeyError:
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = u'连接配置缺少字段,请检查'
self.onLog(log)
return
# 发起连接
self.connection.eConnect(self.host, self.port, self.clientId)
# 查询服务器时间
self.connection.reqCurrentTime()
# 请求账户数据主推更新
self.connection.reqAccountUpdates(True, '')
#----------------------------------------------------------------------
def subscribe(self, subscribeReq):
"""订阅行情"""
# 订阅行情
self.tickerId += 1
contract = Contract()
contract.m_symbol = str(subscribeReq.symbol)
contract.m_exchange = exchangeMap.get(subscribeReq.exchange, '')
contract.m_secType = productClassMap.get(subscribeReq.productClass, '')
contract.m_currency = currencyMap.get(subscribeReq.currency, '')
contract.m_expiry = subscribeReq.expiry
contract.m_strike = subscribeReq.strikePrice
contract.m_right = optionTypeMap.get(subscribeReq.optionType, '')
self.connection.reqMktData(self.tickerId, contract, '', False)
# 创建Tick对象并保存到字典中
tick = VtTickData()
tick.symbol = subscribeReq.symbol
tick.exchange = subscribeReq.exchange
tick.vtSymbol = '.'.join([tick.symbol, tick.exchange])
tick.gatewayName = self.gatewayName
self.tickDict[self.tickerId] = tick
#----------------------------------------------------------------------
def sendOrder(self, orderReq):
"""发单"""
# 增加报单号1最后再次进行查询
# 这里双重设计的目的是为了防止某些情况下连续发单时nextOrderId的回调推送速度慢导致没有更新
self.orderId += 1
# 创建合约对象
contract = Contract()
contract.m_symbol = str(orderReq.symbol)
contract.m_exchange = exchangeMap.get(orderReq.exchange, '')
contract.m_secType = productClassMap.get(orderReq.productClass, '')
contract.m_currency = currencyMap.get(orderReq.currency, '')
contract.m_expiry = orderReq.expiry
contract.m_strike = orderReq.strikePrice
contract.m_right = optionTypeMap.get(orderReq.optionType, '')
# 创建委托对象
order = Order()
order.m_orderId = self.orderId
order.m_clientId = self.clientId
order.m_action = directionMap.get(orderReq.direction, '')
order.m_lmtPrice = orderReq.price
order.m_totalQuantity = orderReq.volume
order.m_orderType = priceTypeMap.get(orderReq.priceType, '')
# 发送委托
self.connection.placeOrder(self.orderId, contract, order)
# 查询下一个有效编号
self.connection.reqIds(1)
#----------------------------------------------------------------------
def cancelOrder(self, cancelOrderReq):
"""撤单"""
self.connection.cancelOrder(cancelOrderReq.orderID)
#----------------------------------------------------------------------
def getAccount(self):
"""查询账户资金"""
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = u'IB接口账户信息提供主推更新无需查询'
self.onLog(log)
#----------------------------------------------------------------------
def getPosition(self):
"""查询持仓"""
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = u'IB接口持仓信息提供主推更新无需查询'
self.onLog(log)
#----------------------------------------------------------------------
def close(self):
"""关闭"""
self.connection.eDisconnect()
########################################################################
class IbWrapper(EWrapper):
"""IB回调接口的实现"""
#----------------------------------------------------------------------
def __init__(self, gateway):
"""Constructor"""
super(IbWrapper, self).__init__()
self.connectionStatus = False # 连接状态
self.gateway = gateway # gateway对象
self.gatewayName = gateway.gatewayName # gateway对象名称
self.tickDict = gateway.tickDict # tick快照字典key为tickerIdvalue为VtTickData对象
self.orderDict = gateway.orderDict # order字典
self.accountDict = gateway.accountDict # account字典
#----------------------------------------------------------------------
def tickPrice(self, tickerId, field, price, canAutoExecute):
"""行情推送(价格相关)"""
if field in tickFieldMap:
tick = self.tickDict[tickerId]
key = tickFieldMap[field]
tick.__setattr__(key, price)
else:
print field
#----------------------------------------------------------------------
def tickSize(self, tickerId, field, size):
"""行情推送(量相关)"""
if field in tickFieldMap:
tick = self.tickDict[tickerId]
key = tickFieldMap[field]
tick.__setattr__(key, size)
else:
print field
#----------------------------------------------------------------------
def tickOptionComputation(self, tickerId, field, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice):
"""行情推送(期权数值)"""
pass
#----------------------------------------------------------------------
def tickGeneric(self, tickerId, tickType, value):
"""行情推送(某些通用字段)"""
pass
#----------------------------------------------------------------------
def tickString(self, tickerId, tickType, value):
"""行情推送,特殊字段相关"""
if tickType == 45:
lt = localtime(int(value))
tick = self.tickDict[tickerId]
tick.time = strftime('%H:%M:%S', lt)
tick.date = strftime('%Y%m%d')
# 这里使用copy的目的是为了保证推送到事件系统中的对象
# 不会被当前的API线程修改否则可能出现多线程数据同步错误
newtick = copy(tick)
self.gateway.onTick(newtick)
#----------------------------------------------------------------------
def tickEFP(self, tickerId, tickType, basisPoints, formattedBasisPoints, impliedFuture, holdDays, futureExpiry, dividendImpact, dividendsToExpiry):
"""行情推送(合约属性相关)"""
pass
#----------------------------------------------------------------------
def orderStatus(self, orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld):
"""报单成交回报"""
pass
orderId = str(orderId)
if orderId in self.orderDict:
od = self.orderDict[orderId]
else:
od = VtOrderData() # od代表orderData
od.orderID = orderId
od.vtOrderID = '.'.join([self.gatewayName, orderId])
od.gatewayName = self.gatewayName
self.orderDict[orderId] = od
od.status = orderStatusMapReverse.get(status, STATUS_UNKNOWN)
od.tradedVolume = filled
newod = copy(od)
self.gateway.onOrder(newod)
#----------------------------------------------------------------------
def openOrder(self, orderId, contract, order, orderState):
"""报单信息推送"""
orderId = str(orderId) # orderId是整数
if orderId in self.orderDict:
od = self.orderDict[orderId]
else:
od = VtOrderData() # od代表orderData
od.orderID = orderId
od.vtOrderID = '.'.join([self.gatewayName, orderId])
od.symbol = contract.m_symbol
od.exchange = exchangeMapReverse.get(contract.m_exchange, '')
od.vtSymbol = '.'.join([od.symbol, od.exchange])
od.gatewayName = self.gatewayName
self.orderDict[orderId] = od
od.direction = directionMapReverse.get(order.m_action, '')
od.price = order.m_lmtPrice
od.totalVolume = order.m_totalQuantity
newod = copy(od)
self.gateway.onOrder(newod)
#----------------------------------------------------------------------
def openOrderEnd(self):
""" generated source for method openOrderEnd """
pass
#----------------------------------------------------------------------
def updateAccountValue(self, key, value, currency, accountName):
"""更新账户数据"""
# 仅逐个字段更新数据这里对于没有currency的推送忽略
if currency:
name = '.'.join([accountName, currency])
if name in self.accountDict:
account = self.accountDict[name]
else:
account = VtAccountData()
account.accountID = name
account.vtAccountID = name
account.gatewayName = self.gatewayName
self.accountDict[name] = account
if key in accountKeyMap:
k = accountKeyMap[key]
account.__setattr__(k, float(value))
#----------------------------------------------------------------------
def updatePortfolio(self, contract, position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, accountName):
"""持仓更新推送"""
pos = VtPositionData()
pos.symbol = contract.m_symbol
pos.exchange = exchangeMapReverse.get(contract.m_exchange, contract.m_exchange)
pos.vtSymbol = '.'.join([pos.symbol, pos.exchange])
pos.direction = DIRECTION_NET
pos.position = position
pos.price = averageCost
pos.vtPositionName = pos.vtSymbol
pos.gatewayName = self.gatewayName
self.gateway.onPosition(pos)
#----------------------------------------------------------------------
def updateAccountTime(self, timeStamp):
"""更新账户数据的时间"""
# 推送数据
for account in self.accountDict.values():
newaccount = copy(account)
self.gateway.onAccount(newaccount)
#----------------------------------------------------------------------
def accountDownloadEnd(self, accountName):
""" generated source for method accountDownloadEnd """
pass
#----------------------------------------------------------------------
def nextValidId(self, orderId):
"""下一个有效报单编号更新"""
self.gateway.orderId = orderId
#----------------------------------------------------------------------
def contractDetails(self, reqId, contractDetails):
""" generated source for method contractDetails """
pass
#----------------------------------------------------------------------
def bondContractDetails(self, reqId, contractDetails):
""" generated source for method bondContractDetails """
#----------------------------------------------------------------------
def contractDetailsEnd(self, reqId):
""" generated source for method contractDetailsEnd """
pass
#----------------------------------------------------------------------
def execDetails(self, reqId, contract, execution):
"""成交推送"""
trade = VtTradeData()
trade.gatewayName = self.gatewayName
trade.tradeID = execution.m_execId
trade.vtTradeID = '.'.join([self.gatewayName, trade.tradeID])
trade.symbol = contract.m_symbol
trade.exchange = exchangeMapReverse.get(contract.m_exchange, '')
trade.vtSymbol = '.'.join([trade.symbol, trade.exchange])
trade.orderID = str(execution.m_orderId)
trade.direction = directionMapReverse.get(execution.m_side, '')
trade.price = execution.m_price
trade.volume = execution.m_shares
trade.tradeTime = execution.m_time
self.gateway.onTrade(trade)
#----------------------------------------------------------------------
def execDetailsEnd(self, reqId):
""" generated source for method execDetailsEnd """
pass
#----------------------------------------------------------------------
def updateMktDepth(self, tickerId, position, operation, side, price, size):
""" generated source for method updateMktDepth """
pass
#----------------------------------------------------------------------
def updateMktDepthL2(self, tickerId, position, marketMaker, operation, side, price, size):
""" generated source for method updateMktDepthL2 """
pass
#----------------------------------------------------------------------
def updateNewsBulletin(self, msgId, msgType, message, origExchange):
""" generated source for method updateNewsBulletin """
pass
#----------------------------------------------------------------------
def managedAccounts(self, accountsList):
""" generated source for method managedAccounts """
pass
#----------------------------------------------------------------------
def receiveFA(self, faDataType, xml):
""" generated source for method receiveFA """
pass
#----------------------------------------------------------------------
def historicalData(self, reqId, date, open, high, low, close, volume, count, WAP, hasGaps):
""" generated source for method historicalData """
pass
#----------------------------------------------------------------------
def scannerParameters(self, xml):
""" generated source for method scannerParameters """
pass
#----------------------------------------------------------------------
def scannerData(self, reqId, rank, contractDetails, distance, benchmark, projection, legsStr):
''' generated source for method scannerData '''
pass
#----------------------------------------------------------------------
def scannerDataEnd(self, reqId):
""" generated source for method scannerDataEnd """
pass
#----------------------------------------------------------------------
def realtimeBar(self, reqId, time, open, high, low, close, volume, wap, count):
""" generated source for method realtimeBar """
pass
#----------------------------------------------------------------------
def currentTime(self, time):
""" generated source for method currentTime """
t = strftime('%H:%M:%S', localtime(time))
self.connectionStatus = True
self.gateway.connected = True
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = (u'IB接口连接成功当前服务器时间%s' %t)
self.gateway.onLog(log)
#----------------------------------------------------------------------
def fundamentalData(self, reqId, data):
""" generated source for method fundamentalData """
pass
#----------------------------------------------------------------------
def deltaNeutralValidation(self, reqId, underComp):
""" generated source for method deltaNeutralValidation """
pass
#----------------------------------------------------------------------
def tickSnapshotEnd(self, reqId):
""" generated source for method tickSnapshotEnd """
pass
#----------------------------------------------------------------------
def marketDataType(self, reqId, marketDataType):
""" generated source for method marketDataType """
pass
#----------------------------------------------------------------------
def commissionReport(self, commissionReport):
""" generated source for method commissionReport """
pass
#----------------------------------------------------------------------
def position(self, account, contract, pos, avgCost):
""" generated source for method position """
pass
#----------------------------------------------------------------------
def positionEnd(self):
""" generated source for method positionEnd """
pass
#----------------------------------------------------------------------
def accountSummary(self, reqId, account, tag, value, currency):
""" generated source for method accountSummary """
pass
#----------------------------------------------------------------------
def accountSummaryEnd(self, reqId):
""" generated source for method accountSummaryEnd """
pass
#----------------------------------------------------------------------
def error(self, id=None, errorCode=None, errorMsg=None):
"""错误回报"""
err = VtErrorData()
err.gatewayName = self.gatewayName
err.errorID = errorCode
err.errorMsg = errorMsg
self.gateway.onError(err)
#----------------------------------------------------------------------
def error_0(self, strval=None):
"""错误回报(单一字符串)"""
err = VtErrorData()
err.gatewayName = self.gatewayName
err.errorMsg = strval
self.gateway.onError(err)
#----------------------------------------------------------------------
def error_1(self, id=None, errorCode=None, errorMsg=None):
"""错误回报(字符串和代码)"""
err = VtErrorData()
err.gatewayName = self.gatewayName
err.errorID = errorCode
err.errorMsg = errorMsg
self.gateway.onError(err)
#----------------------------------------------------------------------
def connectionClosed(self):
"""连接断开"""
self.connectionStatus = False
self.gateway.connected = False
log = VtLogData()
log.gatewayName = self.gatewayName
log.logContent = (u'IB接口连接断开')
self.gateway.onLog(log)

View File

@ -393,7 +393,15 @@ class LtsMdApi(MdApi):
req = {}
req['InstrumentID'] = str(subscribeReq.symbol)
req['ExchangeID'] = str(subscribeReq.exchange)
<<<<<<< HEAD
self.subscribeMarketData(req)
=======
# 这里的设计是,如果尚未登录就调用了订阅方法
# 则先保存订阅请求,登录完成后会自动订阅
if self.loginStatus:
self.subscribeMarketData(req)
>>>>>>> refs/remotes/vnpy/master
self.subscribedSymbols.add(subscribeReq)
@ -565,10 +573,13 @@ class LtsTdApi(TdApi):
#----------------------------------------------------------------------
def onRtnOrder(self, data):
"""报单回报"""
<<<<<<< HEAD
print '-'*20
for k, v in data.items():
print k, ':', v
=======
>>>>>>> refs/remotes/vnpy/master
# 更新最大报单编号
newref = data['OrderRef']
self.orderRef = max(self.orderRef, int(newref))
@ -662,10 +673,13 @@ class LtsTdApi(TdApi):
#----------------------------------------------------------------------
def onErrRtnOrderInsert(self, data, error):
"""发单错误回报(交易所)"""
<<<<<<< HEAD
print '-'*20
for k, v in data.items():
print k, ':', v
=======
>>>>>>> refs/remotes/vnpy/master
err = VtErrorData()
err.gatewayName = self.gatewayName
err.errorID = error['ErrorID']

View File

@ -27,7 +27,14 @@ class BasicCell(QtGui.QTableWidgetItem):
#----------------------------------------------------------------------
def setContent(self, text):
"""设置内容"""
<<<<<<< HEAD
self.setText(text)
=======
if text == '0' or text == '0.0':
self.setText('')
else:
self.setText(text)
>>>>>>> refs/remotes/vnpy/master
########################################################################
@ -533,7 +540,24 @@ class TradingWidget(QtGui.QFrame):
EXCHANGE_DCE,
EXCHANGE_CZCE,
EXCHANGE_SSE,
<<<<<<< HEAD
EXCHANGE_SZSE]
=======
EXCHANGE_SZSE,
EXCHANGE_SMART,
EXCHANGE_GLOBEX,
EXCHANGE_IDEALPRO]
currencyList = [CURRENCY_CNY,
CURRENCY_USD]
productClassList = [PRODUCT_UNKNOWN,
PRODUCT_EQUITY,
PRODUCT_FUTURES,
PRODUCT_OPTION]
gatewayList = ['']
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def __init__(self, mainEngine, eventEngine, dataEngine, parent=None):
@ -544,6 +568,12 @@ class TradingWidget(QtGui.QFrame):
self.dataEngine = dataEngine
self.symbol = ''
<<<<<<< HEAD
=======
# 添加交易接口
self.gatewayList.extend(mainEngine.gatewayDict.keys())
>>>>>>> refs/remotes/vnpy/master
self.initUi()
self.connectSignal()
@ -565,6 +595,12 @@ class TradingWidget(QtGui.QFrame):
labelVolume = QtGui.QLabel(u'数量')
labelPriceType = QtGui.QLabel(u'价格类型')
labelExchange = QtGui.QLabel(u'交易所')
<<<<<<< HEAD
=======
labelCurrency = QtGui.QLabel(u'货币')
labelProductClass = QtGui.QLabel(u'产品类型')
labelGateway = QtGui.QLabel(u'交易接口')
>>>>>>> refs/remotes/vnpy/master
self.lineSymbol = QtGui.QLineEdit()
self.lineName = QtGui.QLineEdit()
@ -588,7 +624,20 @@ class TradingWidget(QtGui.QFrame):
self.comboPriceType.addItems(self.priceTypeList)
self.comboExchange = QtGui.QComboBox()
<<<<<<< HEAD
self.comboExchange.addItems(self.exchangeList)
=======
self.comboExchange.addItems(self.exchangeList)
self.comboCurrency = QtGui.QComboBox()
self.comboCurrency.addItems(self.currencyList)
self.comboProductClass = QtGui.QComboBox()
self.comboProductClass.addItems(self.productClassList)
self.comboGateway = QtGui.QComboBox()
self.comboGateway.addItems(self.gatewayList)
>>>>>>> refs/remotes/vnpy/master
gridleft = QtGui.QGridLayout()
gridleft.addWidget(labelSymbol, 0, 0)
@ -599,6 +648,13 @@ class TradingWidget(QtGui.QFrame):
gridleft.addWidget(labelVolume, 5, 0)
gridleft.addWidget(labelPriceType, 6, 0)
gridleft.addWidget(labelExchange, 7, 0)
<<<<<<< HEAD
=======
gridleft.addWidget(labelCurrency, 8, 0)
gridleft.addWidget(labelProductClass, 9, 0)
gridleft.addWidget(labelGateway, 10, 0)
>>>>>>> refs/remotes/vnpy/master
gridleft.addWidget(self.lineSymbol, 0, 1)
gridleft.addWidget(self.lineName, 1, 1)
gridleft.addWidget(self.comboDirection, 2, 1)
@ -607,6 +663,12 @@ class TradingWidget(QtGui.QFrame):
gridleft.addWidget(self.spinVolume, 5, 1)
gridleft.addWidget(self.comboPriceType, 6, 1)
gridleft.addWidget(self.comboExchange, 7, 1)
<<<<<<< HEAD
=======
gridleft.addWidget(self.comboCurrency, 8, 1)
gridleft.addWidget(self.comboProductClass, 9, 1)
gridleft.addWidget(self.comboGateway, 10, 1)
>>>>>>> refs/remotes/vnpy/master
# 右边部分
labelBid1 = QtGui.QLabel(u'买一')
@ -716,13 +778,25 @@ class TradingWidget(QtGui.QFrame):
#----------------------------------------------------------------------
def updateSymbol(self):
"""合约变化"""
<<<<<<< HEAD
symbol = unicode(self.lineSymbol.text())
exchange = unicode(self.comboExchange.currentText())
=======
# 读取组件数据
symbol = unicode(self.lineSymbol.text())
exchange = unicode(self.comboExchange.currentText())
currency = unicode(self.comboCurrency.currentText())
productClass = unicode(self.comboProductClass.currentText())
gatewayName = unicode(self.comboGateway.currentText())
# 查询合约
>>>>>>> refs/remotes/vnpy/master
if exchange:
vtSymbol = '.'.join([symbol, exchange])
contract = self.dataEngine.getContract(vtSymbol)
else:
<<<<<<< HEAD
contract = self.dataEngine.getContract(symbol)
if contract:
@ -770,6 +844,59 @@ class TradingWidget(QtGui.QFrame):
# 更新组件当前交易的合约
self.symbol = contract.vtSymbol
=======
vtSymbol = symbol
contract = self.dataEngine.getContract(symbol)
if contract:
gatewayName = contract.gatewayName
self.lineName.setText(contract.name)
exchange = contract.exchange # 保证有交易所代码
# 清空价格数量
self.spinPrice.setValue(0)
self.spinVolume.setValue(0)
# 清空行情显示
self.labelBidPrice1.setText('')
self.labelBidPrice2.setText('')
self.labelBidPrice3.setText('')
self.labelBidPrice4.setText('')
self.labelBidPrice5.setText('')
self.labelBidVolume1.setText('')
self.labelBidVolume2.setText('')
self.labelBidVolume3.setText('')
self.labelBidVolume4.setText('')
self.labelBidVolume5.setText('')
self.labelAskPrice1.setText('')
self.labelAskPrice2.setText('')
self.labelAskPrice3.setText('')
self.labelAskPrice4.setText('')
self.labelAskPrice5.setText('')
self.labelAskVolume1.setText('')
self.labelAskVolume2.setText('')
self.labelAskVolume3.setText('')
self.labelAskVolume4.setText('')
self.labelAskVolume5.setText('')
self.labelLastPrice.setText('')
self.labelReturn.setText('')
# 重新注册事件监听
self.eventEngine.unregister(EVENT_TICK + self.symbol, self.signal.emit)
self.eventEngine.register(EVENT_TICK + vtSymbol, self.signal.emit)
# 订阅合约
req = VtSubscribeReq()
req.symbol = symbol
req.exchange = exchange
req.currency = currency
req.productClass = productClass
self.mainEngine.subscribe(req, gatewayName)
# 更新组件当前交易的合约
self.symbol = vtSymbol
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def updateTick(self, event):
@ -804,8 +931,17 @@ class TradingWidget(QtGui.QFrame):
self.labelAskVolume5.setText(str(tick.askVolume5))
self.labelLastPrice.setText(str(tick.lastPrice))
<<<<<<< HEAD
rt = (tick.lastPrice/tick.preClosePrice)-1
self.labelReturn.setText(('%.2f' %(rt*100))+'%')
=======
if tick.preClosePrice:
rt = (tick.lastPrice/tick.preClosePrice)-1
self.labelReturn.setText(('%.2f' %(rt*100))+'%')
else:
self.labelReturn.setText('')
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def connectSignal(self):
@ -815,13 +951,24 @@ class TradingWidget(QtGui.QFrame):
#----------------------------------------------------------------------
def sendOrder(self):
"""发单"""
<<<<<<< HEAD
symbol = str(self.lineSymbol.text())
exchange = str(self.comboExchange.currentText())
=======
symbol = unicode(self.lineSymbol.text())
exchange = unicode(self.comboExchange.currentText())
currency = unicode(self.comboCurrency.currentText())
productClass = unicode(self.comboProductClass.currentText())
gatewayName = unicode(self.comboGateway.currentText())
# 查询合约
>>>>>>> refs/remotes/vnpy/master
if exchange:
vtSymbol = '.'.join([symbol, exchange])
contract = self.dataEngine.getContract(vtSymbol)
else:
<<<<<<< HEAD
contract = self.dataEngine.getContract(symbol)
if contract:
@ -834,6 +981,27 @@ class TradingWidget(QtGui.QFrame):
req.priceType = unicode(self.comboPriceType.currentText())
req.offset = unicode(self.comboOffset.currentText())
self.mainEngine.sendOrder(req, contract.gatewayName)
=======
vtSymbol = symbol
contract = self.dataEngine.getContract(symbol)
if contract:
gatewayName = contract.gatewayName
exchange = contract.exchange # 保证有交易所代码
req = VtOrderReq()
req.symbol = symbol
req.exchange = exchange
req.price = self.spinPrice.value()
req.volume = self.spinVolume.value()
req.direction = unicode(self.comboDirection.currentText())
req.priceType = unicode(self.comboPriceType.currentText())
req.offset = unicode(self.comboOffset.currentText())
req.currency = currency
req.productClass = productClass
self.mainEngine.sendOrder(req, gatewayName)
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def cancelAll(self):

View File

@ -2,3 +2,250 @@
'''CTA模块相关的GUI控制组件'''
<<<<<<< HEAD
=======
from uiBasicWidget import QtGui, QtCore, BasicCell
from eventEngine import *
########################################################################
class ValueMonitor(QtGui.QTableWidget):
"""数值监控"""
signal = QtCore.pyqtSignal()
#----------------------------------------------------------------------
def __init__(self, parent=None):
"""Constructor"""
super(ValueMonitor , self).__init__(parent)
self.keyCellDict = {}
self.row = 0
self.data = None
self.initUi()
self.signal.connect(self.updateTable)
#----------------------------------------------------------------------
def initUi(self):
"""初始化界面"""
self.setColumnCount(2)
self.verticalHeader().setVisible(False)
self.horizontalHeader().setVisible(False)
self.setEditTriggers(self.NoEditTriggers)
self.setAlternatingRowColors(True)
#----------------------------------------------------------------------
def updateData(self, data):
"""更新数据"""
self.data = data
self.signal.emit()
#----------------------------------------------------------------------
def updateTable(self):
"""更新表格"""
for key, value in self.data.items():
if key in self.keyCellDict:
cell = self.keyCellDict[key]
cell.setText(unicode(value))
else:
# 创建并保存单元格
keyCell = BasicCell(unicode(key))
cell = BasicCell(unicode(value))
self.keyCellDict[key] = cell
# 移动到下一行
self.insertRow(self.row)
self.setItem(self.row, 0, keyCell)
self.setItem(self.row, 1, cell)
self.row += 1
########################################################################
class CtaStrategyManager(QtGui.QGroupBox):
"""策略管理组件"""
#----------------------------------------------------------------------
def __init__(self, ctaEngine, eventEngine, name, parent=None):
"""Constructor"""
super(CtaStrategyManager, self).__init__(parent)
self.ctaEngine = ctaEngine
self.eventEngine = eventEngine
self.name = name
self.initUi()
self.updateMonitor()
self.registerEvent()
#----------------------------------------------------------------------
def initUi(self):
"""初始化界面"""
self.setTitle(self.name)
paramLabel = QtGui.QLabel(u'参数')
varLabel = QtGui.QLabel(u'变量')
self.paramMonitor = ValueMonitor(self)
self.varMonitor = ValueMonitor(self)
buttonStart = QtGui.QPushButton(u'启动')
buttonStop = QtGui.QPushButton(u'停止')
buttonStart.clicked.connect(self.start)
buttonStop.clicked.connect(self.stop)
hbox = QtGui.QHBoxLayout()
hbox.addWidget(buttonStart)
hbox.addWidget(buttonStop)
hbox.addStretch()
vbox = QtGui.QVBoxLayout()
vbox.addLayout(hbox)
vbox.addWidget(paramLabel)
vbox.addWidget(self.paramMonitor)
vbox.addWidget(varLabel)
vbox.addWidget(self.varMonitor)
self.setLayout(vbox)
#----------------------------------------------------------------------
def updateMonitor(self, event=None):
"""显示策略最新状态"""
paramDict = self.ctaEngine.getStrategyParam(self.name)
if paramDict:
self.paramMonitor.updateData(paramDict)
varDict = self.ctaEngine.getStrategyVar(self.name)
if varDict:
self.varMonitor.updateData(varDict)
#----------------------------------------------------------------------
def registerEvent(self):
"""注册事件监听"""
self.eventEngine.register(EVENT_TIMER, self.updateMonitor)
#----------------------------------------------------------------------
def start(self):
"""启动策略"""
self.ctaEngine.startStrategy(self.name)
#----------------------------------------------------------------------
def stop(self):
"""停止策略"""
self.ctaEngine.stopStrategy(self.name)
########################################################################
class CtaEngineManager(QtGui.QWidget):
"""CTA引擎管理组件"""
signal = QtCore.pyqtSignal(type(Event()))
#----------------------------------------------------------------------
def __init__(self, ctaEngine, eventEngine, parent=None):
"""Constructor"""
super(CtaEngineManager, self).__init__(parent)
self.ctaEngine = ctaEngine
self.eventEngine = eventEngine
self.strategyLoaded = False
self.initUi()
self.registerEvent()
# 记录日志
self.ctaEngine.writeCtaLog(u'CTA引擎启动成功')
#----------------------------------------------------------------------
def initUi(self):
"""初始化界面"""
self.setWindowTitle(u'CTA策略')
# 按钮
loadButton = QtGui.QPushButton(u'加载策略')
startAllButton = QtGui.QPushButton(u'全部启动')
stopAllButton = QtGui.QPushButton(u'全部停止')
loadButton.clicked.connect(self.load)
startAllButton.clicked.connect(self.startAll)
stopAllButton.clicked.connect(self.stopAll)
# 滚动区域放置所有的CtaStrategyManager
self.scrollArea = QtGui.QScrollArea()
# CTA组件的日志监控
self.ctaLogMonitor = QtGui.QTextEdit()
self.ctaLogMonitor.setReadOnly(True)
# 设置布局
hbox2 = QtGui.QHBoxLayout()
hbox2.addWidget(loadButton)
hbox2.addWidget(startAllButton)
hbox2.addWidget(stopAllButton)
hbox2.addStretch()
vbox = QtGui.QVBoxLayout()
vbox.addLayout(hbox2)
vbox.addWidget(self.scrollArea)
vbox.addWidget(self.ctaLogMonitor)
self.setLayout(vbox)
#----------------------------------------------------------------------
def initStrategyManager(self):
"""初始化策略管理组件界面"""
w = QtGui.QWidget()
hbox = QtGui.QHBoxLayout()
for name in self.ctaEngine.strategyDict.keys():
strategyManager = CtaStrategyManager(self.ctaEngine, self.eventEngine, name)
hbox.addWidget(strategyManager)
w.setLayout(hbox)
self.scrollArea.setWidget(w)
#----------------------------------------------------------------------
def startAll(self):
"""全部启动"""
for name in self.ctaEngine.strategyDict.keys():
self.ctaEngine.startStrategy(name)
#----------------------------------------------------------------------
def stopAll(self):
"""全部停止"""
for name in self.ctaEngine.strategyDict.keys():
self.ctaEngine.stopStrategy(name)
#----------------------------------------------------------------------
def load(self):
"""加载策略"""
if not self.strategyLoaded:
self.ctaEngine.loadStrategySetting()
self.initStrategyManager()
self.strategyLoaded = True
self.ctaEngine.writeCtaLog(u'策略加载成功')
#----------------------------------------------------------------------
def updateCtaLog(self, event):
"""更新CTA相关日志"""
log = event.dict_['data']
content = '\t'.join([log.logTime, log.logContent])
self.ctaLogMonitor.append(content)
#----------------------------------------------------------------------
def registerEvent(self):
"""注册事件监听"""
self.signal.connect(self.updateCtaLog)
self.eventEngine.register(EVENT_CTA_LOG, self.signal.emit)
>>>>>>> refs/remotes/vnpy/master

View File

@ -3,7 +3,11 @@
import psutil
from uiBasicWidget import *
<<<<<<< HEAD
=======
from uiCtaWidget import CtaEngineManager
>>>>>>> refs/remotes/vnpy/master
########################################################################
class MainWindow(QtGui.QMainWindow):
@ -77,6 +81,12 @@ class MainWindow(QtGui.QMainWindow):
connectWindAction = QtGui.QAction(u'连接Wind', self)
connectWindAction.triggered.connect(self.connectWind)
<<<<<<< HEAD
=======
connectIbAction = QtGui.QAction(u'连接IB', self)
connectIbAction.triggered.connect(self.connectIb)
>>>>>>> refs/remotes/vnpy/master
testAction = QtGui.QAction(u'测试', self)
testAction.triggered.connect(self.testSubscribe)
@ -89,6 +99,12 @@ class MainWindow(QtGui.QMainWindow):
contractAction = QtGui.QAction(u'查询合约', self)
contractAction.triggered.connect(self.openContract)
<<<<<<< HEAD
=======
ctaAction = QtGui.QAction(u'CTA策略', self)
ctaAction.triggered.connect(self.openCta)
>>>>>>> refs/remotes/vnpy/master
# 创建菜单
menubar = self.menuBar()
@ -96,11 +112,19 @@ class MainWindow(QtGui.QMainWindow):
sysMenu.addAction(connectCtpAction)
sysMenu.addAction(connectLtsAction)
sysMenu.addAction(connectWindAction)
<<<<<<< HEAD
=======
sysMenu.addAction(connectIbAction)
>>>>>>> refs/remotes/vnpy/master
sysMenu.addAction(testAction)
sysMenu.addAction(exitAction)
functionMenu = menubar.addMenu(u'功能')
functionMenu.addAction(contractAction)
<<<<<<< HEAD
=======
functionMenu.addAction(ctaAction)
>>>>>>> refs/remotes/vnpy/master
helpMenu = menubar.addMenu(u'帮助')
helpMenu.addAction(aboutAction)
@ -150,6 +174,7 @@ class MainWindow(QtGui.QMainWindow):
self.mainEngine.connect('Wind')
#----------------------------------------------------------------------
<<<<<<< HEAD
def testSubscribe(self):
"""测试订阅"""
req = VtSubscribeReq()
@ -181,6 +206,33 @@ class MainWindow(QtGui.QMainWindow):
req.symbol = 'SR1601'
req.exchange = EXCHANGE_CZCE
self.mainEngine.subscribe(req, 'Wind')
=======
def connectIb(self):
"""连接Ib"""
self.mainEngine.connect('IB')
#----------------------------------------------------------------------
def testSubscribe(self):
"""测试订阅"""
req = VtSubscribeReq()
req.symbol = 'GOOG'
req.productClass = PRODUCT_EQUITY
req.exchange = EXCHANGE_SMART
req.currency = CURRENCY_USD
self.mainEngine.subscribe(req, 'IB')
req.symbol = 'AAPL'
self.mainEngine.subscribe(req, 'IB')
req.symbol = 'YHOO'
self.mainEngine.subscribe(req, 'IB')
req.symbol = 'MSFT'
self.mainEngine.subscribe(req, 'IB')
req.symbol = 'GE'
self.mainEngine.subscribe(req, 'IB')
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def openAbout(self):
@ -199,6 +251,18 @@ class MainWindow(QtGui.QMainWindow):
except AttributeError:
self.contractM = ContractMonitor(self.mainEngine.dataEngine)
self.contractM.show()
<<<<<<< HEAD
=======
#----------------------------------------------------------------------
def openCta(self):
"""打开CTA组件"""
try:
self.ctaM.show()
except AttributeError:
self.ctaM = CtaEngineManager(self.mainEngine.ctaEngine, self.eventEngine)
self.ctaM.show()
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def closeEvent(self, event):

View File

@ -12,6 +12,10 @@ DIRECTION_LONG = u'多'
DIRECTION_SHORT = u''
DIRECTION_UNKNOWN = u'未知'
DIRECTION_NET = u''
<<<<<<< HEAD
=======
DIRECTION_SELL = u'卖出' # IB接口
>>>>>>> refs/remotes/vnpy/master
# 开平常量
OFFSET_NONE = u'无开平'
@ -34,6 +38,10 @@ PRODUCT_FUTURES = u'期货'
PRODUCT_OPTION = u'期权'
PRODUCT_INDEX = u'指数'
PRODUCT_COMBINATION = u'组合'
<<<<<<< HEAD
=======
PRODUCT_FOREX = u'外汇'
>>>>>>> refs/remotes/vnpy/master
PRODUCT_UNKNOWN = u'未知'
# 价格类型常量
@ -53,5 +61,20 @@ EXCHANGE_CFFEX = u'CFFEX' # 中金所
EXCHANGE_SHFE = u'SHFE' # 上期所
EXCHANGE_CZCE = u'CZCE' # 郑商所
EXCHANGE_DCE = u'DCE' # 大商所
<<<<<<< HEAD
EXCHANGE_UNKNOWN = 'UNKNOWN'# 未知交易所
EXCHANGE_NONE = '' # 空交易所
=======
EXCHANGE_UNKNOWN = 'UNKNOWN'# 未知交易所
EXCHANGE_NONE = '' # 空交易所
EXCHANGE_SMART = u'SMART' # IB智能路由股票、期权
EXCHANGE_GLOBEX = u'GLOBEX' # CME电子交易平台
EXCHANGE_IDEALPRO = u'IDEALPRO' # IB外汇ECN
# 货币类型
CURRENCY_USD = 'USD' # 美元
CURRENCY_CNY = 'CNY' # 人民币
CURRENCY_UNKNOWN = 'UNKNOWN' # 未知货币
>>>>>>> refs/remotes/vnpy/master

View File

@ -1,6 +1,10 @@
# encoding: UTF-8
import shelve
<<<<<<< HEAD
=======
from collections import OrderedDict
>>>>>>> refs/remotes/vnpy/master
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
@ -8,9 +12,17 @@ from pymongo.errors import ConnectionFailure
from eventEngine import *
from ctpGateway import CtpGateway
from ltsGateway import LtsGateway
<<<<<<< HEAD
from windGateway import WindGateway
from vtGateway import *
import uiBasicWidget
=======
#from windGateway import WindGateway
from ibGateway import IbGateway
from vtGateway import *
import uiBasicWidget
from ctaEngine import CtaEngine
>>>>>>> refs/remotes/vnpy/master
########################################################################
@ -29,7 +41,7 @@ class MainEngine(object):
uiBasicWidget.NameCell.setDataEngine(uiBasicWidget.NameCell, self.dataEngine) # 将数据引擎对象传给NameCell
# 用来保存接口对象的字典
self.gatewayDict = {}
self.gatewayDict = OrderedDict()
# 创建我们想要接入的接口对象
self.addGateway(CtpGateway, 'CTP')
@ -40,8 +52,18 @@ class MainEngine(object):
#self.addGateway(WindGateway, 'Wind') # 没有Wind的请注释掉这一行
<<<<<<< HEAD
# MongoDB数据库相关
self.dbClient = None # MongoDB客户端对象
=======
self.addGateway(IbGateway, 'IB')
# MongoDB数据库相关
self.dbClient = None # MongoDB客户端对象
# CTA引擎
self.ctaEngine = CtaEngine(self, self.eventEngine, self.dataEngine)
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def addGateway(self, gateway, gatewayName=None):
@ -56,7 +78,11 @@ class MainEngine(object):
gateway.connect()
else:
self.writeLog(u'接口不存在:%s' %gatewayName)
<<<<<<< HEAD
=======
>>>>>>> refs/remotes/vnpy/master
#----------------------------------------------------------------------
def subscribe(self, subscribeReq, gatewayName):
"""订阅特定接口的行情"""

View File

@ -164,7 +164,8 @@ class VtTickData(VtBaseData):
# 成交数据
self.lastPrice = EMPTY_FLOAT # 最新成交价
self.volume = EMPTY_INT # 最新成交量
self.lastVolume = EMPTY_INT # 最新成交量
self.volume = EMPTY_INT # 今天总成交量
self.openInterest = EMPTY_INT # 持仓量
self.time = EMPTY_STRING # 时间 11:20:56.5
self.date = EMPTY_STRING # 日期 20151009
@ -371,6 +372,13 @@ class VtSubscribeReq:
self.symbol = EMPTY_STRING # 代码
self.exchange = EMPTY_STRING # 交易所
# 以下为IB相关
self.productClass = EMPTY_UNICODE # 合约类型
self.currency = EMPTY_STRING # 合约货币
self.expiry = EMPTY_STRING # 到期日
self.strikePrice = EMPTY_FLOAT # 行权价
self.optionType = EMPTY_UNICODE # 期权类型
########################################################################
class VtOrderReq:
@ -387,6 +395,16 @@ class VtOrderReq:
self.priceType = EMPTY_STRING # 价格类型
self.direction = EMPTY_STRING # 买卖
self.offset = EMPTY_STRING # 开平
<<<<<<< HEAD
=======
# 以下为IB相关
self.productClass = EMPTY_UNICODE # 合约类型
self.currency = EMPTY_STRING # 合约货币
self.expiry = EMPTY_STRING # 到期日
self.strikePrice = EMPTY_FLOAT # 行权价
self.optionType = EMPTY_UNICODE # 期权类型
>>>>>>> refs/remotes/vnpy/master
########################################################################