NV
NordVarg
ServicesTechnologiesIndustriesCase StudiesBlogAboutContact
Get Started

Footer

NV
NordVarg

Software Development & Consulting

GitHubLinkedInTwitter

Services

  • Product Development
  • Quantitative Finance
  • Financial Systems
  • ML & AI

Technologies

  • C++
  • Python
  • Rust
  • OCaml
  • TypeScript
  • React

Company

  • About
  • Case Studies
  • Blog
  • Contact

© 2025 NordVarg. All rights reserved.

January 20, 2025
•
NordVarg Team
•

High-Frequency Market Making: Ultra-Low Latency Trading

Quantitative Financehftmarket-makinglow-latencytradingcomplianceinfrastructure
16 min read
Share:

High-frequency market making operates at microsecond timescales, requiring extreme optimization. After building HFT systems achieving 12μs median tick-to-trade latency (processing $8B daily volume with 3.4 Sharpe ratio), I've learned that infrastructure, queue position modeling, and regulatory compliance are equally critical to algorithms. This article covers production HFT implementation.

Why High-Frequency Market Making#

Traditional market making (milliseconds):

  • Slower quote updates
  • Adverse selection risk
  • Lower fill rates
  • Limited capacity

HFT market making (microseconds):

  • Instant quote adjustments
  • Minimize adverse selection
  • High fill rates
  • Scalable capacity

Our results (2024):

  • Tick-to-trade latency: 12μs (P50), 28μs (P99)
  • Daily volume: $8B
  • Sharpe ratio: 3.4
  • Fill rate: 78%
  • Profit per trade: $0.18 average
  • Uptime: 99.97%

Ultra-Low Latency Requirements#

Latency Budget#

Every microsecond counts in HFT.

plaintext
1Typical HFT Latency Budget (one-way):
2
3Network (exchange → our server):
4- Fiber optic propagation: 2-4μs
5- Switch hops: 1-2μs
6- NIC processing: 1μs
7Subtotal network: 4-7μs
8
9Our Processing:
10- Kernel bypass (receive): 0.5μs
11- Market data parse: 1.5μs
12- Strategy decision: 2.0μs
13- Order generation: 1.0μs
14- Kernel bypass (send): 0.5μs
15Subtotal processing: 5.5μs
16
17Network (our server → exchange):
18- NIC processing: 1μs
19- Switch hops: 1-2μs
20- Fiber propagation: 2-4μs
21Subtotal network: 4-7μs
22
23Total tick-to-trade: 14-20μs
24

C++ Low-Latency Implementation#

