Execute multiple flywheel configs and return a ranked leaderboard.
(
dataset: ResearchDataset,
configs: list[dict[str, Any]],
*,
run_names: list[str] | None = None,
)
| 185 | |
| 186 | |
| 187 | def run_flywheel_grid( |
| 188 | dataset: ResearchDataset, |
| 189 | configs: list[dict[str, Any]], |
| 190 | *, |
| 191 | run_names: list[str] | None = None, |
| 192 | ) -> dict[str, Any]: |
| 193 | """Execute multiple flywheel configs and return a ranked leaderboard.""" |
| 194 | if not configs: |
| 195 | raise ValueError("configs cannot be empty") |
| 196 | if run_names is not None and len(run_names) != len(configs): |
| 197 | raise ValueError("run_names/configs length mismatch") |
| 198 | |
| 199 | rows: list[dict[str, Any]] = [] |
| 200 | runs: list[dict[str, Any]] = [] |
| 201 | |
| 202 | for idx, cfg in enumerate(configs): |
| 203 | run_name = run_names[idx] if run_names is not None else f"run_{idx:02d}" |
| 204 | out = run_flywheel_iteration(dataset, config=cfg) |
| 205 | summary = out["summary"].row(0, named=True) |
| 206 | promotion = out["promotion"] |
| 207 | costs = out["costs"] |
| 208 | |
| 209 | row = { |
| 210 | "run_name": run_name, |
| 211 | "run_index": idx, |
| 212 | "config_digest": research_run_manifest(cfg)["config_digest"], |
| 213 | "portfolio_sharpe": float(summary["portfolio_sharpe"]), |
| 214 | "realized_sharpe": float(summary["realized_sharpe"]), |
| 215 | "net_sharpe": float(summary["net_sharpe"]), |
| 216 | "gross_total_return": float(costs["gross_total_return"]), |
| 217 | "net_total_return": float(costs["net_total_return"]), |
| 218 | "turnover": float(costs["turnover"]), |
| 219 | "estimated_cost": float(costs["estimated_total_cost"]), |
| 220 | "passed_realized_sharpe": bool(promotion["passed_realized_sharpe"]), |
| 221 | "passed_net_sharpe": bool(promotion["passed_net_sharpe"]), |
| 222 | "passed_alignment_guard": bool(promotion["passed_alignment_guard"]), |
| 223 | "passed_event_order_guard": bool(promotion["passed_event_order_guard"]), |
| 224 | "promote_candidate": bool(promotion["promote_candidate"]), |
| 225 | } |
| 226 | rows.append(row) |
| 227 | runs.append({"run_name": run_name, "config": cfg, "output": out}) |
| 228 | |
| 229 | leaderboard = pl.DataFrame(rows).sort( |
| 230 | by=["promote_candidate", "net_sharpe", "realized_sharpe", "run_index"], |
| 231 | descending=[True, True, True, False], |
| 232 | ) |
| 233 | return { |
| 234 | "leaderboard": leaderboard, |
| 235 | "records": leaderboard.to_dicts(), |
| 236 | "runs": runs, |
| 237 | } |
| 238 | |
| 239 | |
| 240 | def _turnover(positions: list[float]) -> float: |
nothing calls this directly
no test coverage detected