Skip to main content

A historical market simulation environment for testing AI trading agent reasoning against real market data.

Project description


tags: [finlet, readme, overview, trading, AI] keywords: Finlet, evaluation harness, AI trading agents, backtesting alternative, FastAPI, MCP priority: normal

Finlet

An evaluation harness for AI trading agents. Daily-timeframe. US equities. Long-only.

Test your AI agent's reasoning — not just its algorithms.

Finlet is an agent evaluation harness that tests whether AI trading agents make sound decisions with the information available to them. It provides a simulation clock that controls what data your agent can see, a Date Ceiling Enforcer that strips future data from every response, and a tamper-evident reasoning trace that logs every query and decision with SHA-256 checksums.

This is not a backtester. Backtesters test strategies against historical data. Finlet tests whether your agent reasons well given the same information a human analyst would have had on that date.

Why Finlet?

Most backtesting frameworks test algorithms. Finlet tests reasoning.

As a backtester, Finlet would lose to QuantConnect on every metric — data coverage, asset classes, speed. As an evaluation harness, it has no direct product competitor.

  • Date Ceiling Enforcer — Defense-in-depth runtime enforcement strips any data past the simulation clock. Property-based tests prove no future item passes. No competitor has an equivalent.
  • SHA-256 Reasoning Trace — Every query, decision, and order is logged with tamper-evident checksums. No backtester tracks agent reasoning.
  • Cross-Scenario Leaderboard — Standardized evaluation with composite scoring across returns, risk, drawdown, reasoning quality, and information efficiency
  • Real data sources — S3 Parquet price data, SEC EDGAR filings, FRED economic indicators, Finnhub news — not synthetic datasets
  • MCP native — Connect Claude Code (or any MCP client) directly as a trading agent via 16 purpose-built tools

v1 Scope

Finlet v1 is intentionally scoped to daily-timeframe, US-equities, long-only evaluation. These are design choices, not gaps:

Scope Decision Rationale
EOD data only Agent evaluation tests reasoning quality, not execution speed
US equities only Deepest data coverage (price, filings, economic, news)
Long-only Isolates reasoning from margin/borrow mechanics
No partial fills Honest about what EOD data supports (no order book depth)
No live/paper trading Evaluation harness, not trading platform

See docs/V1_SCOPE.md for the complete scope document with rationale.


Quick Start

Finlet's launch user is an LLM agent invoking via CLI or MCP, not a human clicking a UI. The web dashboard at finlet.dev is a read-only monitoring surface for sessions your agent drives — order entry, plugin configuration, and account management all live behind the CLI/MCP. Setup guide for agents: finlet.dev/setup. Machine-readable index: finlet.dev/llms.txt.

1. Install the CLI

pip install finlet
# Activate your virtualenv (`source .venv/bin/activate`) so the
# `finlet` command lands on your PATH.

2. Connect Claude (or any MCP client) as a trading agent

Add Finlet's MCP server to your Claude Code config (.claude.json or VS Code settings):

{
  "mcpServers": {
    "finlet": {
      "command": "finlet",
      "args": ["mcp", "serve"]
    }
  }
}

Then prompt the agent: "Use Finlet to analyze AAPL's fundamentals as of January 2024 and decide whether to buy." The agent gets purpose-built tools (get_price_data, get_fundamentals, submit_order, advance_time, etc.) — see the MCP Tools section below or dashboard/agent-guide.html (/agent-guide) for the full inventory.

MCP-native auth with OAuth 2.1

The MCP tool surface authenticates via OAuth 2.1 + PKCE Bearer tokens only — api_key as a tool argument is rejected with a 401 envelope. Run finlet auth login to mint a token (Claude Desktop / Cursor / Windsurf use their built-in OAuth flows automatically). REST /v1/... endpoints are unchanged. See docs/MCP_OAUTH_MIGRATION.md for per-client setup.

3. Drive a session from the CLI

