Library · Special topics: trading and crypto (not financial advice)

Algorithmic trading with Claude Code: connecting Alpaca through MCP and managing risk

Builder90 minUpdated: October 2026
100 of 105 in the library

Module: Trending cases 2026 | Time: about 30 min theory + 60 min practice (paper trading)


The gist

Claude Code can manage a trading account, analyze the market and build strategies through Alpaca's official MCP server and API. This is not "AI predicts prices" (nobody can do that reliably). It's "AI automates carrying out a strategy, keeping track of a portfolio and managing risk." Start with paper trading, using virtual money, until you trust your strategy. This lesson teaches you to work with the tools. It does not promise income and is not investment advice.

🎨 Picture this: Claude Code for trading is like a hired executive who carries out your trades. You set the rules: "buy when X, sell when Y, never risk more than 5%." It follows them. It doesn't sleep, doesn't panic, doesn't sell out of fear and doesn't hold out of greed.


⚠️ Required disclaimer

This is an educational lesson. It is not financial advice and not an investment recommendation. Algorithmic trading carries a real risk of losing money, and results on a virtual account don't guarantee results on a real one. A large share of retail traders lose money: some regulators require brokers to publish the percentage of losing accounts, so look for that number at your broker. Always start with paper trading. Real money only after a long test on a virtual account, after you understand every line of the code, and after talking to a licensed professional.


