Simple Moving Average Strategy
A classic trend-following strategy using moving average crossovers.
Strategy Overview
This strategy uses two simple moving averages (SMAs) to generate buy and sell signals:
- Short SMA: 10-day moving average
- Long SMA: 30-day moving average
- Buy Signal: Short SMA crosses above Long SMA
- Sell Signal: Short SMA crosses below Long SMA
Complete Agent Code
sma_crossover_agent.pypython
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from podium_sdk import Agent, Context
class SmaCrossoverAgent(Agent):
"""
A simple moving average crossover strategy.
Buys when the 10-day SMA crosses above the 30-day SMA.
Sells when the 10-day SMA crosses below the 30-day SMA.
"""
# Define universe of stocks to trade
universe = [
"AAPL", "MSFT", "GOOGL", "AMZN", "META",
"NVDA", "TSLA", "JPM", "V", "WMT"
]
# Risk limits
risk_limits = {
"max_position_size": 0.1, # Max 10% per position
"max_drawdown": 0.2, # 20% max drawdown
}
# Run daily
schedule = "daily"
def initialize(self, context: Context) -> None:
"""Called once at agent startup."""
context.log.info("Initializing SMA Crossover Agent")
context.log.info(f"Universe: {', '.join(self.universe)}")
def analyze(self, context: Context) -> None:
"""Main analysis method called on each tick."""
# Get historical price data
prices = context.data.prices(
symbols=self.universe,
lookback="40d" # Get enough data for 30-day SMA
)
# Calculate moving averages
short_window = 10
long_window = 30
short_sma = prices["close"].rolling(short_window).mean()
long_sma = prices["close"].rolling(long_window).mean()
# Get current positions
current_positions = context.portfolio.positions()
# Generate signals for each symbol
for symbol in self.universe:
# Skip if we don't have enough data
if prices["close"][symbol].isna().any():
continue
# Current SMAs
current_short = short_sma[symbol].iloc[-1]
current_long = long_sma[symbol].iloc[-1]
previous_short = short_sma[symbol].iloc[-2]
previous_long = long_sma[symbol].iloc[-2]
# Check for crossover
bullish_cross = (
previous_short <= previous_long and
current_short > current_long
)
bearish_cross = (
previous_short >= previous_long and
current_short < current_long
)
# Current position
position = current_positions.get(symbol, 0)
# Execute trades
if bullish_cross and position <= 0:
# Buy signal - allocate equal weight
weight = 1.0 / len(self.universe)
context.orders.buy(symbol, weight=weight)
context.log.info(f"BUY {symbol}: Short SMA ({current_short:.2f}) "
f"> Long SMA ({current_long:.2f})")
elif bearish_cross and position > 0:
# Sell signal - close position
context.orders.sell(symbol, weight=1.0)
context.log.info(f"SELL {symbol}: Short SMA ({current_short:.2f}) "
f"< Long SMA ({current_long:.2f})")
elif position == 0 and not bullish_cross:
# No position and no signal - ensure we're flat
context.orders.sell(symbol, weight=1.0)
# Run the agent
if __name__ == "__main__":
agent = SmaCrossoverAgent()
agent.run()How It Works
1
Fetch Data
Retrieve 40 days of historical price data for all symbols in the universe.
2
Calculate Indicators
Compute 10-day and 30-day simple moving averages using pandas rolling windows.
3
Detect Crossovers
Compare current and previous SMA values to identify crossover events.
4
Execute Trades
Buy on bullish crossovers, sell on bearish crossovers, using equal weight allocation.
Performance Note: Simple moving average strategies can underperform in choppy or range-bound markets. Consider adding filters like volume confirmation or trend strength indicators to improve performance.
Strategy Variations
Exponential Moving Average (EMA)
Use EMA instead of SMA for faster reaction to price changes:prices["close"].ewm(span=10).mean()
Triple Crossover
Add a third SMA for additional confirmation. Buy only when all three are aligned bullish.
Adaptive Windows
Adjust SMA periods based on market volatility or trend strength.
Next Steps
- Backtest this strategy to see historical performance
- Build a multi-factor model for more sophisticated signals
- Explore the Agent API for more configuration options