Bespoke trading strategy library — backtest, compare, and build custom strategies
Project description
bespoke
A Python library for backtesting, comparing, and building trading strategies. Bespoke provides a clean API for defining strategy logic, running historical simulations with realistic slippage modeling, and evaluating performance through standard financial metrics like Sharpe ratio, CAGR, max drawdown, and rolling-window composite scores.
Install
pip install bespoke
Quick Start
from bespoke import Backtester
from bespoke.strategies import get_strategy
strategy = get_strategy("spy_buy_and_hold")
bt = Backtester(strategy, start="2020-01-01", end="2025-12-31")
result = bt.run()
print(f"Return: {result['metrics']['total_return']:.2%}")
print(f"Sharpe: {result['metrics']['sharpe_ratio']:.2f}")
CLI
Bespoke includes a command-line interface for quick analysis.
# List all available strategies
bespoke list
# Show details for a strategy
bespoke info spy_buy_and_hold
# Run a backtest
bespoke backtest spy_buy_and_hold --start 2020-01-01 --end 2025-12-31
# Run on all 28 rolling windows (1Y-15Y x 4 end years)
bespoke backtest spy_buy_and_hold --windows
# Compare two strategies side by side
bespoke compare spy_buy_and_hold balanced_sixty_forty
# Save results to JSON
bespoke save spy_buy_and_hold --output results.json
Creating a Custom Strategy
Subclass BaseStrategy and implement generate_signals:
from bespoke.strategies.base import BaseStrategy, StrategyConfig
class MomentumStrategy(BaseStrategy):
def __init__(self):
super().__init__(StrategyConfig(
name="momentum",
description="Buy assets with positive 50-day momentum",
universe=["SPY", "QQQ", "IWM"],
rebalance_frequency="monthly",
max_position_size=0.50,
))
def generate_signals(self, date, prices, portfolio, data):
signals = {}
for sym in self.universe:
if sym in data and date in data[sym].index:
sma50 = data[sym].loc[:date, "SMA_50"].iloc[-1]
if prices.get(sym, 0) > sma50:
signals[sym] = 1.0
return signals
Then backtest it:
from bespoke import Backtester
bt = Backtester(MomentumStrategy(), start="2020-01-01")
result = bt.run()
Architecture
bespoke/
core/
backtester.py Event-driven backtester with slippage + rebalancing
portfolio.py Position tracking, cash management, trade history
metrics.py Sharpe, Sortino, CAGR, drawdown, alpha/beta, composite
data/
fetcher.py OHLCV via yfinance with parquet caching + indicators
strategies/
base.py BaseStrategy + StrategyConfig dataclass
registry.py Auto-discovery and name-based lookup
generic/ Baseline strategies (SPY, 60/40, three-fund)
compat/
loader.py Bridge to load external strategy collections
cli/
main.py Command-line interface (argparse)
Data flow:
Backtesterloads OHLCV data viafetch_ohlcv(cached locally)- Technical indicators are added (SMA, RSI, MACD, Bollinger, ATR)
- On each trading day,
Strategy.generate_signals()returns target weights Portfolioexecutes rebalancing trades with slippagecompute_metrics()evaluates the resulting equity curve
Available Strategies
Three baseline strategies are included out of the box:
| Name | Description | Universe |
|---|---|---|
spy_buy_and_hold |
100% S&P 500, never trade | SPY |
balanced_sixty_forty |
60% stocks / 40% bonds, monthly rebalance | SPY, AGG |
three_fund_passive |
50% SPY + 30% QQQ + 20% GLD | SPY, QQQ, GLD |
These baselines serve as the performance bar that any custom strategy must clear to justify its complexity.
The bespoke.compat module provides a bridge to load additional strategy collections. See bespoke/compat/loader.py for details.
Metrics
Every backtest produces:
- Total Return and CAGR -- absolute and annualized performance
- Sharpe Ratio -- risk-adjusted return (excess over risk-free rate)
- Sortino Ratio -- penalizes only downside volatility
- Max Drawdown -- worst peak-to-trough decline
- Calmar Ratio -- CAGR / max drawdown
- Win Rate -- fraction of positive trading days
- Alpha / Beta -- vs benchmark (when benchmark data available)
- Composite Score -- rolling-window consistency metric
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-strategy) - Add your strategy in
src/bespoke/strategies/ - Write tests in
tests/ - Run
pytestto verify - Submit a pull request
License
MIT License. See LICENSE for details.
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 bespoke-0.1.1.tar.gz.
File metadata
- Download URL: bespoke-0.1.1.tar.gz
- Upload date:
- Size: 506.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.26.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ac36bbcb7afc1039908e56015d0ae14a72e84f0ce6083cf2e636c366b643468
|
|
| MD5 |
01652676d0a64004412b49d165a58a5a
|
|
| BLAKE2b-256 |
6c819dbef1403594dd7436f9713218193a5ea027cc8e6439a5577d12078e7f39
|
File details
Details for the file bespoke-0.1.1-py3-none-any.whl.
File metadata
- Download URL: bespoke-0.1.1-py3-none-any.whl
- Upload date:
- Size: 232.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.26.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
828a38cee801ffd796fbfe51c844aee3c2f71b9d964c78ef1cff78eebfd3a532
|
|
| MD5 |
7b2f525f84e591de5e0cf43132e8b93c
|
|
| BLAKE2b-256 |
fe2944041e7ea55a2e47e1db8242a101d5a7d0f618c25e971a4beef9ca7fce2c
|