Skip to main content

Framework for LLM-driven autoresearch trading systems: walk-forward evaluator, anti-overfit gates, and swappable Broker/DataProvider/StrategyBase/CostModel interfaces. Ships an India/Dhan reference implementation.

Project description

autoresearch-trading

A framework for building LLM-driven autoresearch trading systems: an immutable walk-forward evaluator with anti-overfit gates, and four swappable extension points — Broker, DataProvider, StrategyBase, CostModel — so you can target your own market, broker, and signal.

It ships with a complete reference implementation: a long-only, delivery-only swing-trading system for Indian equities (NSE) executing through the Dhan HQ Trading API, using only free public data. That reference is the repo itself — strategy.py at the root, scripts/ for operations — built on top of the same autoresearch package you install.

⚠️ Not financial advice. This is research/engineering infrastructure. The reference system can place real orders with real money. Backtests overfit, live markets differ from simulations, and you are solely responsible for any capital you deploy. Start in paper mode and read the code before trading.


The idea

Three layers, decoupled by small interfaces:

  1. Research harness (autoresearch.research, autoresearch.backtest) — a walk-forward evaluator with anti-overfit gates (Bonferroni correction, random-walk Monte-Carlo null, sub-period stationarity, parsimony budget, cost-aware Sortino). This is the immutable part you don't edit.
  2. Strategy (StrategyBase) — your signal, as a backtrader strategy that changes positions only via order_target_percent.
  3. Execution + data (Broker, DataProvider, CostModel) — how orders reach a venue, how prices/universe are sourced, and what trading costs apply.

The autoresearch loop (scripts/loop.py) closes the circle: an LLM reads a journal of past hypotheses, proposes one edit to your strategy.py, runs the evaluator, and KEEP/REVERTs against the gates — so your editable strategy.py and journal.md are your project's files, while the immutable machinery is the installed library.


Install

Requires Python ≥ 3.11. With uv:

uv add autoresearch-trading   # or: pip install autoresearch-trading

The distribution is autoresearch-trading; the importable package is autoresearch (e.g. from autoresearch.interfaces import StrategyBase).

To work on the reference system, clone the repo and sync:

git clone <this-repo>
cd autoresearch-trading-india
uv sync --extra dev

Start your own project

The fastest way in — scaffold a project that runs immediately, then edit three files:

autoresearch-init my-quant       # or: uv run autoresearch-init my-quant
cd my-quant
python run.py                     # backtests on synthetic data — no setup

You now own strategy.py, provider.py, config.py, and journal.md. Edit them in that order — your signal, your data, your knobs. The library stays installed and untouched. (autoresearch-init is one command in this package, not a separate install.)

Quickstart (no data, no credentials)

Or run the bundled example — a toy backtest on deterministic synthetic data that shows the extension points wired together:

uv run python examples/minimal/run.py

This uses SyntheticDataProvider(DataProvider) + MinimalMomentum(StrategyBase) through the backtest engine. See examples/minimal/.

You can also generate a synthetic prices + universe pair directly:

uv run autoresearch-data            # writes storage/prices.duckdb + universe.duckdb

Getting the data (real market data)

All data is free and self-fetched — there is no dataset to buy. The reference system scrapes free public archives into local DuckDB stores. The only credential is a free FRED API key for macro series.

Data Source (free) Store
Stock prices NSE bhav archive (daily ZIPs) storage/prices.duckdb
Universe derived point-in-time from price history storage/universe.duckdb
Macro FRED (FRED_API_KEY) + yfinance indices (India VIX / Nifty) storage/macro.duckdb
Fundamentals yfinance + NSE XBRL filings storage/fundamentals.duckdb
News MoneyControl / Pulse RSS / NSE filings / RBI / SEBI storage/news.duckdb

The data stores are git-ignored and never shipped in the wheel — you regenerate them locally. Two steps:

cp .env.example .env            # add FRED_API_KEY (optional but recommended)

# 1. Fast bootstrap: last ~30 days, enough to start
uv run python -m scripts.bootstrap_ingest

# 2. Optional deep history for backtests (~hours, resumable)
uv run python -m scripts.backfill_5y --all
uv run python -m scripts.backfill_universe

Bringing your own market? Ignore NSE ingestion entirely and implement DataProvider for your source, returning the documented table shape (below).


Run the reference system

The India reference lives at the repo root (strategy.py) and in scripts/. It defaults to paper mode (DHAN_MOCK=1), so no broker account is needed to try it.

