Skip to content
Published on

Securities MTS/HTS Developer: Exchange Protocols to Microsecond Latency

Authors

Who's this for

This piece targets junior developers entering securities IT roles (MTS, HTS, OMS, exchange gateways) and 5-10 year experienced engineers thinking of moving from fintech or adjacent domains into a brokerage. JD lines like "experience with high-throughput systems" and "real-time market data" are abstract until you map them to specific protocols, latency numbers, and failure patterns - that's what this article unpacks. Don't stop at memorizing company names; build the muscle to know which keyword to search when you open a one-page exchange spec.

Why MTS/HTS development is "handling things"

A securities IT engineer is not just building screens. The actual things being handled are three layers.

First, the market. The moment KRX regular session opens at 09:00, tens of thousands of orders rush in simultaneously. Between 09:00:00.000 and 09:00:00.500 (500ms), the OMS has to traverse order-book residuals, price-time priority, and call-auction matching logic before forwarding to the exchange.

Second, protocols. KRX EXTURE+ uses its proprietary binary protocol KRX UMS; the global standard is FIX 4.4/5.0. Nasdaq uses ITCH (market data) / OUCH (orders); TSE uses Arrowhead's proprietary binary frame. You deal with message frame layouts, sequence number processing, and gap-fill logic for all of these.

Third, systems. From the front (MTS/HTS app) through API Gateway to Order Router to OMS to Exchange Gateway is 6-7 hops, and latency must stay under 50ms for retail to feel snappy. HFT pushes tick-to-trade down to <100μs.

"Handling" really means making trade-offs across these three layers, every single day.

System architecture overview

A typical Korean brokerage trading system is a 5-tier architecture.

  1. Client tier: MTS (iOS/Android, React Native or native), HTS (Windows C++/.NET native), Web Trading (React/Vue)
  2. Gateway tier: API Gateway (Nginx/Envoy + custom auth), WebSocket Gateway (market data push), MQTT broker (mobile push)
  3. Middleware tier: Order Router, Risk Engine, Position Manager, Account Service - Java Spring Boot or C++ low-latency
  4. Backend tier: OMS, EMS, market data distribution engine, settlement system
  5. Exchange Gateway tier: KRX gateway, KOSCOM backbone connection, ATS link, FIX gateways to overseas exchanges

Between each tier sits a messaging middleware: Kafka, Solace, Tibco RV, Aeron. Korean brokerages tend toward Kafka + Redis; global IBs lean Solace or Tibco.

Core protocols: FIX 4.4/5.0, FAST, ITCH/OUCH, Arrowhead, KRX UMS, ISO 20022

"Have you worked with FIX?" in a securities IT interview is a serious question. The standard protocols:

  • FIX 4.4/5.0: Financial Information eXchange. ASCII tag=value SOH-delimited messages. De facto standard for global IB and overseas equity routing
  • FIX FAST: Binary-compressed FIX for market data, saves bandwidth
  • ITCH/OUCH: Nasdaq market data (ITCH) / orders (OUCH). Binary protocol, low-latency optimized
  • Arrowhead: TSE proprietary protocol. Introduced in 2010, now at 5th generation (Arrowhead Renewal 2024)
  • KRX UMS: Korea Exchange standard message protocol. Binary frame with own sequence number management
  • ISO 20022: XML message standard for payment/clearing/settlement. SWIFT next-gen, KSD (Korea Securities Depository) adopting

FIX is human-readable, easy to debug. ITCH/OUCH is binary so you need the wire-format spec and Wireshark dumps.

A real day