# Start the API server (also serves the read-only dashboard at /)
finlet serve

# Create a session
finlet session create \
  --name tech-test \
  --start 2024-01-02 \
  --capital 100000 \
  --universe AAPL,GOOGL,MSFT,NVDA

# Submit a market order (also available via the MCP `submit_order` tool)
finlet order \
  --session <session-id> \
  --side BUY \
  --ticker AAPL \
  --quantity 50 \
  --type MARKET

# Inspect portfolio state
finlet portfolio --session <session-id>

# Configure plugin API keys
finlet plugins add finnhub --api-key=YOUR_KEY
finlet plugins add fred --api-key=YOUR_KEY

The cloud equivalent (finlet.dev) accepts the same calls — set FINLET_API_URL=https://finlet.dev and pass FINLET_API_KEY=<your_key> after registering on the site.

4. Watch your agent work in the monitoring dashboard

Visit https://finlet.dev (or http://localhost:8000 when running locally) to see the read-only monitoring surface for your agent's sessions: equity curve, positions, trade log, reasoning trace, plugin health, leaderboard. The dashboard observes — it does not control. All write paths are CLI/MCP-only post-2026-05-06; cut UI is preserved at legacy/dashboard-ui/. See docs/decisions/ui-removal-launch-cut.md for the rationale.

Direct REST API (alternative to CLI/MCP)

Any HTTP client works:

import httpx

async with httpx.AsyncClient(base_url="http://localhost:8000") as client:
    clock = await client.get(f"/sessions/{session_id}/clock")
    prices = await client.get(
        f"/sessions/{session_id}/market/price",
        params={"ticker": "AAPL", "period": "3mo"},
    )
    await client.post(f"/sessions/{session_id}/trade/order", json={
        "side": "BUY",
        "ticker": "AAPL",
        "quantity": 50,
        "order_type": "MARKET",
        "reasoning": "Strong Q4 earnings beat, raising guidance, reasonable P/E",
    })

Features

Simulation Clock

Three modes to control how time flows:

Mode Behavior
FROZEN Clock is stopped. Agent can make unlimited queries at the current time.
STEPPING Clock advances by a fixed interval when explicitly told to step.
CONTINUOUS Clock advances in real-time at a configurable speed multiplier.

The clock only moves forward when explicitly advanced. No implicit time progression.

Date Ceiling Enforcer

Defense-in-depth protection against future data leakage:

  • All timestamps in response data must be <= current sim clock time
  • Items with timestamps after the ceiling are stripped
  • Items without timestamps are excluded by default
  • Strip counts are logged internally but never exposed to the agent (that would leak information about future data existence)

Portfolio Engine

Full portfolio tracking with computed metrics:

  • Cash tracking, position management, P&L (realized + unrealized)
  • Sharpe ratio, max drawdown, win rate
  • Equity curve time series for charting

Order System

Market, limit, and stop orders with full lifecycle tracking:

PENDING -> FILLED | CANCELLED | REJECTED

Each order supports an optional reasoning field for trace logging.

Plugin System

Extensible data source architecture. Built-in plugins connect to real financial APIs:

Plugin Data Type API Key Notes
PricePlugin Price (OHLCV) None S3 Parquet-backed historical price data.
EDGAR SEC Filings None* 10-K, 10-Q, 8-K, 13-F, Form 4. *Requires User-Agent email.
FRED Economic Free key GDP, unemployment, CPI, rates. ALFRED vintage dates.
Finnhub News + Fundamentals User key Company news, earnings, fundamentals. 60 calls/min free tier.
# Configure plugin API keys
finlet plugins add finnhub --api-key=YOUR_KEY
finlet plugins add fred --api-key=YOUR_KEY

Plugin configuration is stored at ~/.finlet/plugins.json (never committed to git).

Reasoning Trace

Every agent interaction is logged:

  • Action type: What kind of query or action (price, news, filing, order, etc.)
  • Sim time + real time: When it happened in simulation and wall clock
  • Request params: What was requested
  • Response summary: What was returned
  • Reasoning: Agent's own explanation for the action
  • Latency: How long the operation took

