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_CTP2VT[data["PosiDirection"]], gateway_name=self.gateway_name ) self.positions[key] = position # Get contract size, return if size value not collected size = symbol_size_map.get(position.symbol, None) if not size: return # 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"] # 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: 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 on_position(self, data: dict) -> None: """""" pos = PositionData( symbol=data["instrument_id"], exchange=Exchange.OKEX, direction=Direction.NET, volume=int(data["position"]), frozen=float(data["avail_position"]) - float(data["avail_position"]), price=float(data["avg_cost"]), pnl=float(data["realized_pnl"]), gateway_name=self.gateway_name, ) self.gateway.on_position(pos)
def on_pos_event(self, data: dict) -> None: """""" position = PositionData( symbol=data["code"], exchange=EXCHANGE_PT2VT[data["exchange"]], direction=Direction.LONG, volume=data["volume"], frozen=data["volume"] - data["available"], price=data["buy_price"], pnl=data["profit"], yd_volume=data["available"], gateway_name=self.gateway_name, ) self.gateway.on_position(position)
def OnQueryPosition(self, xtp_position: XTPQueryStkPositionRsp, error_info: XTPRspInfoStruct, request_id: int, is_last: bool, session_id: int) -> Any: """""" position = PositionData(symbol=xtp_position.ticker, exchange=MARKET_XTP2VT[xtp_position.market], direction=Direction.LONG, volume=xtp_position.total_qty, frozen=xtp_position.locked_position, price=xtp_position.avg_price, pnl=xtp_position.unrealized_pnl, yd_volume=xtp_position.yesterday_position, gateway_name=self.gateway_name) self.gateway.on_position(position)
def _parse_position_holding(holding, symbol, gateway_name): """parse single 'holding' record in replied position data to PositionData. """ position = int(holding["position"]) pos = PositionData( symbol=symbol, exchange=Exchange.OKEX, direction=DIRECTION_OKEXS2VT[holding['side']], volume=position, frozen=float(position - float(holding["avail_position"])), price=float(holding['avg_cost']), pnl=float(holding['realized_pnl']), gateway_name=gateway_name, ) return pos
def onRtnPosition(self, data: dict, error: dict, reqid: int, last: bool): """ Callback of position status update. """ long_position = PositionData( symbol=data["TreatyCode"], exchange=EXCHANGE_DA2VT[data["ExchangeNo"]], direction=Direction.LONG, volume=data["BuyHoldNumber"], price=data["BuyHoldOpenPrice"], gateway_name=self.gateway_name ) self.gateway.on_position(long_position) short_position = PositionData( symbol=data["TreatyCode"], exchange=EXCHANGE_DA2VT[data["ExchangeNo"]], direction=Direction.SHORT, volume=data["SaleHoldNumber"], price=data["SaleHoldOpenPrice"], gateway_name=self.gateway_name ) self.gateway.on_position(short_position)
def on_position(self, d): """""" symbol = d["symbol"] position = self.positions.get(symbol, None) if not position: position = PositionData( symbol=d["symbol"], exchange=Exchange.BITMEX, direction=Direction.NET, gateway_name=self.gateway_name, ) self.positions[symbol] = position volume = d.get("currentQty", None) if volume is not None: position.volume = volume price = d.get("avgEntryPrice", None) if price is not None: position.price = price self.gateway.on_position(copy(position))
def onRspQryInvestorPosition(self, data: dict, error: dict, reqid: int, last: bool): """""" if not data: return # Get buffered position object key = f"{data['InstrumentID'], data['Direction']}" position = self.positions.get(key, None) if not position: position = PositionData( symbol=data["InstrumentID"], exchange=symbol_exchange_map[data["InstrumentID"]], direction=DIRECTION_FEMAS2VT[data["Direction"]], gateway_name=self.gateway_name, ) self.positions[key] = position position.yd_volume = data["YdPosition"] # Calculate previous position cost cost = position.price * position.volume # Update new position volume position.volume += data["Position"] # Calculate average position price if position.volume: cost += data["PositionCost"] position.price = cost / position.volume # Get frozen volume position.frozen += data["FrozenPosition"] if last: for position in self.positions.values(): self.gateway.on_position(position) self.positions.clear()
def on_info(self, data: dict): """""" for account_data in data["position"]: _type = account_data["type"] # Spot if "spot" in _type: account = AccountData( accountid=account_data["contract"], balance=float(account_data["total_amount"]), frozen=float(account_data["frozen"]), gateway_name=self.gateway_name ) self.gateway.on_account(account) # Futures elif _type == "future": long_position = PositionData( symbol=account_data["contract"], exchange=Exchange.OKEX, # todo add Exchange direction=Direction.LONG, volume=account_data["total_amount_long"], frozen=account_data["total_amount_long"] - \ account_data["available_long"], gateway_name=self.gateway_name, ) short_position = PositionData( symbol=account_data["contract"], exchange=Exchange.OKEX, # todo add Exchange direction=Direction.SHORT, volume=account_data["total_amount_short"], frozen=account_data["total_amount_short"] - \ account_data["available_short"], gateway_name=self.gateway_name, ) self.gateway.on_position(long_position) self.gateway.on_position(short_position)
def on_query_position(self, packet: list): """""" data = packet['result'] for pos in data: position = PositionData( symbol=pos['instrument_name'], exchange=Exchange.DERIBIT, direction=Direction.NET, volume=pos['size'], pnl=float(pos['floating_profit_loss']), gateway_name=self.gateway_name, ) self.gateway.on_position(position) self.query_pos_done = True
def on_query_position(self, data, request): positions = data["positions"] for pos in positions: symbol = pos["instrument"] long_pos = pos["long"] if long_pos["units"] != "0": direction = Direction.LONG volume = int(long_pos["units"]) avg_price = float(long_pos["averagePrice"]) pnl = float(long_pos["pl"]) + float(long_pos["unrealizedPL"]) position = PositionData( symbol=symbol, exchange=Exchange.OANDA, direction=direction, volume=volume, price=avg_price, pnl=pnl, gateway_name=self.gateway_name, ) self.gateway.on_position(position) short_pos = pos["short"] if short_pos["units"] != "0": direction = Direction.SHORT volume = int(long_pos["units"]) avg_price = float(long_pos["averagePrice"]) pnl = float(long_pos["pl"]) + float(long_pos["unrealizedPL"]) position = PositionData( symbol=symbol, exchange=Exchange.OANDA, direction=direction, volume=volume, price=avg_price, pnl=pnl, gateway_name=self.gateway_name, ) self.gateway.on_position(position)
def on_query_position(self, data: dict, request: Request) -> None: """""" if self.check_error(data, "查询持仓"): return for d in data["data"]["responseBody"][::-1]: if not d.get("goodsCode", None): continue if d["buyHoldAmount"]: long_position = PositionData( gateway_name=self.gateway_name, symbol=d["goodsCode"], exchange=Exchange.SR, direction=Direction.LONG, volume=d["buyHoldAmount"], frozen=d["buyLockedAmount"], price=d["buyAvgPrice"] / 100, pnl=0, ) self.gateway.on_position(long_position) if d["sellHoldAmount"]: short_position = PositionData( gateway_name=self.gateway_name, symbol=d["goodsCode"], exchange=Exchange.SR, direction=Direction.SHORT, volume=d["sellHoldAmount"], frozen=d["sellLockedAmount"], price=d["sellAvgPrice"] / 100, pnl=0, ) self.gateway.on_position(short_position)
def get_position(self, vt_symbol: str, direction: Direction): """""" key = (vt_symbol, direction) if key in self.positions: return self.positions[key] else: symbol, exchange = extract_vt_symbol(vt_symbol) position = PositionData(symbol=symbol, exchange=exchange, direction=direction, gateway_name=GATEWAY_NAME) self.positions[key] = position return position
def on_query_position(self, data: dict, request: Request) -> None: """""" for d in data: position = PositionData( symbol=d["symbol"], exchange=Exchange.BINANCE, direction=Direction.NET, volume=float(d["positionAmt"]), price=float(d["entryPrice"]), pnl=float(d["unRealizedProfit"]), gateway_name=self.gateway_name, ) if position.volume != 0: self.gateway.on_position(position)
def on_position(self, packet: dict): """""" for d in packet["data"]: if d["side"] == "Buy": volume = d["size"] else: volume = -d["size"] position = PositionData(symbol=d["symbol"], exchange=Exchange.BYBIT, direction=Direction.NET, volume=volume, price=float(d["entry_price"]), gateway_name=self.gateway_name) self.gateway.on_position(position)
def query_position(self): """""" data = self.api.list_positions() for item in data: pos = PositionData( symbol=item.code, exchange=EXCHANGE_SINOPAC2VT.get("TSE", Exchange.TSE), direction=Direction.LONG if item.quantity >= 0 else Direction.SHORT, volume=abs(item.quantity), frozen=item.quantity - item.quantity, price=item.price, pnl=item.pnl, yd_volume=item.yd_quantity, gateway_name=self.gateway_name, ) self.on_position(pos)
def onQueryOptHolding(self, data: dict, head: dict, reqid: int) -> None: """""" last = head["isEnd"] #print(data) pos = PositionData(symbol=data["securityId"], exchange=EXCHANGE_OES2VT[data["mktId"]], direction=DIRECTION_OES2VT[data["positionType"]], volume=data["sumQty"], frozen=data["closeFrzQty"], price=data["costPrice"] / 10000, gateway_name=self.gateway_name) self.gateway.on_position(pos) if last: self.gateway.write_log("期权持仓查询成功")
def onRspSOPQryPosition(self, data: dict, error: dict, last: bool) -> None: """""" if not data or not data["securityOptionID"]: return pos = PositionData( symbol=data["securityOptionID"], exchange=EXCHANGE_SEC2VT[data["exchangeID"]], direction=DIRECTION_SEC2VT[data["entrustDirection"]], volume=data["totalQty"], price=data["openAvgPrice"], gateway_name=self.gateway_name) self.gateway.on_position(pos) pos_symbol = f"{data['securityOptionID']}_{data['entrustDirection']}" self.positions[pos_symbol] = pos
def onRspStockQryPosition(self, data: dict, error: dict, last: bool) -> None: """""" if not data or not data["securityID"]: return pos = PositionData(symbol=data["securityID"], exchange=EXCHANGE_SEC2VT[data["exchangeID"]], direction=Direction.NET, volume=data["totalQty"], price=data["avgPositionPrice"], gateway_name=self.gateway_name) self.gateway.on_position(pos) pos_symbol = f"{data['securityID']}_{data['exchangeID']}" self.positions[pos_symbol] = pos
def parse_position_data(self, pos_data) -> Tuple[PositionData, PositionData]: symbol = pos_data['instrument'] pos_long, pos_short = [ PositionData( gateway_name=self.gateway_name, symbol=symbol, exchange=Exchange.OANDA, direction=direction, volume=int(data['units']), price=float(data.get('averagePrice', 0.0)), pnl=float(data.get('unrealizedPL', 0.0)), ) for direction, data in ((Direction.LONG, pos_data['long']), (Direction.SHORT, pos_data['short'])) ] return pos_long, pos_short
def on_stock_holding(self, d: OesRspMsgBodyT): """""" data = d.rptMsg.rptBody.stkHoldingRpt position = PositionData( gateway_name=self.gateway.gateway_name, symbol=data.securityId, exchange=EXCHANGE_OES2VT[data.mktId], direction=Direction.NET, volume=data.sumHld, frozen=data.lockHld, price=data.costPrice / 10000, # pnl=data.costPrice - data.originalCostAmt, pnl=0, yd_volume=data.originalHld, ) self.gateway.on_position(position)
def on_position_change(self, tiger_account: str, data: list): """""" data = dict(data) symbol, exchange = convert_symbol_tiger2vt(data["origin_symbol"]) pos = PositionData( symbol=symbol, exchange=exchange, direction=Direction.NET, volume=int(data["quantity"]), frozen=0.0, price=data["average_cost"], pnl=data["unrealized_pnl"], gateway_name=self.gateway_name, ) self.on_position(pos)
def onQueryPosition(self, data: dict, error: dict, request: int, last: bool, session: int) -> None: """""" if data["market"] == 0: return position = PositionData( symbol=data["ticker"], exchange=MARKET_XTP2VT[data["market"]], direction=POSITION_DIRECTION_XTP2VT[data["position_direction"]], volume=data["total_qty"], frozen=data["locked_position"], price=data["avg_price"], pnl=data["unrealized_pnl"], yd_volume=data["yesterday_position"], gateway_name=self.gateway_name) self.gateway.on_position(position)
def on_query_position(self, data: dict, request: Request) -> None: """""" if not data["holding"]: return for pos_data in data["holding"]: pos = PositionData( symbol=pos_data["instrument_id"], exchange=Exchange.OKEX, direction=Direction.NET, volume=int(pos_data["position"]), frozen=float(pos_data["avail_position"]) - float(pos_data["avail_position"]), price=float(pos_data["avg_cost"]), pnl=float(pos_data["realized_pnl"]), gateway_name=self.gateway_name, ) self.gateway.on_position(pos)
def on_query_position(self, packet: dict): """""" data = packet["result"] currency = self.reqid_currency_map[packet["id"]] for pos in data: position = PositionData( symbol=pos["instrument_name"], exchange=Exchange.DERIBIT, direction=Direction.NET, volume=pos["size"], pnl=float(pos["floating_profit_loss"]), gateway_name=self.gateway_name, ) self.gateway.on_position(position) self.gateway.write_log(f"{currency}持仓查询成功")
def onQueryPositionRsp(self, data: dict, error: dict, reqid: int, last: bool, pos: str) -> None: """""" if not data["symbol"]: return exchange, symbol = data["symbol"].split(".") pos = PositionData( gateway_name=self.gateway_name, symbol=symbol, exchange=EXCHANGE_GTJA2VT[exchange], direction=Direction.NET, volume=data["volume"], price=data["cost_price"] / 10000, pnl=data["total_income"] / 10000, ) self.gateway.on_position(pos)
def on_query_position(self, data: dict, request: Request) -> None: """""" if self.check_error(data, "查询持仓"): return positions = data["body"]["holdShareUnitList"] for d in positions: position = PositionData( symbol=d["productCode"], exchange=EXCHANGE_KAISA2VT[d["exchangeCode"]], direction=Direction.NET, volume=int(d["qty"]), frozen=int(d["qty"]) - int(d["availQty"]), price=float(d["avgCost"]), pnl=float(d["pl"]), gateway_name=self.gateway_name) self.gateway.on_position(position)
def onQueryStkHolding(self, data: dict, head: dict, reqid: int) -> None: """""" last = head["isEnd"] #print(data) pos = PositionData(symbol=data["securityId"], exchange=EXCHANGE_OES2VT[data["mktId"]], direction=DIRECTION_OES2VT[1], volume=data["sumHld"], frozen=data["sellFrzHld"], price=data["costPrice"] / 10000, yd_volume=data["originalHld"], gateway_name=self.gateway_name) self.gateway.on_position(pos) if last: self.gateway.write_log("现货持仓查询成功") pass
def on_query_position(self, data: List[Dict[str, str]]) -> None: """""" if not data: return for d in data: position = PositionData( symbol=d["option_code"], exchange=EXCHANGE_HSOPTION2VT[d["exchange_type"]], direction=POS_DIRECTION_HSOPTION2VT[d["opthold_type"]], volume=int(float(d["hold_amount"])), pnl=float(d["income_balance"]), price=float(d["opt_cost_price"]), frozen=int( (float(d["hold_amount"]) - float(d["enable_amount"]))), gateway_name=self.gateway_name) self.gateway.on_position(position)
def query_position(self): """""" self.api.get_stock_account_unreal_profitloss().update() data = self.api.get_stock_account_unreal_profitloss().data()["summary"] for item in data: pos = PositionData( symbol=f"{item['stock']} {item['stocknm']}", exchange=EXCHANGE_SINOPAC2VT.get('TSE', Exchange.TSE), direction=Direction.LONG if float( item['real_qty']) >= 0 else Direction.SHORT, volume=float(item['real_qty']) / 1000, frozen=float(item['real_qty']) / 1000 - float(item['qty']) / 1000, price=float(item['avgprice']), pnl=float(item['unreal']), yd_volume=float(item['qty']) / 1000, gateway_name=self.gateway_name ) self.on_position(pos)
def updatePortfolio( # pylint: disable=invalid-name self, contract: Contract, position: float, marketPrice: float, marketValue: float, averageCost: float, unrealizedPNL: float, realizedPNL: float, accountName: str, ): """ Callback of position update. """ super(IbApi, self).updatePortfolio( contract, position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, accountName, ) if not contract.exchange: return ib_size = contract.multiplier if not ib_size: ib_size = 1 price = averageCost / ib_size pos = PositionData( symbol=contract.conId, exchange=EXCHANGE_IB2VT.get(contract.exchange, contract.exchange), direction=Direction.NET, volume=position, price=price, pnl=unrealizedPNL, gateway_name=self.gateway_name, ) self.gateway.on_position(pos)