cd /news/ai-agents/trader-llm-agent-for-robinhood-with-… · home topics ai-agents article
[ARTICLE · art-20438] src=github.com pub= topic=ai-agents verified=true sentiment=· neutral

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.

read8 min publishedJun 3, 2026

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 toolsto read your portfolio, fetch quotes, and place orders. Every order is intercepted**by a typed RustSafetyValidator

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
git clone https://github.com/zhangxd6/Trader.git
cd Trader

cp .env.example .env

cp config/strategy.example.yaml config/strategy.yaml
cargo build --release
./target/release/trader auth    # confirms MCP connection
./target/release/trader tools   # lists all available Robinhood tools
./target/release/trader simulate --reset

./target/release/trader simulate --once

./target/release/trader simulate --tui

./target/release/trader simulate --status --chart

./target/release/trader simulate --csv equity.csv
tail -1 logs/audit.jsonl | jq .

tail -1 logs/audit.jsonl | jq '.tool_calls[] | {tool, intercepted}'

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 for the full reference including multi-strategy and research options.

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 offlineGroq 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]  [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
}
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; readlogs/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.

── more in #ai-agents 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/trader-llm-agent-for…] indexed:0 read:8min 2026-06-03 ·