diff --git a/nautilus_dolphin/nautilus_dolphin/nautilus/alpha_asset_selector.py b/nautilus_dolphin/nautilus_dolphin/nautilus/alpha_asset_selector.py index 716ca1f..e5f134c 100755 --- a/nautilus_dolphin/nautilus_dolphin/nautilus/alpha_asset_selector.py +++ b/nautilus_dolphin/nautilus_dolphin/nautilus/alpha_asset_selector.py @@ -10,7 +10,7 @@ import math import numpy as np from numba import njit from dataclasses import dataclass -from typing import Dict, List, Optional, Tuple +from typing import Dict, List, Optional, Set, Tuple # ── Constants (matching dolphin_vbt_real.py lines 104-115) ──────────────────── @@ -195,9 +195,13 @@ class AlphaAssetSelector: self, lookback_horizon: int = IRP_LOOKBACK, ars_weights: Optional[List[float]] = None, + asset_bucket_ban_set: Optional[Set[int]] = None, + asset_bucket_assignments: Optional[Dict[str, int]] = None, ): self.H = lookback_horizon self.weights = ars_weights or ARS_WEIGHTS + self.asset_bucket_ban_set = asset_bucket_ban_set + self.asset_bucket_assignments = asset_bucket_assignments or {} def rank_assets( self, @@ -236,6 +240,15 @@ class AlphaAssetSelector: best_eff = valid[ri, 4] asset = asset_names[asset_idx] + + # GREEN-only bucket-ban filter. BLUE passes None → no-op. + # Skips banned-bucket assets so the next-ranked asset takes the slot + # (preserves capital; a sizer 0× would waste the slot). + if self.asset_bucket_ban_set: + bkt = self.asset_bucket_assignments.get(asset) + if bkt is not None and bkt in self.asset_bucket_ban_set: + continue + action = "SHORT" if trade_dir == -1 else "LONG" orientation = "DIRECT" if trade_dir == regime_direction else "INVERSE"