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:
parent
8b5d27f46c
commit
676c4c6d40
17
.gitignore
vendored
17
.gitignore
vendored
@ -37,8 +37,23 @@ Release/
|
||||
# 其他文件
|
||||
*.dump
|
||||
*.vssettings
|
||||
<<<<<<< HEAD
|
||||
vnpy.pyproj.user
|
||||
.idea/workspace.xml
|
||||
.idea/.name
|
||||
.idea/vnpy.iml
|
||||
*.xml
|
||||
*.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
74
vn.ctp/CMakeLists.txt
Normal 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})
|
||||
|
||||
# 链接boost库,anaconda
|
||||
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
30
vn.ctp/readme.md
Normal 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 2013;linux下使用g++。
|
||||
|
||||
# 编译过程
|
||||
-------------
|
||||
|
||||
* 在vn.ctp目录下新建文件夹,并命名为build, 保存编译的临时文件及库文件
|
||||
* 打开命令行工具输入:cmake-gui .. 则打开cmake配置界面
|
||||
* 点击configure。
|
||||
* 点击generate。如果没有错误则配置成功
|
||||
* 进入build目录,双击vn_ctp_api.sln打开解决方案
|
||||
* 点击编译按钮,建议编译release库
|
@ -14,7 +14,7 @@ CREATE TABLE `TB_Trade` (
|
||||
`fee` float DEFAULT '0',
|
||||
`profit` float DEFAULT '0',
|
||||
`profitRate` float DEFAULT '0'
|
||||
)
|
||||
)
|
||||
|
||||
create table TB_Bar
|
||||
(
|
||||
|
@ -39,8 +39,7 @@ class Config(object):
|
||||
toke_ = '44ebc0f058981f85382595f9f15f967' + \
|
||||
'0c7eaf2695de30dd752e8f33e9022baa0'
|
||||
|
||||
token = '7c2e59e212dbff90ffd6b382c7afb57' + \
|
||||
'bc987a99307d382b058af6748f591d723'
|
||||
token = '575593eb7696aec7339224c0fac2313780d8645f68b77369dcb35f8bcb419a0b'
|
||||
|
||||
body = {
|
||||
'ssl': False,
|
||||
|
@ -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.
@ -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;
|
||||
};
|
||||
|
14
vn.trader/CTA_setting.json
Normal file
14
vn.trader/CTA_setting.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"Test1": {
|
||||
"strategyClassName": "TestStrategy",
|
||||
"vtSymbol": "IF1511"
|
||||
},
|
||||
"Test3": {
|
||||
"strategyClassName": "TestStrategy",
|
||||
"vtSymbol": "IF1512"
|
||||
},
|
||||
"Test2": {
|
||||
"strategyClassName": "TestStrategy",
|
||||
"vtSymbol": "IH1511"
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
5
vn.trader/IB_connect.json
Normal file
5
vn.trader/IB_connect.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"host": "localhost",
|
||||
"port": 7496,
|
||||
"clientId": 888
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
|
@ -4,4 +4,11 @@
|
||||
在本文件中引入所有希望在系统中使用的策略类
|
||||
'''
|
||||
|
||||
strategyClassDict = {}
|
||||
<<<<<<< HEAD
|
||||
strategyClassDict = {}
|
||||
=======
|
||||
from ctaStrategyTemplate import TestStrategy
|
||||
|
||||
strategyClassDict = {}
|
||||
strategyClassDict[u'TestStrategy'] = TestStrategy
|
||||
>>>>>>> refs/remotes/vnpy/master
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
608
vn.trader/ibGateway.py
Normal 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为tickerId,value为VtTickData对象
|
||||
|
||||
self.orderId = 0 # 订单编号
|
||||
self.orderDict = {} # 报单字典,key为orderId,value为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为tickerId,value为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)
|
||||
|
||||
|
@ -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']
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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_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
|
||||
|
@ -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):
|
||||
"""订阅特定接口的行情"""
|
||||
|
@ -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
|
||||
@ -370,6 +371,13 @@ class VtSubscribeReq:
|
||||
"""Constructor"""
|
||||
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 # 期权类型
|
||||
|
||||
|
||||
########################################################################
|
||||
@ -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
|
||||
|
||||
|
||||
########################################################################
|
||||
|
Loading…
Reference in New Issue
Block a user