@ -1343,6 +1343,81 @@ class PaperTradingEngine:
if entropy is not None and entropy > ent_thr :
return " sgov "
# Low-vol overlay: upgrade base symbol (e.g. QQQM → TQQQ) when market is calm
overlay_sym = ( risk . cash_parking_low_vol_overlay_symbol or " " ) . upper ( )
if overlay_sym and overlay_sym != sym and self . _parking_brake_cooldown_remaining < = 0 :
def _compute_hurst ( lb : int ) - > float | None :
if n < lb + 1 :
return None
rets = [ ]
for i in range ( n - lb , n ) :
if closes [ i - 1 ] > 0 :
rets . append ( ( closes [ i ] - closes [ i - 1 ] ) / closes [ i - 1 ] )
if len ( rets ) < 30 :
return None
def _rs ( series : list [ float ] ) - > float :
nn = len ( series )
mean = sum ( series ) / nn
devs = [ x - mean for x in series ]
cumdev , s = [ ] , 0.0
for d in devs :
s + = d
cumdev . append ( s )
r = max ( cumdev ) - min ( cumdev )
std = ( sum ( d * * 2 for d in devs ) / nn ) * * 0.5
return r / std if std > 0 else 0.0
window_sizes = [ w for w in [ 8 , 12 , 16 , 24 , 32 ] if w < = len ( rets ) / / 2 ]
if len ( window_sizes ) < 2 :
return None
log_n , log_rs = [ ] , [ ]
for w in window_sizes :
rs_vals = [ _rs ( rets [ s : s + w ] ) for s in range ( 0 , len ( rets ) - w + 1 , w ) if len ( rets [ s : s + w ] ) == w ]
if rs_vals :
avg_rs = sum ( rs_vals ) / len ( rs_vals )
if avg_rs > 0 :
log_n . append ( math . log ( w ) )
log_rs . append ( math . log ( avg_rs ) )
if len ( log_n ) < 2 :
return None
nn2 = len ( log_n )
xm , ym = sum ( log_n ) / nn2 , sum ( log_rs ) / nn2
num = sum ( ( log_n [ i ] - xm ) * ( log_rs [ i ] - ym ) for i in range ( nn2 ) )
den = sum ( ( log_n [ i ] - xm ) * * 2 for i in range ( nn2 ) )
return num / den if den > 0 else 0.5
overlay_ok = True
overlay_vol_thr = risk . cash_parking_low_vol_overlay_vol_threshold
if overlay_vol_thr > 0 and ( vol is None or vol > = overlay_vol_thr ) :
overlay_ok = False
if overlay_ok :
temp_max = risk . cash_parking_low_vol_overlay_temperature_max
if temp_max > 0 :
if vol_15 is None or vol_50 is None or vol_50 < = 0 or ( vol_15 / vol_50 ) > temp_max :
overlay_ok = False
if overlay_ok :
entropy_max = risk . cash_parking_low_vol_overlay_entropy_max
if entropy_max > 0 :
ov_entropy = _compute_entropy ( risk . cash_parking_entropy_lookback )
if ov_entropy is None or ov_entropy > entropy_max :
overlay_ok = False
if overlay_ok :
hurst_min = risk . cash_parking_low_vol_overlay_hurst_min
if hurst_min > 0 :
hurst = _compute_hurst ( 60 )
if hurst is None or hurst < hurst_min :
overlay_ok = False
if overlay_ok :
logger . info ( " parking_overlay_selected " , symbol = overlay_sym )
return overlay_sym . lower ( )
return actual_sym
def _parking_check_shock_brake ( self , today : dt . date ) - > bool :