Files
sanguo_vnpy_v2/sanguo_trader/models.py
T
claude_dev 05d74fc2c1 fix(trader): M+L 接口校验 (listing_days/NaN/输入校验/类型注数) review
M1: PaperOrder+limit+matcher 加 listing_days(创业/科创/北交所前5日不锁,0=已过)
M3: is_locked_for_*_symbol cfg 注解 AccountConfig
M4: matcher NaN bar 拒单 bar_missing
L3: PositionLedger price/volume 正数校验
L5: PaperOrder __post_init__ volume 类型校验(拒 float/bool)
M5: current_close 契约 docstring + H3 残留注释修正(transfer_fee 双向)
79 tests passed.
2026-07-07 11:23:16 +08:00

90 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""模拟盘数据模型(immutable DTOs)。
数据类承载配置与订单/成交/拒单状态,跨模块传递时保持不可变。
费率默认值见 §6.4(Issue #3 费率参数化)。
"""
from dataclasses import dataclass
from enum import Enum
class MatchSession(str, Enum):
"""撮合时点(spec §6.1)。
- NEXT_OPEN:下一根 bar 的 open(收盘型策略,安全)
- CURRENT_CLOSE:当根 bar 的 close(尾盘抓涨停型,策略不得用当根 OHLC)
- CALL_AUCTION:集合竞价(首版预留)
"""
NEXT_OPEN = "next_open"
CURRENT_CLOSE = "current_close"
CALL_AUCTION = "call_auction"
class OrderSide(str, Enum):
BUY = "buy"
SELL = "sell"
@dataclass(frozen=True)
class AccountConfig:
"""账户费率/撮合参数(Issue #3 全字段可配)。"""
initial_capital: float
rate: float = 0.0003 # 佣金率
min_commission: float = 5.0 # 最低佣金 5 元
stamp_duty_rate: float = 0.0005 # 印花税(仅卖,2023.8.28 起 0.05%
transfer_fee_rate: float = 0.00001 # 过户费率(沪深双向,matcher 出 ×2 总额,review H3
slippage: float = 0.0
pricetick: float = 0.01
size: float = 1.0
@dataclass(frozen=True)
class PaperOrder:
"""策略下单请求。match_session 决定撮合时点。
listing_days:上市天数(新股涨跌停特判,0=已过新股期;spec §6.2)。
current_close 契约:策略 on_bar 内不得访问当根 close/high/low,否则前瞻偏差。
"""
strategy_id: str
symbol: str
side: OrderSide
price: float
volume: int
is_market: bool = True
match_session: MatchSession = MatchSession.NEXT_OPEN
listing_days: int = 0
def __post_init__(self) -> None:
if not isinstance(self.volume, int) or isinstance(self.volume, bool):
raise TypeError(f"volume 必须是 int,收到 {type(self.volume).__name__}")
@dataclass(frozen=True)
class PaperTrade:
"""已成交记录(含费用拆分)。transfer_fee 为沪深双向总额(review H3Account 不再 ×2)。"""
strategy_id: str
symbol: str
side: OrderSide
price: float
volume: int
commission: float
stamp_duty: float
transfer_fee: float
bar_date: str
match_session: MatchSession
@dataclass(frozen=True)
class PaperReject:
"""拒单记录。reason 枚举:limit_up_locked / limit_down_locked /
limit_not_touched / volume_below_min_lot / unsupported_match_session /
insufficient_cash / blocked_by_strategy=<id>。"""
strategy_id: str
symbol: str
reason: str
bar_date: str