rustyschwab

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 7 GitHub stars
Code Gecti
  • Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Unofficial Rust SDK, Python package and MCP server for the Charles Schwab Trader API: orders sent at most once, risk limits outside the strategy, a deterministic paper venue, and policy-gated tools for LLM agents.

README.md

rustyschwab

An unofficial Rust SDK, Python package and MCP server for the Charles Schwab Trader and Market Data APIs, built for automated strategies and LLM agents that place real orders.

[!WARNING]
Automated trading can lose money. This software is provided as is, without warranty. Start with the paper venue, which runs locally and does not connect to thinkorswim paperMoney. Not affiliated with or endorsed by Charles Schwab & Co., Inc.

Status: 0.3.0. The Rust crates are on crates.io; the Python package is not on PyPI yet, so build it from this repository. One maintainer. Everything is tested against recorded Schwab responses and local fakes, but no live-account run has been recorded yet, so treat live trading as unproven. See what is core, what is experimental, and what has run live.

What is in it

Part For Docs
rustyschwab Rust applications: OAuth, REST, the streamer, the order journal, risk limits, paper venue, history cache, performance analytics crate guide
rustyschwab (Python) The same SDK from asyncio or blocking Python, order templates, one strategy for backtest, paper and live, a NautilusTrader adapter Python guide
rustyschwab-mcp LLM agents: an MCP server with 40 tools over the SDK, behind per-principal policy, approvals and a paper mode, plus operator and gateway commands MCP guide

What it does differently

The hard part of broker automation is what happens when something goes wrong. rustyschwab is built around that:

  • An order is sent at most once. Every submission is journaled before it leaves the process. A timeout or dropped connection becomes SubmissionUnknown, never a retry, and the account's next submission waits until the journal reconciles the order against Schwab.
  • Limits hold outside the strategy. Risk limits, a daily-loss halt, an operator halt and a dead-man switch that cancels a silent agent's orders are enforced by the SDK and the server, not by the code placing the orders.
  • Agents get a narrow, checked surface. MCP write tools are off by default. Each principal is held to its accounts, tools, symbols, price collar and daily budget; orders can require operator or user approval; check_order explains every local reason an order would fail before anything reaches Schwab; and every write is recorded, with the model's stated rationale, in a hash-chained audit journal.
  • Simulation uses the same code path. The paper venue is deterministic and durable (SQLite), with finite liquidity, latency, fees and settlement in exact decimals. A Python strategy runs unchanged as a backtest, against the paper venue on live data, or live.
  • Credentials stay out of reach. Tokens live in the OS keychain or an encrypted file, are zeroized in memory, and never appear in logs, errors or reprs.

Quickstart

Register an app at developer.schwab.com with callback URL https://127.0.0.1:8080, then:

git clone https://github.com/epistates/rustyschwab && cd rustyschwab
cp .env.example .env            # set SCHWAB_APP_KEY, SCHWAB_APP_SECRET
cargo run -p oauth-flow         # sign in once; tokens are stored securely

The setup guide covers each step, the token stores, and a one-time mkcert setup that removes the browser's certificate warning from sign-in.

Rust

[dependencies]
rustyschwab = "0.3"
tokio = { version = "1", features = ["full"] }
use rustyschwab::prelude::*;

let client = SchwabClient::new(SchwabConfig::from_env()?)?;
client.init().await?;
let quotes = client.get_quotes(&["AAPL", "MSFT"]).await?;

Placing orders, brackets and options: ORDERS.md. Streaming: STREAMING.md.

Python

pip install ./crates/schwab-py   # from the clone; builds the extension, needs a Rust toolchain
import asyncio
from rustyschwab import Client, orders
from rustyschwab.trader import Trader

def strategy(tc, events):
    for event in events:
        if event["type"] == "candle" and not tc.positions.get(event["symbol"]):
            tc.order(orders.equity_buy_market(event["symbol"], 1))

async def main():
    run = await Trader(Client.from_env()).backtest(strategy, ["AAPL"], days=5, cash=10_000)
    print(run.report())

asyncio.run(main())

trader.paper(...) and trader.live(...) run the same function. PYTHON.md has the rest; coming from Schwabdev maps every Schwabdev call to its equivalent.

MCP

cargo install rustyschwab-mcp    # installs the server and its operator tools
claude mcp add schwab -e SCHWAB_APP_KEY=… -e SCHWAB_APP_SECRET=… \
  -e SCHWAB_TOKENS_FILE="$PWD/schwab_tokens.json" \
  -- "$(command -v rustyschwab-mcp)"

Order tools stay off until you enable them. To let an agent trade without real money, run the server over the paper venue:

SCHWAB_MCP_PAPER_CONFIG=ops/paper/config.json SCHWAB_MCP_PAPER_STATE=state/paper.sqlite3 \
SCHWAB_MCP_ALLOW_TRADING=1 rustyschwab-mcp

Claude Desktop configuration, the tool catalog and the policy model: MCP guide. Policies, approvals, risk limits, metrics and recovery: Operations.

Documentation

docs/INDEX.md lists every guide. The ones most people need:

Runnable programs are under examples/: cargo run -p oauth-flow, comprehensive, auth_test, and streaming-examples (--bin streaming_quotes).

Contributing and security

See CONTRIBUTING.md and the changelog. Report vulnerabilities privately as described in SECURITY.md.

License

MIT or Apache-2.0, at your option.

Yorumlar (0)

Sonuc bulunamadi