quant-web/strategies/registry.py
epistemophiliac 627b2326df Add Python strategy engine, parameter optimization, and faster Docker builds.
Support builtin and custom generate_signals strategies with SQLite persistence, exhaustive grid scans (VectorBT comb optimization for MA crossover), professional backtest/optimize UI, and split harvester/app requirements with BuildKit pip cache.
2026-06-19 01:29:28 -04:00

72 lines
2.1 KiB
Python

"""Builtin strategy registry."""
from __future__ import annotations
import inspect
from dataclasses import dataclass
from typing import Any, Callable
from strategies.builtin import ma_crossover, rsi_reversion
SignalFn = Callable[..., tuple[Any, Any]]
@dataclass(frozen=True)
class BuiltinStrategy:
key: str
display_name: str
description: str
module: Any
generate_signals: SignalFn
default_params: dict[str, Any]
param_grid: dict[str, list[Any]]
source_code: str
def optimize(self, close, init_cash: float, fees: float, metric: str, grid_override: dict | None = None):
if self.key == "ma_crossover":
pool = (grid_override or {}).get("window_pool", self.param_grid.get("window_pool"))
return self.module.optimize_vectorized(
close,
window_pool=pool,
init_cash=init_cash,
fees=fees,
metric=metric,
)
if self.key == "rsi_reversion":
return self.module.optimize_grid(
close,
param_grid=grid_override or self.param_grid,
init_cash=init_cash,
fees=fees,
metric=metric,
)
raise NotImplementedError(f"No optimizer for {self.key}")
def _register(module) -> BuiltinStrategy:
return BuiltinStrategy(
key=module.STRATEGY_KEY,
display_name=module.DISPLAY_NAME,
description=module.DESCRIPTION,
module=module,
generate_signals=module.generate_signals,
default_params=dict(module.DEFAULT_PARAMS),
param_grid=dict(module.PARAM_GRID),
source_code=inspect.getsource(module),
)
BUILTIN_STRATEGIES: dict[str, BuiltinStrategy] = {
ma_crossover.STRATEGY_KEY: _register(ma_crossover),
rsi_reversion.STRATEGY_KEY: _register(rsi_reversion),
}
def list_builtins() -> list[BuiltinStrategy]:
return list(BUILTIN_STRATEGIES.values())
def get_builtin(key: str) -> BuiltinStrategy:
if key not in BUILTIN_STRATEGIES:
raise KeyError(f"Unknown builtin strategy: {key}")
return BUILTIN_STRATEGIES[key]