commanderzee commited on
Commit
8e80d26
·
verified ·
1 Parent(s): 915739a

hybrid edge-margin policy (edge_threshold + entry_price_max cap) — BTC +$1247

Browse files
Files changed (1) hide show
  1. train.py +32 -26
train.py CHANGED
@@ -384,22 +384,29 @@ def _directional_policy_apply(
384
  dn_asks: np.ndarray,
385
  pnl_ups: np.ndarray,
386
  pnl_dns: np.ndarray,
387
- p_up_thr: float,
388
- p_dn_thr: float,
389
- entry_price_max: float,
390
  ) -> Tuple[np.ndarray, np.ndarray]:
391
- """Given model's P(UP wins) per row + per-row side asks at tick 120, pick
392
- which side (if any) to enter. Enter UP iff preds >= p_up_thr AND up_ask
393
- entry_price_max. Enter DN iff preds p_dn_thr AND dn_ask
394
- entry_price_max. Priority: UP signal wins ties with DN signal. Returns
395
- (flag, pnl_per_row) arrays."""
 
 
 
 
 
 
396
  n = len(preds)
397
  flag = np.zeros(n, dtype=bool)
398
  pnl = np.zeros(n, dtype=np.float64)
399
  for i in range(n):
400
- up_ok = preds[i] >= p_up_thr and up_asks[i] <= entry_price_max
401
- dn_ok = preds[i] <= p_dn_thr and dn_asks[i] <= entry_price_max
402
- if up_ok:
 
 
403
  flag[i] = True
404
  pnl[i] = pnl_ups[i]
405
  elif dn_ok:
@@ -425,10 +432,12 @@ def _lgb_params_from_trial(trial: optuna.Trial) -> Tuple[Dict, Dict]:
425
  "n_estimators": 500,
426
  }
427
  trading = {
428
- "p_up_threshold": trial.suggest_float("p_up_threshold", 0.50, 0.80),
429
- "p_dn_threshold": trial.suggest_float("p_dn_threshold", 0.20, 0.50),
430
- # "lower is better" — cap the entry price we're willing to pay
431
- "entry_price_max": trial.suggest_float("entry_price_max", 0.20, 0.60),
 
 
432
  }
433
  return params, trading
434
 
