Files
DOLPHIN/prod/diag_acb_actor.py

144 lines
5.7 KiB
Python
Raw Normal View History

"""
ACB + actor-style loop diagnostic.
Static vol_ok (T=2155 base) + patched ACB eigenvalues from ng6_data.
Measures ROI improvement from partial ACB data (11/56 dates).
"""
import sys, math, pathlib
import numpy as np
import pandas as pd
sys.path.insert(0, '/mnt/dolphinng5_predict')
sys.path.insert(0, '/mnt/dolphinng5_predict/nautilus_dolphin')
print("Importing...", flush=True)
from nautilus_dolphin.nautilus.proxy_boost_engine import create_boost_engine
from nautilus_dolphin.nautilus.adaptive_circuit_breaker import ACBConfig, AdaptiveCircuitBreaker
print("Import done.", flush=True)
PARQUET_DIR = pathlib.Path('/mnt/dolphinng5_predict/vbt_cache')
EIGENVALUES_PATH = pathlib.Path('/mnt/dolphinng6_data/eigenvalues')
VOL_P60_INWINDOW = 0.00009868
ENG_KWARGS = dict(
max_hold_bars=120, min_irp_alignment=0.45, max_leverage=8.0,
vel_div_threshold=-0.02, vel_div_extreme=-0.05,
min_leverage=0.5, leverage_convexity=3.0,
fraction=0.20, fixed_tp_pct=0.0095, stop_pct=1.0,
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, use_sp_fees=True, use_sp_slippage=True,
sp_maker_entry_rate=0.62, sp_maker_exit_rate=0.50,
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 make_engine(cap=25000.0, with_acb=False, all_dates=None):
eng = create_boost_engine(mode='d_liq', initial_capital=cap, **ENG_KWARGS)
eng.set_esoteric_hazard_multiplier(0.0)
if with_acb:
acb = AdaptiveCircuitBreaker()
acb.config.EIGENVALUES_PATH = EIGENVALUES_PATH # patch instance config, not class
if all_dates:
print(f" Preloading w750 for {len(all_dates)} dates...", flush=True)
acb.preload_w750(all_dates)
n_loaded = sum(1 for v in acb._w750_vel_cache.values() if v != 0.0)
print(f" w750 loaded: {n_loaded}/{len(all_dates)}, threshold={acb._w750_threshold:.6f}", flush=True)
eng.set_acb(acb)
return eng
def compute_vol_ok(df):
btc_f = df['BTCUSDT'].values.astype('float64')
n = len(btc_f)
vol_ok = np.zeros(n, dtype=bool)
for j in range(50, n):
seg = btc_f[max(0, j-50):j]
diffs = np.diff(seg)
denom = seg[:-1]
if np.any(denom == 0):
continue
v = float(np.std(diffs / denom))
if math.isfinite(v) and v > 0:
vol_ok[j] = v > VOL_P60_INWINDOW
return vol_ok
def run_day(df, date_str, eng, nan_fix=True):
eng.begin_day(date_str)
data_arr = df.values
cols = df.columns.tolist()
vd_idx = cols.index('vel_div') if 'vel_div' in cols else -1
v50_idx = cols.index('v50_lambda_max_velocity') if 'v50_lambda_max_velocity' in cols else -1
v750_idx = cols.index('v750_lambda_max_velocity') if 'v750_lambda_max_velocity' in cols else -1
i50_idx = cols.index('instability_50') if 'instability_50' in cols else -1
usdt_idxs = [(c, cols.index(c)) for c in cols if c.endswith('USDT')]
vol_ok = compute_vol_ok(df)
trades = 0
for i in range(len(df)):
row_vals = data_arr[i]
vd_raw = float(row_vals[vd_idx]) if vd_idx != -1 else float('nan')
if not math.isfinite(vd_raw):
if nan_fix:
eng._global_bar_idx += 1
continue
v750 = float(row_vals[v750_idx]) if v750_idx != -1 and math.isfinite(float(row_vals[v750_idx])) else 0.0
inst50 = float(row_vals[i50_idx]) if i50_idx != -1 and math.isfinite(float(row_vals[i50_idx])) else 0.0
v50 = float(row_vals[v50_idx]) if v50_idx != -1 and math.isfinite(float(row_vals[v50_idx])) else 0.0
prices = {sym: float(row_vals[ci]) for sym, ci in usdt_idxs
if math.isfinite(float(row_vals[ci])) and float(row_vals[ci]) > 0}
prev_pos = eng.position
if hasattr(eng, 'pre_bar_proxy_update'):
eng.pre_bar_proxy_update(inst50, v750)
eng.step_bar(
bar_idx=i, vel_div=vd_raw, prices=prices,
v50_vel=v50, v750_vel=v750,
vol_regime_ok=bool(vol_ok[i]),
)
if prev_pos is not None and eng.position is None:
trades += 1
eng.end_day()
return trades
def main():
files = sorted(PARQUET_DIR.glob('*.parquet'))
all_dates = [pf.stem for pf in files]
print(f"Days: {len(files)}", flush=True)
# Check available eigenvalue dates
have_eigen = [d for d in all_dates if (EIGENVALUES_PATH / d).exists()]
print(f"Eigenvalue dates: {len(have_eigen)}/56: {have_eigen}", flush=True)
# Baseline: no ACB (should reproduce T=2155, ROI=90.23%)
print("\nBuilding BASELINE engine (no ACB)...", flush=True)
base_eng = make_engine(with_acb=False)
# ACB engine: patched path
print("\nBuilding ACB engine (ng6_data eigenvalues)...", flush=True)
acb_eng = make_engine(with_acb=True, all_dates=all_dates)
base_T = acb_T = 0
for pf in files:
date_str = pf.stem
df = pd.read_parquet(pf)
tb = run_day(df, date_str, base_eng, nan_fix=True)
ta = run_day(df, date_str, acb_eng, nan_fix=True)
base_T += tb
acb_T += ta
boost_flag = '*' if date_str in have_eigen else ' '
print(f"{date_str}{boost_flag}: BASE+{tb:3d}(cum={base_T:4d} ${base_eng.capital:8.0f}) "
f"ACB+{ta:3d}(cum={acb_T:4d} ${acb_eng.capital:8.0f})", flush=True)
ic = 25000.0
print(f"\nBASELINE: T={base_T}, cap=${base_eng.capital:.2f}, ROI={100*(base_eng.capital/ic-1):.2f}%", flush=True)
print(f"ACB: T={acb_T}, cap=${acb_eng.capital:.2f}, ROI={100*(acb_eng.capital/ic-1):.2f}%", flush=True)
print(f"\nGold target: T=2155, ROI=+189.48%", flush=True)
if __name__ == '__main__':
main()