This commit is contained in:
2026-09-06 11:34:23 +08:00
parent b38ff12f2a
commit ac9e9193ad
32 changed files with 235 additions and 61 deletions

View File

@@ -11,7 +11,7 @@ def _number(value: Any, kind: type = float) -> Any:
return kind()
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class OrderItem:
"""由 QMT 委托明细解析得到的标准订单记录。"""
id: str
@@ -64,13 +64,14 @@ class OrderItem:
)
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class PositionItem:
stock_code: str = ""
stock_name: str = ""
trade_id:str = ""
direction: Any = None
volume: int = 0
open_cost: float = 0.0
open_price: float = 0.0
float_profit: float = 0.0
market_value: float = 0.0
@@ -88,7 +89,7 @@ class PositionItem:
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 ""),
trade_id=str(data.get("TradeID") or ""),
trade_id=str(data.get("TradeID") or ""),open_cost=_number(data.get("OpenCost")),
direction=data.get("Direction"), volume=_number(data.get("Volume"), int),
open_price=_number(data.get("OpenPrice")), float_profit=_number(data.get("FloatProfit")),
market_value=_number(data.get("MarketValue")), stock_holder=str(data.get("StockHolder") or ""),
@@ -107,6 +108,7 @@ class PositionItem:
trade_id=str(data.get("TradeID") or ""),
direction=data.get("Direction"),
volume=_number(data.get("Volume"), int),
open_cost=_number(data.get("OpenCost")),
open_price=_number(data.get("OpenPrice")),
float_profit=_number(data.get("FloatProfit")),
market_value=_number(data.get("MarketValue")),
@@ -122,7 +124,7 @@ class PositionItem:
)
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class Assets:
total: float = 0.0
available: float = 0.0
@@ -136,7 +138,7 @@ class Assets:
)
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class Portfolio:
assets: Assets
positions: dict[str, PositionItem]
@@ -152,7 +154,7 @@ def _trade_datetime(data: dict[str, Any]) -> datetime | None:
return None
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class Tick:
last_price: float = 0.0
last_close: float = 0.0
@@ -169,7 +171,7 @@ class Tick:
)
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class HistoryDataRequest:
length: int = 10
period: str = ""
@@ -178,7 +180,7 @@ class HistoryDataRequest:
skip_paused: bool = True
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class MarketDataRequest:
fields: list[str] = field(default_factory=list)
stocks: list[str] = field(default_factory=list)
@@ -189,7 +191,7 @@ class MarketDataRequest:
count: int = 0
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class FinancialDataRequest:
tabname: str = ""; colname: str = ""; market: str = ""; code: str = ""
report_type: str = ""; barpos: int = 0
@@ -197,22 +199,22 @@ class FinancialDataRequest:
start_date: str = ""; end_date: str = ""
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class FactorDataRequest:
field_list: list[str] = field(default_factory=list); stock_list: list[str] = field(default_factory=list)
stock_code: str = ""; start_date: str = ""; end_date: str = ""
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class BSMPriceRequest:
option_type: str; object_prices: Any; strike_price: float; risk_free: float; sigma: float; days: int; dividend: float
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class BSMIVRequest:
option_type: str; object_prices: float; strike_price: float; option_price: float; risk_free: float; days: int; dividend: float
@dataclass(frozen=True, slots=True)
@dataclass(slots=True)
class LocalDataRequest:
stock_code: str; start_time: str = ""; end_time: str = ""; period: str = ""; divid_type: str = ""; count: int = 0

View File

@@ -6,6 +6,14 @@ from .models import Assets, OrderItem, Portfolio, PositionItem
class PortfolioMixin:
def org(self, datatype: str) -> list[dict[str, Any]]:
"""查询 account、order、deal 或 position返回原始字段字典列表。"""
datatype = str(datatype).strip().lower()
if datatype not in {"account", "order", "deal", "position"}:
raise ValueError(f"unsupported org datatype: {datatype}")
response = self._get_json(f"/api/portfolio/org/{datatype}")
return response["data"]
def portfolio(self) -> Portfolio:
data = self._get_json("/api/portfolio") or {}
positions = {