Building Your First Trading Bot in Python: A Step-by-Step Guide
Building Your First Trading Bot in Python
Every quant's journey starts somewhere. This tutorial walks you through building a simple momentum trading bot from scratch — the same foundation used in professional systematic trading.
Architecture Overview
A trading bot has four components:
Step 1: Data Pipeline
import pandas as pd
import yfinance as yf
def fetch_data(tickers: list[str], period: str = "2y") -> pd.DataFrame:
"""Fetch daily OHLCV data for a universe of stocks."""
data = yf.download(tickers, period=period, group_by="ticker")
# Pivot to get adjusted close prices
closes = pd.DataFrame({
ticker: data[ticker]["Adj Close"]
for ticker in tickers
})
return closes
Step 2: Momentum Signal
The classic 12-1 momentum signal: rank stocks by their 12-month return, excluding the most recent month (to avoid short-term reversal).
def momentum_signal(prices: pd.DataFrame, lookback=252, skip=21) -> pd.DataFrame:
"""12-month momentum with 1-month skip."""
returns = prices.pct_change(lookback).shift(skip)
# Cross-sectional rank (0 to 1)
ranked = returns.rank(axis=1, pct=True)
return ranked
Step 3: Portfolio Construction
def construct_portfolio(signals: pd.DataFrame, long_pct=0.2) -> pd.DataFrame:
"""Long top quintile, equal-weight."""
threshold = 1 - long_pct
weights = (signals >= threshold).astype(float)
# Normalize to sum to 1
weights = weights.div(weights.sum(axis=1), axis=0).fillna(0)
return weights
Step 4: Backtest
def backtest(prices, weights):
"""Simple vectorized backtest."""
daily_returns = prices.pct_change()
portfolio_returns = (weights.shift(1) * daily_returns).sum(axis=1)
cumulative = (1 + portfolio_returns).cumprod()
sharpe = portfolio_returns.mean() / portfolio_returns.std() (252 * 0.5)
return cumulative, sharpe
What's Next
This bot trades once a month with zero leverage. To make it competition-ready:
- Add risk management (position limits, stop-losses, volatility targeting)
- Combine multiple signals (momentum + value + quality)
- Optimize execution timing (avoid trading at the close)