malkhut: friction settings configurable per scenario
Scenario gains 3 new fields: maker_fee_bps: Optional[float] = None (override per-scenario) taker_fee_bps: Optional[float] = None (override per-scenario) adverse_cost_bps: Optional[float] = None (per-fill adverse selection) ScenarioFactory gains friction constructor params: ScenarioFactory(exchange_id='bingx', maker_fee_bps=2.0, taker_fee_bps=5.0) _make_state() accepts friction overrides → applies to VenueRules _behavior_state() passes friction overrides through All 34 scenario builder calls updated with friction overrides. System can now learn in ALL conditions: Scenario A: maker=0, taker=5 (free maker fills) Scenario B: maker=2, taker=5 (BingX real) Scenario C: maker=1, taker=3 (Binance-like) CMA-ES optimizes strategy for EACH friction profile independently.
This commit is contained in:
@@ -308,7 +308,11 @@ class Scenario:
|
||||
counterparties: Tuple[CounterpartyPolicy, ...]
|
||||
max_steps: int = 50
|
||||
tags: Tuple[str, ...] = ()
|
||||
venue: str = "bingx" # exchange this scenario simulates (default: BingX for backward compat)
|
||||
venue: str = "bingx" # exchange this scenario simulates
|
||||
# Per-scenario friction overrides (None = use AssetProfile defaults)
|
||||
maker_fee_bps: Optional[float] = None
|
||||
taker_fee_bps: Optional[float] = None
|
||||
adverse_cost_bps: Optional[float] = None # per-fill adverse selection cost
|
||||
|
||||
|
||||
class ScenarioFactory:
|
||||
@@ -328,9 +332,15 @@ class ScenarioFactory:
|
||||
"""
|
||||
|
||||
def __init__(self, counterparties: Optional[Tuple[CounterpartyPolicy, ...]] = None,
|
||||
exchange_id: str = "bingx") -> None:
|
||||
exchange_id: str = "bingx",
|
||||
maker_fee_bps: Optional[float] = None,
|
||||
taker_fee_bps: Optional[float] = None,
|
||||
adverse_cost_bps: Optional[float] = None) -> None:
|
||||
self.counterparties = counterparties or default_counterparty_ecology()
|
||||
self.exchange_id = exchange_id
|
||||
self.maker_fee_bps = maker_fee_bps
|
||||
self.taker_fee_bps = taker_fee_bps
|
||||
self.adverse_cost_bps = adverse_cost_bps
|
||||
|
||||
# --- Behavior-driven helpers ---
|
||||
|
||||
@@ -374,10 +384,11 @@ class ScenarioFactory:
|
||||
@staticmethod
|
||||
def _behavior_state(symbol: str, spread_mult: float = 1.0,
|
||||
depth_fraction: float = 1.0,
|
||||
exchange_id: str = "bingx") -> "MarketWorldState":
|
||||
exchange_id: str = "bingx",
|
||||
maker_fee_bps: Optional[float] = None,
|
||||
taker_fee_bps: Optional[float] = None) -> "MarketWorldState":
|
||||
"""Create a MarketWorldState from AssetBehavior with realistic params.
|
||||
|
||||
Auto-compiles unknown assets from Binance API if needed.
|
||||
Friction overrides take precedence over defaults.
|
||||
"""
|
||||
b = ScenarioFactory._get_behavior(symbol)
|
||||
mid = ScenarioFactory._behavior_mid(symbol)
|
||||
@@ -394,7 +405,9 @@ class ScenarioFactory:
|
||||
bid_qty, ask_qty = 1.0, 1.0
|
||||
return ScenarioFactory._make_state(symbol, bid=bid, ask=ask,
|
||||
bid_qty=bid_qty, ask_qty=ask_qty,
|
||||
exchange_id=exchange_id)
|
||||
exchange_id=exchange_id,
|
||||
maker_fee_bps=maker_fee_bps,
|
||||
taker_fee_bps=taker_fee_bps)
|
||||
|
||||
def build_suite(
|
||||
self,
|
||||
@@ -444,7 +457,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"normal_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=1.0, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=1.0, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("normal", "liquid"),
|
||||
@@ -455,7 +468,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"thin_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.1, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.1, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("thin", "illiquid"),
|
||||
@@ -466,7 +479,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"wide_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=100.0, depth_fraction=0.5, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=100.0, depth_fraction=0.5, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("wide", "volatile"),
|
||||
@@ -478,7 +491,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"toxic_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=2.0, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=2.0, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.3),),
|
||||
max_steps=steps,
|
||||
tags=("toxic", "adverse_selection"),
|
||||
@@ -489,7 +502,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"chop_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.5, depth_fraction=0.2, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.5, depth_fraction=0.2, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("chop", "noise"),
|
||||
@@ -501,7 +514,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"flash_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=3.0, depth_fraction=0.05, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=3.0, depth_fraction=0.05, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.3), ToxicTakerPolicy(sensitivity=0.4)),
|
||||
max_steps=steps,
|
||||
tags=("flash_crash", "thin_book"),
|
||||
@@ -513,7 +526,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"vacuum_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=5.0, depth_fraction=0.01, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=5.0, depth_fraction=0.01, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.2),),
|
||||
max_steps=steps,
|
||||
tags=("liquidity_vacuum", "extreme"),
|
||||
@@ -525,7 +538,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"multi_toxic_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(
|
||||
ToxicTakerPolicy(sensitivity=0.3),
|
||||
ToxicTakerPolicy(sensitivity=0.4),
|
||||
@@ -540,7 +553,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"trend_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.8, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.8, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("trending", "momentum"),
|
||||
@@ -551,7 +564,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"revert_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=20.0, depth_fraction=0.6, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=20.0, depth_fraction=0.6, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("mean_reverting", "wide_spread"),
|
||||
@@ -563,7 +576,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"weekend_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=5.0, depth_fraction=0.05, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=5.0, depth_fraction=0.05, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(self.counterparties[3],),
|
||||
max_steps=steps,
|
||||
tags=("weekend", "low_participation", "thin"),
|
||||
@@ -577,7 +590,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"funding_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(LiquidationFlowPolicy(trigger_bps=30.0), ToxicTakerPolicy(sensitivity=0.4)),
|
||||
max_steps=steps,
|
||||
tags=("funding_shock", "deleveraging"),
|
||||
@@ -591,7 +604,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"cascade_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.2, depth_fraction=0.2, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.2, depth_fraction=0.2, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(
|
||||
LiquidationFlowPolicy(trigger_bps=40.0),
|
||||
ToxicTakerPolicy(sensitivity=0.3),
|
||||
@@ -609,7 +622,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"diverge_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.3), self.counterparties[0]),
|
||||
max_steps=steps,
|
||||
tags=("divergence", "correlation_breakdown"),
|
||||
@@ -623,7 +636,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"stale_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.6, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.6, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(StaleQuoteAttackerPolicy(), LatencyArbPolicy(lead_threshold=0.4)),
|
||||
max_steps=steps,
|
||||
tags=("stale_quote", "latency_arb"),
|
||||
@@ -637,7 +650,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"squeeze_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(InventoryMarketMakerPolicy(max_inventory=0.05), ToxicTakerPolicy(sensitivity=0.4)),
|
||||
max_steps=steps,
|
||||
tags=("squeeze", "inventory_risk"),
|
||||
@@ -650,7 +663,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"news_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=10.0, depth_fraction=0.03, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=10.0, depth_fraction=0.03, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.2), ToxicTakerPolicy(sensitivity=0.3)),
|
||||
max_steps=steps,
|
||||
tags=("news_spike", "gap", "thin"),
|
||||
@@ -662,7 +675,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"tighten_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.3, depth_fraction=1.0, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.3, depth_fraction=1.0, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("spread_tightening", "competition"),
|
||||
@@ -675,7 +688,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"stop_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.2, depth_fraction=0.2, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.2, depth_fraction=0.2, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.3), ToxicTakerPolicy(sensitivity=0.5)),
|
||||
max_steps=steps,
|
||||
tags=("stop_hunting", "manipulation"),
|
||||
@@ -688,7 +701,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"whale_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.2),),
|
||||
max_steps=steps,
|
||||
tags=("whale", "large_order", "impact"),
|
||||
@@ -700,7 +713,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"imbalance_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.8, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.8, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("imbalance", "order_flow", "asymmetry"),
|
||||
@@ -713,7 +726,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"withdraw_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.3, depth_fraction=0.15, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.3, depth_fraction=0.15, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(PassiveMakerPolicy(join_probability=0.2), ToxicTakerPolicy(sensitivity=0.3)),
|
||||
max_steps=steps,
|
||||
tags=("withdrawal", "liquidity_dry", "stress"),
|
||||
@@ -726,7 +739,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"wars_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.8, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.8, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(
|
||||
PassiveMakerPolicy(join_probability=0.8),
|
||||
PassiveMakerPolicy(join_probability=0.7),
|
||||
@@ -743,7 +756,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"arb_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.5, depth_fraction=0.5, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.5, depth_fraction=0.5, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(LatencyArbPolicy(lead_threshold=0.3), ToxicTakerPolicy(sensitivity=0.4)),
|
||||
max_steps=steps,
|
||||
tags=("arbitrage", "cross_venue", "price_discovery"),
|
||||
@@ -755,7 +768,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"flow_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.5, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.5, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=self.counterparties,
|
||||
max_steps=steps,
|
||||
tags=("order_flow", "institutional", "asymmetry"),
|
||||
@@ -768,7 +781,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"volregime_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.1, depth_fraction=0.7, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.1, depth_fraction=0.7, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.4),),
|
||||
max_steps=steps,
|
||||
tags=("volatility_regime", "transition", "adaptive"),
|
||||
@@ -781,7 +794,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"pump_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.2, depth_fraction=0.2, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.2, depth_fraction=0.2, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.2), ToxicTakerPolicy(sensitivity=0.3)),
|
||||
max_steps=steps,
|
||||
tags=("pump_dump", "manipulation", "coordinated"),
|
||||
@@ -794,7 +807,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"iceberg_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.3),),
|
||||
max_steps=steps,
|
||||
tags=("iceberg", "hidden_order", "gradual_impact"),
|
||||
@@ -808,7 +821,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"margin_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.3, depth_fraction=0.15, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.3, depth_fraction=0.15, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(
|
||||
LiquidationFlowPolicy(trigger_bps=30.0),
|
||||
ToxicTakerPolicy(sensitivity=0.3),
|
||||
@@ -825,7 +838,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"oracle_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=3.0, depth_fraction=0.05, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=3.0, depth_fraction=0.05, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.2), ToxicTakerPolicy(sensitivity=0.3)),
|
||||
max_steps=steps,
|
||||
tags=("oracle_manipulation", "flash_loan", "dex"),
|
||||
@@ -838,7 +851,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"whale_retail_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.5, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(ToxicTakerPolicy(sensitivity=0.3), NoiseTraderPolicy()),
|
||||
max_steps=steps,
|
||||
tags=("whale_vs_retail", "institutional", "retail"),
|
||||
@@ -851,7 +864,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"arb_stress_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.8, depth_fraction=0.3, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=0.8, depth_fraction=0.3, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(LatencyArbPolicy(lead_threshold=0.2), ToxicTakerPolicy(sensitivity=0.4)),
|
||||
max_steps=steps,
|
||||
tags=("cross_exchange", "arb_stress", "price_discovery"),
|
||||
@@ -864,7 +877,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"decay_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.7, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=1.0, depth_fraction=0.7, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(PassiveMakerPolicy(join_probability=0.1), ToxicTakerPolicy(sensitivity=0.4)),
|
||||
max_steps=steps,
|
||||
tags=("decay", "liquidity_withdrawal", "gradual"),
|
||||
@@ -878,7 +891,7 @@ class ScenarioFactory:
|
||||
return Scenario(
|
||||
scenario_id=f"breakdown_{symbol}_{seed}",
|
||||
symbol=symbol,
|
||||
initial_state=self._behavior_state(symbol, spread_mult=5.0, depth_fraction=0.15, exchange_id=self.exchange_id),
|
||||
initial_state=self._behavior_state(symbol, spread_mult=5.0, depth_fraction=0.15, exchange_id=self.exchange_id), maker_fee_bps=self.maker_fee_bps, taker_fee_bps=self.taker_fee_bps,
|
||||
counterparties=(
|
||||
ToxicTakerPolicy(sensitivity=0.3),
|
||||
LatencyArbPolicy(lead_threshold=0.3),
|
||||
@@ -976,8 +989,12 @@ class ScenarioFactory:
|
||||
|
||||
@staticmethod
|
||||
def _make_state(symbol: str, bid: float, ask: float, bid_qty: float, ask_qty: float,
|
||||
exchange_id: str = "bingx") -> MarketWorldState:
|
||||
"""Create a market state using asset classification for realistic parameters."""
|
||||
exchange_id: str = "bingx",
|
||||
maker_fee_bps: Optional[float] = None,
|
||||
taker_fee_bps: Optional[float] = None) -> MarketWorldState:
|
||||
"""Create a market state using asset classification for realistic parameters.
|
||||
Friction overrides take precedence over AssetProfile defaults.
|
||||
"""
|
||||
from malkhut.training.asset_classification import get_asset_profile, ASSET_PROFILES
|
||||
|
||||
profile = get_asset_profile(symbol)
|
||||
@@ -986,7 +1003,8 @@ class ScenarioFactory:
|
||||
exchange=exchange_id, symbol=symbol,
|
||||
tick_size=profile.tick_size, lot_size=profile.lot_size,
|
||||
min_qty=profile.lot_size, min_notional=5.0,
|
||||
maker_fee_bps=profile.maker_fee_bps, taker_fee_bps=profile.taker_fee_bps,
|
||||
maker_fee_bps=maker_fee_bps if maker_fee_bps is not None else profile.maker_fee_bps,
|
||||
taker_fee_bps=taker_fee_bps if taker_fee_bps is not None else profile.taker_fee_bps,
|
||||
post_only_supported=True, reduce_only_supported=True,
|
||||
max_orders_per_second=100, max_cancels_per_minute=120,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user