[Mod]add module_locale in femas pybind11 wrap

This commit is contained in:
vn.py 2019-04-24 11:44:39 +08:00
parent 347edb2906
commit b990ae7758
10 changed files with 48 additions and 370 deletions

View File

@ -7,7 +7,7 @@ from vnpy.trader.ui import MainWindow, create_qapp
from vnpy.gateway.bitmex import BitmexGateway
from vnpy.gateway.futu import FutuGateway
from vnpy.gateway.ib import IbGateway
from vnpy.gateway.ctp import CtpGateway
#from vnpy.gateway.ctp import CtpGateway
from vnpy.gateway.femas import FemasGateway
from vnpy.gateway.tiger import TigerGateway
from vnpy.gateway.oes import OesGateway
@ -30,7 +30,7 @@ def main():
event_engine = EventEngine()
main_engine = MainEngine(event_engine)
main_engine.add_gateway(CtpGateway)
# main_engine.add_gateway(CtpGateway)
main_engine.add_gateway(FemasGateway)
main_engine.add_gateway(IbGateway)
main_engine.add_gateway(FutuGateway)

View File

@ -1,173 +0,0 @@
# encoding: UTF-8
# flake8: noqa
from __future__ import print_function
import sys
from time import sleep
from PyQt4 import QtGui
from vnfemasmd import *
#----------------------------------------------------------------------
def print_dict(d):
"""按照键值打印一个字典"""
for key,value in d.items():
print(key + ':' + str(value))
#----------------------------------------------------------------------
def simple_log(func):
"""简单装饰器用于输出函数名"""
def wrapper(*args, **kw):
print("")
print(str(func.__name__))
return func(*args, **kw)
return wrapper
########################################################################
class TestMdApi(MdApi):
"""测试用实例"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
super(TestMdApi, self).__init__()
#----------------------------------------------------------------------
@simple_log
def onFrontConnected(self):
"""服务器连接"""
pass
#----------------------------------------------------------------------
@simple_log
def onFrontDisconnected(self, n):
"""服务器断开"""
print(n)
#----------------------------------------------------------------------
@simple_log
def onHeartBeatWarning(self, n):
"""心跳报警"""
print(n)
#----------------------------------------------------------------------
@simple_log
def onRspError(self, error, n, last):
"""错误"""
print_dict(error)
@simple_log
#----------------------------------------------------------------------
def onRspUserLogin(self, data, error, n, last):
"""登陆回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRspUserLogout(self, data, error, n, last):
"""登出回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRspSubMarketData(self, data, error, n, last):
"""订阅合约回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRspUnSubMarketData(self, data, error, n, last):
"""退订合约回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRtnDepthMarketData(self, data):
"""行情推送"""
print_dict(data)
#----------------------------------------------------------------------
@simple_log
def onRspQryTopic(self, data, error, n, last):
"""订阅合约回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRspSubscribeTopic(self, data, error, n, last):
"""退订合约回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
def main():
"""主测试函数出现堵塞时可以考虑使用sleep"""
reqid = 0
# 创建Qt应用对象用于事件循环
app = QtGui.QApplication(sys.argv)
# 创建API对象
api = TestMdApi()
# 在C++环境中创建MdApi对象传入参数是希望用来保存.con文件的地址
api.createFtdcMdApi('')
# 注册前置机地址
api.registerFront("tcp://118.126.16.229:17101")
# 初始化api连接前置机
api.init()
sleep(0.5)
# 登陆
loginReq = {} # 创建一个空字典
loginReq['UserID'] = '' # 参数作为字典键值的方式传入
loginReq['Password'] = '' # 键名和C++中的结构体成员名对应
loginReq['BrokerID'] = ''
reqid = reqid + 1 # 请求数必须保持唯一性
i = api.reqUserLogin(loginReq, 1)
sleep(0.5)
## 登出,测试出错(无此功能)
#reqid = reqid + 1
#i = api.reqUserLogout({}, 1)
#sleep(0.5)
## 安全退出,测试通过
#i = api.exit()
## 获取交易日,目前输出为空
#day = api.getTradingDay()
#print 'Trading Day is:' + str(day)
#sleep(0.5)
## 订阅合约,测试通过
#i = api.subscribeMarketData('IF1505')
## 退订合约,测试通过
#i = api.unSubscribeMarketData('IF1505')
# 订阅询价,测试通过
#i = api.subscribeForQuoteRsp('IO1504-C-3900')
# 退订询价,测试通过
#i = api.unSubscribeForQuoteRsp('IO1504-C-3900')
# 连续运行,用于输出行情
app.exec_()
if __name__ == '__main__':
main()

View File

@ -1,166 +0,0 @@
# encoding: UTF-8
# flake8: noqa
from __future__ import print_function
import sys
from time import sleep
from PyQt4 import QtGui
from vnfemastd import *
#----------------------------------------------------------------------
def print_dict(d):
"""按照键值打印一个字典"""
for key,value in d.items():
print(key + ':' + str(value))
#----------------------------------------------------------------------
def simple_log(func):
"""简单装饰器用于输出函数名"""
def wrapper(*args, **kw):
print("")
print(str(func.__name__))
return func(*args, **kw)
return wrapper
########################################################################
class TestTdApi(TdApi):
"""测试用实例"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
super(TestTdApi, self).__init__()
#----------------------------------------------------------------------
@simple_log
def onFrontConnected(self):
"""服务器连接"""
pass
#----------------------------------------------------------------------
@simple_log
def onFrontDisconnected(self, n):
"""服务器断开"""
print(n)
#----------------------------------------------------------------------
@simple_log
def onHeartBeatWarning(self, n):
"""心跳报警"""
print(n)
#----------------------------------------------------------------------
@simple_log
def onRspError(self, error, n, last):
"""错误"""
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRspUserLogin(self, data, error, n, last):
"""登陆回报"""
print_dict(data)
print_dict(error)
self.brokerID = data['BrokerID']
self.userID = data['UserID']
self.frontID = data['FrontID']
self.sessionID = data['SessionID']
#----------------------------------------------------------------------
@simple_log
def onRspUserLogout(self, data, error, n, last):
"""登出回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRspQrySettlementInfo(self, data, error, n, last):
"""查询结算信息回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRspSettlementInfoConfirm(self, data, error, n, last):
"""确认结算信息回报"""
print_dict(data)
print_dict(error)
#----------------------------------------------------------------------
@simple_log
def onRspQryInstrument(self, data, error, n, last):
"""查询合约回报"""
print_dict(data)
print_dict(error)
print(n)
print(last)
#----------------------------------------------------------------------
def main():
"""主测试函数出现堵塞时可以考虑使用sleep"""
reqid = 0
# 创建Qt应用对象用于事件循环
app = QtGui.QApplication(sys.argv)
# 创建API对象测试通过
api = TestTdApi()
# 在C++环境中创建MdApi对象传入参数是希望用来保存.con文件的地址测试通过
api.createFtdcTraderApi('')
# 设置数据流重传方式,测试通过
api.subscribePrivateTopic(1)
api.subscribePublicTopic(1)
api.subscribeUserTopic(1)
# 注册前置机地址,测试通过
api.registerFront("tcp://118.126.16.229:17111")
# 初始化api连接前置机测试通过
api.init()
sleep(2)
# 登陆,测试通过
loginReq = {} # 创建一个空字典
loginReq['UserID'] = '' # 参数作为字典键值的方式传入
loginReq['Password'] = '' # 键名和C++中的结构体成员名对应
loginReq['BrokerID'] = ''
reqid = reqid + 1 # 请求数必须保持唯一性
i = api.reqUserLogin(loginReq, reqid)
sleep(0.5)
## 查询合约, 测试通过
#reqid = reqid + 1
#i = api.reqQryInstrument({}, reqid)
## 查询结算, 测试通过
#req = {}
#req['BrokerID'] = api.brokerID
#req['InvestorID'] = api.userID
#reqid = reqid + 1
#i = api.reqQrySettlementInfo(req, reqid)
#sleep(0.5)
## 确认结算, 测试通过
#req = {}
#req['BrokerID'] = api.brokerID
#req['InvestorID'] = api.userID
#reqid = reqid + 1
#i = api.reqSettlementInfoConfirm(req, reqid)
#sleep(0.5)
# 连续运行
app.exec_()
if __name__ == '__main__':
main()

