89 lines
2.7 KiB
Python
89 lines
2.7 KiB
Python
|
|
"""
|
||
|
|
Validates the two root-cause fixes:
|
||
|
|
1. Capital no longer resets to 25k (portfolio sync removed)
|
||
|
|
2. _exec_submit_entry no longer throws NaN (entry_price added to entry dict)
|
||
|
|
|
||
|
|
Runs TWO consecutive days and verifies capital carries forward.
|
||
|
|
"""
|
||
|
|
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 prod.nautilus_actor_56day_backtest import (
|
||
|
|
run_one_day_nautilus, get_parquet_files, _safe_capital
|
||
|
|
)
|
||
|
|
|
||
|
|
files = get_parquet_files()
|
||
|
|
if len(files) < 2:
|
||
|
|
print("FAIL: Need at least 2 parquet files for validation")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
print("=" * 60)
|
||
|
|
print("CAPITAL CARRY-FORWARD VALIDATION")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
# Build vol_p60
|
||
|
|
df0 = pd.read_parquet(files[0])
|
||
|
|
btc = df0['BTCUSDT'].values
|
||
|
|
vols = []
|
||
|
|
for i in range(50, len(btc)):
|
||
|
|
seg = btc[max(0, i-50):i]
|
||
|
|
if len(seg) >= 10:
|
||
|
|
v = float(np.std(np.diff(seg) / seg[:-1]))
|
||
|
|
if v > 0 and np.isfinite(v):
|
||
|
|
vols.append(v)
|
||
|
|
vol_p60 = float(np.percentile(vols, 60)) if vols else 0.0002
|
||
|
|
print(f"vol_p60 = {vol_p60:.8f}")
|
||
|
|
|
||
|
|
assets = [c for c in df0.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'
|
||
|
|
}]
|
||
|
|
all_dates = [f.stem for f in files]
|
||
|
|
|
||
|
|
# --- Day 1 ---
|
||
|
|
d1 = files[0].stem
|
||
|
|
print(f"\n[Day 1] {d1} start_cap=$25,000.00")
|
||
|
|
r1 = run_one_day_nautilus(d1, 25000.0, vol_p60, all_dates, assets)
|
||
|
|
cap1 = r1['capital']
|
||
|
|
pnl1 = r1['pnl']
|
||
|
|
trades1 = r1['trades']
|
||
|
|
print(f" -> capital=${cap1:,.2f} pnl=${pnl1:+,.2f} trades={trades1}")
|
||
|
|
|
||
|
|
if not np.isfinite(cap1):
|
||
|
|
print("FAIL: Day 1 capital is non-finite!")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
# --- Day 2 (carried forward) ---
|
||
|
|
d2 = files[1].stem
|
||
|
|
print(f"\n[Day 2] {d2} start_cap=${cap1:,.2f}")
|
||
|
|
r2 = run_one_day_nautilus(d2, cap1, vol_p60, all_dates, assets)
|
||
|
|
cap2 = r2['capital']
|
||
|
|
pnl2 = r2['pnl']
|
||
|
|
trades2 = r2['trades']
|
||
|
|
print(f" -> capital=${cap2:,.2f} pnl=${pnl2:+,.2f} trades={trades2}")
|
||
|
|
|
||
|
|
if not np.isfinite(cap2):
|
||
|
|
print("FAIL: Day 2 capital is non-finite!")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print("RESULTS:")
|
||
|
|
print(f" Day 1 end cap : ${cap1:,.2f}")
|
||
|
|
print(f" Day 2 end cap : ${cap2:,.2f}")
|
||
|
|
print(f" Day 2 started with ${cap1:,.2f} (not $25,000)")
|
||
|
|
|
||
|
|
if abs(cap1 - 25000.0) < 0.01 and trades1 > 0:
|
||
|
|
print(" FAIL: capital still stuck at $25,000 after trades!")
|
||
|
|
elif abs(cap2 - 25000.0) < 0.01 and cap1 != 25000.0 and trades2 > 0:
|
||
|
|
print(" FAIL: Day 2 reset capital back to $25,000 (carry-forward broken)!")
|
||
|
|
else:
|
||
|
|
print(" PASS: Capital carry-forward is working correctly")
|
||
|
|
|
||
|
|
print("=" * 60)
|