How to Build a 24/7 AI Trading Agent with Claude Code and Alpaca
Use Claude Code Routines and the Alpaca API to build an autonomous trading agent that researches, trades, and journals without manual intervention.
What This Agent Actually Does
Most people who want an AI trading agent end up with one of two things: a rigid rule-based bot that can’t adapt, or a one-shot Claude session that fires off a few trades and then goes quiet. Neither is what you actually want.
What you want is a Claude Code trading agent that wakes up on a schedule, scans the market, reasons about what to do, places trades through the Alpaca API, and logs everything to a structured journal — all without you touching it. That’s what this guide builds.
The agent has three main jobs:
- Research — Pull market data, news, and technical signals for a defined watchlist.
- Trade — Evaluate what the research says and place buy/sell/hold orders through Alpaca.
- Journal — Write a structured log entry explaining every decision, including the ones where it did nothing.
This is a paper trading setup by default. You can flip it to live trading once you’re confident in the agent’s behavior, but starting on paper is the only sensible approach.
Prerequisites
Before writing a single line of code, you need three things in place.
An Alpaca Account
Alpaca offers commission-free stock and crypto trading with a proper REST API. Sign up for a free account and generate both a paper trading API key and a live trading API key. Keep them separate. You’ll use paper keys throughout development.
Your .env file will look like this:
APCA_API_KEY_ID=your_paper_key_id
APCA_API_SECRET_KEY=your_paper_secret_key
APCA_BASE_URL=https://paper-api.alpaca.markets
Claude Code Installed and Configured
You need Claude Code running locally. If you haven’t set up Claude Code with scheduled routines yet, do that first. The scheduling layer is what makes this agent genuinely autonomous rather than a script you run manually.
A Basic File Structure
/trading-agent
CLAUDE.md # Agent instructions and persona
watchlist.json # Stocks/ETFs to monitor
journal/ # Trade logs stored here
scripts/
research.py # Data fetching helpers
trade.py # Order placement helpers
.env # API credentials (never commit this)
You don’t need everything built before you start. You’ll build these out in sequence.
Step 1: Define the Agent’s Persona in CLAUDE.md
The CLAUDE.md file is the agent’s operating manual. Claude Code reads it at the start of every session. This is where you set the rules of engagement.
Here’s a solid starting template:
# Trading Agent Instructions
You are an autonomous trading agent managing a paper portfolio.
## Your Core Responsibilities
- Every market day at 9:45 AM ET: Run the research routine
- Every market day at 10:00 AM ET: Evaluate research and place trades
- Every market day at 4:15 PM ET: Write a journal entry covering the day
## Rules You Must Always Follow
- Never invest more than 5% of total portfolio value in a single position
- Never place a market order — always use limit orders within 0.2% of ask
- If a position drops 8% from your entry, close it without waiting
- Always write a journal entry, even on days you make no trades
- Never place trades when market status is "closed"
## Decision Framework
Before placing any trade, answer these questions:
1. What is the current portfolio cash balance?
2. What positions are already open?
3. What does recent news say about this ticker?
4. What do the 20-day and 50-day moving averages tell you?
5. What is the risk if this trade goes wrong?
## Output Format
Every action must be logged to journal/YYYY-MM-DD.md in structured format.
The more specific you are here, the more predictable the agent’s behavior. Vague instructions produce vague behavior. This is true of all agent design — structured prompting with a clear workflow produces better outcomes than letting the agent improvise its own process.
Step 2: Build the Research Skill
The agent needs to pull real market data before it can make decisions. This is a Python helper script that the agent calls as a tool.
# scripts/research.py
import os
import requests
from datetime import datetime, timedelta
import json
ALPACA_KEY = os.getenv("APCA_API_KEY_ID")
ALPACA_SECRET = os.getenv("APCA_API_SECRET_KEY")
BASE_URL = os.getenv("APCA_BASE_URL")
def get_bars(symbol, timeframe="1Day", limit=60):
"""Fetch historical price bars for a symbol."""
headers = {
"APCA-API-KEY-ID": ALPACA_KEY,
"APCA-API-SECRET-KEY": ALPACA_SECRET,
}
url = f"https://data.alpaca.markets/v2/stocks/{symbol}/bars"
params = {
"timeframe": timeframe,
"limit": limit,
"adjustment": "raw"
}
response = requests.get(url, headers=headers, params=params)
return response.json()
def get_account():
"""Get current portfolio status."""
headers = {
"APCA-API-KEY-ID": ALPACA_KEY,
"APCA-API-SECRET-KEY": ALPACA_SECRET,
}
url = f"{BASE_URL}/v2/account"
response = requests.get(url, headers=headers)
return response.json()
def get_positions():
"""Get all open positions."""
headers = {
"APCA-API-KEY-ID": ALPACA_KEY,
"APCA-API-SECRET-KEY": ALPACA_SECRET,
}
url = f"{BASE_URL}/v2/positions"
response = requests.get(url, headers=headers)
return response.json()
def get_news(symbol):
"""Get recent news for a symbol."""
headers = {
"APCA-API-KEY-ID": ALPACA_KEY,
"APCA-API-SECRET-KEY": ALPACA_SECRET,
}
url = f"https://data.alpaca.markets/v1beta1/news"
params = {
"symbols": symbol,
"limit": 5,
"sort": "desc"
}
response = requests.get(url, headers=headers, params=params)
return response.json()
if __name__ == "__main__":
import sys
action = sys.argv[1] if len(sys.argv) > 1 else "account"
symbol = sys.argv[2] if len(sys.argv) > 2 else None
if action == "bars" and symbol:
print(json.dumps(get_bars(symbol)))
elif action == "news" and symbol:
print(json.dumps(get_news(symbol)))
elif action == "positions":
print(json.dumps(get_positions()))
else:
print(json.dumps(get_account()))
The agent can call this script directly from a bash tool: python scripts/research.py bars AAPL returns 60 days of price bars as JSON. Claude can then calculate moving averages, identify trends, and factor in the news before making a decision.
Step 3: Build the Trade Execution Skill
Placing trades through Alpaca’s API is straightforward. The tricky part is building in the guard rails your agent needs before it can touch real money.
# scripts/trade.py
import os
import requests
import json
import sys
ALPACA_KEY = os.getenv("APCA_API_KEY_ID")
ALPACA_SECRET = os.getenv("APCA_API_SECRET_KEY")
BASE_URL = os.getenv("APCA_BASE_URL")
def place_order(symbol, qty, side, limit_price=None):
"""Place a buy or sell order."""
headers = {
"APCA-API-KEY-ID": ALPACA_KEY,
"APCA-API-SECRET-KEY": ALPACA_SECRET,
"Content-Type": "application/json"
}
order_data = {
"symbol": symbol,
"qty": qty,
"side": side, # "buy" or "sell"
"type": "limit" if limit_price else "market",
"time_in_force": "day",
}
if limit_price:
order_data["limit_price"] = str(limit_price)
url = f"{BASE_URL}/v2/orders"
response = requests.post(url, headers=headers, json=order_data)
return response.json()
def cancel_all_orders():
"""Cancel all open orders."""
headers = {
"APCA-API-KEY-ID": ALPACA_KEY,
"APCA-API-SECRET-KEY": ALPACA_SECRET,
}
url = f"{BASE_URL}/v2/orders"
response = requests.delete(url, headers=headers)
return response.status_code
def get_market_status():
"""Check if the market is open."""
headers = {
"APCA-API-KEY-ID": ALPACA_KEY,
"APCA-API-SECRET-KEY": ALPACA_SECRET,
}
url = f"{BASE_URL}/v2/clock"
response = requests.get(url, headers=headers)
return response.json()
if __name__ == "__main__":
action = sys.argv[1]
if action == "status":
print(json.dumps(get_market_status()))
elif action == "order":
symbol = sys.argv[2]
qty = sys.argv[3]
side = sys.argv[4]
limit_price = sys.argv[5] if len(sys.argv) > 5 else None
print(json.dumps(place_order(symbol, qty, side, limit_price)))
elif action == "cancel":
print(cancel_all_orders())
Notice that market orders are technically available in this script but the agent’s CLAUDE.md instructs it to never use them. This is an important pattern: the safety rules live in the agent’s instructions, not just in the code. That way Claude reasons about them rather than blindly bypassing them.
This is part of a broader principle in agentic workflow design — the workflow controls the agent, not the other way around.
Step 4: Set Up the Trade Journal
Every decision the agent makes gets logged. This is non-negotiable. If you don’t know why the agent did something, you can’t improve it and you can’t catch it making mistakes.
The journal format is simple markdown:
# Trade Journal — 2026-04-18
## Portfolio Status
- Cash: $12,450.00
- Positions: NVDA (42 shares @ $845.20), SPY (15 shares @ $521.00)
- Total Value: $23,891.80
## Market Research
### NVDA
- 20-day MA: $838.50 | 50-day MA: $812.00 — bullish trend intact
- News: Positive analyst upgrade from Morgan Stanley, +8% PT increase
- Earnings: 3 weeks out — potential catalyst
### AAPL
- 20-day MA: $195.20 | 50-day MA: $198.80 — short-term weakness
- News: Supply chain concerns in Taiwan Strait reporting
- Decision: No action, watch for stabilization
## Trades Executed
| Time | Symbol | Action | Qty | Price | Reasoning |
|------|--------|--------|-----|-------|-----------|
| 10:03 | NVDA | BUY | 5 | $847.50 | MA trend + analyst upgrade = entry |
## Positions Closed
None today.
## End-of-Day Reflection
NVDA trade aligned with thesis. Held off on AAPL given macro uncertainty in news.
Tomorrow: Watch AAPL for reversal signal, check MSFT earnings preview.
The agent writes this file automatically at the end of each trading day. Over time, this journal becomes valuable data — you can feed prior entries back to the agent so it learns from past decisions. This is exactly the pattern described in building self-improving AI agents: the agent produces outputs that inform its next iteration.
Step 5: Configure the Claude Code Routine
This is where the agent stops being a script you run manually and becomes something genuinely autonomous. Claude Code Routines let you define scheduled tasks that fire on a cron schedule, using Claude Code in headless mode — no terminal window required.
Create a file called .claude/routines.json in your project directory:
{
"routines": [
{
"name": "Morning Research",
"schedule": "45 9 * * 1-5",
"timezone": "America/New_York",
"prompt": "Run the morning research routine. Check market status first. If the market is open, pull bars and news for every symbol in watchlist.json. Summarize findings in a structured format and save to journal/YYYY-MM-DD.md under the Research section.",
"allowed_tools": ["bash", "read", "write"]
},
{
"name": "Trading Session",
"schedule": "0 10 * * 1-5",
"timezone": "America/New_York",
"prompt": "Run the trading session. Read today's research from the journal file. Check current positions and cash balance. For each symbol in the watchlist, decide whether to buy, sell, or hold based on the research and your trading rules in CLAUDE.md. Place limit orders for any decisions. Log all actions and reasoning to the journal.",
"allowed_tools": ["bash", "read", "write"]
},
{
"name": "End of Day Journal",
"schedule": "15 16 * * 1-5",
"timezone": "America/New_York",
"prompt": "Run the end-of-day routine. Pull final positions and account value. Read all orders placed today. Complete the journal entry for today with a reflection section. Note what worked, what didn't, and what to watch tomorrow.",
"allowed_tools": ["bash", "read", "write"]
}
]
}
The 1-5 in the cron schedule means Monday through Friday only — the agent won’t attempt to trade on weekends. And even on weekdays, the first thing the agent does in each session is call python scripts/trade.py status to verify the market is open. If it’s a holiday or there’s a delayed open, the agent logs that and exits cleanly.
For a deeper look at how scheduled routines work under the hood, see how to deploy AI agents that run while you sleep.
Step 6: The Watchlist
Keep your watchlist tight, especially at the start. The agent needs enough research to make reasonable decisions but not so many symbols it gets overwhelmed.
{
"watchlist": [
{
"symbol": "SPY",
"description": "S&P 500 ETF — baseline market exposure",
"max_allocation_pct": 15
},
{
"symbol": "QQQ",
"description": "Nasdaq ETF — tech sector exposure",
"max_allocation_pct": 10
},
{
"symbol": "NVDA",
"description": "GPU/AI infrastructure — high conviction holding",
"max_allocation_pct": 8
},
{
"symbol": "AAPL",
"description": "Large cap tech — stability anchor",
"max_allocation_pct": 8
},
{
"symbol": "MSFT",
"description": "Cloud/enterprise — AI infrastructure play",
"max_allocation_pct": 8
}
],
"cash_reserve_pct": 20
}
The max_allocation_pct values give the agent hard limits per position. The cash_reserve_pct tells it to always keep 20% in cash — so even if it’s bullish on everything, it can’t go fully invested. This kind of structured constraint prevents the agent from taking positions that look reasonable individually but are reckless in aggregate.
This is similar to how AI agents for financial services are typically designed: guardrails at the data level, not just the instruction level.
Step 7: Risk Controls That Actually Work
Agent risk management fails in one of two ways: the rules are too vague (“don’t take too much risk”) or they’re enforced only in the prompt and the agent ignores them under pressure.
Build your risk controls into three layers:
Layer 1: CLAUDE.md Instructions
Hard rules written in plain language. The agent reads these every session. Be specific about numbers, not principles.
Layer 2: Script-Level Validation
Your trade script can validate orders before they go to Alpaca:
def validate_order(symbol, qty, side, current_price, account_value, current_positions):
"""Pre-flight checks before placing any order."""
order_value = qty * current_price
allocation_pct = (order_value / account_value) * 100
# Check max position size
if allocation_pct > 10:
return False, f"Order exceeds 10% allocation limit: {allocation_pct:.1f}%"
# Check total exposure (positions + this order < 80%)
total_invested = sum(p['market_value'] for p in current_positions)
if (total_invested + order_value) / account_value > 0.80:
return False, "Order would violate 20% cash reserve requirement"
return True, "Order validated"
Layer 3: Alpaca’s Built-In Protections
Alpaca offers paper trading with realistic fills, so you see what would actually happen. Use their built-in features like day-trade protection flags and buying power checks as a final safety net.
Step 8: Running Multiple Agents in Parallel (Optional)
Once the single-agent setup is stable, you can add a second agent that acts as a critic. This is a multi-agent debate pattern applied to trading.
The setup:
- Agent A (Trader) — Makes decisions and proposes trades
- Agent B (Risk Reviewer) — Reads Agent A’s proposals and approves or rejects them
Agent B runs 15 minutes after Agent A and reads the journal file. If it finds a proposed trade it disagrees with, it flags it and sets a review_required field in the journal. The execution routine won’t place flagged orders until a human clears them.
This adds latency, but it also catches the cases where Agent A’s reasoning was plausible-sounding but wrong. This is the same principle behind parallel agent teams sharing a task list — different agents checking each other’s work produces better outputs than one agent working alone.
For most people starting out, stick with the single-agent setup. Get comfortable with its behavior on paper trading before adding complexity.
Step 9: Managing Token Costs
A trading agent running three times a day, five days a week, with research on five symbols will accumulate meaningful token usage over a month. You need to keep this in check.
A few practical approaches:
- Truncate historical data. Pull 60 bars by default, not 500. The agent doesn’t need a year of daily bars to make a daily decision.
- Summarize the journal rather than passing it in full. If the agent needs context from prior days, pass a summary file rather than the last 30 journal entries.
- Set explicit tool budgets. Claude Code lets you cap the number of tool calls per session — use this to prevent runaway research loops.
There’s a detailed breakdown of how to handle this in the AI agent token budget management guide. The short version: define what “done” looks like for each routine so the agent doesn’t keep calling tools after it has enough information to decide.
Step 10: Monitoring Without Babysitting
The whole point is that this runs without you. But you still want to know what’s happening. Two things make this easy:
Daily email digest. Add a final step to the end-of-day routine that sends a summary email. You can use a simple script with SendGrid or Mailgun:
# scripts/notify.py — sends today's journal as an email
import os, sys
import sendgrid
from sendgrid.helpers.mail import Mail
def send_digest(journal_path):
with open(journal_path, 'r') as f:
content = f.read()
sg = sendgrid.SendGridAPIClient(os.getenv("SENDGRID_API_KEY"))
message = Mail(
from_email="agent@yourdomain.com",
to_emails=os.getenv("NOTIFY_EMAIL"),
subject=f"Trading Agent Report — {journal_path.split('/')[-1]}",
plain_text_content=content
)
sg.send(message)
if __name__ == "__main__":
send_digest(sys.argv[1])
Heartbeat check. The agent writes a heartbeat.json file at the end of each run with a timestamp and status. If you haven’t seen a heartbeat by 5 PM on a trading day, something went wrong. This is the agentic OS heartbeat pattern in its simplest form.
What Realistic Results Look Like
Before you go in with expectations, look at how similar setups have actually performed. The OpenClaw AI trading bot challenge ran an AI-driven trading agent with $10,000 over 30 days and produced detailed public results — including the losses.
The takeaways from that experiment are applicable here:
- AI agents are good at consistent execution of a defined strategy, not at predicting market direction.
- The journal is the most valuable part of the whole system. It’s where you find patterns in why the agent underperforms.
- Paper trading results will look better than live results because of slippage and partial fills.
Set your expectations accordingly. This isn’t a money printer. It’s a tool for executing a strategy consistently, studying the results, and iterating.
Where Remy Fits
The trading agent in this guide runs on Claude Code. The research scripts, trade helpers, and journal system are all written in Python. If you’re comfortable with that setup, you’re good to go.
But if you want to go further — a full-stack dashboard that shows your portfolio in real time, a web interface for reviewing the journal, or a proper admin panel for adjusting the watchlist and risk settings without editing JSON files — that’s where Remy becomes useful.
Remy compiles annotated markdown specs into full-stack applications: a real backend, SQL database, authentication, and a frontend. So instead of reading your journal files in a text editor, you describe the interface you want in a spec and Remy builds it. The agent writes to the database instead of flat files. You log in from any browser and see positions, journal entries, and trade history in a proper UI.
The spec might look something like:
## Trading Dashboard
Shows the current portfolio state and trade journal.
### Portfolio View
Displays: cash balance, open positions with P&L, total account value.
Data source: Alpaca API via backend method.
### Journal Browser
Lists journal entries by date. Clicking an entry shows the full markdown.
Entries are stored in: journal_entries table [date: date, content: text, pnl_delta: decimal]
### Watchlist Manager
Allows editing the watchlist symbols and their allocation limits.
Validates that total max_allocation_pct across all symbols <= 80.
That spec compiles into a working application — backend, database, auth, deployment. The agent writes to it, you read from it. It’s a cleaner architecture than a pile of markdown files in a folder.
You can try Remy at mindstudio.ai/remy.
Frequently Asked Questions
Can I run this agent with live money instead of paper trading?
Yes, but only after extensive paper trading. Change APCA_BASE_URL to https://api.alpaca.markets and swap in your live API credentials. Be aware that live trading involves real fills, real slippage, and real tax implications. The SEC and FINRA regulate algorithmic trading for professional traders — individual retail investors using automated systems have more flexibility, but you should understand the rules that apply to your account type before going live.
How much does it cost to run this agent?
The main costs are Claude API inference (for three daily sessions), Alpaca (free for stock trading, some fees for crypto), and any hosting if you’re running this on a server rather than your local machine. Claude inference costs for a lightweight trading agent running three times per day typically run a few dollars per month. If you run deeper research loops or larger watchlists, costs go up. The Claude Code token budget management guide covers how to keep this predictable.
What happens if the agent makes a bad trade?
With the 5% position limit and 8% stop-loss rule in place, any single bad trade is contained. The bigger risk is a series of bad trades in the same direction. This is why the cash reserve rule matters — the agent can’t go all-in even if it’s convinced. Beyond that, reviewing the journal regularly (the daily email digest helps here) lets you catch systematic errors before they compound.
Can this agent short stocks or trade options?
The setup described here is long-only. Alpaca supports short selling and there are options APIs available, but both add significant complexity to the risk model. Short positions have theoretically unlimited downside, and options introduce Greeks and expiry management that require a much more sophisticated decision framework. Build confidence with long-only first.
Does the agent need the market to be open to run?
No, it runs on its schedule regardless. But the first step in every trading session is a market status check. If the market is closed (weekend, holiday, delayed open), the agent logs that and exits without placing any orders. The research and journaling routines can still run on non-trading days if you want the agent to do pre-market preparation.
How do I improve the agent’s strategy over time?
Read the journals. The agent’s explanations for its decisions are the diagnostic tool. If you see patterns — always selling too early, consistently missing momentum plays, getting spooked by news that turns out to be irrelevant — you update the CLAUDE.md instructions to address that pattern specifically. This is iterative. The agent doesn’t automatically get better, but you get better at directing it by studying what it does.
Key Takeaways
- A Claude Code trading agent runs three routines: research, execution, and journaling. Each is a separate scheduled task.
- Alpaca’s paper trading API gives you realistic fills without risking real capital. Use it until you trust the agent.
- Risk controls belong in three places: CLAUDE.md instructions, script-level validation, and Alpaca’s built-in protections.
- The trade journal is the most important output. It’s how you understand, audit, and improve the agent’s behavior.
- Token costs are manageable with tight research scopes and journal summarization — don’t pull more data than the agent needs.
- For a proper UI on top of the agent’s data, Remy compiles a full-stack dashboard from a spec without requiring you to hand-wire a backend.