View File

@ -717,7 +717,7 @@ public:
PYBIND11_MODULE(vnfemasmd, m)
{
class_<MdApi, PyMdApi> mdapi(m, "MdApi");
class_<MdApi, PyMdApi> mdapi(m, "MdApi", module_local());
mdapi
.def(init<>())
.def("createFtdcMdApi", &MdApi::createFtdcMdApi)

View File

@ -23,7 +23,7 @@
<ProjectGuid>{F00054FF-282F-4826-848E-D58BFB9E9D9F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>vnfemasmd</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectName>vnfemasmd</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@ -95,10 +95,10 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>C:\Python37\include;$(SolutionDir);$(SolutionDir)..\include;$(SolutionDir)..\include\femas;$(IncludePath)</IncludePath>
<IncludePath>C:\Miniconda3\include;$(SolutionDir);$(SolutionDir)..\include;$(SolutionDir)..\include\femas;$(IncludePath)</IncludePath>
<ReferencePath>$(ReferencePath)</ReferencePath>
<TargetExt>.pyd</TargetExt>
<LibraryPath>C:\Python37\libs;$(SolutionDir)..\libs;$(LibraryPath)</LibraryPath>
<LibraryPath>C:\Miniconda3\include\libs;$(SolutionDir)..\libs;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)..\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -181,7 +181,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>C:\ProgramData\VNConda\libs;C:\Users\Administrator\Documents\GitHub\vnpy\vnpy\api\femasctp\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>C:\Miniconda3\libs;$(SolutionDir)..\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>USTPmduserapiAF.lib;USTPtraderapiAF.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>

View File

@ -2451,14 +2451,11 @@ void TdApi::processRspQryInvestorAccount(Task *task)
data["Margin"] = task_data->Margin;
data["Premium"] = task_data->Premium;
data["Risk"] = task_data->Risk;
print("processRspQryInvestorAccount");
print(data["AccountID"]);
delete task->task_data;
}
dict error;
if (task->task_error)
{
print("task->task_error");
CUstpFtdcRspInfoField *task_error = (CUstpFtdcRspInfoField*)task->task_error;
error["ErrorID"] = task_error->ErrorID;
error["ErrorMsg"] = toUtf(task_error->ErrorMsg);
@ -4237,7 +4234,7 @@ public:
PYBIND11_MODULE(vnfemastd, m)
{
class_<TdApi, PyTdApi> TdApi(m, "TdApi");
class_<TdApi, PyTdApi> TdApi(m, "TdApi", module_local());
TdApi
.def(init<>())
.def("createFtdcTraderApi", &TdApi::createFtdcTraderApi)

View File

@ -23,7 +23,7 @@
<ProjectGuid>{016732E6-5789-4F7C-9A1C-C46A249080CF}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>vnfemastd</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectName>vnfemastd</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@ -95,8 +95,8 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetExt>.pyd</TargetExt>
<IncludePath>C:\Python37\include;$(SolutionDir);$(SolutionDir)..\include;$(SolutionDir)..\include\femas;$(IncludePath)</IncludePath>
<LibraryPath>C:\Python37\libs;$(SolutionDir)..\libs;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Miniconda3\include;$(SolutionDir);$(SolutionDir)..\include;$(SolutionDir)..\include\femas;$(IncludePath)</IncludePath>
<LibraryPath>C:\Miniconda3\include\libs;$(SolutionDir)..\libs;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)..\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -178,7 +178,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>C:\ProgramData\VNConda\libs;C:\Users\Administrator\Documents\GitHub\vnpy\vnpy\api\femasctp\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>C:\Miniconda3\libs;$(SolutionDir)..\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>USTPmduserapiAF.lib;USTPtraderapiAF.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>

Binary file not shown.

Binary file not shown.

View File

@ -30,7 +30,7 @@ from vnpy.api.femas import (
USTP_FTDC_TC_GFD,
USTP_FTDC_TC_IOC,
USTP_FTDC_VC_AV,
USTP_FTDC_VC_CV,
USTP_FTDC_VC_CV
)
from vnpy.trader.constant import (
Direction,
@ -39,6 +39,7 @@ from vnpy.trader.constant import (
OptionType,
OrderType,
Status,
Product
)
from vnpy.trader.event import EVENT_TIMER
from vnpy.trader.gateway import BaseGateway
@ -86,6 +87,12 @@ OFFSET_VT2FEMAS = {
}
OFFSET_FEMAS2VT = {v: k for k, v in OFFSET_VT2FEMAS.items()}
# PRODUCT_CTP2VT = {
# THOST_FTDC_PC_Futures: Product.FUTURES,
# THOST_FTDC_PC_Options: Product.OPTION,
# THOST_FTDC_PC_Combination: Product.SPREAD
# }
DIRECTION_FEMAS2VT = {v: k for k, v in DIRECTION_VT2FEMAS.items()}
DIRECTION_FEMAS2VT[USTP_FTDC_PD_Long] = Direction.LONG
DIRECTION_FEMAS2VT[USTP_FTDC_PD_Short] = Direction.SHORT
@ -237,16 +244,15 @@ class FemasMdApi(MdApi):
"""
self.connect_status = False
self.login_status = False
self.gateway.write_log(f"行情连接断开,原因{reason}")
self.gateway.write_log(f"行情服务器连接断开,原因{reason}")
def onRspUserLogin(self, data: dict, error: dict, reqid: int, last: bool):
"""
Callback when user is logged in.
"""
if self.gateway.if_error_write_error("行情登录失败", error):
if self.gateway.if_error_write_error("行情服务器登录失败", error):
return
self.login_status = True
self.gateway.write_log("onRspUserLogin行情服务器登录成功")
self.gateway.write_log("行情服务器登录成功")
for symbol in self.subscribed:
@ -373,7 +379,7 @@ class FemasTdApi(TdApi):
def onFrontConnected(self):
""""""
self.connect_status = True
self.gateway.write_log("onFrontConnected交易连接成功")
self.gateway.write_log("交易服务器连接成功")
self.login()
@ -381,7 +387,7 @@ class FemasTdApi(TdApi):
""""""
self.connect_status = False
self.login_status = False
self.gateway.write_log(f"交易连接断开,原因{reason}")
self.gateway.write_log(f"交易服务器连接断开,原因{reason}")
def onRspUserLogin(self, data: dict, error: dict, reqid: int, last: bool):
""""""
@ -391,13 +397,13 @@ class FemasTdApi(TdApi):
self.localID, int(data["MaxOrderLocalID"])
) # 目前最大本地报单号
self.login_status = True
self.gateway.write_log("onRspUserLogin交易登录成功")
self.gateway.write_log("交易服务器登录成功")
self.reqid += 1
self.reqQryInstrument({}, self.reqid)
else:
self.login_failed = True
self.gateway.if_error_write_error("交易登录失败", error)
self.gateway.if_error_write_error("交易服务器登录失败", error)
def onRspOrderInsert(self, data: dict, error: dict, reqid: int, last: bool):
""""""
@ -486,28 +492,41 @@ class FemasTdApi(TdApi):
balance=data["PreBalance"],
gateway_name=self.gateway_name,
)
# todo: check for error
self.gateway.on_account(account)
def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool):
"""
Callback of instrument query.
"""
# Femas gateway provides no ProductClass data, so need to determine
# product type using other logic.
option_type = OPTIONTYPE_FEMAS2VT.get(data["OptionsType"], None)
if option_type:
product = Product.OPTION
elif data["InstrumentID_2"]:
product = Product.SPREAD
else:
product = Product.FUTURES
contract = ContractData(
product=data["ProductID"],
symbol=data["InstrumentID"],
exchange=EXCHANGE_FEMAS2VT[data["ExchangeID"]],
name=data["InstrumentName"],
size=data["VolumeMultiple"],
pricetick=data["PriceTick"],
option_underlying=data["UnderlyingInstrID"],
option_type=OPTIONTYPE_FEMAS2VT.get(data["OptionsType"], None),
option_strike=data["StrikePrice"],
option_expiry=datetime.strptime(data["ExpireDate"], "%Y%m%d"),
gateway_name=self.gateway_name,
product=product,
gateway_name=self.gateway_name
)
if product == Product.OPTION:
contract.option_underlying = data["UnderlyingInstrID"]
contract.option_type = OPTIONTYPE_FEMAS2VT.get(
data["OptionsType"], None)
contract.option_strike = data["StrikePrice"]
contract.option_expiry = datetime.strptime(
data["ExpireDate"], "%Y%m%d")
self.gateway.on_contract(contract)
symbol_exchange_map[contract.symbol] = contract.exchange
@ -522,7 +541,8 @@ class FemasTdApi(TdApi):
Callback of order status update.
"""
# 更新最大报单编号
self.localID = max(self.localID, int(data["UserOrderLocalID"])) # 检查并增加本地报单编号
self.localID = max(self.localID, int(
data["UserOrderLocalID"])) # 检查并增加本地报单编号
symbol = data["InstrumentID"]
exchange = symbol_exchange_map.get(symbol, "")