Skip to main content

Indicators & Signals

Indicators are mathematical calculations based on price, volume, or other market data. They form the building blocks of trading signals.

What is a Signal?​

A signal is a trigger that suggests a trading action. Signals are typically generated from indicators.

Indicator → Condition → Signal → Action
↓ ↓ ↓ ↓
RSI RSI < 30 Buy Open long

Trend Indicators​

Moving Averages​

Smooth price data to identify trends.

Simple Moving Average (SMA)

def sma(prices, window):
return sum(prices[-window:]) / window

# Usage
sma_20 = sma(close_prices, 20)
sma_50 = sma(close_prices, 50)

# Signal: Golden Cross (SMA20 crosses above SMA50)
if sma_20 > sma_50 and prev_sma_20 <= prev_sma_50:
signal = "BUY"

Exponential Moving Average (EMA)

Gives more weight to recent prices.

def ema(prices, window):
multiplier = 2 / (window + 1)
ema = prices[0]
for price in prices[1:]:
ema = (price - ema) * multiplier + ema
return ema

# VecAlpha built-in
ema_20 = self.ema(20) # In strategy class

Average Directional Index (ADX)​

Measures trend strength (not direction).

ADX ValueTrend Strength
0-25Weak or no trend
25-50Strong trend
50-75Very strong trend
75-100Extremely strong
adx = self.adx(14)
if adx > 25:
# Strong trend - use trend-following strategies
else:
# Weak trend - consider mean-reversion

Momentum Indicators​

Relative Strength Index (RSI)​

Measures speed and magnitude of price changes.

RSI = 100 - (100 / (1 + RS))
RS = Average Gain / Average Loss
RSI RangeInterpretation
> 70Overbought
50-70Bullish
30-50Bearish
< 30Oversold
rsi = self.rsi(14)

# Mean reversion signals
if rsi < 30:
signal = "BUY" # Oversold
elif rsi > 70:
signal = "SELL" # Overbought

MACD (Moving Average Convergence Divergence)​

Combines trend and momentum.

macd, signal_line, histogram = self.macd(12, 26, 9)

# Crossover signal
if macd > signal_line and prev_macd <= prev_signal:
signal = "BUY"
elif macd < signal_line and prev_macd >= prev_signal:
signal = "SELL"

Volatility Indicators​

Bollinger Bands​

Volatility-based envelopes around price.

Middle Band = 20 SMA
Upper Band = Middle + (2 × Standard Deviation)
Lower Band = Middle - (2 × Standard Deviation)
upper, middle, lower = self.bollinger(20, 2)

# Mean reversion signal
if price < lower:
signal = "BUY" # Price at lower band
elif price > upper:
signal = "SELL" # Price at upper band

Average True Range (ATR)​

Measures volatility.

atr = self.atr(14)

# Use for position sizing
stop_loss_distance = 2 * atr
position_size = risk_amount / stop_loss_distance

Volume Indicators​

On-Balance Volume (OBV)​

Tracks cumulative volume flow.

obv = self.obv()

# Divergence detection
if price_making_new_highs and obv_not_making_new_highs:
signal = "POTENTIAL_REVERSAL"

Volume Weighted Average Price (VWAP)​

Average price weighted by volume.

vwap = self.vwap()

# Mean reversion
if price < vwap:
# Price below VWAP - potential buy
signal = "BUY"

Combining Indicators​

Single indicators are rarely enough. Combine multiple for confirmation:

Example: Trend + Momentum​

def generate_signal(self):
# Trend filter
trend = self.sma(50) > self.sma(200)

# Momentum signal
rsi = self.rsi(14)

# Combined signal
if trend and rsi < 40: # Uptrend + oversold
return "BUY"
elif not trend and rsi > 60: # Downtrend + overbought
return "SELL"

return "HOLD"

Example: Multiple Timeframes​

def multi_timeframe_signal(self):
# Higher timeframe trend
daily_trend = self.sma(50, timeframe='1d') > self.sma(200, timeframe='1d')

# Lower timeframe entry
hourly_rsi = self.rsi(14, timeframe='1h')

if daily_trend and hourly_rsi < 30:
return "BUY"
return "HOLD"

Indicator Best Practices​

1. Understand What You're Measuring​

CategoryWhat It MeasuresExample Indicators
TrendDirection of price movementSMA, EMA, ADX
MomentumSpeed of price changeRSI, MACD, Stochastic
VolatilityMagnitude of price swingsATR, Bollinger Bands
VolumeTrading activityOBV, VWAP, Volume

2. Avoid Redundancy​

Don't use multiple indicators that measure the same thing:

# REDUNDANT: All measure momentum
indicators = ['RSI', 'Stochastic', 'CCI']

# BETTER: Different aspects
indicators = ['RSI', 'MACD', 'ATR'] # Momentum + Trend + Volatility

3. Match Indicators to Strategy Type​

Strategy TypeBest Indicators
Trend FollowingSMA, EMA, ADX, MACD
Mean ReversionRSI, Bollinger Bands, Stochastic
BreakoutATR, Donchian Channels
Pairs TradingCointegration, Correlation

4. Parameter Selection​

Common parameter ranges:

IndicatorDefaultRange to Test
SMA/EMA20, 50, 20010-200
RSI147-21
MACD12, 26, 9Various
Bollinger20, 215-25, 1.5-2.5

Custom Indicators​

Create your own in VecAlpha:

from vecalpha import Indicator

class CustomIndicator(Indicator):
"""Custom momentum indicator."""

def __init__(self, window=14):
self.window = window

def calculate(self, data):
closes = data['close']
volumes = data['volume']

# Custom calculation
momentum = closes.pct_change(self.window)
volume_weight = volumes / volumes.rolling(self.window).mean()

return momentum * volume_weight

# Use in strategy
custom = CustomIndicator(14)
signal_value = custom.calculate(self.data)

Next Steps​