From f5917b9cdc9cd8e81234a917eef0848eb270d80c Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 25 Mar 2019 14:50:41 +0800 Subject: [PATCH] [Add]net_position member of ContractData --- vnpy/gateway/bitmex/bitmex_gateway.py | 1 + vnpy/gateway/futu/futu_gateway.py | 1 + vnpy/gateway/ib/ib_gateway.py | 1 + vnpy/gateway/oes/oes_td.py | 1 + vnpy/gateway/tiger/tiger_gateway.py | 140 ++++++++++++++------------ vnpy/trader/object.py | 1 + 6 files changed, 83 insertions(+), 62 deletions(-) diff --git a/vnpy/gateway/bitmex/bitmex_gateway.py b/vnpy/gateway/bitmex/bitmex_gateway.py index 03536083..3c3e6879 100644 --- a/vnpy/gateway/bitmex/bitmex_gateway.py +++ b/vnpy/gateway/bitmex/bitmex_gateway.py @@ -607,6 +607,7 @@ class BitmexWebsocketApi(WebsocketClient): pricetick=d["tickSize"], size=d["lotSize"], stop_supported=True, + net_position=True, gateway_name=self.gateway_name, ) diff --git a/vnpy/gateway/futu/futu_gateway.py b/vnpy/gateway/futu/futu_gateway.py index 6b2e7635..c6205da2 100644 --- a/vnpy/gateway/futu/futu_gateway.py +++ b/vnpy/gateway/futu/futu_gateway.py @@ -303,6 +303,7 @@ class FutuGateway(BaseGateway): product=product, size=1, pricetick=0.001, + net_position=True, gateway_name=self.gateway_name, ) self.on_contract(contract) diff --git a/vnpy/gateway/ib/ib_gateway.py b/vnpy/gateway/ib/ib_gateway.py index 87d7bde1..c50dc520 100644 --- a/vnpy/gateway/ib/ib_gateway.py +++ b/vnpy/gateway/ib/ib_gateway.py @@ -459,6 +459,7 @@ class IbApi(EWrapper): product=PRODUCT_IB2VT[ib_product], size=ib_size, pricetick=contractDetails.minTick, + net_position=True, gateway_name=self.gateway_name, ) diff --git a/vnpy/gateway/oes/oes_td.py b/vnpy/gateway/oes/oes_td.py index 0ce0882d..dccb3dfb 100644 --- a/vnpy/gateway/oes/oes_td.py +++ b/vnpy/gateway/oes/oes_td.py @@ -468,6 +468,7 @@ class OesTdApi: name=data.securityName, product=PRODUCT_OES2VT[data.mktId], size=data.buyQtyUnit, + net_position=True, pricetick=data.priceUnit, ) self.gateway.on_contract(contract) diff --git a/vnpy/gateway/tiger/tiger_gateway.py b/vnpy/gateway/tiger/tiger_gateway.py index 29151d0a..eecd9305 100644 --- a/vnpy/gateway/tiger/tiger_gateway.py +++ b/vnpy/gateway/tiger/tiger_gateway.py @@ -14,7 +14,7 @@ import traceback import pandas as pd from pandas import DataFrame -from tigeropen.tiger_open_config import TigerOpenClientConfig +from tigeropen.tiger_open_config import TigerOpenClientConfig from tigeropen.common.consts import Language, Currency, Market from tigeropen.quote.quote_client import QuoteClient from tigeropen.trade.trade_client import TradeClient @@ -33,16 +33,16 @@ from vnpy.trader.object import ( PositionData, SubscribeRequest, OrderRequest, - CancelRequest, + CancelRequest, ) PRODUCT_VT2TIGER = { - Product.EQUITY: "STK", - Product.OPTION: "OPT", - Product.WARRANT: "WAR", + Product.EQUITY: "STK", + Product.OPTION: "OPT", + Product.WARRANT: "WAR", Product.WARRANT: "IOPT", - Product.FUTURES: "FUT", - Product.OPTION: "FOP", + Product.FUTURES: "FUT", + Product.OPTION: "FOP", Product.FOREX: "CASH", } @@ -88,7 +88,7 @@ PUSH_STATUS_TIGER2VT = { class TigerGateway(BaseGateway): """""" - default_setting = { + default_setting = { "tiger_id": "", "account": "", "standard_account": "", @@ -131,7 +131,7 @@ class TigerGateway(BaseGateway): func(*args) except Empty: pass - + def add_task(self, func, *args): """""" self.queue.put((func, [*args])) @@ -172,7 +172,8 @@ class TigerGateway(BaseGateway): """ try: self.quote_client = QuoteClient(self.client_config) - self.symbol_names = dict(self.quote_client.get_symbol_names(lang=Language.zh_CN)) + self.symbol_names = dict( + self.quote_client.get_symbol_names(lang=Language.zh_CN)) self.query_contract() except ApiException: self.write_log("查询合约失败") @@ -180,7 +181,7 @@ class TigerGateway(BaseGateway): self.write_log("行情接口连接成功") self.write_log("合约查询成功") - + def connect_trade(self): """ Connect to trade server. @@ -193,16 +194,17 @@ class TigerGateway(BaseGateway): except ApiException: self.write_log("交易接口连接失败") return - + self.write_log("交易接口连接成功") - + def connect_push(self): """ Connect to push server. """ protocol, host, port = self.client_config.socket_host_port self.push_client = PushClient(host, port, (protocol == 'ssl')) - self.push_client.connect(self.client_config.tiger_id, self.client_config.private_key) + self.push_client.connect( + self.client_config.tiger_id, self.client_config.private_key) self.push_client.quote_changed = self.on_quote_change self.push_client.asset_changed = self.on_asset_change @@ -233,22 +235,22 @@ class TigerGateway(BaseGateway): name=self.symbol_names[symbol], ) self.ticks[symbol] = tick - + tick.datetime = datetime.fromtimestamp(data["latest_time"] / 1000) tick.pre_close = data.get("prev_close", 0) tick.last_price = data.get("latest_price", 0) tick.volume = data.get("volume", 0) tick.open_price = data.get("open", 0) - tick.open_price = data.get("open", 0) - tick.high_price = data.get("high", 0) - tick.low_price = data.get("low", 0) + tick.open_price = data.get("open", 0) + tick.high_price = data.get("high", 0) + tick.low_price = data.get("low", 0) tick.ask_price_1 = data.get("ask_price", 0) - tick.bid_price_1 = data.get("bid_price", 0) - tick.ask_volume_1 = data.get("ask_size", 0) - tick.bid_volume_1 = data.get("bid_size", 0) + tick.bid_price_1 = data.get("bid_price", 0) + tick.ask_volume_1 = data.get("ask_size", 0) + tick.bid_volume_1 = data.get("bid_size", 0) self.on_tick(copy(tick)) - + def on_asset_change(self, tiger_account: str, data: list): """""" data = dict(data) @@ -261,7 +263,7 @@ class TigerGateway(BaseGateway): frozen=0.0, gateway_name=self.gateway_name, ) - self.on_account(account) + self.on_account(account) def on_position_change(self, tiger_account: str, data: list): """""" @@ -281,22 +283,25 @@ class TigerGateway(BaseGateway): self.on_position(pos) def on_order_change(self, tiger_account: str, data: list): - """""" + """""" data = dict(data) - print("委托推送", data["origin_symbol"], data["order_id"], data["filled"], data["status"]) + print("委托推送", data["origin_symbol"], + data["order_id"], data["filled"], data["status"]) symbol, exchange = convert_symbol_tiger2vt(data["origin_symbol"]) status = PUSH_STATUS_TIGER2VT[data["status"]] - + order = OrderData( symbol=symbol, exchange=exchange, - orderid=self.ID_TIGER2VT.get(str(data["order_id"]), self.get_new_local_id()), + orderid=self.ID_TIGER2VT.get( + str(data["order_id"]), self.get_new_local_id()), direction=Direction.NET, price=data.get("limit_price", 0), volume=data["quantity"], traded=data["filled"], status=status, - time=datetime.fromtimestamp(data["order_time"] / 1000).strftime("%H:%M:%S"), + time=datetime.fromtimestamp( + data["order_time"] / 1000).strftime("%H:%M:%S"), gateway_name=self.gateway_name, ) self.on_order(order) @@ -312,19 +317,20 @@ class TigerGateway(BaseGateway): orderid=self.ID_TIGER2VT[str(data["order_id"])], price=data["avg_fill_price"], volume=data["filled"], - time=datetime.fromtimestamp(data["trade_time"] / 1000).strftime("%H:%M:%S"), + time=datetime.fromtimestamp( + data["trade_time"] / 1000).strftime("%H:%M:%S"), gateway_name=self.gateway_name, ) self.on_trade(trade) def get_new_local_id(self): - self.local_id += 1 + self.local_id += 1 return self.local_id - + def send_order(self, req: OrderRequest): """""" local_id = self.get_new_local_id() - order = req.create_order_data(local_id, self.gateway_name) + order = req.create_order_data(local_id, self.gateway_name) self.on_order(order) self.add_task(self._send_order, req, local_id) @@ -332,22 +338,24 @@ class TigerGateway(BaseGateway): def _send_order(self, req: OrderRequest, local_id): """""" - currency = config_symbol_currency(req.symbol) - try: - contract = self.trade_client.get_contracts(symbol=req.symbol, currency=currency)[0] + currency = config_symbol_currency(req.symbol) + try: + contract = self.trade_client.get_contracts( + symbol=req.symbol, currency=currency)[0] order = self.trade_client.create_order( - account=self.account, - contract=contract, - action=DIRECTION_VT2TIGER[req.direction], - order_type=ORDERTYPE_VT2TIGER[req.type], - quantity=int(req.volume), + account=self.account, + contract=contract, + action=DIRECTION_VT2TIGER[req.direction], + order_type=ORDERTYPE_VT2TIGER[req.type], + quantity=int(req.volume), limit_price=req.price, ) self.ID_TIGER2VT[str(order.order_id)] = local_id self.ID_VT2TIGER[local_id] = str(order.order_id) self.trade_client.place_order(order) - print("发单:", order.contract.symbol, order.order_id, order.quantity, order.status) + print("发单:", order.contract.symbol, + order.order_id, order.quantity, order.status) except: # noqa traceback.print_exc() @@ -372,9 +380,11 @@ class TigerGateway(BaseGateway): def query_contract(self): """""" # HK Stock - - symbols_names_HK = self.quote_client.get_symbol_names(lang=Language.zh_CN, market=Market.HK) - contract_names_HK = DataFrame(symbols_names_HK, columns=['symbol', 'name']) + + symbols_names_HK = self.quote_client.get_symbol_names( + lang=Language.zh_CN, market=Market.HK) + contract_names_HK = DataFrame( + symbols_names_HK, columns=['symbol', 'name']) contractList = list(contract_names_HK["symbol"]) i, n = 0, len(contractList) @@ -386,8 +396,9 @@ class TigerGateway(BaseGateway): result = result.append(r) contract_detail_HK = result.sort_values(by="symbol", ascending=True) - contract_HK = pd.merge(contract_names_HK, contract_detail_HK, how='left', on='symbol') - + contract_HK = pd.merge( + contract_names_HK, contract_detail_HK, how='left', on='symbol') + for ix, row in contract_HK.iterrows(): contract = ContractData( symbol=row["symbol"], @@ -396,13 +407,15 @@ class TigerGateway(BaseGateway): product=Product.EQUITY, size=1, pricetick=row["min_tick"], + net_position=True, gateway_name=self.gateway_name, ) self.on_contract(contract) self.contracts[contract.vt_symbol] = contract # US Stock - symbols_names_US = self.quote_client.get_symbol_names(lang=Language.zh_CN, market=Market.US) + symbols_names_US = self.quote_client.get_symbol_names( + lang=Language.zh_CN, market=Market.US) contract_US = DataFrame(symbols_names_US, columns=['symbol', 'name']) for ix, row in contract_US.iterrows(): @@ -419,7 +432,8 @@ class TigerGateway(BaseGateway): self.contracts[contract.vt_symbol] = contract # CN Stock - symbols_names_CN = self.quote_client.get_symbol_names(lang=Language.zh_CN, market=Market.CN) + symbols_names_CN = self.quote_client.get_symbol_names( + lang=Language.zh_CN, market=Market.CN) contract_CN = DataFrame(symbols_names_CN, columns=['symbol', 'name']) for ix, row in contract_CN.iterrows(): @@ -437,7 +451,7 @@ class TigerGateway(BaseGateway): ) self.on_contract(contract) self.contracts[contract.vt_symbol] = contract - + def query_account(self): """""" try: @@ -446,7 +460,7 @@ class TigerGateway(BaseGateway): self.write_log("查询资金失败") return - for i in assets: + for i in assets: account = AccountData( accountid=self.account, balance=i.summary.net_liquidation, @@ -465,7 +479,7 @@ class TigerGateway(BaseGateway): return for i in position: - symbol, exchange = convert_symbol_tiger2vt(i.contract.symbol) + symbol, exchange = convert_symbol_tiger2vt(i.contract.symbol) pos = PositionData( symbol=symbol, @@ -473,13 +487,13 @@ class TigerGateway(BaseGateway): direction=Direction.NET, volume=int(i.quantity), frozen=0.0, - price=i.average_cost, - pnl=float(i.unrealized_pnl), + price=i.average_cost, + pnl=float(i.unrealized_pnl), gateway_name=self.gateway_name, ) self.on_position(pos) - + def query_order(self): """""" try: @@ -502,7 +516,7 @@ class TigerGateway(BaseGateway): def process_order(self, data): """""" - for i in data: + for i in data: symbol, exchange = convert_symbol_tiger2vt(str(i.contract)) local_id = self.get_new_local_id() @@ -515,16 +529,17 @@ class TigerGateway(BaseGateway): volume=i.quantity, traded=i.filled, status=STATUS_TIGER2VT[i.status], - time=datetime.fromtimestamp(i.order_time / 1000).strftime("%H:%M:%S"), + time=datetime.fromtimestamp( + i.order_time / 1000).strftime("%H:%M:%S"), gateway_name=self.gateway_name, ) - self.ID_TIGER2VT[str(i.order_id)] = local_id + self.ID_TIGER2VT[str(i.order_id)] = local_id self.on_order(order) self.ID_VT2TIGER = {v: k for k, v in self.ID_TIGER2VT.items()} print("原始委托字典", self.ID_TIGER2VT) print("原始反向字典", self.ID_VT2TIGER) - + def process_deal(self, data): """ Process trade data for both query and update. @@ -542,7 +557,8 @@ class TigerGateway(BaseGateway): orderid=self.ID_TIGER2VT[str(i.order_id)], price=i.avg_fill_price, volume=i.filled, - time=datetime.fromtimestamp(i.trade_time / 1000).strftime("%H:%M:%S"), + time=datetime.fromtimestamp( + i.trade_time / 1000).strftime("%H:%M:%S"), gateway_name=self.gateway_name, ) @@ -559,7 +575,7 @@ def convert_symbol_tiger2vt(symbol): else: if len(symbol) < 6: exchange = Exchange.SEHK - elif symbol.startswith("6"): + elif symbol.startswith("6"): exchange = Exchange.SSE elif symbol.endswith(".SH"): exchange = Exchange.SSE @@ -574,7 +590,7 @@ def convert_symbol_vt2tiger(symbol, exchange): """ Convert symbol from vt to tiger. """ - if exchange == Exchange.SSE and symbol.startswith("0"): + if exchange == Exchange.SSE and symbol.startswith("0"): symbol = symbol + ".SH" else: symbol = symbol @@ -593,4 +609,4 @@ def config_symbol_currency(symbol): currency = Currency.HKD else: currency = Currency.CNH - return currency + return currency diff --git a/vnpy/trader/object.py b/vnpy/trader/object.py index 1fa897be..b7ecd02e 100644 --- a/vnpy/trader/object.py +++ b/vnpy/trader/object.py @@ -234,6 +234,7 @@ class ContractData(BaseData): pricetick: float stop_supported: bool = False # whether server supports stop order + net_position: bool = False # whether gateway uses net position volume option_strike: float = 0 option_underlying: str = "" # vt_symbol of underlying contract