Skip to main content
Skip to main content
Version: Next 🚧

EMA Crossover Strategy

Learn to build a sophisticated trend-following strategy using Exponential Moving Averages (EMAs) with additional confirmation filters. This intermediate tutorial builds on the basics and introduces multi-condition entry logic.

Strategy Overview

This strategy improves upon simple moving average crossovers by:

  • Using EMAs instead of SMAs (more responsive to recent price action)
  • Adding price position filter (price must be above both EMAs for long entries)
  • Including volume confirmation
  • Implementing trailing stops to maximize profits
  • Using partial exits to lock in gains progressively

Expected Performance

  • Win Rate: 40-50%
  • Profit Factor: 1.8-2.5
  • Best Markets: Trending stocks/commodities
  • Timeframe: 15m to 1h
  • Risk-Reward: 1:3

Why EMA Over SMA?

Exponential Moving Average (EMA) gives more weight to recent prices, making it:

  • More responsive to price changes
  • Better for trend-following
  • Generates earlier signals
  • Reduces lag compared to SMA

Formula: EMA = (Close × Multiplier) + (Previous EMA × (1 - Multiplier))

  • Multiplier = 2 / (Period + 1)

Step 1: Basic Configuration

Strategy Details

Name: EMA Trend Follower
Description: EMA crossover with price and volume confirmation
Strategy Type: Momentum
Timeframe: 15m
Symbols: NSE:RELIANCE, NSE:TCS, NSE:INFY
Multiple Symbols

Trading multiple symbols:

  • Diversifies risk across different stocks
  • Increases signal opportunities
  • Reduces impact of single stock volatility
  • Ensure symbols are not highly correlated

Step 2: Position Sizing

Use Risk-based position sizing for better risk management:

{
"method": "risk_based",
"riskPercentage": 1.5,
"stopLossPercentage": 2
}

How It Works

Position Size = (Account Balance × Risk%) / Stop Loss Distance

Example:
- Account: ₹100,000
- Risk per trade: 1.5% = ₹1,500
- Stop loss: 2% = ₹40 per share (if entry at ₹2,000)
- Position size: ₹1,500 / ₹40 = 37.5 shares ≈ 37 shares

This automatically adjusts position size based on stop loss distance, ensuring consistent risk per trade.

Step 3: Entry Conditions

Create a multi-condition entry system with three filters:

Condition 1: EMA Crossover (Primary Signal)

For Long Entries:

{
"type": "indicator_indicator",
"indicator1": "EMA",
"period1": 9,
"indicator2": "EMA",
"period2": 21,
"operator": "crosses_above"
}

The 9 EMA crossing above the 21 EMA signals bullish momentum.

