Source code for trader.reporting.window
"""Shared default-start-date resolution for report commands (issue #57).
`docs/operational-timeline.md` (2026-08-22) established that the live account
has no single clean "went live" instant — 2026-07-30 through 2026-08-16 mixes
manual `run-once` testing, an intermittent early daemon, a real business-trip
outage, and two machine migrations. Every report command used to default to
the earliest data available, which silently folded that pre-service noise
into every headline number unless an operator remembered to pass `--start` by
hand. `config/reporting.yaml`'s optional `default_report_start_date` fixes the
default; this module is the ONE place that decides how it interacts with an
explicit `--start` and the new `--since-creation` opt-out, so five call sites
(`trader performance`, `trader outcomes`, `trader sim-report`,
`tools/roi_investigation.py`, `trader web`) cannot each invent slightly
different precedence rules.
"""
from datetime import UTC, date, datetime, time
__all__ = ["resolve_report_start"]
[docs]
def resolve_report_start(
*,
explicit_start: datetime | None,
since_creation: bool,
default_start_date: date | None,
) -> datetime | None:
"""The effective start-of-window `datetime` a report command should use.
Precedence, matching the issue's own wording and every affected command's
docstring:
1. `explicit_start` (a real `--start` the operator typed) ALWAYS wins,
even over `--since-creation` — the flag combination "give me full
history, but not before this date" only makes sense if `--start`
stays authoritative when both are given.
2. `since_creation=True` returns `None` — no floor, full history — the
opt-out this issue adds. Only reached when `explicit_start` is absent.
3. `default_start_date` (`ReportingConfig.default_report_start_date`),
converted to UTC midnight — the new default this issue ships.
4. `default_start_date is None` (the config field was never set) returns
`None` — full history, byte-for-byte the pre-issue-#57 default. This is
the "absence is fine, wrongness is not" rule `config/reporting.yaml`
already documents for `benchmark_tickers`, extended to this field.
`None` throughout this module means "no floor" — the same convention
`SnapshotRepository.snapshots_in_range`/`snapshots_since` already use, so
a caller can pass this straight through to those methods (or an
equivalent date-range filter) unchanged.
"""
if explicit_start is not None:
return explicit_start
if since_creation:
return None
if default_start_date is not None:
return datetime.combine(default_start_date, time.min, tzinfo=UTC)
return None