from __future__ import annotations from dataclasses import dataclass from datetime import date from decimal import Decimal from enum import StrEnum class TradeSide(StrEnum): BUY = "buy" SELL = "sell" class TradeGroup(StrEnum): BASE = "base" GRID = "grid" OTHER = "other" @dataclass(frozen=True) class Account: id: int | None name: str initial_cash: Decimal notes: str = "" @dataclass(frozen=True) class Instrument: id: int | None code: str name: str market: str = "A" lot_size: int = 100 manual_price: Decimal | None = None allow_odd_lot: bool = False active: bool = True @dataclass(frozen=True) class StrategyTemplate: id: int | None name: str grid_spacing_pct: Decimal amount_per_grid: Decimal base_target_amount: Decimal max_position_amount: Decimal min_lot: int = 100 is_default: bool = False @dataclass(frozen=True) class StrategyOverride: instrument_id: int template_id: int | None = None grid_spacing_pct: Decimal | None = None amount_per_grid: Decimal | None = None base_target_amount: Decimal | None = None max_position_amount: Decimal | None = None min_lot: int | None = None @dataclass(frozen=True) class Trade: id: int | None account_id: int instrument_id: int trade_date: date side: TradeSide price: Decimal quantity: int commission: Decimal = Decimal("0") stamp_tax: Decimal = Decimal("0") transfer_fee: Decimal = Decimal("0") trade_group: TradeGroup = TradeGroup.GRID notes: str = "" @property def gross_amount(self) -> Decimal: return self.price * Decimal(self.quantity) @property def total_fee(self) -> Decimal: return self.commission + self.stamp_tax + self.transfer_fee @dataclass(frozen=True) class CashLedgerEntry: id: int | None account_id: int entry_date: date amount: Decimal category: str instrument_id: int | None = None notes: str = "" @dataclass(frozen=True) class FeeRules: commission_rate: Decimal min_commission: Decimal stamp_tax_rate: Decimal transfer_fee_rate: Decimal @dataclass(frozen=True) class FeeEstimate: commission: Decimal stamp_tax: Decimal transfer_fee: Decimal @property def total(self) -> Decimal: return self.commission + self.stamp_tax + self.transfer_fee @dataclass(frozen=True) class GridLevelSuggestion: level: int buy_price: Decimal buy_amount: Decimal suggested_quantity: int actual_investment: Decimal sell_price: Decimal estimated_gross_profit: Decimal @dataclass(frozen=True) class QuoteSnapshot: symbol: str code: str name: str price: Decimal source: str quote_time: str | None = None previous_close: Decimal | None = None open_price: Decimal | None = None high: Decimal | None = None low: Decimal | None = None change: Decimal | None = None change_percent: Decimal | None = None @dataclass(frozen=True) class PositionSummary: instrument_id: int code: str name: str market: str current_price: Decimal | None price_source: str total_quantity: int available_quantity: int base_quantity: int grid_quantity: int other_quantity: int remaining_cost: Decimal cost_price: Decimal | None position_breakeven_price: Decimal | None account_breakeven_price: Decimal | None realized_pnl: Decimal grid_profit: Decimal floating_pnl: Decimal | None market_value: Decimal | None @dataclass(frozen=True) class AccountSummary: total_assets: Decimal cash: Decimal market_value: Decimal floating_pnl: Decimal capital_usage_rate: Decimal