Leaderboard

Standardized evaluation across 5 scenarios with composite scoring. Agents are scored on:

  • Portfolio returns vs. benchmark
  • Risk-adjusted returns (Sharpe ratio)
  • Maximum drawdown
  • Reasoning quality
  • Information efficiency (returns per API call)

Opt in to data sharing to appear on the public leaderboard and compare your agent against others.


Architecture

+-------------------------------------------------------------+
|                     AI Trading Agent                         |
|               (Claude Code, custom bot, etc.)                |
+----------+------------------------------+--------------------+
           | MCP (stdio)                  | REST API
           v                              v
+-------------------------------------------------------------+
|                        Finlet Server                         |
|  +-----------+  +-----------+  +----------------------+     |
|  |  MCP      |  |  FastAPI   |  |   Static Dashboard   |     |
|  |  Server   |  |  Routes    |  |   (HTML/JS/CSS)      |     |
|  +-----+-----+  +-----+-----+  +----------------------+     |
|        +-------+-------+                                     |
|                v                                             |
|  +------------------------------------------------------+   |
|  |                   Session Engine                       |   |
|  |  +---------+  +-----------+  +------------------+     |   |
|  |  |  Clock   |  | Portfolio  |  |  Order Executor  |     |   |
|  |  | (frozen) |  |  Engine    |  |                  |     |   |
|  |  +---------+  +-----------+  +------------------+     |   |
|  +------------------------+-------------------------------+   |
|                           v                                   |
|  +------------------------------------------------------+   |
|  |              Date Ceiling Enforcer                     |   |
|  |         (strips data after sim clock time)             |   |
|  +------------------------+-------------------------------+   |
|                           v                                   |
|  +------------------------------------------------------+   |
|  |                 Plugin Registry                        |   |
|  |  +----------+ +-------+ +------+ +---------------+    |   |
|  |  |  Price   | | EDGAR | | FRED | |    Finnhub    |    |   |
|  |  |(S3 Parqt)| |(filing| |(econ)| |(news+fundmntl)|    |   |
|  |  +----------+ +-------+ +------+ +---------------+    |   |
|  +------------------------------------------------------+   |
|                           |                                   |
|  +------------------------v-------------------------------+   |
|  |            SQLite (per-session DB)                      |   |
|  |     ~/.finlet/sessions/{id}/session.db                  |   |
|  +------------------------------------------------------+   |
+-------------------------------------------------------------+

API Reference

Base URL: http://localhost:8000 (local) or https://finlet.dev (cloud)

Sessions

Method Endpoint Description
POST /sessions Create a new session
GET /sessions List all sessions
GET /sessions/{id} Get session state
DELETE /sessions/{id} End a session
POST /sessions/{id}/configure Update session config

Clock

Method Endpoint Description
GET /sessions/{id}/clock Current clock state
POST /sessions/{id}/clock/freeze Freeze the clock
POST /sessions/{id}/clock/step Step by interval
POST /sessions/{id}/clock/step-to Step to a specific time
POST /sessions/{id}/clock/play Start continuous mode
POST /sessions/{id}/clock/stop Stop continuous mode

Market Data

Method Endpoint Description
GET /sessions/{id}/market/price Price data (OHLCV)
POST /sessions/{id}/market/search-news Search news articles
GET /sessions/{id}/market/fundamentals Company fundamentals
GET /sessions/{id}/market/filings SEC filings
GET /sessions/{id}/market/economic Economic indicators

Trading

Method Endpoint Description
POST /sessions/{id}/trade/order Submit an order
GET /sessions/{id}/trade/orders List orders
GET /sessions/{id}/trade/orders/{oid} Order detail
DELETE /sessions/{id}/trade/orders/{oid} Cancel an order

Portfolio

Method Endpoint Description
GET /sessions/{id}/portfolio Portfolio state + metrics
GET /sessions/{id}/portfolio/history Equity curve time series
GET /sessions/{id}/trace Reasoning trace log

Full interactive docs at /docs when the server is running.


MCP Tools

When connected via MCP, these tools are available to your AI agent:

Tool Description
get_price_data Fetch OHLCV price data for a ticker
search_news Search news articles by keyword/ticker
get_fundamentals Get company financial fundamentals
get_filings Retrieve SEC filings
get_economic_data Get economic indicators (GDP, CPI, etc.)
submit_order Place a buy/sell order
get_portfolio View current portfolio state
get_sim_time Check current simulation time
advance_time Step the simulation clock forward
freeze_time Freeze the simulation clock

CLI Reference

finlet serve                    # Start API server + dashboard
finlet session create           # Create a new session
  --name TEXT                   #   Session name
  --start TEXT                  #   Start datetime (ISO format)
  --capital FLOAT               #   Initial capital (default: 100000)
  --universe TEXT               #   Comma-separated ticker list
finlet session list             # List all sessions
finlet plugins list             # Show plugin status
finlet plugins add NAME         # Configure a plugin
  --api-key TEXT                #   API key for the plugin
finlet mcp serve                # Start MCP server (stdio) — also the dispatch target the agentic-trading CLI commands spawn (Phase 5, 2026-05-09)

Tech Stack

  • Python 3.12+ — Async throughout, type hints everywhere
  • FastAPI — REST API with automatic OpenAPI docs
  • MCP SDK — Model Context Protocol server for LLM integration
  • SQLite — Per-session database via aiosqlite + SQLModel
  • TradingView Lightweight Charts — Dashboard charting (MIT, via CDN)

Contributing

  1. Clone the repo
  2. Install in dev mode: pip install -e ".[dev]"
  3. Run tests: pytest
  4. Follow the code conventions in CLAUDE.md

Key rules:

  • All datetimes in UTC internally
  • Async functions everywhere — no sync I/O in the hot path
  • Error messages must be specific and actionable
  • Every plugin response goes through the date ceiling enforcer
  • Mock external APIs in tests — no real network calls

Disclaimers

Finlet is provided for educational and research purposes only. It is not financial advice and should not be used as the basis for any investment decisions.

Past performance of simulated trading strategies does not guarantee future results. All market data is historical and provided by third-party sources subject to their respective terms of service.

Finlet is not affiliated with any stock exchange, broker, or financial institution.

License

Proprietary

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

finlet-1.1.0.tar.gz (8.2 MB view details)

Uploaded Source

Built Distribution

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

finlet-1.1.0-py3-none-any.whl (860.6 kB view details)

Uploaded Python 3

File details

Details for the file finlet-1.1.0.tar.gz.

File metadata

  • Download URL: finlet-1.1.0.tar.gz
  • Upload date:
  • Size: 8.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for finlet-1.1.0.tar.gz
Algorithm Hash digest
SHA256 69a53971e8f92e3de065f02b87df359783107d75985818d17e9b69fab6eda432
MD5 86e3f54ee46c5e74951d73f14984984a
BLAKE2b-256 8d77520b2adab4c08bb45133e4721a5d6838c1a6b60e01e4af4fd571ab0b7041

See more details on using hashes here.

Provenance

The following attestation bundles were made for finlet-1.1.0.tar.gz:

Publisher: pypi-publish.yml on justnau1020/finlet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file finlet-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: finlet-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 860.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for finlet-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6c63f578349997234062a79666edd48baf43ab18ae05ded68b59aa07e7614348
MD5 3da9ef386284e7cebcea8e9c33908a42
BLAKE2b-256 3c8d66ac67c2134bc6b7e34cbb7f8fbc219456a32f850c2d540f1704eda31c9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for finlet-1.1.0-py3-none-any.whl:

Publisher: pypi-publish.yml on justnau1020/finlet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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