Files
big-qmt/py-client/sdk/models.py

219 lines
4.9 KiB
Python
Raw Normal View History

2026-08-28 18:52:27 +08:00
from __future__ import annotations
2026-08-30 00:34:27 +08:00
from datetime import datetime
2026-08-28 18:52:27 +08:00
from dataclasses import dataclass, field
from typing import Any
def _number(value: Any, kind: type = float) -> Any:
try:
return kind(value or 0)
except (TypeError, ValueError):
return kind()
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-30 00:34:27 +08:00
class OrderItem:
2026-09-07 14:04:26 +08:00
"""Fields match format_orders() exactly."""
stock_code: str = ""
order_sys_id: str = ""
ref: int = 0
order_ref: str = ""
direction: int = 0
offset_flag: int = 0
limit_price: float = 0.0
volume_total_original: int = 0
volume_traded: int = 0
volume_total: int = 0
traded_price: float = 0.0
2026-08-30 00:34:27 +08:00
trade_amount: float = 0.0
2026-09-07 14:04:26 +08:00
insert_date: str = ""
insert_time: str = ""
remark: str = ""
order_status: int = 0
2026-08-30 00:34:27 +08:00
2026-09-07 14:04:26 +08:00
@property
def side(self) -> str:
return _side(self.offset_flag)
@property
2026-09-07 18:18:00 +08:00
def get_local_order_id(self) -> str:
2026-09-07 14:04:26 +08:00
return self.remark.split("|", 1)[0]
@property
def created_at(self) -> datetime | None:
return _parse_datetime(self.insert_date, self.insert_time)
2026-08-30 00:34:27 +08:00
2026-09-06 14:49:46 +08:00
@dataclass(slots=True)
class DealItem:
2026-09-07 14:04:26 +08:00
"""Fields match format_deals() exactly."""
stock_code: str = ""
order_sys_id: str = ""
ref: int = 0
order_ref: str = ""
direction: int = 0
offset_flag: int = 0
2026-09-07 00:27:33 +08:00
price: float = 0.0
2026-09-07 14:04:26 +08:00
volume: int = 0
2026-09-07 00:27:33 +08:00
trade_amount: float = 0.0
2026-09-07 14:04:26 +08:00
trade_date: str = ""
trade_time: str = ""
remark: str = ""
close_profit: float = 0.0
@property
def side(self) -> str:
return _side(self.offset_flag)
2026-09-06 14:49:46 +08:00
2026-09-07 14:04:26 +08:00
@property
2026-09-07 18:18:00 +08:00
def get_local_order_id(self) -> str:
2026-09-07 14:04:26 +08:00
return self.remark.split("|", 1)[0]
2026-09-06 14:49:46 +08:00
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-30 00:34:27 +08:00
class PositionItem:
2026-09-07 14:04:26 +08:00
"""Fields match format_holding() exactly."""
2026-08-28 18:52:27 +08:00
stock_code: str = ""
stock_name: str = ""
direction: Any = None
volume: int = 0
open_price: float = 0.0
2026-09-07 14:04:26 +08:00
open_cost: float = 0.0
2026-08-28 18:52:27 +08:00
float_profit: float = 0.0
market_value: float = 0.0
stock_holder: str = ""
frozen_volume: int = 0
can_use_volume: int = 0
on_road_volume: int = 0
yesterday_volume: int = 0
last_price: float = 0.0
profit_rate: float = 0.0
future_trade_type: Any = None
expire_date: str = ""
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class Assets:
2026-09-07 14:04:26 +08:00
"""Fields match format_assets() exactly."""
2026-08-28 18:52:27 +08:00
total: float = 0.0
available: float = 0.0
2026-08-30 00:34:27 +08:00
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-09-03 11:33:43 +08:00
class Portfolio:
assets: Assets
positions: dict[str, PositionItem]
orders: list[OrderItem]
2026-09-07 14:04:26 +08:00
def _side(offset_flag: int) -> str:
return {"23": "BUY", "24": "SELL", "48": "BUY", "49": "SELL"}.get(str(offset_flag), "")
2026-09-06 14:49:46 +08:00
def _parse_datetime(date: str, clock: str) -> datetime | None:
clock = clock.replace(":", "").zfill(6)
2026-08-30 00:34:27 +08:00
try:
2026-09-07 14:04:26 +08:00
return datetime.strptime(date.replace("-", "") + clock, "%Y%m%d%H%M%S")
2026-08-30 00:34:27 +08:00
except ValueError:
return None
2026-08-28 18:52:27 +08:00
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class Tick:
last_price: float = 0.0
last_close: float = 0.0
raw: dict[str, Any] = field(default_factory=dict)
2026-09-03 11:33:43 +08:00
@classmethod
def from_dict(cls, data: Any) -> "Tick":
if not isinstance(data, dict):
return cls()
return cls(
2026-09-06 14:49:46 +08:00
last_price=_number(
data.get("lastPrice", data.get("last_price", data.get("LastPrice")))
),
last_close=_number(
data.get("lastClose", data.get("last_close", data.get("LastClose")))
),
2026-09-03 11:33:43 +08:00
raw=data,
)
2026-08-28 18:52:27 +08:00
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class HistoryDataRequest:
length: int = 10
period: str = ""
field: str = ""
dividend_type: int = 0
skip_paused: bool = True
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class MarketDataRequest:
fields: list[str] = field(default_factory=list)
stocks: list[str] = field(default_factory=list)
start_time: str = ""
end_time: str = ""
period: str = ""
dividend_type: str = ""
count: int = 0
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class FinancialDataRequest:
2026-09-06 14:49:46 +08:00
tabname: str = ""
colname: str = ""
market: str = ""
code: str = ""
report_type: str = ""
barpos: int = 0
field_list: list[str] = field(default_factory=list)
stock_list: list[str] = field(default_factory=list)
start_date: str = ""
end_date: str = ""
2026-08-28 18:52:27 +08:00
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class FactorDataRequest:
2026-09-06 14:49:46 +08:00
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 = ""
2026-08-28 18:52:27 +08:00
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class BSMPriceRequest:
2026-09-06 14:49:46 +08:00
option_type: str
object_prices: Any
strike_price: float
risk_free: float
sigma: float
days: int
dividend: float
2026-08-28 18:52:27 +08:00
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class BSMIVRequest:
2026-09-06 14:49:46 +08:00
option_type: str
object_prices: float
strike_price: float
option_price: float
risk_free: float
days: int
dividend: float
2026-08-28 18:52:27 +08:00
2026-09-06 11:34:23 +08:00
@dataclass(slots=True)
2026-08-28 18:52:27 +08:00
class LocalDataRequest:
2026-09-06 14:49:46 +08:00
stock_code: str
start_time: str = ""
end_time: str = ""
period: str = ""
divid_type: str = ""
count: int = 0