Donchian渠道趋势跟踪策略

Author: ChaoZhang, Date: 2024-01-22 12:30:05
Tags:

Donchian渠道趋势跟踪策略

概述

Donchian渠道趋势跟踪策略是一种基于Donchian通道指标的趋势跟踪策略。它使用不同长度的Donchian通道来识别价格趋势,并在价格突破通道时产生交易信号。

该策略的主要思想是使用长周期的Donchian通道判断大趋势方向,使用短周期的Donchian通道作为入场和止损的信号。它旨在捕捉中长线的价格趋势,避免被市场中的短期波动所迷惑。

策略原理

  1. 计算长周期(如50日)的最高收盘价和最低收盘价构建Donchian通道。当价格突破通道上轨时看多,突破下轨时看空。这是判断大趋势的基础。

  2. 计算短周期(如20日)的最高收盘价和最低收闭作为入场和止损的标准。当价格突破长线通道时,如果收盘价也突破短线通道,则入场做多/空。

  3. 当持有多头头寸时,如果价格跌破短线下轨则止损。当持有空头头寸时,如果价格突破短线上轨则止损。

  4. 止损点设置为N倍ATR。这可以根据市场波动性来自动调整,有利于减少止损被激活的可能性。

  5. 可以选择在交易结束前平仓,或一直持仓直到止损。这可以通过一个输入参数来控制。

该策略同时考虑了趋势判断和利润止损,既可以捕捉价格趋势又可以控制风险,适合中长线操作。

优势分析

  1. 有效识别中长线趋势,避免被短期市场噪音干扰。

  2. 自动止损机制可以限制单笔损失。

  3. ATR止损可以根据市场波动性调整止损距离,降低止损被冲击的可能性。

  4. 可选择在没法交易时自动平仓,管理交易风险。

  5. 策略逻辑简单清晰易于理解。

风险分析

  1. 在无明确趋势的市场中,策略会产生较多交易,这会增加交易成本和实现损失的可能。

  2. 虽然有止损机制,但在异常行情下,价格gaps可能直接跌破止损点造成重大损失。

  3. ATR计算仅基于历史数据,无法准确预测未来走势和波动性,实际止损距离可能过大或过小。

  4. 在实盘中,止损单无法百分百确保得到执行。极端行情下可能被跳过造成损失。

优化方向

  1. 调整Donchian通道参数,优化识别趋势的效果。

  2. 结合其他指标确认交易信号,如MACD,KDJ等,提升策略稳定性。

  3. 增加移动止损,让止损点随价格一起移动,进一步限制损失。

  4. 测试不同持仓时间对总体效果的影响,确定最佳持仓周期。

  5. 考虑动态调整仓位规模,在趋势行情中加大仓位。

总结

Donchian渠道趋势跟踪策略整合了趋势判断与风险控制,通过趋势识别获取 excess return,同时止损机制控制尾部风险。该策略适用于识别和捕捉中长线价格趋势,在参数优化和机制补充后可以获得稳定的正向收益。


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

//@version=5
strategy(title="Donchian", overlay=true, calc_on_every_tick=true)

// =============================================================================
// VARIABLES
// =============================================================================

donch_string = input.string(title="Lenght", options = ['20/10','50/20', '50/50', '20/20', '100/100'], defval='20/10')
permit_long  = input.bool(title = 'Permit long', defval = true)
permit_short  = input.bool(title = 'Permit short', defval = true)
risk_percent = input.float(title="Position Risk %", defval=0.5, step=0.25)
stopOffset = input.float(title="ATR mult", defval=2.0, step=0.5)
atrLen = input.int(title="ATR Length", defval=20)
close_in_end  = input.bool(title = 'Close in end', defval = true)
permit_stop  = input.bool(title = 'Permit stop', defval = true)


// =============================================================================
// CALCULATIONS
// =============================================================================

donch_len_big = 
 donch_string == '50/20' ? 50 : 
 donch_string == '50/50' ? 50 : 
 donch_string == '20/20' ? 20 : 
 donch_string == '20/10' ? 20 : 
 donch_string == '100/100' ? 100 : 
 na
donch_len_small = 
 donch_string == '50/20' ? 20 : 
 donch_string == '50/50' ? 50 : 
 donch_string == '20/20' ? 20 : 
 donch_string == '20/10' ? 10 : 
 donch_string == '100/100' ? 100 : 
 na

