malkhut: all exchange order types in DSL + action_menu
ActionType → OrderType mapping (common-sensical): QUOTE/REQUOTE/CHASE: LIMIT (passive, post_only) CROSS_SPREAD (high urgency): MARKET (immediate fill) CROSS_SPREAD (medium urgency): LIMIT + IOC (partial fill) STOP_LOSS: STOP_MARKET (trigger → market exit) TAKE_PROFIT: TRIGGER_MARKET (trigger → market exit) TRAILING_STOP: TRAILING_STOP (trailing stop exit) EXIT/FLAT_ALL: STOP_MARKET EMERGENCY_EXIT: MARKET (immediate) All order types exercised: LIMIT, MARKET, STOP_MARKET, TRIGGER_MARKET, TRAILING_STOP
This commit is contained in:
@@ -5,6 +5,14 @@ Menu size target:
|
|||||||
our actions: 8-24
|
our actions: 8-24
|
||||||
each counterparty role: 3-12
|
each counterparty role: 3-12
|
||||||
depth: 2-4
|
depth: 2-4
|
||||||
|
|
||||||
|
Order type mapping (common-sensical):
|
||||||
|
QUOTE/REQUOTE/CHASE: LIMIT (passive, post_only)
|
||||||
|
CROSS_SPREAD (low urgency): LIMIT + IOC (taker, partial fill OK)
|
||||||
|
CROSS_SPREAD (high urgency): MARKET (immediate fill)
|
||||||
|
STOP_LOSS: STOP_MARKET (trigger → market exit)
|
||||||
|
TAKE_PROFIT: TRIGGER_MARKET (trigger → market exit)
|
||||||
|
TRAILING_STOP: TRAILING_STOP (trailing stop exit)
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -116,18 +124,17 @@ def build_our_actions(
|
|||||||
# Below threshold: passive only (maker). Above: aggressive (taker).
|
# Below threshold: passive only (maker). Above: aggressive (taker).
|
||||||
# The system learns the cheapest/fastest path as a function of urgency.
|
# The system learns the cheapest/fastest path as a function of urgency.
|
||||||
if intent.urgency > params.urgency_taker_threshold:
|
if intent.urgency > params.urgency_taker_threshold:
|
||||||
# High urgency: aggressive taker fills
|
# High urgency: MARKET for immediate fill
|
||||||
for frac in (0.05, 0.10, 0.25):
|
for frac in (0.05, 0.10, 0.25):
|
||||||
actions.append(FulfilmentAction(
|
actions.append(FulfilmentAction(
|
||||||
kind=ActionKind.CROSS_SPREAD, side=side,
|
kind=ActionKind.CROSS_SPREAD, side=side,
|
||||||
order_type=OrderType.LIMIT, price_ticks_from_best=0,
|
order_type=OrderType.MARKET, price_ticks_from_best=0,
|
||||||
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
||||||
time_in_force="IOC",
|
|
||||||
reduce_only=intent.reduce_only,
|
reduce_only=intent.reduce_only,
|
||||||
metadata={"urgency": intent.urgency, "mode": "taker"},
|
metadata={"urgency": intent.urgency, "mode": "taker_market"},
|
||||||
))
|
))
|
||||||
elif intent.urgency > params.urgency_taker_threshold * 0.5:
|
elif intent.urgency > params.urgency_taker_threshold * 0.5:
|
||||||
# Medium urgency: aggressive but with IOC (partial fill OK)
|
# Medium urgency: LIMIT + IOC (partial fill OK)
|
||||||
for frac in (0.03, 0.06):
|
for frac in (0.03, 0.06):
|
||||||
actions.append(FulfilmentAction(
|
actions.append(FulfilmentAction(
|
||||||
kind=ActionKind.CROSS_SPREAD, side=side,
|
kind=ActionKind.CROSS_SPREAD, side=side,
|
||||||
@@ -135,17 +142,18 @@ def build_our_actions(
|
|||||||
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
qty_fraction=frac, ttl_ms=params.aggressive_ttl_ms,
|
||||||
time_in_force="IOC",
|
time_in_force="IOC",
|
||||||
reduce_only=intent.reduce_only,
|
reduce_only=intent.reduce_only,
|
||||||
metadata={"urgency": intent.urgency, "mode": "taker_partial"},
|
metadata={"urgency": intent.urgency, "mode": "taker_ioc"},
|
||||||
))
|
))
|
||||||
# Low urgency: passive only (maker) — no taker actions added
|
# Low urgency: passive only (maker) — no taker actions added
|
||||||
|
|
||||||
# Path-risk exits
|
# Path-risk exits
|
||||||
if _path_risk_says_exit(state, params):
|
if _path_risk_says_exit(state, params):
|
||||||
|
# STOP_MARKET for stop-loss exits (trigger → market)
|
||||||
actions.append(FulfilmentAction(
|
actions.append(FulfilmentAction(
|
||||||
kind=ActionKind.FULL_EXIT, side=_exit_side_for_position(state),
|
kind=ActionKind.FULL_EXIT, side=_exit_side_for_position(state),
|
||||||
order_type=OrderType.MARKET, price_ticks_from_best=0,
|
order_type=OrderType.STOP_MARKET, price_ticks_from_best=0,
|
||||||
qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
||||||
metadata={"reason": "path_risk_exit"},
|
metadata={"reason": "path_risk_exit", "exit_type": "stop_market"},
|
||||||
))
|
))
|
||||||
|
|
||||||
# Chase actions (cancel → wait → retry with configurable wait_to_retry_ms)
|
# Chase actions (cancel → wait → retry with configurable wait_to_retry_ms)
|
||||||
@@ -160,7 +168,8 @@ def build_our_actions(
|
|||||||
ttl_ms=chase_ttl,
|
ttl_ms=chase_ttl,
|
||||||
post_only=True,
|
post_only=True,
|
||||||
metadata={"chase": True, "chase_offset": offset,
|
metadata={"chase": True, "chase_offset": offset,
|
||||||
"chase_max_retries": params.chase_max_retries},
|
"chase_max_retries": params.chase_max_retries,
|
||||||
|
"order_type_combo": "LIMIT+post_only+chase"},
|
||||||
))
|
))
|
||||||
|
|
||||||
return tuple(actions)
|
return tuple(actions)
|
||||||
|
|||||||
@@ -616,10 +616,17 @@ def _primitive_to_action(primitive: ActionPrimitive, state: MarketWorldState) ->
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif at in (ActionType.CROSS, ActionType.SNIPER, ActionType.PING):
|
elif at in (ActionType.CROSS, ActionType.SNIPER, ActionType.PING):
|
||||||
|
# CROSS: aggressive fill. Use MARKET for immediate execution.
|
||||||
|
# SNIPER: precision entry, use LIMIT + IOC for partial fill control.
|
||||||
|
# PING: small aggressive test, use LIMIT + IOC.
|
||||||
|
if at == ActionType.CROSS:
|
||||||
|
order_type = OrderType.MARKET
|
||||||
|
else:
|
||||||
|
order_type = OrderType.LIMIT
|
||||||
return FulfilmentAction(
|
return FulfilmentAction(
|
||||||
kind=ActionKind.CROSS_SPREAD, side=primitive.side, order_type=OrderType.LIMIT,
|
kind=ActionKind.CROSS_SPREAD, side=primitive.side, order_type=order_type,
|
||||||
price_ticks_from_best=0, qty_fraction=primitive.size_fraction, ttl_ms=50,
|
price_ticks_from_best=0, qty_fraction=primitive.size_fraction, ttl_ms=50,
|
||||||
time_in_force="IOC",
|
time_in_force="IOC" if order_type == OrderType.LIMIT else "GTC",
|
||||||
)
|
)
|
||||||
|
|
||||||
elif at == ActionType.CANCEL_ALL:
|
elif at == ActionType.CANCEL_ALL:
|
||||||
@@ -637,8 +644,10 @@ def _primitive_to_action(primitive: ActionPrimitive, state: MarketWorldState) ->
|
|||||||
side = Side.SELL if pos and pos.qty > 0 else Side.BUY if pos and pos.qty < 0 else None
|
side = Side.SELL if pos and pos.qty > 0 else Side.BUY if pos and pos.qty < 0 else None
|
||||||
if side is None:
|
if side is None:
|
||||||
return FulfilmentAction(ActionKind.NOOP, None, None, 0, 0.0, 0)
|
return FulfilmentAction(ActionKind.NOOP, None, None, 0, 0.0, 0)
|
||||||
|
# EMERGENCY_EXIT uses MARKET for immediate fill; EXIT uses STOP_MARKET
|
||||||
|
order_type = OrderType.MARKET if at == ActionType.EMERGENCY_EXIT else OrderType.STOP_MARKET
|
||||||
return FulfilmentAction(
|
return FulfilmentAction(
|
||||||
kind=ActionKind.FULL_EXIT, side=side, order_type=OrderType.MARKET,
|
kind=ActionKind.FULL_EXIT, side=side, order_type=order_type,
|
||||||
price_ticks_from_best=0, qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
price_ticks_from_best=0, qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -648,9 +657,9 @@ def _primitive_to_action(primitive: ActionPrimitive, state: MarketWorldState) ->
|
|||||||
if side is None:
|
if side is None:
|
||||||
return FulfilmentAction(ActionKind.NOOP, None, None, 0, 0.0, 0)
|
return FulfilmentAction(ActionKind.NOOP, None, None, 0, 0.0, 0)
|
||||||
return FulfilmentAction(
|
return FulfilmentAction(
|
||||||
kind=ActionKind.FULL_EXIT, side=side, order_type=OrderType.MARKET,
|
kind=ActionKind.FULL_EXIT, side=side, order_type=OrderType.STOP_MARKET,
|
||||||
price_ticks_from_best=0, qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
price_ticks_from_best=0, qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
||||||
metadata={"reason": "stop_loss"},
|
metadata={"reason": "stop_loss", "order_type_combo": "STOP_MARKET"},
|
||||||
)
|
)
|
||||||
|
|
||||||
elif at == ActionType.TAKE_PROFIT:
|
elif at == ActionType.TAKE_PROFIT:
|
||||||
@@ -659,9 +668,9 @@ def _primitive_to_action(primitive: ActionPrimitive, state: MarketWorldState) ->
|
|||||||
if side is None:
|
if side is None:
|
||||||
return FulfilmentAction(ActionKind.NOOP, None, None, 0, 0.0, 0)
|
return FulfilmentAction(ActionKind.NOOP, None, None, 0, 0.0, 0)
|
||||||
return FulfilmentAction(
|
return FulfilmentAction(
|
||||||
kind=ActionKind.FULL_EXIT, side=side, order_type=OrderType.MARKET,
|
kind=ActionKind.FULL_EXIT, side=side, order_type=OrderType.TRIGGER_MARKET,
|
||||||
price_ticks_from_best=0, qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
price_ticks_from_best=0, qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
||||||
metadata={"reason": "take_profit"},
|
metadata={"reason": "take_profit", "order_type_combo": "TRIGGER_MARKET"},
|
||||||
)
|
)
|
||||||
|
|
||||||
elif at == ActionType.TRAILING_STOP:
|
elif at == ActionType.TRAILING_STOP:
|
||||||
@@ -670,9 +679,10 @@ def _primitive_to_action(primitive: ActionPrimitive, state: MarketWorldState) ->
|
|||||||
if side is None:
|
if side is None:
|
||||||
return FulfilmentAction(ActionKind.NOOP, None, None, 0, 0.0, 0)
|
return FulfilmentAction(ActionKind.NOOP, None, None, 0, 0.0, 0)
|
||||||
return FulfilmentAction(
|
return FulfilmentAction(
|
||||||
kind=ActionKind.FULL_EXIT, side=side, order_type=OrderType.MARKET,
|
kind=ActionKind.FULL_EXIT, side=side, order_type=OrderType.TRAILING_STOP,
|
||||||
price_ticks_from_best=0, qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
price_ticks_from_best=0, qty_fraction=1.0, ttl_ms=0, reduce_only=True,
|
||||||
metadata={"reason": "trailing_stop", "trail_bps": primitive.trail_distance_bps},
|
metadata={"reason": "trailing_stop", "trail_bps": primitive.trail_distance_bps,
|
||||||
|
"order_type_combo": "TRAILING_STOP"},
|
||||||
)
|
)
|
||||||
|
|
||||||
elif at == ActionType.HALF_EXIT:
|
elif at == ActionType.HALF_EXIT:
|
||||||
|
|||||||
Reference in New Issue
Block a user