EMA Periods
  • 9 EMA: Fast-moving, captures short-term trends
  • 21 EMA: Medium-term trend filter
  • 50 EMA: Long-term trend direction (we'll use this next)

Common combinations: 9/21, 12/26, 20/50

Condition 2: Price Above EMAs (Trend Filter)

{
"type": "price_indicator",
"priceType": "close",
"indicator": "EMA",
"period": 50,
"operator": "above"
}

This ensures we only enter when price is above the 50 EMA, confirming an uptrend.

Why This Matters:

  • Filters out counter-trend signals
  • Increases win rate significantly
  • Aligns trades with dominant trend
  • Reduces whipsaws in ranging markets

Condition 3: Volume Confirmation

{
"type": "indicator_value",
"indicator": "Volume",
"period": 20,
"operator": "above",
"value": "SMA"
}

Volume must be above its 20-period average, confirming genuine buying interest.

Complete Entry Configuration

{
"positionType": "both",
"logicalOperator": "AND",
"confirmationCandles": 2,
"conditions": [
{
"type": "indicator_indicator",
"indicator1": "EMA",
"period1": 9,
"indicator2": "EMA",
"period2": 21,
"operator": "crosses_above"
},
{
"type": "price_indicator",
"priceType": "close",
"indicator": "EMA",
"period": 50,
"operator": "above"
},
{
"type": "indicator_value",
"indicator": "Volume",
"period": 20,
"operator": "above",
"value": "SMA"
}
]
}
Confirmation Candles

Setting confirmationCandles: 2 means:

  • Wait for 2 candles after signal
  • Reduces false breakouts
  • Slightly delays entry but improves quality
  • Recommended for 15m timeframe

Step 4: Exit Conditions

Implement a sophisticated exit strategy with multiple components:

Stop Loss: ATR-Based

{
"type": "ATR",
"period": 14,
"multiplier": 2.0
}

Average True Range (ATR) adapts to market volatility:

  • High volatility → Wider stops (avoids premature exits)
  • Low volatility → Tighter stops (protects capital)
  • 2.0 multiplier is standard (1.5 for aggressive, 2.5 for conservative)

Example:

Entry: ₹2,000
ATR(14): ₹30
Stop Loss: ₹2,000 - (₹30 × 2.0) = ₹1,940

Take Profit: Multiple Targets (Partial Exits)

{
"type": "multiple_targets",
"targets": [
{
"percentage": 3,
"exitPercentage": 33,
"moveStopTo": "breakeven"
},
{
"percentage": 6,
"exitPercentage": 33
},
{
"percentage": 9,
"exitPercentage": 34
}
]
}

Scaling Out Strategy:

  1. First Target (3%): Exit 33% of position, move stop to breakeven
  2. Second Target (6%): Exit another 33%
  3. Third Target (9%): Exit remaining 34%

Benefits:

  • Locks in profits progressively
  • Reduces risk after first target
  • Lets winners run
  • Psychological comfort (guaranteed profit after target 1)

Trailing Stop

{
"enabled": true,
"type": "percentage",
"percentage": 2,
"activationThreshold": 2
}

How It Works:

  1. Activates after 2% profit
  2. Trails price by 2%
  3. Locks in profits as price rises
  4. Never moves down (only up for longs)

Example:

Entry: ₹2,000
Price rises to ₹2,100 (+5%)
Trailing stop: ₹2,100 - 2% = ₹2,058
Price rises to ₹2,150 (+7.5%)
Trailing stop: ₹2,150 - 2% = ₹2,107

Exit on Opposite Signal

{
"enabled": true,
"closeImmediately": true
}

Exit long positions when 9 EMA crosses below 21 EMA (and vice versa for shorts).

Step 5: Risk Parameters

{
"maxPositionSize": 15,
"maxDailyLoss": 4,
"maxOpenPositions": 5,
"riskRewardRatio": 2
}

Parameter Explanations

maxPositionSize: 15%

  • Allows larger positions than beginner strategy
  • Still maintains diversification
  • Suitable for liquid stocks

maxDailyLoss: 4%

  • Circuit breaker for bad days
  • Prevents emotional trading
  • Protects capital

maxOpenPositions: 5

  • Can trade multiple symbols simultaneously
  • Increases opportunity
  • Manages overall exposure

riskRewardRatio: 2

  • Minimum 1:2 risk-reward
  • With 40% win rate, still profitable
  • Ensures favorable odds

Complete Strategy Configuration

Here's the full JSON configuration:

{
"name": "EMA Trend Follower",
"description": "EMA crossover with price and volume confirmation",
"strategyType": "momentum",
"timeframe": "15m",
"symbols": ["NSE:RELIANCE", "NSE:TCS", "NSE:INFY"],

"positionSizing": {
"method": "risk_based",
"riskPercentage": 1.5,
"stopLossPercentage": 2
},

"entryConditions": {
"positionType": "both",
"logicalOperator": "AND",
"confirmationCandles": 2,
"conditions": [
{
"type": "indicator_indicator",
"indicator1": "EMA",
"period1": 9,
"indicator2": "EMA",
"period2": 21,
"operator": "crosses_above"
},
{
"type": "price_indicator",
"priceType": "close",
"indicator": "EMA",
"period": 50,
"operator": "above"
},
{
"type": "indicator_value",
"indicator": "Volume",
"period": 20,
"operator": "above",
"value": "SMA"
}
]
},

"exitConditions": {
"stopLoss": {
"type": "ATR",
"period": 14,
"multiplier": 2.0
},
"takeProfit": {
"type": "multiple_targets",
"targets": [
{
"percentage": 3,
"exitPercentage": 33,
"moveStopTo": "breakeven"
},
{
"percentage": 6,
"exitPercentage": 33
},
{
"percentage": 9,
"exitPercentage": 34
}
]
},
"trailingStop": {
"enabled": true,
"type": "percentage",
"percentage": 2,
"activationThreshold": 2
},
"exitOnOppositeSignal": {
"enabled": true,
"closeImmediately": true
}
},

"riskParameters": {
"maxPositionSize": 15,
"maxDailyLoss": 4,
"maxOpenPositions": 5,
"riskRewardRatio": 2
}
}

Running a Backtest

Before deploying, test the strategy:

1. Create Backtest

Navigate to BacktestsNew Backtest

2. Configure Parameters

Date Range: Last 6 months
Initial Balance: ₹100,000
Symbols: NSE:RELIANCE, NSE:TCS, NSE:INFY
Slippage: 0.1%
Commission: 0.05% per trade

3. Interpret Results

Look for these metrics:

Good Results:

Total Trades: 45
Win Rate: 44%
Profit Factor: 2.1
Total Return: +18.5%
Max Drawdown: -8.2%
Sharpe Ratio: 1.8

Warning Signs:

Win Rate: <35% (too many losses)
Profit Factor: <1.5 (not profitable enough)
Max Drawdown: >20% (too risky)
Total Trades: <20 (not enough data)

4. Analyze Trade Distribution

Check the trade distribution chart:

  • Should see more winning trades than losing
  • Winning trades should be larger than losing trades
  • Drawdown periods should recover quickly

Optimization Tips

If Win Rate is Too Low (<40%)

  1. Increase confirmation candles from 2 to 3
  2. Add RSI filter: Only enter when RSI is between 40-60 (neutral zone)
  3. Tighten trend filter: Require price above both 21 and 50 EMAs

If Profit Factor is Low (<1.5)

  1. Widen stop loss: Increase ATR multiplier from 2.0 to 2.5
  2. Adjust targets: Change to 4%, 8%, 12% instead of 3%, 6%, 9%
  3. Use trailing stop more aggressively: Activate at 1% instead of 2%

If Too Few Signals

  1. Reduce confirmation candles from 2 to 1
  2. Remove volume filter (keep only EMA and price filters)
  3. Add more symbols to trade
  4. Use shorter timeframe (5m instead of 15m)

If Too Many Signals

  1. Add time filters: Trade only during high-volume hours (10 AM - 2 PM)
  2. Increase EMA periods: Use 12/26 instead of 9/21
  3. Add ADX filter: Only trade when ADX > 25 (strong trend)

Common Mistakes to Avoid

1. Ignoring Market Conditions

Problem: Strategy works in trending markets but fails in ranging markets.

Solution:

  • Add ADX filter (ADX > 25 for trending markets)
  • Pause algorithm during low-volatility periods
  • Monitor market regime (trending vs ranging)

2. Over-Optimization

Problem: Tweaking parameters until backtest looks perfect.

Solution:

  • Use walk-forward optimization
  • Test on out-of-sample data
  • Keep parameters simple and logical
  • Avoid curve-fitting

3. Ignoring Slippage and Commissions

Problem: Backtest shows profit but live trading loses money.

Solution:

  • Always include realistic slippage (0.1-0.2%)
  • Add broker commissions (0.03-0.05% per trade)
  • Account for STT and GST (Indian markets)
  • Test with conservative assumptions

4. Not Adapting to Volatility

Problem: Fixed stops get hit too often in volatile markets.

Solution:

  • Use ATR-based stops (already implemented)
  • Adjust position size based on volatility
  • Consider volatility-adjusted position sizing

Next Steps

1. Add Advanced Filters

Enhance the strategy with:

2. Optimize Parameters

Use walk-forward optimization:

  • Test different EMA periods (9/21, 12/26, 20/50)
  • Experiment with ATR multipliers (1.5, 2.0, 2.5)
  • Try various partial exit levels

Learn more: Strategy Optimization

3. Deploy to Paper Trading

Test in real-time:

  • Run for 2-4 weeks minimum
  • Monitor signal quality
  • Track slippage and execution
  • Compare to backtest results

4. Go Live

When ready:

  • Start with 1 symbol
  • Use 50% of intended position size
  • Monitor closely for first week
  • Gradually scale up

Learn more: Paper to Live Transition

Summary

You've learned to build a sophisticated EMA crossover strategy with:

  • ✅ Multi-condition entry logic (EMA crossover + price filter + volume)
  • ✅ ATR-based adaptive stops
  • ✅ Partial exits for progressive profit-taking
  • ✅ Trailing stops to maximize gains
  • ✅ Risk-based position sizing
  • ✅ Comprehensive backtesting

Key Improvements Over Simple MA Crossover:

  • EMAs respond faster than SMAs
  • Price filter ensures trend alignment
  • Volume confirms genuine moves
  • ATR adapts to volatility
  • Partial exits optimize profit-taking
  • Trailing stops capture extended moves

This strategy works best in trending markets with clear directional moves. In ranging markets, consider adding filters or pausing the algorithm.

Ready for more advanced techniques? Try the RSI Divergence Strategy next!