Initial strategy32 research and live runtime
This commit is contained in:
104
scripts/run_ablation_analysis.py
Normal file
104
scripts/run_ablation_analysis.py
Normal file
@@ -0,0 +1,104 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pandas as pd
|
||||
|
||||
PACKAGE_PARENT = Path(__file__).resolve().parents[2]
|
||||
if str(PACKAGE_PARENT) not in sys.path:
|
||||
sys.path.insert(0, str(PACKAGE_PARENT))
|
||||
|
||||
from strategy29.backtest.window_analysis import evaluate_window_result, slice_bundle
|
||||
from strategy32.backtest.simulator import Strategy32Backtester
|
||||
from strategy32.config import PROFILE_V5_BASELINE, build_strategy32_config
|
||||
from strategy32.data import build_strategy32_market_bundle
|
||||
|
||||
|
||||
WINDOWS = [(30, "1m"), (365, "1y"), (1095, "3y"), (1825, "5y")]
|
||||
|
||||
|
||||
def build_variants() -> list[tuple[str, dict[str, bool]]]:
|
||||
return [
|
||||
("baseline_v5", {}),
|
||||
("no_sideways", {"enable_sideways_engine": False}),
|
||||
("strong_kill_switch", {"enable_strong_kill_switch": True}),
|
||||
("daily_trend_filter", {"enable_daily_trend_filter": True}),
|
||||
("expanded_hedge", {"enable_expanded_hedge": True}),
|
||||
("max_holding_exit", {"enable_max_holding_exit": True}),
|
||||
]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
base = build_strategy32_config(PROFILE_V5_BASELINE)
|
||||
end = pd.Timestamp("2026-03-15 00:00:00", tz="UTC")
|
||||
start = end - pd.Timedelta(days=max(days for days, _ in WINDOWS) + base.warmup_days + 14)
|
||||
|
||||
print("fetching bundle...")
|
||||
bundle, latest_completed_bar, accepted_symbols, rejected_symbols, quote_by_symbol = build_strategy32_market_bundle(
|
||||
symbols=base.symbols,
|
||||
auto_discover_symbols=base.auto_discover_symbols,
|
||||
quote_assets=base.quote_assets,
|
||||
excluded_base_assets=base.excluded_base_assets,
|
||||
min_quote_volume_24h=base.discovery_min_quote_volume_24h,
|
||||
start=start,
|
||||
end=end,
|
||||
timeframe=base.timeframe,
|
||||
max_staleness_days=base.max_symbol_staleness_days,
|
||||
)
|
||||
print("latest", latest_completed_bar)
|
||||
|
||||
results: dict[str, dict[str, dict[str, float | int | str]]] = {}
|
||||
for name, overrides in build_variants():
|
||||
cfg = copy.deepcopy(base)
|
||||
for key, value in overrides.items():
|
||||
setattr(cfg, key, value)
|
||||
variant_results = {}
|
||||
print("\nVARIANT", name)
|
||||
for days, label in WINDOWS:
|
||||
eval_end = latest_completed_bar
|
||||
eval_start = eval_end - pd.Timedelta(days=days)
|
||||
raw_start = eval_start - pd.Timedelta(days=cfg.warmup_days)
|
||||
sliced = slice_bundle(bundle, raw_start, eval_end)
|
||||
backtester = Strategy32Backtester(cfg, sliced, trade_start=eval_start)
|
||||
backtester.engine_config.initial_capital = 1000.0
|
||||
result = backtester.run()
|
||||
metrics = evaluate_window_result(result, eval_start=eval_start, bars_per_day=backtester.engine_config.bars_per_day)
|
||||
metrics["engine_pnl"] = result.engine_pnl
|
||||
metrics["total_trades"] = result.total_trades
|
||||
variant_results[label] = metrics
|
||||
print(
|
||||
label,
|
||||
"ret",
|
||||
round(float(metrics["total_return"]) * 100, 2),
|
||||
"mdd",
|
||||
round(float(metrics["max_drawdown"]) * 100, 2),
|
||||
"sharpe",
|
||||
round(float(metrics["sharpe"]), 2),
|
||||
"trades",
|
||||
metrics["trade_count"],
|
||||
)
|
||||
results[name] = variant_results
|
||||
|
||||
payload = {
|
||||
"strategy": "strategy32",
|
||||
"analysis": "v6_single_change_ablation",
|
||||
"initial_capital": 1000.0,
|
||||
"auto_discover_symbols": base.auto_discover_symbols,
|
||||
"latest_completed_bar": str(latest_completed_bar),
|
||||
"requested_symbols": [] if base.auto_discover_symbols else base.symbols,
|
||||
"accepted_symbols": accepted_symbols,
|
||||
"rejected_symbols": rejected_symbols,
|
||||
"quote_by_symbol": quote_by_symbol,
|
||||
"timeframe": base.timeframe,
|
||||
"results": results,
|
||||
}
|
||||
out = Path("/tmp/strategy32_v6_ablation.json")
|
||||
out.write_text(json.dumps(payload, indent=2), encoding="utf-8")
|
||||
print("\nwrote", out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user