A ideia central desta estratégia é seguir a tendência detectando quebras de médias móveis em prazos mais altos.
A estratégia é desenvolvida em Pine Script e consiste nos seguintes componentes principais:
Input
Define o período dos parâmetros de entrada como o período da média móvel, por defeito para 200; e o período como o período de barras, por defeito para D (barras diárias).
Média móvel
Calcula a média móvel exponencial (EMA) utilizando a função ta.ema.
Detecção de fuga
Identifica rupturas e avarias utilizando as funções ta.crossover e ta.crossunder.
Planejamento de sinais
Traça setas para cima e para baixo nas barras quando ocorrem fuga.
Entradas e saídas comerciais
Entre em negociação com sinais de ruptura e sai quando o preço atinge 2x a distância de stop loss.
A estratégia aproveita principalmente a capacidade de seguir tendências de médias móveis em prazos mais longos.
As principais vantagens desta estratégia incluem:
Lógica simples, fácil de entender e dominar.
Depende apenas de um indicador, com ajuste mínimo de parâmetros.
Os sinais de ruptura tendem a alinhar-se com a tendência, evitando negociações excessivas.
Os prazos mais longos mostram claramente as principais tendências sem ruído.
As combinações de prazos flexíveis atendem a diferentes produtos.
Fácil escalabilidade entre produtos, evitando reduções simultâneas.
Os riscos potenciais são:
Os sinais de ruptura podem revelar-se falsos, incapazes de filtrar eficazmente o ruído do mercado.
Incapaz de capitalizar oportunidades de curto prazo.
Perdas maciças se a grande direcção da tendência estiver errada.
O desajuste de prazo entre a média móvel e o prazo de negociação pode conduzir a um excesso de negociação ou a perdas de lucro.
A falta de stop loss em tempo real pode resultar em perdas ampliadas.
As soluções possíveis incluem a combinação com indicadores de tendência, a adição de filtros, a redução do período de retenção, a implementação de stop loss dinâmicos, etc.
A estratégia pode ser melhorada nos seguintes aspectos:
Adicione indicadores de tendência como MACD, KD para aumentar a confiabilidade da fuga.
Adicionar filtros baseados em volume ou Bandas de Bollinger para evitar falsas rupturas.
Otimizar a regulação dos parâmetros para que o período de retenção corresponda ao ciclo de tendência.
Incorporar stop loss em tempo real para controlar a perda de uma única transação.
Explorar técnicas de aprendizagem de máquina para otimização de parâmetros dinâmicos.
Teste várias combinações de alocação de ativos para melhorar a estabilidade geral.
Em resumo, esta é uma estratégia simples e prática para seguir tendências através de breakouts de média móvel. É fácil de entender e implementar, servindo como uma boa estratégia introdutória para a negociação de algo. Mas também tem algumas falhas que precisam ser abordadas através de combinações de indicadores, ajuste de parâmetros, stop loss dinâmico, etc.
/*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)