@@ -543,8 +552,7 @@ def run_training(
543
  continue
544
  flag, pnl = _directional_policy_apply(
545
  res["preds"], uav, dav, pup_v, pdn_v,
546
- trading["p_up_threshold"],
547
- trading["p_dn_threshold"],
548
  trading["entry_price_max"],
549
  )
550
  sim = simulate_flagging_pnl(pnl, flag)
@@ -562,8 +570,7 @@ def run_training(
562
 
563
  best_params_trial = dict(study.best_trial.params)
564
  best_trading = {
565
- "p_up_threshold": float(best_params_trial.pop("p_up_threshold")),
566
- "p_dn_threshold": float(best_params_trial.pop("p_dn_threshold")),
567
  "entry_price_max": float(best_params_trial.pop("entry_price_max")),
568
  }
569
  best_lgb_params = {
@@ -595,8 +602,7 @@ def run_training(
595
  res = _train_fold_core(Xt, yt, Xv, yv, best_lgb_params)
596
  flag, pnl = _directional_policy_apply(
597
  res["preds"], uav, dav, pup_v, pdn_v,
598
- best_trading["p_up_threshold"],
599
- best_trading["p_dn_threshold"],
600
  best_trading["entry_price_max"],
601
  )
602
  sim = simulate_flagging_pnl(pnl, flag)
@@ -638,8 +644,7 @@ def run_training(
638
  hold_preds = final_booster.predict(X_hold)
639
  hold_flag, hold_pnl = _directional_policy_apply(
640
  hold_preds, up_ask_hold, dn_ask_hold, pnl_up_hold, pnl_dn_hold,
641
- best_trading["p_up_threshold"],
642
- best_trading["p_dn_threshold"],
643
  best_trading["entry_price_max"],
644
  )
645
  hold_sim = simulate_flagging_pnl(hold_pnl, hold_flag)
@@ -685,9 +690,10 @@ def run_training(
685
  json.dumps(
686
  {
687
  "trading": best_trading,
688
- "notes": "Directional model: enter UP if pred >= p_up_threshold "
689
- "AND up_ask <= entry_price_max. Enter DN if pred <= "
690
- "p_dn_threshold AND dn_ask <= entry_price_max. Else skip.",
 
691
  },
692
  indent=2,
693
  )
 
384
  dn_asks: np.ndarray,
385
  pnl_ups: np.ndarray,
386
  pnl_dns: np.ndarray,
387
+ edge_threshold: float,
388
+ entry_price_max: float = 1.0,
 
389
  ) -> Tuple[np.ndarray, np.ndarray]:
390
+ """Edge-margin decision rule.
391
+
392
+ On Polymarket the ask for side S is approximately the market's implied
393
+ P(S wins). So `edge_up = model_pred - up_ask` = our estimate minus the
394
+ market's the expected PnL per share before fees. If this exceeds a
395
+ threshold on either side, we trade that side. Whichever edge is larger
396
+ wins when both clear threshold.
397
+
398
+ Single-knob policy (one Optuna param) — drops the prior 3-param setup
399
+ (p_up_threshold, p_dn_threshold, entry_price_max) which was
400
+ susceptible to overfit in Optuna's larger search space."""
401
  n = len(preds)
402
  flag = np.zeros(n, dtype=bool)
403
  pnl = np.zeros(n, dtype=np.float64)
404
  for i in range(n):
405
+ edge_up = preds[i] - up_asks[i]
406
+ edge_dn = (1.0 - preds[i]) - dn_asks[i]
407
+ up_ok = (edge_up >= edge_threshold) and (up_asks[i] <= entry_price_max)
408
+ dn_ok = (edge_dn >= edge_threshold) and (dn_asks[i] <= entry_price_max)
409
+ if up_ok and (not dn_ok or edge_up >= edge_dn):
410
  flag[i] = True
411
  pnl[i] = pnl_ups[i]
412
  elif dn_ok:
 
432
  "n_estimators": 500,
433
  }
434
  trading = {
435
+ # primary: edge-margin (model_pred - market_ask for the chosen side)
436
+ "edge_threshold": trial.suggest_float("edge_threshold", 0.03, 0.25),
437
+ # safety cap: block high-entry overconfident trades where the
438
+ # model's probability is likely uncalibrated. Without this, BTC
439
+ # lost -$621 on a run (vs +$390 with the cap).
440
+ "entry_price_max": trial.suggest_float("entry_price_max", 0.40, 0.65),
441
  }
442
  return params, trading
443
 
 
552
  continue
553
  flag, pnl = _directional_policy_apply(
554
  res["preds"], uav, dav, pup_v, pdn_v,
555
+ trading["edge_threshold"],
 
556
  trading["entry_price_max"],
557
  )
558
  sim = simulate_flagging_pnl(pnl, flag)
 
570
 
571
  best_params_trial = dict(study.best_trial.params)
572
  best_trading = {
573
+ "edge_threshold": float(best_params_trial.pop("edge_threshold")),
 
574
  "entry_price_max": float(best_params_trial.pop("entry_price_max")),
575
  }
576
  best_lgb_params = {
 
602
  res = _train_fold_core(Xt, yt, Xv, yv, best_lgb_params)
603
  flag, pnl = _directional_policy_apply(
604
  res["preds"], uav, dav, pup_v, pdn_v,
605
+ best_trading["edge_threshold"],
 
606
  best_trading["entry_price_max"],
607
  )
608
  sim = simulate_flagging_pnl(pnl, flag)
 
644
  hold_preds = final_booster.predict(X_hold)
645
  hold_flag, hold_pnl = _directional_policy_apply(
646
  hold_preds, up_ask_hold, dn_ask_hold, pnl_up_hold, pnl_dn_hold,
647
+ best_trading["edge_threshold"],
 
648
  best_trading["entry_price_max"],
649
  )
650
  hold_sim = simulate_flagging_pnl(hold_pnl, hold_flag)
 
690
  json.dumps(
691
  {
692
  "trading": best_trading,
693
+ "notes": "Edge-margin rule: edge_up = model_pred - up_ask; "
694
+ "edge_dn = (1 - model_pred) - dn_ask. Enter the side "
695
+ "with the larger edge, iff that edge >= edge_threshold. "
696
+ "Edge is expected PnL per share before fees.",
697
  },
698
  indent=2,
699
  )