0bps

Strategy vault / Trend following

EMA Crossover Trading Strategy

The EMA Crossover trading strategy generates buy and sell signals by calculating EMA lines of different periods and detecting their crossover situations. When the faster EMA crosses above the slower EMA, a buy signal…

Author
ChaoZhang
Complexity
Starter · 77 lines
Parameters
5
Backtest bar
1h · intraday
Tested on
BTC/USDT · futures

IMG

Overview

The EMA Crossover trading strategy generates buy and sell signals by calculating EMA lines of different periods and detecting their crossover situations. When the faster EMA crosses above the slower EMA, a buy signal is generated. When the faster EMA crosses below the slower EMA, a sell signal is generated.

Strategy Logic

The core of this strategy is to compute two EMA lines with different periods, including a faster EMA with a default period of 9, and a slower EMA with a default period of 20. The code calculates these two lines by calling the built-in ema function in Pine Script. It then generates trading signals by detecting if the two EMA lines cross. Specifically, if the faster EMA crosses above the slower EMA, a buy signal is triggered. If the faster EMA crosses below the slower EMA, a sell signal is triggered.

The crossover situations are detected using the crossover and crossunder built-in functions in Pine Script. The crossover function checks if the faster EMA crosses above the slower EMA and returns a boolean value. The crossunder function checks if the faster EMA crosses below the slower EMA and returns a boolean value. Based on the return values of these two functions, the code submits corresponding buy or sell orders.

In addition, the code provides some auxiliary conditions such as setting start/end dates, restricting only long or short trades, etc. These features help conduct more sophisticated backtests or optimizations.

Advantage Analysis

The biggest advantage of this strategy is that it is very simple and straightforward, easy to understand and implement, making it suitable for beginners to learn. Also, as a trend following indicator, moving averages can effectively track market trends and generate additional profits by exploiting the momentum. Lastly, this strategy has few parameters, which makes it easy to tune and optimize.

Risk Analysis

The main risks this strategy faces are whipsaw trades and trend reversals. EMA lines are susceptible to short-term market fluctuations, which may generate false signals and trigger unnecessary trades, increasing trading frequency and costs. On the other hand, when crossover signals trigger, the trend may be nearing its reversal point, making trades riskier. Inappropriate parameter settings can also impact strategy performance.

Methods like adjusting EMA periods, adding filters can help reduce whipsaws. Stop loss orders control single trade loss. Parameter optimization improves robustness. However, no trading strategies can completely avoid losses, so one must be ready to take on risks.

Optimization Opportunities

This strategy can be improved in the following aspects:

  1. Optimize EMA periods to find best parameter sets
  2. Add indicators like MACD, RSI as filters to reduce false signals
  3. Incorporate trend metrics to avoid trend reversals
  4. Select stocks based on fundamentals
  5. Adjust position sizing, set stops based on ATR

Conclusion

The EMA crossover is a simple yet effective trend following strategy. It uses EMA crosses to generate trading signals, automatically capturing price trends. This easy to understand and adjustable strategy is perfect for beginners to learn. It can also be integrated into more complex strategies. However, all strategies bear risks and need prudent management. Continued enhancements in terms of optimization and enriching market conditions can make this strategy more robust.

Parameters

NameDefaultWhat it controls
v_input_19Fast EMA
v_input_220Slow EMA
v_input_30Trade Direction: Both | Short | Long
v_input_4timestamp(01 Jan 1970 00:00)Start Date
v_input_5timestamp(31 Dec 2170 23:59)End Date

Source Pine Script

/*backtest
start: 2024-01-01 00:00:00
end: 2024-01-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// This strategy has been created for illustration purposes only and should not be relied upon as a basis for buying, selling, or holding any asset or security.
// © kirilov

//@version=4
strategy(
     "EMA Cross Strategy",
     overlay=true,
     calc_on_every_tick=true,
     currency=currency.USD
     )

// INPUT:

// Options to enter fast and slow Exponential Moving Average (EMA) values
emaFast = input(title="Fast EMA", type=input.integer, defval=9, minval=1, maxval=9999)
emaSlow = input(title="Slow EMA", type=input.integer, defval=20, minval=1, maxval=9999)

// Option to select trade directions
tradeDirection = input(title="Trade Direction", options=["Long", "Short", "Both"], defval="Both")

// Options that configure the backtest date range
startDate = input(title="Start Date", type=input.time, defval=timestamp("01 Jan 1970 00:00"))
endDate = input(title="End Date", type=input.time, defval=timestamp("31 Dec 2170 23:59"))


// CALCULATIONS:

// Use the built-in function to calculate two EMA lines
fastEMA = ema(close, emaFast)
slowEMA = ema(close, emaSlow)


// PLOT:

// Draw the EMA lines on the chart
plot(series=fastEMA, color=color.black, linewidth=2)
plot(series=slowEMA, color=color.red, linewidth=2)


// CONDITIONS:

// Check if the close time of the current bar falls inside the date range
inDateRange = true

// Translate input into trading conditions
longOK  = (tradeDirection == "Long") or (tradeDirection == "Both")
shortOK = (tradeDirection == "Short") or (tradeDirection == "Both")

// Decide if we should go long or short using the built-in functions
longCondition = crossover(fastEMA, slowEMA)
shortCondition = crossunder(fastEMA, slowEMA)


// ORDERS:

// Submit entry (or reverse) orders
if (longCondition and inDateRange)
    strategy.entry(id="long", long=true, when = longOK)
if (shortCondition and inDateRange)
    strategy.entry(id="short", long=false, when = shortOK)
    
// Submit exit orders in the cases where we trade only long or only short
if (strategy.position_size > 0 and shortCondition)
    strategy.exit(id="exit long", stop=close)
if (strategy.position_size < 0 and longCondition)
    strategy.exit(id="exit short", stop=close)

Published by ChaoZhang on the FMZ strategy square · last modified 2024-02-22. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.

Build this with AgenKit

A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.

in Claude Code, Cursor, Codex & 4 more
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/EMA-Crossover-Trading-Strategy.md
  1. npx agenkit install engineering-kit in your project
  2. Paste the command into your agent and approve each phase
  3. Get tests, backtest, risk controls and a paper-trading switch

Understand it first

Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.

Related specs

esc

Try , , or .

↑↓ move↵ open