[Add] da_gateway for Direct Access Futures

This commit is contained in:
vn.py 2019-09-01 22:40:29 +08:00
parent 8eb0553574
commit f3e7543f7a
16 changed files with 815 additions and 30 deletions

View File

@ -11,21 +11,22 @@ from vnpy.trader.ui import MainWindow, create_qapp
# from vnpy.gateway.ctp import CtpGateway
# from vnpy.gateway.ctptest import CtptestGateway
# from vnpy.gateway.mini import MiniGateway
from vnpy.gateway.sopt import SoptGateway
# from vnpy.gateway.sopt import SoptGateway
# from vnpy.gateway.minitest import MinitestGateway
# from vnpy.gateway.femas import FemasGateway
# from vnpy.gateway.tiger import TigerGateway
# from vnpy.gateway.oes import OesGateway
from vnpy.gateway.okex import OkexGateway
# from vnpy.gateway.okex import OkexGateway
# from vnpy.gateway.huobi import HuobiGateway
from vnpy.gateway.bitfinex import BitfinexGateway
# from vnpy.gateway.bitfinex import BitfinexGateway
# from vnpy.gateway.onetoken import OnetokenGateway
from vnpy.gateway.okexf import OkexfGateway
# from vnpy.gateway.okexf import OkexfGateway
# from vnpy.gateway.xtp import XtpGateway
# from vnpy.gateway.hbdm import HbdmGateway
# from vnpy.gateway.tap import TapGateway
# from vnpy.gateway.tora import ToraGateway
# from vnpy.gateway.alpaca import AlpacaGateway
from vnpy.gateway.da import DaGateway
from vnpy.app.cta_strategy import CtaStrategyApp
# from vnpy.app.csv_loader import CsvLoaderApp
@ -49,7 +50,7 @@ def main():
# main_engine.add_gateway(CtpGateway)
# main_engine.add_gateway(CtptestGateway)
# main_engine.add_gateway(MiniGateway)
main_engine.add_gateway(SoptGateway)
#
# main_engine.add_gateway(MinitestGateway)
# main_engine.add_gateway(FemasGateway)
# main_engine.add_gateway(IbGateway)
@ -67,6 +68,7 @@ def main():
# main_engine.add_gateway(TapGateway)
# main_engine.add_gateway(ToraGateway)
# main_engine.add_gateway(AlpacaGateway)
main_engine.add_gateway(DaGateway)
main_engine.add_app(CtaStrategyApp)
main_engine.add_app(CtaBacktesterApp)

View File

@ -1,2 +0,0 @@
[A]
LocalID=13499

View File

@ -1,5 +0,0 @@
[Generel]
SUB=HKEX,00001.HK;
SHOW=
ApiLog=1
Stock=1

4
vnpy/api/da/__init__.py Normal file
View File

@ -0,0 +1,4 @@
from .vndamarket import MarketApi
from .vndafuture import FutureApi
from .vndastock import StockApi
from .da_constant import *

View File

@ -0,0 +1,15 @@
DA_STR_SIZE = 256
MAX_BROKER = 4096
DAAPI_VERSION = "1.12"
OS_NAME = "Windows"
OS_NAME = "Linux"
MAX_SUB_COUNT = 20
DAF_TYPE_Stock = 'S'
DAF_TYPE_Future = 'D'
DAF_TYPE_Unknown = 0
DAF_SUB_Append = '1'
DAF_SUB_Replace = '2'
DAF_SUB_Unsubcribe = '3'
DAF_SUB_UnsubcribeAll = '4'
DAF_Market_Full = 'Z'
DAF_Market_Fill = 'Y'

View File

