[verified] Task 8: verification evidence + fail-closed look-ahead fix + docs (event-driven backtest)
This commit is contained in:
@@ -106,3 +106,4 @@
|
||||
- Real dated dividend-history collector (2026-08-27, commit `f9973e8`): `siamchart.py` gained `parse_dividend_history`/`fetch_dividend_history` (reads the "ประวัติการปันผล" ex-date + DPS table per stock-info page); `dividend_ledger.py` gained `populate_dated_dividends` (registers dated rows, estimate=False). `POST /api/v1/dividends/update` fetches all snapshot symbols and persists a dated ledger at `data/dividends/ledger.json`; `use_ledger` backtests prefer the dated ledger (`dividend_method=dated_ledger`) and fall back to DPS estimates when unpopulated. Full backend **292 passed** (was 286). Live network fetch: 49/49 symbols, 1410 dated payments; use_ledger → `dated_ledger`. Note: this sandbox HAS outbound network (curl/https to siamchart 200) — contrary to earlier assumption.
|
||||
- Auto-refresh dated dividend ledger (2026-08-27, commit `03195dc`): `AppDataScheduler` now calls `_maybe_refresh_dated_dividends()` in `refresh_all` — a cooldown-gated (default 6h) fetch of real dated dividend history into `data/dividends/ledger.json`, so the ledger stays fresh without manual `/api/v1/dividends/update` and without hammering the source every tick. `DIVIDEND_REFRESH_COOLDOWN_SECONDS` env toggle. Full backend **294 passed** (was 292).
|
||||
- Single-container Docker packaging (2026-08-27, commit `f9b8cd1`): added `Dockerfile` (python:3.11-slim + nginx; serves the PREBUILT `frontend/dist` SPA, proxies `/api` → 127.0.0.1:5000, `VOLUME /app/backend/data`, HEALTHCHECK on /api/v1/dashboard/summary, exposes :80), `deploy/nginx.conf`, `deploy/entrypoint.sh` (Flask HOST=0.0.0.0:5000 + nginx foreground), `docker-compose.yml` (port 8080:80, volume `./backend/data`), `.dockerignore`, and `.gitignore` now tracks `frontend/dist/` (prebuilt bundle required by the image; `backend/data/` stays untracked). Backend runtime verified (test_client `/api/v1/dashboard/summary` = 200). No local docker on this machine so the image itself must build on EasyPanel.
|
||||
- Event-driven PIT backtest (2026-08-28, commits `68f2cc1` → `d73a58b`, 8-phase plan at `.hermes/plans/2026-08-28_091000-event-driven-pit-backtest.md`): replaces the calendar-rebalance backtest with a strict point-in-time event-driven engine. Confirmed user decisions: (1) strict PIT — block when factor/Siamchart/price coverage is incomplete; (2) execute at next trading-day close after release (no same-day look-ahead); (3) dividend cash available ex_date+30 calendar days (`ex_date_plus_30d` assumption, not an observed pay date — Siamchart source gives ex-date+DPS only); (4) average-cost realized P&L; (5) all-in 0.3% fee per trade, no added tax. Ships: `backtest_readiness.py` (readiness + recommended start/end defaults, fail-closed), `backtest_events.py` (event calendar + next-trading-day mapping), `portfolio_ledger.py` (cash/positions/avg-cost/realized+unrealized P&L/dividend receivables/fees; gross realized + fees subtracted once), `portfolio_rebalancer.py` (50/20/30 → executable 100-lot orders, sells-first, no trade on unchanged target), `backtest_engine.py` (event processor; refuses to fall back to the live board without a PIT scorer — fail-closed, was flagged by cycle-1 review `deleg_5225e9de` and fixed), `backtest_store.py` (durable atomic JSON runs at `data/backtest/runs.json`), strict route `POST /api/v1/backtest/run` (readiness-gate → 400 with missing list when not ready) + `GET /api/v1/backtest/run(+<id>)`, and frontend (readiness gate disables Run + shows missing coverage; report shows realized/unrealized P&L, dividend received/receivable, fees, final holdings with avg cost/last price/unrealized). Offline standalone suite **52 tests** (9+14+15+5+5+4); compileall + diff-check clean; static scan no secrets/eval/debug (4 "secret"-regex hits are the prose "missing token" string, not credentials). Live probes: `GET /api/v1/backtest/readiness` on real data → ready=false, recommended_end=2026-08-27; `POST /api/v1/backtest/run` on real data (no vintages) → 400 + missing list; happy-path `scripts/probe_event_backtest.py` (synthetic PIT-complete) → accounting_reconciled=True, identity lhs=rhs, leakage_guard=True, 100-lot holdings.
|
||||
|
||||
Reference in New Issue
Block a user