Files
atm/tests/test_report.py
Claude Agent bf70ca3ac7 feat: complete Faza 1 implementation (105 tests green)
All 12 modules built per reviewed plan:
- detector, state_machine (5-state phased FSM), canary, levels Phase B
- notifier fanout (Discord + Telegram, bounded queue, retry, dead-letter)
- audit (JSONL daily rotation), journal, report (weekly R-multiple PnL)
- calibrate + labeler (Tk, lazy-imported), dryrun with acceptance gate
- unified CLI: atm calibrate|label|dryrun|run|journal|report

README + Phase 2 prop-firm TOS audit checklist included.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 22:17:41 +00:00

77 lines
2.2 KiB
Python

"""Tests for atm.report."""
from __future__ import annotations
import pytest
from atm.journal import TradeEntry
from atm.report import iso_week, weekly_report
WEEK = "2026-16"
BASE_TS = "2026-04-14T10:00:00"
def _trade(
outcome: str,
direction: str = "BUY",
entry: float = 100.0,
sl: float = 90.0,
exit_: float | None = None,
detected_ts: str | None = None,
ts: str = BASE_TS,
) -> TradeEntry:
return TradeEntry(
ts=ts,
direction=direction,
symbol="US30",
entry=entry,
sl=sl,
tp1=None,
tp2=None,
exit=exit_,
outcome=outcome,
detected_ts=detected_ts,
notes="",
)
def test_win_rate_and_pnl() -> None:
"""5 synthetic trades: tp1 +2R, tp2 +3R, sl -1.5R, manual +2R, open excluded."""
trades = [
# tp1: BUY, entry=100, sl=90, exit=120 → R = (120-100)/(100-90) = +2.0
_trade("tp1", exit_=120.0, detected_ts="2026-04-14T09:59:55"),
# tp2: BUY, entry=100, sl=90, exit=130 → R = (130-100)/(100-90) = +3.0
_trade("tp2", exit_=130.0),
# sl: BUY, entry=100, sl=90, exit=85 → R = (85-100)/(100-90) = -1.5
_trade("sl", exit_=85.0, detected_ts="2026-04-14T09:59:50"),
# manual: SELL, entry=100, sl=110, exit=80 → R = (80-100)/(100-110) = +2.0
_trade("manual", direction="SELL", sl=110.0, exit_=80.0),
# open: excluded from counts
_trade("open"),
]
report = weekly_report(trades, WEEK)
assert report.week == WEEK
assert report.n_trades == 4
assert report.n_wins == 2
assert report.n_losses == 2
assert report.win_rate == pytest.approx(0.5)
assert report.pnl_r == pytest.approx(5.5)
# slippage: trade[0]=5s, trade[2]=10s → avg=7.5s
assert report.avg_slippage == pytest.approx(7.5)
def test_iso_week() -> None:
assert iso_week("2026-04-14T10:00:00") == "2026-16"
assert iso_week("2026-01-01T00:00:00") == "2026-01"
def test_empty_week() -> None:
report = weekly_report([], WEEK)
assert report.n_trades == 0
assert report.n_wins == 0
assert report.n_losses == 0
assert report.win_rate == 0.0
assert report.pnl_r == 0.0
assert report.avg_slippage is None