MACD均线交叉趋势追踪止损策略


创建日期: 2023-11-06 11:56:14 最后修改: 2023-11-06 11:56:14
复制: 0 点击次数: 623
avatar of ChaoZhang ChaoZhang
1
关注
1617
关注者

MACD均线交叉趋势追踪止损策略

概述

该策略运用MACD指标判断趋势方向,结合EMA均线和SMA均线交叉作为辅助判断。入场信号为MACD直线上穿信号线且趋势向上,止损为价格跌破由ATR计算的浮动止损线。策略还设置了分批出场,首先平掉一部分头寸获利了结,其次在价格达到较大涨幅时再平仓一部分确保大额利润,最后将部分头寸追踪持有直到止损。

原理

入场信号

当快线EMA上穿慢线EMA时,表示短期价格变化趋势好于长期趋势,判断为买入信号。同时,快速SMA上穿慢速SMA也表明短期价格上涨势头好于长期。因此结合MACD直线上穿信号线和趋势向上的EMA&SMA交叉信号,可以确定较强的入场时机。

止损方式

采用ATR来计算止损位。ATR可以有效反映价格的波动范围。当价格跌破该波动范围则退出止损。ATR的周期可以调节,周期调小可以使止损更精确但也更容易被突破,周期调大止损位会更宽但不易被突破。同时,止损位随着价格上涨而向上漂移,实现趋势跟踪。

出场方式

分批出场,首先在小幅上涨后就平掉一部分头寸回笼资金。然后在价格大幅上涨时再平一部分头寸获利。最后将部分头寸追踪持有直到止损位触发止损。这样可以锁定部分利润且持有一定时间获利。

优势

  • 利用MACD判断趋势方向,再辅以EMA和SMA的交叉信号,可以较准确判断入场时机
  • ATR计算的止损位既可实现止损又可跟踪趋势
  • 分批出场,可以回笼资金、锁定利润且持有一段时间

风险及对策

  • MACD和趋势指标发出错误信号的风险。可以适当调整参数,或增加其他指标进行辅助判断。
  • ATR止损被突破的风险。可以适当扩大ATR周期或增加止损系数。
  • 部分头寸追踪时被套牢的风险。可以缩小追踪头寸比例,及时止损。

优化方向

-优化MACD参数,使其对趋势的判断更准确

  • 优化ATR周期参数,使止损更合适

  • 优化出场比例和头寸控制,减少被套风险

  • 增加移动止盈或考虑波动率指标优化止损

总结

该策略综合运用MACD、EMA/SMA等多种指标判断趋势方向,以求取准确的入场时机。同时采用浮动的ATR止损来锁定利润且跟踪趋势达到更好的效果。出场设置分批平仓,可以回笼资金、确保利润且持有一段时间。总体来说,该策略稳定性较好,可以获得不错的效果。但仍需对指标参数及出场方式进行优化,以求取更佳回报。

