Files
Auto-Trader/agent/backtest/models.py
T
Haozhe Wu d3c76819c3 fix: complete October 11-12 maintenance and research updates
Fix live option guards, grounding operand evidence, source-bound benchmarks, trade artifacts, attribution, drawdowns, valuation tolerances, and SEC point-in-time factor inputs.

Add Brazil research data and market support, 13 fundamental and valuation factors, channel progress forwarding, and opt-in ZimaOS templates. Update seven README News sections with three visible dates.

Validation: 17,635 backend tests passed; 1,084 final targeted tests and 103 frontend tests passed. Frontend build, package build, documentation checks, and CI gates passed.
2026-10-12 02:29:46 +08:00

129 lines
3.8 KiB
Python

"""Shared data models for backtest engines.
Immutable dataclasses for positions, fills, trades, and equity snapshots.
"""
from __future__ import annotations
from dataclasses import dataclass
import pandas as pd
@dataclass(frozen=True)
class Position:
"""An open position in a single instrument.
Args:
symbol: Instrument identifier.
direction: 1 for long, -1 for short.
entry_price: Execution price at entry.
entry_time: Timestamp when position was opened.
size: Number of shares / coins.
leverage: Effective leverage (1 for spot/stocks).
entry_bar_idx: Index in the dates array at entry (for holding_bars).
entry_commission: Commission paid at entry.
open_price: Execution price of the fill that opened the position.
``entry_price`` becomes the weighted cost once the position is
scaled into; this keeps what was actually paid at the open.
open_size: Quantity of the fill that opened the position.
"""
symbol: str
direction: int
entry_price: float
entry_time: pd.Timestamp
size: float
leverage: float = 1.0
entry_bar_idx: int = 0
entry_commission: float = 0.0
open_price: float | None = None
open_size: float | None = None
@dataclass(frozen=True)
class FillRecord:
"""Immutable evidence for one executed position delta.
``margin`` is the margin-equivalent traded value at the execution price;
it is evidence for turnover, not a second source of account state.
``holding_bars`` is populated only for reducing fills and is derived from
prior fill evidence under the engine's proportional compressed-position
accounting.
"""
symbol: str
timestamp: pd.Timestamp
bar_idx: int
action: str
signed_quantity: float
notional: float
execution_price: float
fee: float
margin: float
reason: str
holding_bars: float | None = None
@dataclass(frozen=True)
class TradeRecord:
"""A completed round-trip trade.
Args:
symbol: Instrument identifier.
direction: 1 for long, -1 for short.
entry_price: Entry execution price.
exit_price: Exit execution price.
entry_time: Entry timestamp.
exit_time: Exit timestamp.
size: Number of shares / coins traded.
leverage: Effective leverage.
pnl: Realised profit/loss in cash terms.
pnl_pct: Realised P&L as percentage of margin.
exit_reason: Why closed (signal / liquidation / end_of_backtest).
holding_bars: Number of bars held.
commission: Total commission (entry + exit).
entry_margin: Actual margin allocated at entry, after size rounding.
exit_margin: Margin-equivalent value traded at the exit price.
open_price: Execution price of the fill that opened the position,
or ``None`` when the position did not record it.
open_size: Quantity of that opening fill, or ``None``.
"""
symbol: str
direction: int
entry_price: float
exit_price: float
entry_time: pd.Timestamp
exit_time: pd.Timestamp
size: float
leverage: float
pnl: float
pnl_pct: float
exit_reason: str
holding_bars: float
commission: float
entry_margin: float = 0.0
exit_margin: float = 0.0
open_price: float | None = None
open_size: float | None = None
@dataclass(frozen=True)
class EquitySnapshot:
"""Portfolio state at a single point in time.
Args:
timestamp: Bar timestamp.
capital: Free cash.
unrealized: Total unrealised P&L across all positions.
equity: capital + margin_in_use + unrealized.
positions: Number of open positions.
"""
timestamp: pd.Timestamp
capital: float
unrealized: float
equity: float
positions: int