update api,libs
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
|
||||
@@ -12,7 +12,60 @@ def _number(value: Any, kind: type = float) -> Any:
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class Position:
|
||||
class OrderItem:
|
||||
"""由 QMT 委托明细解析得到的标准订单记录。"""
|
||||
id: str
|
||||
code: str
|
||||
side: str
|
||||
remark: str
|
||||
status: str
|
||||
created_at: datetime | None
|
||||
volume: int
|
||||
local_order_id: str = ""
|
||||
traded_volume: int = 0
|
||||
remaining_volume: int = 0
|
||||
exchange_id: str = ""
|
||||
name: str = ""
|
||||
price: float = 0.0
|
||||
trade_price: float = 0.0
|
||||
trade_amount: float = 0.0
|
||||
|
||||
@classmethod
|
||||
def from_trade_detail(cls, data: dict[str, Any]) -> "OrderItem":
|
||||
"""从 TradeDetailData 的 QMT 原始字段创建订单。"""
|
||||
instrument_id = str(data.get("m_strInstrumentID") or "")
|
||||
exchange_id = str(data.get("m_strExchangeID") or "")
|
||||
code = (
|
||||
f"{instrument_id}.{exchange_id}"
|
||||
if instrument_id and exchange_id
|
||||
else instrument_id
|
||||
)
|
||||
remaining_volume = _number(data.get("m_nVolumeTotal"), int)
|
||||
traded_volume = _number(data.get("m_nVolumeTraded"), int)
|
||||
remark = str(data.get("m_strRemark") or "")
|
||||
return cls(
|
||||
id=str(data.get("m_strOrderSysID") or ""),
|
||||
code=code,
|
||||
side={"23": "BUY", "24": "SELL", "48": "BUY", "49": "SELL"}.get(
|
||||
str(data.get("m_nOffsetFlag")), ""
|
||||
),
|
||||
remark=remark,
|
||||
status=str(data.get("m_nOrderStatus") or ""),
|
||||
created_at=_trade_datetime(data),
|
||||
volume=remaining_volume + traded_volume,
|
||||
local_order_id=remark.split("|", 1)[0] if remark else "",
|
||||
traded_volume=traded_volume,
|
||||
remaining_volume=remaining_volume,
|
||||
exchange_id=exchange_id,
|
||||
name=str(data.get("m_strInstrumentName") or ""),
|
||||
price=_number(data.get("m_dPrice")),
|
||||
trade_price=_number(data.get("m_dTradePrice")),
|
||||
trade_amount=_number(data.get("m_dTradeAmount")),
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PositionItem:
|
||||
stock_code: str = ""
|
||||
stock_name: str = ""
|
||||
direction: Any = None
|
||||
@@ -31,7 +84,7 @@ class Position:
|
||||
expire_date: str = ""
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any], code: str = "") -> "Position":
|
||||
def from_dict(cls, data: dict[str, Any], code: str = "") -> "PositionItem":
|
||||
return cls(
|
||||
stock_code=str(data.get("StockCode") or code), stock_name=str(data.get("StockName") or ""),
|
||||
direction=data.get("Direction"), volume=_number(data.get("Volume"), int),
|
||||
@@ -43,12 +96,58 @@ class Position:
|
||||
future_trade_type=data.get("FutureTradeType"), expire_date=str(data.get("ExpireDate") or ""),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_trade_detail(cls, data: dict[str, Any]) -> "PositionItem":
|
||||
"""从 TradeDetailData/Holding 的 QMT 原始字段创建持仓。"""
|
||||
instrument_id = str(data.get("m_strInstrumentID") or "")
|
||||
exchange_id = str(data.get("m_strExchangeID") or "")
|
||||
stock_code = (
|
||||
f"{instrument_id}.{exchange_id}"
|
||||
if instrument_id and exchange_id
|
||||
else instrument_id
|
||||
)
|
||||
return cls(
|
||||
stock_code=stock_code,
|
||||
stock_name=str(data.get("m_strInstrumentName") or ""),
|
||||
direction=data.get("m_nDirection"),
|
||||
volume=_number(data.get("m_nVolume"), int),
|
||||
open_price=_number(data.get("m_dOpenPrice")),
|
||||
float_profit=_number(data.get("m_dFloatProfit")),
|
||||
market_value=_number(data.get("m_dMarketValue")),
|
||||
stock_holder=str(data.get("m_strStockHolder") or ""),
|
||||
frozen_volume=_number(data.get("m_nFrozenVolume"), int),
|
||||
can_use_volume=_number(data.get("m_nCanUseVolume"), int),
|
||||
on_road_volume=_number(data.get("m_nOnRoadVolume"), int),
|
||||
yesterday_volume=_number(data.get("m_nYesterdayVolume"), int),
|
||||
last_price=_number(data.get("m_dLastPrice")),
|
||||
profit_rate=_number(data.get("m_dProfitRate")),
|
||||
future_trade_type=data.get("m_eFutureTradeType"),
|
||||
expire_date=str(data.get("m_strExpireDate") or ""),
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class Assets:
|
||||
total: float = 0.0
|
||||
available: float = 0.0
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any]) -> "Assets":
|
||||
"""兼容新版 QMT 原始资金字段及旧版简化字段。"""
|
||||
return cls(
|
||||
total=_number(data.get("m_dBalance", data.get("total"))),
|
||||
available=_number(data.get("m_dAvailable", data.get("available"))),
|
||||
)
|
||||
|
||||
|
||||
def _trade_datetime(data: dict[str, Any]) -> datetime | None:
|
||||
date = str(data.get("m_strInsertDate") or "")
|
||||
clock = str(data.get("m_strInsertTime") or "").replace(":", "").zfill(6)
|
||||
try:
|
||||
return datetime.strptime(date + clock, "%Y%m%d%H%M%S")
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class Tick:
|
||||
|
||||
Reference in New Issue
Block a user