KarlQuant commited on
Commit
5df31eb
Β·
verified Β·
1 Parent(s): a5b2942

Upload Quasar_axrvi_ranker.py

Browse files
Files changed (1) hide show
  1. Quasar_axrvi_ranker.py +45 -28
Quasar_axrvi_ranker.py CHANGED
@@ -378,7 +378,7 @@ SYMBOL_MAP = {
378
  "1HZ100V": "V100_1s",
379
  "CRASH500": "CRASH500",
380
  "CRASH1000": "CRASH1000",
381
- "stpRNG2": "STEP200", # CONFIRMED: live Deriv WS API returns "stpRNG2" (STPRNG200 does not exist)
382
  }
383
  SYMBOL_MAP_REVERSE = {v: k for k, v in SYMBOL_MAP.items()}
384
 
@@ -408,7 +408,7 @@ ASSET_REGISTRY: Dict[str, dict] = {
408
  "V100_1s": {"symbol": "1HZ100V", "base_vol": 100.0, "max_pos": 0.002},
409
  "CRASH500": {"symbol": "CRASH500", "base_vol": 50.0, "max_pos": 0.003},
410
  "CRASH1000":{"symbol": "CRASH1000", "base_vol": 100.0, "max_pos": 0.002},
411
- "STEP200": {"symbol": "stpRNG2", "base_vol": 200.0, "max_pos": 0.002}, # CONFIRMED: stpRNG2 is the live Deriv symbol
412
  }
413
 
414
  # ── Per-asset MULTUP/MULTDOWN multipliers (BROKER-VALIDATED ACCEPTABLE RANGES) ──
