KRX Volatility Interruption (VI)-Aware Order Router Playbook
Date: 2026-02-25 (KST)
TL;DR
If you treat KRX VI as “just another market event,” live automation will eventually send the right order at the wrong micro-state.
This playbook turns VI into explicit execution state:
- Detect whether the symbol is in normal matching or 2-minute VI single-price mode
- Shift from spread capture to uncertainty control (smaller clips, wider patience, stricter caps)
- Resume with a re-entry protocol after VI ends (no immediate overreaction chase)
Goal: reduce avoidable slippage spikes and reject loops during high-volatility transitions.
1) Why this matters in KR live trading
KRX VI is a built-in per-symbol volatility brake. For execution engines, the key point is not theory but mechanics:
- Matching mode changes temporarily (continuous -> single-price style)
- Queue and fill behavior change discontinuously
- Repeated VI triggers can happen intraday (no simple "once and done")
So routing logic must be stateful, not a static “submit and retry” loop.
2) What to encode from official rules
Based on KRX regulation pages (유가증권시장 종목별 변동성완화장치):
- VI cooling period: 2-minute single-price trading window
- Types:
- Dynamic VI: abrupt movement from specific order impact
- Static VI: cumulative/larger movement pressure
- Trigger reference differs by type (latest execution vs single-price reference)
- No daily cap on VI trigger count
- Some overlap/collision rules apply with other stabilization mechanisms (e.g., CB precedence)
Implementation takeaway:
Never hardcode “VI should be rare.” Design for repeated transitions.
3) Session-aware trigger map (practical baseline)
KRX documents separate trigger-rate bands by product/session bucket (e.g., KOSPI200 vs 일반종목, regular vs closing single-price windows). Treat these as configuration data, not constants in strategy code.
Recommended config shape:
viTriggerTable:
version: "krx-vi-2026-02"
equity:
kospi200:
regular: 0.03
closeAuction: 0.02
afterHoursSinglePrice: 0.03
general:
regular: 0.06
closeAuction: 0.04
afterHoursSinglePrice: 0.06
static:
default: 0.10
Why config-first:
- rule updates happen
- market segment expansion happens
- ATS/venue policy interaction can evolve
4) Execution state machine (minimum viable)
Use a symbol-level state machine:
- NORMAL
- continuous matching assumptions valid
- standard participation controls
- VI_ACTIVE
- 2-minute single-price mode assumptions
- clip-size reduction + aggression cap tightening
- VI_RECOVERY (30–180s after release, tune by symbol)
- reopen shock buffer
- gradual participation restore
Transition examples:
NORMAL -> VI_ACTIVEwhen VI flag/event is confirmedVI_ACTIVE -> VI_RECOVERYon VI end + first stable printsVI_RECOVERY -> NORMALwhen spread/markout/imbalance normalize
Add hysteresis so it does not flap under noisy flags.
5) Policy deltas by state
5.1 NORMAL
- keep baseline POV bounds
- normal passive TTL and cancel rhythm
5.2 VI_ACTIVE
- reduce max child qty (e.g., 30-70% cut by liquidity bucket)
- prohibit panic “catch-up” behavior
- stricter per-slice worst-price guard
- if residual pressure is high, switch objective to loss containment over schedule purity
5.3 VI_RECOVERY
- re-enter with stepped ramp (e.g., 25% -> 50% -> baseline)
- require short stabilization checks:
- spread compression
- reduced adverse markout burst
- sane fill/reject ratio
6) Venue fragmentation note (KRX + ATS era)
From FSC ATS rollout guidance (Nextrade launch context):
- KRX opening auction remains 08:30-09:00 (indicative display reduced window)
- KRX closing auction remains 15:20-15:30
- During KRX opening/closing auctions, Nextrade transactions are temporarily suspended
- Best-execution/SOR duties become more operationally important
For router design:
- maintain venue-state map and session-state map separately
- VI and auction states should be first-class inputs to SOR
- avoid stale assumptions copied from single-venue era
7) Data contract (implementation-ready)
interface ViSignal {
ts: string
symbol: string
venue: 'KRX' | 'NXT'
viType: 'DYNAMIC' | 'STATIC' | 'UNKNOWN'
phase: 'START' | 'END'
refPrice?: number
triggerRate?: number
}
interface SymbolExecState {
symbol: string
mode: 'NORMAL' | 'VI_ACTIVE' | 'VI_RECOVERY'
modeSince: string
recoveryStep?: number
reasonCodes: string[]
}
Audit rule:
- every order decision logs
(symbolMode, viFlag, sessionState, venueState) - this is mandatory for postmortem and regulator-facing explainability
8) Monitoring checklist
Track per symbol bucket:
- Slippage p95 during
VI_ACTIVEvs baseline - Reject/fill ratio around VI transitions
- Post-VI first-5-min markout distribution
- Number of repeated VI cycles per day
- Opportunity-cost drift from over-defensive behavior
Bad smell:
- low reject rate but exploding markout right after VI release
- this usually means router exits recovery state too early
9) Fast rollout plan
- Shadow mode: classify VI states, no behavior change
- Paper policy mode: simulate state-based caps/ramp
- Canary symbols: liquid names first
- Bucket rollout: by ADV/liquidity class
- Weekly tuning: recovery horizon, ramp pace, clip caps
References
- KRX Regulation (종목별 변동성완화장치): http://regulation.krx.co.kr/contents/RGL/03/03010409/RGL03010409.jsp
- FSC press release on ATS/Nextrade market structure updates (2025-02-05): https://www.fsc.go.kr/eng/pr010101/83967
- KRX data portal (VI trigger status datasets): http://data.krx.co.kr/
One-line takeaway
In KR live execution, VI is not an edge case—it is a state transition you must model explicitly, or your router will keep making “locally reasonable” decisions in globally wrong market mode.