Alpaca stock trading with Python from setup to strategy

Alpaca stock trading with Python from setup to strategy
Alpaca stock trading through Python lets you buy, sell, and manage U.S. stocks with a few lines of code instead of clicking through a brokerage interface. If you're new to algorithmic trading (using software to place trades automatically based on rules you define), Alpaca is one of the easiest places to start. It offers commission-free trading. It also has a paper trading mode, so you can practice without risking real money. Its Python SDK handles most of the connection setup. If you want to compare Alpaca's approach with another popular brokerage API, see this guide to automating trades with Interactive Brokers.
Alpaca's own marketing site lists product features but doesn't show you how to actually use the platform with Python. This walkthrough fills that gap. It shows how to connect to Alpaca, download historical stock data, submit an order, and run a simple rule-based trading script.
How Alpaca Stock Trading Works
Alpaca is a brokerage built for developers. Instead of a traditional trading app with charts and buttons, it gives you an API (a way for your code to talk directly to the brokerage's servers). You send instructions like "buy 10 shares of AAPL" from a Python script, and Alpaca executes the trade.
There are two modes. Paper trading uses fake money so you can test your code without consequences. Live trading uses real money in a funded account. Both modes use the same API, so switching from practice to real trading requires changing only your API keys (the credentials that identify your account).
Alpaca supports U.S. stocks, options, and crypto, but not every account gets access to every feature. Availability depends on your account type, approval status, and region. This walkthrough focuses on stocks because that's where most people start.
Why an API Helps
Manual trading doesn't scale. If you want to monitor 50 stocks and adjust your holdings every day based on specific rules, doing that by hand is slow and error-prone. An API lets you write those rules once and run them automatically.
Alpaca's commission-free model also matters. When you're testing strategies that trade often, commissions eat into returns fast. Removing that cost makes it practical to experiment with approaches that place many small trades.
Alpaca Stock Python Setup
To follow along, create a free Alpaca account at alpaca.markets and generate your API key and secret key from the dashboard. For now, use the paper trading keys. Store them as environment variables so they don't end up in your code. Then install the alpaca-trade-api Python package.
A note on the SDK. Alpaca has promoted newer client libraries in recent years, but alpaca-trade-api still appears in many tutorials and works fine for learning. Check Alpaca's current docs if you want the latest recommended package.
pip install alpaca-trade-api
Now connect to Alpaca from Python. If your environment variables aren't set or your keys are wrong, the code below will raise an error, so wrap the connection in a try/except block.
import alpaca_trade_api as tradeapi
import os
API_KEY = os.environ["APCA_API_KEY_ID"]
SECRET_KEY = os.environ["APCA_API_SECRET_KEY"]
BASE_URL = "https://paper-api.alpaca.markets"
try:
api = tradeapi.REST(API_KEY, SECRET_KEY, BASE_URL, api_version="v2")
account = api.get_account()
print(f"Cash available: ${account.cash}")
print(f"Portfolio value: ${account.portfolio_value}")
except Exception as e:
print(f"Connection failed: {e}")
print("Check that your API keys are set correctly.")
If this prints your account details, you're connected. The BASE_URL points to the paper trading server. When you're ready for real money, you'd change it to https://api.alpaca.markets and use your live keys.
How to Pull Alpaca Stock Data and Place Orders
Getting Historical Price Data
Before you trade, you need data. Alpaca provides historical bars (price summaries over a time period like one day or one minute) through the same SDK. One thing to watch out for is that the code below uses your local machine's clock to set the date range. If you run it during market hours, the most recent day's bar may be incomplete or missing. Daily data is most reliable after the market session ends.
from alpaca_trade_api.rest import TimeFrame
from datetime import datetime, timedelta
bars = api.get_bars(
"AAPL",
TimeFrame.Day,
start=(datetime.now() - timedelta(days=30)).strftime("%Y-%m-%d"),
end=datetime.now().strftime("%Y-%m-%d"),
).df
print(bars.tail())
This returns a pandas DataFrame with columns for open, high, low, close, and volume. You can use this data to calculate indicators, test ideas, or just see what a stock has been doing recently. For a deeper look at how to turn historical data into a testable strategy, see this guide to building and testing trading strategies.
Submitting an Alpaca Stock Order
You can place an order with one function call. Keep in mind that a market order tells the broker to buy as soon as possible, but the final fill price can move slightly from the last displayed price. You don't get exact price control with market orders.
try:
order = api.submit_order(
symbol="AAPL",
qty=5,
side="buy",
type="market",
time_in_force="day"
)
print(f"Order ID: {order.id}")
print(f"Status: {order.status}")
except Exception as e:
print(f"Order failed: {e}")
The time_in_force="day" parameter means the order expires at market close if it hasn't been filled. Another option is "gtc" (good till canceled), which keeps the order open across multiple trading days.
An important detail is that when submit_order returns successfully, that means the order was accepted, not necessarily filled. The broker still needs to match it with a seller. You can check whether the trade actually completed by calling api.get_order(order.id) or looking at the order status in your Alpaca dashboard.
You can also place limit orders, which only execute at a price you specify.
limit_order = api.submit_order(
symbol="MSFT",
qty=3,
side="buy",
type="limit",
limit_price="400.00",
time_in_force="gtc"
)
This order will only fill if MSFT drops to $400 or below.
Checking Your Positions
After you place orders, check your current positions with this code.
positions = api.list_positions()
for p in positions:
profit_loss = float(p.unrealized_pl)
print(f"{p.symbol}: {p.qty} shares, unrealized profit or loss: ${profit_loss:.2f}")
The unrealized_pl field shows how much money you'd make or lose if you sold right now. This is useful for building logic that exits positions when they hit a profit target or a loss limit.
A Complete Alpaca Stock Trading Strategy in Python
Here's a working example that ties everything together. This strategy uses a simple moving average crossover. It calculates two averages of recent closing prices (one short-term, one long-term) and buys when the short-term average crosses above the long-term average. That crossover suggests recent prices are rising faster than the longer trend.
The script compares the two most recent completed trading days. If the short average was below the long average yesterday but is above it today, that counts as a buy signal (a rule that tells the script when to act). The reverse counts as a sell signal. This example leaves out several checks you would want before trading real money.
import alpaca_trade_api as tradeapi
from alpaca_trade_api.rest import TimeFrame
from datetime import datetime, timedelta
import pandas as pd
import os
API_KEY = os.environ["APCA_API_KEY_ID"]
SECRET_KEY = os.environ["APCA_API_SECRET_KEY"]
BASE_URL = "https://paper-api.alpaca.markets"
api = tradeapi.REST(API_KEY, SECRET_KEY, BASE_URL, api_version="v2")
SYMBOL = "SPY"
SHORT_WINDOW = 10
LONG_WINDOW = 30
# Pull recent daily bars
bars = api.get_bars(
SYMBOL,
TimeFrame.Day,
start=(datetime.now() - timedelta(days=60)).strftime("%Y-%m-%d"),
end=datetime.now().strftime("%Y-%m-%d"),
).df
# Make sure we have enough data
if len(bars) < LONG_WINDOW + 2:
print(f"Not enough data: got {len(bars)} bars, need at least {LONG_WINDOW + 2}")
else:
# Calculate moving averages
bars["sma_short"] = bars["close"].rolling(window=SHORT_WINDOW).mean()
bars["sma_long"] = bars["close"].rolling(window=LONG_WINDOW).mean()
latest = bars.iloc[-1]
previous = bars.iloc[-2]
crossed_above = (
previous["sma_short"] <= previous["sma_long"]
and latest["sma_short"] > latest["sma_long"]
)
crossed_below = (
previous["sma_short"] >= previous["sma_long"]
and latest["sma_short"] < latest["sma_long"]
)
# Get current position
try:
position = api.get_position(SYMBOL)
has_position = True
current_qty = int(position.qty)
except Exception:
has_position = False
current_qty = 0
# Execute trades
if crossed_above and not has_position:
api.submit_order(
symbol=SYMBOL, qty=10, side="buy",
type="market", time_in_force="day"
)
print(f"BUY signal: purchased 10 shares of {SYMBOL}")
elif crossed_below and has_position:
api.submit_order(
symbol=SYMBOL, qty=current_qty, side="sell",
type="market", time_in_force="day"
)
print(f"SELL signal: sold {current_qty} shares of {SYMBOL}")
else:
print(f"No signal. SMA{SHORT_WINDOW}: {latest['sma_short']:.2f}, "
f"SMA{LONG_WINDOW}: {latest['sma_long']:.2f}")
This script is meant to run once per day, after market close or before market open. You could schedule it with cron on Linux or Task Scheduler on Windows. Each run pulls fresh data, recalculates the averages, and decides whether to buy, sell, or do nothing.
This is a teaching example, not code you should run with real money without more testing. Moving average crossovers on their own don't reliably make money. The useful part is the workflow. The script downloads data, applies a rule, checks whether you already hold the stock, and then decides whether to trade. Once you have this skeleton, you can swap in any logic you want.
You should also test any strategy on old market data before running it with real money. That process checks your trading rule against historical prices to see how it would have behaved. It won't guarantee future results, but it catches obvious problems. For a walkthrough on how to do that with Alpaca, see this covered call strategy example.
For full API documentation, including a live data connection that pushes updates to your program as they happen, see the official Alpaca API docs.
Before You Trade Alpaca Stock With Real Money
Start with paper trading and stay there until you've run your script for at least a week. Log every order and your account value each day so you can see whether the strategy behaves the way you expect.
Use small order sizes. Even after switching to a live account, there's no reason to risk large amounts while you're still learning the API. Always confirm that an order was actually filled by checking its status, either through api.get_order(order.id) or in the Alpaca dashboard. Submitting an order and completing a trade are two different things.
From here, you can limit how much money goes into one trade. You can also expand the script to handle more than one stock or use a different entry rule. Run this script in paper trading for a week and log each order and account value before considering real capital.
The free Algorithmic Trading With Python guides explain how to test a trading rule on old market data and how to run your code against a real brokerage account.