@@ -468,16 +468,16 @@ ASSET_ACCEPTABLE_MULTIPLIERS: Dict[str, List[int]] = {
468
  # Stop-loss as fraction of stake per asset (capped to protect $6 account)
469
  # e.g. 0.50 = close when $0.50 of the $1 stake is lost
470
  ASSET_STOP_LOSS_FRAC: Dict[str, float] = {
471
- "V25": 0.60, # slow mover β€” give it room
472
  "V30_1s": 0.55,
473
- "V50": 0.55, # FIX 2: was missing β€” added explicit entry
474
  "V50_1s": 0.55,
475
  "V75": 0.50,
476
  "V75_1s": 0.45,
477
- "JD100": 0.50, # FIX 2: was missing β€” added explicit entry
478
- "V100": 0.50, # FIX 2: was missing β€” added explicit entry
479
  "V100_1s": 0.40,
480
- "CRASH500": 0.50, # hard spike cap β€” bail at 50%
481
  "CRASH1000":0.50,
482
  "STEP200": 0.55,
483
  }
@@ -486,12 +486,12 @@ ASSET_STOP_LOSS_FRAC: Dict[str, float] = {
486
  ASSET_TAKE_PROFIT_FRAC: Dict[str, float] = {
487
  "V25": 1.00,
488
  "V30_1s": 0.90,
489
- "V50": 0.90, # FIX 3: was missing β€” added explicit entry
490
  "V50_1s": 0.90,
491
  "V75": 0.80,
492
  "V75_1s": 0.75,
493
- "JD100": 0.80, # FIX 3: was missing β€” added explicit entry
494
- "V100": 0.80, # FIX 3: was missing β€” added explicit entry
495
  "V100_1s": 0.70,
496
  "CRASH500": 0.80,
497
  "CRASH1000":0.80,
@@ -521,8 +521,8 @@ GAMMA = 0.99
521
  LAMBDA_RANK = 0.4
522
  LAMBDA_RISK = 0.3
523
  REPLAY_CAPACITY = 10_000
524
- TRAIN_BATCH = 2 # FIX 4: Lowered to 2 β€” trains after only 2 closed trades (faster warmup with 12 assets)
525
- TRAIN_EVERY_N = 2 # FIX 4: Check buffer every 2 rank cycles for faster training start
526
 
527
  # Connection
528
  WS_RECONNECT_DELAY = 5
@@ -829,15 +829,29 @@ class AssetSnapshot:
829
  self.training_steps = int(training.get("training_steps", self.training_steps))
830
 
831
  if voting:
832
- raw_signal = voting.get("dominant_signal", self.dominant_signal)
 
 
 
 
 
 
 
 
833
  self.dominant_signal = (
834
- raw_signal.upper()
835
- if isinstance(raw_signal, str)
836
- and raw_signal.upper() in {"BUY", "SELL", "NEUTRAL"}
837
  else "NEUTRAL"
838
  )
839
  self.buy_count = int(voting.get("buy_count", self.buy_count))
840
  self.sell_count = int(voting.get("sell_count", self.sell_count))
 
 
 
 
 
 
841
 
842
  self.last_updated = snapshot.get("last_updated", time.time())
843
 
@@ -847,6 +861,9 @@ class AssetSnapshot:
847
 
848
  @property
849
  def signal_confidence(self) -> float:
 
 
 
850
  if self.total_votes == 0:
851
  return 0.0
852
  return max(self.buy_count, self.sell_count) / self.total_votes
@@ -6510,7 +6527,7 @@ class PortfolioRiskManager:
6510
  if self._peak_equity <= 0:
6511
  return 0.0
6512
  raw_dd = (self._peak_equity - self._current_equity) / self._peak_equity
6513
- return min(1.0, max(0.0, raw_dd)) # FIX 5: clamp to [0,1] β€” prevents 476%+ when equity goes negative
6514
 
6515
  def _get_max_pos(self, asset_id: str) -> float:
6516
  return self.asset_registry.get(asset_id, {}).get("max_pos", 0.002)
@@ -6796,8 +6813,8 @@ class QuasarAXRVIBridge:
6796
  reward_strategy: str = "simple",
6797
  hub_ws_url: str = os.environ.get("QUASAR_HUB_URL", "ws://localhost:7860/ws/subscribe"),
6798
  enable_logging: bool = True,
6799
- checkpoint_dir: str = "./Ranker7", # FIX 6: new fresh folder β€” no restoring from Ranker6
6800
- resume: bool = False, # FIX 6: fresh start β€” do NOT resume from old checkpoint
6801
  hf_repo_id: Optional[str] = "KarlQuant/k1rl-checkpoints", # HF Dataset repo
6802
  ):
6803
  self.config = config or AssetRankerConfig()
@@ -9061,7 +9078,7 @@ class RankerCheckpointManager:
9061
 
9062
  def __init__(
9063
  self,
9064
- checkpoint_dir: str = "./Ranker7",
9065
  hf_repo_id: Optional[str] = None,
9066
  ):
9067
  self.checkpoint_dir = checkpoint_dir
@@ -10370,8 +10387,8 @@ async def run_live_trading_system(
10370
  hub_ws_url: str = "ws://localhost:7860/ws/subscribe",
10371
  enable_logging: bool = True,
10372
  shreve_config: Optional[ShreveConfig] = None,
10373
- checkpoint_dir: str = "./Ranker7", # FIX 6: new fresh folder
10374
- resume: bool = False, # FIX 6: fresh start β€” no restore
10375
  hf_repo_id: Optional[str] = "KarlQuant/k1rl-checkpoints", # HF Dataset repo
10376
  ) -> None:
10377
  config = AssetRankerConfig(
@@ -10655,7 +10672,7 @@ def test_components() -> None:
10655
  def _parse_args():
10656
  """Parse CLI args, stripping any Jupyter kernel args."""
10657
  filtered = [a for a in sys.argv[1:] if not a.startswith("-f")]
10658
- parser = argparse.ArgumentParser(description="QUASAR AXRVI Ranker v7 β€” Shreve Framework | Fresh ./Ranker7 folder")
10659
  parser.add_argument("--test", action="store_true",
10660
  help="Run component tests and exit")
10661
  parser.add_argument("--assets", nargs="+",
@@ -10684,12 +10701,12 @@ def _parse_args():
10684
  help="[S6/S8] Trade horizon Ο„ in seconds (default 60)")
10685
  parser.add_argument("--martingale-epsilon", type=float, default=0.05,
10686
  help="[S7] Gate E martingale deviation threshold (default 0.05)")
10687
- parser.add_argument("--checkpoint-dir", default="./Ranker7",
10688
- help="Directory for full-state checkpoints (default ./Ranker7 β€” fresh folder, no restore)")
10689
  parser.add_argument("--no-resume", dest="no_resume", action="store_true", default=True,
10690
- help="FIX 7: Default True β€” always start fresh from ./Ranker7 folder.")
10691
  parser.add_argument("--resume", dest="no_resume", action="store_false",
10692
- help="Restore from latest Ranker7 checkpoint (overrides --no-resume default)")
10693
  parser.add_argument("--hf-repo", default=None,
10694
  metavar="OWNER/REPO",
10695
  help="Hugging Face Dataset repo for checkpoint sync "
@@ -10746,7 +10763,7 @@ if __name__ == "__main__":
10746
  hub_ws_url = args.hub,
10747
  enable_logging = not args.no_logs,
10748
  checkpoint_dir = args.checkpoint_dir,
10749
- resume = not args.no_resume, # FIX 1: default True (always resume)
10750
  hf_repo_id = args.hf_repo or "KarlQuant/k1rl-checkpoints",
10751
  )
10752
 
 
378
  "1HZ100V": "V100_1s",
379
  "CRASH500": "CRASH500",
380
  "CRASH1000": "CRASH1000",
381
+ "stpRNG2": "STEP200", # CONFIRMED: live Deriv WS API returns "stpRNG2"
382
  }
383
  SYMBOL_MAP_REVERSE = {v: k for k, v in SYMBOL_MAP.items()}
384
 
 
408
  "V100_1s": {"symbol": "1HZ100V", "base_vol": 100.0, "max_pos": 0.002},
409
  "CRASH500": {"symbol": "CRASH500", "base_vol": 50.0, "max_pos": 0.003},
410
  "CRASH1000":{"symbol": "CRASH1000", "base_vol": 100.0, "max_pos": 0.002},
411
+ "STEP200": {"symbol": "stpRNG2", "base_vol": 200.0, "max_pos": 0.002}, # CONFIRMED live symbol
412
  }
413
 
414
  # ── Per-asset MULTUP/MULTDOWN multipliers (BROKER-VALIDATED ACCEPTABLE RANGES) ──
 
468
  # Stop-loss as fraction of stake per asset (capped to protect $6 account)
469
  # e.g. 0.50 = close when $0.50 of the $1 stake is lost
470
  ASSET_STOP_LOSS_FRAC: Dict[str, float] = {
471
+ "V25": 0.60,
472
  "V30_1s": 0.55,
473
+ "V50": 0.55,
474
  "V50_1s": 0.55,
475
  "V75": 0.50,
476
  "V75_1s": 0.45,
477
+ "JD100": 0.50,
478
+ "V100": 0.50,
479
  "V100_1s": 0.40,
480
+ "CRASH500": 0.50,
481
  "CRASH1000":0.50,
482
  "STEP200": 0.55,
483
  }
 
486
  ASSET_TAKE_PROFIT_FRAC: Dict[str, float] = {
487
  "V25": 1.00,
488
  "V30_1s": 0.90,
489
+ "V50": 0.90,
490
  "V50_1s": 0.90,
491
  "V75": 0.80,
492
  "V75_1s": 0.75,
493
+ "JD100": 0.80,
494
+ "V100": 0.80,
495
  "V100_1s": 0.70,
496
  "CRASH500": 0.80,
497
  "CRASH1000":0.80,
 
521
  LAMBDA_RANK = 0.4
522
  LAMBDA_RISK = 0.3
523
  REPLAY_CAPACITY = 10_000
524
+ TRAIN_BATCH = 2 # FIX: Lowered to 2 β€” trains after 2 closed trades
525
+ TRAIN_EVERY_N = 2 # FIX: Check every 2 rank cycles
526
 
527
  # Connection
528
  WS_RECONNECT_DELAY = 5
 
829
  self.training_steps = int(training.get("training_steps", self.training_steps))
830
 
831
  if voting:
832
+ # ── CORE FIX 6: prefer latest_signal (per-message, always fresh) ──
833
+ # dominant_signal = accumulated ALL-TIME vote majority β†’ stale.
834
+ # With 7.5K historical SELL votes, a fresh BUY is invisible.
835
+ # latest_signal = set by hub on EVERY voting message received β†’
836
+ # always reflects the engine's most recent inference output.
837
+ _raw_latest = voting.get("latest_signal", "")
838
+ _raw_dominant = voting.get("dominant_signal", self.dominant_signal)
839
+ # Use latest_signal if present and valid, else fall back to dominant
840
+ _preferred = _raw_latest if _raw_latest.upper() in {"BUY", "SELL", "NEUTRAL"} else _raw_dominant
841
  self.dominant_signal = (
842
+ _preferred.upper()
843
+ if isinstance(_preferred, str)
844
+ and _preferred.upper() in {"BUY", "SELL", "NEUTRAL"}
845
  else "NEUTRAL"
846
  )
847
  self.buy_count = int(voting.get("buy_count", self.buy_count))
848
  self.sell_count = int(voting.get("sell_count", self.sell_count))
849
+ # When using latest_signal, confidence = 1.0 (direct model output,
850
+ # not a vote ratio). Override only if we actually got latest_signal.
851
+ if _raw_latest.upper() in {"BUY", "SELL"}:
852
+ self._latest_signal_confidence = 1.0
853
+ else:
854
+ self._latest_signal_confidence = None # use vote ratio
855
 
856
  self.last_updated = snapshot.get("last_updated", time.time())
857
 
 
861
 
862
  @property
863
  def signal_confidence(self) -> float:
864
+ # ── CORE FIX 6b: use 1.0 when signal came from latest_signal ──
865
+ if hasattr(self, "_latest_signal_confidence") and self._latest_signal_confidence is not None:
866
+ return self._latest_signal_confidence
867
  if self.total_votes == 0:
868
  return 0.0
869
  return max(self.buy_count, self.sell_count) / self.total_votes
 
6527
  if self._peak_equity <= 0:
6528
  return 0.0
6529
  raw_dd = (self._peak_equity - self._current_equity) / self._peak_equity
6530
+ return min(1.0, max(0.0, raw_dd)) # FIX: clamp [0,1]
6531
 
6532
  def _get_max_pos(self, asset_id: str) -> float:
6533
  return self.asset_registry.get(asset_id, {}).get("max_pos", 0.002)
 
6813
  reward_strategy: str = "simple",
6814
  hub_ws_url: str = os.environ.get("QUASAR_HUB_URL", "ws://localhost:7860/ws/subscribe"),
6815
  enable_logging: bool = True,
6816
+ checkpoint_dir: str = "./Ranker8", # FIX: fresh folder
6817
+ resume: bool = False, # FIX: fresh start
6818
  hf_repo_id: Optional[str] = "KarlQuant/k1rl-checkpoints", # HF Dataset repo
6819
  ):
6820
  self.config = config or AssetRankerConfig()
 
9078
 
9079
  def __init__(
9080
  self,
9081
+ checkpoint_dir: str = "./Ranker8",
9082
  hf_repo_id: Optional[str] = None,
9083
  ):
9084
  self.checkpoint_dir = checkpoint_dir
 
10387
  hub_ws_url: str = "ws://localhost:7860/ws/subscribe",
10388
  enable_logging: bool = True,
10389
  shreve_config: Optional[ShreveConfig] = None,
10390
+ checkpoint_dir: str = "./Ranker8",
10391
+ resume: bool = False, # FIX: fresh start
10392
  hf_repo_id: Optional[str] = "KarlQuant/k1rl-checkpoints", # HF Dataset repo
10393
  ) -> None:
