Skip to main content

NeutrinoBT

CI Python 3.12+ License: MIT

A high-performance Python backtesting library powered by Numba JIT.

NeutrinoBT runs your trading strategies fast — the core engine is compiled to machine code via Numba so that even large parameter sweeps complete in seconds. The API is modeled after Pine Script, so moving from TradingView concepts to Python is straightforward.


Features

Core Engine

  • Numba JIT backtesting@njit(cache=True) compiled execution loop; orders, stops, and equity curves computed at native speed
  • Two signal modes — vectorized (NumPy arrays) for simple strategies; Pine Script-style order API (order(), exit(), cancel()) for complex logic
  • Multiple positions — FIFO, LIFO, or BY_ID close selection; configurable max_positions
  • Stops & exits — per-trade stop loss, take profit, and trailing stops (activation by price or points)
  • Leverage & liquidation — configurable leverage with automatic liquidation price calculation
  • Entry on bar close — optional entry_on_bar_close=True fills at next bar open (matches Pine Script strategy.entry behaviour)
  • Commission & slippage — applied separately to entries and stops

Indicators (self.I / nt.*)

25+ built-in indicators, all Numba-accelerated, organized into five categories:

Category Indicators
Moving Averages EMA, SMA, RMA, WMA, DEMA, TEMA, HMA, VWMA
Momentum RSI, MACD, Stoch, StochRSI, CCI, Williams %R, ADX, MFI
Volatility ATR, STDEV, SuperTrend, Bollinger Bands, Keltner Channel, Donchian Channel
Trend Parabolic SAR, Ichimoku Cloud, Linear Regression
Volume OBV, VWAP

All indicators support a timeframe= parameter for multi-timeframe analysis without look-ahead bias.

Optimization

  • Grid search — exhaustive sweep over all parameter combinations
  • Random search — sampled trials with reproducible seeds
  • Genetic optimizer (GeneticOptimizer) — tournament selection, uniform crossover, per-gene mutation, elitism; for search spaces too large for grid search (100M+ combinations)
  • GPU-accelerated screeningbackend="auto"/"gpu"/"cpu" on Optimizer.run() / GeneticOptimizer.run(); a Numba CUDA kernel (reactor_cuda.py, one thread per backtest) screens every parameter set, then the top-K are re-run on the CPU reactor for the authoritative score. Falls back to CPU loudly if no CUDA toolkit is available — see docs/gpu_setup.md
  • Parallel workersn_jobs= via multiprocessing.Pool (Windows-safe)
  • Built-in objectivesnet_profit, sharpe, profit_factor, gt_score, negative_max_drawdown, rto, prom, ars; or pass any callable
  • SQLite result store (OptimizeStore) — every trial (grid, random, or GA generation) persisted with stable parameter IDs and stats columns, so a long-running sweep can be queried live from another process

Statistics

Professional-grade metrics in the style of TradingView's Strategy Tester: Net Profit, Gross Profit/Loss, Profit Factor, Sharpe, Sortino, Calmar, Max Drawdown, PROM, GT-Score, Win Rate, Avg Win/Loss, Avg Bars in Trade, CAGR, T-Test — all broken down by All / Long / Short.

Jupyter / In-Notebook Visualization

  • plot_equity — equity curve chart from mark-to-market or trade-step fallback
  • plot_drawdown — underwater / drawdown chart (% from running peak)
  • plot_price_with_trades — close price overlaid with long/short entry & exit markers
  • display_statistics_summary — styled statistics table rendered inline in Jupyter
  • QuantStats exportquantstats_returns() converts the equity curve to per-bar decimal returns compatible with the QuantStats tear-sheet library (optional install)

Dashboard & Export

  • HTML dashboard — self-contained interactive report with TradingView price chart, equity curve, drawdown, returns heatmap, MFE/MAE scatter, and paginated trade log
  • Pine Script export — generate a Pine Script indicator from your strategy's signals
  • CSV export — statistics table and full trade list

Walk-Forward Optimization (neutrinobt.wfo)

True walk-forward validation: per-window re-optimization with no look-ahead bias.

  • run_rolling_wfo(...) — rolling train/test windows with per-window parameter search (CPU grid/random or GPU screening), followed by a single CPU ground-truth backtest on the test slice
  • Windowing — compact horizon syntax (days/weeks/months/quarters/years); both train and test use explicit rolling boundaries
  • Built-in guardrails — DSR (Deflated Sharpe Ratio), opt-in PBO (Probability of Backtest Overfitting) via fixed candidate list, per-window train/test degradation grid, WFE (Walk-Forward Efficiency), and the composite R97 KILL/ARCHIVE/PROMOTE gate
  • OOS replay — trades stitched from all windows; full equity curve and statistics from out-of-sample performance
  • Text/HTML reports — best-parameter and OOS-stitched report export bundles

Statistical Guardrails (neutrinobt.statistics)