Key concepts

  • Alpaca: a broker with an API (application programming interface, a way for programs to talk to each other) built for algorithmic trading (US stocks, crypto)
  • Alpaca MCP: Alpaca's official MCP server for Claude Code
  • Paper trading: trading with virtual money (free, you only need to sign up on the broker's site)
  • Position limit: the maximum size of one position (5% in this lesson, as a teaching example)
  • Stop-loss: automatically closing a position when it loses a set amount (-8% in this lesson, as a teaching example)
  • Backtesting: testing a strategy on historical data

Theory

Alpaca: an API-first broker

Alpaca is a US broker built specifically for algorithmic trading. Unlike retail brokers with a polished app, Alpaca's main product is its API.

🎨 Picture this: Alpaca is like a bank for programmers. A regular bank has a nice app, but its API is closed or paid. With Alpaca, the API is free and documented, and the app comes second.

Features (the broker's terms change, so check its website):

Feature Alpaca
US stocks ✅ (NYSE, NASDAQ)
Fractional shares ✅ (minimum amount: on Alpaca's site)
Crypto ✅ (BTC, ETH and others)
Paper trading ✅ Free, sign-up required
Live account ✅ Terms and fees: on Alpaca's site
Minimum deposit None for paper; for a live account: on Alpaca's site
API cost Basic access is free; extended market data may cost extra
WebSocket streams ✅ Real-time data
Countries where you can open an account ⚠️ The list changes: check whether Alpaca accepts residents of your country

Signing up for paper trading:

  1. alpaca.markets → Sign Up
  2. Create an account → you get a paper trading account and keys
  3. Paper trading comes with a virtual balance (the starting amount is listed on Alpaca's site)
  4. Your keys are in your dashboard → API Keys

Alpaca MCP: connecting it to Claude Code

Alpaca has an official MCP server (the alpacahq/alpaca-mcp-server repository). It runs through uvx (a Python package runner):

bash
# Connect with one command
claude mcp add alpaca --scope user --transport stdio uvx alpaca-mcp-server

Or through a .mcp.json file in your project folder:

json
{
  "mcpServers": {
    "alpaca": {
      "command": "uvx",
      "args": ["alpaca-mcp-server"],
      "env": {
        "ALPACA_API_KEY": "your_key_id",
        "ALPACA_SECRET_KEY": "your_secret_key",
        "ALPACA_PAPER_TRADE": "true"
      }
    }
  }
}

To check that the server connected, run the /mcp command.

ALPACA_PAPER_TRADE=true: virtual money (this is the default) ALPACA_PAPER_TRADE=false with live keys: real money. Don't switch until you've passed every check in this lesson.

Don't paste your keys directly into a file that will end up in git: keep them in environment variables or a password manager (more on this in the lesson Security in Claude Code).

🎨 Picture this: the difference between paper and live mode is like a flight simulator versus a real airplane. They look the same and behave the same. But in the simulator you can fly into a mountain and try again.


What Claude Code can do through Alpaca MCP

Once it's connected, you ask Claude Code:

Type this into the chat
"Show my current balance and open positions"
"Buy 10 shares of AAPL at market price"
"Sell 5 shares of MSFT with a $420 limit"
"Show my trade history for the past week"
"Close all open positions"
"What's my P&L for today?"

Claude Code turns these requests into API calls to Alpaca and returns the results.


Python + Alpaca API: full control

For more complex strategies, use Python code directly.

Important: the example below uses the alpaca-trade-api library. Its repository was archived (June 2026), and for new code Alpaca recommends its official SDK, alpaca-py. The logic of the checks (position size, stop-loss, daily limit) doesn't depend on the library: when you move to alpaca-py, only the API calls change.

bash
pip install alpaca-trade-api pandas numpy
python
import alpaca_trade_api as tradeapi
import pandas as pd
import os

# Connect to paper trading
api = tradeapi.REST(
    os.environ['ALPACA_API_KEY'],
    os.environ['ALPACA_SECRET_KEY'],
    'https://paper-api.alpaca.markets',
    api_version='v2'
)

def check_account():
    """Check the account status"""
    account = api.get_account()
    print(f"Balance: ${float(account.equity):.2f}")
    print(f"Buying power: ${float(account.buying_power):.2f}")
    print(f"Status: {account.status}")

def get_positions():
    """Current positions"""
    positions = api.list_positions()
    for pos in positions:
        pnl = float(pos.unrealized_pl)
        pnl_pct = float(pos.unrealized_plpc) * 100
        print(f"{pos.symbol}: {pos.qty} shares | P&L: ${pnl:.2f} ({pnl_pct:.1f}%)")

def safe_market_order(symbol: str, qty: float, side: str, 
                       max_position_pct: float = 0.05):
    """
    Safe market order with a position size check.
    max_position_pct = no more than 5% of capital in one position.
    """
    account = api.get_account()
    equity = float(account.equity)
    
    # Get the price
    last_trade = api.get_latest_trade(symbol)
    price = float(last_trade.price)
    
    # Check the position size
    position_value = qty * price
    position_pct = position_value / equity
    
    if position_pct > max_position_pct:
        max_qty = int((equity * max_position_pct) / price)
        print(f"⚠️ Reducing size: {qty} → {max_qty} (5% portfolio limit)")
        qty = max_qty
    
    if qty <= 0:
        print("❌ Position size is too small")
        return None
    
    # Place the order
    order = api.submit_order(
        symbol=symbol,
        qty=qty,
        side=side,         # 'buy' or 'sell'
        type='market',
        time_in_force='gtc'
    )
    
    print(f"✅ Order placed: {side.upper()} {qty}x {symbol} (~${position_value:.2f})")
    return order

def set_stop_loss(symbol: str, stop_loss_pct: float = 0.08):
    """
    Sets a stop-loss on an existing position.
    stop_loss_pct = 0.08 → close if the loss reaches 8%
    """
    try:
        position = api.get_position(symbol)
        current_price = float(position.current_price)
        stop_price = current_price * (1 - stop_loss_pct)
        qty = abs(int(float(position.qty)))
        
        # Stop-loss order
        order = api.submit_order(
            symbol=symbol,
            qty=qty,
            side='sell',
            type='stop',
            stop_price=round(stop_price, 2),
            time_in_force='gtc'
        )
        
        print(f"🛡️ Stop-loss set: {symbol} @ ${stop_price:.2f} ({stop_loss_pct*100}%)")
        return order
    except Exception as e:
        print(f"❌ No position in {symbol}: {e}")

# Example usage
if __name__ == "__main__":
    check_account()
    print("\nCurrent positions:")
    get_positions()
    
    # Buy AAPL (no more than 5% of the portfolio)
    safe_market_order("AAPL", 5, "buy")
    
    # Set a -8% stop-loss
    set_stop_loss("AAPL", 0.08)

A simple strategy: moving averages

🎨 Picture this: a moving average is like the average temperature over the last 30 days. It doesn't jump around from one day to the next. It shows the trend. When the short average (7 days) crosses the long one (21 days) from below, that may be the start of a rise. When it crosses from above, that may be the start of a fall.

python
def simple_ma_strategy(symbol: str, short_window: int = 7, long_window: int = 21):
    """
    Moving average crossover strategy.
    FOR LEARNING ONLY. Not financial advice!
    """
    import datetime
    
    # Get historical data
    end = datetime.datetime.now()
    start = end - datetime.timedelta(days=60)
    
    bars = api.get_bars(
        symbol,
        tradeapi.TimeFrame.Day,
        start.strftime('%Y-%m-%d'),
        end.strftime('%Y-%m-%d')
    ).df
    
    # Calculate the moving averages
    bars['SMA_short'] = bars['close'].rolling(window=short_window).mean()
    bars['SMA_long'] = bars['close'].rolling(window=long_window).mean()
    
    # Signals
    bars['signal'] = 0
    bars.loc[bars['SMA_short'] > bars['SMA_long'], 'signal'] = 1   # Long
    bars.loc[bars['SMA_short'] < bars['SMA_long'], 'signal'] = -1  # Short/Flat
    
    # Latest signal
    last_signal = bars['signal'].iloc[-1]
    last_price = bars['close'].iloc[-1]
    
    print(f"\n{symbol} @ ${last_price:.2f}")
    print(f"SMA{short_window}: ${bars['SMA_short'].iloc[-1]:.2f}")
    print(f"SMA{long_window}: ${bars['SMA_long'].iloc[-1]:.2f}")
    
    if last_signal == 1:
        print("📈 Signal: BUY (SMA_short > SMA_long)")
    elif last_signal == -1:
        print("📉 Signal: SELL (SMA_short < SMA_long)")
    else:
        print("⏸️ Signal: NEUTRAL")
    
    return last_signal, last_price

# Analyze several symbols
watchlist = ["AAPL", "MSFT", "NVDA", "AMZN"]
for ticker in watchlist:
    signal, price = simple_ma_strategy(ticker)

Risk management: required rules

🎨 Picture this: risk management rules are like safety rules on a construction site. You can work without a hard hat until a brick falls on your head. After the first brick, everyone wears one. In trading, the brick is a margin call. After that, there may be nothing left to protect.

5 basic rules (a teaching example, pick your own numbers):

python
RISK_RULES = {
    # Rule 1: No more than 5% of capital in one position
    "max_position_pct": 0.05,
    
    # Rule 2: A stop-loss on every position
    "stop_loss_pct": 0.08,
    
    # Rule 3: No more than 20% in one sector
    "max_sector_pct": 0.20,
    
    # Rule 4: Daily loss limit
    "max_daily_loss_pct": 0.03,  # Stop trading at -3% for the day
    
    # Rule 5: A check before every trade
    "pre_trade_checks": True,
}

def check_daily_loss_limit():
    """Stop trading if the daily loss is > 3%"""
    account = api.get_account()
    
    # Compare with the start of the day
    daily_pnl_pct = float(account.equity) / float(account.last_equity) - 1
    
    if daily_pnl_pct < -RISK_RULES["max_daily_loss_pct"]:
        print(f"🚨 DAILY LIMIT: loss {daily_pnl_pct*100:.1f}%. Stopping trading.")
        return False
    return True

Binance Futures through MCP (advanced)

For crypto trading, MCP catalogs list MCP servers for Binance futures. They're written by third-party authors, so before you connect one, check the author, the code and the repository history. You connect them the same way as any MCP server (claude mcp add or a .mcp.json file).

json
{
  "mcpServers": {
    "binance-futures": {
      "command": "uvx",
      "args": ["binance-futures-mcp"],
      "env": {
        "BINANCE_API_KEY": "your_key",
        "BINANCE_SECRET_KEY": "your_secret",
        "TESTNET": "true"  // ALWAYS start with testnet!
      }
    }
  }
}

Important: Binance Futures are leveraged derivatives. The risks are far higher than buying stocks without leverage. Start only on Testnet, and only if you fully understand how futures work. Availability depends on your country: check whether the exchange serves residents of your country.


What paper trading teaches you and what it doesn't

Developers regularly post experiments with a virtual account run through Claude Code and the Alpaca API. You can't verify the numbers in those posts, and you shouldn't treat them as a benchmark: they depend on the time period, the stocks chosen, and what the author shared or left out. The learning value of such an experiment is something else: you check that your code places orders, respects the limits and keeps a log.

What's important to understand: paper trading doesn't account for slippage (the difference between the price when the signal fires and the price you actually get), the market impact of large orders, or the psychology of real money. Real results are usually worse than virtual ones, and past results guarantee nothing about the future.


Practice

  1. Sign up at alpaca.markets → get paper trading API keys
  2. Set up Alpaca MCP in Claude Code (paper trading URL!)
  3. Ask Claude: "show my balance and open positions"
  4. Run the Python script → buy 1 share of AAPL (paper trading)
  5. Set a stop-loss on the position you bought
  6. Check your P&L after 24 hours and write down what needs fixing in the code

Tools and resources

  • Alpaca Markets: sign-up + documentation
  • Alpaca MCP: the official MCP server
  • alpaca-py: the current official Python SDK (the older alpaca-trade-api library is archived)
  • Backtrader: a Python framework for backtesting
  • MCPMarket: a catalog of MCP servers (servers for exchanges are written by third-party authors, so check their code)

Key takeaways

Alpaca MCP is the official way to manage a trading account through Claude Code. Always start with paper trading. Real money only after a long test on a virtual account, and even that doesn't guarantee results.

Teaching risk rules: 5% maximum per position, an 8% stop-loss on each one, a -3% daily loss limit. Without risk rules it's not trading, it's gambling. Choose your actual numbers yourself, together with a licensed professional.

Claude Code doesn't "predict" the market. Nobody can. It automates carrying out a strategy, monitoring risk and keeping logs. The strategy is your responsibility. This is not investment advice.


Next lesson

→ Social media automation: Instagram, messaging apps, content on autopilot

The mark stays in this browser only and is never sent anywhere. My progress