Trader – LLM agent for Robinhood with a Rust safety layer and paper trading A new open-source trading agent called "Trader" connects large language models to Robinhood's official agentic trading API through a Rust-based safety layer that enforces hard risk limits on every order. The agent operates as an MCP bridge, allowing LLMs from OpenAI, Anthropic, Groq, or Ollama to read portfolios, fetch quotes, and place orders while a typed `SafetyValidator` intercepts and validates all transactions against user-defined thresholds for stop-losses, position caps, and buy filters. The system supports paper trading against live market data with a virtual portfolio, full audit logging to JSONL, and a TUI dashboard for monitoring multiple strategies running in parallel. A Rust agent that connects an LLM to Robinhood's official agentic trading API, enforces hard risk limits in a typed safety layer, and paper-trades against live market data before you risk a dollar. trader is an agentic loop that: Builds a prompt from your strategy YAML — hard thresholds stop-loss, position caps, buy filters and free-text judgment rules. Hands it to an LLM OpenAI, Anthropic, Groq, Ollama, or any compatible endpoint . The LLM calls Robinhood's MCP tools to read your portfolio, fetch quotes, and place orders. Every order is intercepted by a typed Rust SafetyValidator that enforces your risk limits — rejecting anything that violates them regardless of what the model decided. Everything is audited — system prompt, user message, every tool call and result, intermediate LLM reasoning, and final response — to a JSONL file. The agent does not re-implement the Robinhood API. It is an MCP bridge: the LLM drives the tools; we sit in the middle and enforce safety. scheduler tick │ ▼ TradingAgent ── build system prompt + user message from strategy YAML │ ▼ LlmProvider.run agent loop ← OpenAI / Anthropic / Groq / Ollama │ the LLM calls tools in a loop until it reaches a final answer ▼ SafetyValidator Rust, hard-enforced │ ├─ read tools → forwarded as-is; result observed │ └─ order tools → checked against all risk limits, then forwarded or blocked ▼ SimulationExecutor paper mode or Robinhood MCP live │ intercepts orders; applies them to │ │ a virtual portfolio on disk │ ▼ ▼ AuditLogger → logs/audit.jsonl one JSON line per cycle, full conversation The executor chain is a trait stack ToolExecutor . Each layer is independent, testable, and composable. Adding a new broker, a new LLM, or a new safety rule does not touch the others. | Feature | Details | |---|---| Hybrid strategy | Structured thresholds enforced by Rust + free-text rules passed to LLM | Any LLM | OpenAI, Anthropic, Groq, Ollama, Azure, or any OpenAI/Anthropic-compatible endpoint | Paper trading | Simulation mode uses live Robinhood market data against a virtual portfolio | Equity curve | ASCII chart + CSV export of every simulated cycle's portfolio value | Research tools | LLM can call get stock news Yahoo Finance RSS and web search Brave/DDG | Full audit trail | Every cycle → JSONL: system prompt, user message, all tool calls, full conversation | TUI dashboard | Live ratatui panels for strategy, portfolio, reasoning, and logs — all scrollable | Multiple strategies | Run several strategies in parallel, each on its own scheduler interval | Docker | docker-compose up for containerised runs | - Rust 1.75+ - A Robinhood Agent Account https://robinhood.com/us/en/agentic-trading/ and its MCP OAuth token - An LLM: Ollama https://ollama.com locally free , or API keys for OpenAI / Anthropic / Groq git clone https://github.com/zhangxd6/Trader.git cd Trader cp .env.example .env Edit .env — add ROBINHOOD MCP TOKEN and any LLM API keys cp config/strategy.example.yaml config/strategy.yaml Edit config/strategy.yaml — choose your LLM and strategy cargo build --release Binary is at ./target/release/trader ./target/release/trader auth confirms MCP connection ./target/release/trader tools lists all available Robinhood tools Reset a fresh $10,000 virtual portfolio ./target/release/trader simulate --reset Run one decision cycle and see what the LLM would do ./target/release/trader simulate --once Live TUI dashboard with equity curve ./target/release/trader simulate --tui Check P&L after several cycles ./target/release/trader simulate --status --chart Export equity curve to CSV ./target/release/trader simulate --csv equity.csv Pretty-print the latest cycle jq required tail -1 logs/audit.jsonl | jq . See every tool call the LLM made tail -1 logs/audit.jsonl | jq '.tool calls | {tool, intercepted}' Read the full LLM conversation tail -1 logs/audit.jsonl | jq '.conversation' Strategies combine hard limits Rust-enforced with free-text rules LLM-guided : strategy: name: "Mag7 Dip Buyer" description: Buy the Magnificent 7 on pullbacks from recent highs. Hold for momentum recovery. Never chase. Preserve 30% cash at all times. watchlist: AAPL, MSFT, NVDA, GOOGL, META, AMZN, TSLA industries: Technology, AI, Cloud Computing structured: ← enforced by Rust; LLM cannot override stop loss pct: 6.0 take profit pct: 20.0 max positions: 4 min confidence: 0.75 buy filters: max price vs 52w high pct: 85.0 only buy ≥15% off 52w high min volume ratio: 0.90 rules: ← passed verbatim to the LLM prompt - "Only BUY on a clear pullback — at least 5% below a recent local high" - "Do not open a new position if SPY is in a confirmed downtrend" - "Prefer NVDA and MSFT for AI exposure; treat TSLA as higher-risk" interval minutes: 30 risk: dry run: true set false only when ready for real money max trade usd: 1000.0 max position pct: 0.20 max daily trades: 4 min cash reserve pct: 0.30 See config/strategy.example.yaml /zhangxd6/Trader/blob/main/config/strategy.example.yaml for the full reference including multi-strategy and research options. config/small-account.yaml /zhangxd6/Trader/blob/main/config/small-account.yaml is a worked example targeting 10% monthly growth from a $300 cash account: Concentrated : max 2 positions, $130 each, $54 cash floor Disciplined entries : only buy on ≥5% pullback with volume confirmation Fast exits : take-profit at 12%, stop-loss at 5%, no averaging down LLM-guided : market context, name selection, and timing rules in plain English ./target/release/trader --config config/small-account.yaml simulate --tui provider value | Endpoint | Example models | |---|---|---| openai | api.openai.com | gpt-4o , gpt-4o-mini | anthropic | api.anthropic.com | claude-opus-4-7 , claude-sonnet-4-6 | openai-compatible | any set base url | Groq llama-3.3-70b , Ollama qwen2.5:7b , Azure | anthropic-compatible | any set base url | Claude proxies / gateways | Recommended free options: Ollama locally : ollama pull qwen2.5:7b — no rate limits, works offline Groq free tier : llama-3.3-70b-versatile — fast, generous daily quota For reliable tool calling use models ≥7B. Models that don't support the tools API e.g. some deepseek variants on Ollama will not work. ┌─ Strategy ▲▼ ────────────────┐┌─ Portfolio ─────────────────────────┐ │ Nano AI Swing ││ Cash: $ 170.00 │ │ Mode: SIMULATE ││ Equity: $ 130.50 │ │ ││ Total: $ 300.50 +0.17% │ │ HARD RULES ││ ● Running market: open │ │ Stop-loss: 5.0% │└─────────────────────────────────────┘ │ Take-profit: 12.0% │┌─ Positions ──────────────────────────┐ │ Max positions: 2 ││ Symbol Qty Price P&L% │ │ Min confidence: 0.82 ││ ANET 0.55 $236.50 +0.21% │ │ Buy filters: │└─────────────────────────────────────┘ │ Price < 88% of 52w high │ │ Volume 1.1x avg │ └──────────────────────────────┘ ┌─ Latest Reasoning ▲▼ ────────────────────────────┐┌─ Logs ▲▼ ──────────────────────────────┐ │ Reviewed portfolio: $170 cash, 0.55 ANET @ ││ 14:32:01 CYCLE starting cycle a1b2… │ │ $234.20 avg. ANET is +1.0% from cost — holding. ││ 14:32:02 MCP get portfolio {} │ │ MRVL pulled back 6.2% from 3-day high on above- ││ 14:32:03 MCP get equity quotes … │ │ average volume. Confidence 0.85 ≥ 0.82 threshold. ││ 14:32:05 LLM querying openai/… │ │ Placing fractional buy: $125 MRVL. ││ 14:32:08 ORDER place equity order … │ │ ││ 14:32:08 CYCLE complete — 1 placed │ └────────────────────────────────────────────────────┘└────────────────────────────────────────┘ q quit p pause tab focus ↑↓/jk scroll All three text panels Strategy, Reasoning, Logs are independently scrollable. Tab cycles focus; the active panel gets a cyan border. Two independent layers protect every trade: Robinhood's structural isolation — the agent account is separate from your main portfolio and limited to its pre-loaded balance.— on every order the Rust layer checks: SafetyValidator - symbol is on the watchlist if one is configured - buy/sell direction is permitted - per-trade USD cap not exceeded - position concentration limit not breached - daily trade count not exceeded - minimum cash reserve maintained dry run: true blocks all orders entirely Violations are logged and returned to the LLM as an error; they never reach the broker. Every cycle produces one JSON line in logs/audit.jsonl : { "cycle id": "a1b2c3...", "timestamp": "2026-06-01T14:32:01Z", "strategy name": "Nano AI Swing", "mode": "SIMULATE", "dry run": false, "system prompt": "You are a disciplined trading agent...", "user message": "Current time: 2026-06-01 14:32 UTC. Review my portfolio...", "final response": "Placed fractional buy of $125 MRVL at $67.30...", "iterations": 3, "tool calls": { "tool": "get portfolio", "arguments": {}, "result": {...}, "intercepted": false }, { "tool": "place equity order", "arguments": {...}, "result": {...}, "intercepted": false } , "orders attempted": { "symbol": "MRVL", "side": "buy", "quantity": 1.858, "outcome": "simulated" } , "conversation": ... // full turn-by-turn thread; disable with audit.full conversation: false } Copy and edit .env, then: docker-compose up The compose file mounts config/ , logs/ , and simulation/ as volumes so state persists across restarts. cargo test unit tests cargo clippy lints Module layout: | Path | Responsibility | |---|---| src/mcp/ | Robinhood MCP client Streamable HTTP, JSON-RPC + SSE | src/llm/ | Provider-agnostic agent loop; OpenAI & Anthropic implementations | src/safety/ | Risk enforcement middleware ToolExecutor trait | src/research/ | News Yahoo Finance RSS and web search Brave/DDG tool middleware | src/simulation/ | Paper trading with persisted virtual portfolio + equity curve | src/agent/ | Cycle orchestration, prompt building, TUI event emission | src/scheduler/ | Interval loop with market-hours guard | src/tui/ | ratatui live dashboard | src/audit/ | Append-only JSONL audit trail | simulate --once — run a single cycle; read logs/audit.jsonl to see what the LLM reasoned. simulate --tui — run continuously; watch the TUI for entries and reasoning. simulate --status --chart — review the equity curve after several sessions.- Tune config/strategy.yaml until simulated results are convincing. once --dry-run — run against the live account; orders are blocked but you see exactly what would have been placed.- Set dry run: false and start with conservative caps. Trading involves real financial risk. This software is provided as-is with no warranty. Always start in simulation or dry-run mode. You are solely responsible for any trades placed through your account. Not affiliated with Robinhood Markets, Inc. Apache-2.0 — see LICENSE /zhangxd6/Trader/blob/main/LICENSE .