"""模拟盘数据模型(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 # 过户费率(沪深双向 ×2,由 Account 计算) slippage: float = 0.0 pricetick: float = 0.01 size: float = 1.0 @dataclass(frozen=True) class PaperOrder: """策略下单请求。match_session 决定撮合时点。""" strategy_id: str symbol: str side: OrderSide price: float volume: int is_market: bool = True match_session: MatchSession = MatchSession.NEXT_OPEN @dataclass(frozen=True) class PaperTrade: """已成交记录(含费用拆分)。transfer_fee 为单边,Account 扣款时 ×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=。""" strategy_id: str symbol: str reason: str bar_date: str