# Walk-forward backtest of the current strategy.py (+ anti-overfit gates)
uv run autoresearch-eval research
# equivalently: uv run python -m autoresearch.research.prepare research

# One end-to-end paper run for today
uv run python -m scripts.run_live --date $(date +%Y-%m-%d)

# One autoresearch loop iteration (LLM proposes a strategy.py edit, gated)
uv run python -m scripts.loop --iterations 1

The autoresearch loop needs an LLM CLI, not a Python SDK. It drives the model by shelling out to a local command, so there's no LLM package to install. Install and sign in to either Claude Code (the claude CLI) or the OpenAI Codex CLI (the codex CLI) and put it on your PATH — the loop (and the optional LLM classifiers) use whichever is available. Everything else — backtests, the evaluator, paper trading — needs no LLM at all.

The operational commands (run_live, daily_update, premarket_scan, daily_report, loop) live in scripts/ and run from a clone with python -m scripts.<name>. Enabling real live trading requires explicit, deliberate steps (a halt-flag gate + a paper-validation window) — see the code and CLAUDE.md.


Build your own

Implement the interfaces in autoresearch.interfaces and point the evaluator at your strategy. The India/Dhan classes are the reference implementations.

from autoresearch.interfaces import Broker, DataProvider, StrategyBase, CostModel
  • StrategyBase — subclass it; change positions only via order_target_percent. Put your strategy in a strategy.py at your project root (this is the file the autoresearch loop edits).
  • Brokerplace_order / get_positions / get_holdings / get_cash / get_fills / …. Reference: DhanBroker, DhanMock.
  • DataProviderread_prices + pit_universe. Reference: NSE bhav ingest.
  • CostModelcommission + round_trip_cost. Reference: IndiaCostModel.

DataProvider table-schema contract

The library reads adjusted daily bars in this shape (DuckDB daily_bars in the reference impl):

daily_bars(ticker TEXT, dt DATE, open DOUBLE, high DOUBLE, low DOUBLE,
           close DOUBLE, volume DOUBLE)   -- split/bonus-adjusted close

A point-in-time universe must be derivable from bar history alone (never a "current membership" list — that injects survivorship bias). See examples/minimal/provider.py for a working implementation and autoresearch/interfaces/data_provider.py for the full contract.


The research + anti-overfit harness

autoresearch.research.prepare is the immutable evaluator. It walk-forwards over train/validation folds, holds out a sealed test window, and scores each variant against atomic gates — a variant that fails any gate is rejected, not partially accepted. This is the point of the framework: the loop will try to overfit, and the gates are what catch it. Settings that a downstream user changes (capital, currency, universe size, cadence, vol target, dates, storage paths) live in autoresearch.config.Config with the India values as defaults.


Repository layout

autoresearch/            # the installable library
  interfaces/            #   Broker, DataProvider, StrategyBase, CostModel (ABCs)
  config.py              #   typed Config (India defaults)
  research/prepare.py    #   immutable walk-forward evaluator + gates
  backtest/              #   engine, metrics, risk, costs
  brokers/ data/ llm/ storage/   # India/Dhan reference implementations
strategy.py              # reference strategy (loop-editable, at repo root)
journal.md               # reference autoresearch memory (at repo root)
scripts/                 # reference operational CLIs
examples/minimal/        # runnable synthetic-data example
tests/                   # test suite

License

MIT.

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

autoresearch_trading-0.1.0.tar.gz (158.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autoresearch_trading-0.1.0-py3-none-any.whl (189.8 kB view details)

Uploaded Python 3

File details

Details for the file autoresearch_trading-0.1.0.tar.gz.

File metadata

  • Download URL: autoresearch_trading-0.1.0.tar.gz
  • Upload date:
  • Size: 158.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for autoresearch_trading-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c42e147967b98fcdd95eeb89ed8c3058e0f17229d40d8a2d5c5c97a9242162b1
MD5 0bb6636c2845c7c352dfc190b8492e61
BLAKE2b-256 1bfeefb15a1fb4c92765a5a3a497712787a7b90050d74ca1e616efcfd766fade

See more details on using hashes here.

File details

Details for the file autoresearch_trading-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: autoresearch_trading-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 189.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for autoresearch_trading-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b68c861e35d894343ab749069fe4eb5b58b24968d0a72586f408d96be082054d
MD5 bdc7b011ef32fdee6a39f626ef1f963e
BLAKE2b-256 c550ff77e7b572d945121499643fa65334b056b143d33a3d41f2cf406d5c0221

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page