malkhut: fee+slippage execution threshold
This commit is contained in:
@@ -120,30 +120,50 @@ def build_our_actions(
|
||||
post_only=intent.prefer_maker, reduce_only=intent.reduce_only,
|
||||
))
|
||||
|
||||
# Aggressive crossing — urgency-driven maker/taker decision
|
||||
# Below threshold: passive only (maker). Above: aggressive (taker).
|
||||
# The system learns the cheapest/fastest path as a function of urgency.
|
||||
# Aggressive crossing — urgency + fee+slippage threshold driven maker/taker decision
|
||||
# The system learns: if (fee + slippage) < threshold → execute (pay the friction)
|
||||
# Threshold is movable (CMA-ES optimizable), tested at 2-3 bps per leg.
|
||||
estimated_fee_bps = state.venue.taker_fee_bps # what taker would pay
|
||||
estimated_slippage_bps = 0.5 # rough estimate; calibrated model refines in CWM
|
||||
estimated_friction = estimated_fee_bps + estimated_slippage_bps
|
||||
|
||||
if intent.urgency > params.urgency_taker_threshold:
|
||||
# High urgency: MARKET for immediate fill
|
||||
for frac in (0.05, 0.10, 0.25):
|
||||
actions.append(FulfilmentAction(
|
||||
kind=ActionKind.CROSS_SPREAD, side=side,
|
||||
order_type=OrderType.MARKET, price_ticks_from_best=0,
|
||||
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
||||
reduce_only=intent.reduce_only,
|
||||
metadata={"urgency": intent.urgency, "mode": "taker_market"},
|
||||
))
|
||||
# High urgency: full taker if friction is acceptable
|
||||
if estimated_friction <= params.execution_friction_threshold_bps or intent.urgency > 0.9:
|
||||
for frac in (0.05, 0.10, 0.25):
|
||||
actions.append(FulfilmentAction(
|
||||
kind=ActionKind.CROSS_SPREAD, side=side,
|
||||
order_type=OrderType.MARKET, price_ticks_from_best=0,
|
||||
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
||||
reduce_only=intent.reduce_only,
|
||||
metadata={"urgency": intent.urgency, "mode": "taker_market",
|
||||
"friction_bps": estimated_friction},
|
||||
))
|
||||
else:
|
||||
# Friction too high even at high urgency → IOC partial
|
||||
for frac in (0.03, 0.06):
|
||||
actions.append(FulfilmentAction(
|
||||
kind=ActionKind.CROSS_SPREAD, side=side,
|
||||
order_type=OrderType.LIMIT, price_ticks_from_best=0,
|
||||
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
||||
time_in_force="IOC",
|
||||
reduce_only=intent.reduce_only,
|
||||
metadata={"urgency": intent.urgency, "mode": "taker_ioc",
|
||||
"friction_bps": estimated_friction},
|
||||
))
|
||||
elif intent.urgency > params.urgency_taker_threshold * 0.5:
|
||||
# Medium urgency: LIMIT + IOC (partial fill OK)
|
||||
for frac in (0.03, 0.06):
|
||||
actions.append(FulfilmentAction(
|
||||
kind=ActionKind.CROSS_SPREAD, side=side,
|
||||
order_type=OrderType.LIMIT, price_ticks_from_best=0,
|
||||
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
||||
time_in_force="IOC",
|
||||
reduce_only=intent.reduce_only,
|
||||
metadata={"urgency": intent.urgency, "mode": "taker_ioc"},
|
||||
))
|
||||
# Medium urgency: IOC partial if friction is low
|
||||
if estimated_friction <= params.execution_friction_threshold_bps * 1.5:
|
||||
for frac in (0.03, 0.06):
|
||||
actions.append(FulfilmentAction(
|
||||
kind=ActionKind.CROSS_SPREAD, side=side,
|
||||
order_type=OrderType.LIMIT, price_ticks_from_best=0,
|
||||
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
||||
time_in_force="IOC",
|
||||
reduce_only=intent.reduce_only,
|
||||
metadata={"urgency": intent.urgency, "mode": "taker_ioc",
|
||||
"friction_bps": estimated_friction},
|
||||
))
|
||||
# Low urgency: passive only (maker) — no taker actions added
|
||||
|
||||
# Path-risk exits
|
||||
|
||||
@@ -397,3 +397,7 @@ class FulfilmentPolicyParams:
|
||||
# Urgency-driven maker/taker decision (CMA-ES optimizable)
|
||||
urgency_taker_threshold: float = 0.65 # above this urgency, prefer taker
|
||||
urgency_taker_penalty_bps: float = 2.0 # penalty for taker at low urgency
|
||||
|
||||
# Fee+slippage execution threshold (movable, CMA-ES optimizable)
|
||||
# If (fee + slippage) < threshold → system tends to EXECUTE (pay the friction)
|
||||
execution_friction_threshold_bps: float = 3.0 # per leg, test 2-3 bps
|
||||
|
||||
@@ -107,6 +107,7 @@ def _params() -> FulfilmentPolicyParams:
|
||||
low_liquidity_weight=2.0, latency_stress_weight=1.0,
|
||||
wait_to_retry_ms=0, chase_enabled=False, chase_offset_ticks=1, chase_max_retries=0,
|
||||
urgency_taker_threshold=0.65, urgency_taker_penalty_bps=2.0,
|
||||
execution_friction_threshold_bps=3.0,
|
||||
)
|
||||
|
||||
def _place(side: Side = Side.BUY, price_ticks: int = 0, qty: float = 0.10,
|
||||
|
||||
@@ -95,6 +95,7 @@ class CMAParameterCodec:
|
||||
ParamSpec("chase_max_retries", "int", 0, 5),
|
||||
ParamSpec("urgency_taker_threshold", "float", 0.1, 0.9),
|
||||
ParamSpec("urgency_taker_penalty_bps", "float", 0.0, 10.0),
|
||||
ParamSpec("execution_friction_threshold_bps", "float", 0.5, 10.0),
|
||||
)
|
||||
|
||||
def initial_vector(self, baseline: FulfilmentPolicyParams) -> list[float]:
|
||||
@@ -157,6 +158,7 @@ class CMAParameterCodec:
|
||||
chase_max_retries=vals.get("chase_max_retries", 0),
|
||||
urgency_taker_threshold=vals.get("urgency_taker_threshold", 0.65),
|
||||
urgency_taker_penalty_bps=vals.get("urgency_taker_penalty_bps", 2.0),
|
||||
execution_friction_threshold_bps=vals.get("execution_friction_threshold_bps", 3.0),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user