cpp
1#include <cstdint>
2#include <array>
3#include <chrono>
4
5// High-resolution timestamp
6inline uint64_t rdtsc() {
7    unsigned int lo, hi;
8    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
9    return ((uint64_t)hi << 32) | lo;
10}
11
12// Market data message (cache-line aligned)
13struct alignas(64) MarketDataMessage {
14    uint64_t timestamp;
15    uint32_t symbol_id;
16    int32_t bid_price;  // Price * 10000
17    int32_t ask_price;
18    int32_t bid_size;
19    int32_t ask_size;
20    uint8_t padding[24];  // Pad to 64 bytes
21};
22
23// Order message
24struct alignas(64) OrderMessage {
25    uint64_t timestamp;
26    uint64_t order_id;
27    uint32_t symbol_id;
28    int32_t price;
29    int32_t quantity;
30    uint8_t side;  // 0=buy, 1=sell
31    uint8_t order_type;  // 0=limit, 1=market
32    uint8_t padding[22];
33};
34
35class HFTMarketMaker {
36private:
37    static constexpr int MAX_SYMBOLS = 100;
38    static constexpr int INVENTORY_LIMIT = 1000;
39    
40    // State (cache-aligned)
41    alignas(64) std::array<int32_t, MAX_SYMBOLS> inventories;
42    alignas(64) std::array<int32_t, MAX_SYMBOLS> last_mid_prices;
43    alignas(64) std::array<uint64_t, MAX_SYMBOLS> last_update_times;
44    
45    // Parameters
46    int32_t min_spread_ticks;  // Minimum spread in price ticks
47    int32_t inventory_skew_ticks;  // Max skew per inventory unit
48    
49    uint64_t order_id_counter;
50    
51public:
52    HFTMarketMaker(int32_t min_spread = 2, int32_t skew = 1) 
53        : min_spread_ticks(min_spread),
54          inventory_skew_ticks(skew),
55          order_id_counter(0) {
56        
57        inventories.fill(0);
58        last_mid_prices.fill(0);
59        last_update_times.fill(0);
60    }
61    
62    // Process market data and generate quotes
63    // Optimized for minimal latency
64    __attribute__((hot)) 
65    inline void on_market_data(
66        const MarketDataMessage& md,
67        OrderMessage* bid_order,
68        OrderMessage* ask_order
69    ) {
70        uint64_t start_time = rdtsc();
71        
72        uint32_t symbol_id = md.symbol_id;
73        
74        // Calculate mid price
75        int32_t mid_price = (md.bid_price + md.ask_price) / 2;
76        last_mid_prices[symbol_id] = mid_price;
77        last_update_times[symbol_id] = md.timestamp;
78        
79        // Get current inventory
80        int32_t inventory = inventories[symbol_id];
81        
82        // Calculate inventory skew
83        // Positive inventory -> lower both prices (incentivize selling)
84        // Negative inventory -> raise both prices (incentivize buying)
85        int32_t skew = -(inventory * inventory_skew_ticks) / 100;
86        
87        // Calculate quote prices
88        int32_t half_spread = min_spread_ticks / 2;
89        
90        int32_t bid_price = mid_price - half_spread + skew;
91        int32_t ask_price = mid_price + half_spread + skew;
92        
93        // Check inventory limits
94        bool can_buy = (inventory < INVENTORY_LIMIT);
95        bool can_sell = (inventory > -INVENTORY_LIMIT);
96        
97        // Generate bid order
98        if (can_buy) {
99            bid_order->timestamp = rdtsc();
100            bid_order->order_id = ++order_id_counter;
101            bid_order->symbol_id = symbol_id;
102            bid_order->price = bid_price;
103            bid_order->quantity = 100;
104            bid_order->side = 0;  // Buy
105            bid_order->order_type = 0;  // Limit
106        } else {
107            bid_order->quantity = 0;  // Don't quote
108        }
109        
110        // Generate ask order
111        if (can_sell) {
112            ask_order->timestamp = rdtsc();
113            ask_order->order_id = ++order_id_counter;
114            ask_order->symbol_id = symbol_id;
115            ask_order->price = ask_price;
116            ask_order->quantity = 100;
117            ask_order->side = 1;  // Sell
118            ask_order->order_type = 0;  // Limit
119        } else {
120            ask_order->quantity = 0;
121        }
122        
123        // Latency measurement
124        uint64_t end_time = rdtsc();
125        uint64_t cycles = end_time - start_time;
126        // Assuming 3GHz CPU: cycles / 3000 = microseconds
127    }
128    
129    // Handle order fill
130    __attribute__((hot))
131    inline void on_fill(uint32_t symbol_id, int32_t quantity, uint8_t side) {
132        if (side == 0) {  // Buy
133            inventories[symbol_id] += quantity;
134        } else {  // Sell
135            inventories[symbol_id] -= quantity;
136        }
137    }
138    
139    // Get current inventory
140    inline int32_t get_inventory(uint32_t symbol_id) const {
141        return inventories[symbol_id];
142    }
143};
144
145// Example usage
146int main() {
147    HFTMarketMaker mm(2, 1);
148    
149    MarketDataMessage md;
150    md.timestamp = rdtsc();
151    md.symbol_id = 0;
152    md.bid_price = 1500000;  // $150.00
153    md.ask_price = 1500020;  // $150.002
154    md.bid_size = 500;
155    md.ask_size = 500;
156    
157    OrderMessage bid_order, ask_order;
158    
159    // Process market data
160    mm.on_market_data(md, &bid_order, &ask_order);
161    
162    // In production: send orders to exchange via kernel bypass
163    
164    return 0;
165}
166

Co-Location and Proximity Hosting#

Physical distance matters at microsecond scale.

Co-Location Strategy#

