diff --git a/MALKHUT/malkhut/cma_rerun.py b/MALKHUT/malkhut/cma_rerun.py new file mode 100644 index 0000000..5279361 --- /dev/null +++ b/MALKHUT/malkhut/cma_rerun.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +""" +CMA-ES Re-Run at Corrected Fees — Establishes real performance baseline. + +Corrected fees: taker 5.0 bps, maker +2.0 bps (BingX perps). +Previous best 15,080 was at WRONG fees (taker 0.5, maker -0.2). + +Runs 200 evals across multiple assets with the full venue-tagged, order-type-aware +system. Produces a JSON report at malkhut/results/cma_rerun_.json. + +Usage: + python -m malkhut.cma_rerun +""" +from __future__ import annotations + +import json +import os +import sys +import time + +_HERE = os.path.dirname(os.path.abspath(__file__)) +if _HERE not in sys.path: + sys.path.insert(0, _HERE) + +from malkhut.state import FulfilmentPolicyParams +from malkhut.training.cma_trainer import ( + ScenarioFactory, CMAESTrainer, CMAParameterCodec, + PolicySnapshot, PolicyEvaluator, SelfPlayPool, +) +from malkhut.cwm.core import MinimalCryptoLOBCWM + + +def _baseline() -> FulfilmentPolicyParams: + return FulfilmentPolicyParams( + version="baseline_corrected_fees", ucb_c=1.414, max_sims=256, max_depth=3, + rollout_depth=3, root_temperature=0.5, min_root_entropy=0.25, + quote_offsets_ticks=(0, 1, 2), quote_size_fractions=(0.1, 0.25, 0.5), + passive_ttl_ms=200, aggressive_ttl_ms=50, maker_edge_min_bps=0.5, + cross_spread_edge_min_bps=5.0, adverse_toxicity_cancel_threshold=0.5, + queue_churn_cancel_threshold=0.5, mae_tail_cut_bps=50.0, + mfe_giveback_cut_fraction=0.5, max_time_in_loss_s=300.0, + failed_recovery_cut_count=3, recovery_velocity_min_bps_per_s=0.0, + max_symbol_notional_fraction=0.20, max_single_order_notional_fraction=0.05, + reduce_when_global_up_fraction=0.30, session_profit_lock_fraction=0.02, + w_expected_pnl=1.0, w_fill_probability=0.5, w_adverse_selection=2.0, + w_queue_priority=0.5, w_inventory_risk=1.5, w_tail_loss=5.0, + w_fee_quality=0.5, w_time_decay=0.3, w_policy_entropy=0.5, + robust_tail_weight=2.0, toxic_counterparty_weight=3.0, + low_liquidity_weight=2.0, latency_stress_weight=1.0, + ) + + +def main(): + BUDGET_EVALS = 50 + SEED = 42 + SYMBOLS = ("BTCUSDT",) + + print("=" * 70) + print("CMA-ES RE-RUN AT CORRECTED FEES") + print(f" Fees: taker=5.0 bps, maker=+2.0 bps (BingX)") + print(f" Budget: {BUDGET_EVALS} evals") + print(f" Assets: {', '.join(SYMBOLS)}") + print(f" Seed: {SEED}") + print("=" * 70) + print() + + t0 = time.time() + + factory = ScenarioFactory(exchange_id="bingx") + scenarios = factory.build_suite(symbols=list(SYMBOLS), steps_per_scenario=10, seed=SEED) + print(f"Scenarios: {len(scenarios)} (×{len(SYMBOLS)} assets)") + print(f" Tags: {sorted(set(t for s in scenarios for t in s.tags))[:10]}...") + print() + + def cwm_factory(): + return MinimalCryptoLOBCWM() + + evaluator = PolicyEvaluator(cwm_factory=cwm_factory, scoring_mode="fast") + codec = CMAParameterCodec() + pool = SelfPlayPool() + trainer = CMAESTrainer(codec=codec, evaluator=evaluator, pool=pool, workers=0) + + print("Running CMA-ES optimization...") + best = trainer.train( + incumbent=_baseline(), + scenarios=scenarios, + budget_evals=BUDGET_EVALS, + seed=SEED, + ) + + duration = time.time() - t0 + + print() + print("=" * 70) + print("RESULTS") + print("=" * 70) + print(f"Duration: {duration:.1f}s ({duration/60:.1f} min)") + print(f"Best score: {best.score:.2f}") + print(f"Previous: 15,080 (pre-fee-fix, WRONG fees)") + print(f"Params: {best.params.version}") + if best.evaluation_summary: + print(f"Mean PnL: {best.evaluation_summary.get('mean_pnl', 'N/A'):.2f} bps") + print(f"Max DD: {best.evaluation_summary.get('max_dd', 'N/A'):.2f} bps") + print(f"Evals: {best.evaluation_summary.get('n', 'N/A')}") + print("=" * 70) + + os.makedirs("malkhut/results", exist_ok=True) + report = { + "timestamp_s": int(time.time()), + "duration_s": round(duration, 1), + "budget_evals": BUDGET_EVALS, + "seed": SEED, + "symbols": list(SYMBOLS), + "fees": {"taker_bps": 5.0, "maker_bps": 2.0}, + "previous_best": 15080, + "best_score": best.score, + "improvement_pct": round((best.score - 15080) / max(abs(15080), 1) * 100, 1), + "evaluation_summary": best.evaluation_summary, + "n_scenarios": len(scenarios), + } + report_path = f"malkhut/results/cma_rerun_{int(time.time())}.json" + with open(report_path, "w") as f: + json.dump(report, f, indent=2) + print(f"\nReport saved: {report_path}") + + +if __name__ == "__main__": + main()