0bps

Strategy vault / Trend following

MACD Trend Following Trading Strategy Based on MACD Indicator

This strategy identifies trend direction based on MACD indicator and makes specific buy and sell decisions using Stoch indicator. It adopts long cycle MACD to determine major trend and short cycle Stoch for entries…

Author
ChaoZhang
Complexity
Intermediate · 126 lines
Parameters
26
Backtest bar
10m · intraday
Tested on
BTC/USDT · futures

Overview

This strategy identifies trend direction based on MACD indicator and makes specific buy and sell decisions using Stoch indicator. It adopts long cycle MACD to determine major trend and short cycle Stoch for entries and exits.

Strategy Logic

  1. Judging major trend direction using MACD indicator

    • Calculating fast EMA, slow EMA and MACD histogram

    • Comparing MACD movements in different cycles to determine trend

  2. Identifying specific buy and sell points using Stoch indicator

    • Calculating %K line and %D line

    • Divergence near overbought or oversold zone, with Stoch bouncing back as trading signals

  3. Making buy and sell decisions based on trend direction and Stoch signals

    • Go long when major cycle MACD rises and Stoch buy signal appears

    • Go short when major cycle MACD falls and Stoch sell signal appears

  4. Setting stop loss and take profit to optimize risk management

Advantage Analysis

  • Combining trend following and overbought-oversold indicator helps capture mid-to-long term trends effectively

  • MACD determines major direction while Stoch works out trading details, which reduces risks

  • Making full use of indicator combinations to form systematic strategies

  • Setting stop loss and take profit controls trading risks

  • Optimizable parameters adapt to different market conditions

Risk Analysis

  • Inaccurate mid-to-long term trend judgment may lead to contrarian trading losses

  • False signals from Stoch cause insufficient profit or losses

  • Stop loss point may be broken when trend changes, expanding losses

  • Improper profit target levels affect strategy performance

  • Ineffective parameters and failure to adapt to changing environment can invalidate the strategy

  • Risks can be reduced by optimizing trend judgment, verifying Stoch signals, adjusting stop loss and take profit, etc.

Optimization Directions

  • Optimize MACD parameter mix to improve trend judgment accuracy

  • Consider multi-cycle Stoch to avoid false signals

  • Dynamically adjust stop loss and take profit ratios to adapt market volatility

  • Add other indicator signals to verify and improve validity

  • Optimize parameters based on different products' characteristics and trading sessions

  • Introduce machine learning models to assist trend direction judgment

  • Incorporate volume indicators to avoid insufficient chasing or excessive follow

Conclusion

This strategy integrates the strengths of MACD and Stoch indicators to capture mid-to-long term trends while controlling risks. It can be effective in various market conditions by optimizing parameters, setting stop loss and take profit, verifying signals, etc. There is still room for improvement by further parameter tuning, improving signal accuracy, and incorporating machine learning. The strategy can be more comprehensive and intelligent.

Parameters

NameDefaultWhat it controls
v_input_13%D Smoothing
v_input_214%K Length
v_input_342%K2 Length
v_input_4126%K3 Length
v_input_5378%K4 Length
v_input_614%K5 Length
v_input_730%K6 Length
v_input_8true%K Smoothing
v_input_90.3buffer
v_input_10144Fast Length
v_input_11312Slow Length
v_input_12_close0Source: close | high | low | open | hl2 | hlc3 | hlcc4 | ohlc4
v_input_13108Signal Smoothing
v_input_140Oscillator MA Type: EMA | SMA
v_input_150Signal Line MA Type: EMA | SMA
v_input_1630MACDCHAStep Size
v_input_1720MACDCHAStep Size2
v_input_1810MACDCHAStep Size3
v_input_195MACDCHAStep Size4
v_input_203MACDCHAStep Size5
v_input_21trueMACDCHAStep Size6
v_input_2250histStep Size
v_input_234Long stop loss %
v_input_2410Go long and take profit %
v_input_254Short stop loss %
v_input_2610Short selling and take profit %

