import sys, time from pathlib import Path import numpy as np import pandas as pd sys.path.insert(0, str(Path(__file__).parent)) from nautilus_dolphin.nautilus.alpha_orchestrator import NDAlphaEngine from nautilus_dolphin.nautilus.adaptive_circuit_breaker import AdaptiveCircuitBreaker from nautilus_dolphin.nautilus.ob_features import OBFeatureEngine from nautilus_dolphin.nautilus.ob_provider import MockOBProvider VBT_DIR = Path(r"C:\Users\Lenovo\Documents\- DOLPHIN NG HD HCM TSF Predict\vbt_cache") META_COLS = {'timestamp', 'scan_number', 'v50_lambda_max_velocity', 'v150_lambda_max_velocity', 'v300_lambda_max_velocity', 'v750_lambda_max_velocity', 'vel_div', 'instability_50', 'instability_150'} # Load parquet files correctly parquet_files = sorted(VBT_DIR.glob("*.parquet")) parquet_files = [p for p in parquet_files if 'catalog' not in str(p)] print("Loading data...") all_vols = [] for pf in parquet_files[:2]: df = pd.read_parquet(pf) if 'BTCUSDT' not in df.columns: continue pr = df['BTCUSDT'].values for i in range(60, len(pr)): seg = pr[max(0,i-50):i] if len(seg)<10: continue v = float(np.std(np.diff(seg)/seg[:-1])) if v > 0: all_vols.append(v) vol_p60 = float(np.percentile(all_vols, 60)) pq_data = {} for pf in parquet_files: df = pd.read_parquet(pf) ac = [c for c in df.columns if c not in META_COLS] bp = df['BTCUSDT'].values if 'BTCUSDT' in df.columns else None dv = np.full(len(df), np.nan) if bp is not None: for i in range(50, len(bp)): seg = bp[max(0,i-50):i] if len(seg)<10: continue dv[i] = float(np.std(np.diff(seg)/seg[:-1])) pq_data[pf.stem] = (df, ac, dv) # Initialize systems acb = AdaptiveCircuitBreaker() acb.preload_w750([pf.stem for pf in parquet_files]) ENGINE_KWARGS = dict( initial_capital=25000.0, vel_div_threshold=-0.02, vel_div_extreme=-0.05, min_leverage=0.5, max_leverage=5.0, leverage_convexity=3.0, fraction=0.20, fixed_tp_pct=0.0099, stop_pct=1.0, max_hold_bars=120, use_direction_confirm=True, dc_lookback_bars=7, dc_min_magnitude_bps=0.75, dc_skip_contradicts=True, dc_leverage_boost=1.0, dc_leverage_reduce=0.5, use_asset_selection=True, min_irp_alignment=0.45, use_sp_fees=True, use_sp_slippage=True, use_ob_edge=True, ob_edge_bps=5.0, ob_confirm_rate=0.40, lookback=100, use_alpha_layers=True, use_dynamic_leverage=True, seed=42, ) def run_test(name, ob_engine=None): engine = NDAlphaEngine(**ENGINE_KWARGS) if ob_engine: engine.set_ob_engine(ob_engine) bar_idx = 0; peak_cap = engine.capital; max_dd = 0.0 for pf in parquet_files: ds = pf.stem # ACB logic acb_info = acb.get_dynamic_boost_for_date(ds, ob_engine=ob_engine) base_boost = acb_info['boost'] # This is now exactly (1.0 - cut) beta = acb_info['beta'] df, acols, dvol = pq_data[ds] ph = {} for ri in range(len(df)): row = df.iloc[ri]; vd = row.get("vel_div") if vd is None or not np.isfinite(vd): bar_idx+=1; continue prices = {} for ac in acols: p = row[ac] if p and p > 0 and np.isfinite(p): prices[ac] = float(p) if ac not in ph: ph[ac] = [] ph[ac].append(float(p)) if len(ph[ac]) > 500: ph[ac] = ph[ac][-200:] if not prices: bar_idx+=1; continue vrok = False if ri < 100 else (np.isfinite(dvol[ri]) and dvol[ri] > vol_p60) # 3-scale meta-boost: ACB boost * (1 + beta * strength^3) if beta > 0 and base_boost > 1.0: ss = 0.0 if vd < -0.02: raw = (-0.02 - float(vd)) / (-0.02 - -0.05) ss = min(1.0, max(0.0, raw)) ** 3.0 engine.regime_size_mult = base_boost * (1.0 + beta * ss) else: engine.regime_size_mult = base_boost engine.process_bar(bar_idx=bar_idx, vel_div=float(vd), prices=prices, vol_regime_ok=vrok, price_histories=ph) # (no fraction reset needed) bar_idx += 1 peak_cap = max(peak_cap, engine.capital) dd = (peak_cap - engine.capital) / peak_cap * 100 max_dd = max(max_dd, dd) trades = engine.trade_history w = [t for t in trades if t.pnl_absolute > 0] l = [t for t in trades if t.pnl_absolute <= 0] gw = sum(t.pnl_absolute for t in w) if w else 0 gl = abs(sum(t.pnl_absolute for t in l)) if l else 0 roi = (engine.capital - 25000) / 25000 * 100 pf_val = gw / gl if gl > 0 else 999 wr = len(w) / len(trades) * 100 if trades else 0 returns = [(t.pnl_absolute / (25000+sum(x.pnl_absolute for x in trades[:i]))) for i, t in enumerate(trades)] if not returns: returns = [0] mc_med_cagr, mc_tail_cagr, mc_p40, mc_med_dd = compute_mc_cagr(returns) print(f"\n{name}") print(f" ROI: {roi:+.2f}%") print(f" MaxDD (Emp): {max_dd:.2f}%") print(f" Trades: {len(trades)}") print(f" Win Rate: {wr:.1f}%") print(f" Prof Factor: {pf_val:.3f}") print(f" MC Med CAGR: {mc_med_cagr:+.1f}%") print(f" MC Med DD: {mc_med_dd:.1f}%") print(f" MC P(>40DD): {mc_p40:.1f}%") # Helper for Monte Carlo def compute_mc_cagr(returns, periods=252, n_simulations=1000): np.random.seed(42) dr = np.array(returns) if len(dr) == 0: return 0,0,0,0 # Resample daily (simulated by block since returns are per trade, we approximate) sr = np.random.choice(dr, size=(n_simulations, periods), replace=True) eq = np.cumprod(1.0 + sr, axis=1) cagrs = (eq[:, -1] - 1.0) * 100 med_cagr = np.median(cagrs) tail_cagr = np.percentile(cagrs, 5) max_dds = np.zeros(n_simulations) for i in range(n_simulations): curve = eq[i] peaks = np.maximum.accumulate(curve) dds = (peaks - curve) / peaks max_dds[i] = np.max(dds) p40 = np.mean(max_dds >= 0.40) * 100 mdd = np.median(max_dds) * 100 return med_cagr, tail_cagr, p40, mdd # 1. Test Baseline run_test("A. ACB v4 Baseline (No OB, Pure ACB)") # 2. Test Full Production (ACB Cut + OB Engine Hard Skip) mock = MockOBProvider(imbalance_bias=-0.09, depth_scale=1.0, assets=["BTCUSDT", "ETHUSDT", "BNBUSDT", "SOLUSDT"], imbalance_biases={"BNBUSDT": 0.20, "SOLUSDT": 0.20}) ob_engine = OBFeatureEngine(mock) ob_engine.preload_date("mock", mock.get_assets()) run_test("B. Production Stack (ACB + OB Hard-Skip, 5.0x)", ob_engine) from nautilus_dolphin.nautilus.esf_alpha_orchestrator import NDAlphaEngine as ThrottledEngine import json def run_throttled_test(name, ob_engine=None): engine = ThrottledEngine(**ENGINE_KWARGS) if ob_engine: engine.set_ob_engine(ob_engine) bar_idx = 0; peak_cap = engine.capital; max_dd = 0.0 for pf in parquet_files: ds = pf.stem acb_info = acb.get_dynamic_boost_for_date(ds, ob_engine=ob_engine) base_boost = acb_info['boost'] beta = acb_info['beta'] eso_path = VBT_DIR / f"ESOTERIC_data_{ds}.json" eso = {} if eso_path.exists(): with open(eso_path, 'r') as f: eso = json.load(f) hazard = 0.0 dow = eso.get('day_of_week', -1) if dow == 1: hazard = 1.0 elif dow in [0, 2]: hazard = 0.5 if eso.get('moon_illumination', 0.5) <= 0.05: hazard = 1.0 engine.set_esoteric_hazard_multiplier(hazard) # Enable 6.0x dynamic engine.set_mc_forewarner_status(True) df, acols, dvol = pq_data[ds] ph = {} for ri in range(len(df)): row = df.iloc[ri]; vd = row.get("vel_div") if vd is None or not np.isfinite(vd): bar_idx+=1; continue prices = {} for ac in acols: p = row[ac] if p and p > 0 and np.isfinite(p): prices[ac] = float(p) if ac not in ph: ph[ac] = [] ph[ac].append(float(p)) if len(ph[ac]) > 500: ph[ac] = ph[ac][-200:] if not prices: bar_idx+=1; continue vrok = False if ri < 100 else (np.isfinite(dvol[ri]) and dvol[ri] > vol_p60) if beta > 0 and base_boost > 1.0: ss = 0.0 if vd < -0.02: raw = (-0.02 - float(vd)) / (-0.02 - -0.05) ss = min(1.0, max(0.0, raw)) ** 3.0 engine.regime_size_mult = base_boost * (1.0 + beta * ss) else: engine.regime_size_mult = base_boost engine.process_bar(bar_idx=bar_idx, vel_div=float(vd), prices=prices, vol_regime_ok=vrok, price_histories=ph) bar_idx += 1 peak_cap = max(peak_cap, engine.capital) dd = (peak_cap - engine.capital) / peak_cap * 100 max_dd = max(max_dd, dd) trades = engine.trade_history w = [t for t in trades if t.pnl_absolute > 0] l = [t for t in trades if t.pnl_absolute <= 0] gw = sum(t.pnl_absolute for t in w) if w else 0 gl = abs(sum(t.pnl_absolute for t in l)) if l else 0 roi = (engine.capital - 25000) / 25000 * 100 pf_val = gw / gl if gl > 0 else 999 wr = len(w) / len(trades) * 100 if trades else 0 returns = [(t.pnl_absolute / (25000+sum(x.pnl_absolute for x in trades[:i]))) for i, t in enumerate(trades)] if not returns: returns = [0] mc_med_cagr, mc_tail_cagr, mc_p40, mc_med_dd = compute_mc_cagr(returns) print(f"\n{name}") print(f" ROI: {roi:+.2f}%") print(f" MaxDD (Emp): {max_dd:.2f}%") print(f" Trades: {len(trades)}") print(f" Win Rate: {wr:.1f}%") print(f" Prof Factor: {pf_val:.3f}") print(f" MC Med CAGR: {mc_med_cagr:+.1f}%") print(f" MC Med DD: {mc_med_dd:.1f}%") print(f" MC P(>40DD): {mc_p40:.1f}%") run_throttled_test("C. Ultimate Stack (Production OB + Dynamic 5-6x + EsoF Taper)", ob_engine)