malkhut(T2): Code World Model — deterministic exchange simulator
CWM core (core.py): price-time priority, sequential level consumption, partial fills, queue position, latency injection, maker/taker fees. Numba acceleration (numba_core.py): JIT hot loops, 1.8x fill speedup. Replay verification (replay_verify.py): binary search, trajectory recording. Supporting: adverse_selection, correlation, latency_model, multi_level, queue_model, spread_dynamics, volatility, hftbacktest_validator.
This commit is contained in:
131
MALKHUT/malkhut/cwm/latency_model.py
Normal file
131
MALKHUT/malkhut/cwm/latency_model.py
Normal file
@@ -0,0 +1,131 @@
|
||||
"""
|
||||
Latency Model — simulate realistic feed and order latencies.
|
||||
|
||||
Essential for:
|
||||
- Realistic fill simulation
|
||||
- Latency arbitrage defense
|
||||
- Optimal order timing
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
from numba import njit
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class LatencyState:
|
||||
"""Latency state for the CWM."""
|
||||
feed_latency_ms: float
|
||||
order_latency_ms: float
|
||||
feed_jitter_ms: float
|
||||
order_jitter_ms: float
|
||||
|
||||
|
||||
@njit(cache=True)
|
||||
def simulate_feed_latency(
|
||||
base_latency_ms: float,
|
||||
jitter_ms: float,
|
||||
rng_seed: int,
|
||||
) -> float:
|
||||
"""
|
||||
Simulate feed latency with jitter.
|
||||
|
||||
Model: base_latency + uniform(-jitter, +jitter)
|
||||
Returns latency in milliseconds.
|
||||
"""
|
||||
# Simple deterministic jitter using seed
|
||||
jitter = jitter_ms * (2.0 * ((rng_seed % 1000) / 1000.0) - 1.0)
|
||||
return max(0.0, base_latency_ms + jitter)
|
||||
|
||||
|
||||
@njit(cache=True)
|
||||
def simulate_order_latency(
|
||||
base_latency_ms: float,
|
||||
jitter_ms: float,
|
||||
queue_position: int,
|
||||
recent_trade_rate: float,
|
||||
rng_seed: int = 0,
|
||||
) -> float:
|
||||
"""
|
||||
Simulate order latency with queue dynamics.
|
||||
|
||||
Model:
|
||||
- Base latency + jitter
|
||||
- Additional latency from queue position (longer queue = slower fill)
|
||||
- Reduced latency when trade rate is high (faster queue consumption)
|
||||
|
||||
Returns latency in milliseconds.
|
||||
"""
|
||||
jitter = jitter_ms * (2.0 * ((rng_seed % 1000) / 1000.0) - 1.0)
|
||||
queue_delay = queue_position / max(recent_trade_rate, 0.01) * 1000.0
|
||||
return max(0.0, base_latency_ms + jitter + queue_delay * 0.1)
|
||||
|
||||
|
||||
@njit(cache=True)
|
||||
def compute_latency_impact(
|
||||
feed_latency_ms: float,
|
||||
order_latency_ms: float,
|
||||
price_change_per_ms: float,
|
||||
) -> float:
|
||||
"""
|
||||
Compute the cost of latency in basis points.
|
||||
|
||||
Model:
|
||||
- Feed latency: price moves before we see it
|
||||
- Order latency: price moves before our order arrives
|
||||
- Total cost = (feed_latency + order_latency) * price_change_per_ms
|
||||
|
||||
Returns cost in basis points.
|
||||
"""
|
||||
total_latency_ms = feed_latency_ms + order_latency_ms
|
||||
# Assume price moves ~1bp per 10ms in volatile markets
|
||||
cost_bps = total_latency_ms * price_change_per_ms
|
||||
return cost_bps
|
||||
|
||||
|
||||
class LatencyModel:
|
||||
"""
|
||||
Latency model for the CWM.
|
||||
|
||||
Simulates realistic feed and order latencies.
|
||||
Used by CWM to make fill simulation realistic.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
feed_latency_ms: float = 10.0,
|
||||
order_latency_ms: float = 50.0,
|
||||
feed_jitter_ms: float = 2.0,
|
||||
order_jitter_ms: float = 10.0,
|
||||
) -> None:
|
||||
self._feed_latency = feed_latency_ms
|
||||
self._order_latency = order_latency_ms
|
||||
self._feed_jitter = feed_jitter_ms
|
||||
self._order_jitter = order_jitter_ms
|
||||
self._rng_seed = 0
|
||||
|
||||
def simulate_feed_latency(self) -> float:
|
||||
"""Simulate current feed latency."""
|
||||
self._rng_seed += 1
|
||||
return simulate_feed_latency(self._feed_latency, self._feed_jitter, self._rng_seed)
|
||||
|
||||
def simulate_order_latency(self, queue_position: int = 0, recent_trade_rate: float = 0.5) -> float:
|
||||
"""Simulate current order latency."""
|
||||
self._rng_seed += 1
|
||||
return simulate_order_latency(self._order_latency, self._order_jitter, queue_position, recent_trade_rate, self._rng_seed)
|
||||
|
||||
def compute_latency_cost(self, price_change_per_ms: float = 0.001) -> float:
|
||||
"""Compute latency cost in basis points."""
|
||||
return compute_latency_impact(self._feed_latency, self._order_latency, price_change_per_ms)
|
||||
|
||||
@property
|
||||
def feed_latency_ms(self) -> float:
|
||||
return self._feed_latency
|
||||
|
||||
@property
|
||||
def order_latency_ms(self) -> float:
|
||||
return self._order_latency
|
||||
Reference in New Issue
Block a user