From 9e5258b8df7e3351b545553954cf0bec6dc3d310 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 21 May 2019 11:11:51 +0800 Subject: [PATCH 1/5] [Del] remove duplicate line --- vnpy/trader/database/database_sql.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/vnpy/trader/database/database_sql.py b/vnpy/trader/database/database_sql.py index 6415c1bb..6111cfae 100644 --- a/vnpy/trader/database/database_sql.py +++ b/vnpy/trader/database/database_sql.py @@ -311,8 +311,6 @@ def init_models(db: Database, driver: Driver): else: for c in chunked(dicts, 50): DbTickData.insert_many(c).on_conflict_replace().execute() - DbTickData.insert_many( - c).on_conflict_replace().execute() db.connect() db.create_tables([DbBarData, DbTickData]) From b56d0ce160d307ce9ee4a18b8791099971e313a0 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 21 May 2019 14:26:55 +0800 Subject: [PATCH 2/5] [Add] XtpGateway support margin trading --- tests/trader/run.py | 26 +++++----- vnpy/gateway/xtp/xtp_gateway.py | 86 ++++++++++++++++++++++++++++++--- 2 files changed, 91 insertions(+), 21 deletions(-) diff --git a/tests/trader/run.py b/tests/trader/run.py index b06b4af4..610e6f7d 100644 --- a/tests/trader/run.py +++ b/tests/trader/run.py @@ -35,20 +35,20 @@ def main(): main_engine = MainEngine(event_engine) main_engine.add_gateway(XtpGateway) - main_engine.add_gateway(CtpGateway) + # main_engine.add_gateway(CtpGateway) # main_engine.add_gateway(CtptestGateway) - main_engine.add_gateway(FemasGateway) - main_engine.add_gateway(IbGateway) - main_engine.add_gateway(FutuGateway) - main_engine.add_gateway(BitmexGateway) - main_engine.add_gateway(TigerGateway) - main_engine.add_gateway(OesGateway) - main_engine.add_gateway(OkexGateway) - main_engine.add_gateway(HuobiGateway) - main_engine.add_gateway(BitfinexGateway) - main_engine.add_gateway(OnetokenGateway) - main_engine.add_gateway(OkexfGateway) - main_engine.add_gateway(HbdmGateway) + # main_engine.add_gateway(FemasGateway) + # main_engine.add_gateway(IbGateway) + # main_engine.add_gateway(FutuGateway) + # main_engine.add_gateway(BitmexGateway) + # main_engine.add_gateway(TigerGateway) + # main_engine.add_gateway(OesGateway) + # main_engine.add_gateway(OkexGateway) + # main_engine.add_gateway(HuobiGateway) + # main_engine.add_gateway(BitfinexGateway) + # main_engine.add_gateway(OnetokenGateway) + # main_engine.add_gateway(OkexfGateway) + # main_engine.add_gateway(HbdmGateway) main_engine.add_app(CtaStrategyApp) main_engine.add_app(CtaBacktesterApp) diff --git a/vnpy/gateway/xtp/xtp_gateway.py b/vnpy/gateway/xtp/xtp_gateway.py index 0d8d784d..fbaff25b 100644 --- a/vnpy/gateway/xtp/xtp_gateway.py +++ b/vnpy/gateway/xtp/xtp_gateway.py @@ -17,6 +17,7 @@ from vnpy.api.xtp.vnxtp import ( XTPOrderInfo, XTPTradeReport, XTPOrderCancelInfo, + XTPCrdDebtInfo, XTPQueryStkPositionRsp, XTPQueryAssetRsp, XTPStructuredFundInfo, @@ -32,6 +33,11 @@ from vnpy.api.xtp.vnxtp import ( XTP_TE_RESUME_TYPE, XTP_SIDE_BUY, XTP_SIDE_SELL, + XTP_SIDE_MARGIN_TRADE, + XTP_SIDE_SHORT_SELL, + XTP_SIDE_REPAY_MARGIN, + XTP_SIDE_REPAY_STOCK, + XTP_ACCOUNT_TYPE, XTP_BUSINESS_TYPE, XTP_TICKER_TYPE, XTP_MARKET_TYPE, @@ -40,7 +46,7 @@ from vnpy.api.xtp.vnxtp import ( ) from vnpy.event import EventEngine from vnpy.trader.event import EVENT_TIMER -from vnpy.trader.constant import Exchange, Product, Direction, OrderType, Status +from vnpy.trader.constant import Exchange, Product, Direction, OrderType, Status, Offset from vnpy.trader.gateway import BaseGateway from vnpy.trader.object import (CancelRequest, OrderRequest, SubscribeRequest, TickData, ContractData, OrderData, TradeData, @@ -71,9 +77,17 @@ PRODUCT_XTP2VT = { XTP_TICKER_TYPE.XTP_TICKER_TYPE_OPTION: Product.OPTION } +# DIRECTION_VT2XTP = { +# Direction.LONG: XTP_SIDE_BUY, +# Direction.SHORT: XTP_SIDE_SELL +# } DIRECTION_VT2XTP = { - Direction.LONG: XTP_SIDE_BUY, - Direction.SHORT: XTP_SIDE_SELL + (Direction.LONG, Offset.OPEN): XTP_SIDE_MARGIN_TRADE, + (Direction.SHORT, Offset.CLOSE): XTP_SIDE_REPAY_MARGIN, + (Direction.SHORT, Offset.OPEN): XTP_SIDE_SHORT_SELL, + (Direction.LONG, Offset.CLOSE): XTP_SIDE_REPAY_STOCK, + (Direction.SHORT, Offset.NONE): XTP_SIDE_BUY, + (Direction.LONG, Offset.NONE): XTP_SIDE_SELL, } DIRECTION_XTP2VT = {v: k for k, v in DIRECTION_VT2XTP.items()} @@ -95,6 +109,7 @@ STATUS_XTP2VT = { symbol_name_map = {} +symbol_exchange_map = {} class XtpGateway(BaseGateway): @@ -428,6 +443,9 @@ class XtpQuoteApi(API.QuoteSpi): symbol_name_map[contract.vt_symbol] = contract.name + if contract.product != Product.INDEX: + symbol_exchange_map[contract.symbol] = contract.exchange + if is_last: self.gateway.write_log(f"{contract.exchange.value}合约信息查询成功") @@ -487,6 +505,13 @@ class XtpTraderApi(API.TraderSpi): self.session_id = 0 self.reqid = 0 + # Whether current account supports margin or option + self.margin_trading = False + self.option_trading = False + + # + self.short_positions = {} + def connect( self, userid: str, @@ -564,9 +589,13 @@ class XtpTraderApi(API.TraderSpi): xtp_req.market = MARKET_VT2XTP[req.exchange] xtp_req.price = req.price xtp_req.quantity = int(req.volume) - xtp_req.side = DIRECTION_VT2XTP[req.direction] + xtp_req.side = DIRECTION_VT2XTP.get((req.direction, req.offset), "") xtp_req.price_type = ORDERTYPE_VT2XTP[req.type] - xtp_req.business_type = XTP_BUSINESS_TYPE.XTP_BUSINESS_TYPE_CASH + + if req.offset == Offset.NONE: + xtp_req.business_type = XTP_BUSINESS_TYPE.XTP_BUSINESS_TYPE_CASH + else: + xtp_req.business_type = XTP_BUSINESS_TYPE.XTP_BUSINESS_TYPE_MARGIN orderid = self.api.InsertOrder(xtp_req, self.session_id) @@ -595,6 +624,10 @@ class XtpTraderApi(API.TraderSpi): self.reqid += 1 self.api.QueryPosition("", self.session_id, self.reqid) + if self.margin_trading: + self.reqid += 1 + self.api.QueryCreditDebtInfo(self.session_id, self.reqid) + def check_error(self, func_name: str, error_info: XTPRspInfoStruct): """""" if error_info and error_info.error_id: @@ -617,12 +650,15 @@ class XtpTraderApi(API.TraderSpi): """""" self.check_error("委托下单", error_info) + direction, offset = DIRECTION_XTP2VT[ order_info.side] + order = OrderData( symbol=order_info.ticker, exchange=MARKET_XTP2VT[order_info.market], orderid=str(order_info.order_xtp_id), type=ORDERTYPE_XTP2VT[order_info.price_type], - direction=DIRECTION_XTP2VT[order_info.side], + direction=direction, + offset=offset, price=order_info.price, volume=order_info.quantity, traded=order_info.qty_traded, @@ -635,12 +671,15 @@ class XtpTraderApi(API.TraderSpi): def OnTradeEvent(self, trade_info: XTPTradeReport, session_id: int) -> Any: """""" + direction, offset = DIRECTION_XTP2VT[trade_info.side] + trade = TradeData( symbol=trade_info.ticker, exchange=MARKET_XTP2VT[trade_info.market], orderid=str(trade_info.order_xtp_id), tradeid=str(trade_info.exec_id), - direction=DIRECTION_XTP2VT[trade_info.side], + direction=direction, + offset=offset, price=trade_info.price, volume=trade_info.quantity, time=trade_info.trade_time, @@ -682,7 +721,7 @@ class XtpTraderApi(API.TraderSpi): position = PositionData( symbol=xtp_position.ticker, exchange=MARKET_XTP2VT[xtp_position.market], - direction=Direction.NET, + direction=Direction.LONG, volume=xtp_position.total_qty, frozen=xtp_position.locked_position, price=xtp_position.avg_price, @@ -703,6 +742,11 @@ class XtpTraderApi(API.TraderSpi): ) self.gateway.on_account(account) + if asset.account_type == XTP_ACCOUNT_TYPE.XTP_ACCOUNT_CREDIT: + self.margin_trading = True + elif asset.account_type == XTP_ACCOUNT_TYPE.XTP_ACCOUNT_DERIVE: + self.option_trading = True + def OnQueryStructuredFund(self, fund_info: XTPStructuredFundInfo, error_info: XTPRspInfoStruct, is_last: bool, session_id: int) -> Any: """""" @@ -741,3 +785,29 @@ class XtpTraderApi(API.TraderSpi): is_last: bool, session_id: int) -> Any: """""" pass + + def OnQueryCreditDebtInfo(self, debt_info: XTPCrdDebtInfo, error_info: XTPRspInfoStruct, + request_id: int, is_last: bool, session_id: int) -> Any: + """""" + if debt_info.debt_type == 1: + symbol = debt_info.ticker + exchange = MARKET_XTP2VT[debt_info.market] + + position = self.short_positions.get(symbol, None) + if not position: + position = PositionData( + symbol=symbol, + exchange=exchange, + direction=Direction.SHORT, + gateway_name=self.gateway_name + ) + self.short_positions[symbol] = position + + position.volume += debt_info.remain_qty + + if is_last: + for position in self.short_positions.values(): + self.gateway.on_position(position) + + self.short_positions.clear() + From f316c5412c99c3d9a048e5bef96687778d87c1c7 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Wed, 22 May 2019 11:29:28 +0800 Subject: [PATCH 3/5] [Fix] change contract map string --- vnpy/gateway/hbdm/hbdm_gateway.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vnpy/gateway/hbdm/hbdm_gateway.py b/vnpy/gateway/hbdm/hbdm_gateway.py index f1848c09..fe0d93dc 100644 --- a/vnpy/gateway/hbdm/hbdm_gateway.py +++ b/vnpy/gateway/hbdm/hbdm_gateway.py @@ -84,7 +84,7 @@ INTERVAL_VT2HBDM = { CONTRACT_TYPE_MAP = { "this_week": "CW", "next_week": "NW", - "this_quarter": "CQ" + "quarter": "CQ" } @@ -654,7 +654,7 @@ class HbdmRestApi(RestClient): ) self.gateway.on_contract(contract) - symbol_type_map[contract.symbol] = d['contract_type'] + symbol_type_map[contract.symbol] = d["contract_type"] self.gateway.write_log("合约信息查询成功") From f30fce70bda45c1d07bf5bcc365a426146a76980 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Wed, 22 May 2019 15:18:32 +0800 Subject: [PATCH 4/5] [Add] relogin after disconnected --- vnpy/gateway/xtp/xtp_gateway.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vnpy/gateway/xtp/xtp_gateway.py b/vnpy/gateway/xtp/xtp_gateway.py index fbaff25b..9a66f309 100644 --- a/vnpy/gateway/xtp/xtp_gateway.py +++ b/vnpy/gateway/xtp/xtp_gateway.py @@ -306,6 +306,8 @@ class XtpQuoteApi(API.QuoteSpi): """""" self.gateway.write_log("行情服务器连接断开") + self.login() + def OnError(self, error_info: XTPRspInfoStruct) -> Any: """""" self.check_error("行情接口", error_info) @@ -641,6 +643,8 @@ class XtpTraderApi(API.TraderSpi): """""" self.gateway.write_log("交易服务器连接断开") + self.login() + def OnError(self, error_info: XTPRspInfoStruct) -> Any: """""" self.check_error("交易接口", error_info) From cb54d52e86707d92e5eb8cee589016ae2a6831d2 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Thu, 23 May 2019 09:42:57 +0800 Subject: [PATCH 5/5] [Mod] flake8 code quanlity improve --- tests/trader/run.py | 26 +++++++++++++------------- vnpy/gateway/xtp/xtp_gateway.py | 3 +-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/trader/run.py b/tests/trader/run.py index 610e6f7d..b06b4af4 100644 --- a/tests/trader/run.py +++ b/tests/trader/run.py @@ -35,20 +35,20 @@ def main(): main_engine = MainEngine(event_engine) main_engine.add_gateway(XtpGateway) - # main_engine.add_gateway(CtpGateway) + main_engine.add_gateway(CtpGateway) # main_engine.add_gateway(CtptestGateway) - # main_engine.add_gateway(FemasGateway) - # main_engine.add_gateway(IbGateway) - # main_engine.add_gateway(FutuGateway) - # main_engine.add_gateway(BitmexGateway) - # main_engine.add_gateway(TigerGateway) - # main_engine.add_gateway(OesGateway) - # main_engine.add_gateway(OkexGateway) - # main_engine.add_gateway(HuobiGateway) - # main_engine.add_gateway(BitfinexGateway) - # main_engine.add_gateway(OnetokenGateway) - # main_engine.add_gateway(OkexfGateway) - # main_engine.add_gateway(HbdmGateway) + main_engine.add_gateway(FemasGateway) + main_engine.add_gateway(IbGateway) + main_engine.add_gateway(FutuGateway) + main_engine.add_gateway(BitmexGateway) + main_engine.add_gateway(TigerGateway) + main_engine.add_gateway(OesGateway) + main_engine.add_gateway(OkexGateway) + main_engine.add_gateway(HuobiGateway) + main_engine.add_gateway(BitfinexGateway) + main_engine.add_gateway(OnetokenGateway) + main_engine.add_gateway(OkexfGateway) + main_engine.add_gateway(HbdmGateway) main_engine.add_app(CtaStrategyApp) main_engine.add_app(CtaBacktesterApp) diff --git a/vnpy/gateway/xtp/xtp_gateway.py b/vnpy/gateway/xtp/xtp_gateway.py index 9a66f309..4c3fa492 100644 --- a/vnpy/gateway/xtp/xtp_gateway.py +++ b/vnpy/gateway/xtp/xtp_gateway.py @@ -654,7 +654,7 @@ class XtpTraderApi(API.TraderSpi): """""" self.check_error("委托下单", error_info) - direction, offset = DIRECTION_XTP2VT[ order_info.side] + direction, offset = DIRECTION_XTP2VT[order_info.side] order = OrderData( symbol=order_info.ticker, @@ -814,4 +814,3 @@ class XtpTraderApi(API.TraderSpi): self.gateway.on_position(position) self.short_positions.clear() -