资源加载中... loading...

ADX动态平均趋势指标策略

Author: ChaoZhang, Date: 2024-01-15 15:32:45
Tags:

ADX动态平均趋势指标策略

概述

ADX动态平均趋势指标策略是一种利用ADX指标判断市场趋势强弱以及趋势方向的量化交易策略。该策略通过计算平均方向指数(ADX)判断市场是否存在趋势,通过计算正向指标(DI+)和负向指标(DI-)判断趋势的方向,从而产生买入和卖出信号。

策略原理

该策略首先利用ADX指标判断市场是否存在趋势。ADX高于用户设定的关键值(默认为23),表示市场趋势较强。当ADX的当前值高于ADX之前n天的值时(n为用户设定的回看天数,默认为3天),表示ADX正在上涨,市场趋势正在形成。

然后策略利用DI+和DI-判断市场趋势的方向。当DI+高于DI-时,表示市场处于上涨趋势;当DI+低于DI-时,表示市场处于下跌趋势。

最后,策略综合判断ADX和DI的情况,产生具体的买入和卖出信号:

  1. 当ADX上涨,高于关键值,且DI+高于DI-,产生买入信号
  2. 当ADX上涨,高于关键值,且DI+低于DI-,产生卖出信号
  3. 当ADX转为下降,产生平仓信号

该策略还提供移动平均线过滤和定制回测时间范围等功能,可以按需配置。

优势分析

ADX动态平均趋势指标策略具有以下优势:

  1. 可以自动判断市场趋势存在与否,避免无效交易
  2. 可以自动判断市场趋势方向,进行趋势追踪
  3. 提供趋势存在时买入/趋势消失时平仓的清晰逻辑
  4. 可配置移动平均线进行过滤,避免假突破
  5. 可配置回测时间范围进行历史测试
  6. 指标和参数可调整,可以针对不同品种进行优化

风险分析

该策略也存在一些风险:

  1. ADX指标存在滞后,可能错过趋势早期机会
  2. 多空判断依赖DI指标,DI指标敏感,可能产生错误信号
  3. 移动平均线过滤可能错过短线机会
  4. 回测时间范围不当可能导致过拟合
  5. 指标参数设置不当可能影响策略效果

为了降低风险,可以考虑以下几点:

  1. 适当缩短ADX参数,减少滞后
  2. 调整或删除DI过滤,防止错误信号
  3. 适当缩短移动平均线周期
  4. 扩大回测时间范围,进行全样本测试
  5. 优化指标参数,寻找最佳设置

优化方向

该策略可以从以下几个方面进行优化:

  1. 结合多个股票进行组合测试,分散单一股票风险
  2. 增加止损逻辑以控制单笔损失
  3. 结合其他指标进行组合验证,提高信号准确率
  4. 引入机器学习算法判断买卖信号
  5. 增加自动参数优化模块,实现动态参数调整

总结

ADX动态平均趋势指标策略利用ADX判断趋势存在和DI判断趋势方向,在趋势存在时产生交易信号,策略思路清晰。该策略可以自动判断趋势,追踪趋势,在一定程度上规避非趋势市场的无效交易。通过一定的优化,该策略可以成为中长线量化交易的有力工具。


/*backtest
start: 2024-01-07 00:00:00
end: 2024-01-14 00:00:00
period: 10m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © millerrh with inspiration from @9e52f12edd034d28bdd5544e7ff92e 
//The intent behind this study is to look at ADX when it has an increasing slope and is above a user-defined key level (23 default). 
//This is to identify when it is trending.
//It then looks at the DMI levels.  If D+ is above D- and the ADX is sloping upwards and above the key level, it triggers a buy condition.  Opposite for short.
//Can use a user-defined moving average to filter long/short if desried.
// NOTE: THIS IS MEANT TO BE USED IN CONJUNCTION WITH MY "ATX TRIGGER" INDICATOR FOR VISUALIZATION. MAKE SURE SETTINGS ARE THE SAME FOR BOTH.

strategy("ADX | DMI Trend", overlay=true, initial_capital=10000, currency='USD', 
   default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.04)

// === BACKTEST RANGE ===
From_Year  = input(defval = 2019, title = "From Year")
From_Month = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
From_Day   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
To_Year    = input(defval = 9999, title = "To Year")
To_Month   = input(defval = 1, title = "To Month", minval = 1, maxval = 12)
To_Day     = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
Start  = timestamp(From_Year, From_Month, From_Day, 00, 00)  // backtest start window
Finish = timestamp(To_Year, To_Month, To_Day, 23, 59)        // backtest finish window

// == INPUTS ==
// ADX Info
adxlen = input(14, title="ADX Smoothing")
dilen = input(14, title="DI Period")
keyLevel = input(23, title="Keylevel for ADX")
adxLookback = input(3, title="Lookback Period for Slope")

// == FILTERING ==
// Inputs
useMaFilter = input(title = "Use MA for Filtering?", type = input.bool, defval = true)
maType = input(defval="EMA", options=["EMA", "SMA"], title = "MA Type For Filtering")
maLength   = input(defval = 200, title = "MA Period for Filtering", minval = 1)

// Declare function to be able to swap out EMA/SMA
ma(maType, src, length) =>
    maType == "EMA" ? ema(src, length) : sma(src, length) //Ternary Operator (if maType equals EMA, then do ema calc, else do sma calc)
maFilter = ma(maType, close, maLength)
plot(maFilter, title = "Trend Filter MA", color = color.green, linewidth = 3, style = plot.style_line, transp = 50)

// Check to see if the useMaFilter check box is checked, this then inputs this conditional "maFilterCheck" variable into the strategy entry 
maFilterCheck = if useMaFilter == true
    maFilter
else
    close

// == USE BUILT-IN DMI FUNCTION TO DETERMINE ADX AND BULL/BEAR STRENGTH
[diplus, diminus, adx] = dmi(dilen, adxlen)

buySignal = (adx[0]-adx[adxLookback] > 0) and adx > keyLevel and diplus > diminus  and close >= maFilterCheck
// buySignalValue = valuewhen(buySignal, close, 0)
shortSignal = (adx[0]-adx[adxLookback] > 0) and adx > keyLevel and diplus < diminus  and close <= maFilterCheck
// shortSignalValue = valuewhen(shortSignal, close, 0)
sellCoverSignal = adx[0]-adx[adxLookback] < 0

// == ENTRY & EXIT CRITERIA
// Triggers to be TRUE for it to fire of the BUY Signal : (opposite for the SELL signal).
// (1): Price is over the 200 EMA line. (EMA level configurable by the user)
// (2): "D+" is OVER the "D-" line
// (3): RSI 7 is under 30 (for SELL, RSI 7 is over 70)
// 1* = The ultimate is to have a combination line of 3 EMA values, EMA 14, EMA 50 and EMA 200 - And if price is over this "combo" line, then it's a strong signal

// == STRATEGY ENTRIES/EXITS == 
strategy.entry("Long", strategy.long, when = buySignal)
strategy.close("Long", when = sellCoverSignal)
strategy.entry("Short", strategy.short, when = shortSignal)
strategy.close("Short", when = sellCoverSignal)
    
// == ALERTS == 
// alertcondition(buySignal, title='ADX Trigger Buy', message='ADX Trigger Buy')
// alertcondition(sellSignal, title='ADX Trigger Sell', message='ADX Trigger Sell')

更多内容