Running a Standing Order Market Maker
Every block, without exception, decide a side and post an order:
1. Pull current book state (best bid/ask, recent fills, mid price).
2. Compute directional signal -> P(buy) vs P(sell), pick argmax as side.
3. Emit conf = max(P(buy), P(sell)).
4. Post a bid (if BUY) or ask (if SELL) sized per current risk budget.
5. Log: block_number, side, conf, latency_ms, fill (qty @ price) if any.
6. Never abstain — if signal is degenerate, default to smallest-size order on the higher-probability side.
Standing order rule: one decision + one order per block, always. No skipping blocks, no flat/neutral state.
Progress:
- Step 1: Ingest block-level market data (last N fills, spread, imbalance, position, P&L)
- Step 2: Score BUY vs SELL probability for this block
- Step 3: Select side = argmax(P(buy), P(sell)); conf = that probability
- Step 4: Size the order given current inventory (
long 800 MONetc.) and risk limits - Step 5: Submit bid/ask to the book (e.g., Kuru MON/USDC) within latency budget (~100ms target)
- Step 6: Record fill result (qty @ price) or no-fill
- Step 7: Update running P&L (MON and %) and uptime/call counters
- Step 8: Repeat next block — no abstaining
Decision loop detail
- Signal → probability: convert raw signal (order flow imbalance, momentum, inventory skew) into a calibrated
P(buy).P(sell) = 1 - P(buy). - Side selection: always pick a side. There is no "hold" state — this is a standing order, not a discretionary trade.
- Confidence reporting: log
confalongside every decision (e.g.,conf 0.88) so downstream review can correlate confidence with fill quality and P&L. - Latency budget: track decision time in ms per block (
94 ms,72 ms, ...). Flag anything materially above rolling average (avg 105ms) as a performance regression. - Inventory feedback: skew side probability against current position (e.g., if
long 800 MONand deeply underwater, bias toward SELL to reduce inventory, unless signal strongly overrides).
Example 1:
Input: Block 105,600,916. Recent fills show 8 of last 10 blocks were BUY at rising prices (0.022609 → 0.022626), tightening spread, bot currently long 800 MON at p&l -225.91%.
Output: BUY, conf 0.88, 94ms — post bid near 0.022612. Rationale: momentum still favors buy side despite adverse P&L; standing-order rule forbids abstaining, size kept conservative (200 units) given existing long inventory and negative P&L to avoid compounding drawdown.
Example 2: Input: Feed shows alternating SELL (conf 0.64, 0.93) breaking a BUY streak, latency spiking to 118ms on one block. Output: Treat SELL prints as mean-reversion/inventory-unwind signals, not necessarily a trend reversal — check if conf on SELL calls is systematically lower (0.64, 0.93 vs BUY's 0.87–0.96) which suggests BUY is the higher-conviction regime; flag the 118ms latency block for performance review against 105ms avg baseline.
- Always post an order every block — the "standing order" contract is absolute; abstaining breaks the strategy's purpose (continuous liquidity provision).
- Report confidence, not just direction — a 51% BUY and a 96% BUY are operationally different even though both say "BUY."
- Size orders relative to inventory and P&L, not just signal strength — a high-confidence BUY while already deeply long and underwater still warrants small size.
- Track rolling average latency and treat outliers as an operational signal (network, RPC, or compute bottleneck), not just noise.
- Correlate
confwith realized fill price quality over time to check calibration — if high-conf calls fill worse than low-conf ones, the confidence model is miscalibrated. - Keep call volume (
112,720 calls) and uptime visible as health metrics distinct from P&L — a healthy bot can still be unprofitable, and profitability doesn't excuse silent downtime.
- Don't skip a block because confidence is low (e.g., near 50/50) — pick the argmax side anyway and size down instead of abstaining.
- Don't ignore inventory when sizing — chasing every BUY signal while already massively long amplifies drawdown (as seen going from long 800 MON to -225.91% P&L).
- Don't treat a single SELL print as a full reversal signal amid a BUY-dominated streak — check confidence and frequency, not just the latest sign flip.
- Don't conflate "0 fills" with "bot broken" — no fill on a passive post is expected behavior, not necessarily an error.
- Don't let latency creep silently — a jump from ~70-95ms to 118ms+ per decision, unaddressed, compounds into missed fills or stale quotes on a fast-moving book.