Esta estrategia combina dos indicadores técnicos principales: el indicador Oma y el indicador Apollo para implementar el comercio de doble carril de posiciones largas y cortas. Su idea básica es encontrar oportunidades de retroceso a corto plazo cuando la tendencia a mediano y largo plazo se juzga alcista para establecer posiciones largas. Cuando la tendencia a mediano y largo plazo se juzga bajista, busca oportunidades en rebotes a corto plazo para establecer posiciones cortas.
Esta estrategia utiliza promedios móviles de 50 y 200 días para determinar la tendencia a medio y largo plazo.
A continuación, la estrategia utiliza el indicador Oma para localizar oportunidades de reversión de precios a corto plazo. El indicador Oma incluye líneas %K y %D, que son los resultados del indicador RSI suavizado por un promedio móvil simple. Cuando %K se rompe por debajo de %D desde el área de sobrecompra (por encima de 80), indica que el precio está pasando de un estado de sobrecompra a un retroceso hacia abajo; cuando %K se rompe por encima de %D desde el área de sobreventa (por debajo de 20), indica que el precio está rebotando desde el área de sobreventa, lo que presenta una oportunidad larga.
Además, para filtrar aún más las señales falsas, esta estrategia también incorpora el indicador Apollo. El indicador Apollo muestra los puntos extremos de los valores %D de la línea K. Cuando %K forma un nuevo mínimo, significa que la fuerza de rebote es relativamente débil. Cuando forma un nuevo máximo, significa que la fuerza de rebote es relativamente fuerte. Combinado con las señales del indicador Oma, esto puede mejorar aún más la precisión de la entrada.
Específicamente, en una tendencia alcista, esta estrategia comprobará la nueva información del punto más alto al mismo tiempo que el indicador Oma muestra una oportunidad por debajo del área de sobrecompra, para confirmar la fuerza del rebote.
A través del proceso anterior, esta estrategia aprovecha al máximo los puntos fuertes del juicio de tendencias a medio y largo plazo y los indicadores de reversión a corto plazo para construir un sistema de comercio de doble vía estable.
La estrategia combina el trading de tendencias y el trading de contratrends mediante el uso tanto de indicadores de juicio de tendencias como de inversión, formando un marco de trading híbrido estable.
Al filtrar el doble indicador, se puede reducir la proporción de señal falsa y mejorar la fiabilidad de las señales.
Los parámetros de la estrategia son relativamente simples, fáciles de entender y optimizar, adecuados para el comercio cuantitativo.
El rendimiento de la estrategia es robusto, con una buena tasa de ganancia y características de la relación riesgo-recompensa.
Al adoptar dos carriles para el largo y el corto, las oportunidades comerciales se pueden obtener continuamente sin limitarse a una sola dirección.
Como estrategia de reversión, pueden producirse pérdidas consecutivas cuando cambia la tendencia.
La estrategia requiere un control emocional relativamente alto por parte del operador, que necesita soportar un cierto nivel de retirada.
Algunos parámetros, como los períodos de media móvil, implican cierta subjetividad y deben determinarse mediante pruebas de retroceso y optimización.
Tanto los indicadores Oma como Apollo tienen cierta sensibilidad a las fluctuaciones anormales y pueden fallar en condiciones extremas de mercado.
Esta estrategia es más adecuada para mercados volátiles de rango y puede tener un rendimiento inferior en mercados con tendencias fuertes.
Los riesgos pueden mitigarse ajustando adecuadamente el período de media móvil para introducir el filtrado de tendencias y añadiendo stop loss/take profit.
Prueba diferentes combinaciones de parámetros para obtener mejores ajustes de parámetros, por ejemplo, utilizando medias móviles de suavizado EWMA.
Se añadirán indicadores de volumen o de BV para evaluar la divergencia que pueden ayudar a verificar la fiabilidad de la señal.
Añadir índices de volatilidad como VIX como indicadores de monitoreo, para reducir el tamaño de la posición cuando el mercado está en pánico.
Optimizar las estrategias de stop loss/take profit, como la adopción de un ATR dinámico de stop loss.
Introducir algoritmos de aprendizaje automático para optimizar dinámicamente la configuración de parámetros.
Añadir modelos multifactorial para mejorar la calidad de la señal.
En general, esta es una estrategia comercial cuantitativa estable y eficiente. Combina el juicio de tendencia y los indicadores de reversión, y adopta una doble verificación utilizando los indicadores Oma y Apollo, que pueden descubrir efectivamente oportunidades de reversión de precios a corto plazo. En comparación con el uso de sistemas puramente de tendencia o reversión, esta forma de estrategia es más robusta con un control de extracción superior, y es una estrategia comercial cuantitativa recomendada. Por supuesto, los usuarios también deben ser conscientes de los riesgos involucrados, y utilizar la optimización de parámetros, stop loss / take profit, identificación del régimen de mercado, etc. para controlar los riesgos y lograr el mejor rendimiento.
/*backtest start: 2023-10-25 00:00:00 end: 2023-10-28 00:00:00 period: 5m basePeriod: 1m 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/ // © PtGambler //@version=5 strategy("2 EMA + Stoch RSI + ATR [Pt]", shorttitle = "2EMA+Stoch+ATR", overlay=true, initial_capital = 10000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, calc_on_order_fills = false, max_bars_back = 500) // ********************************** Trade Period / Strategy Setting ************************************** startY = input(title='Start Year', defval=2011, group = "Backtesting window") startM = input.int(title='Start Month', defval=1, minval=1, maxval=12, group = "Backtesting window") startD = input.int(title='Start Day', defval=1, minval=1, maxval=31, group = "Backtesting window") finishY = input(title='Finish Year', defval=2050, group = "Backtesting window") finishM = input.int(title='Finish Month', defval=12, minval=1, maxval=12, group = "Backtesting window") finishD = input.int(title='Finish Day', defval=31, minval=1, maxval=31, group = "Backtesting window") timestart = timestamp(startY, startM, startD, 00, 00) timefinish = timestamp(finishY, finishM, finishD, 23, 59) // ****************************************************************************************** group_ema = "EMA" group_stoch = "Stochastic RSI" group_atr = "ATR Stoploss Finder" // ----------------------------------------- 2 EMA ------------------------------------- ema1_len = input.int(50, "EMA Length 1", group = group_ema) ema2_len = input.int(200, "EMA Length 2", group = group_ema) ema1 = ta.ema(close, ema1_len) ema2 = ta.ema(close, ema2_len) plot(ema1, "ema1", color.white, linewidth = 2) plot(ema2, "ema2", color.orange, linewidth = 2) ema_bull = ema1 > ema2 ema_bear = ema1 < ema2 // -------------------------------------- Stochastic RSI ----------------------------- smoothK = input.int(3, "K", minval=1, group = group_stoch) smoothD = input.int(3, "D", minval=1, group = group_stoch) lengthRSI = input.int(14, "RSI Length", minval=1, group = group_stoch) lengthStoch = input.int(14, "Stochastic Length", minval=1, group = group_stoch) src = close rsi1 = ta.rsi(src, lengthRSI) k = ta.sma(ta.stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK) d = ta.sma(k, smoothD) var trigger_stoch_OB = k > 80 var trigger_stoch_OS = k < 20 stoch_crossdown = ta.crossunder(k, d) stoch_crossup = ta.crossover(k, d) P_hi = ta.pivothigh(k,1,1) P_lo = ta.pivotlow(k,1,1) previous_high = ta.valuewhen(P_hi, k, 1) previous_low = ta.valuewhen(P_lo, k, 1) recent_high = ta.valuewhen(P_hi, k, 0) recent_low = ta.valuewhen(P_lo, k, 0) // --------------------------------------- ATR stop loss finder ------------------------ length = input.int(title='Length', defval=14, minval=1, group = group_atr) smoothing = input.string(title='Smoothing', defval='EMA', options=['RMA', 'SMA', 'EMA', 'WMA'], group = group_atr) m = input.float(0.7, 'Multiplier', step = 0.1, group = group_atr) src1 = input(high, "Source for upper band", group = group_atr) src2 = input(low, "Source for lower band", group = group_atr) showatr = input.bool(true, 'Show ATR Bands', group = group_atr) collong = input.color(color.purple, 'Long ATR SL', inline='1', group = group_atr) colshort = input.color(color.purple, 'Short ATR SL', inline='2', group = group_atr) ma_function(source, length) => if smoothing == 'RMA' ta.rma(source, length) else if smoothing == 'SMA' ta.sma(source, length) else if smoothing == 'EMA' ta.ema(source, length) else ta.wma(source, length) a = ma_function(ta.tr(true), length) * m up = ma_function(ta.tr(true), length) * m + src1 down = src2 - ma_function(ta.tr(true), length) * m p1 = plot(showatr ? up : na, title='ATR Short Stop Loss', color=colshort) p2 = plot(showatr ? down : na, title='ATR Long Stop Loss', color=collong) // ******************************* Profit Target / Stop Loss ********************************************* RR = input.float(2.0, "Reward to Risk ratio (X times SL)", step = 0.1, group = "Profit Target") var L_PT = 0.0 var S_PT = 0.0 var L_SL = 0.0 var S_SL = 0.0 BSLE = ta.barssince(strategy.opentrades.entry_bar_index(0) == bar_index) if strategy.position_size > 0 and BSLE == 1 L_PT := close + (close-down)*RR L_SL := L_SL[1] S_PT := close - (up - close)*RR S_SL := up else if strategy.position_size < 0 and BSLE == 1 S_PT := close - (up - close)*RR S_SL := S_SL[1] L_PT := close + (close-down)*RR L_SL := down else if strategy.position_size != 0 L_PT := L_PT[1] S_PT := S_PT[1] else L_PT := close + (close-down)*RR L_SL := down S_PT := close - (up - close)*RR S_SL := up entry_line = plot(strategy.position_size != 0 ? strategy.opentrades.entry_price(0) : na, "Entry Price", color.white, linewidth = 1, style = plot.style_linebr) L_PT_line = plot(strategy.position_size > 0 and BSLE > 0 ? L_PT : na, "L PT", color.green, linewidth = 2, style = plot.style_linebr) S_PT_line = plot(strategy.position_size < 0 and BSLE > 0 ? S_PT : na, "S PT", color.green, linewidth = 2, style = plot.style_linebr) L_SL_line = plot(strategy.position_size > 0 and BSLE > 0 ? L_SL : na, "L SL", color.red, linewidth = 2, style = plot.style_linebr) S_SL_line = plot(strategy.position_size < 0 and BSLE > 0 ? S_SL : na, "S SL", color.red, linewidth = 2, style = plot.style_linebr) fill(L_PT_line, entry_line, color = color.new(color.green,90)) fill(S_PT_line, entry_line, color = color.new(color.green,90)) fill(L_SL_line, entry_line, color = color.new(color.red,90)) fill(S_SL_line, entry_line, color = color.new(color.red,90)) // ---------------------------------- strategy setup ------------------------------------------------------ var L_entry_trigger1 = false var S_entry_trigger1 = false L_entry_trigger1 := ema_bull and close < ema1 and k < 20 and strategy.position_size == 0 S_entry_trigger1 := ema_bear and close > ema1 and k > 80 and strategy.position_size == 0 L_entry1 = L_entry_trigger1[1] and stoch_crossup and recent_low > previous_low S_entry1 = S_entry_trigger1[1] and stoch_crossdown and recent_high < previous_high //debugging plot(L_entry_trigger1[1]?1:0, "L Entry Trigger") plot(stoch_crossup?1:0, "Stoch Cross Up") plot(recent_low > previous_low?1:0, "Higher low") plot(S_entry_trigger1[1]?1:0, "S Entry Trigger") plot(stoch_crossdown?1:0, "Stoch Cross down") plot(recent_high < previous_high?1:0, "Lower high") if L_entry1 strategy.entry("Long", strategy.long) if S_entry1 strategy.entry("Short", strategy.short) strategy.exit("Exit Long", "Long", limit = L_PT, stop = L_SL, comment_profit = "Exit Long, PT hit", comment_loss = "Exit Long, SL hit") strategy.exit("Exit Short", "Short", limit = S_PT, stop = S_SL, comment_profit = "Exit Short, PT hit", comment_loss = "Exit Short, SL hit") //resetting triggers L_entry_trigger1 := L_entry_trigger1[1] ? L_entry1 or ema_bear or S_entry1 ? false : true : L_entry_trigger1 S_entry_trigger1 := S_entry_trigger1[1] ? S_entry1 or ema_bull or L_entry1 ? false : true : S_entry_trigger1 //Trigger zones bgcolor(L_entry_trigger1 ? color.new(color.green ,90) : na) bgcolor(S_entry_trigger1 ? color.new(color.red,90) : na)