Real-Time Stock Quotes via KIS WebSocket (H0STASP0/H0STCNT0)
TECH INSIGHT / EXPLAINED
Streaming quotes are useful only when the parser, subscription state, and freshness checks agree. KIS exposes distinct real-time channels; treat each as a versioned schema, not as an interchangeable array of numbers.
Separate trade prices from account fills
H0STASP0 is KRX order-book data; H0STCNT0 is KRX market trade data. Market trades do not confirm that your account order filled. Reconcile account execution notifications and order queries separately. Other venue/integrated channels have different identifiers, so choose the market intentionally.
The index error that changes a strategy
In the official H0STCNT0 sample field list, zero-based index 2 is STCK_PRPR, index 7 is STCK_OPRC, index 10 is ASKP1, and index 13 is ACML_VOL. Thus using 10 for the opening price or 13 for previous close is incorrect. Map a schema to field names, validate record length and numeric conversion, and reject nonfinite prices. Obtain previous close from its documented source rather than relabeling cumulative volume.
A parser contract to test
For a synthetic row with current price 70,100, opening price 70,000, best ask 70,200 and cumulative volume 45,678, the calculated change from open is (70,100/70,000−1)×100≈0.142857%. It must never use 70,200 or 45,678 as the baseline. Test truncated rows, empty fields, nonnumeric text, multiple records in one envelope and the correct TR before applying a schema. Log a redacted public-data fixture rather than authentication messages.
Desired subscriptions are not confirmed subscriptions
Track (TR, symbol, connection generation) as the key. Keep desired, pending, confirmed and rejected states separate; add to confirmed only after the documented acknowledgement. On reconnect, clear connection-local confirmations and restore desired subscriptions within current service limits. A fixed 50 ms delay is not a delivery guarantee.
Two clocks and one trading gate
Track last transport/heartbeat activity and last valid quote for each symbol separately. A quiet stock is not automatically a dead connection, and a heartbeat does not make an old quote fresh. Use market/session-aware thresholds measured for your application, not universal 30/60-second constants. Pause signals whose required inputs are stale; resume only after re-subscription and fresh validated data.
Separate frame interpretation from strategy input
When a receive callback immediately evaluates trading conditions, mixed control replies and market data become difficult to diagnose. Classify control messages, data frames, and unknown formats first. Decode with the selected TR schema, then enqueue only validated events. The official KIS common example treats system responses and PINGPONG separately. Follow the applicable example and channel rules for the actual heartbeat response format.
For multiple records, validate the advertised count against the expected schema width. Do not interpret an unfamiliar TR using the nearest-looking array or pass a truncated final record as a valid price. Quarantine failures with a reason and a bounded public-data sample. Authentication and account-notification payloads must not enter ordinary parser diagnostics.
Discard callbacks from an earlier connection
A subscription acknowledgement from connection 3 can arrive after connection 4 starts. Capture the connection generation in each callback and prevent older generations from changing current state. A new connection is confirmed only by acknowledgements associated with that connection. A delayed acknowledgement must also not restore a symbol already removed from the desired subscription set.
An educational replay sequence is: request subscription, disconnect, open a new connection, receive the old acknowledgement, receive the new acknowledgement, receive a fresh quote. The old acknowledgement must have no effect. The new acknowledgement alone must not satisfy quote freshness. Reevaluate dependent signals only after both subscription confirmation and valid new data are observed.
Distinguish latest-state inputs from event-complete inputs
If consumers fall behind, classify their requirements before allowing an unlimited queue. When a channel supplies complete current snapshots and the strategy only needs present state, updates may be coalesced into the latest value per symbol. A calculation that accumulates individual trades or depends on tick order changes when intermediate events are dropped. The two consumers therefore need different queue policies.
Field semantics matter too: CNTG_VOL and ACML_VOL in the KIS quote schema describe individual trade volume and cumulative volume. A cumulative difference cannot reconstruct every missing tick's time and price path. Determine whether historical queries can fill the required gap. If they cannot, reset the affected indicator or wait until enough fresh input has accumulated to make it valid again.
Replay session boundaries as well as prices
A time-only field needs market timezone, trading date, and session context. Blindly attaching the receiving PC's current date can misclassify delayed messages and session transitions. Preserve source-event time separately from local receipt time. Do not claim exact global ordering when the input lacks enough ordering information.
Replay public synthetic fixtures containing a valid frame, another TR, a record-count mismatch, an empty numeric field, a burst, and delayed callbacks during reconnection. Inspect strategy-event count, rejected-frame count, queue delay, and connection generation as well as calculated prices. Restored subscriptions do not establish that missing trades have been reconstructed. This procedure trains the local parser and state manager without opening a broker stream or submitting orders.
Documentation and next steps
Content and examples reviewed: 2026-10-01
댓글
댓글 쓰기