Основная идея этой стратегии заключается в том, чтобы следовать за трендом, обнаруживая прорывы скользящих средних за более высокие временные рамки.
Стратегия разработана в Pine Script и состоит из следующих основных компонентов:
Вводные материалы
Определяет период входных параметров как скользящий средний период, по умолчанию 200; и временные рамки как временные рамки бар, по умолчанию D (ежедневные бары).
Движущаяся средняя
Вычисляет экспоненциальную скользящую среднюю (EMA) с использованием функции ta.ema.
Выявление прорыва
Определяет прорывы и сбои с помощью функций ta.crossover и ta.crossunder.
Схема сигналов
Указывает стрелы вверх и вниз на решетке, когда происходит прорыв.
Торговые входы и выходы
Вступает в торговлю по сигналам прорыва и выходит, когда цена достигает 2x стоп-лосс расстояния.
Стратегия в основном использует способность следовать за трендом скользящих средних за более высокие временные рамки.
К основным преимуществам этой стратегии относятся:
Простая логика, легко понять и освоить.
Зависит только от одного индикатора, с минимальной настройкой параметров.
Сигналы прорыва, как правило, соответствуют тренду, избегая чрезмерной торговли.
Более высокие временные рамки ясно показывают основные тенденции без шума.
Гибкие временные рамки для различных продуктов.
Легко масштабируемый по всем продуктам, избегая одновременных отказов.
Потенциальными рисками являются:
Сигналы прорыва могут оказаться ложными, не способными эффективно фильтровать рыночный шум.
Не в состоянии использовать краткосрочные возможности.
Огромные потери, если основная направленность тренда неверна.
Несоответствие между скользящей средней и временной шкалой торговли может привести к переоценке или упущенной прибыли.
Отсутствие стоп-потери в реальном времени может привести к увеличению потерь.
Возможные решения включают сочетание с индикаторами, следующими за тенденцией, добавление фильтров, сокращение периода хранения, внедрение динамического стоп-лосса и т.д.
Стратегия может быть улучшена в следующих аспектах:
Добавьте индикаторы тренда, такие как MACD, KD, чтобы повысить надежность прорыва.
Добавьте фильтры на основе объема или полос Боллинджера, чтобы избежать ложных прорывов.
Оптимизировать настройку параметров для соответствия периода хранения с циклом тренда.
Включить стоп-лосс в режиме реального времени для контроля потерь на одной сделке.
Изучить методы машинного обучения для оптимизации динамических параметров.
Испытать различные комбинации распределения активов для повышения общей стабильности.
Вкратце, это простая и практичная стратегия для отслеживания тренда с помощью перемещающихся средних прорывов. Она проста в понимании и внедрении, служа хорошей вводной стратегией для торговли алгоритмами. Но у нее также есть некоторые недостатки, которые необходимо устранить с помощью комбинаций индикаторов, настройки параметров, динамической стоп-лосс и т. Д. Остается много возможностей для улучшений и расширений.
/*backtest start: 2023-09-29 00:00:00 end: 2023-10-29 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // @version=5 // Open-Range-Breakout strategy // No license. Free and Open Source. strategy('Strategy: ORB', shorttitle="ORB", overlay=true , currency=currency.NONE, initial_capital=100000) // Inputs period = input.int(defval=15, title="TimeRange", tooltip="The range in minutes (default: 15m)") sessionInput = input(defval="0915-0930", title="Time Range", group="ORB settings", tooltip='What is the timeperiod (default 9:15AM to 9:30AM, exchange timezone') hide = input.bool(defval = false, title="Hide ORB Range", group="ORB setting", tooltip = 'Hide the ORB range drawing') // SL Related slAtrLen = input.int(defval=14, title="ATR Period for placing SL", group="StopLoss settings") showSLLines = input.bool(defval=false, title="Show SL lines in chart", tooltip="Show SL lines also as dotted lines in chart. Note: chart may look untidy.", group="StopLoss settings") // Further Filtering ignoreMementumVolume = input.bool(defval=false, title="Ignore Momentum & Volume", tooltip="Ignore Momentum & Volume to find out trades", group="Strengh Settings") rsiLen = input.int(defval=14, title="Momentum Period", group="Strengh Settings", tooltip = 'To determine the momentum, RSI period is set default to 100') rsiBullish = input.int(defval=50, step=1, title="Bullish Momentum", group="Strengh Settings", tooltip = 'Bullish Momentum, default set to RSI as 50') rsiBearish = input.int(defval=50, step=1, title="Bearish Momentum", group="Strengh Settings", tooltip = 'Bearish Momentum, default set to RSI as 50') volAvg = input.int(defval=20, step=1, title="Volume Average Period", group="Strengh Settings", tooltip = 'To calculate average volume, how many historical bars are considered. Default: 20.') volThreshold = input.float(defval=1, step=0.1, title="Volume Strengh", group="Strengh Settings", tooltip = 'Multiplier: How big the current bar volume compared to average of last 20') trendPeriod = input.int(defval=200, step=1, title="Trend Period", group="Trend Settings", tooltip = 'To calculate trend, what period is considered. Default: 200.') hideTrend = input.bool(defval = false, title="Hide the trend line", group="Trend Settings", tooltip = 'Hide the trend') hidePDHCL = input.bool(defval = false, title="Hide the PDHCL (prev day High Close Low range)", tooltip = 'Hide the Previous Day High, Close, Low lines') hideTable = input.bool(defval = false, title="Hide the Summary Table", tooltip = 'Hide the summary table.') // Trade related rrRatio = input.float(title='Risk:Reward', step=0.1, defval=2.0, group="Trade settings") endOfDay = input.int(defval=1500, title="Close all trades, default is 3:00 PM, 1500 hours (integer)", group="Trade settings") mktAlwaysOn = input.bool(defval=true, title="Markets that never closed (Crypto, Forex, Commodity)", tooltip="Some markers never closes. For those cases, make this checked.", group="Trade settings") lotSize = input.int(title='Lot Size', step=1, defval=1, group="Trade settings") // Util method is_newbar(res) => timeframe.change(time(res)) != 0 // print table printTable(txt) => var table t = table.new(position.bottom_right, 1, 1) table.cell(t, 0, 0, txt, text_halign = text.align_left, bgcolor = color.lime) // globals t = time(timeframe.period, sessionInput + ":1234567") // everyday in_session = not na(t) is_first = in_session and not in_session[1] is_end_session = in_session[1] and not in_session green(open, close) => close > open ? true : false red(open, close) => close < open ? true : false var float orb_high = na var float orb_low = na if is_first orb_high := high orb_low := low else orb_high := orb_high[1] orb_low := orb_low[1] if high > orb_high and in_session orb_high := high if low < orb_low and in_session orb_low := low plot(hide ? na : orb_high, style=plot.style_line, color=orb_high[1] != orb_high ? na : color.green, title="ORB High", linewidth=2) plot(hide ? na : orb_low, style=plot.style_line, color=orb_low[1] != orb_low ? na : color.red, title="ORB Low", linewidth=2) // PDHCL (Previous Day High Close Low) [dh,dl,dc] = request.security(syminfo.ticker, "D", [high[1],low[1], close[1]], lookahead=barmerge.lookahead_on) plot(hidePDHCL ? na : dh, title="Prev High", color=color.red, linewidth=2, trackprice=true, show_last = 1) plot(hidePDHCL ? na : dl, title="Prev Low", color=color.green, linewidth=2, trackprice=true, show_last = 1) plot(hidePDHCL ? na : dc, title="Prev Close", color=color.black, linewidth=2, trackprice=true, show_last = 1) plot(hidePDHCL ? na : ta.vwap(close), title="Prev VWAP", color=color.fuchsia, linewidth=2, trackprice=true, show_last = 1) var l1 = label.new(bar_index, hidePDHCL ? na : dh, 'PDH', style=label.style_label_right) // Previous Day WWAP // For SL calculation atr = ta.atr(slAtrLen) highestHigh = ta.highest(high, 7) lowestLow = ta.lowest(low, 7) longStop = showSLLines ? lowestLow - (atr * 1) : na shortStop = showSLLines ? highestHigh + (atr * 1) : na plot(longStop, title="Buy SL", color=color.green, style=plot.style_cross) plot(shortStop, title="Sell SL", color=color.red, style=plot.style_cross) // Momentum: rsi rsi = ta.rsi(close, rsiLen) // trend: EMA200 ema = ta.ema(close, trendPeriod) plot(hideTrend ? na : ema, "EMA Trend", color=close > ema ? color.green : color.red, linewidth = 1) // Volume-Weighed Moving Average calculation vwmaAvg = ta.vwma(close, volAvg) vwma_latest = volume // plotshape((barstate.isconfirmed and (vwma_latest > (vwmaAvg * volThreshold))), title='VolumeData', text='', location=location.abovebar, style=shape.diamond, color=color.gray, textcolor=color.gray, size=size.tiny) // Trade signals longCond = barstate.isconfirmed and (ta.crossover(close, orb_high) or ta.crossover(close, dh)) and green(open, close) and (ignoreMementumVolume ? true : rsi > rsiBullish and (vwma_latest > (vwmaAvg * volThreshold))) shortCond = barstate.isconfirmed and (ta.crossunder(close, orb_low) or ta.crossunder(close, dl)) and red(open, close) and (ignoreMementumVolume ? true : rsi < rsiBearish and (vwma_latest > (vwmaAvg * volThreshold))) plotshape(longCond, title='Breakout', text='BO', location=location.belowbar, style=shape.triangleup, color=color.green, textcolor=color.green) plotshape(shortCond, title='Breakout', text='BD', location=location.abovebar, style=shape.triangledown, color=color.red, textcolor=color.red) // Trade execute h = hour(time('1'), syminfo.timezone) m = minute(time('1'), syminfo.timezone) hourVal = h * 100 + m totalTrades = strategy.opentrades + strategy.closedtrades if (mktAlwaysOn or (hourVal < endOfDay)) // Entry var float sl = na var float target = na if (longCond) strategy.entry("enter long", strategy.long, lotSize, limit=na, stop=na, comment="Enter Long") sl := longStop target := close + ((close - longStop) * rrRatio) alert('Buy:' + syminfo.ticker + ' ,SL:' + str.tostring(math.floor(sl)) + ', Target:' + str.tostring(target), alert.freq_once_per_bar) if (shortCond) strategy.entry("enter short", strategy.short, lotSize, limit=na, stop=na, comment="Enter Short") sl := shortStop target := close - ((shortStop - close) * rrRatio) alert('Sell:' + syminfo.ticker + ' ,SL:' + str.tostring(math.floor(sl)) + ', Target:' + str.tostring(target), alert.freq_once_per_bar) // Exit: target or SL if ((close >= target) or (close <= sl)) strategy.close("enter long", comment=close < sl ? "Long SL hit" : "Long target hit") if ((close <= target) or (close >= sl)) strategy.close("enter short", comment=close > sl ? "Short SL hit" : "Short target hit") else if (not mktAlwaysOn) // Close all open position at the end if Day strategy.close_all(comment = "Close all entries at end of day.") // Plotting table if (not hideTable and is_end_session) message = syminfo.ticker + " :\n\nORB Upper: " + str.tostring(math.round(orb_high)) + "\nORB Lower: " + str.tostring(math.round(orb_low)) + "\nPDH: " + str.tostring(math.round(dh)) + "\nPDC: " + str.tostring(math.round(dc)) + "\nPDL: " + str.tostring(math.round(dl)) + "\nVWAP: " + str.tostring(math.round(ta.vwap(close))) printTable(message) alert(message, alert.freq_once_per_bar_close)