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.
129 lines
3.8 KiB
Python
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
|