feat: advanced microstructure modules — HLP, Hawkes, Whipsaw, Term Structure, Liq Waterfall, Spoof Detector

6 new modules with 46 new tests (230 total):

#21 HLP Vault Monitor (live/monitors/hlp_vault.py):
  Tracks Hyperliquid's native protocol market maker at address
  0xfefefe... Queries clearinghouseState + metaAndAssetCtxs.
  - Delta exposure per asset (notional + PnL)
  - Overextension detection (notional exceeds  M threshold)
  - Rebalancing signals: fade_short when HLP too short,
    fade_long when HLP too long (front-run forced rebalancing)
  - Toxicity score: HLP losing money = absorbing informed flow
  - Historical delta tracking

#29 Hawkes Processes (microstructure/hawkes.py):
  Multivariate Hawkes calibrator for limit order book dynamics.
  - MLE calibration via SGD gradient descent on log-likelihood
  - Branching ratio enforcement (alpha/beta < 0.99 for stationarity)
  - Intensity computation λ_i(t) with cross-excitation
  - Activity forecasting (expected event count in horizon)
  - Synthetic event generator (Ogata thinning)
  - Pure functions: hawkes_intensity, hawkes_log_likelihood,
    generate_hawkes_events

#23 Funding Whipsaw Trader (live/strategies/funding_whipsaw.py):
  Premium index decay trading in final 60s of funding epoch.
  - Detects deterministic convergence of premium→0 at settlement
  - Time-scaled position sizing (larger closer to settlement)
  - Auto-close after funding epoch completes
  - Confidence scoring based on premium magnitude

#32 Term Structure Monitor (live/monitors/term_structure.py):
  Perp/quarterly/bi-quarterly futures basis curve trading.
  - Quarterly-perp basis with z-score anomaly detection
  - BiQ-quarterly curve steepness monitoring
  - Fair quarterly price via interest rate parity + funding carry
  - Calendar spread signals: buy_basis, sell_basis,
    curve_steepener, curve_flattener

#24 Liquidation Waterfall (live/monitors/liq_waterfall.py):
  Cross-margin liquidation order prediction.
  - Margin ratio tracking (equity / maintenance margin)
  - Danger/critical level classification
  - Asset liquidation priority: maintenance / book_liquidity ratio
    (least liquid asset relative to margin = dumped first)
  - Strategy output: widen_spreads on target, tighten on rest

#31 Spoof Detector (microstructure/spoof_detector.py):
  Adversarial ML-style spoofing pattern recognition.
  - Rule 1: Large order far from mid, cancelled immediately
  - Rule 2: Cancel right before trade approaches price level
  - Rule 3: Oversized order with no fill within short lifetime
  - Spoof probability (rolling window ratio)
  - Cancel-to-fill ratio monitoring
This commit is contained in:
ramseshk
2026-08-07 17:52:20 +08:00
parent 31c1fe7fbe
commit 5304534e38
11 changed files with 1892 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
"""
Tests for live/strategies/funding_whipsaw.py — premium index decay trading.
"""
from unittest.mock import patch, MagicMock
from live.strategies.funding_whipsaw import FundingWhipsawTrader
class TestFundingWhipsaw:
def test_initial_no_signal_outside_window(self):
"""With default 60s entry window and >60s to funding, no signal."""
trader = FundingWhipsawTrader()
trader.update(mark_px=64500, oracle_px=64480)
with patch.object(trader, 'seconds_to_funding', return_value=300.0):
s = trader.signal()
assert s["action"] == "none"
assert s["reason"] == "outside_entry_window"
def test_enter_long_on_negative_premium(self):
trader = FundingWhipsawTrader(min_premium_bps=0.5)
trader.update(mark_px=64400, oracle_px=64500) # negative premium: -1.55 bps
with patch.object(trader, 'seconds_to_funding', return_value=30.0):
s = trader.signal()
assert s["action"] == "enter_long"
assert s["side"] == "buy"
assert s["confidence"] > 0
assert s["size"] > 0
def test_enter_short_on_positive_premium(self):
trader = FundingWhipsawTrader(min_premium_bps=0.5)
trader.update(mark_px=64600, oracle_px=64500) # positive premium: +1.55 bps
with patch.object(trader, 'seconds_to_funding', return_value=30.0):
s = trader.signal()
assert s["action"] == "enter_short"
assert s["side"] == "sell"
assert s["confidence"] > 0
def test_no_signal_on_small_premium(self):
trader = FundingWhipsawTrader(min_premium_bps=5.0)
trader.update(mark_px=64501, oracle_px=64500) # tiny premium: 0.015 bps
with patch.object(trader, 'seconds_to_funding', return_value=30.0):
s = trader.signal()
assert s["action"] == "none"
assert s["reason"] == "premium_too_small"
def test_close_after_funding(self):
"""After entering, close when funding settles."""
trader = FundingWhipsawTrader()
trader.update(mark_px=64600, oracle_px=64500)
with patch.object(trader, 'seconds_to_funding', return_value=30.0):
s = trader.signal()
assert s["action"].startswith("enter")
# Now funding just happened
with patch.object(trader, 'seconds_to_funding', return_value=8*3600 - 2.0):
with patch.object(trader, 'seconds_since_funding', return_value=2.0):
s = trader.signal()
assert s["action"] == "close"
def test_hold_after_entry(self):
trader = FundingWhipsawTrader()
trader.update(mark_px=64600, oracle_px=64500)
with patch.object(trader, 'seconds_to_funding', return_value=30.0):
trader.signal() # enter
# Next tick, still before funding
with patch.object(trader, 'seconds_to_funding', return_value=25.0):
s = trader.signal()
assert s["action"] == "hold"
def test_larger_position_with_more_premium(self):
trader = FundingWhipsawTrader(min_premium_bps=0.5, max_size=0.001)
trader.update(mark_px=65100, oracle_px=64500) # large premium
with patch.object(trader, 'seconds_to_funding', return_value=30.0):
s = trader.signal()
assert s["confidence"] > 0.5 # high confidence
assert s["size"] > 0
def test_seconds_to_funding_returns_positive(self):
trader = FundingWhipsawTrader()
secs = trader.seconds_to_funding()
assert secs > 0
assert secs <= 8 * 3600 # Max 8 hours
def test_signal_includes_premium_info(self):
trader = FundingWhipsawTrader()
trader.update(mark_px=64600, oracle_px=64500)
with patch.object(trader, 'seconds_to_funding', return_value=45.0):
s = trader.signal()
assert "premium_bps" in s
assert "seconds_to_funding" in s
assert "confidence" in s
assert s["premium_bps"] > 0