Metadata-Version: 2.4
Name: backtestchat
Version: 0.1.0
Summary: Local-first agentic strategy lab CLI: chat, backtest, and paper-trade long/flat strategies on keyless Binance public data.
Project-URL: Homepage, https://github.com/barisarat/backtestchat
Project-URL: Repository, https://github.com/barisarat/backtestchat
Project-URL: Issues, https://github.com/barisarat/backtestchat/issues
Author: Baris Arat
License: MIT
License-File: LICENSE
Keywords: agent,backtest,binance,cli,langgraph,paper-trading,trading
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.12
Requires-Dist: httpx>=0.27.0
Requires-Dist: langchain-core>=0.3.0
Requires-Dist: langchain>=0.3.0
Requires-Dist: langgraph-checkpoint-sqlite>=2.0.0
Requires-Dist: langgraph>=0.2.60
Requires-Dist: plotly>=5.22.0
Requires-Dist: rich>=13.7.0
Requires-Dist: typer>=0.12.0
Provides-Extra: anthropic
Requires-Dist: langchain-anthropic>=0.2.0; extra == 'anthropic'
Provides-Extra: ollama
Requires-Dist: langchain-ollama>=0.2.0; extra == 'ollama'
Provides-Extra: openai
Requires-Dist: langchain-openai>=0.2.0; extra == 'openai'
Description-Content-Type: text/markdown

# backtestchat

An open-source, local-first agentic strategy lab in your terminal. Chat with a
LangGraph agent to fetch keyless Binance public market data, design and backtest
long/flat crypto strategies, and run simulated paper trades. Charts render to
self-contained plotly HTML that opens in your browser.

**Paper-only by design.** backtestchat simulates fills from closed bars. It never
places real orders and never needs exchange API keys. Market data comes from the
public, keyless Binance REST API. The only key you supply is your own model
(BYOK) key, or a local Ollama endpoint.

> backtestchat is a research and simulation tool and a portfolio/learning project.
> It is not financial advice and not a trading product. Do not use it to make
> investment decisions.

<!-- TODO: asciinema GIF of a chat session (quote -> backtest -> chart). -->
<!-- TODO: screenshot of a backtestReport chart. -->

## Quickstart

Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/).

```bash
git clone https://github.com/barisarat/backtestchat
cd backtestchat
uv sync --extra openai              # deps + the OpenAI model provider

export BACKTESTCHAT_MODEL=openai:gpt-5.4-nano
export OPENAI_API_KEY=sk-...

uv run backtestchat chat                # talk to the agent
uv run backtestchat runs sync           # advance paper runs to the latest closed bar
uv run backtestchat runs list           # check paper run status
```

Two things to know:

- The `backtestchat` command lives in the project venv, so either prefix every
  command with `uv run`, or activate the venv once with
  `source .venv/bin/activate` and call `backtestchat` directly.
- Always sync with the extra for the provider you use. A plain `uv sync`
  removes extras, and `backtestchat chat` will fail until you
  `uv sync --extra openai` again.

Market data works with **zero keys**; only the chat agent needs a model key.
Other providers (Anthropic, Ollama, ...) are covered under
[Model setup](#model-setup-byok).

## What it does

- **Chat** with a tool-calling agent (LangGraph) that maps your plain-English
  requests onto market-data, backtest, and paper-trade actions.
- **Backtest** ~11 single-signal long/flat strategies (SMA/EMA crossover, MACD,
  RSI, Bollinger, Donchian, ROC, stochastic, ATR channel, price-vs-SMA,
  buy & hold) with CAGR, Sharpe, max drawdown, win rate, and trade count.
- **Compare** several strategies at once, ranked, on one chart.
- **Paper-trade** a strategy with simulated fills. Runs advance by replaying
  closed bars - no daemon, no scheduler. Any command can trigger a cheap sync.
- **Charts** are deterministic plotly HTML written to `./artifacts`. The model
  never writes HTML; it only triggers the tools that build the charts.

Supported intervals: **15m, 1h, 4h, 1d**. Symbols: any Binance spot pair
(BTCUSDT, ETHUSDT, SOLUSDT, XRPUSDT, DOGEUSDT, ...).

## Model setup (BYOK)

backtestchat talks to any provider via LangChain's `init_chat_model`, configured with
a `provider:model` string in `BACKTESTCHAT_MODEL` (or `model = "..."` in
`./backtestchat.toml`). The default setup uses OpenAI:

```bash
uv sync --extra openai
export BACKTESTCHAT_MODEL=openai:gpt-5.4-nano
export OPENAI_API_KEY=sk-...
```

Any provider `init_chat_model` supports works the same way: install the matching
extra (`--extra anthropic`, `--extra ollama`, ...) and set `BACKTESTCHAT_MODEL` to
that provider's `provider:model` string plus its API key (Ollama runs locally
and needs no key).

If no model is configured, `backtestchat chat` prints these instructions and exits.
Check what is resolved with `backtestchat config`.

## Usage

```bash
uv run backtestchat chat
```

Then talk to it naturally:

```
you > what's BTC trading at?
you > backtest an ma crossover 20/50 on BTCUSDT 1h over the last 3 months
you > compare that against buy and hold and rsi
you > save that strategy            # asks you to confirm in the terminal
you > start a paper run with 5000 usdt   # asks you to confirm
you > list my paper runs
```

Charts open automatically in your browser and are saved under `./artifacts`.
Saving a strategy and starting a paper run pause for a y/n confirmation
(human-in-the-loop, implemented with LangGraph interrupts).

### Commands

```bash
backtestchat chat [--new] [--thread ID]   # agent REPL (resumes the last thread by default)
backtestchat runs list [--status active]  # list paper runs (stored state)
backtestchat runs sync                    # advance all active runs to the latest closed bar
backtestchat show [last|FILE]             # open a rendered chart artifact
backtestchat config                       # print resolved configuration
```

### How paper runs work

A paper run does not backdate: the first simulated fill happens on the first bar
that **closes after** you create the run, so a fresh run shows
"waiting for first tick" until then. Advancing a run replays every closed bar
since its last processed bar, one signal evaluation per bar. Because the
already-processed-bar guard is the only cadence control, `backtestchat runs sync` is
safe to run anytime and is idempotent.

## LangSmith tracing (optional)

Set the standard env vars and traces appear in your LangSmith project - no code
or flags required:

```bash
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=...
```

## Configuration

Resolved in order: environment variables > `./backtestchat.toml` > defaults.

| Key | Env var | Default |
|---|---|---|
| model | `BACKTESTCHAT_MODEL` | (unset; required for chat) |
| data dir | `BACKTESTCHAT_DATA_DIR` | `./data` |
| artifacts dir | `BACKTESTCHAT_ARTIFACTS_DIR` | `./artifacts` |

`./data` holds the sqlite store (strategies, paper runs, trades) and the
LangGraph checkpoint database. `./artifacts` holds rendered chart HTML. Both are
gitignored.

## Development

```bash
uv sync --extra openai  # dev dependencies included; keep your provider extra
uv run pytest -q        # deterministic, no network, no model key
```

The engine, signals, broker window logic, and paper runner are pure and tested
against fixture bars. Market-data and agent layers are tested with mocked HTTP
and a scripted fake model, so the whole suite runs offline.

## License

MIT - see [LICENSE](LICENSE).
