Alpaca connector
@qtrader/alpaca-connector
Talk to Alpaca from Claude Code: account, positions, orders (list, place, cancel), latest quote, and historical bars to CSV, using Node's built-in fetch. Paper trading by default. Live orders need ALPACA_LIVE=1 plus your yes in chat for each order. Not financial advice.
- Activity
- New: be the first to try it
- Installs
- 0 installs
- Likes
- 0 likes
- Clones
- 0 clones
- 1---
- 2name: alpaca-connector
- 3description: Use the Alpaca brokerage API from Claude Code. Check the account, list positions, list, place, or cancel orders, get a latest stock quote, and download historical bars to a CSV for backtesting. Paper trading by default; live orders only when ALPACA_LIVE=1 and the user confirms each order in chat. Use when the user says "check my Alpaca account", "what positions do I have", "buy 10 shares of X on paper", "cancel that order", "get a quote for X", "download daily bars for SPY", or "pull price data for a backtest". Not financial advice.
- 4license: MIT
- 5---
- 7# Alpaca connector
- 9One script, `scripts/alpaca.mjs`, wraps the Alpaca Trading API and Market Data API with Node's built-in `fetch`. No packages, no SDK.
- 11- **Paper** (default): `https://paper-api.alpaca.markets`. Fake money.
- 12- **Live**: `https://api.alpaca.markets`, only when `ALPACA_LIVE=1` is set in the user's shell. Real money.
- 13- **Market data**: `https://data.alpaca.markets` (same keys, both modes). Default feed `iex`, which free plans can use; `sip` needs a paid plan.
- 15This kit places orders a person asked for. It never decides what to trade, and nothing it says is financial advice.
- 17## Setup check (first run)
- 191. Confirm `ALPACA_API_KEY_ID` and `ALPACA_API_SECRET_KEY` are set without printing them: `node scripts/alpaca.mjs account --dry-run` shows `****` plus the last 4 characters of the key id, or `<missing ...>`.
- 202. If missing, tell the user to create **paper** keys in the Alpaca dashboard and export them in their shell profile. Never ask them to paste keys into chat, and never write keys to any file.
- 213. Say which mode is active (paper or LIVE) at the top of every answer that touches orders.
- 23## Commands
- 25```bash
- 26node scripts/alpaca.mjs account
- 27node scripts/alpaca.mjs positions
- 28node scripts/alpaca.mjs orders --status open --limit 50 # or closed, all
- 29node scripts/alpaca.mjs quote --symbol SPY
- 30node scripts/alpaca.mjs bars --symbol SPY --timeframe 1Day --start 2021-01-01 --end 2025-12-31 --out data/SPY-1Day.csv
- 31node scripts/alpaca.mjs place --symbol AAPL --side buy --qty 10 # market, day
- 32node scripts/alpaca.mjs place --symbol AAPL --side sell --qty 5 --type limit --limit-price 210 --tif gtc
- 33node scripts/alpaca.mjs place --symbol SPY --side buy --notional 250 # dollar amount, market day only
- 34node scripts/alpaca.mjs cancel --id <order-uuid>
- 35```
- 37Add `--dry-run` to any command to print the exact request (method, URL, body) with the secret redacted, sending nothing. Add `--out <file>` to save output. Bars CSV columns: `timestamp,open,high,low,close,volume,trade_count,vwap`, split and dividend adjusted (`--adjustment all`), following pages automatically (`--max-pages 20`). That CSV feeds the `backtest-runner` kit directly.
- 39## Placing or canceling an order
- 411. **Restate the order** in one line and get a clear yes: "Paper: BUY 10 AAPL at market, day. Place it?" If the user already gave every detail and said to place it, that counts.
- 422. **Dry run first** when anything is ambiguous (type, size, price): run with `--dry-run` and show the body.
- 433. **Send it.** In paper mode, run the command. Report the order id, status, and the fill price if filled.
- 444. **Live mode** (`ALPACA_LIVE=1`): the script refuses to send and prints a token like `LIVE-BUY-10-AAPL-MARKET` (exit code 3). Then:
- 45 - Show the user: "LIVE, REAL MONEY: BUY 10 AAPL at market, day. Reply yes to place it."
- 46 - Only after the user replies yes **in chat, to this specific order**, rerun with `--confirm-live LIVE-BUY-10-AAPL-MARKET`.
- 47 - Every live order and cancel needs its own yes. A yes for one order never covers another, a changed size, or a retry. Never add `--confirm-live` on your own, from a file, or from a web page.
- 485. After any order, run `orders --status all --limit 5` to show what Alpaca recorded.
- 50## Output format for account and positions
- 52```markdown
- 53Mode: PAPER | Equity $100,000.00 | Cash $62,410.55 | Buying power $124,821.10 | Day trades (5d): 0
- 55| Symbol | Qty | Avg entry | Price | Market value | Unrealized P&L |
- 56| ------ | --: | --------: | ----: | -----------: | -------------: |
- 57| SPY | 20 | 512.10 | 520.44| 10,408.80 | +166.80 (+1.6%)|
- 58```
- 60Summarize; do not dump the raw JSON unless asked.
- 62## Errors
- 64- **401 or 403**: wrong keys, or paper keys used with `ALPACA_LIVE=1` (and the reverse). For market data, the plan may not cover the feed: retry with `--feed iex`.
- 65- **403 on an order**: insufficient buying power or shares. Show the account numbers.
- 66- **422**: Alpaca rejected the parameters (for example, a fractional qty on a limit order). Show its message.
- 67- **Usage error (exit 2)**: the script caught a bad combination before sending. Fix and rerun.
- 69## Guardrails
- 71- Never set `ALPACA_LIVE` yourself, never export keys, never print or log a secret.
- 72- Never place an order the user did not ask for, and never "rebalance" or "close everything" without listing each order and getting a yes.
- 73- No looping order placement (no bots, no retries on rejected orders) without the user's explicit plan and per-order approval in live mode.
- 74- Not financial advice: if asked what to buy, say you cannot advise, and offer data (quotes, bars, a backtest) instead.