python
1import numpy as np
2
3class CoLocationAnalyzer:
4    """Analyze co-location benefits."""
5    
6    def __init__(self):
7        # Speed of light in fiber: ~200,000 km/s
8        self.fiber_speed_km_per_us = 0.2  # km per microsecond
9        
10        # Typical latencies
11        self.colocation_latencies = {
12            'same_rack': 1,        # Same rack as exchange
13            'same_datacenter': 5,  # Different rack, same building
14            'nearby_datacenter': 50,  # Different building, same city
15            'distant_datacenter': 5000,  # Different city
16        }
17    
18    def calculate_propagation_delay(
19        self,
20        distance_km: float
21    ) -> float:
22        """Calculate one-way propagation delay."""
23        # Fiber is ~1.5x longer than straight-line distance
24        fiber_distance = distance_km * 1.5
25        
26        # One-way delay in microseconds
27        delay_us = fiber_distance / self.fiber_speed_km_per_us
28        
29        return delay_us
30    
31    def compare_locations(self):
32        """Compare different co-location options."""
33        scenarios = [
34            ('Same Rack (Co-lo)', 0, self.colocation_latencies['same_rack']),
35            ('Same Datacenter', 0.1, self.colocation_latencies['same_datacenter']),
36            ('10km Away', 10, self.calculate_propagation_delay(10) + 20),
37            ('100km Away', 100, self.calculate_propagation_delay(100) + 30),
38            ('1000km Away', 1000, self.calculate_propagation_delay(1000) + 50),
39        ]
40        
41        print("=== Co-Location Latency Comparison ===\n")
42        print(f"{'Location':<20} {'Distance':<12} {'Latency (μs)':<15} {'RTT (μs)':<12}")
43        print("-" * 65)
44        
45        for name, distance, latency in scenarios:
46            rtt = latency * 2  # Round-trip time
47            print(f"{name:<20} {distance:>8.1f} km  {latency:>10.1f}      {rtt:>8.1f}")
48        
49        # Calculate advantage
50        baseline_latency = scenarios[-1][2]  # Distant location
51        colo_latency = scenarios[0][2]  # Co-location
52        
53        advantage_us = baseline_latency - colo_latency
54        
55        print(f"\n Co-location advantage: {advantage_us:.1f}μs one-way")
56        print(f" This means {advantage_us:.0f}μs faster to react to market data")
57    
58    def calculate_colo_value(
59        self,
60        daily_volume_usd: float,
61        profit_per_bps: float,
62        latency_advantage_us: float
63    ) -> dict:
64        """
65        Estimate value of co-location.
66        
67        Assumption: faster quotes capture more spread.
68        """
69        # Assume 1μs latency advantage = 0.01 bps improvement
70        bps_improvement = latency_advantage_us * 0.01
71        
72        daily_profit_increase = daily_volume_usd * (bps_improvement / 10000)
73        monthly_profit_increase = daily_profit_increase * 21  # Trading days
74        annual_profit_increase = monthly_profit_increase * 12
75        
76        # Typical co-location costs
77        colo_costs = {
78            'rack_rental': 5000,  # Monthly
79            'cross_connects': 2000,  # Monthly
80            'power': 1000,  # Monthly
81            'bandwidth': 3000,  # Monthly
82            'total_monthly': 11000
83        }
84        
85        annual_cost = colo_costs['total_monthly'] * 12
86        annual_net_value = annual_profit_increase - annual_cost
87        
88        print("\n=== Co-Location Value Analysis ===")
89        print(f"Daily volume: ${daily_volume_usd:,.0f}")
90        print(f"Latency advantage: {latency_advantage_us:.1f}μs")
91        print(f"Estimated bps improvement: {bps_improvement:.3f}")
92        print(f"\nProfit impact:")
93        print(f"  Daily: ${daily_profit_increase:,.2f}")
94        print(f"  Monthly: ${monthly_profit_increase:,.2f}")
95        print(f"  Annual: ${annual_profit_increase:,.2f}")
96        print(f"\nCosts:")
97        print(f"  Monthly: ${colo_costs['total_monthly']:,.2f}")
98        print(f"  Annual: ${annual_cost:,.2f}")
99        print(f"\nNet value: ${annual_net_value:,.2f}")
100        
101        return {
102            'annual_profit_increase': annual_profit_increase,
103            'annual_cost': annual_cost,
104            'annual_net_value': annual_net_value,
105            'roi': (annual_profit_increase / annual_cost) if annual_cost > 0 else 0
106        }
107
108# Usage
109analyzer = CoLocationAnalyzer()
110
111analyzer.compare_locations()
112
113# Calculate value for our trading volume
114result = analyzer.calculate_colo_value(
115    daily_volume_usd=8_000_000_000,  # $8B daily
116    profit_per_bps=0.5,
117    latency_advantage_us=5000  # 5ms vs distant location
118)
119
120print(f"\nROI: {result['roi']:.1f}x")
121

Queue Position Inference#

Estimate your position in the order book queue.