big_maxclose = ta.highest(close, donch_len_big)
big_minclose = ta.lowest(close, donch_len_big)

small_maxclose = ta.highest(close, donch_len_small)
small_minclose = ta.lowest(close, donch_len_small)

atrValue = ta.atr(atrLen)[1]

tradeWindow  = true

// =============================================================================
// NOTOPEN QTY
// =============================================================================

risk_usd     = (risk_percent / 100) * strategy.equity
atr_currency = (atrValue * syminfo.pointvalue)
notopen_qty  = risk_usd / (stopOffset * atr_currency)

// =============================================================================
// LONG STOP
// =============================================================================

long_stop_price = 0.0
long_stop_price := 
 strategy.position_size > 0 and na(long_stop_price[1]) ? strategy.position_avg_price - stopOffset * atrValue : 
 strategy.position_size > 0 and strategy.openprofit > risk_usd ? strategy.position_avg_price:
 strategy.position_size > 0 ? long_stop_price[1] : 
 na

// =============================================================================
// SHORT STOP
// =============================================================================

short_stop_price = 0.0
short_stop_price := 
 strategy.position_size < 0 and na(short_stop_price[1]) ? strategy.position_avg_price + stopOffset * atrValue : 
 strategy.position_size < 0 and strategy.openprofit > risk_usd ? strategy.position_avg_price :
 strategy.position_size < 0 ? short_stop_price[1] : 
 na

// =============================================================================
// PLOT BG VERTICAL COLOR
// =============================================================================

cross_up = strategy.position_size <= 0 and close == big_maxclose and close >= syminfo.mintick and tradeWindow and permit_long
cross_dn =  strategy.position_size >= 0 and close == big_minclose and close >= syminfo.mintick and tradeWindow and permit_short
bg_color = cross_up ? color.green : cross_dn ? color.red : na
bg_color := color.new(bg_color, 70)
bgcolor(bg_color)

// =============================================================================
// PLOT HORIZONTAL LINES
// =============================================================================

s1 = cross_up ? na : cross_dn ? na : strategy.position_size != 0 ? strategy.position_avg_price : na
s2 = cross_up ? na : cross_dn ? na : strategy.position_size > 0 ? small_minclose : strategy.position_size < 0 ? small_maxclose : na
s3 = cross_up ? na : cross_dn ? na : not permit_stop ? na : 
 strategy.position_size > 0 ? long_stop_price : strategy.position_size < 0 ? short_stop_price : na

plot(series=big_maxclose, style=plot.style_linebr, color=color.black, linewidth=1, title="Donch Big Maxclose Black")
plot(series=big_minclose, style=plot.style_linebr, color=color.black, linewidth=1, title="Donch Big Minclose Black")

plot(series=s1, style=plot.style_linebr, color=color.yellow, linewidth=2, title="Entry Yellow")
plot(series=s2, style=plot.style_linebr, color=color.red, linewidth=1, title="Donch Small Red")
plot(series=s3, style=plot.style_linebr, color=color.fuchsia, linewidth=2, title="Stop Fuchsia")

// =============================================================================
// ENTRY ORDERS
// =============================================================================

if strategy.position_size <= 0 and close == big_maxclose and close >= syminfo.mintick and tradeWindow and permit_long
    strategy.entry("Long", strategy.long, qty=notopen_qty)

if (strategy.position_size >= 0) and close == big_minclose and close >= syminfo.mintick and tradeWindow and permit_short
    strategy.entry("Short", strategy.short, qty=notopen_qty)

// =============================================================================
// EXIT ORDERS
// =============================================================================

if strategy.position_size > 0 and permit_stop
    strategy.exit(id="Stop", from_entry="Long", stop=long_stop_price)

if strategy.position_size < 0 and permit_stop
    strategy.exit(id="Stop", from_entry="Short", stop=short_stop_price)

// ==========

if strategy.position_size > 0 and close == small_minclose and not barstate.islast
    strategy.close(id="Long", comment='Donch')

if strategy.position_size < 0 and close == small_maxclose and not barstate.islast
    strategy.close(id="Short", comment='Donch')

// ==========

if close_in_end
    if not tradeWindow
        strategy.close_all(comment='In end')

// =============================================================================
// END
// =============================================================================

更多内容