Anti-overfitting checks for promoting a strategy out of research, per Bailey & López de Prado:

  • Deflated Sharpe Ratio (DSR) — corrects Sharpe for multiple-trials selection bias, with PASS/BORDERLINE/FAIL verdicts
  • Probability of Backtest Overfitting (PBO) — CSCV implementation, vectorized fast path
  • Per-window degradation grid — train/test metric table with red/yellow/green status per window
  • R97 gate — composite KILL / ARCHIVE / PROMOTE decision from DSR + PBO + per-window ratio + WFE

Performance

Benchmark: EMA(12/26) crossover strategy, 8,640 rows of BTCUSDT 30 m data, measured at 10 / 100 / 1,000 repeated runs (Numba JIT pre-warmed).

Engine Avg time / run × NeutrinoBT × backtrader
Hardcoded (raw NumPy) ~1 ms 22× faster 1,090× faster
NeutrinoBT ~22 ms ~50× faster
backtesting.py ~77 ms 3.5× slower 14× faster
backtrader ~1,090 ms 50× slower

NeutrinoBT is only ~22× behind a raw NumPy loop (the theoretical floor) while delivering a production-grade framework: stops, leverage, multi-position, full statistics, and HTML export. At 1,000-parameter-sweep scale, backtrader takes ~18 min total vs ~22 s for NeutrinoBT.

Source: backtesting-showcase.ipynb in the repo root. Results vary by CPU; the first per-session run includes Numba JIT compilation (~1–2 s one-time cost).


Installation

# Using uv (recommended)
uv pip install neutrinobt

# Or with pip
pip install neutrinobt

Requirements: Python 3.12+, NumPy, Numba, Pandas, Polars. Jinja2/Matplotlib (dashboard), CCXT (data), CuPy/CUDA (GPU) etc. are optional extras — see below.

Optional extras:

# Development tools from a source checkout (JupyterLab, pytest, ruff)
uv sync --group dev

# Binance / CCXT data downloader helpers
pip install "neutrinobt[data]"

# QuantStats tear sheets (pulls scipy, seaborn, yfinance)
pip install "neutrinobt[analytics]"

# HTML dashboard / static plot export (Jinja2, Matplotlib)
pip install "neutrinobt[reporting]"

# CUDA-accelerated optimization (needs an NVIDIA GPU + CUDA 12 toolkit)
pip install "neutrinobt[gpu]"

# Everything optional
pip install "neutrinobt[all]"

Quick Start

import numpy as np
from neutrinobt.data.loader import CSVLoader
from neutrinobt.strategy.base import Strategy
from neutrinobt.core.reactor import Reactor
import neutrinobt.indicators as nt

# 1. Load OHLCV data
loader = CSVLoader("sampledata/BTCUSDTUSDT/1h.csv")
bars = loader.load({
    "time": "timestamp", "open": "open", "high": "high",
    "low": "low", "close": "close", "volume": "volume",
})

# 2. Define a strategy
class EMACrossover(Strategy):
    def init(self):
        self.ema_fast = self.I.EMA(20)
        self.ema_slow = self.I.EMA(50)

    def generate_signals(self):
        valid = ~(np.isnan(self.ema_fast) | np.isnan(self.ema_slow))
        self.buy_cond(nt.crossover(self.ema_fast, self.ema_slow) & valid)
        self.sell_cond(nt.crossunder(self.ema_fast, self.ema_slow) & valid)

    def create_reactor(self):
        return Reactor(bars, initial_balance=10_000.0, commission_rate=0.001)

# 3. Run
results = EMACrossover(bars).run(show_summary=True)
print(f"Final equity: ${results['final_equity']:,.2f}")

Jupyter Plotting

# Pass export_timeseries=True to record bar-by-bar equity
results = EMACrossover(bars).run(export_timeseries=True, show_summary=False)

from neutrinobt.notebook.plots import plot_equity, plot_drawdown, display_statistics_summary
from neutrinobt.notebook.quantstats_export import quantstats_returns

plot_equity(bars, equity_curve=results["equity_curve"])
plot_drawdown(bars, equity_curve=results["equity_curve"])
display_statistics_summary(results["statistics"])

# Export per-bar decimal returns ready for QuantStats
qs = quantstats_returns(bars=bars, equity_curve=results["equity_curve"])
# import quantstats; quantstats.reports.basic(qs.strategy, benchmark=qs.benchmark)

See examples/notebooks/09_jupyter_plotting.ipynb for a full walkthrough.


Tutorials

The examples/ folder is a step-by-step curriculum. Scripts 0108 cover the core engine; the notebooks/ subfolder has interactive Jupyter examples.

Scripts — run from the project root:

File Topic What you learn
01_getting_started.py First backtest Load data, validate, define a strategy, read results
02_strategy_basics.py Strategy class init(), generate_signals(), create_reactor(), statistics keys
03_indicators.py All 25+ indicators Every indicator category, standalone use, multi-timeframe
04_risk_management.py Risk controls Fixed/ATR stop loss & take profit, trailing stops, leverage, sizing
05_advanced_orders.py Order-based API order(), exit(), cancel(), limit/stop entries, multiple positions
06_optimization.py Parameter search Optimizer.run(), grid vs random, built-in objectives, parallel
07_dashboard_report.py HTML report export_html=True, generate_report(), all dashboard sections
08_real_world_strategy.py Full strategy Date range, warmup, production backtest, trade analysis
09_gpu_ga_optimization.py GA + GPU search GeneticOptimizer.run(), backend="auto"/"gpu", CPU finalize, live SQLite leaderboard
10_pinescript_export.py Pine export generate_pine_script(), export_pine_script(), Strategy.run(export_pine=True)
python examples/01_getting_started.py