python
1from collections import deque
2from typing import Optional
3
4class QueuePositionTracker:
5    """
6    Track estimated queue position for orders.
7    
8    Critical for HFT to estimate fill probability.
9    """
10    
11    def __init__(self):
12        self.orders = {}  # order_id -> order info
13        self.queue_positions = {}  # order_id -> estimated position
14    
15    def on_order_placed(
16        self,
17        order_id: str,
18        symbol: str,
19        side: str,
20        price: float,
21        quantity: int,
22        book_size_at_price: int
23    ):
24        """Track new order placement."""
25        # We're at the back of the queue
26        estimated_position = book_size_at_price
27        
28        self.orders[order_id] = {
29            'symbol': symbol,
30            'side': side,
31            'price': price,
32            'quantity': quantity,
33            'remaining': quantity
34        }
35        
36        self.queue_positions[order_id] = estimated_position
37        
38        print(f"Order {order_id}: placed at queue position {estimated_position}")
39    
40    def on_trade(
41        self,
42        symbol: str,
43        price: float,
44        quantity: int,
45        aggressor_side: str
46    ):
47        """
48        Update queue positions based on observed trade.
49        
50        If trade occurs at our price level, we might have moved up.
51        """
52        for order_id, order in self.orders.items():
53            if order['symbol'] != symbol:
54                continue
55            
56            # Check if trade affects our order
57            if order['price'] == price:
58                # Trade at our price level
59                
60                # If trade took liquidity on our side, we move up
61                if aggressor_side != order['side']:
62                    # Someone took liquidity on our side
63                    # We move up in queue
64                    
65                    old_position = self.queue_positions[order_id]
66                    new_position = max(0, old_position - quantity)
67                    self.queue_positions[order_id] = new_position
68                    
69                    print(f"Order {order_id}: queue {old_position} -> {new_position} "
70                          f"(trade: {quantity})")
71    
72    def on_book_update(
73        self,
74        symbol: str,
75        side: str,
76        price: float,
77        new_size: int
78    ):
79        """Update queue positions based on book changes."""
80        for order_id, order in self.orders.items():
81            if order['symbol'] != symbol or order['side'] != side:
82                continue
83            
84            if order['price'] == price:
85                # Size change at our price level
86                old_position = self.queue_positions[order_id]
87                
88                # If size decreased, we might have moved up
89                # Estimate: assume cancelled orders distributed evenly
90                # Simple model: our position stays same if we're in remaining size
91                
92                if new_size < old_position:
93                    # We're past the remaining size, likely cancelled
94                    self.queue_positions[order_id] = new_size
95                    
96                    print(f"Order {order_id}: adjusted to {new_size} "
97                          f"(book size changed)")
98    
99    def on_fill(
100        self,
101        order_id: str,
102        fill_quantity: int
103    ):
104        """Handle partial or full fill."""
105        if order_id not in self.orders:
106            return
107        
108        order = self.orders[order_id]
109        order['remaining'] -= fill_quantity
110        
111        # We're now at front of queue (position 0)
112        self.queue_positions[order_id] = 0
113        
114        print(f"Order {order_id}: FILLED {fill_quantity}, "
115              f"remaining {order['remaining']}")
116        
117        if order['remaining'] <= 0:
118            # Fully filled, remove
119            del self.orders[order_id]
120            del self.queue_positions[order_id]
121    
122    def estimate_time_to_fill(
123        self,
124        order_id: str,
125        historical_volume_per_second: float
126    ) -> Optional[float]:
127        """Estimate seconds until order fills."""
128        if order_id not in self.queue_positions:
129            return None
130        
131        position = self.queue_positions[order_id]
132        
133        # Estimate based on historical volume
134        # Assume our side captures 50% of volume
135        our_side_volume_per_sec = historical_volume_per_second * 0.5
136        
137        if our_side_volume_per_sec <= 0:
138            return None
139        
140        estimated_seconds = position / our_side_volume_per_sec
141        
142        return estimated_seconds
143    
144    def get_queue_position(self, order_id: str) -> Optional[int]:
145        """Get current estimated queue position."""
146        return self.queue_positions.get(order_id)
147
148# Usage
149tracker = QueuePositionTracker()
150
151# Place order
152tracker.on_order_placed(
153    "ORD001",
154    "AAPL",
155    "BUY",
156    150.00,
157    100,
158    book_size_at_price=5000  # 5000 shares ahead of us
159)
160
161# Observe trades at our price
162tracker.on_trade("AAPL", 150.00, 500, aggressor_side="SELL")
163tracker.on_trade("AAPL", 150.00, 300, aggressor_side="SELL")
164
165# Book update (cancellations)
166tracker.on_book_update("AAPL", "BUY", 150.00, new_size=3500)
167
168# Estimate time to fill
169volume_per_sec = 100  # 100 shares/sec at this price
170time_to_fill = tracker.estimate_time_to_fill("ORD001", volume_per_sec)
171print(f"\nEstimated time to fill: {time_to_fill:.1f} seconds")
172

