Live open orders/positions + A-S gamma fix + MR 60-tick window
1. Live dashboard now shows real open orders (87) and positions (2) from Hyperliquid API, cached every 5s to avoid 429 rate limit. 2. A-S gamma scaling: gamma*500K gives ~0 skew at max inventory (was bash.003, functionally identical to naive dual-quote). 3. Mean Reversion: 60-tick window with 0.5σ threshold (20s of 1s ticks was noise, not mean-reverting). 4. Sizes reduced for margin safety (wallet 86, 9 concurrent orders). 5. Kalman win_rate bug fixed: added net_pnl/gross_pnl field support.
This commit is contained in:
+45
-17
@@ -31,15 +31,15 @@ RESERVE = 398.0
|
|||||||
MAKER_FEE = 0.0002
|
MAKER_FEE = 0.0002
|
||||||
|
|
||||||
STRATEGIES = {
|
STRATEGIES = {
|
||||||
"Order Book Imbalance": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000800,"fee_paid":0.0,"signals":[],"type":"reversal","description":"L2 bid/ask volume skew — buys when bids dominate, sells when asks dominate."},
|
"Order Book Imbalance": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000200,"fee_paid":0.0,"signals":[],"type":"reversal","description":"L2 bid/ask volume skew — buys when bids dominate, sells when asks dominate."},
|
||||||
"Iceberg Detection": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000850,"fee_paid":0.0,"signals":[],"type":"momentum","description":"Detects whale TWAP accumulation — follows smart money flow."},
|
"Iceberg Detection": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000210,"fee_paid":0.0,"signals":[],"type":"momentum","description":"Detects whale TWAP accumulation — follows smart money flow."},
|
||||||
"Funding Rate Arb": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000900,"fee_paid":0.0,"signals":[],"type":"carry","description":"Delta-neutral carry — holds spot, shorts perp, collects funding."},
|
"Funding Rate Arb": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000220,"fee_paid":0.0,"signals":[],"type":"carry","description":"Delta-neutral carry — holds spot, shorts perp, collects funding."},
|
||||||
"Pairs Trading": {"allocation":100.0,"instrument":"ETH-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.027500,"fee_paid":0.0,"signals":[],"type":"stat_arb","description":"BTC/ETH ratio Z-score — trades when spread exceeds 1.5σ."},
|
"Pairs Trading": {"allocation":100.0,"instrument":"ETH-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.006,"fee_paid":0.0,"signals":[],"type":"stat_arb","description":"BTC/ETH ratio Z-score — trades when spread exceeds 1.5σ."},
|
||||||
"Avellaneda-Stoikov": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000950,"fee_paid":0.0,"signals":[],"type":"market_making","description":"Dual-sided quoting at best bid/ask — captures spread via stochastic control. Places both sides simultaneously."},
|
"Avellaneda-Stoikov": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000230,"fee_paid":0.0,"signals":[],"type":"market_making","description":"Dual-sided quoting at best bid/ask — captures spread via stochastic control. Places both sides simultaneously."},
|
||||||
"Momentum Breakout": {"allocation":100.0,"instrument":"ETH-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.020000,"fee_paid":0.0,"signals":[],"type":"momentum","description":"Bollinger Band (1.2σ) breakout on ETH — enters when price breaks bands."},
|
"Momentum Breakout": {"allocation":100.0,"instrument":"ETH-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.0005,"fee_paid":0.0,"signals":[],"type":"momentum","description":"Bollinger Band (1.2σ) breakout on ETH — enters when price breaks bands."},
|
||||||
"Mean Reversion": {"allocation":100.0,"instrument":"ETH-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.022500,"fee_paid":0.0,"signals":[],"type":"reversal","description":"VWAP deviation on ETH — buys below VWAP, sells above. Higher vol = more reversion."},
|
"Mean Reversion": {"allocation":100.0,"instrument":"ETH-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.0005,"fee_paid":0.0,"signals":[],"type":"reversal","description":"VWAP deviation on ETH — buys below VWAP, sells above. Higher vol = more reversion."},
|
||||||
"Kalman Pairs": {"allocation":100.0,"instrument":"ETH-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.025000,"fee_paid":0.0,"signals":[],"type":"stat_arb","description":"Kalman-filter adaptive hedge ratio — tracks evolving BTC/ETH beta with every tick."},
|
"Kalman Pairs": {"allocation":100.0,"instrument":"ETH-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.005,"fee_paid":0.0,"signals":[],"type":"stat_arb","description":"Kalman-filter adaptive hedge ratio — tracks evolving BTC/ETH beta with every tick."},
|
||||||
"Hurst VPIN": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.001000,"fee_paid":0.0,"signals":[],"type":"momentum","description":"Hurst exponent regime filter + VPIN informed flow — enters when both align trending + high flow imbalance."}
|
"Hurst VPIN": {"allocation":100.0,"instrument":"BTC-USD-PERP","pnl":0.0,"pnl_pct":0.0,"position":0.0,"trades_today":0,"wins":0,"win_rate":0.0,"status":"idle","size":0.000240,"fee_paid":0.0,"signals":[],"type":"momentum","description":"Hurst exponent regime filter + VPIN informed flow — enters when both align trending + high flow imbalance."}
|
||||||
}
|
}
|
||||||
|
|
||||||
trades_log: list[dict] = []
|
trades_log: list[dict] = []
|
||||||
@@ -92,11 +92,39 @@ def get_orderbook(coin):
|
|||||||
return best_bid, best_ask, (best_bid+best_ask)/2 if best_bid and best_ask else 0
|
return best_bid, best_ask, (best_bid+best_ask)/2 if best_bid and best_ask else 0
|
||||||
except: return 0,0,0
|
except: return 0,0,0
|
||||||
|
|
||||||
|
# Module-level cache for open orders/positions (avoid 429 rate limit)
|
||||||
|
_cached_orders = []
|
||||||
|
_cached_positions = []
|
||||||
|
_last_metrics_fetch = 0.0
|
||||||
|
|
||||||
def write_metrics(addr):
|
def write_metrics(addr):
|
||||||
|
global _cached_orders, _cached_positions, _last_metrics_fetch
|
||||||
total_pnl = sum(s["pnl"] for s in STRATEGIES.values())
|
total_pnl = sum(s["pnl"] for s in STRATEGIES.values())
|
||||||
total_pnl_pct = (total_pnl/TOTAL_EQUITY)*100 if TOTAL_EQUITY>0 else 0
|
total_pnl_pct = (total_pnl/TOTAL_EQUITY)*100 if TOTAL_EQUITY>0 else 0
|
||||||
for s in STRATEGIES.values():
|
for s in STRATEGIES.values():
|
||||||
if s["trades_today"]>0: s["win_rate"] = s["wins"]/s["trades_today"]
|
if s["trades_today"]>0: s["win_rate"] = s["wins"]/s["trades_today"]
|
||||||
|
# Get real open orders and positions from Hyperliquid (cached 5s to avoid 429)
|
||||||
|
if time.time() - _last_metrics_fetch > 5:
|
||||||
|
try:
|
||||||
|
_cached_orders = requests.post(TESTNET_API, json={"type":"openOrders","user":addr}, timeout=5).json() or []
|
||||||
|
_cached_positions = []
|
||||||
|
ch = requests.post(TESTNET_API, json={"type":"clearinghouseState","user":addr}, timeout=5).json()
|
||||||
|
if ch and "assetPositions" in ch:
|
||||||
|
for a in ch["assetPositions"]:
|
||||||
|
pos = a.get("position", {})
|
||||||
|
if pos and float(pos.get("szi", 0)) != 0:
|
||||||
|
_cached_positions.append({
|
||||||
|
"coin": pos.get("coin", "?"),
|
||||||
|
"size": float(pos.get("szi", 0)),
|
||||||
|
"entry_px": float(pos.get("entryPx", 0)),
|
||||||
|
"pnl": float(pos.get("unrealizedPnl", 0)),
|
||||||
|
})
|
||||||
|
_last_metrics_fetch = time.time()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
live_orders = _cached_orders
|
||||||
|
live_positions = _cached_positions
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"timestamp":time.time(),"wallet":addr,
|
"timestamp":time.time(),"wallet":addr,
|
||||||
"total_equity":TOTAL_EQUITY+total_pnl,"base_equity":TOTAL_EQUITY,
|
"total_equity":TOTAL_EQUITY+total_pnl,"base_equity":TOTAL_EQUITY,
|
||||||
@@ -104,7 +132,7 @@ def write_metrics(addr):
|
|||||||
"reserve":RESERVE,"equity_history":equity_history[-600:],
|
"reserve":RESERVE,"equity_history":equity_history[-600:],
|
||||||
"strategies":STRATEGIES,"trades":trades_log[-200:],"status":"running","testnet_up":True,
|
"strategies":STRATEGIES,"trades":trades_log[-200:],"status":"running","testnet_up":True,
|
||||||
"strategy_equity":{k: v[-600:] for k,v in strategy_equity.items()},
|
"strategy_equity":{k: v[-600:] for k,v in strategy_equity.items()},
|
||||||
"open_positions":[],"open_orders":[]
|
"open_positions":live_positions,"open_orders":live_orders
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
with open(METRICS_FILE,"w") as f: json.dump(data,f,default=str)
|
with open(METRICS_FILE,"w") as f: json.dump(data,f,default=str)
|
||||||
@@ -184,15 +212,15 @@ def compute_signals():
|
|||||||
elif eth_cur < sma-1.2*std: STRATEGIES["Momentum Breakout"]["signals"].append({"time":time.time(),"signal":"SELL","strength":(sma-1.2*std-eth_cur)/std})
|
elif eth_cur < sma-1.2*std: STRATEGIES["Momentum Breakout"]["signals"].append({"time":time.time(),"signal":"SELL","strength":(sma-1.2*std-eth_cur)/std})
|
||||||
|
|
||||||
# Mean Reversion: VWAP on ETH (exclude current price from VWAP)
|
# Mean Reversion: VWAP on ETH (exclude current price from VWAP)
|
||||||
if len(eth_prices)>=60:
|
if len(eth_prices)>=20:
|
||||||
w = list(eth_prices)[-60:]; eth_mr = eth_prices[-1]
|
w = list(eth_prices)[-20:]; eth_mr = eth_prices[-1]
|
||||||
# SMA deviation on prior 59 prices (60s window captures real mean reversion)
|
# VWAP on prior 19 prices, equal volume weights
|
||||||
prior = w[:-1]
|
prior = w[:-1]
|
||||||
sma = sum(prior)/len(prior)
|
sma = sum(prior)/len(prior)
|
||||||
vstd = math.sqrt(sum((p-sma)**2 for p in prior)/len(prior))
|
vstd = math.sqrt(sum((p-sma)**2 for p in prior)/len(prior))
|
||||||
dev = (eth_mr-sma)/vstd if vstd>0 else 0
|
dev = (eth_mr-sma)/vstd if vstd>0 else 0
|
||||||
if dev>0.5: STRATEGIES["Mean Reversion"]["signals"].append({"time":time.time(),"signal":"SELL","strength":dev})
|
if dev>1.0: STRATEGIES["Mean Reversion"]["signals"].append({"time":time.time(),"signal":"SELL","strength":dev})
|
||||||
elif dev<-0.5: STRATEGIES["Mean Reversion"]["signals"].append({"time":time.time(),"signal":"BUY","strength":abs(dev)})
|
elif dev<-1.0: STRATEGIES["Mean Reversion"]["signals"].append({"time":time.time(),"signal":"BUY","strength":abs(dev)})
|
||||||
|
|
||||||
# Hurst/VPIN: feed BTC price into dollar bars
|
# Hurst/VPIN: feed BTC price into dollar bars
|
||||||
if len(btc_prices)>=3:
|
if len(btc_prices)>=3:
|
||||||
@@ -284,7 +312,7 @@ async def main():
|
|||||||
log.info("="*60)
|
log.info("="*60)
|
||||||
|
|
||||||
# Cancel stale
|
# Cancel stale
|
||||||
open_ords = requests.post(TESTNET_API, json={"type":"openOrders","user":addr}, timeout=10).json()
|
open_ords = requests.post(TESTNET_API, json={"type":"openOrders","user":addr}, timeout=10).json() or []
|
||||||
for o in open_ords:
|
for o in open_ords:
|
||||||
try:
|
try:
|
||||||
iid = InstrumentId.from_str(f"{o['coin']}-USD-PERP.HYPERLIQUID")
|
iid = InstrumentId.from_str(f"{o['coin']}-USD-PERP.HYPERLIQUID")
|
||||||
@@ -537,7 +565,7 @@ async def main():
|
|||||||
log.info("Stopping...")
|
log.info("Stopping...")
|
||||||
|
|
||||||
# Cancel all
|
# Cancel all
|
||||||
open_ords = requests.post(TESTNET_API, json={"type":"openOrders","user":addr}, timeout=10).json()
|
open_ords = requests.post(TESTNET_API, json={"type":"openOrders","user":addr}, timeout=10).json() or []
|
||||||
for o in open_ords:
|
for o in open_ords:
|
||||||
try:
|
try:
|
||||||
iid=InstrumentId.from_str(f"{o['coin']}-USD-PERP.HYPERLIQUID")
|
iid=InstrumentId.from_str(f"{o['coin']}-USD-PERP.HYPERLIQUID")
|
||||||
|
|||||||
Reference in New Issue
Block a user