Alpaca Markets Trading API Review: Commission-Free Algo Trading for Developers
A developer's hands-on review of Alpaca's trading API — paper trading setup, Python SDK, real-time websocket streams, order execution, and how it compares to IBKR for retail algo trading.
When I first heard about Alpaca Markets, the pitch was “commission-free trading with an API designed for developers.” I had been wrestling with Interactive Brokers’ TWS gateway for months — the Java process that crashes every Tuesday, the binary socket protocol, the callback spaghetti. Alpaca promised a REST API, a Python SDK that installs with one command, and paper trading that does not require running a local gateway. I was skeptical. Broker APIs that are easy to use usually sacrifice something — instrument coverage, execution quality, market data depth. After building and running a small momentum strategy on Alpaca for six months, here is what I found.
Setting Up in Under Five Minutes
This is the part that genuinely impressed me. Open an account at alpaca.markets, generate API keys from the dashboard, and you are writing code in less time than it takes IBKR’s account approval to clear:
from alpaca.trading.client import TradingClient
from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
import os
trading_client = TradingClient(
api_key=os.environ['ALPACA_API_KEY'],
secret_key=os.environ['ALPACA_SECRET_KEY'],
paper=True # Flip to False for live trading
)
account = trading_client.get_account()
print(f"Buying power: ${account.buying_power}")
print(f"Portfolio value: ${account.portfolio_value}")
The paper=True flag routes everything to Alpaca’s paper trading environment. No separate credentials. No local gateway. The paper environment simulates fills with reasonable latency and includes all the same endpoints as live — orders, positions, account data. This is the first broker API I have used where paper trading actually felt like a first-class feature rather than an afterthought.
The SDK splits logically into three modules: alpaca.trading for orders and positions, alpaca.data for historical and real-time market data, and alpaca.broker for account management. You import only what you need. This is good API design.
Real-Time Data via WebSocket
Alpaca offers two data paths: a REST API for historical bars and a WebSocket stream for real-time quotes, trades, and bars. The WebSocket is where most algo trading strategies live:
from alpaca.data.live import StockDataStream
stream = StockDataStream(
api_key=os.environ['ALPACA_API_KEY'],
secret_key=os.environ['ALPACA_SECRET_KEY']
)
async def on_bar(data):
print(f"{data.symbol}: ${data.close} | VWAP ${data.vwap} | Vol {data.volume}")
stream.subscribe_bars(on_bar, 'AAPL', 'TSLA', 'SPY')
stream.run() # Blocks until interrupted
The WebSocket connection handles reconnection automatically, which is more than I can say for some paid data providers. The trade-off is data fidelity — Alpaca’s free tier provides IEX-sourced data (typically 5-10% of consolidated volume), while the paid tier ($9/month at time of writing) provides SIP-sourced consolidated data. For strategies that trade on closing prices or daily signals, IEX is fine. For anything that needs tick-level precision or depends on volume analysis, the paid tier is necessary.
Placing and Managing Orders
Alpaca’s order model is clean: you create an order request object, submit it, and receive an order object back with a unique ID you can use to query status, cancel, or modify:
from alpaca.trading.requests import LimitOrderRequest, TakeProfitRequest, StopLossRequest
from alpaca.trading.enums import OrderSide, OrderClass, TimeInForce
# Bracket order: parent limit order + take profit + stop loss
order = LimitOrderRequest(
symbol='SPY',
qty=10,
side=OrderSide.BUY,
time_in_force=TimeInForce.DAY,
limit_price=440.50,
order_class=OrderClass.BRACKET,
take_profit=TakeProfitRequest(limit_price=445.00),
stop_loss=StopLossRequest(stop_price=435.00)
)
result = trading_client.submit_order(order)
print(f"Order ID: {result.id}")
Bracket orders are worth highlighting because they execute atomically — the take profit and stop loss are not separate API calls. If the parent fills, the brackets are immediately active. If the parent is cancelled, the brackets are cancelled automatically. This is the difference between a strategy that survives a network blip and one that leaves a naked position open overnight.
The one limitation I hit repeatedly: Alpaca supports equities and ETFs only. No options, no futures, no forex, no bonds. If your strategy requires anything beyond stocks, you will eventually outgrow Alpaca. I moved my options strategies back to IBKR and kept Alpaca for the equity momentum strategy that doesn’t need derivatives.
Building a Simple Momentum Strategy
Here is a minimal example that actually runs — it buys the top-performing ETF from a basket based on trailing 20-day returns and rebalances weekly:
import pandas as pd
from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockBarsRequest
from alpaca.data.timeframe import TimeFrame
data_client = StockHistoricalDataClient(api_key, secret_key)
symbols = ['SPY', 'QQQ', 'IWM', 'TLT', 'GLD']
def get_momentum_scores():
request = StockBarsRequest(
symbol_or_symbols=symbols,
timeframe=TimeFrame.Day,
start=(pd.Timestamp.now() - pd.Timedelta(days=30)).strftime('%Y-%m-%d'),
limit=25
)
bars = data_client.get_stock_bars(request).df
returns = bars.groupby('symbol')['close'].last() / \
bars.groupby('symbol')['close'].first() - 1
return returns.sort_values(ascending=False)
scores = get_momentum_scores()
print(f"Top performer: {scores.index[0]} ({scores.iloc[0]:.2%})")
This is not a profitable strategy. It is a template. Replace the ETF basket with your own universe, add a volatility filter, and test before live deployment. The point is that Alpaca’s API surface is small enough that you can build an end-to-end strategy in under 100 lines of Python — from data fetch to order execution — without fighting infrastructure.
Alpaca vs. Interactive Brokers: When to Use Which
After using both APIs for real money, the decision framework is straightforward:
Use Alpaca if: you are building equity-only strategies, value clean APIs over instrument coverage, want to get from idea to paper trading in an afternoon, or are deploying on a cloud server and do not want to manage a local gateway process.
Use IBKR if: you need options, futures, forex, or international markets; your strategy depends on smart order routing across multiple exchanges; you require margin trading with programmatic margin requirement queries; or you are trading sizes where the $0.65 Alpaca charges on short sales adds up.
Alpaca is commission-free for stock and ETF trades. Short selling costs roughly $0.65 per trade at time of writing. IBKR’s pricing is volume-tiered and can be lower for active traders but adds exchange fees and regulatory fees that Alpaca absorbs.
For my own workflow, I use Alpaca for the momentum rotation strategy (equities only, weekly rebalance, simple execution) and IBKR for anything involving options or margin. The API styles are different enough that context-switching between them is annoying, but the right tool for the job is usually determined by asset class, not API aesthetics.
FAQ
Is Alpaca's paper trading realistic enough to test strategies?
Does Alpaca support short selling?
Can I run multiple strategies on the same Alpaca account?
How does Alpaca handle corporate actions (dividends, splits, mergers)?
What happens if the WebSocket disconnects mid-trade?
Related reading
2026-06-22
Position Sizing and Risk per Trade: The Math Retail Investors Skip in 2026
How to size a trade from risk instead of conviction: the fixed-fractional formula, fractional Kelly, R-multiples, and the drawdown math that decides whether a losing streak is survivable.
2026-06-22
Dollar-Cost Averaging vs Lump Sum: What the Math Really Says
A measured look at why lump-sum investing usually beats dollar-cost averaging on expected return, when DCA still makes sense, and how to decide for your own cash.
2026-06-22
What the Sharpe Ratio Actually Tells You (and Where It Misleads)
The Sharpe ratio measures excess return per unit of volatility. Here is exactly what the number captures, the four assumptions that break it, and when to trust it.
2026-06-22
Tiingo vs Polygon.io: Market Data APIs for Indie Quant Projects in 2026
A practical comparison of Tiingo and Polygon.io for solo quant builders in 2026 — pricing, rate limits, data coverage, and which one fits a weekend backtester.
2026-06-22
Building a Portfolio Rebalancing Script in Python: From Drift to Trades
A practical walkthrough of writing a Python rebalancing script: measuring allocation drift, generating a self-funding trade list, and using threshold bands to avoid over-trading.
Get the best tools, weekly
One email every Friday. No spam, unsubscribe anytime.