Corrected fees: taker=5.0, maker=+2.0 (BingX). Previous best: 15,080 (pre-fee-fix, WRONG fees). New best: 34,898 (+131.4%). 50 evals, 8.3 min, BTCUSDT. Mean PnL: 582 bps, Max DD: 83 bps.
129 lines
4.5 KiB
Python
129 lines
4.5 KiB
Python
#!/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_<ts>.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()
|