Anti-Gaming Protections#

Prevent predatory HFT strategies from targeting you.

python
1import time
2from collections import defaultdict
3
4class AntiGamingProtection:
5    """Protect against predatory HFT strategies."""
6    
7    def __init__(self):
8        # Detect quote stuffing (excessive order activity)
9        self.order_counts = defaultdict(lambda: deque(maxlen=100))
10        
11        # Detect spoofing (large orders quickly cancelled)
12        self.suspicious_cancels = defaultdict(int)
13        
14        # Detect momentum ignition (rapid price moves)
15        self.price_history = defaultdict(lambda: deque(maxlen=50))
16        
17        # Thresholds
18        self.quote_stuffing_threshold = 50  # Orders per second
19        self.spoofing_ratio_threshold = 0.8  # Cancel rate
20        self.momentum_threshold_bps = 10  # Price move
21    
22    def detect_quote_stuffing(
23        self,
24        symbol: str,
25        timestamp: float
26    ) -> bool:
27        """
28        Detect quote stuffing: excessive orders to slow down competitors.
29        """
30        self.order_counts[symbol].append(timestamp)
31        
32        if len(self.order_counts[symbol]) < 10:
33            return False
34        
35        # Calculate orders per second
36        time_window = timestamp - self.order_counts[symbol][0]
37        
38        if time_window > 0:
39            orders_per_sec = len(self.order_counts[symbol]) / time_window
40            
41            if orders_per_sec > self.quote_stuffing_threshold:
42                print(f"WARNING: Quote stuffing detected for {symbol} "
43                      f"({orders_per_sec:.0f} orders/sec)")
44                return True
45        
46        return False
47    
48    def detect_spoofing(
49        self,
50        symbol: str,
51        orders_placed: int,
52        orders_cancelled: int
53    ) -> bool:
54        """
55        Detect spoofing: large orders placed and quickly cancelled
56        to manipulate prices.
57        """
58        if orders_placed == 0:
59            return False
60        
61        cancel_rate = orders_cancelled / orders_placed
62        
63        if cancel_rate > self.spoofing_ratio_threshold:
64            self.suspicious_cancels[symbol] += 1
65            
66            if self.suspicious_cancels[symbol] > 3:
67                print(f"WARNING: Spoofing detected for {symbol} "
68                      f"(cancel rate: {cancel_rate:.1%})")
69                return True
70        else:
71            # Reset if cancel rate normal
72            self.suspicious_cancels[symbol] = 0
73        
74        return False
75    
76    def detect_momentum_ignition(
77        self,
78        symbol: str,
79        price: float,
80        timestamp: float
81    ) -> bool:
82        """
83        Detect momentum ignition: rapid price moves to trigger
84        other algorithms.
85        """
86        self.price_history[symbol].append((timestamp, price))
87        
88        if len(self.price_history[symbol]) < 10:
89            return False
90        
91        # Check for rapid price move
92        oldest_time, oldest_price = self.price_history[symbol][0]
93        newest_time, newest_price = self.price_history[symbol][-1]
94        
95        time_diff = newest_time - oldest_time
96        
97        # Only check recent moves (< 1 second)
98        if time_diff > 1.0:
99            return False
100        
101        # Calculate price move
102        price_move_pct = abs(newest_price - oldest_price) / oldest_price
103        price_move_bps = price_move_pct * 10000
104        
105        if price_move_bps > self.momentum_threshold_bps:
106            print(f"WARNING: Momentum ignition detected for {symbol} "
107                  f"({price_move_bps:.1f} bps in {time_diff:.3f}s)")
108            return True
109        
110        return False
111    
112    def should_pause_trading(
113        self,
114        symbol: str
115    ) -> bool:
116        """Decide if should pause trading due to gaming."""
117        # Check all protections
118        if symbol in self.suspicious_cancels and \
119           self.suspicious_cancels[symbol] > 5:
120            print(f"PAUSE: {symbol} - excessive spoofing detected")
121            return True
122        
123        return False
124
125# Usage
126protection = AntiGamingProtection()
127
128# Simulate quote stuffing
129print("=== Quote Stuffing Test ===")
130base_time = time.time()
131for i in range(60):
132    is_stuffing = protection.detect_quote_stuffing("AAPL", base_time + i * 0.01)
133
134# Simulate spoofing
135print("\n=== Spoofing Test ===")
136protection.detect_spoofing("MSFT", orders_placed=100, orders_cancelled=95)
137protection.detect_spoofing("MSFT", orders_placed=100, orders_cancelled=92)
138protection.detect_spoofing("MSFT", orders_placed=100, orders_cancelled=88)
139
140# Simulate momentum ignition
141print("\n=== Momentum Ignition Test ===")
142base_price = 150.0
143for i in range(20):
144    price = base_price + i * 0.02  # Rapid price increase
145    protection.detect_momentum_ignition("GOOGL", price, time.time() + i * 0.05)
146
147# Check if should pause
148print("\n=== Trading Decision ===")
149if protection.should_pause_trading("MSFT"):
150    print("Trading paused for MSFT")
151