Operations runs on market hours.

  • 07:00 In the office. Check overnight batch (T-1 settlement, corporate actions, FX translation). Review exchange notices (KRX MDS, KOSCOM scheduled maintenance)
  • 07:30 Pre-market single price (07:30-08:30) kicks off; order books warm up
  • 08:30 Regular session call auction (08:30-09:00). Order-book depth explodes
  • 09:00 Regular session opens. The first minute can be 5-10% of daily volume. Watch OMS/EMS throughput, latency
  • 10:00 Daily stand-up. Yesterday's incident review, today's release plan
  • 13:00 Exchange spec review. KRX next-gen changes, new instruments (ETN, ETF, security tokens)
  • 15:30 KRX regular session closes. After-market single price (15:40-16:00), after-market closing price (15:40-15:50)
  • 16:00 US pre-market prep. Verify overseas equity gateways
  • 18:00 Korean release window. MTS deployments are typically Tue/Thu evenings or Saturday dawn
  • 21:30 US regular session opens (22:30 under DST). Night team takes over
  • 05:00 US regular session closes. Batch begins

No releases during market hours. Change Freeze policy is strict.

Smart Order Router

A Smart Order Router (SOR) splits a single order across multiple venues. Korea historically had a single-venue market with KRX, so SOR demand was low, but with the launch of the Nextrade ATS in 2025 it's becoming serious.

What an SOR weighs:

  • Price (Best Bid/Offer): which venue has the better quote
  • Available quantity: how much can fill at once
  • Fee: venue-by-venue fee differences
  • Latency: which venue responds faster
  • Market impact: split large orders to minimize price impact

SOR is typically built in C++ or Java Aeron. Decision logic runs in microseconds; GC pauses are not allowed.

Korean exchanges: KRX KOSPI/KOSDAQ, ATS, Nextrade

Korea historically operated under a single-exchange regime with KRX running KOSPI, KOSDAQ, and KONEX. That changed with the 2025 launch of Nextrade ATS.

  • KRX EXTURE+: KRX's current matching engine. Introduced 2014, response time around 70μs
  • KOSCOM: KRX subsidiary running the brokerage backbone network. Provides the EXTURE+ access gateway
  • Nextrade: Korea's first Alternative Trading System, launched 2025. Trading outside regular hours (intraday/overnight)

Brokerage gateways connect to KRX via KOSCOM circuits. Circuits are dual-routed and reach KOSCOM's Busan backup data center.

Japanese exchanges: TSE Arrowhead, JPX, PTS

The Japanese market is unified under JPX (Japan Exchange Group), which consolidated TSE (Tokyo Stock Exchange) and OSE (Osaka Securities Exchange).

  • TSE Arrowhead: Next-gen matching system introduced 2010. 5th-gen (Arrowhead Renewal 2024) response time around 200μs
  • JPX: Holding company over TSE, OSE, and JPX Clearing. TOPIX and Nikkei 225 sit here
  • PTS (Proprietary Trading System): Japan's ATS. SBI Japannext and ODX (Cboe Japan, ex-Chi-X Japan) are the main names
  • ToSTNeT: TSE's off-exchange system. Used for block trades and single-price auctions

Japanese brokers handle the TSE FLEX protocol (proprietary binary); global IBs in Japan use FIX 4.4 + FIX FAST.

Latency budgets: tick-to-trade <100μs HFT vs <10ms retail

Latency targets vary by segment.

  • HFT (High Frequency Trading): tick-to-trade <100μs. From quote receipt to order send within 100 microseconds. Colocation at the exchange, FPGA acceleration, kernel bypass (DPDK, Solarflare OpenOnload)
  • Algo trading (in-house broker algos): 1-10ms. Java Aeron, Chronicle Queue, off-heap memory
  • Retail MTS: 50-200ms. Mobile network latency dominates. Backend itself targets <10ms
  • Retail HTS: 30-100ms. Desktop direct connection beats mobile

HFT doesn't tolerate even a 5ms GC pause in Java. People use pauseless GC like Zing JVM, Azul Platform Prime, or rewrite in C++/Rust.

Korean tech stack: Java/Spring Boot, Kafka, Redis, Cassandra, kdb+, C++

