Fee optimization: per-strategy maker/taker model + signal strength filter + 9 backtests

This commit is contained in:
ramseshk
2026-08-04 06:12:35 +00:00
parent e2b3f40b37
commit 2c0750e355
11 changed files with 32476 additions and 20 deletions
+22 -13
View File
@@ -27,8 +27,10 @@ MAINNET_API = "https://api.hyperliquid.xyz/info"
METRICS_FILE = "/tmp/ftdt-paper-metrics.json"
STARTING_CAPITAL = 100000.0 # $100,000 paper trading capital
RESERVE = 30000.0
TAKER_FEE = 0.0005 # 5 bps taker (realistic for paper fills)
TAKER_FEE = 0.0005 # 5 bps taker
MAKER_FEE = 0.0002 # 2 bps maker
SLIPPAGE_BPS = 1.0 # 1 bps slippage
MIN_SIGNAL_STRENGTH = 0.25 # Minimum signal strength to overcome fees
# ═══════════════════════ Strategy state ═══════════════════════
@@ -37,63 +39,63 @@ STRATEGIES = {
"allocation": 10000.0, "instrument": "BTC", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "reversal", "size": 0.002,
"signals": [], "type": "reversal", "size": 0.002, "fee_model": "taker",
"description": "L2 bid/ask volume skew — buys when bids dominate, sells when asks dominate. Mean-reverting at volume extremes.",
},
"Iceberg Detection": {
"allocation": 10000.0, "instrument": "BTC", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "momentum", "size": 0.001,
"signals": [], "type": "momentum", "size": 0.001, "fee_model": "taker",
"description": "Detects whale accumulation (many small buys over time). Follows the smart money flow.",
},
"Funding Rate Arb": {
"allocation": 10000.0, "instrument": "BTC", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "carry", "size": 0.005,
"signals": [], "type": "carry", "size": 0.005, "fee_model": "taker",
"description": "Delta-neutral carry trade — shorts perp when funding rate is high, collects hourly payments.",
},
"Pairs Trading": {
"allocation": 10000.0, "instrument": "ETH", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "stat_arb", "size": 0.05,
"signals": [], "type": "stat_arb", "size": 0.05, "fee_model": "taker",
"description": "BTC/ETH spread mean reversion — trades when Z-score exceeds 1.5 sigma. Pairs converge back to equilibrium.",
},
"Avellaneda-Stoikov": {
"allocation": 10000.0, "instrument": "BTC", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "market_making", "size": 0.001,
"signals": [], "type": "market_making", "size": 0.001, "fee_model": "maker",
"description": "Dual-sided quoting at best bid/ask — captures spread via stochastic control. Simulated fill when spread is crossed.",
},
"Momentum Breakout": {
"allocation": 10000.0, "instrument": "BTC", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "momentum", "size": 0.002,
"signals": [], "type": "momentum", "size": 0.002, "fee_model": "taker",
"description": "Bollinger Band (2σ) breakout — enters when price breaks bands with volume confirmation.",
},
"Mean Reversion": {
"allocation": 10000.0, "instrument": "BTC", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "reversal", "size": 0.002,
"signals": [], "type": "reversal", "size": 0.002, "fee_model": "taker",
"description": "VWAP deviation — buys below VWAP, sells above. Oscillates around fair value.",
},
"Hawkes OFI (new)": {
"allocation": 10000.0, "instrument": "BTC", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "hawkes", "size": 0.002,
"signals": [], "type": "hawkes", "size": 0.002, "fee_model": "taker",
"description": "Hawkes process OFI — self-exciting point process model capturing clustered order flow. Predicts direction from buy/sell intensity imbalance. Academically rigorous stochastic process.",
},
"Deep LOB (new)": {
"allocation": 10000.0, "instrument": "BTC", "pnl": 0.0,
"trades_today": 0, "wins": 0, "win_rate": 0.0, "status": "idle",
"position": 0.0, "entry_price": 0.0, "fee_paid": 0.0,
"signals": [], "type": "deep_lob", "size": 0.002,
"signals": [], "type": "deep_lob", "size": 0.002, "fee_model": "maker",
"description": "Full orderbook depth analysis — wall detection, depth imbalance, thin-side prediction. Uses 10 levels of LOB to find fair value and directional pressure.",
},
}
@@ -261,12 +263,14 @@ def compute_signals():
# ═══════════════════════ Fill Simulation ═══════════════════════
def simulate_fill(name: str, side: str, coin: str, price: float):
"""Simulate a trade fill at market price with fees."""
"""Simulate a trade fill at market price with strategy-specific fees."""
cfg = STRATEGIES[name]
sz = cfg["size"]
notional = sz * price
fee = notional * TAKER_FEE
# Use strategy's fee model
fee_rate = MAKER_FEE if cfg.get("fee_model") == "maker" else TAKER_FEE
fee = notional * fee_rate
slippage = notional * SLIPPAGE_BPS / 10000
cfg["fee_paid"] += fee
@@ -512,12 +516,17 @@ async def main():
if name == "Avellaneda-Stoikov":
continue # Already handled above
# Check for signals
# Check for signals with strength > fee barrier
if not cfg["signals"]:
continue
sig = cfg["signals"][-1]
signal_str = str(sig["signal"])
strength = abs(sig.get("strength", 0))
# Skip weak signals that can't overcome fees
if strength < MIN_SIGNAL_STRENGTH:
continue
coin = cfg["instrument"]
px = btc if coin == "BTC" else eth