Esta estratégia usa o Índice Direcional Médio (DI +) e Índice Direcional Negativo (DI-) em dois prazos para determinar a direção da tendência para negociações longas e curtas. Quando o DI + é maior que o DI - em prazos maiores e menores, ele indica uma tendência ascendente e um sinal longo é acionado. Quando o DI - é maior que o DI + em ambos os prazos, ele indica uma tendência descendente e um sinal curto é acionado.
A estratégia baseia-se em vários princípios:
Calcule DI+ e DI-. Obtenha DI+ e DI- usando preços altos, próximos e baixos.
Comparar DI+ e DI- em dois intervalos de tempo. Calcular DI+ e DI- respectivamente no período de tempo principal do gráfico (por exemplo, 1 hora) e um período de tempo maior (por exemplo, diário). Comparar os valores entre os dois intervalos de tempo.
Determine a direção da tendência. Quando o DI+ é maior que o DI- em ambos os prazos maiores e menores, indica uma tendência ascendente. Quando o DI- é maior que o DI+ em ambos os prazos, indica uma tendência descendente.
DI+>DI- em ambos os quadros dá sinal longo.
Usar o ATR para calcular o stop loss dinâmico para seguir a tendência.
Condições de saída: saída quando o stop loss é atingido ou o preço reverte.
A estratégia apresenta as seguintes vantagens:
Usando o DI de duplo quadro de tempo, filtramos algumas falhas.
O ATR trailing stop maximiza a proteção dos lucros e evita que as paradas sejam muito apertadas.
O stop loss oportuno controla as perdas em operações individuais.
A negociação com a tendência permite a captação contínua de tendências.
Regras simples e claras, fáceis de implementar para negociação ao vivo.
Há também vários riscos:
O DI tem efeito de atraso, pode perder o tempo de entrada, pode otimizar parâmetros ou adicionar outros indicadores.
O duplo quadro de tempo pode ter divergência entre o TF maior e menor. Adicione mais validação de quadro de tempo.
Stop loss muito agressivo pode causar excesso de negociação.
A serralheira no mercado lateral pode causar trocas frequentes.
A otimização de parâmetros depende de dados históricos e pode ser sobreajustada.
A estratégia pode ser melhorada nos seguintes aspectos:
Otimizar os parâmetros de cálculo do DI para o melhor conjunto de parâmetros.
Adicionar outros filtros de indicadores para melhorar a precisão do sinal, por exemplo, MACD, KDJ, etc.
Melhorar a estratégia de stop loss para adaptar mais condições de mercado, tais como trailing stop ou ordens pendentes.
Adicione filtros de sessão de negociação para evitar eventos noticiosos significativos.
Teste a robustez dos parâmetros em diferentes produtos para melhorar a adaptabilidade.
Introduzir aprendizado de máquina para treinar modelos com dados históricos.
Em resumo, esta é uma estratégia típica de seguimento de tendências que usa DI para determinar a direção da tendência e definir stop loss para bloquear lucros ao longo da tendência. A vantagem reside em sua lógica clara e facilidade de implementação para negociação ao vivo.
/*backtest start: 2022-10-31 00:00:00 end: 2023-11-06 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/ // © DojiEmoji //@version=5 strategy("DI+/- multi TF Strat [KL]", overlay=true, pyramiding=1, initial_capital=1000000000, default_qty_type=strategy.percent_of_equity, default_qty_value=5) var string GROUP_ALERT = "Alerts" var string GROUP_SL = "Stop loss" var string GROUP_ORDER = "Order size" var string GROUP_TP = "Profit taking" var string GROUP_HORIZON = "Time horizon of backtests" var string GROUP_IND = "Directional IndicatorDI+ DI-" // ADX Indicator { adx_len = input(14, group=GROUP_IND, tooltip="Typically 14") tf1 = input.timeframe("", title="DI +/- in Timeframe 1", group=GROUP_IND, tooltip="Main: DI+ > DI-") tf2 = input.timeframe("1D", title="DI +/- in Timeframe 2", group=GROUP_IND, tooltip="Confirmation: DI+ > DI-") // adx_thres = input(20, group=GROUP_IND) //threshold not used in this strategy get_ADX(_high, _close, _low) => // (high, close, mid) -> [plus_DM, minus_DM] // Based on TradingView user BeikabuOyaji's implementation _tr = math.max(math.max(_high - _low, math.abs(_high - nz(_close[1]))), math.abs(_low - nz(_close[1]))) smooth_tr = 0.0 smooth_tr := nz(smooth_tr[1]) - nz(smooth_tr[1]) / adx_len + _tr smooth_directional_mov_plus = 0.0 smooth_directional_mov_plus := nz(smooth_directional_mov_plus[1]) - nz(smooth_directional_mov_plus[1]) / adx_len + (_high - nz(_high[1]) > nz(_low[1]) - _low ? math.max(_high - nz(_high[1]), 0) : 0) smooth_directional_mov_minus = 0.0 smooth_directional_mov_minus := nz(smooth_directional_mov_minus[1]) - nz(smooth_directional_mov_minus[1]) / adx_len + (nz(_low[1]) - _low > _high - nz(_high[1]) ? math.max(nz(_low[1]) - _low, 0) : 0) plus_DM = smooth_directional_mov_plus / smooth_tr * 100 minus_DM = smooth_directional_mov_minus / smooth_tr * 100 // DX = math.abs(plus_DM - minus_DM) / (plus_DM + minus_DM) * 100 // DX not used in this strategy [plus_DM, minus_DM] // DI +/- from timeframes 1 and 2 [plus_DM_tf1, minus_DM_tf1] = get_ADX(request.security(syminfo.tickerid, tf1, high), request.security(syminfo.tickerid, tf1, close),request.security(syminfo.tickerid, tf1, low)) [plus_DM_tf2, minus_DM_tf2] = get_ADX(request.security(syminfo.tickerid, tf2, high),request.security(syminfo.tickerid, tf2, close),request.security(syminfo.tickerid, tf2, low)) // } end of block: ADX Indicator var string ENUM_LONG = "LONG" var string LONG_MSG_ENTER = input.string("Long entered", title="Alert MSG for buying (Long position)", group=GROUP_ALERT) var string LONG_MSG_EXIT = input.string("Long closed", title="Alert MSG for closing (Long position)", group=GROUP_ALERT) backtest_timeframe_start = input(defval=timestamp("01 Apr 2020 13:30 +0000"), title="Backtest Start Time", group=GROUP_HORIZON) within_timeframe = true // Signals for entry _uptrend_confirmed = plus_DM_tf1 > minus_DM_tf1 and plus_DM_tf2 > minus_DM_tf2 entry_signal_long = _uptrend_confirmed plotshape(_uptrend_confirmed, style=shape.triangleup, location=location.bottom, color=color.green) plotshape(not _uptrend_confirmed, style=shape.triangledown, location=location.bottom, color=color.red) // Trailing stop loss ("TSL") { tsl_multi = input.float(2.0, title="ATR Multiplier for trailing stoploss", group=GROUP_SL) SL_buffer = ta.atr(input.int(14, title="Length of ATR for trailing stoploss", group=GROUP_SL)) * tsl_multi TSL_source_long = low var stop_loss_price_long = float(0) var pos_opened_long = false stop_loss_price_long := pos_opened_long ? math.max(stop_loss_price_long, TSL_source_long - SL_buffer) : TSL_source_long - SL_buffer // MAIN: { if pos_opened_long and TSL_source_long <= stop_loss_price_long pos_opened_long := false alert(LONG_MSG_EXIT, alert.freq_once_per_bar) strategy.close(ENUM_LONG, comment=close < strategy.position_avg_price ? "stop loss" : "take profit") // (2) Update the stoploss to latest trailing amt. if pos_opened_long strategy.exit(ENUM_LONG, stop=stop_loss_price_long, comment="SL") // (3) INITIAL ENTRY: if within_timeframe and entry_signal_long pos_opened_long := true alert(LONG_MSG_ENTER, alert.freq_once_per_bar) strategy.entry(ENUM_LONG, strategy.long, comment="long") // Plotting: TSL_transp_long = pos_opened_long and within_timeframe ? 0 : 100 plot(stop_loss_price_long, color=color.new(color.green, TSL_transp_long)) // CLEAN UP: Setting variables back to default values once no longer in use if ta.change(strategy.position_size) and strategy.position_size == 0 pos_opened_long := false if not pos_opened_long stop_loss_price_long := float(0) // } end of MAIN block