Korean brokerage IT stacks tend to look like this.

  • Languages: Java 17/21 (Spring Boot 3.x), C++ (low-latency cores), Python (data/ML)
  • Frameworks: Spring Boot, Spring Cloud, Netty (WebSocket), occasionally Akka
  • Messaging: Apache Kafka (primary), Redis Pub/Sub, RabbitMQ (legacy)
  • Cache: Redis (order state, order-book cache), Hazelcast (distributed cache)
  • DB: Oracle (legacy ledger), PostgreSQL (new), MySQL, MariaDB
  • Time-series DB: kdb+ (market data standard), InfluxDB, TimescaleDB
  • NoSQL: Cassandra (order logs), MongoDB (customer behavior)
  • Infrastructure: VMware -> Kubernetes migration in progress, segregated internal network
  • Monitoring: Grafana + Prometheus, ELK, Datadog

Mirae Asset, Korea Investment, Samsung, KB lean Java/Spring. C++ low-latency cores show up only in select OMS/EMS components.

Global / Japan tech stack: C++/Java, Aeron, Chronicle, Solace, Tibco RV

Global IBs (Goldman, JPM, MS, Citi) and large Japanese brokers (Nomura, Daiwa, SBI) differ from the Korean stack.

  • Languages: C++17/20 (EMS/OMS cores), Java (LMAX Disruptor, Aeron, Chronicle), Rust (new projects)
  • Low-latency libs: Aeron (UDP-based messaging), Chronicle Queue (off-heap persistent queue), LMAX Disruptor (lock-free ring buffer)
  • Messaging: Solace PubSub+ (global IB standard), Tibco Rendezvous (legacy), Kafka (enterprise data pipelines)
  • Time-series: kdb+ (virtually every global IB), Onetick
  • OS: Linux (RHEL/Rocky), some Solaris (legacy)
  • Network: Solarflare/Mellanox NICs, kernel bypass (OpenOnload, DPDK), Arista switches

Big Japanese brokers run similar stacks. Their in-house standards skew conservative so Java is dominant; C++ shows up only on select trading desks.

Security: PKI, biometrics, OTP, 2FA, FIDO2, network segregation, ISMS-P, FISC

Two axes: user authentication and network security.

  • Korean PKI certificates: After Korea retired the official "gongin" certificate in 2020, it forked into the Financial Certificate and the Joint Certificate
  • Biometrics: Fingerprint (Touch ID), Face ID, voice. Tied to mobile device keychain
  • OTP/2FA: HOTP/TOTP, SMS auth, Kakao auth, PASS app
  • FIDO2: WebAuthn-based, global standard. Korea has been expanding adoption since 2023
  • Network segregation: A mandate in Korean finance. Business net and internet net are physically separated; developers carry two laptops
  • ISMS-P: Korea's information security certification. Annual renewal
  • FISC safety standards: Japan FISC standards. Mandatory for Japanese financial institutions

Because of segregation, Korean brokerage devs can't access GitHub.com directly. They use internal GitLab/Bitbucket and pull OSS through a proxy like Nexus.

Korean brokerage IT: Mirae Asset, KIS, Samsung, KB, Shinhan

Korean brokerage IT splits into in-house vs SI-outsourced models.

  • Mirae Asset Securities: Strong in-house. M-STOCK app developed internally. Digital Innovation HQ under CIO
  • Korea Investment Securities (KIS): Mix of in-house and outsourced. Operates KIS ICT subsidiary
  • Samsung Securities: In-house. Some Samsung SDS collaboration. mPOP app
  • KB Securities: Heavy outsourcing. Some KB Datasystems collaboration. M-able app
  • Shinhan Investment: Mix of in-house and outsourced. Collaborates with Shinhan DS (group IT subsidiary)
  • NH Investment: Works with NongHyup IT
  • Kiwoom: Strong in-house. Largest retail market share in Korea; HeroMoon HTS/MTS built internally

Fresh-grad hiring at Mirae, KIS, Samsung, KB runs in the double-digits each year. SI outsourcing names: LG CNS, Samsung SDS, KOSCOM, KIS ICT, Shinhan DS.

Japanese brokerage IT: SBI, Rakuten, Matsui, Nomura, Daiwa + Toss STARTRADE, Kakao Pay Securities KakaoStock