10394
  config = AssetRankerConfig(
 
10672
  def _parse_args():
10673
  """Parse CLI args, stripping any Jupyter kernel args."""
10674
  filtered = [a for a in sys.argv[1:] if not a.startswith("-f")]
10675
+ parser = argparse.ArgumentParser(description="QUASAR AXRVI Ranker v7 β€” Shreve Framework")
10676
  parser.add_argument("--test", action="store_true",
10677
  help="Run component tests and exit")
10678
  parser.add_argument("--assets", nargs="+",
 
10701
  help="[S6/S8] Trade horizon Ο„ in seconds (default 60)")
10702
  parser.add_argument("--martingale-epsilon", type=float, default=0.05,
10703
  help="[S7] Gate E martingale deviation threshold (default 0.05)")
10704
+ parser.add_argument("--checkpoint-dir", default="./Ranker8",
10705
+ help="Directory for full-state checkpoints (default ./Ranker7)")
10706
  parser.add_argument("--no-resume", dest="no_resume", action="store_true", default=True,
10707
+ help="Default True β€” always fresh start.")
10708
  parser.add_argument("--resume", dest="no_resume", action="store_false",
10709
+ help="Restore from latest Ranker7 checkpoint")
10710
  parser.add_argument("--hf-repo", default=None,
10711
  metavar="OWNER/REPO",
10712
  help="Hugging Face Dataset repo for checkpoint sync "
 
10763
  hub_ws_url = args.hub,
10764
  enable_logging = not args.no_logs,
10765
  checkpoint_dir = args.checkpoint_dir,
10766
+ resume = not args.no_resume, # default False β€” always start fresh on Ranker8
10767
  hf_repo_id = args.hf_repo or "KarlQuant/k1rl-checkpoints",
10768
  )
10769