Backtest smarter.
Ship faster.

71 technical features, realistic execution modeling, and 27 chart types — one API call away. No infra to manage.

Get Started Live API Docs
$ pip install cobweb-py
71
Technical features
27
Chart types
3
Execution horizons
<30
Lines to backtest
📊

71 Technical Features

Returns, momentum, MACD, RSI, Bollinger, ATR, stochastic, volume, risk, beta, regime detection. Computed server-side, lazily evaluated.

Realistic Execution

Spread, slippage, market impact (sqrt model), participation caps, and multi-bar order slicing. Three horizon presets: intraday, swing, longterm.

🧪

Full Backtest Engine

Signal-to-trade conversion, cash/margin constraints, rebalance modes, and RL-ready reward series with turnover and drawdown penalties.

📈

27 Plot Types

Equity curves, drawdown, rolling Sharpe/Sortino, regime performance, trade analysis, volume diagnostics, correlation heatmaps, and more.

🐍

Python SDK

pip install cobweb-py — accepts CSV, DataFrame, or JSON. Includes scoring, signal generation, and Plotly chart helpers.

🌐

REST API

Three endpoints: /features, /backtest, /plots. JSON in, JSON out. Works from any language.

30 lines to a full backtest

Grab data, compute features, generate signals, and backtest with realistic friction.

import yfinance as yf
from cobweb_py import CobwebSim, BacktestConfig, fix_timestamps, print_signal
from cobweb_py.plots import save_equity_plot

# Grab SPY data
df = yf.download("SPY", start="2020-01-01", end="2024-12-31")
df.columns = df.columns.get_level_values(0)
df = df.reset_index().rename(columns={"Date": "timestamp"})
rows = df[["timestamp","Open","High","Low","Close","Volume"]].to_dict("records")
data = fix_timestamps(rows)

# Connect (free, no key needed)
sim = CobwebSim("https://web-production-83f3e.up.railway.app")

# Simple momentum: long when price > 50-day SMA
close = df["Close"].values
sma50 = df["Close"].rolling(50).mean().values
signals = [1.0 if c > s else 0.0 for c, s in zip(close, sma50)]
signals[:50] = [0.0] * 50

# Backtest with realistic friction
bt = sim.backtest(data, signals=signals,
    config=BacktestConfig(exec_horizon="swing", initial_cash=100_000))

print_signal(bt)
save_equity_plot(bt, out_html="equity.html")