Japan has a long-established / newcomer split.

  • Nomura: Japan's largest, runs a trading platform on par with global IBs. Distributed Tokyo/Hong Kong/London/New York
  • Daiwa: Strong in-house, Daiwa Securities Group ICT subsidiary
  • SBI Securities: #1 internet broker. Under SBI Holdings. Runs its own ATS, SBI Japannext
  • Rakuten Securities: Strong mobile trading with Rakuten group synergy
  • Matsui Securities: Pioneer of Japan's online brokerage (1998 internet pivot)
  • Monex: Strong in US markets. Acquired TradeStation in the US

Korean newcomers: Toss Securities (STARTRADE system) and Kakao Pay Securities (KakaoStock app). Toss Securities operates its own OMS in-house; Kakao Pay Securities runs a custom front on KIS ICT's backend.

AI/ML applications: fraud detection, KYC OCR, chatbots, stock recommendations

Five common AI/ML applications in brokerages.

  1. Fraud Detection System (FDS): Detection of nominee accounts, wash trades, market manipulation, pump-and-dump. Graph Neural Networks, anomaly detection
  2. KYC: ID document OCR, face recognition, liveness checks. AWS Textract, GCP Vision API
  3. Chatbots: Balance lookup, order history, market info. LLM-based (GPT-4o, Claude, HyperCLOVA X)
  4. Stock recommendations: Portfolio analysis, similar-customer purchase recommendations. Collaborative Filtering, Matrix Factorization
  5. Algo trading signals: Price patterns + volume + fundamentals. XGBoost, LSTM, Transformer

AI is often a separate org (Mirae's AI Lab inside Digital Innovation HQ, KIS's AI Task Force). Trading system developers more often integrate AI team outputs than build models themselves.

Failure cases: Samsung Securities 2018 employee stock incident, Knight Capital 2012, KOSCOM 2008

Failure cases every securities IT engineer should memorize.

  • 2018 Samsung Securities employee stock incident: A 2.8 billion KRW cash dividend on employee shares was wrongly entered as 2.8 billion shares. Some employees actually sold, causing market shock. Caused by missing input validation and limit checks
  • 2012 Knight Capital (US): A new deployment reused a deprecated flag; 45 minutes of erroneous orders cost the firm 460M USD and pushed it into bankruptcy. SDLC deployment process failed
  • 2008 KOSCOM matching system outage: KOSDAQ market data distribution went down for about an hour. Backup system failover failed
  • 2010 Flash Crash (US): A single mutual fund's large sell caused the Dow to drop ~1000 points in 9 minutes. Algorithmic trading cascade
  • 2020 Robinhood outage: US retail trading app went down for hours during a volatility spike. Capacity planning failure

The common thread: input validation, limit checks, deployment process, or backup procedures broke somewhere.

20 interview questions

Twenty common questions for securities IT interviews.

  1. Difference between FIX 4.4 MsgType=D (NewOrderSingle) and MsgType=8 (ExecutionReport)?
  2. Explain the responsibility split between OMS and EMS
  3. Recovery procedure when a sequence number gap occurs?
  4. How would you represent the order book in memory? Data structure and time complexity
  5. Idempotency key design to prevent duplicate orders
  6. Which Java GC and config to guarantee a <5ms pause?
  7. Solving hot partition when Kafka partition key is the ticker
  8. Memory estimation and eviction policy for a Redis order-book cache
  9. Lock-free queue implementations in low-latency settings (SPSC, MPMC)
  10. How do you bring in external OSS in a network-segregated environment?
  11. Price-time priority of the 09:00:00 call auction
  12. Margin loan vs stock loan differences and what data the IT system tracks
  13. Forced liquidation algorithm when a margin call goes unmet
  14. FX handling for 24-hour US equity trading (pre-market, after-market)
  15. Backpressure handling when pushing market data over WebSocket
  16. Corporate-action handling: stock splits, bonus issues, dividends and auto-adjustment of positions
  17. Difference in exchange messages for Market Order vs Limit Order
  18. How options-expiry index SQ (Special Quotation) is calculated
  19. Implementation of ETF Liquidity Provider (LP) quoting obligations
  20. Differences between TWAP, VWAP, IS, and POV algo strategies