策略源码
/*backtest
start: 2022-10-30 00:00:00
end: 2023-11-05 00:00:00
period: 1d
basePeriod: 1h
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/
// © Deobald

//@version=4
strategy("MACD Strategy", overlay=true)

// FUNCTIONS

Ema(src,p) =>
    ema = 0.
    sf = 2/(p+1)
    ema := nz(ema[1] + sf*(src - ema[1]),src)

Sma(src,p) => a = cum(src), (a - a[max(p,0)])/max(p,0)

Atr(p) =>
    atr = 0.
    Tr = max(high - low, max(abs(high - close[1]), abs(low - close[1])))
    atr := nz(atr[1] + (Tr - atr[1])/p,Tr)

/// TREND
ribbon_period = input(34, "Period", step=1)

leadLine1 = ema(close, ribbon_period)
leadLine2 = sma(close, ribbon_period)

p3 = plot(leadLine1, color= #53b987, title="EMA", transp = 50, linewidth = 1)
p4 = plot(leadLine2, color= #eb4d5c, title="SMA", transp = 50, linewidth = 1)
fill(p3, p4, transp = 60, color = leadLine1 > leadLine2 ? #53b987 : #eb4d5c)


// MACD
fast_length = input(title="Fast Length", type=input.integer, defval=3)
slow_length = input(title="Slow Length", type=input.integer, defval=5)
src = input(title="Source", type=input.source, defval=close)
signal_length = input(title="Signal Smoothing", type=input.integer, minval = 1, maxval = 50, defval = 2)
sma_source = input(title="Simple MA(Oscillator)", type=input.bool, defval=false)
sma_signal = input(title="Simple MA(Signal Line)", type=input.bool, defval=true)

// Plot colors
col_grow_above = #26A69A
col_grow_below = #FFCDD2
col_fall_above = #B2DFDB
col_fall_below = #EF5350
col_macd = #0094ff
col_signal = #ff6a00

// Calculating
fast_ma = sma_source ? Sma(src, fast_length) : Ema(src, fast_length)
slow_ma = sma_source ? Sma(src, slow_length) : Ema(src, slow_length)
macd = fast_ma - slow_ma
signal = sma_signal ? Sma(macd, signal_length) : Ema(macd, signal_length)
hist = macd - signal

//plot(hist, title="Histogram", style=plot.style_columns, color=(hist>=0 ? (hist[1] < hist ? col_grow_above : col_fall_above) : (hist[1] < hist ? col_grow_below : col_fall_below) ), transp=0 )
// plot(macd, title="MACD", color=col_macd, transp=0)
// plot(signal, title="Signal", color=col_signal, transp=0)



// TAKE PROFIT AND STOP LOSS
long_tp1_inp = input(1, title='Long Take Profit 1 %', step=0.1)/100
long_tp1_qty = input(10, title="Long Take Profit 1 Qty", step=1)

long_tp2_inp = input(5, title='Long Take Profit 2%', step=0.1)/100
long_tp2_qty = input(50, title="Long Take Profit 2 Qty", step=1)

long_take_level_1 = strategy.position_avg_price * (1 + long_tp1_inp)
long_take_level_2 = strategy.position_avg_price * (1 + long_tp2_inp)




// Stop Loss
multiplier = input(2.2, "SL Mutiplier", minval=1, step=0.1)
ATR_period=input(17,"ATR period", minval=1, step=1)

// Strategy
entry_long=crossover(macd,signal) and leadLine2 < leadLine1
entry_price_long=valuewhen(entry_long,close,0)
SL_floating_long = entry_price_long - multiplier*Atr(ATR_period)
exit_long= close < SL_floating_long 

///// BACKTEST PERIOD ///////
testStartYear = input(2018, "Backtest Start Year")
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear, testStartMonth, testStartDay, 0, 0)

testStopYear = input(2020, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear, testStopMonth, testStopDay, 0, 0)

testPeriod() => true

if testPeriod()
    strategy.entry("long", strategy.long, comment="Long", when=entry_long)
    strategy.exit("TP1","long", qty_percent=long_tp1_qty, limit=long_take_level_1)//, trail_points=entry_price_long * long_trailing / syminfo.mintick, trail_offset=entry_price_long * long_trailing / syminfo.mintick)
    strategy.exit("TP2", qty_percent=long_tp2_qty, limit=long_take_level_2) //, trail_points=entry_price_long * long_trailing / syminfo.mintick, trail_offset=entry_price_long * long_trailing / syminfo.mintick)
    strategy.close_all("long", when=exit_long, comment="exit long" )


// LONG POSITION
plot(strategy.position_size > 0 ? long_take_level_1 : na, style=plot.style_linebr, color=color.green, linewidth=1, title="1st Long Take Profit")
plot(strategy.position_size > 0 ? long_take_level_2 : na, style=plot.style_linebr, color=color.green, linewidth=1, title="2nd Long Take Profit")
plot(strategy.position_size > 0 ? SL_floating_long : na, style=plot.style_linebr, color=color.red, linewidth=1, title="Long Stop Loss")