Antback: Lightweight Backtesting with Heavyweight Insight
Project description
Antback
Antback: Fast, Transparent, and Debuggable Backtesting
A lightweight, event-loop-style backtest engine that allows a function-driven imperative style using efficient stateful helper functions and data containers.
Key Features
- Transparency: Every step is visible and debuggable. No black-box logic.
- Balances simplicity with robustness - ideal for rapid strategy prototyping.
- Interactive HTML Reports: Detailed reports with sorting and filtering capabilities via DataTables.
- High Performance: Optimized data structures for speed - very fast.
- Easy to use with different data sources - only needs
dateandpricevalues. - Avoids Lookahead Bias: by processing data sequentially. Use wait functions to enforce delays between signals.
Installation
A key feature is the generation of interactive HTML reports, which allow for easy inspection of trades. The lightweight df2table module is used for this purpose. For Excel reports, xlreport is used.
pip install antback df2tables xlreport
Core functionality requires only numpy and pandas (pandas for reporting only).
Demo
import antback as ab
ab.demo()
The demo feature generates random trades of several stocks at random prices and generates an interactive report. A profit is slightly more likely than a loss—it's a demo, after all.
Quick Start
Simple SMA Crossover Strategy
import numpy as np
import antback as ab
import yfinance as yf
symbol = "QQQ"
data = yf.Ticker(symbol).history(period='10y')
port = ab.Portfolio(10_000, single=True)
fast, slow = 10, 30
prices = ab.RollingList(maxlen=slow)
cross = ab.new_cross_func()
for date, price in data["Close"].items():
prices.append(price)
price_history = prices.values()
signal = None # Reset signal
if len(price_history) >= slow:
fast_ma, slow_ma = np.mean(price_history[-fast:]), np.mean(price_history[-slow:])
direction = cross(fast_ma, slow_ma) # active crosses passive
if direction == "up":
signal = "buy"
elif direction == "down":
signal = "sell"
port.process(signal, symbol, date, price)
port.basic_report(show=True)
descr = f"Simple SMA Crossover on {symbol}"
port.full_report("html", outfile=f"{descr}_report.html", title=descr)
Html report screenshot
Interactive Filtering trades
Generate excel report
port.full_report('excel', outfile=f'{descr}_report.xlsx', title=descr)
See detailed excel report generated with above example.
Note: In fact, the average lengths in this case are slightly optimized; see: examples/07_optimization.py. The results may be even better if trailing ATR stop is used (examples/04_atr_stop.py) for the sell signal instead of the averages.
Core Components
Portfolio Class
The main trading engine that handles position management, trade execution, and performance tracking:
port = ab.Portfolio(
cash=10_000, # Starting capital (minimum 10,000)
single=True, # Single asset mode
warn=False, # Show warnings
allow_fractional=False, # Allow fractional shares
fees=0.0015 # Trading fees (0.15%)
)
Trading Patterns:
- Simple strategies: Use
port.process()
if direction == "up":
signal = 'buy'
elif direction == "down":
signal = 'sell'
port.process(signal, symbol, date, price)
- Complex strategies: Use
port.buy(),port.sell(),port.update()
if direction == "up":
port.buy(symbol, date, price)
elif direction == "down":
port.sell(symbol, date, price)
port.update(symbol, date, price)
Important Notes
- No re-buying or re-selling: Duplicate signals are ignored (set
warn=Trueto see warnings) - Multi-position support - Currently supported with manual trade sizing via
fixed_valparameter. (set single=False) - Intraday support: Available but not extensively tested
- Long-only: Currently, only long positions are possible.
More Examples & Use Cases
Explore the examples to see Antback in action—from basic strategies to multi-asset rotations.
Useful functions
Wait Functions - Preventing Lookahead Bias
Example use of a wait function.
sell_timer = ab.new_wait_n_bars(4) # wait 4 bars, then sell
for date, price in data:
signal = None
ready_to_sell = sell_timer(bar=date)
if ready_to_sell:
signal = 'sell'
if buy_conditon:
signal = 'buy'
sell_timer(start=True)
port.process(signal, symbol, date, price)
See examples 05_easter_effect_test.py.
There is also a per-ticker wait version (new_multi_ticker_wait) that creates separate functions for each symbol: wait demo
Cross Function
new_cross_func() returns a stateful crossover detector function that tracks when one time series crosses another.
The returned function compares an active and passive series value at each call and returns:
- "up" when the active value crosses above the passive
- "down" when the active crosses below
- None if there's no crossover or insufficient data
Optimized Data Structures
RollingArray
Fast numpy-based rolling window (Uses manual slice assignment ([:] = [...]) In-place operation; avoids temporary memory allocations. can be 2 to 10 times faster than np.roll.
prices = ab.RollingArray(window_size=50)
prices.append(new_price)
price_history = prices.values()
RollingList
Efficient deque-based storage for objects:
prices = ab.RollingList(maxlen=30)
prices.append(price_data)
recent_prices = prices.values()
Multi-ticker strategies
For more advanced multi-ticker strategies or those using machine learning, it's often necessary to track more than a few dozen rolling features. The NamedRollingArrays and PerTickerNamedRollingArrays classes are available for this purpose (rolling demo).
Performance & Technical Indicators
Antback does not include its own indicators (except for a useful ATR stop line), but you can use any technical analysis (TA) library. Antback is most suitable with event-driven technical indicators. For optimal performance, talipp indicators, which is designed for streaming data may be used:
from talipp.indicators import SMA
fast_sma, slow_sma = SMA(period=10), SMA(period=30)
for date, price in data.items():
fast_sma.add(price)
slow_sma.add(price)
if fast_sma[-1] and slow_sma[-1]: # Check if indicators have valid data
signal = determine_signal(fast_sma[-1], slow_sma[-1])
Performance
Benchmark data: Although Antback was not specifically designed for speed, it is surprisingly fast. Run the benchmark included with the examples (30-year SPY moving average crossover).
examples/11_simple_benchmark.py
License
MIT
Perfect for teaching, prototyping, and production backtesting. Excellent clarity and control per bar.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file antback-0.0.2.tar.gz.
File metadata
- Download URL: antback-0.0.2.tar.gz
- Upload date:
- Size: 212.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55da050bd23ddd492ca46158c25de1666c60578be24184f1b3ace94d4b3ccce3
|
|
| MD5 |
f5e615609d30c28223f6885b1ffd8094
|
|
| BLAKE2b-256 |
3fb45a3e0bc81c778a22e1d132d23ec4c45484994797af19281905ce63a4bfe6
|
File details
Details for the file antback-0.0.2-py2.py3-none-any.whl.
File metadata
- Download URL: antback-0.0.2-py2.py3-none-any.whl
- Upload date:
- Size: 59.9 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c0f76921d61979ae34e18ceabe2f308d99ab8e76d90b691956c77a5790b3a2d
|
|
| MD5 |
ba9b9533c1abb57989c2732d0faaba56
|
|
| BLAKE2b-256 |
fef0cb3ee7e56d2391a4c28ad997f9ef504ecf3309d31c4f96e50a61be4e27df
|