Эта стратегия использует средний направленный индекс (DI +) и отрицательный направленный индекс (DI-) на двух временных рамках, чтобы определить направление тренда для длинных и коротких сделок. Когда DI + выше, чем DI- как на больших, так и на меньших временных рамках, это указывает на восходящий тренд, и запускается длинный сигнал. Когда DI- выше, чем DI + на обеих рамках, это указывает на нисходящий тренд, и запускается короткий сигнал.
Стратегия основана на нескольких принципах:
Вычислить DI+ и DI-. Получить DI+ и DI- с использованием высоких, близких и низких цен.
Сравните DI+ и DI- на двух временных отрезках. Вычислите DI+ и DI- соответственно на основных графических временных отрезках (например, 1 час) и более крупных временных отрезках (например, ежедневно). Сравните значения между двумя временными отрезками.
Определите направление тренда. Когда DI+ больше DI- как в больших, так и в меньших временных рамках, это указывает на тенденцию к росту. Когда DI- больше DI+ в обеих рамках, это указывает на тенденцию к снижению.
Ди-> Ди- на обоих кадрах дает длинный сигнал.
Используйте ATR для расчета динамического стоп-лосса для следования тренду.
Условия выхода. Выход, когда стоп-лосс достигнут или цена изменится.
Стратегия имеет следующие преимущества:
Используя двойные временные рамки, ИИ отфильтровывает ложные прорывы.
ATR задержка максимизирует защиту прибыли и избегает остановки слишком тесно.
Своевременная остановка потери контролирует потери на единичных сделках.
Торговля с трендом позволяет непрерывно улавливать тенденции.
Простые и понятные правила, легко применяемые для торговли в реальном времени.
Существует также несколько рисков:
DI имеет эффект задержки, может пропустить время входа. Может оптимизировать параметры или добавить другие показатели.
Двойные временные рамки могут иметь расхождения между большим и меньшим TF. Добавьте больше проверки временных рамок.
Слишком агрессивная стоп-лосс может привести к переоценке.
Добавить фильтры, чтобы уменьшить частоту торговли.
Оптимизация параметров основана на исторических данных и может быть перегружена. Оценивайте надежность параметров осторожно.
Стратегия может быть улучшена в следующих аспектах:
Оптимизировать параметры расчета DI для лучшего набора параметров.
Добавить другие фильтры индикаторов для улучшения точности сигнала, например MACD, KDJ и т.д.
Улучшить стратегию стоп-лосса для адаптации к более широким рыночным условиям, таким как остановка или ожидание ордеров.
Добавьте фильтры торговых сессий, чтобы избежать значительных новостных событий.
Испытать прочность параметров на различных продуктах для улучшения адаптивности.
Внедрить машинное обучение для обучения модели на исторических данных.
В целом, это типичная стратегия, которая использует DI для определения направления тренда и установки стоп-лосса для блокировки прибыли вдоль тренда. Преимущество заключается в его четкой логике и простоте реализации для живой торговли.
/*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