High-Frequency Trading Backtesting with HFTBacktest: A Practical Guide to Nanosecond-Level Simulation

HFTBacktest leverages Numba JIT compilation to simulate limit-order-book data at nanosecond granularity, enabling precise backtesting of latency-sensitive strategies through a lightweight event-driven API.

The paperswithbacktest/awesome-systematic-trading repository serves as a curated index of quantitative trading resources, cataloging open-source libraries and academic strategy implementations. Among the approximately 97 tools listed in the README.md—specifically at line 00106—HFTBacktest emerges as the definitive solution for high-frequency trading backtesting, offering researchers a Python-based engine to evaluate market-making and ultra-low-latency algorithms without live market risk.

Locating HFTBacktest in the Awesome-Systematic-Trading Ecosystem

Within the repository’s README.md, HFTBacktest appears in the Libraries & Packages section alongside other backtesting frameworks like zipline, backtrader, and vectorbt. The entry at line 00106 describes it as a “highly precise backtest on HFT data in Python+Numba”【00106†L1-L3】. Unlike general-purpose backtesters, HFTBacktest is purpose-built for limit-order-book (LOB) simulation, requiring tick-level data rather than aggregated OHLC bars.

The repository does not contain HFTBacktest’s source code; instead, it links to the dedicated repository at github.com/nkaz001/hftbacktest. The awesome-systematic-trading project complements this by providing over 40 academic strategy implementations in static/strategies/*.py (such as volatility-risk-premium-effect.py) that can be adapted to run on HFTBacktest’s engine after migrating from their original QuantConnect Lean format.

Core Architecture and Workflow

HFTBacktest’s design prioritizes execution speed and temporal precision. Built atop NumPy with Numba Just-In-Time (JIT) compilation, the engine processes events sequentially while maintaining nanosecond resolution of order book states.

The Strategy Base Class

All trading logic inherits from the Strategy class, implementing callback methods that the engine invokes during simulation:

  • on_tick(self, tick): Called for every market data update, receiving the current book state including best_bid_price, best_ask_price, and tick_size.
  • on_order(self, order): Handles execution reports and fill notifications.

Strategy instances interact with the market through order management methods like self.order_limit(price, size, side), which submits passive liquidity to the book.

The Backtest Orchestrator

The Backtest class acts as the simulation controller. It accepts a pandas DataFrame of LOB data and a Strategy subclass, then orchestrates the event loop. Key methods include:

  • Backtest(data, strategy, start_cash): Initializes the engine with initial capital and data feed.
  • bt.run(): Executes the JIT-compiled event loop, stepping through every tick, matching orders, and updating PnL.
  • Result: The object returned by bt.run(), providing summary() and detailed latency statistics.

Data Requirements

HFTBacktest requires raw tick or order-book snapshots rather than aggregated bars. Input DataFrames must contain timestamp-indexed columns such as best_bid_price, best_ask_price, tick_size, and depth data, depending on the specific asset class being simulated.

Practical Implementation: Market-Making Strategy

Below is a minimal, self-contained example demonstrating a market-making strategy that posts bid and ask orders one tick away from the mid-price. This assumes you have installed the package via pip install hftbacktest and possess a sample LOB CSV file.


# example_hft_strategy.py

import pandas as pd
import numpy as np
from hftbacktest import Backtest, Strategy, Result

class MarketMaker(Strategy):
    """Simple market-making: post bid/ask one tick away from mid-price."""
    def __init__(self, spread: int = 2):
        self.spread = spread

    def on_tick(self, tick):
        # Calculate mid-price from best bid/ask

        mid = (tick.best_bid_price + tick.best_ask_price) / 2
        # Post limit orders inside the spread

        bid_price = mid - self.spread * tick.tick_size
        ask_price = mid + self.spread * tick.tick_size
        self.order_limit(price=bid_price, size=100, side='buy')
        self.order_limit(price=ask_price, size=100, side='sell')

# Load LOB data with required columns: timestamp, best_bid_price, best_ask_price, tick_size

lob = pd.read_csv('sample_lob.csv', parse_dates=['timestamp'])

# Initialize backtest with $1M starting capital

bt = Backtest(lob, MarketMaker(spread=2), start_cash=1_000_000)

# Run simulation

result: Result = bt.run()

# Output performance metrics

print(result.summary())

Key components explained:

  • class MarketMaker(Strategy): Defines the logic within on_tick, accessing real-time book state through the tick parameter.
  • self.order_limit: Submits passive orders to the simulated exchange; the engine handles queue position and priority.
  • Backtest(lob, MarketMaker(...), start_cash=...): Feeds the DataFrame into the JIT-compiled engine.
  • result.summary(): Returns aggregated statistics including Sharpe ratio, total PnL, and latency distributions.

Adapting Academic Strategies from the Repository

The static/strategies/ directory contains over 40 Python scripts implementing peer-reviewed strategies, such as static/strategies/volatility-risk-premium-effect.py. These files are originally formatted for QuantConnect’s Lean engine, using Initialize and OnData methods.

To migrate these strategies to HFTBacktest:

  1. Extract the core logic from the QuantConnect OnData method, identifying entry/exit signals and position sizing rules.
  2. Create a Strategy subclass with an on_tick method that replicates the signal generation.
  3. Replace QuantConnect’s SetHoldings or LimitOrder calls with HFTBacktest’s self.order_limit or self.order_market methods.
  4. Adjust data feeds to ensure your LOB DataFrame contains the granular fields required by HFTBacktest rather than minute-level trade bars.

This migration allows you to test the same alpha logic under realistic high-frequency conditions, accounting for queue position and adverse selection effects that coarse backtesters ignore.

Summary

  • HFTBacktest is referenced at line 00106 of paperswithbacktest/awesome-systematic-trading’s README.md as the premier tool for nanosecond-level simulation.
  • The engine is built on Numba JIT compilation, processing limit-order-book data through an event-driven Strategy class interface.
  • A typical workflow involves loading tick data, subclassing Strategy to implement on_tick, instantiating Backtest, and calling bt.run() to generate a Result object.
  • Strategies from the repository’s static/strategies/ folder (e.g., volatility-risk-premium-effect.py) can be ported from QuantConnect Lean to HFTBacktest by adapting their event handlers to the Strategy callback pattern.

Frequently Asked Questions

What data format is required for HFTBacktest?

HFTBacktest requires raw tick or limit-order-book data in a pandas DataFrame, containing columns such as timestamp, best_bid_price, best_ask_price, and tick_size. Unlike traditional backtesters that use OHLC aggregates, HFTBacktest processes every book update to simulate queue position and execution priority accurately.

How does HFTBacktest achieve nanosecond-level precision?

The library uses Numba to JIT-compile the core event loop, allowing Python-defined strategy logic to execute at near-C speeds while maintaining nanosecond timestamps. This precision is essential for modeling latency-sensitive strategies where microseconds determine profitability.

Can strategies from the awesome-systematic-trading repository run on HFTBacktest?

Yes. The Python scripts in static/strategies/*.py (such as volatility-risk-premium-effect.py) can be adapted by converting their QuantConnect Initialize and OnData methods into HFTBacktest’s Strategy subclass structure with on_tick callbacks. The underlying alpha logic remains portable while gaining access to high-fidelity execution simulation.

What performance metrics does the Result class provide?

The Result object returned by bt.run() includes comprehensive metrics via result.summary(), typically covering total PnL, Sharpe ratio, maximum drawdown, trade count, and detailed latency statistics that reveal slippage and adverse selection impacts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →