Vectorized backtesting & forward-testing framework for intraday strategies
Project description
mtrader
Vectorized backtesting & forward-testing framework for intraday strategies.
Clean raw tick/minute data, compute 40+ technical indicators, define entry/exit conditions in a declarative dict format, and execute vectorized simulations with Sharpe, drawdown, and volatility metrics — all in NumPy/CuPy with optional Numba acceleration.
Installation
pip install numpy pandas inspecty numba
# optional — GPU acceleration
pip install cupy
Quick start
import pandas as pd
from mtrader import clean_data, add_indicators
from mtrader import precalculate_exit_time_amount_profit
from mtrader import take_trade_on_condition_numpy
# 1. Load & clean OHLC data
df = pd.read_csv("data.csv")
df = clean_data(df, start_time="09:15", end_time="15:30",
start_date="2024-01-01", end_date="2024-12-31")
# 2. Add indicators
df = add_indicators(df, add=["sma1", "ema1", "vwap", "close", "high", "low"],
rolling_minutes=[5, 15, 30])
# 3. Define exit strategy
conditions = [[
{
"first_column_name": "can1_sma1_p5",
"second_column_name": "close",
"shift_down_first": 0,
"shift_down_second": 0,
"lower_range_of_difference": -np.inf,
"upper_range_of_difference": -50,
"perform_normalization_of_diff": False,
}
]]
df = precalculate_exit_time_amount_profit(
df, conditions, buy_or_sell="buy",
target_delta=200, stoploss_delta=100,
)
# 4. Run backtest
trades, final_capital, metrics = take_trade_on_condition_numpy(
df, conditions, leverage=1, initial_capital=100000
)
print(metrics)
Pipeline
raw CSV/DataFrame
│
▼
clean_data() — auto-detect column types, normalize OHLC,
│ fill gaps, handle stock splits
▼
add_indicators() — SMA, EMA, WMA, SSMA + volatilities + VWAP,
│ distance-to-MA, z-score, normalizations
▼
precalculate_exit_time_amount_profit()
│ — vectorized exit signal engine with
│ target & stoploss (absolute or %)
▼
take_trade_on_condition*()
— capital simulation, Sharpe, drawdown
Modules
| Module | Exports | Description |
|---|---|---|
data_cleaner |
clean_data, detect_data_types_with_formats, fill_missing_rows |
Column-type detection, OHLC normalization, gap filling, split adjustment |
indicators |
ema, evol, wma, wvol, ssma, ssvol |
Individual MA & volatility functions on raw numpy arrays |
indicator_engine |
add_indicators, add_indicators_on_group |
Multi-period indicator computation with automatic dependency resolution |
monotonic_stack |
monotonic_stack_for_value1_gt_value2, monotonic_stack_for_value1_lessthan_value2 |
Numba-accelerated next-index lookup for exit timing |
exit_strategy |
precalculate_exit_time_amount_profit |
Vectorized exit signal generation with target, stoploss, and condition-based exits |
trading |
take_trade_on_condition, take_trade_on_condition_numpy, take_trade_on_condition2, take_trade_on_condition3, take_trade_on_condition_vectorized, take_trade_on_condition_vectorized2, update_cond |
Trade execution engines — NumPy, CuPy, multi-range grid search, GPU-optimized variants |
optimize_exit |
find_best_exit |
Grid search over exit params (target, stoploss) to maximize Sharpe / capital |
utils |
printo, timenum |
Time-string conversion |
Indicators
Moving averages
| Code | Name |
|---|---|
sma |
Simple Moving Average |
ema |
Exponential Moving Average |
wma |
Weighted Moving Average |
ssma |
Smoothed Simple Moving Average |
Volatility
| Code | Name |
|---|---|
svol |
Simple volatility (std) |
evol |
Exponentially-weighted volatility |
wvol |
Weighted volatility |
ssvol |
Smoothed volatility |
Price / volume
vwap,ewap,iwap— volume, equal-weighted, and incremental-weighted average pricemax,min— rolling high/lowmax_inday,min_inday— intraday rolling high/low
Feature codes
Base signals are referenced by numeric codes:
| Code | Signal |
|---|---|
0, 1 |
close |
2 |
av2 (H+L)/2 |
3 |
av3 (H+L+C)/3 |
4 |
av4 (O+H+L+C)/4 |
5 |
open |
6 |
high |
7 |
low |
8..34 |
dif, ret, lret for 1/3/5/10/15/20/30/60 bars |
Column naming: can1_{indicator}{code}_p{period}, e.g. can1_sma1_p5.
Normalizations
Prefix an indicator name for ratio-based forms:
| Prefix | Normalization |
|---|---|
SMN |
Divide by SMA |
EMN |
Divide by EMA |
WMN |
Divide by WMA |
SSMN |
Divide by SSMA |
SVN |
Divide by volatility (std) |
EVN |
Divide by EW volatility |
WVN |
Divide by weighted volatility |
SSVN |
Divide by smoothed volatility |
Z |
Z-score |
BRN, TMN |
Base-ratio / time normalization |
Suffix controls the denominator source: ""/F uses the signal itself; P/0 uses close price; B uses the base signal; a numeric code uses that feature.
Condition format
Entry and exit conditions use a declarative dict structure:
[
[ # OR group — any matching group triggers
{ # AND within a group — all must match
"first_column_name": "can1_sma1_p5",
"second_column_name": "close",
"shift_down_first": 0,
"shift_down_second": 0,
"lower_range_of_difference": -np.inf,
"upper_range_of_difference": -50,
"perform_normalization_of_diff": False,
}
]
]
The helper update_cond() recursively rewrites fields across nested condition lists.
Exit strategy
precalculate_exit_time_amount_profit() supports:
- Condition-based exits — exit when column difference falls in a range
- Target (take-profit) — absolute delta or normalized (% of price)
- Stoploss — absolute or normalized; configurable slippage and candle-close wait
- Combined — earliest of condition, target, or stoploss wins
- Side —
buyorsellmode
Trade simulation
| Function | Backend | Use case |
|---|---|---|
take_trade_on_condition_numpy |
NumPy | Standard backtesting |
take_trade_on_condition |
NumPy/CuPy auto | Same, with GPU fallback |
take_trade_on_condition2 |
CuPy views | Memory-efficient GPU |
take_trade_on_condition3 |
CuPy | Simplified GPU variant |
take_trade_on_condition_vectorized |
CuPy 2D | Grid search over range combinations |
take_trade_on_condition_vectorized2 |
CuPy 2D | Optimized grid search |
All return (filtered_trades_df, final_capital, metrics_dict) where metrics include:
VolatilitySharpe RatioMax Drawdown
Exit optimization
Given a fixed entry condition, find_best_exit() grid-searches over exit parameters to maximize Sharpe, final capital, or any other metric.
from mtrader import find_best_exit
best_params, results_df = find_best_exit(
df,
entry_conditions=entry_conditions,
buy_or_sell="buy",
target_deltas=[50, 100, 150, 200, 300],
stoploss_deltas=[25, 50, 75, 100],
metric="sharpe", # or "final_capital", "max_drawdown"
risk_free_rate=0.05,
)
print(best_params)
# {'target_delta': 150, 'stoploss_delta': 75, ...}
# Full grid in results_df:
# target_delta | stoploss_delta | trades | final_capital | sharpe | volatility | max_drawdown
Works with absolute deltas, normalized (% of price) deltas, and custom exit conditions. Set verbose=True to see each combination's results as they run.
Data cleaning
clean_data() handles the messy real-world pipeline:
- Auto-detects datetime, numeric, and string columns
- Identifies date/time columns and combines them
- Maps columns to
open,high,low,close,volume - Rounds timestamps to the minute and deduplicates
- Forward-fills zero-price candles
- Split detection — automatically detects and adjusts for stock splits and reverse mergers (≥30% gap, validates integer ratio 2:1 to 5:1)
- Filters by date and time range
- Drops days with insufficient records
- Optionally fills intraday gaps
Testing
python -m pytest mtrader/tests/test_backtest.py -v
15 end-to-end tests cover: data cleaning, indicator computation, exit precalculation, trade simulation (NumPy + CuPy pipelines), empty-trade edge cases, monotonic stack correctness, and utility functions.
Dependencies
- Required:
numpy,pandas,inspecty - Optional:
numba(monotonic stack acceleration),cupy(GPU trading)
License
MIT
Project details
Release history Release notifications | RSS feed
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 mtrader-0.3.0.tar.gz.
File metadata
- Download URL: mtrader-0.3.0.tar.gz
- Upload date:
- Size: 24.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25b818c0df11faa16a980865126403d4891fa732eb36cdce5427a76c2f86c69f
|
|
| MD5 |
f0d5d78c0849257eabba78ac3b8a996e
|
|
| BLAKE2b-256 |
a583fab65c5f91c9a0c07df7ef776b198c0685bd1d7e6d11e6a324f55b03163e
|
File details
Details for the file mtrader-0.3.0-py3-none-any.whl.
File metadata
- Download URL: mtrader-0.3.0-py3-none-any.whl
- Upload date:
- Size: 22.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da984d3e199dd9f973b4890714d6dab91d35e9b95c7339f339dd21be6e9f75a9
|
|
| MD5 |
092632c68820bdb504075afe8a10031c
|
|
| BLAKE2b-256 |
c83dc3c2c8b414c0dff3f188cfcbd755c4a2722b329454fdaf4249e43b05a6da
|