KRX Sidecar + Circuit Breaker Automation Runbook (KOSPI/KOSDAQ)

2026-02-25 ยท finance

KRX Sidecar + Circuit Breaker Automation Runbook (KOSPI/KOSDAQ)

Date: 2026-02-25 (KST)

TL;DR

For KR live trading, Sidecar and Circuit Breaker (CB) are not "market news"โ€”they are execution-state transitions.

If your bot keeps routing as if nothing changed, you get the classic failure combo:

This runbook turns KRX stabilization rules into implementable trading-engine behavior.


1) Rule facts you should encode (not memorize)

1.1 KOSPI Sidecar (program order effectiveness suspension)

From ์œ ๊ฐ€์ฆ๊ถŒ์‹œ์žฅ ์—…๋ฌด๊ทœ์ • ์ œ16์กฐ:

Release:

1.2 KOSDAQ Sidecar

From ์ฝ”์Šค๋‹ฅ์‹œ์žฅ ์—…๋ฌด๊ทœ์ • ์ œ13์กฐ:

1.3 Market-wide Circuit Breaker (CB)

From ์œ ๊ฐ€์ฆ๊ถŒ์‹œ์žฅ ์—…๋ฌด๊ทœ์ • ์ œ25์กฐ / ์ฝ”์Šค๋‹ฅ์‹œ์žฅ ์—…๋ฌด๊ทœ์ • ์ œ26์กฐ:

From each market ์‹œํ–‰์„ธ์น™(์œ ๊ฐ€ ์ œ39์กฐ, ์ฝ”์Šค๋‹ฅ ์ œ31์กฐ):


2) Execution architecture: split your state planes

Use separate but interacting state planes:

  1. Market-wide plane
    • NORMAL | CB_STAGE1_HALT | CB_STAGE2_HALT | CB_STAGE3_CLOSED
  2. Program-trading control plane
    • NONE | SIDECAR_BUY_BLOCK | SIDECAR_SELL_BLOCK
  3. Symbol execution plane
    • NORMAL | HALT_REOPEN_AUCTION | POST_HALT_RECOVERY

Do not reduce everything to one enum. You need composability for edge cases.


3) Router policy table (practical defaults)


4) Event ingestion design (donโ€™t trust one source)

Use at least two independent channels:

  1. Primary: exchange/member notice stream (or broker market-status feed)
  2. Secondary: deterministic local detector from index/futures ticks + rule thresholds

Why:

Recommended behavior:


5) Minimal state machine (pseudo)

type MarketState = 'NORMAL' | 'CB1_HALT' | 'CB2_HALT' | 'CB3_CLOSED'
type SidecarState = 'NONE' | 'BUY_BLOCK' | 'SELL_BLOCK'

onEvent(e):
  if e.type == 'CB_STAGE1_START': market = 'CB1_HALT'
  if e.type == 'CB_STAGE2_START': market = 'CB2_HALT'
  if e.type == 'CB_STAGE3_START': market = 'CB3_CLOSED'

  if e.type == 'CB_REOPEN':
    market = 'NORMAL'
    enterRecoveryWindow(symbol='*', minutes=10)

  if e.type == 'SIDECAR_BUY_START': sidecar='BUY_BLOCK'; setTimer(5m)
  if e.type == 'SIDECAR_SELL_START': sidecar='SELL_BLOCK'; setTimer(5m)
  if e.type == 'SIDECAR_END': sidecar='NONE'

preTradeCheck(order):
  if market in ['CB1_HALT','CB2_HALT','CB3_CLOSED']: reject_or_queue(order)
  if sidecar blocks order.programSide: reject_or_reroute(order)
  applyRecoveryCaps(order)

6) Failure patterns to test before live

  1. Duplicate event replay (idempotency check)
  2. Out-of-order events (END arrives before START)
  3. Clock skew around T-40m boundary
  4. Sidecar during post-CB recovery
  5. Feed stall with missing END (timer + heartbeat reconciliation)
  6. Stage progression with insufficient extra -1% (should not false-trigger stage2/3)

7) Monitoring KPIs

Track separately for normal vs stabilization windows:

Bad smell:


8) Implementation checklist (copy/paste)


References


One-line takeaway

Treat Sidecar/CB as hard execution-state transitions, not soft "market context"โ€”that single design choice is what prevents halt-day slippage blowups in KR live trading.