trader.simulation package¶
The shadow-portfolio simulator (issue #33, Slice 3e Part 4).
A forward-only measurement instrument, not a trading path. Read the module docstring on step.py for the isolation boundary this package exists inside.
- class trader.simulation.SimulationRunner(settings, pipeline_config, discovery_settings, fixed_symbols, bar_repository, decision_repository, simulation_repository)[source]¶
Bases:
objectSteps every configured strategy’s shadow portfolio forward one cycle.
Since issue #42, that is two portfolios per strategy id: the normal one (its own sell decisions honoured) and an Always-be-Buying (AbB) variant that reads the same decisions with sell signals ignored, so only the trailing stop can close a position — isolating whether the sell side is what costs performance, independent of whether the entries are any good.
- Parameters:
settings (SimulationSettings)
pipeline_config (PipelineConfig)
discovery_settings (DiscoverySettings)
fixed_symbols (Collection[str])
bar_repository (BarRepository)
decision_repository (DecisionRepository)
simulation_repository (SimulationRepository)
- settings: SimulationSettings¶
- pipeline_config: PipelineConfig¶
- discovery_settings: DiscoverySettings¶
- fixed_symbols: Collection[str]¶
- bar_repository: BarRepository¶
- decision_repository: DecisionRepository¶
- simulation_repository: SimulationRepository¶
- run(*, strategy_ids, now)[source]¶
Advance both of one strategy’s portfolios per id, all four* failure points isolated from each other.
(*) two per strategy, times as many strategies as strategy_ids holds. One variant of one strategy raising (a malformed inputs_json, a repository error) must not stop its own sibling variant, another strategy’s either variant, or the real cycle this was called from — the same per-unit isolation discipline discover_symbols uses per-theme.
- Parameters:
strategy_ids (Sequence[str])
now (datetime)
- Return type:
None
- trader.simulation.advance(*, strategy_id, now, bar_repository, decision_repository, simulation_repository, settings, pipeline_config, discovery_settings, fixed_symbols, portfolio_key=None, disable_sell_signals=False)[source]¶
Step strategy_id’s simulated portfolio through every completed, not-yet-applied bar of settings.sim_interval.
portfolio_key names the SimPortfolio row this call reads and writes; it defaults to strategy_id when left unset, which is every caller before issue #42. Decisions are always read using the real strategy_id — only the portfolio/account identity changes — which is how the Always-be-Buying (AbB) variant gets its own isolated ledger from the same recorded decisions a strategy’s normal portfolio already reads.
disable_sell_signals (issue #42) makes a recorded signal_action == “sell” a no-op for this call, as if it were unreadable — no round trip, no cash or position change — so only the trailing-stop test can ever close a position. It does not touch the stop itself.
Idempotent: a bar already recorded in SimPortfolio.last_bar_ts is never reapplied, and SimEquitySnapshot’s own (portfolio_id, bar_ts) unique constraint is the second, independent guard against the same thing. Never raises past this function for anything that can be isolated to one symbol or one bar — the caller’s own try/except is the last resort, not the first.
- Parameters:
strategy_id (str)
now (datetime)
bar_repository (BarRepository)
decision_repository (DecisionRepository)
simulation_repository (SimulationRepository)
settings (SimulationSettings)
pipeline_config (PipelineConfig)
discovery_settings (DiscoverySettings)
fixed_symbols (Collection[str])
portfolio_key (str | None)
disable_sell_signals (bool)
- Return type:
None