Rolling train/test folds over 3 years of data auto-optimize the three
cheap-to-tune trading parameters (STRONG/BUY score thresholds, max hold
time) via grid search on each fold's train window, then evaluate purely
on the held-out test window. Stitching all out-of-sample results gives
an honest performance estimate uninflated by tuning against the same
data used to score it.
Split signal_scoring.py's expensive 13-algorithm scoring from its cheap
final threshold classification so grid search can replay many parameter
combinations without recomputing indicators each time. Moved the
backtest engine (fetch/precompute/simulate) out of the API layer into
app/services/backtest_engine.py so both /backtest/run and the new
walk-forward optimizer share one implementation instead of drifting
copies — same rationale as the earlier signal_service.py split (item h).
Also merges two long-diverged Alembic migration heads discovered while
adding the walk_forward_results table, so `alembic upgrade head` has a
single target again.
New: POST/GET/DELETE /walk-forward/* endpoints, a Walk-Forward tab on
the Backtest page (fold table, out-of-sample equity curve, run history).
19 new backend tests (153 total, all passing).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- orders.place_order: yêu cầu role trader/admin (get_current_trader_user)
thay vì bất kỳ user đã đăng nhập nào — viewer không còn đặt được lệnh thật
- orders.place_order: resolve exchange theo OrderRequest.exchange thay vì
hardcode "mexc", fallback về credential active gần nhất nếu không truyền
- security.py: mã hoá API key chuyển AES-256-CBC -> AES-256-GCM (có xác thực
toàn vẹn), giữ đường giải mã cũ để credential đã lưu trước đây không hỏng
- main_api.py: CORS_ORIGINS rỗng -> deny-all thay vì fallback "*" (kèm
allow_credentials=True là cấu hình nguy hiểm)
- docker-compose.yml: đồng bộ DB_PASSWORD giữa backend-api/scheduler và db
- frontend: OrderPanel/DashboardPage truyền kèm exchange đang chọn khi đặt lệnh
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>