@ -20,16 +20,12 @@ using namespace std;
class MarketApi : public IMarketEvent
{
private:
CMarketApi* api; //API¶ÔÏó
public:
MarketApi()
{
};
CMarketApi *api; //API¶ÔÏó
~MarketApi()
{
};
public:
MarketApi(){};
~MarketApi(){};
//-------------------------------------------------------------------------------------
//API回调函数
@ -39,7 +35,7 @@ public:
void OnFrontDisconnected(int iReason);
void OnHeartBeatWarning(int iTimeLapse);
void OnRspRawData(const char* rawData);
void OnRspRawData(const char *rawData);
void OnRspUserLogin(CMarketRspInfoField *pRspInfo, int iRequestID, bool bIsLast);
void OnRspTradeDate(CMarketRspTradeDateField *pRspTradeDate, CMarketRspInfoField *pRspInfo, int iRequestID, bool bIsLast);
void OnRspBrokerData(CMarketRspBrokerDataField *pRspBrokerData, CMarketRspInfoField *pRspInfo, int iRequestID, bool bIsLast);
@ -49,24 +45,25 @@ public:
//Python回调函数
//-------------------------------------------------------------------------------------
virtual void onFrontConnected() {};
virtual void onFrontConnected(){};
virtual void onFrontDisconnected(int reqid) {};
virtual void onFrontDisconnected(int reqid){};
virtual void onHeartBeatWarning(int reqid) {};
virtual void onHeartBeatWarning(int reqid){};
virtual void onRspRawData(string data) {};
virtual void onRspRawData(string data){};
virtual void onRspUserLogin(const dict &error, int reqid, bool last) {};
virtual void onRspUserLogin(const dict &error, int reqid, bool last){};
virtual void onRspTradeDate(const dict &data, const dict &error, int reqid, bool last) {};
virtual void onRspTradeDate(const dict &data, const dict &error, int reqid, bool last){};
virtual void onRspBrokerData(const dict &data, const dict &error, int reqid, bool last) {};
virtual void onRspBrokerData(const dict &data, const dict &error, int reqid, bool last){};
virtual void onRspMarketData(const dict &data, const dict &error, int reqid, bool last) {};
virtual void onRspMarketData(const dict &data, const dict &error, int reqid, bool last){};
//-------------------------------------------------------------------------------------
//req:主动函数的请求字典
//-------------------------------------------------------------------------------------
string getVersion();

BIN
vnpy/api/da/vndafuture.lib Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vnpy/api/da/vndastock.lib Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
from .da_gateway import DaGateway

View File

@ -0,0 +1,773 @@
"""
"""
from datetime import datetime
from threading import Thread
import wmi
from vnpy.api.da import (
MarketApi,
FutureApi,
DAF_SUB_Append,
DAF_TYPE_Future
)
from vnpy.trader.constant import (
Direction,
Offset,
Exchange,
OrderType,
Product,
Status,
OptionType
)
from vnpy.trader.gateway import BaseGateway
from vnpy.trader.object import (
TickData,
OrderData,
TradeData,
PositionData,
AccountData,
ContractData,
OrderRequest,
CancelRequest,
SubscribeRequest,
)
from vnpy.trader.utility import get_folder_path
from vnpy.trader.event import EVENT_TIMER
# STATUS_DA2VT = {
# THOST_FTDC_OAS_Submitted: Status.SUBMITTING,
# THOST_FTDC_OAS_Accepted: Status.SUBMITTING,
# THOST_FTDC_OAS_Rejected: Status.REJECTED,
# THOST_FTDC_OST_NoTradeQueueing: Status.NOTTRADED,
# THOST_FTDC_OST_PartTradedQueueing: Status.PARTTRADED,
# THOST_FTDC_OST_AllTraded: Status.ALLTRADED,
# THOST_FTDC_OST_Canceled: Status.CANCELLED
# }
# DIRECTION_VT2DA = {
# Direction.LONG: THOST_FTDC_D_Buy,
# Direction.SHORT: THOST_FTDC_D_Sell
# }
# DIRECTION_DA2VT = {v: k for k, v in DIRECTION_VT2DA.items()}
# DIRECTION_DA2VT[THOST_FTDC_PD_Long] = Direction.LONG
# DIRECTION_DA2VT[THOST_FTDC_PD_Short] = Direction.SHORT
# ORDERTYPE_VT2DA = {
# OrderType.LIMIT: THOST_FTDC_OPT_LimitPrice,
# OrderType.MARKET: THOST_FTDC_OPT_AnyPrice
# }
# ORDERTYPE_DA2VT = {v: k for k, v in ORDERTYPE_VT2DA.items()}
# OFFSET_VT2DA = {
# Offset.OPEN: THOST_FTDC_OF_Open,
# Offset.CLOSE: THOST_FTDC_OFEN_Close,
# Offset.CLOSETODAY: THOST_FTDC_OFEN_CloseToday,
# Offset.CLOSEYESTERDAY: THOST_FTDC_OFEN_CloseYesterday,
# }
# OFFSET_DA2VT = {v: k for k, v in OFFSET_VT2DA.items()}
EXCHANGE_DA2VT = {
"APEX": Exchange.APEX,
# "SGXQ": Exchange.SGX,
# "NYMEX": Exchange.NYMEX,
# "LME": Exchange.LME,
# "CME_CBT": Exchange.CBOT,
# "HKEX": Exchange.HKFE,
# "CME": Exchange.CME,
# "TOCOM": Exchange.TOCOM,
# "KRX": Exchange.KRX,
# "ICE": Exchange.ICE
}
EXCHANGE_VT2DA = {v: k for k, v in EXCHANGE_DA2VT.items()}
PRODUCT_DA2VT = {
"F": Product.FUTURES,
"O": Product.OPTION,
}
# OPTIONTYPE_DA2VT = {
# THOST_FTDC_CP_CallOptions: OptionType.CALL,
# THOST_FTDC_CP_PutOptions: OptionType.PUT
# }
symbol_exchange_map = {}
symbol_name_map = {}
symbol_size_map = {}
class DaGateway(BaseGateway):
"""
VN Trader Gateway for DA .
"""
default_setting = {
"用户名": "",
"密码": "",
"交易服务器": "",
"行情服务器": "",
"授权码": ""
}
exchanges = list(EXCHANGE_DA2VT.values())
def __init__(self, event_engine):
"""Constructor"""
super().__init__(event_engine, "DA")
self.future_api = DaFutureApi(self)
self.market_api = DaMarketApi(self)
def connect(self, setting: dict):
""""""
userid = setting["用户名"]
password = setting["密码"]
future_address = setting["交易服务器"]
market_address = setting["行情服务器"]
auth_code = setting["授权码"]
if not future_address.startswith("tcp://"):
future_address = "tcp://" + future_address
if not market_address.startswith("tcp://"):
market_address = "tcp://" + market_address
self.future_api.connect(future_address, userid, password, auth_code)
self.market_api.connect(market_address, userid, password, auth_code)
def subscribe(self, req: SubscribeRequest):
""""""
self.market_api.subscribe(req)
def send_order(self, req: OrderRequest):
""""""
return self.future_api.send_order(req)
def cancel_order(self, req: CancelRequest):
""""""
self.future_api.cancel_order(req)
def query_account(self):
""""""
pass
def query_position(self):
""""""
pass
def close(self):
""""""
self.future_api.close()
self.market_api.close()
def write_error(self, msg: str, error: dict):
""""""
error_id = error["ErrorID"]
error_msg = error["ErrorMsg"]
msg = f"{msg},代码:{error_id},信息:{error_msg}"
self.write_log(msg)
class DaMarketApi(MarketApi):
""""""
def __init__(self, gateway):
"""Constructor"""
super().__init__()
self.gateway = gateway
self.gateway_name = gateway.gateway_name
self.reqid = 0
self.connect_status = False
self.login_status = False
self.subscribed = {}
self.mac_address = get_mac_address()
self.userid = ""
self.password = ""
self.auth_code = ""
def onFrontConnected(self):
"""
Callback when front server is connected.
"""
self.gateway.write_log("行情服务器连接成功")
self.login()
def onFrontDisconnected(self, reason: int):
"""
Callback when front server is disconnected.
"""
self.login_status = False
self.gateway.write_log(f"行情服务器连接断开,原因{reason}")
def onRspUserLogin(self, error: dict, reqid: int, last: bool):
"""
Callback when user is logged in.
"""
if not error["ErrorID"]:
self.login_status = True
self.gateway.write_log("行情服务器登录成功")
for req in self.subscribed.values():
self.subscribe(req)
else:
self.gateway.write_error("行情服务器登录失败", error)
def onRspMarketData(self, data: dict, error: dict, reqid: int, last: bool):
"""
Callback of tick data update.
"""
print('on rsp', data, error)
symbol = data["TreatyCode"]
exchange = EXCHANGE_DA2VT.get(data["ExchangeCode"], None)
if not exchange:
return
timestamp = f"{data['TradeDay']} {data['Time']}"
tick = TickData(
symbol=symbol,
exchange=exchange,
datetime=datetime.strptime(timestamp, "%Y%m%d %H:%M:%S.%f"),
name=symbol_name_map[symbol],
volume=int(data["FilledNum"]),
open_interest=int(data["HoldNum"]),
limit_up=float(data["LimitUpPrice"]),
limit_down=float(data["LimitDownPrice"]),
last_price=float(data["CurrPrice"]),
open_price=float(data["Open"]),
high_price=float(data["High"]),
low_price=float(data["Low"]),
pre_close=float(data["PreSettlementPrice"]),
bid_price_1=float(data["BuyPrice"]),
bid_price_2=float(data["BuyPrice2"]),
bid_price_3=float(data["BuyPrice3"]),
bid_price_4=float(data["BuyPrice4"]),
bid_price_5=float(data["BuyPrice5"]),
ask_price_1=float(data["SalePrice"]),
ask_price_2=float(data["SalePrice2"]),
ask_price_3=float(data["SalePrice3"]),
ask_price_4=float(data["SalePrice4"]),
ask_price_5=float(data["SalePrice5"]),
bid_volume_1=int(data["BuyNumber"]),
bid_volume_2=int(data["BuyNumber2"]),
bid_volume_3=int(data["BuyNumber3"]),
bid_volume_4=int(data["BuyNumber4"]),
bid_volume_5=int(data["BuyNumber5"]),
ask_volume_1=int(data["SaleNumber"]),
ask_volume_2=int(data["SaleNumber2"]),
ask_volume_3=int(data["SaleNumber3"]),
ask_volume_4=int(data["SaleNumber4"]),
ask_volume_5=int(data["SaleNumber5"]),
gateway_name=self.gateway_name
)
self.gateway.on_tick(tick)
def connect(self, address: str, userid: str, password: str, auth_code: str):
"""
Start connection to server.
"""
self.userid = userid
self.password = password
self.auth_code = auth_code
# If not connected, then start connection first.
if not self.connect_status:
# path = get_folder_path(self.gateway_name.lower())
self.createMarketApi(True, "market_log.txt")
self.registerNameServer(address)
self.init()
self.connect_status = True
# If already connected, then login immediately.
elif not self.login_status:
self.login()
def login(self):
"""
Login onto server.
"""
req = {
"UserId": self.userid,
"UserPwd": self.password,
"AuthorCode": self.auth_code,
"MacAddress": self.mac_address,
"ComputerName": "Dev Server",
"SoftwareName": "vn.py",
"SoftwareVersion": "2.0",
}
self.reqid += 1
self.reqUserLogin(req, self.reqid)
def subscribe(self, req: SubscribeRequest):
"""
Subscribe to tick data update.
"""
if self.login_status:
da_exchange = EXCHANGE_VT2DA.get(req.exchange, "")
if not da_exchange:
self.gateway.write_log(f"不支持的交易所{req.exchange.value}")
return
da_code = f"{da_exchange},{req.symbol}"
da_req = {
"MarketType": DAF_TYPE_Future,
"SubscMode": DAF_SUB_Append,
"MarketCount": 1,
"MarketTrcode": da_code,
}
self.reqid += 1
i = self.reqMarketData(da_req, self.reqid)
print(i, da_req)
self.subscribed[req.symbol] = req
def close(self):
"""
Close the connection.
"""
if self.connect_status:
self.exit()
class DaFutureApi(FutureApi):
""""""
def __init__(self, gateway):
"""Constructor"""
super().__init__()
self.gateway = gateway
self.gateway_name = gateway.gateway_name
self.reqid = 0
self.order_ref = 0
self.connect_status = False
self.login_status = False
self.auth_staus = False
self.login_failed = False
self.userid = ""
self.password = ""
self.auth_code = ""
self.mac_address = get_mac_address()
def onFrontConnected(self):
""""""
self.gateway.write_log("交易服务器连接成功")
self.login()
def onFrontDisconnected(self, reason: int):
""""""
self.login_status = False
self.gateway.write_log(f"交易服务器连接断开,原因{reason}")
def onRspUserLogin(self, error: dict, reqid: int, last: bool):
""""""
if not error["ErrorID"]:
self.login_status = True
self.gateway.write_log("交易服务器登录成功")
# 查询可交易合约
for exchange in EXCHANGE_DA2VT.values():
self.query_contract(exchange)
else:
self.login_failed = True
self.gateway.write_error("交易服务器登录失败", error)
def onRspNeedVerify(self, firstLogin: bool, hasSetQA: bool):
""""""
print("on rsp need verify", firstLogin, hasSetQA)
def onRspOrderInsert(self, data: dict, error: dict, reqid: int, last: bool):
""""""
order_ref = data["OrderRef"]
orderid = f"{self.frontid}_{self.sessionid}_{order_ref}"
symbol = data["InstrumentID"]
exchange = symbol_exchange_map[symbol]
order = OrderData(
symbol=symbol,
exchange=exchange,
orderid=orderid,
direction=DIRECTION_DA2VT[data["Direction"]],
offset=OFFSET_DA2VT.get(data["CombOffsetFlag"], Offset.NONE),
price=data["LimitPrice"],
volume=data["VolumeTotalOriginal"],
status=Status.REJECTED,
gateway_name=self.gateway_name
)
self.gateway.on_order(order)
self.gateway.write_error("交易委托失败", error)
def onRspOrderAction(self, data: dict, error: dict, reqid: int, last: bool):
""""""
self.gateway.write_error("交易撤单失败", error)
def onRspQueryMaxOrderVolume(self, data: dict, error: dict, reqid: int, last: bool):
""""""
pass
def onRspSettlementInfoConfirm(self, data: dict, error: dict, reqid: int, last: bool):
"""
Callback of settlment info confimation.
"""
self.gateway.write_log("结算信息确认成功")
self.reqid += 1
self.reqQryInstrument({}, self.reqid)
def onRspQryInvestorPosition(self, data: dict, error: dict, reqid: int, last: bool):
""""""
if not data:
return
# Get buffered position object
key = f"{data['InstrumentID'], data['PosiDirection']}"
position = self.positions.get(key, None)
if not position:
position = PositionData(
symbol=data["InstrumentID"],
exchange=symbol_exchange_map[data["InstrumentID"]],
direction=DIRECTION_DA2VT[data["PosiDirection"]],
gateway_name=self.gateway_name
)
self.positions[key] = position
# For SHFE position data update
if position.exchange == Exchange.SHFE:
if data["YdPosition"] and not data["TodayPosition"]:
position.yd_volume = data["Position"]
# For other exchange position data update
else:
position.yd_volume = data["Position"] - data["TodayPosition"]
# Get contract size (spread contract has no size value)
size = symbol_size_map.get(position.symbol, 0)
# Calculate previous position cost
cost = position.price * position.volume * size
# Update new position volume
position.volume += data["Position"]
position.pnl += data["PositionProfit"]
# Calculate average position price
if position.volume and size:
cost += data["PositionCost"]
position.price = cost / (position.volume * size)
# Get frozen volume
if position.direction == Direction.LONG:
position.frozen += data["ShortFrozen"]
else:
position.frozen += data["LongFrozen"]
if last:
for position in self.positions.values():
self.gateway.on_position(position)
self.positions.clear()
def onRspQryTradingAccount(self, data: dict, error: dict, reqid: int, last: bool):
""""""
if "AccountID" not in data:
return
account = AccountData(
accountid=data["AccountID"],
balance=data["Balance"],
frozen=data["FrozenMargin"] + data["FrozenCash"] + data["FrozenCommission"],
gateway_name=self.gateway_name
)
account.available = data["Available"]
self.gateway.on_account(account)
def onRspQryExchange(self, data: dict, error: dict, reqid: int, last: bool):
"""
Callback of instrument query.
"""
print(data)
def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool):
"""
Callback of instrument query.
"""
product = PRODUCT_DA2VT.get(data["CommodityType"], None)
if product:
contract = ContractData(
symbol=data["CommodityCode"],
exchange=EXCHANGE_DA2VT[data["ExchangeNo"]],
name=data["ContractFName"],
product=product,
size=data["ProductDot"] / data["UpperTick"],
pricetick=data["UpperTick"],
gateway_name=self.gateway_name
)
self.gateway.on_contract(contract)
if last:
self.gateway.write_log("合约信息查询成功")
def onRtnOrder(self, data: dict):
"""
Callback of order status update.
"""
symbol = data["InstrumentID"]
exchange = symbol_exchange_map.get(symbol, "")
if not exchange:
self.order_data.append(data)
return
frontid = data["FrontID"]
sessionid = data["SessionID"]
order_ref = data["OrderRef"]
orderid = f"{frontid}_{sessionid}_{order_ref}"
order = OrderData(
symbol=symbol,
exchange=exchange,
orderid=orderid,
type=ORDERTYPE_DA2VT[data["OrderPriceType"]],
direction=DIRECTION_DA2VT[data["Direction"]],
offset=OFFSET_DA2VT[data["CombOffsetFlag"]],
price=data["LimitPrice"],
volume=data["VolumeTotalOriginal"],
traded=data["VolumeTraded"],
status=STATUS_DA2VT[data["OrderStatus"]],
time=data["InsertTime"],
gateway_name=self.gateway_name
)
self.gateway.on_order(order)
self.sysid_orderid_map[data["OrderSysID"]] = orderid
def onRtnTrade(self, data: dict):
"""
Callback of trade status update.
"""
symbol = data["InstrumentID"]
exchange = symbol_exchange_map.get(symbol, "")
if not exchange:
self.trade_data.append(data)
return
orderid = self.sysid_orderid_map[data["OrderSysID"]]
trade = TradeData(
symbol=symbol,
exchange=exchange,
orderid=orderid,
tradeid=data["TradeID"],
direction=DIRECTION_DA2VT[data["Direction"]],
offset=OFFSET_DA2VT[data["OffsetFlag"]],
price=data["Price"],
volume=data["Volume"],
time=data["TradeTime"],
gateway_name=self.gateway_name
)
self.gateway.on_trade(trade)
def connect(
self,
address: str,
userid: str,
password: str,
auth_code: str
):
"""
Start connection to server.
"""
self.userid = userid
self.password = password
self.auth_code = auth_code
if not self.connect_status:
#path = get_folder_path(self.gateway_name.lower())
self.createFutureApi(True, "future_log.txt")
self.registerNameServer(address)
self.init()
self.connect_status = True
else:
self.login()
def authenticate(self):
"""
Authenticate with auth_code and appid.
"""
req = {
"UserID": self.userid,
"BrokerID": self.brokerid,
"AuthCode": self.auth_code,
"AppID": self.appid
}
if self.product_info:
req["UserProductInfo"] = self.product_info
self.reqid += 1
self.reqAuthenticate(req, self.reqid)
def login(self):
"""
Login onto server.
"""
req = {
"UserId": self.userid,
"UserPwd": self.password,
"AuthorCode": self.auth_code,
"MacAddress": self.mac_address,
"ComputerName": "Dev Server",
"SoftwareName": "vn.py",
"SoftwareVersion": "2.0",
}
self.reqid += 1
n = self.reqUserLogin(req, self.reqid)
print("login", n)
def send_order(self, req: OrderRequest):
"""
Send new order.
"""
self.order_ref += 1
da_req = {
"InstrumentID": req.symbol,
"ExchangeID": req.exchange.value,
"LimitPrice": req.price,
"VolumeTotalOriginal": int(req.volume),
"OrderPriceType": ORDERTYPE_VT2DA.get(req.type, ""),
"Direction": DIRECTION_VT2DA.get(req.direction, ""),
"CombOffsetFlag": OFFSET_VT2DA.get(req.offset, ""),
"OrderRef": str(self.order_ref),
"InvestorID": self.userid,
"UserID": self.userid,
"BrokerID": self.brokerid,
"CombHedgeFlag": THOST_FTDC_HF_Speculation,
"ContingentCondition": THOST_FTDC_CC_Immediately,
"ForceCloseReason": THOST_FTDC_FCC_NotForceClose,
"IsAutoSuspend": 0,
"TimeCondition": THOST_FTDC_TC_GFD,
"VolumeCondition": THOST_FTDC_VC_AV,
"MinVolume": 1
}
if req.type == OrderType.FAK:
da_req["OrderPriceType"] = THOST_FTDC_OPT_LimitPrice
da_req["TimeCondition"] = THOST_FTDC_TC_IOC
da_req["VolumeCondition"] = THOST_FTDC_VC_AV
elif req.type == OrderType.FOK:
da_req["OrderPriceType"] = THOST_FTDC_OPT_LimitPrice
da_req["TimeCondition"] = THOST_FTDC_TC_IOC
da_req["VolumeCondition"] = THOST_FTDC_VC_CV
self.reqid += 1
self.reqOrderInsert(da_req, self.reqid)
orderid = f"{self.frontid}_{self.sessionid}_{self.order_ref}"
order = req.create_order_data(orderid, self.gateway_name)
self.gateway.on_order(order)
return order.vt_orderid
def cancel_order(self, req: CancelRequest):
"""
Cancel existing order.
"""
frontid, sessionid, order_ref = req.orderid.split("_")
da_req = {
"InstrumentID": req.symbol,
"ExchangeID": req.exchange.value,
"OrderRef": order_ref,
"FrontID": int(frontid),
"SessionID": int(sessionid),
"ActionFlag": THOST_FTDC_AF_Delete,
"BrokerID": self.brokerid,
"InvestorID": self.userid
}
self.reqid += 1
self.reqOrderAction(da_req, self.reqid)
def query_account(self):
"""
Query account balance data.
"""
self.reqid += 1
self.reqQryTradingAccount({}, self.reqid)
def query_position(self):
"""
Query position holding data.
"""
if not symbol_exchange_map:
return
req = {
"BrokerID": self.brokerid,
"InvestorID": self.userid
}
self.reqid += 1
self.reqQryInvestorPosition(req, self.reqid)
def query_contract(self, exchange, page=1):
"""
Query contract data.
"""
da_exchange = EXCHANGE_VT2DA[exchange]
req = {
"PageIndex": page,
"ExchangeNo": da_exchange
}
self.reqid += 1
self.reqQryInstrument(req, self.reqid)
def close(self):
""""""
if self.connect_status:
self.exit()
def get_network_interface():
""""""
c = wmi.WMI()
interfaces = c.Win32_NetworkAdapterConfiguration(IPEnabled=1)
if not interfaces:
return None
# Use interface with default ip gateway
for interface in interfaces:
if interface.DefaultIPGateway:
return interface
# Otherwise use last one
return interface
def get_mac_address():
""""""
interface = get_network_interface()
if not interface:
return ""
return interface.MACAddress