mts1b-oms-algos — public API surface
Each algorithm is an async generator that yields child orders.
The contract
from typing import AsyncIterator
from mts1b_foundation.orders import Order
async def execute(parent: Order, *, params: dict) -> AsyncIterator[Order]:
"""Execute parent order via this algorithm. Yields child orders."""
Algorithms own slice sizing + timing + child order types. OMS owns state, idempotency, broker routing per child.
Algorithms
VWAP
from mts1b_oms_algos.vwap import execute
async for child in execute(parent_order, params={
"horizon_minutes": 30,
"volume_profile": "intraday_estimated", # or "uniform"
"max_participation": 0.10, # cap at 10% of bar volume
"child_order_type": "limit", # or "marketable_limit"
}):
await oms.submit(child)
TWAP
from mts1b_oms_algos.twap import execute
async for child in execute(parent_order, params={
"horizon_minutes": 30,
"n_slices": 30,
"jitter_pct": 0.2, # ±20% jitter on slice timing
"child_order_type": "limit",
}):
await oms.submit(child)
POV — Participation of Volume
from mts1b_oms_algos.pov import execute
async for child in execute(parent_order, params={
"target_participation": 0.15,
"max_horizon_minutes": 120,
"volume_lookback_minutes": 5,
}):
await oms.submit(child)
Iceberg
from mts1b_oms_algos.iceberg import execute
async for child in execute(parent_order, params={
"display_qty": Decimal("100"),
"refill_threshold": Decimal("50"),
"limit_price": Decimal("180.50"),
}):
await oms.submit(child)
Almgren-Chriss
from mts1b_oms_algos.almgren_chriss import execute
async for child in execute(parent_order, params={
"horizon_minutes": 30,
"risk_aversion": 1.0,
"volatility": 0.18, # annualized vol
"permanent_impact": 0.1, # bps per unit of parent size
"temporary_impact": 5.0, # bps per unit of slice size
}):
await oms.submit(child)
Implementation Shortfall (IS)
from mts1b_oms_algos.is_ import execute
async for child in execute(parent_order, params={
"arrival_price": Decimal("180.50"),
"risk_aversion": 1.0,
"max_horizon_minutes": 60,
"urgency": "medium", # low | medium | high
}):
await oms.submit(child)
When to use which
| Scenario | Algorithm |
|---|---|
| Standard rebalance, moderate size | vwap |
| Schedule-driven, want predictable timing | twap |
| Liquidity-driven, fraction-of-flow | pov |
| Hide block size | iceberg |
| Optimal impact-vs-timing tradeoff | almgren_chriss |
| Urgent — beat arrival price | is_ |
| Tiny order (under threshold) | None — direct submit to broker |
Algorithm dispatch by name
from mts1b_oms_algos import ALGO_REGISTRY
algo = ALGO_REGISTRY["vwap"]
async for child in algo(parent_order, params={"horizon_minutes": 30}):
await oms.submit(child)
Risk
Child orders go through the full OMS pipeline — same risk gates as any order. The algorithm only decides the slice schedule; OMS still:
- Dedupes via
idempotency_key - Calls
riskengine.CheckOrderper child - Routes to the broker
A faulty algorithm cannot bypass risk; worst case it generates too many child orders → riskengine rejects the excess.
Child idempotency keys
Each child gets a key derived from the parent + slice index:
child_key = f"{parent.idempotency_key}-slice-{i:03d}"
This makes the algorithm replay-safe across crashes.
TCA hooks (Wave 2)
Post-trade, each algorithm can emit metrics to compare actual vs benchmark:
async for child in execute(parent_order, params={..., "emit_tca": True}):
...
# Published to mts.v1.oms.algos.tca:
# {algo: "vwap", parent_id: ..., avg_fill_price: ..., vwap_benchmark: ...,
# slippage_bps: ..., timing_cost_bps: ...}
See also
repos/oms-algosfoundation.orders.Order- Cookbook — Options hedging — uses IS to enter quickly