Files
DOLPHIN/nautilus_dolphin/test_5s_replay_parity.py

136 lines
4.7 KiB
Python
Raw Normal View History

import sys
import time
from pathlib import Path
from datetime import datetime, timezone
import numpy as np
import pandas as pd
# Ensure we can import from the project root
sys.path.insert(0, str(Path(__file__).parent))
# Import Dolphin components
from nautilus_dolphin.nautilus.esf_alpha_orchestrator import NDAlphaEngine
# Mock configuration
CONFIG = {
'engine': {
'initial_capital': 25000.0,
'vel_div_threshold': -0.02,
'vel_div_extreme': -0.05,
'max_leverage': 5.0,
'use_alpha_layers': True,
'seed': 42
},
'live_mode': False,
'direction': 'short_only'
}
def test_parity():
print("=== DOLPHIN-NAUTILUS PARITY TEST ===")
# 1. Setup Data (load one sample day)
vbt_dir = Path(r"C:\Users\Lenovo\Documents\- DOLPHIN NG HD HCM TSF Predict\vbt_cache")
pq_files = sorted(vbt_dir.glob("*.parquet"))
if not pq_files:
print("Error: No parquet files found in vbt_cache")
return
sample_file = pq_files[0]
date_str = sample_file.stem
print(f"Testing for date: {date_str} using {sample_file.name}")
df = pd.read_parquet(sample_file)
asset_columns = [c for c in df.columns if c not in {
'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'
}]
# Pre-calculate vol_ok (p60 threshold from dynamic_beta_validate)
vol_p60 = 0.000099 # Hardcoded champion p60
bp = df['BTCUSDT'].values if 'BTCUSDT' in df.columns else None
dvol = 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:
dvol[i] = float(np.std(np.diff(seg)/seg[:-1]))
vol_ok_arr = np.where(np.isfinite(dvol), dvol > vol_p60, False)
# 2. Path A: Legacy Batch (NDAlphaEngine.process_day)
print("\nRunning Path A: Legacy Batch logic...")
engine_a = NDAlphaEngine(**CONFIG['engine'])
engine_a.set_acb(None)
batch_stats = engine_a.process_day(
date_str=date_str,
df=df,
asset_columns=asset_columns,
vol_regime_ok=vol_ok_arr,
direction=-1
)
print(f" Batch Result: PnL={batch_stats['pnl']:+.4f} Trades={batch_stats['trades']} Capital={batch_stats['capital']:.2f}")
# 3. Path B: Modern Incremental (Direct NDAlphaEngine methods)
print("\nRunning Path B: Modern Incremental logic (direct methods)...")
engine_b = NDAlphaEngine(**CONFIG['engine'])
engine_b.set_acb(None)
# Orchestrate calls manually to match DolphinActor logic
engine_b.begin_day(date_str, posture='APEX', direction=-1)
for ri in range(len(df)):
row = df.iloc[ri]
vd = row.get('vel_div')
if vd is None or not np.isfinite(float(vd)):
engine_b._global_bar_idx += 1 # MUST increment to maintain parity with process_day logic
continue
v50_raw = row.get('v50_lambda_max_velocity')
v750_raw = row.get('v750_lambda_max_velocity')
v50_val = float(v50_raw) if (v50_raw is not None and np.isfinite(float(v50_raw))) else 0.0
v750_val = float(v750_raw) if (v750_raw is not None and np.isfinite(float(v750_raw))) else 0.0
prices = {}
for ac in asset_columns:
p = row.get(ac)
if p is not None and p > 0 and np.isfinite(p):
prices[ac] = float(p)
if not prices:
engine_b._global_bar_idx += 1 # MUST increment to maintain parity
continue
vol_ok = bool(vol_ok_arr[ri])
# Step the bar (internally increments _global_bar_idx)
engine_b.step_bar(
bar_idx=ri,
vel_div=float(vd),
prices=prices,
vol_regime_ok=vol_ok,
v50_vel=v50_val,
v750_vel=v750_val
)
incremental_stats = engine_b.end_day()
print(f" Incremental Result: PnL={incremental_stats['pnl']:+.4f} Trades={incremental_stats['trades']} Capital={incremental_stats['capital']:.2f}")
# 4. Parity Check
pnl_diff = abs(batch_stats['pnl'] - incremental_stats['pnl'])
trade_diff = abs(batch_stats['trades'] - incremental_stats['trades'])
print("\n=== PARITY ANALYSIS ===")
print(f" PnL Difference: {pnl_diff:.8f}")
print(f" Trade Difference: {trade_diff}")
success = pnl_diff < 1e-6 and trade_diff == 0
if success:
print("\nSUCCESS: Batch and Incremental logic paths are identical.")
else:
print("\nFAILURE: Logic divergence detected.")
sys.exit(1)
if __name__ == "__main__":
test_parity()