Simple backtesting framework for trading strategies
Project description
Simple Backtest
I have removed my githistory because i want to treat this as my base with imporvement in data loader and custom error message A high-performance, asset-agnostic backtesting framework for Python
Features • Installation • Quick Start • Data Loaders • Documentation
📖 About
Simple Backtest provides a clean framework for running strategy backtests with strong validation, robust metrics, and extensible architecture.
You can still bring your own pandas DataFrame, but the project now also includes optional data source integrations so users can load and normalize OHLCV data faster.
✨ Features
- Backtesting Engine: Fast, deterministic strategy execution
- Validation First: Actionable errors for data, config, and strategy inputs
- Asset-Agnostic Design: Works with stocks, forex, crypto, ETFs, and more
- 20+ Metrics: Return, drawdown, Sharpe, Sortino, Calmar, alpha/beta, etc.
- Optimization: Grid search, random search, walk-forward
- Optional Data Integrations:
CSVLoaderYFinanceLoaderCCXTLoaderAlphaVantageLoaderPolygonLoader
📦 Installation
Core package
pip install simple-backtest
Optional loader dependencies
Install only what you use:
# Yahoo Finance
pip install yfinance
# Crypto exchange data
pip install ccxt
# REST API loaders (Alpha Vantage, Polygon)
pip install requests
Development setup
git clone <your-repository-url>
cd simple-backtest
pip install -e ".[dev]"
Requirements: Python 3.10+
🚀 Quick Start
Backtest from any OHLCV DataFrame
from simple_backtest import Backtest, BacktestConfig, MovingAverageStrategy
# data must contain: Open, High, Low, Close (Volume optional unless configured)
strategy = MovingAverageStrategy(short_window=10, long_window=30, shares=10)
config = BacktestConfig.default(initial_capital=10000)
backtest = Backtest(data, config)
results = backtest.run([strategy])
print(results.get_strategy(strategy.get_name()).summary())
Backtest using built-in CSV loader
from simple_backtest import Backtest, BacktestConfig, CSVLoader, MovingAverageStrategy
loader = CSVLoader()
data = loader.load("data/aapl.csv", start="2020-01-01", end="2023-12-31")
backtest = Backtest(data, BacktestConfig.default(initial_capital=10000))
results = backtest.run([MovingAverageStrategy(short_window=10, long_window=30, shares=10)])
🔌 Data Loaders
All loaders inherit from DataLoader and return a validated DataFrame with standardized columns:
Open, High, Low, Close, Volume
Validation is always run internally before the DataFrame is returned.
CSVLoader
- Reads local CSV files
- Auto-detects date column (
Date,date,Datetime,datetime, or datetime index) - Normalizes common column variants (
open→Open, etc.) - Supports optional date filtering via
startandend
from simple_backtest import CSVLoader
data = CSVLoader().load("prices.csv", start="2021-01-01", end="2021-12-31")
YFinanceLoader
- Uses
yfinance.download(...) - Handles yfinance MultiIndex column outputs
- Raises clear import/data errors
from simple_backtest import YFinanceLoader
data = YFinanceLoader().load("AAPL", "2020-01-01", "2023-12-31")
CCXTLoader
- Uses
ccxtexchange clients - Supports constructor args:
exchange_name, optionalapi_key,api_secret - Converts millisecond timestamps to
DatetimeIndex - Auto-paginates OHLCV fetches for larger ranges
from simple_backtest import CCXTLoader
loader = CCXTLoader(exchange_name="binance")
data = loader.load("BTC/USDT", "2021-01-01", "2021-12-31", timeframe="1d")
AlphaVantageLoader
- Uses Alpha Vantage daily REST endpoint
- Constructor requires
api_key - Parses API JSON into standardized OHLCV DataFrame
- Applies
start/endfiltering post-load
from simple_backtest import AlphaVantageLoader
loader = AlphaVantageLoader(api_key="YOUR_KEY")
data = loader.load("AAPL", "2020-01-01", "2023-12-31")
PolygonLoader
- Uses Polygon aggregates REST endpoint
- Constructor requires
api_key - Handles
next_urlpagination - Parses
o/h/l/c/v/tfields into standardized OHLCV DataFrame
from simple_backtest import PolygonLoader
loader = PolygonLoader(api_key="YOUR_KEY")
data = loader.load("AAPL", "2020-01-01", "2023-12-31", timespan="day", multiplier=1)
Create your own loader
import pandas as pd
from simple_backtest import DataLoader
class MyCustomLoader(DataLoader):
def load(self, symbol, start, end) -> pd.DataFrame:
# fetch/construct your data
data = pd.DataFrame(...)
return self._finalize_dataframe(data)
📚 Documentation
Built-in strategy helpers
When writing a custom strategy (subclass of Strategy), you can use:
self.has_position()self.get_position()self.get_cash()self.get_portfolio_value()self.buy(shares)self.sell(shares)self.sell_all()self.hold()self.buy_percent(percent)self.buy_cash(amount)
Config presets
from simple_backtest import BacktestConfig
config = BacktestConfig.default(initial_capital=10000)
config_zero_fees = BacktestConfig.zero_commission(initial_capital=10000)
config_hft = BacktestConfig.high_frequency(initial_capital=100000)
config_swing = BacktestConfig.swing_trading(initial_capital=10000)
Optimizers
GridSearchOptimizerRandomSearchOptimizerWalkForwardOptimizer
🧩 API Reference (What to Import)
This section explains:
- what can be imported directly from
simple_backtest - what should be imported from submodules
- what each import is typically used for
✅ Import from top-level package
These are re-exported in simple_backtest/__init__.py and are stable entry points for most users.
from simple_backtest import (
# Core
Backtest,
BacktestConfig,
Portfolio,
Strategy,
BacktestResults,
StrategyResult,
# Built-in strategies
BuyAndHoldStrategy,
DCAStrategy,
MovingAverageStrategy,
# Optimizers
Optimizer,
GridSearchOptimizer,
RandomSearchOptimizer,
WalkForwardOptimizer,
# Commission models
Commission,
PercentageCommission,
FlatCommission,
TieredCommission,
# Data loaders
DataLoader,
CSVLoader,
YFinanceLoader,
CCXTLoader,
AlphaVantageLoader,
PolygonLoader,
)
✅ Import from simple_backtest.utils
Use these for execution helpers, validation, logging, and custom commission wiring.
from simple_backtest.utils import (
# Execution price helpers
get_execution_price,
create_execution_price_extractor,
# Data/strategy validation
validate_dataframe,
validate_date_range,
validate_strategies,
# Validation exceptions
BacktestError,
DataValidationError,
DateRangeError,
StrategyError,
# Commission helper factory
get_commission_calculator,
create_custom_commission,
# Logging
get_logger,
setup_logging,
disable_logging,
enable_debug_logging,
)
✅ Import from simple_backtest.metrics
from simple_backtest.metrics import calculate_metrics, format_metrics
calculate_metrics: compute full metric dictionary from returns/trades/portfolio dataformat_metrics: convert metric dictionary into readable report text
✅ Import from simple_backtest.visualization
from simple_backtest.visualization import (
plot_equity_curve,
plot_drawdowns,
plot_returns_distribution,
plot_monthly_returns,
plot_trades,
plot_strategy_trades,
plot_rolling_metrics,
create_comparison_table,
plot_all,
)
⚠️ What is importable but not recommended as public API
You can technically import internals like:
from simple_backtest.metrics.definitions import calculate_sharpe_ratio
from simple_backtest.utils.execution import get_vwap
But these are lower-level internals and may change more often.
Prefer top-level package imports and subpackage __init__ exports shown above.
Quick guide: “which import does what?”
Backtest: runs strategies on price dataBacktestConfig: execution settings (capital, commission, execution price, etc.)Strategy: base class for custom strategy logicPortfolio: tracks cash, positions, and trades...Loaderclasses: fetch/normalize OHLCV data from source...Optimizerclasses: parameter search and evaluationCommissionclasses: trading-cost modelsutilsfunctions: validation, execution-price extraction, logging helpersmetricsfunctions: calculate/format performance metricsvisualizationfunctions: charts and comparison views
📌 One-page Import Cheat Sheet
| You want to... | Import from | Import this |
|---|---|---|
| Run a backtest | simple_backtest |
Backtest, BacktestConfig |
| Build custom strategy | simple_backtest |
Strategy |
| Use built-in strategies | simple_backtest |
MovingAverageStrategy, BuyAndHoldStrategy, DCAStrategy |
| Load CSV data | simple_backtest |
CSVLoader |
| Load Yahoo Finance data | simple_backtest |
YFinanceLoader |
| Load crypto exchange data | simple_backtest |
CCXTLoader |
| Load Alpha Vantage data | simple_backtest |
AlphaVantageLoader |
| Load Polygon data | simple_backtest |
PolygonLoader |
| Create your own loader base | simple_backtest |
DataLoader |
| Use commission models | simple_backtest |
Commission, PercentageCommission, FlatCommission, TieredCommission |
| Optimize parameters | simple_backtest |
GridSearchOptimizer, RandomSearchOptimizer, WalkForwardOptimizer |
| Validate input data/strategies | simple_backtest.utils |
validate_dataframe, validate_date_range, validate_strategies |
| Build execution price logic | simple_backtest.utils |
get_execution_price, create_execution_price_extractor |
| Configure logging | simple_backtest.utils |
setup_logging, enable_debug_logging, disable_logging |
| Compute metrics | simple_backtest.metrics |
calculate_metrics, format_metrics |
| Plot charts | simple_backtest.visualization |
plot_equity_curve, plot_drawdowns, plot_returns_distribution, plot_monthly_returns, plot_trades, plot_strategy_trades, plot_rolling_metrics, create_comparison_table, plot_all |
Rule of thumb: Prefer simple_backtest and package __init__ exports first. Use deep/internal module imports only when you intentionally need low-level internals.
📓 Notebooks
Jupyter examples are available in the notebooks folder:
01_basic_usage.ipynb02_candle_strategies.ipynb03_ta_strategies.ipynb04_ml_strategies.ipynb05_commission_usage.ipynb06_advanced_optimization.ipynb
🛠️ Development
Run tests
pytest
Run linting
ruff check simple_backtest tests
Format
ruff format simple_backtest tests
🤝 Contributing
Contributions are welcome.
- Fork repository
- Create branch
- Add tests for changes
- Run
pytestandruff check - Open pull request
📄 License
MIT. See LICENSE.
📬 Support
- Issues: Use your repository issue tracker
- Discussions: Use your repository discussions page
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 simple_backtest_kankane-0.3.3.tar.gz.
File metadata
- Download URL: simple_backtest_kankane-0.3.3.tar.gz
- Upload date:
- Size: 52.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14c2d656f299d335e83ec060717c97eeac536776c2262a66f187aeb37501eec0
|
|
| MD5 |
a58a5966e0c7bc291b724e9497a84cad
|
|
| BLAKE2b-256 |
7b7aed162dde9cb021afbc0e541d89dc829e3c4eea3c05ef4b5f864d7a65b930
|
File details
Details for the file simple_backtest_kankane-0.3.3-py3-none-any.whl.
File metadata
- Download URL: simple_backtest_kankane-0.3.3-py3-none-any.whl
- Upload date:
- Size: 64.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
843a5ef045db643ab9c0e518de559b7eaac209f61b5b7cd6bccf72e11ee07d79
|
|
| MD5 |
20d97220864072513ae39e5f9d4c73c9
|
|
| BLAKE2b-256 |
0e879d47307df70b55f08a76d95b1a38f74465a8e291aad6e9e3d329debf333d
|