Files
atm-backtesting/scripts/verify_template.py
Marius Mutu 85ca68b11e filtru Prima per Indicator pe grid FERESTRE CANDIDATE x STRATEGIE
- PrimaWin_<idx> helper columns in Trades (per fereastră)
- DASH_WIN_COL dict refactor (zero hardcoded litere)
- Coloana Filtru (D) în window grid: rânduri Toate/Prima paralele
- Score split T (Score_Toate) + U (Score_Prima), ambele hidden
- TOP CANDIDATE: 2 sub-secțiuni — TOP 5 Toate + TOP 5 Prima
- Config!B17 escape hatch (DA/NU) pentru performanță
- 5 sample rows care exercită Prima edge cases
- scripts/verify_template.py: 18 aserțiuni smoke test
- .gitignore: data/backtest.backup-*.xlsx
- sterse 2 backup-uri vechi din git

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 20:25:05 +03:00

238 lines
7.7 KiB
Python

"""Smoke test for data/backtest.xlsx after regeneration.
Asserts column positions, sample row formula structure, and TOP CANDIDATE
formula sources. Run AFTER `python scripts/generate_template.py`.
Exit codes: 0 = all PASS, 1 = at least one FAIL, 2 = workbook missing.
"""
from __future__ import annotations
import sys
from pathlib import Path
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
# Romanian diacritics in test names — force UTF-8 stdout on Windows cp1252.
try:
sys.stdout.reconfigure(encoding="utf-8")
except (AttributeError, OSError):
pass
OUTPUT = Path(__file__).resolve().parent.parent / "data" / "backtest.xlsx"
FAILURES: list[str] = []
def _report(name: str, ok: bool, detail: str = "") -> None:
tag = "[PASS]" if ok else "[FAIL]"
msg = f"{tag} {name}"
if detail:
msg += f" -- {detail}"
print(msg)
if not ok:
FAILURES.append(name)
def _find_row_with(ws, col_letter: str, needle: str) -> int | None:
"""Return 1-based row where ws[col_letter+row].value == needle, else None."""
for row in range(1, ws.max_row + 1):
val = ws[f"{col_letter}{row}"].value
if val == needle:
return row
return None
def _find_col_for_header(ws, row: int, needle: str) -> str | None:
for col_idx in range(1, ws.max_column + 1):
if ws.cell(row=row, column=col_idx).value == needle:
return get_column_letter(col_idx)
return None
def check_window_grid_headers(wb) -> None:
ws = wb["Dashboard"]
header_row = _find_row_with(ws, "A", "Fereastra")
if header_row is None:
_report("Dashboard window grid header row", False, "no row with A='Fereastra'")
return
_report("Dashboard window grid header row", True, f"row {header_row}")
expected = {
"A": "Fereastra",
"D": "Filtru",
"E": "Strategie",
"F": "N",
"S": "Status Edge",
"T": "Score_Toate",
"U": "Score_Prima",
}
for col, want in expected.items():
got = ws[f"{col}{header_row}"].value
if got == want:
_report(f"Dashboard header {col}={want!r}", True)
else:
actual_col = _find_col_for_header(ws, header_row, want)
detail = (
f"got {got!r} at {col}; expected {want!r}. "
f"Header {want!r} actually at column {actual_col}"
)
_report(f"Dashboard header {col}={want!r}", False, detail)
def check_hidden_columns(wb) -> None:
ws = wb["Dashboard"]
for col in ("T", "U"):
hidden = ws.column_dimensions[col].hidden is True
_report(
f"Dashboard column {col} hidden",
hidden,
"" if hidden else f"hidden={ws.column_dimensions[col].hidden!r}",
)
def check_primawin_headers(wb) -> tuple[str | None, int]:
"""Return (column letter of PrimaWin_0, count of PrimaWin_* headers)."""
ws = wb["Trades"]
win0_col: str | None = None
count = 0
for col_idx in range(1, ws.max_column + 1):
v = ws.cell(row=1, column=col_idx).value
if isinstance(v, str) and v.startswith("PrimaWin_"):
count += 1
if v == "PrimaWin_0":
win0_col = get_column_letter(col_idx)
if count == 0:
_report("Trades has PrimaWin_* headers", False, "none found")
else:
_report(
"Trades has PrimaWin_* headers",
True,
f"{count} columns; PrimaWin_0 at column {win0_col}",
)
return win0_col, count
def check_primawin_formula(wb, win0_col: str | None) -> None:
if win0_col is None:
_report("PrimaWin_0 sample row formula", False, "no PrimaWin_0 column")
return
ws = wb["Trades"]
formula = ws[f"{win0_col}2"].value
if not isinstance(formula, str):
_report(
"PrimaWin_0 sample row formula",
False,
f"row 2 value is {formula!r}, not a formula",
)
return
must_have = ["TIME(16,30,0)", "Config!$B$17", "COUNTIFS"]
missing = [token for token in must_have if token not in formula]
if missing:
_report(
"PrimaWin_0 sample row formula",
False,
f"missing tokens: {missing}; formula starts: {formula[:120]!r}",
)
else:
_report("PrimaWin_0 sample row formula", True, "TIME(16,30,0) + Config!$B$17 present")
def check_top_candidate_sources(wb) -> None:
ws = wb["Dashboard"]
title_toate = "TOP 5 FERESTRE — Toate trade-urile"
title_prima = "TOP 5 FERESTRE — Prima per Indicator"
# Fallback: scan loosely if the em-dash doesn't match.
def _find_title(prefix: str) -> int | None:
for row in range(1, ws.max_row + 1):
v = ws.cell(row=row, column=1).value
if isinstance(v, str) and v.startswith(prefix):
return row
return None
cases = [
("TOP 5 Toate", title_toate, "Toate", "LARGE($T$"),
("TOP 5 Prima", title_prima, "Prima per Indicator", "LARGE($U$"),
]
for name, exact_title, fallback_prefix, expected_token in cases:
title_row = _find_row_with(ws, "A", exact_title)
if title_row is None:
title_row = _find_title(f"TOP 5 FERESTRE")
# Narrow: must mention the discriminator
title_row = None
for row in range(1, ws.max_row + 1):
v = ws.cell(row=row, column=1).value
if isinstance(v, str) and "TOP 5 FERESTRE" in v and fallback_prefix in v:
title_row = row
break
if title_row is None:
_report(f"{name} title found", False, f"no row containing 'TOP 5 FERESTRE' + {fallback_prefix!r}")
continue
_report(f"{name} title found", True, f"row {title_row}")
# Look at the next few rows for a LARGE() formula in any column.
found = False
for offset in (1, 2, 3):
scan_row = title_row + offset
for col_idx in range(1, ws.max_column + 1):
cell = ws.cell(row=scan_row, column=col_idx).value
if isinstance(cell, str) and expected_token in cell:
_report(
f"{name} uses {expected_token}",
True,
f"row {scan_row} col {get_column_letter(col_idx)}",
)
found = True
break
if found:
break
if not found:
# Sample a formula for diagnostics.
sample = ws.cell(row=title_row + 1, column=1).value
_report(
f"{name} uses {expected_token}",
False,
f"token not found in rows {title_row+1}..{title_row+3}; sample A: {sample!r}",
)
def check_config_escape_hatch(wb) -> None:
ws = wb["Config"]
a17 = ws["A17"].value
b17 = ws["B17"].value
_report(
"Config!A17 = 'Activează filtru Prima'",
a17 == "Activează filtru Prima",
f"got {a17!r}",
)
_report("Config!B17 = 'DA'", b17 == "DA", f"got {b17!r}")
def main() -> int:
if not OUTPUT.exists():
print(f"Workbook not found: {OUTPUT}")
print("RUN python scripts/generate_template.py FIRST")
return 2
wb = load_workbook(OUTPUT, data_only=False)
print(f"Verifying {OUTPUT}")
print("-" * 60)
check_window_grid_headers(wb)
check_hidden_columns(wb)
win0_col, _ = check_primawin_headers(wb)
check_primawin_formula(wb, win0_col)
check_top_candidate_sources(wb)
check_config_escape_hatch(wb)
print("-" * 60)
if FAILURES:
print(f"{len(FAILURES)} FAIL: {FAILURES}")
return 1
print("ALL CHECKS PASSED")
return 0
if __name__ == "__main__":
sys.exit(main())