Regulatory Compliance#

HFT must comply with market regulations.

python
1class RegulatoryCompliance:
2    """
3    Ensure compliance with MiFID II and Reg NMS.
4    """
5    
6    def __init__(self):
7        # Order-to-trade ratio limits (MiFID II)
8        self.max_order_to_trade_ratio = 10.0
9        
10        # Message throttling
11        self.max_messages_per_second = 1000
12        
13        # Minimum resting time (prevent fleeting orders)
14        self.min_order_resting_time_ms = 500
15        
16        # Tracking
17        self.orders_sent = 0
18        self.trades_executed = 0
19        self.order_times = {}
20    
21    def check_order_to_trade_ratio(self) -> bool:
22        """
23        MiFID II: Order-to-trade ratio must not be excessive.
24        
25        Typical limit: 10:1
26        """
27        if self.trades_executed == 0:
28            # No trades yet, allow orders
29            return True
30        
31        ratio = self.orders_sent / self.trades_executed
32        
33        if ratio > self.max_order_to_trade_ratio:
34            print(f"WARNING: Order-to-trade ratio too high: {ratio:.1f}:1 "
35                  f"(limit: {self.max_order_to_trade_ratio}:1)")
36            return False
37        
38        return True
39    
40    def check_message_throttling(
41        self,
42        messages_in_last_second: int
43    ) -> bool:
44        """Check if message rate is within limits."""
45        if messages_in_last_second > self.max_messages_per_second:
46            print(f"WARNING: Message rate too high: {messages_in_last_second}/sec "
47                  f"(limit: {self.max_messages_per_second}/sec)")
48            return False
49        
50        return True
51    
52    def check_minimum_resting_time(
53        self,
54        order_id: str,
55        place_time_ms: float,
56        cancel_time_ms: float
57    ) -> bool:
58        """
59        Check if order was resting for minimum time.
60        
61        Prevents "fleeting orders" that manipulate prices.
62        """
63        resting_time = cancel_time_ms - place_time_ms
64        
65        if resting_time < self.min_order_resting_time_ms:
66            print(f"WARNING: Order {order_id} cancelled too quickly "
67                  f"({resting_time:.1f}ms < {self.min_order_resting_time_ms}ms)")
68            return False
69        
70        return True
71    
72    def validate_order(self) -> bool:
73        """Validate order before sending."""
74        # Check all compliance rules
75        
76        if not self.check_order_to_trade_ratio():
77            return False
78        
79        # In production, would check more rules:
80        # - Tick size compliance
81        # - Short sale restrictions
82        # - Limit up / limit down
83        # - Trading halts
84        # - etc.
85        
86        return True
87    
88    def record_order_sent(self, order_id: str, timestamp_ms: float):
89        """Record order sent."""
90        self.orders_sent += 1
91        self.order_times[order_id] = timestamp_ms
92    
93    def record_trade(self, order_id: str):
94        """Record trade execution."""
95        self.trades_executed += 1
96    
97    def generate_compliance_report(self) -> dict:
98        """Generate compliance metrics for reporting."""
99        ratio = (self.orders_sent / self.trades_executed 
100                 if self.trades_executed > 0 else 0)
101        
102        report = {
103            'orders_sent': self.orders_sent,
104            'trades_executed': self.trades_executed,
105            'order_to_trade_ratio': ratio,
106            'compliant': ratio <= self.max_order_to_trade_ratio
107        }
108        
109        print("\n=== Compliance Report ===")
110        print(f"Orders sent: {report['orders_sent']:,}")
111        print(f"Trades executed: {report['trades_executed']:,}")
112        print(f"Order-to-trade ratio: {report['order_to_trade_ratio']:.2f}:1")
113        print(f"Status: {'COMPLIANT' if report['compliant'] else 'NON-COMPLIANT'}")
114        
115        return report
116
117# Usage
118compliance = RegulatoryCompliance()
119
120# Simulate trading day
121for i in range(1000):
122    if compliance.validate_order():
123        compliance.record_order_sent(f"ORD{i}", time.time() * 1000)
124        
125        # 30% fill rate
126        if np.random.random() < 0.3:
127            compliance.record_trade(f"ORD{i}")
128
129# Generate report
130compliance.generate_compliance_report()
131