The interviewer is watching how you reason when you don't know. Don't just say "I don't know"; instead say "I'm not sure about this, but if I reason from principle X..."

Compensation

Approximate ranges (2025, base + incentive).

  • Korea fresh-grad (major broker): 50-65M KRW base. Incentive 3-10M KRW
  • Korea 5-year: 70-90M KRW. Incentive 5-20M KRW
  • Korea 10-year senior: 100-130M KRW. Bonus swings widely
  • Korea team lead: 130-180M KRW. Some 150M+ KRW
  • Korea executive (CTO-class): 200-500M KRW+
  • Japan fresh-grad (SBI, Rakuten): 5-7M JPY
  • Japan 5-year: 7-10M JPY
  • Japan senior (Nomura, Daiwa): 10-13M JPY
  • US first-year (IB tech): $120K-150K base, 30-50% bonus
  • US senior (VP): $300K-500K total comp

HFT / algo trading quant dev is a separate market. US Citadel / Two Sigma / Jane Street fresh-grad packages are $400K+; seniors can clear $1M+.

Career path: Junior Dev to Senior to Tech Lead to Architect to CTO

A typical brokerage IT career.

  • Junior Developer (1-3 years): Screen/API work, bug fixes, unit tests. Paired closely with a senior mentor
  • Mid-level (4-6 years): Module-level design, leads new features. Reviews exchange specs directly
  • Senior (7-10 years): Full system design, incident owner. Mentors juniors
  • Tech Lead (10-13 years): Tech decisions for the team, code review responsibility, hiring
  • Principal/Staff Engineer: Firm-wide direction, architecture decisions. Title varies by firm
  • Architect: Cross-tier design, new system adoption decisions (Kafka to Pulsar style)
  • CTO/CDO: Executive. Participates in business decisions

Lateral moves are common. Brokerage to fintech (Toss, Kakao Pay), brokerage to exchange (KRX/KOSCOM), brokerage to global IB (GS, JPM, MS Korea office).

References

Cited references. Better than re-reading these once: bookmark them and skim every new spec release weekly.

# FIX 4.4 ExecutionReport handler example
# In production use a vetted library like QuickFIX/J or onixs

import quickfix as fix
import quickfix44 as fix44

class TradingApp(fix.Application):
    def onMessage(self, message, sessionID):
        msg_type = fix.MsgType()
        message.getHeader().getField(msg_type)

        if msg_type.getValue() == fix.MsgType_ExecutionReport:
            self.handle_execution_report(message, sessionID)

    def handle_execution_report(self, message, sessionID):
        exec_type = fix.ExecType()
        ord_status = fix.OrdStatus()
        order_id = fix.OrderID()
        cl_ord_id = fix.ClOrdID()
        symbol = fix.Symbol()
        side = fix.Side()
        last_qty = fix.LastQty()
        last_px = fix.LastPx()
        cum_qty = fix.CumQty()
        avg_px = fix.AvgPx()

        message.getField(exec_type)
        message.getField(ord_status)
        message.getField(order_id)
        message.getField(cl_ord_id)
        message.getField(symbol)
        message.getField(side)

        # ExecType=F (Trade) -> fill
        if exec_type.getValue() == fix.ExecType_TRADE:
            message.getField(last_qty)
            message.getField(last_px)
            message.getField(cum_qty)
            message.getField(avg_px)

            print(f"[FILL] Order={order_id.getValue()} "
                  f"ClOrdID={cl_ord_id.getValue()} "
                  f"Symbol={symbol.getValue()} "
                  f"Side={side.getValue()} "
                  f"LastQty={last_qty.getValue()} "
                  f"LastPx={last_px.getValue()} "
                  f"CumQty={cum_qty.getValue()} "
                  f"AvgPx={avg_px.getValue()}")

            # Propagate fill to OMS, Position Manager, Risk Engine
            self.publish_to_kafka("fills.equity.kospi", {
                "order_id": order_id.getValue(),
                "symbol": symbol.getValue(),
                "qty": last_qty.getValue(),
                "px": last_px.getValue(),
            })

        # OrdStatus=8 (Rejected) -> exchange rejection
        elif ord_status.getValue() == fix.OrdStatus_REJECTED:
            ord_rej_reason = fix.OrdRejReason()
            message.getField(ord_rej_reason)
            print(f"[REJECT] Order={order_id.getValue()} "
                  f"Reason={ord_rej_reason.getValue()}")
            self.alert_oms_reject(order_id.getValue(), ord_rej_reason.getValue())
