Files
DOLPHIN/prod/test_engine_capital_direct.py

93 lines
3.7 KiB
Python
Raw Normal View History

"""
Direct engine test - bypasses Nautilus completely.
Runs NDAlphaEngine (D_LIQ_GOLD) on Day 1 parquet and prints capital.
Should take ~5 seconds. If capital moves from 25000, the engine is fine.
If capital stays at 25000, reset() is being called somewhere wrong.
"""
import sys
from pathlib import Path
import numpy as np
import pandas as pd
sys.path.insert(0, str(Path(__file__).parent.parent))
sys.path.insert(0, str(Path(__file__).parent.parent / 'nautilus_dolphin'))
from nautilus_dolphin.nautilus.proxy_boost_engine import create_boost_engine
VBT_DIR = Path(__file__).parent.parent / 'vbt_cache'
files = sorted(VBT_DIR.glob('*.parquet'))
files = [f for f in files if 'catalog' not in str(f)]
assert files, f"No parquets in {VBT_DIR}"
df = pd.read_parquet(files[0])
print(f"Day: {files[0].stem} rows={len(df)}")
asset_cols = [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'
}]
engine = create_boost_engine(mode='d_liq', initial_capital=25000.0, seed=42)
# Build vol mask identical to _run_replay_day
btc = df['BTCUSDT'].values if 'BTCUSDT' in df.columns else None
vol_ok = np.zeros(len(df), dtype=bool)
if btc is not None:
for i in range(50, len(btc)):
seg = btc[max(0,i-50):i]
if len(seg) >= 10 and all(seg > 0):
v = float(np.std(np.diff(seg)/seg[:-1]))
if np.isfinite(v):
vol_ok[i] = True # just mark computable; gate uses percentile
vol_p60 = float(np.percentile([float(np.std(np.diff(btc[max(0,i-50):i])/btc[max(0,i-50):i][:-1]))
for i in range(50, len(btc))
if len(btc[max(0,i-50):i])>=10 and all(btc[max(0,i-50):i]>0)
and np.isfinite(float(np.std(np.diff(btc[max(0,i-50):i])/btc[max(0,i-50):i][:-1])))], 60)) if btc is not None else 0.0002
dvol_arr = np.full(len(df), np.nan)
if btc is not None:
for i in range(50, len(btc)):
seg = btc[max(0,i-50):i]
if len(seg)>=10 and (seg>0).all():
dvol_arr[i] = float(np.std(np.diff(seg)/seg[:-1]))
vol_ok_mask = np.where(np.isfinite(dvol_arr), dvol_arr > vol_p60, False)
engine.begin_day(files[0].stem)
trades_count = 0
for i in range(len(df)):
row = df.iloc[i]
vd = row.get('vel_div', 0.0)
if vd is None or not np.isfinite(float(vd)):
continue
prices = {ac: float(row[ac]) for ac in asset_cols
if ac in row and row[ac] is not None and float(row[ac]) > 0 and np.isfinite(float(row[ac]))}
if not prices:
continue
vrok = (i >= 100) and bool(vol_ok_mask[i])
v50 = float(row.get('v50_lambda_max_velocity', 0.0) or 0.0)
v750 = float(row.get('v750_lambda_max_velocity', 0.0) or 0.0)
result = engine.step_bar(bar_idx=i, vel_div=float(vd), prices=prices,
vol_regime_ok=vrok, v50_vel=v50, v750_vel=v750)
if result.get('entry'):
trades_count += 1
day_result = engine.end_day()
capital_end = engine.capital
trades_end = len(engine.trade_history)
print(f"vol_p60 = {vol_p60:.8f}")
print(f"capital_start = $25,000.00")
print(f"capital_end = ${capital_end:,.2f}")
print(f"pnl = ${capital_end - 25000.0:+,.2f}")
print(f"trades_entered = {trades_count}")
print(f"trades_closed = {trades_end}")
if capital_end == 25000.0:
if trades_end == 0:
print("INFO: No trades closed yet (open position or vol gate blocked all entries)")
else:
print("WARN: Capital unchanged despite trades — check fee model and P&L calc")
else:
print("PASS: Capital moved correctly — engine P&L is working")