Strategy vault / Trend following
Adaptive Trading Strategy Based on Multiple EMA Crossovers
This strategy implements adaptive long/short trading using multiple sets of EMA indicators. It adopts EMAs with different parameters for entry and exit based on market long-term and short-term trends. The strategy…
Overview
This strategy implements adaptive long/short trading using multiple sets of EMA indicators. It adopts EMAs with different parameters for entry and exit based on market long-term and short-term trends. The strategy automatically recognizes bull/bear market and uses independent stop loss to control risk.
Strategy Logic
The strategy mainly utilizes the crossover principle of EMA indicators. Long when fast EMA crosses above slow EMA, and short when crossing below. It sets up multiple EMAs and chooses different parameters based on market trends. Specifically, when judging long-term trend is bullish, a set of longer period EMAs are used for long signal; when bearish, another set of shorter period EMAs are used for short. Exits also adopt different period EMAs. Stop loss uses fixed percentage trailing stop based on position direction.
Advantage Analysis
- Multiple adaptive EMA sets work flexibly across different markets.
- Distinguishing bull and bear makes signals clearer.
- Independent entry/exit parameters enables precise positioning.
- Fixed percentage stop loss effectively controls risk.
- Strategy logic is intuitive and easy to understand and implement.
Risks and Improvements
- EMAs can generate false signals, parameter tuning is key.
- Fixed stop loss may fail to track large fluctuations.
- Should add filters like volume to enhance robustness.
- Parameters can be auto optimized with machine learning algorithms.
- Consider using dynamic stop loss like ATR instead of fixed.
Summary
The strategy achieves adaptive effect leveraging multiple EMA crossovers, keeping EMA's advantages and making the strategy more flexible. With proper filters and dynamic stops added, it can become a highly practical automated trading system.
Parameters
| Name | Default | What it controls |
|---|---|---|
| v_input_1 | true | Start Date |
| v_input_2 | true | Start Month |
| v_input_3 | 2020 | Start Year |
| v_input_4 | true | End Date |
| v_input_5 | 12 | End Month |
| v_input_6 | 2021 | End Year |
| v_input_7 | 11 | Long Open - Fast |
| v_input_8 | 33 | Long Open - Slow |
| v_input_9 | 3 | Long Close - Fast |
| v_input_10 | 40 | Long Close - Slow |
| v_input_11 | 5 | Short Open - Fast |
| v_input_12 | 11 | Short Open - Slow |
| v_input_13 | 4 | Short Close - Fast |
| v_input_14 | 7 | Short Close - Slow |
| v_input_15 | 1.7 | Long Stop Loss (%) |
| v_input_16 | 0.4 | Short Stop Loss (%) |
| v_input_17 | 144 | Long-term trend - Longs |
| v_input_18 | 89 | Long-term trend - Shorts |
Source Pine Script
/*backtest
start: 2023-08-26 00:00:00
end: 2023-09-07 00:00:00
period: 12h
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/
// © str1nger
//@version=4
// strategy(title="BTC - 4hr - Long/Short", shorttitle="BTC - 4hr - Long/Short", overlay=true, initial_capital=1000, default_qty_type=strategy.percent_of_equity, default_qty_value=75,commission_type=strategy.commission.percent, commission_value=0.075)//////<---Uses a percentage of starting equity
//DATE RANGE//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
startDate = input(title="Start Date", type=input.integer,
defval=1, minval=1, maxval=31)
startMonth = input(title="Start Month", type=input.integer,
defval=1, minval=1, maxval=12)
startYear = input(title="Start Year", type=input.integer,
defval=2020, minval=2000, maxval=2100)
endDate = input(title="End Date", type=input.integer,
defval=1, minval=1, maxval=31)
endMonth = input(title="End Month", type=input.integer,
defval=12, minval=1, maxval=12)
endYear = input(title="End Year", type=input.integer,
defval=2021, minval=2000, maxval=2100)
inDateRange = true
//EMAs//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LONG
//11,33,3,40
lof= input(11, title="Long Open - Fast", step=1)
los= input(33, title="Long Open - Slow", step=1)
lcf= input(3, title="Long Close - Fast", step=1)
lcs= input(40, title="Long Close - Slow", step=1)
ema_long_open_fast = ema(close, lof)
ema_long_open_slow = ema(close, los)
ema_long_close_fast= ema(close, lcf)
ema_long_close_slow = ema(close, lcs)
//SHORT
//5,11,4,7
sof= input(5, title="Short Open - Fast", step=1)
sos= input(11, title="Short Open - Slow", step=1)
scf= input(4, title="Short Close - Fast", step=1)
scs= input(7, title="Short Close - Slow", step=1)
ema_short_open_fast = ema(close, sof)
ema_short_open_slow = ema(close, sos)
ema_short_close_fast = ema(close, scf)
ema_short_close_slow = ema(close, scs)
//CONDITIONS///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LONG
openlong = crossover(ema_long_open_fast, ema_long_open_slow)
closelong = crossover(ema_long_close_slow, ema_long_close_fast)
//1.7%
long_loss_percent = input(title="Long Stop Loss (%)", type=input.float, minval=0.0, step=0.1, defval=1.7) * 0.01
long_stop_price = strategy.position_avg_price * (1 - long_loss_percent)
//SHORT
openshort = crossover(ema_short_open_slow, ema_short_open_fast)
closeshort = crossover(ema_short_close_fast, ema_short_close_slow)
//0.4%
short_loss_percent = input(title="Short Stop Loss (%)", type=input.float, minval=0.0, step=0.1, defval=0.4) * 0.01
short_stop_price = strategy.position_avg_price * (1 + short_loss_percent)
//PLOT EMAs////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LONG
plot(ema_long_open_fast, "Long EMA open lower", linewidth=1, color=color.green)
plot(ema_long_open_slow, "Long EMA close upper", linewidth=1, color=color.green)
plot(ema_long_close_fast, "Long close lower", linewidth=1, color=color.red)
plot(ema_long_close_slow, "Long close upper", linewidth=1, color=color.red)
//SHORT
plot(ema_short_open_fast, "Short open fast", linewidth=1, color=color.green)
plot(ema_short_open_slow, "Short open slow", linewidth=1, color=color.green)
plot(ema_short_close_fast, "Short close fast", linewidth=1, color=color.red)
plot(ema_short_close_slow, "Short close slow", linewidth=1, color=color.red)
//LONG-TERM TRENDS
//LONG 144
long_term_trend_longs= input(144, title="Long-term trend - Longs", step=1)
lttl= ema(close, long_term_trend_longs)
plot(lttl, "Long-term trend - Longs", linewidth=2, color=color.blue)
//SHORT 89
long_term_trend_shorts= input(89, title="Long-term trend - Shorts", step=1)
ltts = ema(close, long_term_trend_shorts)
plot(ltts, "Long-term trend - Shorts", linewidth=2, color=color.blue)
//STRATEGY//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//LONG
if (inDateRange and openlong and (close > lttl))
strategy.entry("OL", long=true, comment="##insert open long comment here##")
if (inDateRange and closelong)
strategy.close("OL", comment="##insert close long comment here##")
if strategy.position_size > 0
strategy.exit("L-SL", stop=long_stop_price, comment="##insert long stop-loss comment here##")
//SHORT
if (inDateRange and openshort and (close < ltts))
strategy.entry("OS", long=false, comment="##insert open short comment here##")
if (inDateRange and closeshort)
strategy.close("OS", comment="##insert close short comment here##")
if strategy.position_size < 0
strategy.exit("S-SL", stop=short_stop_price, comment="##inster short stop-loss comment here##")
Published by ChaoZhang on the FMZ strategy square · last modified 2023-09-26. 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.
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Adaptive-Trading-Strategy-Based-on-Multiple-EMA-Crossovers.md- npx agenkit install engineering-kit in your project
- Paste the command into your agent and approve each phase
- 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
- ATR Dynamic Trend Following and EMA Crossover Trading StrategyPine Script · Trend following · 1d
- ATR and Moving Average Crossover Hybrid StrategyPine Script · Trend following · 1h
- ATR and T3 Moving Average StrategyPine Script · Trend following · 5m
- Adaptive ATR and RSI Trend Following Strategy with Trailing Stop LossPine Script · Trend following · 1h
- Bollinger Bands and RSI Trend Following StrategyPine Script · Trend following · 1h
- Dual ATR Channel Trend Following StrategyPine Script · Trend following · 15m