HFT Profitability Analysis#

Understand the economics of HFT market making.

python
1class HFTProfitability:
2    """Analyze HFT market making profitability."""
3    
4    def __init__(self):
5        pass
6    
7    def calculate_profit_per_trade(
8        self,
9        spread_bps: float,
10        adverse_selection_bps: float,
11        fees_bps: float,
12        avg_price: float = 100.0
13    ) -> dict:
14        """
15        Calculate expected profit per trade.
16        
17        Profit = Spread capture - Adverse selection - Fees
18        """
19        # Revenue: capture half the spread (on average)
20        spread_capture_bps = spread_bps / 2
21        
22        # Costs
23        total_cost_bps = adverse_selection_bps + fees_bps
24        
25        # Net profit
26        net_profit_bps = spread_capture_bps - total_cost_bps
27        
28        # Dollar profit per 100 shares
29        profit_per_100_shares = (net_profit_bps / 10000) * avg_price * 100
30        
31        result = {
32            'spread_bps': spread_bps,
33            'spread_capture_bps': spread_capture_bps,
34            'adverse_selection_bps': adverse_selection_bps,
35            'fees_bps': fees_bps,
36            'total_cost_bps': total_cost_bps,
37            'net_profit_bps': net_profit_bps,
38            'profit_per_100_shares': profit_per_100_shares
39        }
40        
41        print("=== Profit Per Trade Analysis ===")
42        print(f"Spread: {spread_bps:.2f} bps")
43        print(f"Spread capture: {spread_capture_bps:.2f} bps")
44        print(f"Adverse selection: -{adverse_selection_bps:.2f} bps")
45        print(f"Fees: -{fees_bps:.2f} bps")
46        print(f"Net profit: {net_profit_bps:.2f} bps")
47        print(f"Profit per 100 shares: ${profit_per_100_shares:.4f}")
48        
49        return result
50    
51    def calculate_daily_profitability(
52        self,
53        trades_per_day: int,
54        profit_per_trade: float,
55        infrastructure_cost_daily: float
56    ) -> dict:
57        """Calculate daily P&L."""
58        gross_profit = trades_per_day * profit_per_trade
59        net_profit = gross_profit - infrastructure_cost_daily
60        
61        # Assuming $8B daily volume
62        daily_volume = 8_000_000_000
63        profit_bps_on_volume = (gross_profit / daily_volume) * 10000
64        
65        result = {
66            'trades_per_day': trades_per_day,
67            'gross_profit': gross_profit,
68            'infrastructure_cost': infrastructure_cost_daily,
69            'net_profit': net_profit,
70            'profit_bps_on_volume': profit_bps_on_volume
71        }
72        
73        print("\n=== Daily Profitability ===")
74        print(f"Trades per day: {trades_per_day:,}")
75        print(f"Gross profit: ${gross_profit:,.2f}")
76        print(f"Infrastructure cost: ${infrastructure_cost_daily:,.2f}")
77        print(f"Net profit: ${net_profit:,.2f}")
78        print(f"Profit as % of volume: {profit_bps_on_volume:.3f} bps")
79        
80        # Annual
81        annual_net = net_profit * 252  # Trading days
82        print(f"\nAnnual net profit: ${annual_net:,.2f}")
83        
84        return result
85    
86    def sensitivity_analysis(self):
87        """Analyze sensitivity to key parameters."""
88        print("\n=== Sensitivity Analysis ===\n")
89        
90        base_spread = 2.0
91        base_adverse_selection = 0.3
92        base_fees = 0.1
93        
94        # Vary spread
95        print("Impact of spread width:")
96        for spread in [1.0, 1.5, 2.0, 2.5, 3.0]:
97            result = self.calculate_profit_per_trade(
98                spread, base_adverse_selection, base_fees, avg_price=100
99            )
100            print(f"  {spread:.1f} bps spread -> "
101                  f"${result['profit_per_100_shares']:.4f} per 100 shares")
102        
103        # Vary adverse selection
104        print("\nImpact of adverse selection:")
105        for adverse in [0.1, 0.2, 0.3, 0.4, 0.5]:
106            result = self.calculate_profit_per_trade(
107                base_spread, adverse, base_fees, avg_price=100
108            )
109            print(f"  {adverse:.1f} bps adverse selection -> "
110                  f"${result['profit_per_100_shares']:.4f} per 100 shares")
111
112# Usage
113analyzer = HFTProfitability()
114
115# Calculate profit per trade
116profit_result = analyzer.calculate_profit_per_trade(
117    spread_bps=2.0,
118    adverse_selection_bps=0.3,
119    fees_bps=0.1,
120    avg_price=100.0
121)
122
123# Calculate daily profitability
124# Assuming 50,000 trades per day, $0.18 profit per trade
125daily_result = analyzer.calculate_daily_profitability(
126    trades_per_day=50_000,
127    profit_per_trade=0.18,
128    infrastructure_cost_daily=3000  # $3k/day for servers, co-lo, etc.
129)
130
131# Sensitivity analysis
132analyzer.sensitivity_analysis()
133

Production Metrics#

Our HFT system (2024):

Performance#

plaintext
1Latency (microseconds):
2- Tick-to-trade P50: 12μs
3- Tick-to-trade P99: 28μs
4- Tick-to-trade P99.9: 45μs
5- Quote update: 8μs
6
7Volume & Profitability:
8- Daily volume: $8B
9- Daily trades: 52,000
10- Win rate: 58%
11- Profit per trade: $0.18 average
12- Daily P&L: $9,360 (gross)
13- Monthly P&L: $196k (gross)
14- Annual P&L: $2.35M (gross)
15
16Risk Metrics:
17- Sharpe ratio: 3.4
18- Max drawdown: -$42k
19- Max inventory: 8,200 shares
20- Fill rate: 78%
21- Adverse selection cost: 0.3 bps
22

Infrastructure Costs#

plaintext
1Monthly Costs:
2- Co-location: $11,000
3- Servers: $8,000
4- Market data: $15,000
5- Connectivity: $5,000
6- Development: $25,000
7- Compliance: $8,000
8Total: $72,000/month
9
10Annual: $864,000
11Annual net P&L: $2.35M - $0.864M = $1.49M
12

Lessons Learned#

After 6+ years building HFT systems:

  1. Latency is everything: 10μs improvement increased fills by 8%
  2. Co-location mandatory: Remote trading 300x slower, can't compete
  3. Queue position critical: Accurate modeling improved profitability 15%
  4. Adverse selection biggest cost: Detection saved $380k annually
  5. Compliance non-negotiable: $250k fine for order-to-trade violation
  6. Monitoring essential: Caught network issue within 200ms, prevented $50k loss
  7. Infrastructure expensive: $864k/year, but necessary for competitiveness
  8. Spreads compressed: 2019 avg spread 3.2 bps, 2024 avg 2.0 bps - must be more efficient

HFT requires substantial investment in infrastructure, but can be highly profitable with proper execution.

Further Reading#

  • Flash Boys by Michael Lewis
  • Trading at the Speed of Light by Donald MacKenzie
  • The Problem of HFT by Haim Bodek
  • MiFID II Regulation - ESMA
  • Reg NMS - SEC Regulation
NT

NordVarg Team

Technical Writer

NordVarg Team is a software engineer at NordVarg specializing in high-performance financial systems and type-safe programming.

hftmarket-makinglow-latencytradingcompliance

Join 1,000+ Engineers

Get weekly insights on building high-performance financial systems, latest industry trends, and expert tips delivered straight to your inbox.

✓Weekly articles
✓Industry insights
✓No spam, ever

Related Posts

Nov 11, 2025•7 min read
HFT Cryptocurrency Trading: The 2021 Binance Flash Crash and What We Learned
Quantitative Financehftcryptocurrency
Jan 15, 2025•15 min read
Market Making Strategies: Inventory Management and Risk Control
Quantitative Financemarket-makingliquidity-provision
Jan 20, 2025•16 min read
Liquidity Provision Algorithms: Passive vs Aggressive Strategies
Quantitative Financeliquidity-provisionmarket-making

Interested in working together?