# Smart Order Router decision logic (simplified)
# Real SORs need microsecond latency and are written in C++ or Java Aeron

from dataclasses import dataclass
from typing import List

@dataclass
class Venue:
    name: str          # KRX, Nextrade, NYSE, etc.
    best_bid: float
    best_ask: float
    bid_qty: int
    ask_qty: int
    latency_us: int    # microseconds
    fee_bps: float     # basis points

@dataclass
class Order:
    symbol: str
    side: str          # BUY or SELL
    qty: int
    limit_price: float

def route_order(order: Order, venues: List[Venue]) -> List[dict]:
    """
    Split a single order across venues.
    Priority: price > fee-adjusted net price > latency
    """
    routes = []
    remaining_qty = order.qty

    # BUY against ask, SELL against bid
    if order.side == "BUY":
        candidates = [v for v in venues if v.best_ask <= order.limit_price and v.ask_qty > 0]
        # net price = quote + fee
        candidates.sort(key=lambda v: (
            v.best_ask * (1 + v.fee_bps / 10000),
            v.latency_us,
        ))

        for venue in candidates:
            if remaining_qty <= 0:
                break
            fill_qty = min(remaining_qty, venue.ask_qty)
            routes.append({
                "venue": venue.name,
                "qty": fill_qty,
                "price": venue.best_ask,
            })
            remaining_qty -= fill_qty
    else:  # SELL
        candidates = [v for v in venues if v.best_bid >= order.limit_price and v.bid_qty > 0]
        candidates.sort(key=lambda v: (
            -v.best_bid * (1 - v.fee_bps / 10000),
            v.latency_us,
        ))
        for venue in candidates:
            if remaining_qty <= 0:
                break
            fill_qty = min(remaining_qty, venue.bid_qty)
            routes.append({
                "venue": venue.name,
                "qty": fill_qty,
                "price": venue.best_bid,
            })
            remaining_qty -= fill_qty

    if remaining_qty > 0:
        # Park remainder as resting limit on the best venue
        routes.append({
            "venue": candidates[0].name if candidates else "KRX",
            "qty": remaining_qty,
            "price": order.limit_price,
            "type": "LIMIT_RESTING",
        })

    return routes
# KRX gateway connection configuration example
# In production separate secrets via vault and PKCS#12 certificates

krx_gateway:
  environment: production
  member_code: "001"          # broker member number
  participant_id: "PROD001"

  primary:
    host: ums-primary.koscom.co.kr
    port: 30443
    ssl: true
    cert_path: /opt/secrets/krx-prod.p12
  backup:
    host: ums-backup.koscom.co.kr
    port: 30443
    ssl: true
    cert_path: /opt/secrets/krx-prod.p12

  session:
    heartbeat_interval_sec: 30
    logon_timeout_sec: 10
    sequence_reset_on_logon: false
    max_messages_per_sec: 5000
    reconnect_attempts: 5
    reconnect_delay_sec: 2

  order_limits:
    max_order_qty: 1000000
    max_order_value_krw: 10000000000  # 10 billion KRW
    max_orders_per_second: 1000

  market:
    kospi_open: "09:00:00"
    kospi_close: "15:30:00"
    pre_market_open: "08:30:00"      # call auction
    after_market_close: "16:00:00"   # after-market single price
    timezone: Asia/Seoul

  monitoring:
    metrics_endpoint: http://prometheus.internal:9090
    alert_channel: "#trading-prod-alerts"
    latency_alert_threshold_ms: 50
    rejected_orders_threshold_per_min: 100