Source Pine Script

/*backtest
start: 2023-09-19 00:00:00
end: 2023-09-26 00:00:00
period: 10m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4

// strategy(title="Self-use strategyv0.2",calc_on_order_fills=false,calc_on_every_tick =false, initial_capital=10000,commission_type=strategy.commission.percent, commission_value=0.00,overlay = true,default_qty_type = strategy.cash, default_qty_value = 10000)



//STOCH
periodD = input(3, title="%D Smoothing", minval=1)
periodK = input(14, title="%K Length", minval=1)
periodK2 = input(42, title="%K2 Length", minval=1)
periodK3 = input(126, title="%K3 Length", minval=1)
periodK4 = input(378, title="%K4 Length", minval=1)
periodK5 = input(14, title="%K5 Length", minval=1)
periodK6 = input(30, title="%K6 Length", minval=1)
smoothK = input(1, title="%K Smoothing", minval=1)
k = sma(stoch(close, high, low, periodK), smoothK)
k2 = sma(stoch(close, high, low, periodK2), smoothK*3)
k3 = sma(stoch(close, high, low, periodK3), smoothK*3*3)
k4 = sma(stoch(close, high, low, periodK4), smoothK*3*3*3)
d = sma(k, periodD)
all = (k+k2*3+k3*9+k4*18)/31
allp = sma(all, periodK6)



buffer = input(title="buffer", type=input.float, defval=0.3, minval = 0, step = 0.1)
b1 = close[1]* (1+buffer/100)
b2 = close[1]* (1-buffer/100)

//MACD
fast_length = input(title="Fast Length", defval=144)
slow_length = input(title="Slow Length", defval=312)

src = input(title="Source", defval=close)
signal_length = input(title="Signal Smoothing",  minval = 1, maxval = 200, defval = 108)
sma_source = input(title="Oscillator MA Type",  defval="EMA", options=["SMA", "EMA"])
sma_signal = input(title="Signal Line MA Type", defval="EMA", options=["SMA", "EMA"])

// Calculating
fast_ma = sma_source == "SMA" ? sma(src, fast_length) : ema(src, fast_length)
slow_ma = sma_source == "SMA" ? sma(src, slow_length) : ema(src, slow_length)
macd = fast_ma - slow_ma
signal = sma_signal == "SMA" ? sma(macd, signal_length) : ema(macd, signal_length)
hist = macd - signal
MACDCHA = input(title="MACDCHAStep Size", defval=30)
MACDCHA2 = input(title="MACDCHAStep Size2", defval=20)
MACDCHA3 = input(title="MACDCHAStep Size3", defval=10)
MACDCHA4 = input(title="MACDCHAStep Size4", defval=5)
MACDCHA5 = input(title="MACDCHAStep Size5", defval=3)
MACDCHA6 = input(title="MACDCHAStep Size6", defval=1)
HISTCHA = input(title="histStep Size", defval=50)
macdcha = hist - hist[MACDCHA]
macdcha2 = hist - hist[MACDCHA2]
macdcha3 = hist - hist[MACDCHA3]
macdcha4 = hist - hist[MACDCHA4]
macdcha5 = hist - hist[MACDCHA5]
macdcha6 = hist - hist[MACDCHA6]
histcha = hist[HISTCHA]
var true2 = 0
var true2_1 = 0
var true2_2 = 0
var true2_3 = 0
var true2_4 = 0//Extension
var fangxiang =0
//Confirm direction
if(macdcha>=0 and macdcha2>=0 and macdcha3>=0 and macdcha4>=0 and macdcha5>=0 and macdcha6>=0)
    fangxiang := 1
    true2_2 := 0
if(macdcha<=0 and macdcha2<=0 and macdcha3<=0 and macdcha4<=0 and macdcha5<=0 and macdcha6<=0)
    fangxiang :=-1
    true2_1 := 1
//k3min = min(k3,k3[1],k3[2],k3[3],k3[4],k3[5],k3[6],k3[7],k3[8],k3[9],k3[10],k3[11],k3[12],k3[13],k3[14],k3[15],k3[16],k3[17],k3[18],k3[19],k3[20],k3[21],k3[22],k3[23],k3[24],k3[25],k3[26],k3[27],k3[28],k3[29],k3[30],k3[31],k3[32],k3[33],k3[34],k3[35],k3[36],k3[37],k3[38],k3[39],k3[40],k3[41],k3[42],k3[43],k3[44],k3[45],k3[46],k3[47],k3[48],k3[49],k3[50])
//k3max = max(k3,k3[1],k3[2],k3[3],k3[4],k3[5],k3[6],k3[7],k3[8],k3[9],k3[10],k3[11],k3[12],k3[13],k3[14],k3[15],k3[16],k3[17],k3[18],k3[19],k3[20],k3[21],k3[22],k3[23],k3[24],k3[25],k3[26],k3[27],k3[28],k3[29],k3[30],k3[31],k3[32],k3[33],k3[34],k3[35],k3[36],k3[37],k3[38],k3[39],k3[40],k3[41],k3[42],k3[43],k3[44],k3[45],k3[46],k3[47],k3[48],k3[49],k3[50])
allpmax = max(allp[1],allp[2],allp[3],allp[4],allp[5],allp[6])
allpmin = min(allp[1],allp[2],allp[3],allp[4],allp[5],allp[6])
if(histcha < 0 and macdcha>=0 and macdcha2>=0 and macdcha3>=0 and macdcha4>=0 and macdcha5>=0 and macdcha6>=0 and d < 20 and volume > volume[1] and true2_1 == 1 and allp>allp[1] and allp <80)//and k3max < 80  //and k3min < 30 and k3 >20 and k2<50
    strategy.entry("open long", true, comment = "open long") // and close > close[1] and cci1> MEA1
    true2_1 :=0
if(d >80)
    strategy.close( "open long", comment = "close long")
    true2_1 :=1

stop_loss=input(4, "Long stop loss %", minval = 1, step = 1)
sl = strategy.position_avg_price * (1-stop_loss/100)
close_Stop = close < sl
if(close_Stop or(allp<20 and allp[1]>20))
    strategy.close( "open long", comment = "Long stop loss")
    true2_1 :=1
Target_profit=input(10, "Go long and take profit %", minval = 1, step = 1)
tp = strategy.position_avg_price * (1+Target_profit/100)
close_Target = close > tp
strategy.close("open long", when = close_Target, comment ="Go long and make profit")


//Empty
if(histcha > 0 and macdcha<=0 and macdcha2<=0 and macdcha3<=0 and macdcha4<=0 and macdcha5<=0 and macdcha6<=0 and d > 80 and volume > volume[1] and true2_2 == 1 and allp<allp[1] and allp >20) // and k3max>70 and k3<80
    //strategy.entry("open short", comment = "open short") 
    strategy.entry("open short", strategy.short,comment ="open short")
    true2_2 := 0
if( d <20)
   // strategy.close(  comment = "close short")
    strategy.close("open short",  comment = "close short")
    true2_2 := 1

stop_loss2=input(4, "Short stop loss %", minval = 1, step = 1)
sl2 = strategy.position_avg_price * (1+stop_loss2/100)
close_Stop2 = close > sl2
if(close_Stop2 or(allp>80 and allp[1]<80))
    strategy.close( "open short", comment = "Short stop loss")
    true2_2 == 1
Target_profit2=input(10, "Short selling and take profit %", minval = 1, step = 1)
tp2 = strategy.position_avg_price * (1-Target_profit2/100)
close_Target2 = close < tp2
strategy.close("open short", when = close_Target2, comment ="Short selling profit")



Published by ChaoZhang on the FMZ strategy square · last modified 2023-09-27. 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/MACD-Trend-Following-Trading-Strategy-Based-on-MACD-Indicator.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