Open Net Worth
Open Net Worth is an open-source personal AI wealth assistant you run yourself: one ledger for your whole financial life, worked by an AI agent you control.
翻訳待ち
5,000 trading papers, each backtested on the same clean data, with the Python to run them. Read one in full for free, then make it yours in the browser or from Claude Code, Codex and Cursor.
翻訳待ち
金融Python · ShellGitHub @paperswithbacktestオンライン所有者未確認
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
The toolbox for developing systematic trading strategies. It includes datasets and strategy ideas to assist in developing and backtesting trading algorithms.
翻訳待ち
Loading the full README.
Read the full README ↗The pwb-toolbox package is designed to provide tools and resources for systematic trading strategies. It includes datasets and strategy ideas to assist in developing and backtesting trading algorithms.
To install the pwb-toolbox package:
pip install pwb-toolbox
This package requires Python 3.10 or higher.
To use PWB datasets, you can supply a Papers With Backtest API key via the PWB_API_KEY environment variable. When that is set,
load_dataset will download parquet shards directly from the PWB API, four at a time, into a local cache
(~/.cache/pwb_toolbox/api, or $PWB_CACHE_DIR/api; capped at PWB_API_CACHE_MAX_GB, 10 GB by default, least recently
used files evicted first; PWB_API_CACHE=0 turns it off). A file is kept under its content hash, so a second call, or a
new version of a dataset that leaves a month unchanged, downloads nothing for it. If no API key is available, you can
instead login to the Huggingface Hub (where public PWB datasets are hosted) with an access token:
huggingface-cli login
The pwb-toolbox package offers a range of functionalities for systematic trading analysis. Here are some examples of how to utilize the package:
The pwb_toolbox.datasets module offers to load datasets for different asset classes, such as bonds, commodities, cryptocurrencies, ETFs, forex, indices, and stocks, using the get_pricing or the load_dataset functions:
import pwb_toolbox.datasets as pwb_ds
df = pwb_ds.get_pricing(["AAPL", "MSFT", "GOOGL"])
df = pwb_ds.load_dataset("Bonds-Daily-Price")
df = pwb_ds.load_dataset("Commodities-Daily-Price")
df = pwb_ds.load_dataset("Cryptocurrencies-Daily-Price")
df = pwb_ds.load_dataset("ETFs-Daily-Price")
df = pwb_ds.load_dataset("Forex-Daily-Price")
df = pwb_ds.load_dataset("Indices-Daily-Price")
df = pwb_ds.load_dataset("Stocks-Daily-Price")
df = pwb_ds.load_dataset("Preferreds-Daily-Price")
df = pwb_ds.load_dataset("Warrants-Daily-Price")
df = pwb_ds.load_dataset("StructuredProducts-Daily-Price")
The 1-minute datasets (Stocks-1Min-Price, Cryptocurrencies-1Min-Price, Forex-1Min-Price) are one parquet shard per month. Bound the read with start, end and columns so only the months and columns you need are downloaded and read:
bars = pwb_ds.load_dataset(
"Stocks-1Min-Price",
symbols=["SPY", "QQQ"],
start="2024-01-01",
end="2024-03-31",
columns=["adj_open", "adj_close", "volume"],
)
Without start/end, a minute dataset still loads but warns (UnboundedMinuteLoadWarning): every month is downloaded, about 75 GB for the stocks.
For more, see docs/datasets.md.
The pwb_toolbox.backtesting module offers simple building blocks for running Backtrader simulations.
It runs on backtrader by default, or on Tradewind, the Apache 2.0 engine with the same API (pip install pwb-toolbox[tradewind]). Choose once, before pwb_toolbox.backtesting is imported: PWB_BACKTEST_ENGINE=tradewind in the environment, or pwb_toolbox.engine.select("tradewind") in code. The engine that was not chosen is never imported, and pwb_toolbox.backtesting.bt is the one that was.
Here is a strategy example:
import numpy as np
import backtrader as bt
import pwb_toolbox.backtesting as pwb_bt
import pwb_toolbox.datasets as pwb_ds
# ────────────────────────────────────────────────────────────────
# Toy dual-momentum: each month hold SPY if its lookback return > T-bill,
# otherwise sit in BIL. Kept minimal while using pwb_bt & pwb_ds.
# ────────────────────────────────────────────────────────────────
class SimpleMomentum(bt.Indicator):
"""12-month rate of change on close."""
lines = ("roc",)
params = (("period", 252),)
def __init__(self):
self.lines.roc = bt.indicators.RateOfChange(self.data.close, period=self.p.period)
class MonthlySwitcher(pwb_bt.BaseStrategy):
params = dict(
period=252, # ~12 months
risky="SPY",
safe="BIL",
leverage=1.0,
)
def __init__(self):
super().__init__()
# Attach momentum indicators to each data feed
self.mom = {d._name: SimpleMomentum(d, period=self.p.period) for d in self.datas}
self._last_month = -1
def next(self):
super().next()
# Rebalance only on month change
today = self.datas[0].datetime.date(0)
if today.month == self._last_month:
return
self._last_month = today.month
# Use prior bar to emulate "signal at month-end, trade next month"
idx = -1
spy_m = float(self.mom[self.p.risky].roc[idx])
bil_m = float(self.mom[self.p.safe].roc[idx])
# Decide allocation
hold_risky = (not np.isnan(spy_m)) and (not np.isnan(bil_m)) and (spy_m > bil_m)
targets = {
self.p.risky: self.p.leverage if hold_risky else 0.0,
self.p.safe: 0.0 if hold_risky else self.p.leverage,
}
# Set portfolio targets
for d in self.datas:
self.order_target_percent(d, targets.get(d._name, 0.0))
def run_strategy():
# Minimal universe fetched via pwb_ds inside pwb_bt
symbols = ["SPY", "BIL"]
result = pwb_bt.run_strategy(
indicator_cls=SimpleMomentum, # kept for compatibility, but not required externally
indicator_kwargs={"period": 252},
strategy_cls=MonthlySwitcher,
strategy_kwargs={"period": 252, "risky": "SPY", "safe": "BIL", "leverage": 1.0},
symbols=symbols,
start_date="2005-01-01",
cash=100_000.0,
)
return result
if __name__ == "__main__":
run_strategy()
To explore more, you can find over 140 strategy examples at https://paperswithbacktest.com/strategies).
For more about backtesting, see docs/backtesting.md.
This is the beginning of the README. Read the rest at the original. Read the full README ↗