Notebooks — open in JupyterLab (uv sync --group dev && uv run jupyter lab):

Notebook Topic What you learn
notebooks/09_jupyter_plotting.ipynb In-notebook visualization Equity curve, drawdown, trade markers, statistics table, QuantStats export

Architecture

neutrinobt/
├── core/
│   ├── reactor_core.py   # Numba @njit compiled engine (the hot loop, CPU)
│   ├── reactor_cuda.py   # Numba CUDA port — one thread per backtest (GPU screening)
│   ├── reactor_gpu.py    # legacy CuPy batch reactor
│   ├── reactor.py        # Python wrapper — validation, results, statistics
│   └── statistics.py     # ~30 performance metrics
├── strategy/
│   └── base.py           # Strategy base class + IndicatorFactory (self.I)
├── indicators/           # 25+ @njit indicators
├── notebook/             # Jupyter helpers (no mandatory new deps)
│   ├── plots.py          # plot_equity, plot_drawdown, plot_price_with_trades, display_statistics_summary
│   └── quantstats_export.py  # quantstats_returns, export_quantstats_returns_csv
├── optimization/         # Optimizer, GeneticOptimizer — grid/random/GA, CPU+GPU backends
│   ├── engine.py         # Optimizer (grid/random, backend dispatch)
│   ├── genetic.py        # GeneticOptimizer (GA)
│   ├── cuda_eval.py       # GPU intent-array builder + CUDA grid evaluator
│   ├── gpu_capability.py  # per-strategy CPU/GPU capability gate
│   └── optimize_store.py  # SQLite trial/result store
├── wfo/                  # Walk-forward optimization research pipeline
│   ├── rolling_optimize.py # run_rolling_wfo() — per-window re-optimization WFO
│   └── wfo_result.py       # WFOResult + DSR/PBO/grid/R97 accessors
├── statistics/            # DSR, PBO/CSCV, per-window grid, R97 gate (anti-overfitting)
├── dashboard/            # HTML report generator (Jinja2 + ECharts)
├── export/               # Pine Script exporter
└── data/                 # CSVLoader, Resampler, validation

Execution flow:

  1. Strategy.init() — indicators computed, warmup tracked
  2. Strategy.generate_signals() — boolean arrays or Pine-style orders
  3. Reactor.run() — Numba JIT loop processes every bar: pending fills, trailing updates, liquidations, SL/TP, exits, entries
  4. Results — TradeList, Statistics, optional HTML report

Sample Data

CSV bars live under sampledata/<BASE>USDTUSDT/<timeframe>.csv. That directory is gitignored — fetch Binance USDT‑M perpetual OHLCV with CCXT:

uv sync --group data

# Default list: BTC, XRP, ETH, HYPE, BNB, DOGE — timeframes 30m, 1h, 2h
uv run --group data python scripts/fetch_binance_usdt_perp_ohlcv.py --output-dir sampledata

# Some tests also expect daily BTC / XRP files:
uv run --group data python scripts/fetch_binance_usdt_perp_ohlcv.py --output-dir sampledata \
  --bases BTC XRP --timeframes 1d

# 1-minute history (checkpointed + slower throttle; re-run to resume after 429s):
uv run --group data python scripts/fetch_binance_usdt_perp_ohlcv.py --output-dir sampledata \
  --bases BTC --timeframes 1m --since 2022-01-01 \
  --rate-limit-ms 250 --checkpoint-every 20

See the script docstring for the exact default symbol/timeframe lists.


License

MIT — see LICENSE for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

neutrinobt-0.2.0.tar.gz (373.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

neutrinobt-0.2.0-py3-none-any.whl (427.5 kB view details)

Uploaded Python 3

File details

Details for the file neutrinobt-0.2.0.tar.gz.

File metadata

  • Download URL: neutrinobt-0.2.0.tar.gz
  • Upload date:
  • Size: 373.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for neutrinobt-0.2.0.tar.gz
Algorithm Hash digest
SHA256 0e0c045630f20ad2a3fd9b1c44778e6b58b417a589c20751b509fe4fb1fa2c32
MD5 e75694118326b9b49ed6c13800bc0917
BLAKE2b-256 629cda7ed44d782eaebb040c803021b74e6a88d26ebaff423800273a8152f7e6

See more details on using hashes here.

File details

Details for the file neutrinobt-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: neutrinobt-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 427.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for neutrinobt-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1de7ddfd4a6afb2e3c78b11dcef835cfb1e761744a4f2c102a6b3f83e16a1fcf
MD5 29c25123995f1817617476f83824d532
BLAKE2b-256 ff002fb3365474a0063e9966ed66d561af8622c3547967b4e0475676e39fd835

See more details on using hashes here.

Release history Release notifications | RSS feed

0.4.0

2 files

0.3.0

2 files

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page