Add trailing stops and parameter sweeps
CI/CD / backend (pull_request) Successful in 6m6s
CI/CD / frontend (pull_request) Successful in 5m17s
CI/CD / build (pull_request) Skipped
CI/CD / deploy (pull_request) Skipped
CI/CD / cleanup (pull_request) Skipped

Trailing stops: strategies can pass trailing_stop_pct to enter_long/enter_short.
advance_trailing_stop in app/engine/portfolio.py ratchets the stop with the price
(up for longs, down for shorts) and never loosens; the engine persists the
ratcheted level and the backtester applies the same logic. Position gains a
trailing_stop_pct column (additive migration). momentum exposes it as a param.

Parameter sweeps: app/backtest/sweep.py runs a cartesian grid through the same
backtester and ranks by return minus max drawdown. POST /api/sweep plus a
dashboard Parameter sweep panel.
This commit is contained in:
matitos committed 2026-09-19 23:04:20 +00:00
1 parent d80e7b155e
commit 9dc00eba95
22 files changed
+575 -7

No files matched your search

+14
View File
@@ -25,6 +25,8 @@ from app.schemas import (
StrategyConfigIn,
StrategyConfigOut,
StrategyOut,
SweepRequest,
SweepResult,
)
router = APIRouter(prefix="/api")
@@ -139,6 +141,18 @@ def delete_preset(config_id: int, runtime: GuardedRuntimeDep) -> dict[str, bool]
return {"deleted": True}
@router.post("/sweep", response_model=SweepResult)
async def run_sweep_endpoint(payload: SweepRequest, runtime: GuardedRuntimeDep) -> SweepResult:
try:
return await runtime.run_sweep(payload)
except KeyError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except httpx.HTTPError as exc:
raise HTTPException(status_code=502, detail=f"market data error: {exc}") from exc
def _position_out(position: Position, price: float | None) -> PositionOut:
out = PositionOut.model_validate(position)
if position.status == PositionStatus.OPEN and price is not None: