关于 jump-trading-fpga-hft
面向超低延迟交易系统设计的风格指南,整理 FPGA、网络路径、确定性处理和全栈优化原则。适用于探索市场数据处理与订单生成等系统设计的开发者。
主要功能
- 01以 FPGA 承担关键逻辑
- 02优化网络路径与跳数
- 03强调确定性和低抖动
- 04采用 NIC 侧数据处理
- 05测量端到端线速延迟
适用场景
- 01设计低延迟市场数据解析
- 02规划交易系统网络拓扑
- 03评估 NIC 或 FPGA 处理路径
- 04测量收发链路延迟
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ copyleftdev/ sk1llz --skill jump-trading-fpga-hft安装后在 Claude Code 中输入/jump-trading-fpga-hft确认已加载。
详细介绍
Jump Trading 风格指南
概述
Jump Trading 是一家专有交易公司,以不断突破交易技术的边界而闻名。他们开创了基于 FPGA 的交易技术,投资建设微波网络以实现比光纤更快的连接,并始终处于延迟优化的最前沿。
核心理念
“我们唯一接受的限制是光速。”
“软件太慢。把它放进硬件里。”
“网络延迟只是物理规律。计算延迟则是工程失败。”
Jump 认为,软件太慢时,就应该把逻辑放进硬件里。FPGA 能在数百纳秒内处理市场数据并生成订单——比 CPU 醒来还快。
设计原则
-
硬件 > 软件:延迟至关重要时,使用 FPGA。
-
网络至关重要:微波胜过光纤。共置胜过远程连接。
-
皮秒也很重要:在最前沿,每一纳秒都要全力争取。
-
确定性制胜:抖动是稳定性能的敌人。
-
掌控全栈:从 NIC 到交易所,所有环节都要掌控。
构建超低延迟系统时
始终
- 测量端到端延迟,而非组件延迟
- 使用 FPGA 处理时间关键型决策
- 优化网络路径(共置、交叉连接、交换机)
- 尽可能在 NIC 中处理数据(智能 NIC)
- 消除所有不必要的跳数
- 使用硬件时间戳进行精确测量
绝不
- 信任软件时间戳
- 在关键路径中使用通用交换机
- 认为网络延迟是固定的
- 忽略物理层(线缆、光学器件、交换机)
- 可以流水线处理时却仍按顺序处理
- 可以直通转发时却等待完整消息
优先选择
- 固定逻辑优先使用 FPGA,而非 CPU
- 直通交换优先于存储转发
- 长距离通信优先使用微波/毫米波,而非光纤
- 专用线路优先于共享基础设施
- 硬件时间戳优先于软件时间戳
- 并行处理优先于顺序处理
代码模式
FPGA 市场数据解析器(伪 Verilog)
// FPGA-based market data parsing and order generation
// Processes UDP multicast market data, generates orders in ~200ns
module market_data_parser (
input wire clk_312_5mhz, // 312.5 MHz clock (3.2ns period)
input wire [63:0] eth_data, // 64-bit data from MAC
input wire eth_valid,
input wire eth_sof, // Start of frame
input wire eth_eof, // End of frame
output reg [63:0] order_data,
output reg order_valid,
output reg [15:0] symbol_id,
output reg [31:0] bid_price,
output reg [31:0] ask_price,
output reg [31:0] bid_size,
output reg [31:0] ask_size
);
// Pipeline stages for parallel processing
reg [2:0] state;
localparam IDLE = 0, PARSE_HEADER = 1, PARSE_SYMBOL = 2,
PARSE_BID = 3, PARSE_ASK = 4, GENERATE_ORDER = 5;
// Pre-computed strategy parameters (loaded at startup)
reg [31:0] fair_value [0:4095]; // Per-symbol fair value
reg [31:0] edge_threshold [0:4095]; // Min edge to trade
reg [31:0] max_position [0:4095]; // Position limits
// Current positions (updated by fill handler)
reg [31:0] positions [0:4095];
always @(posedge clk_312_5mhz) begin
case (state)
IDLE: begin
order_valid <= 0;
if (eth_valid && eth_sof) begin
state <= PARSE_HEADER;
end
end
PARSE_HEADER: begin
// Parse UDP header, extract message type
// Skip IP/UDP headers (known fixed offsets)
if (is_quote_message(eth_data)) begin
state <= PARSE_SYMBOL;
end else begin
state <= IDLE;
end
end
PARSE_SYMBOL: begin
symbol_id <= eth_data[15:0];
state <= PARSE_BID;
end
PARSE_BID: begin
bid_price <= eth_data[31:0];
bid_size <= eth_data[63:32];
state <= PARSE_ASK;
end
PARSE_ASK: begin
ask_price <= eth_data[31:0];
ask_size <= eth_data[63:32];
state <= GENERATE_ORDER;
end
GENERATE_ORDER: begin
// All logic executes in single clock cycle
wire [31:0] fv = fair_value[symbol_id];
wire [31:0] edge = edge_threshold[symbol_id];
wire [31:0] pos = positions[symbol_id];
wire [31:0] max_pos = max_position[symbol_id];
// Buy if bid is below fair value minus edge
wire should_buy = (bid_price < fv - edge) && (pos < max_pos);
// Sell if ask is above fair value plus edge
wire should_sell = (ask_price > fv + edge) && (pos > -max_pos);
if (should_buy) begin
order_data <= build_buy_order(symbol_id, bid_price, bid_size);
order_valid <= 1;
end else if (should_sell) begin
order_data <= build_sell_order(symbol_id, ask_price, ask_size);
order_valid <= 1;
end
state <= IDLE;
end
endcase
end
endmodule
网络拓扑优化
class NetworkOptimizer:
"""
Jump's network optimization: every nanosecond counts.
Model and optimize the full network path.
"""
def __init__(self):
self.topology = {}
self.latency_measurements = {}
def model_path_latency(self,
source: str,
destination: str) -> LatencyBreakdown:
"""
Break down latency into components.
"""
path = self.find_path(source, destination)
breakdown = LatencyBreakdown()
for i, (node_a, node_b) in enumerate(zip(path[:-1], path[1:])):
link = self.topology[(node_a, node_b)]
# Propagation delay (speed of light in medium)
# Fiber: ~5 ns/meter, Microwave: ~3.3 ns/meter
prop_delay = link.distance_meters * link.propagation_factor
breakdown.propagation_ns += prop_delay
# Serialization delay (time to put bits on wire)
# 10GbE: 67.2ns for 64-byte frame
serial_delay = (link.frame_size_bytes * 8) / link.bandwidth_gbps
breakdown.serialization_ns += serial_delay
# Switch/router delay
if link.device_type == 'cut_through_switch':
# Cut-through: forward after seeing destination MAC (~300ns)
breakdown.switching_ns += 300
elif link.device_type == 'store_forward_switch':
# Store-and-forward: wait for full frame (~5000ns for 64B)
breakdown.switching_ns += 5000
# NIC delay (if applicable)
if i == 0: # Source NIC
breakdown.nic_tx_ns += link.nic_tx_latency_ns
if i == len(path) - 2: # Destination NIC
breakdown.nic_rx_ns += link.nic_rx_latency_ns
return breakdown
def compare_microwave_vs_fiber(self,
point_a: Location,
point_b: Location) -> dict:
"""
Microwave travels at ~c (speed of light in vacuum).
Fiber travels at ~0.67c (speed of light in glass).
For long distances, microwave wins despite being line-of-sight.
"""
distance_km = self.calculate_distance(point_a, point_b)
# Speed of light
c = 299792.458 # km/s
# Fiber: ~0.67c due to refractive index, plus routing overhead
fiber_speed = c * 0.67
fiber_distance = distance_km * 1.3 # Routing adds ~30%
fiber_latency_ms = (fiber_distance / fiber_speed) * 1000
# Microwave: ~0.99c, nearly straight line
microwave_speed = c * 0.99
microwave_distance = distance_km * 1.02 # Slight deviation for terrain
microwave_latency_ms = (microwave_distance / microwave_speed) * 1000
return {
'fiber_latency_ms': fiber_latency_ms,
'microwave_latency_ms': microwave_latency_ms,
'savings_ms': fiber_latency_ms - microwave_latency_ms,
'savings_percent': (fiber_latency_ms - microwave_latency_ms) / fiber_latency_ms * 100
}
智能 NIC 处理
// Smart NIC (Bluefield/Netronome) for in-NIC processing
// Process market data before it hits CPU
class SmartNICProcessor {
public:
// Run on NIC's ARM cores / P4 engine
struct PacketContext {
uint64_t timestamp_hw; // Hardware timestamp from PHY
uint8_t* packet_data;
uint16_t length;
};
// This runs on the NIC, not the host CPU
__attribute__((section(".nic_code")))
Action process_packet(PacketContext* ctx) {
// Parse at line rate
auto* eth = reinterpret_cast<EthernetHeader*>(ctx->packet_data);
if (eth->ethertype != ETHERTYPE_IP) {
return Action::PASS_TO_HOST;
}
auto* ip = reinterpret_cast<IPHeader*>(eth + 1);
auto* udp = reinterpret_cast<UDPHeader*>(ip + 1);
// Filter: only process market data multicast
if (!is_market_data_multicast(ip->dst_addr, udp->dst_port)) {
return Action::PASS_TO_HOST;
}
auto* msg = reinterpret_cast<MarketDataMessage*>(udp + 1);
// Simple filtering: drop if not in our symbol universe
if (!is_in_universe(msg->symbol_id)) {
return Action::DROP;
}
// Add hardware timestamp and pass to host
ctx->packet_data = prepend_timestamp(ctx->packet_data, ctx->timestamp_hw);
return Action::PASS_TO_HOST;
}
};
精确时间协议(PTP)
// Hardware-based time synchronization
class PTPTimeSync {
/*
* Jump uses PTP (IEEE 1588) for nanosecond-accurate time sync.
* Critical for correlating events across systems and fair latency measurement.
*/
public:
void configure_ptp_hardware(int nic_fd) {
// Enable hardware timestamping
struct hwtstamp_config config = {};
config.tx_type = HWTSTAMP_TX_ON;
config.rx_filter = HWTSTAMP_FILTER_ALL;
struct ifreq ifr = {};
ifr.ifr_data = (char*)&config;
ioctl(nic_fd, SIOCSHWTSTAMP, &ifr);
// Get PHC (PTP Hardware Clock) device
struct ethtool_ts_info info = {};
info.cmd = ETHTOOL_GET_TS_INFO;
ifr.ifr_data = (char*)&info;
ioctl(nic_fd, SIOCETHTOOL, &ifr);
// Open PHC device
char phc_device[32];
snprintf(phc_device, sizeof(phc_device), "/dev/ptp%d", info.phc_index);
phc_fd_ = open(phc_device, O_RDWR);
}
uint64_t get_hardware_time_ns() {
struct ptp_clock_time ptc;
ioctl(phc_fd_, PTP_CLOCK_GETTIME, &ptc);
return ptc.sec * 1000000000ULL + ptc.nsec;
}
// Extract hardware timestamp from received packet
uint64_t extract_rx_timestamp(struct msghdr* msg) {
for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(msg);
cmsg;
cmsg = CMSG_NXTHDR(msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_TIMESTAMPING) {
struct scm_timestamping* ts =
(struct scm_timestamping*)CMSG_DATA(cmsg);
// Use hardware timestamp (ts[2]) not software (ts[0])
return ts->ts[2].tv_sec * 1000000000ULL +
ts->ts[2].tv_nsec;
}
}
return 0;
}
private:
int phc_fd_;
};
端到端延迟测量
class WireToWireLatency {
/*
* Measure true latency: from photons arriving at RX NIC
* to photons leaving TX NIC.
* Software timestamps are useless at these scales.
*/
public:
struct Measurement {
uint64_t rx_hw_timestamp; // When packet hit our NIC (hardware)
uint64_t tx_hw_timestamp; // When response left our NIC (hardware)
uint64_t wire_to_wire_ns; // Total latency
// Component breakdown (if instrumented)
uint64_t parse_ns;
uint64_t strategy_ns;
uint64_t order_build_ns;
uint64_t tx_queue_ns;
};
void record_tick_to_trade(
uint64_t market_data_rx_hw_ts,
uint64_t order_tx_hw_ts) {
uint64_t latency_ns = order_tx_hw_ts - market_data_rx_hw_ts;
histogram_.record(latency_ns);
// Alert if we exceed target
if (latency_ns > target_latency_ns_) {
log_slow_path(latency_ns);
}
}
void print_histogram() {
// Typical Jump-style output:
// p50: 180ns, p99: 320ns, p999: 890ns, max: 1.2us
auto stats = histogram_.get_stats();
printf("Wire-to-wire latency:\n");
printf(" p50: %luns\n", stats.p50);
printf(" p99: %luns\n", stats.p99);
printf(" p999: %luns\n", stats.p999);
printf(" max: %luns\n", stats.max);
}
};
思维模型
Jump 通过以下问题来实现超低延迟:
- 物理极限是什么? 光速 × 距离
- 计算在哪里进行? 将计算移至硬件(FPGA/SmartNIC)
- 网络路径是什么? 优化每一跳
- 抖动有多大? 最坏情况比平均情况更重要
- 能否进行流水线处理? 并行处理,而非顺序处理
Jump 的标志性做法
- 基于 FPGA 的交易逻辑
- 用于长距离传输的微波网络
- 智能 NIC 预处理
- 硬件 PTP 时间同步
- 直通交换
- 端到端延迟测量
- 纳秒级优化
- 在每个主要交易所共置
- 全栈软硬件掌控
评论
支持 Markdown