
La estrategia de arbitraje de indicadores de oscilación aleatoria de doble marco es un sistema de negociación de alta frecuencia diaria basado en indicadores de oscilación aleatoria (estocásticos), cuyo núcleo utiliza dos indicadores de oscilación aleatoria con diferentes configuraciones de parámetros para generar y confirmar señales de negociación en un marco de tiempo de 15 segundos. La lógica principal es identificar puntos de entrada potenciales a través de la intersección de la línea% K y la línea% D de los indicadores aleatorios principales, mientras que se refiere al valor% D de los indicadores aleatorios secundarios como un filtro de estado de mercado.
La estrategia utiliza un doble sistema de indicadores de convulsiones aleatorias, denominados indicadores principales y indicadores de referencia, respectivamente:
Los principales ajustes de los indicadores de temblor al azar:
Para ver la configuración del indicador de temblores aleatorio:
El diseño de la lógica de entrada es preciso, y la validez de la señal se confirma en varios niveles:
Las condiciones de admisión son las siguientes:
Los requisitos para ingresar con la cabeza vacía son:
La lógica de salida se basa en una combinación de señales de tiempo y tecnología:
La estrategia también incluye reconocimiento de formas:
Mecanismo de confirmación de varias capas: Confirmación recíproca mediante dos indicadores de vibración aleatorios de configuración diferente, reduce la falsa señal producida por un solo indicador y mejora la fiabilidad de la señal.
Reglas precisas de entrada y salidaLa estrategia define claramente las condiciones de entrada y salida, elimina la subjetividad de las decisiones comerciales y permite una negociación completamente sistematizada.
Reconocimiento de formasLa capacidad de identificar las formas de “más altos y más bajos” y “más bajos y más altos” en el mercado, para capturar oportunidades de continuación de tendencias, es una función que muchas estrategias simples no pueden lograr.
El filtro del tiempo: Al limitar el tiempo de negociación a las horas normales del mercado, se evita la alta volatilidad y la baja liquidez antes de la apertura y el cierre, reduciendo los puntos de deslizamiento y los costos.
Filtrado de las medias móviles: La función de filtro de promedio móvil opcional añade una capa de confirmación de tendencia para asegurar que la dirección de las operaciones coincida con la tendencia general.
Diferencias de precio y parámetros de diferencia de capacidadLa estrategia introduce varios parámetros para controlar la amplitud de los cambios en los precios y el rango de variación del indicador, filtrando eficazmente las señales de ruido generadas por las fluctuaciones mínimas.
Conversión de lógica dinámica: El sistema puede adaptarse a las condiciones de conversión de multi-cabeza a cabecera y de cabecera a multi-cabeza en función de la dinámica de las condiciones del mercado, y es más adaptable.
Sistema de alerta completoLa estrategia incluye una gran cantidad de condiciones de alerta para la supervisión y ejecución de operaciones en tiempo real.
Riesgo de operaciones de alta frecuencia en un marco de tiempo cortoLa estrategia de usar el marco de tiempo de 15 segundos puede generar demasiadas señales, lo que lleva a una mayor frecuencia de operaciones, aumenta los costos de las operaciones y puede generar una gran cantidad de falsas señales en caso de gran volatilidad del mercado.
La falta de un mecanismo de detención de pérdidasLa falta de control de riesgo es una de las principales debilidades de la estrategia.
Sensibilidad de los parámetrosLos parámetros más precisos utilizados en la estrategia (por ejemplo, un umbral de diferencia de 0.15, un límite de diferencia de precio de 0.1%, etc.) pueden ser demasiado sensibles a las diferentes condiciones del mercado y necesitan ser ajustados con frecuencia.
El costo de oportunidad de las limitaciones de tiempoEl comercio solo durante el horario normal del mercado puede perder algunas oportunidades importantes antes y después del cierre, especialmente en la reacción del mercado después de una noticia importante.
Dependencia de la liquidez: Las estrategias de alta frecuencia pueden tener problemas de puntos de deslizamiento en mercados de baja liquidez, y los precios de ejecución reales pueden diferir significativamente de los precios de la generación de señales.
Retrasos en los indicadores técnicosEl indicador de la oscilación aleatoria tiene un cierto atraso en sí mismo, especialmente en mercados que cambian rápidamente, y puede no capturar los puntos de inflexión a tiempo.
El riesgo de exceso de adaptaciónEl ajuste de los parámetros de la estrategia puede conducir a una ajuste excesivo de los datos históricos y a un mal desempeño en el entorno de mercado futuro.
Aumentar el mecanismo de suspensión de pérdidasEl punto de optimización más importante es la implementación de un sistema de alto riesgo inteligente, que puede considerar una estrategia de alto riesgo basada en el ATR (rango de fluctuación real promedio), o el uso de niveles de tecnología (como los altos y bajos previos) como puntos de alto riesgo para limitar la pérdida máxima de una sola transacción.
Introducción a la gestión de posiciones: Ajuste dinámico de la escala de las operaciones en función de la volatilidad del mercado y la capacidad de asumir el riesgo de la cuenta, utilizando diferentes configuraciones de posición en diferentes intensidades de señal para optimizar la utilización de los fondos y la rentabilidad del riesgo.
Acompañamiento de la confirmación de la entregaLa integración de los indicadores de tráfico en el sistema requiere que las señales de entrada importantes tengan suficiente soporte de tráfico para filtrar las señales no confiables en entornos de bajo tráfico.
Fusión de varios indicadoresConsidere la combinación de otros indicadores de dinámica y tendencia, como el RSI, el MACD o el Brin, para construir una perspectiva de mercado más completa y mejorar la solidez del sistema.
Optimización del marco de tiempo: Prueba diferentes marcos de tiempo básicos, como 1 minuto o 5 minutos, que pueden reducir el ruido y al mismo tiempo mantener suficientes oportunidades de negociación para encontrar el equilibrio óptimo entre la calidad y la cantidad de señales.
Aumentar el seguimiento estadístico de retroalimentación• Implementar indicadores de rendimiento de retroalimentación más completos, como el máximo retiro, el índice de Sharpe, el índice de ganancias, el índice de pérdidas, etc., para evaluar el rendimiento de la estrategia de manera más científica.
Parámetros de adaptaciónTransformar los parámetros fijos en parámetros de adaptación basados en la dinámica de la volatilidad del mercado, lo que permite que la estrategia se adapte a diferentes entornos de mercado.
Aumentar el filtro de las condiciones del mercadoLa inclusión de VIX (indice de volatilidad) o un indicador similar como condición de filtración del entorno de mercado para ajustar los parámetros de la estrategia o suspender la negociación en un entorno de alta volatilidad.
La estrategia de negociación de arbitraje de indicadores de oscilación aleatoria de doble marco horario es un sistema de negociación de alta frecuencia a corto plazo cuidadosamente diseñado que mejora la fiabilidad de la señal de negociación a través de mecanismos de confirmación de múltiples niveles, como indicadores de oscilación aleatoria doble, filtros de promedio móvil y filtros de tiempo. La estrategia identifica puntos de inflexión de sobreventa y sobreventa a corto plazo y formas de continuación de la tendencia dentro de los períodos regulares del mercado, y es adecuada para mercados con suficiente liquidez y volatilidad moderada.
A pesar de la buena estructura del diseño de la estrategia, todavía hay deficiencias en los mecanismos de gestión de riesgos clave, como los riesgos inherentes a la negociación de alta frecuencia y la falta de stop loss. Para mejorar la estabilidad y la rentabilidad a largo plazo de la estrategia, se recomienda agregar medidas de optimización, como el stop loss, el sistema de gestión de posiciones, la confirmación de la transacción y la integración de múltiples indicadores. Además, la conversión de los parámetros fijos en parámetros de adaptación y el aumento del seguimiento estadístico de retroalimentación integral ayudarán a mantener un rendimiento estable de la estrategia en diferentes entornos de mercado.
Con un entendimiento profundo y una optimización continua de la estrategia por parte de los operadores, este sistema de negociación tiene el potencial de ser una parte efectiva de la caja de herramientas de negociación intradiaria, especialmente adecuada para los operadores que tienen un conocimiento profundo de los indicadores técnicos y que pueden monitorear el mercado a tiempo.
/*backtest
start: 2025-01-01 00:00:00
end: 2025-06-17 00:00:00
period: 4h
basePeriod: 4h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
*/
//@version=6
strategy("Dual TF Stochastic Strategy", overlay=false)
// Input parameters with updated defaults
primaryLen = input.int(12, "Primary Stoch K Length", minval=1) // Changed from 14 to 12
primarySmooth = input.int(12, "Primary Stoch K Smoothing", minval=1) // Changed from 3 to 12
primaryDLen = input.int(12, "Primary Stoch D Length", minval=1) // Changed from 3 to 12
primaryRes = input.timeframe("15S", "Primary Timeframe") // Changed from "" to "15S"
refLen = input.int(12, "Reference Stoch K Length", minval=1) // Changed from 14 to 12
refSmooth = input.int(15, "Reference Stoch K Smoothing", minval=1) // Changed from 3 to 15
refDLen = input.int(30, "Reference Stoch D Length", minval=1) // Changed from 3 to 30
refRes = input.timeframe("15S", "Reference Timeframe") // Changed from "D" to "15S"
tolerance = input.float(0.1, "Ref D Tolerance %", minval=0.1, maxval=10.0, step=0.1) // Changed from 1.0 to 0.1
maxPriceDiff = input.float(0.1, "Maximum Price % Difference", minval=0.1, maxval=5.0, step=0.1) // Changed from 1.0 to 0.1
closeKThreshold = input.float(0.7, "Close %K Tolerance %", minval=0.1, maxval=10.0, step=0.1) // Changed from 5.0 to 0.7
minPriceDiffShort = input.float(0.1, "Min Price % Diff for Close %K Short", minval=0.1, maxval=5.0, step=0.1) // Changed from 0.5 to 0.1
showLabels = input.bool(true, "Show Crossover/Crossunder Labels")
// Time Filters (America/New_York timezone, UTC-4)
is_premarket = hour(time, "America/New_York") < 9
is_postmarket = hour(time, "America/New_York") >= 16
is_regular_hours = hour(time, "America/New_York") >= 9 and hour(time, "America/New_York") < 16
is_exit_time = hour(time, "America/New_York") >= 15 and minute(time, "America/New_York") >= 30 // 3:30 PM ET
// Moving Average Settings
useMAFilter = input.bool(true, "Use Moving Average Filter")
maLength = input.int(200, "Moving Average Length", minval=1)
maType = input.string("SMA", "Moving Average Type", options=["SMA", "EMA", "WMA", "VWMA"])
maTimeframe = input.timeframe("", "Moving Average Timeframe")
// Stochastic Calculations
primaryHighest = ta.highest(high, primaryLen)
primaryLowest = ta.lowest(low, primaryLen)
primaryK_raw = 100 * (close - primaryLowest) / (primaryHighest - primaryLowest)
primaryK = ta.sma(primaryK_raw, primarySmooth)
primaryD = ta.sma(primaryK, primaryDLen)
[primaryK_tf, primaryD_tf] = request.security(syminfo.tickerid, primaryRes, [primaryK, primaryD])
refHighest = ta.highest(high, refLen)
refLowest = ta.lowest(low, refLen)
refK_raw = 100 * (close - refLowest) / (refHighest - refLowest)
refK = ta.sma(refK_raw, refSmooth)
refD = ta.sma(refK, refDLen)
[refK_tf, refD_tf] = request.security(syminfo.tickerid, refRes, [refK, refD])
// Calculate Moving Average
var float ma = na
if useMAFilter
if maType == "SMA"
ma := request.security(syminfo.tickerid, maTimeframe, ta.sma(close, maLength))
else if maType == "EMA"
ma := request.security(syminfo.tickerid, maTimeframe, ta.ema(close, maLength))
else if maType == "WMA"
ma := request.security(syminfo.tickerid, maTimeframe, ta.wma(close, maLength))
else if maType == "VWMA"
ma := request.security(syminfo.tickerid, maTimeframe, ta.vwma(close, maLength))
// Price relative to MA
priceAboveMA = not useMAFilter or close > ma
priceBelowMA = not useMAFilter or close < ma
// Crossover Detection and Tracking
crossOver = ta.crossover(primaryK_tf, primaryD_tf)
crossUnder = ta.crossunder(primaryK_tf, primaryD_tf)
// Separate tracking for crossover and crossunder %K and price
var float lastCrossOverK = na
var float lastCrossOverPrice = na
var float currentCrossOverK = na
var float currentCrossOverPrice = na
var float lastCrossUnderK = na
var float lastCrossUnderPrice = na
var float currentCrossUnderK = na
var float currentCrossUnderPrice = na
// Update crossover tracking variables
if crossOver
lastCrossOverK := nz(currentCrossOverK, primaryK_tf[1])
lastCrossOverPrice := nz(currentCrossOverPrice, close[1])
currentCrossOverK := primaryK_tf
currentCrossOverPrice := close
// Update crossunder tracking variables
if crossUnder
lastCrossUnderK := nz(currentCrossUnderK, primaryK_tf[1])
lastCrossUnderPrice := nz(currentCrossUnderPrice, close[1])
currentCrossUnderK := primaryK_tf
currentCrossUnderPrice := close
// Calculate differences separately
crossOverPriceDiffPercent = math.abs((currentCrossOverPrice - lastCrossOverPrice) / lastCrossOverPrice * 100)
crossOverKDiffPercent = math.abs((currentCrossOverK - lastCrossOverK) / lastCrossOverK * 100)
crossUnderPriceDiffPercent = math.abs((currentCrossUnderPrice - lastCrossUnderPrice) / lastCrossUnderPrice * 100)
crossUnderKDiffPercent = math.abs((currentCrossUnderK - lastCrossUnderK) / lastCrossUnderK * 100)
isKCloseCrossUnder = crossUnderKDiffPercent <= closeKThreshold and not na(lastCrossUnderK)
// New condition for long entry based on %K and refD_tf difference
kAndRefDDiffClose = crossOver and math.abs(currentCrossOverK - refD_tf) <= 0.15
// Labels for crossover and crossunder (optional)
if showLabels
if crossOver
diffKandRefD = math.abs(currentCrossOverK - refD_tf)
label.new(bar_index, 50, "CrossOver\nDiff K-RefD: " + str.tostring(diffKandRefD, "#.###"), color=color.green, textcolor=color.black, style=label.style_label_up)
if crossUnder
diffKandRefD = math.abs(currentCrossUnderK - refD_tf)
label.new(bar_index, 50, "CrossUnder\nDiff K-RefD: " + str.tostring(diffKandRefD, "#.###"), color=color.red, textcolor=color.black, style=label.style_label_down)
// Entry Conditions
longKCondition = crossOver and (na(lastCrossOverK) or currentCrossOverK > lastCrossOverK)
shortKCondition = crossUnder and (crossUnderPriceDiffPercent <= maxPriceDiff)
closeKShortCondition = crossUnder and isKCloseCrossUnder and (crossUnderPriceDiffPercent > minPriceDiffShort)
crossUnderBetween50and45 = crossUnder and currentCrossUnderK <= 50 and currentCrossUnderK > 45
// Long to Short if crossunder %K > 80 OR < 60
longToShortCondition = crossUnder and (currentCrossUnderK > 80 or currentCrossUnderK < 60) and strategy.position_size > 0 and is_regular_hours
upperLimit = refD_tf * (1 + tolerance/100)
lowerLimit = refD_tf * (1 - tolerance/100)
withinToleranceLong = primaryK_tf >= lowerLimit and primaryK_tf <= upperLimit
withinToleranceShort = primaryK_tf >= lowerLimit and primaryK_tf <= upperLimit
// Final Entry Conditions with MA filter
longCondition = ((longKCondition and (refD_tf >= 50 or refD_tf < 20)) or kAndRefDDiffClose) and is_regular_hours and not is_exit_time and priceAboveMA
shortCondition = (shortKCondition or (crossUnder and withinToleranceShort and (crossUnderPriceDiffPercent <= maxPriceDiff)) or closeKShortCondition or longToShortCondition or crossUnderBetween50and45) and is_regular_hours and not is_exit_time and priceBelowMA
// Short-to-Long Transition Condition with MA filter
shortToLongCondition = crossOver and currentCrossOverK < 25 and strategy.position_size < 0 and is_regular_hours and not is_exit_time and priceAboveMA
// Tracking for %K crossing under refD_tf
var float lastPrimaryKCrossUnderRefD = na
var float currentPrimaryKCrossUnderRefD = na
var bool isPrimaryKCrossUnderRefD = false
// Check if primary %K crosses under reference %D
isPrimaryKCrossUnderRefD := ta.crossunder(primaryK_tf, refD_tf)
// Update tracking for %K crossing under refD
if isPrimaryKCrossUnderRefD
lastPrimaryKCrossUnderRefD := currentPrimaryKCrossUnderRefD
currentPrimaryKCrossUnderRefD := primaryK_tf
// Exit Conditions
if is_exit_time
strategy.close("Long")
strategy.close("Short")
else if isPrimaryKCrossUnderRefD and not na(lastPrimaryKCrossUnderRefD) and currentPrimaryKCrossUnderRefD < lastPrimaryKCrossUnderRefD
strategy.close("Long")
else if (ta.crossunder(primaryK_tf, primaryD_tf) and primaryK_tf < refD_tf and refD_tf < 60)
strategy.close("Long")
if (ta.crossover(primaryK_tf, primaryD_tf) and primaryK_tf > refD_tf and refD_tf > 20) and not is_exit_time
strategy.close("Short")
// Track if crossunder happens above 85
var bool crossUnderAbove85 = false
// Detect crossunder above 85
if crossUnder and currentCrossUnderK > 85
crossUnderAbove85 := true
// Reset condition if %K crosses over %D
if ta.crossover(primaryK_tf, primaryD_tf)
crossUnderAbove85 := false
// Track previous crossover/crossunder values for Higher Low/Lower High detection
var float prevCrossOverK = na
var float prevCrossUnderK = na
// Update previous values on new crossovers/crossunders
if crossOver
prevCrossOverK := currentCrossOverK
if crossUnder
prevCrossUnderK := currentCrossUnderK
// Higher Low and Lower High conditions
higherLowCondition = crossOver and not na(prevCrossOverK) and currentCrossOverK > prevCrossOverK
lowerHighCondition = crossUnder and not na(prevCrossUnderK) and currentCrossUnderK < prevCrossUnderK
// Strategy Entries and Transitions
if longCondition
strategy.entry("Long", strategy.long)
if shortCondition
if strategy.position_size > 0 // If in a long position, close it first
strategy.close("Long")
strategy.entry("Short", strategy.short)
if shortToLongCondition
strategy.close("Short")
if ((longKCondition and (refD_tf >= 50 or refD_tf < 20)) or kAndRefDDiffClose) // Check full longCondition minus time (already checked)
strategy.entry("Long", strategy.long)
// Add label for Short to Long Transition
if shortToLongCondition
label.new(bar_index, na, "T", color=color.green, textcolor=color.white, style=label.style_label_up)
// Add label for Long to Short Transition
if longToShortCondition
label.new(bar_index, na, "T", color=color.red, textcolor=color.white, style=label.style_label_down)
// Plotting
plot(primaryK_tf, "Primary %K", color=color.white, linewidth=1)
plot(primaryD_tf, "Primary %D", color=color.orange, linewidth=1)
plot(refK_tf, "Reference %K", color=color.navy, linewidth=1)
plot(refD_tf, "Reference %D", color=color.rgb(33, 233, 243), linewidth=2)
// Plot current and last %K only for crossUnder when isKCloseCrossUnder is true and currentCrossUnderK < lastCrossUnderK
plot(crossUnder and isKCloseCrossUnder and currentCrossUnderK < lastCrossUnderK ? currentCrossUnderK : na, "Current CrossUnder %K (Close)", color=color.green, style=plot.style_cross, linewidth=2)
plot(crossUnder and isKCloseCrossUnder and currentCrossUnderK < lastCrossUnderK ? lastCrossUnderK : na, "Last CrossUnder %K (Close)", color=color.red, style=plot.style_cross, linewidth=2)
h0 = hline(85, "Upper Band", color=color.rgb(242, 187, 21))
hline(50, "Middle Band", color=#eaff04)
h1 = hline(20, "Lower Band", color=color.rgb(242, 187, 21))
h2 = hline(40, "Lower Band", color=#787B86)
h3 = hline(60, "Lower Band", color=#787B86)
h = hline(0, "Lower Band", color=#787B86)
h5 = hline(100, "Lower Band", color=#787B86)
fill(h0, h1, color=color.rgb(33, 150, 243, 90), title="Background")
fill(h, h1, color=#1be2781d, title="Background")
fill(h0, h5, color=#e21b742d, title="Background")
// Plot the MA if enabled
plot(useMAFilter ? ma : na, "Moving Average", color=color.yellow, linewidth=2)
// Add plot for visualization (optional)
plot(isPrimaryKCrossUnderRefD ? primaryK_tf : na, "Primary %K CrossUnder RefD", color=color.purple, style=plot.style_cross, linewidth=2)
plot(isPrimaryKCrossUnderRefD and not na(lastPrimaryKCrossUnderRefD) ? lastPrimaryKCrossUnderRefD : na, "Last Primary %K CrossUnder RefD", color=color.fuchsia, style=plot.style_cross, linewidth=2)
// Add new alert conditions
alertcondition(higherLowCondition, title="Stoch Higher Low", message="Stoch Higher Low Pattern Detected")
alertcondition(lowerHighCondition, title="Stoch Lower High", message="Stoch Lower High Pattern Detected")
// Plot markers for Higher Low and Lower High patterns
plot(higherLowCondition ? currentCrossOverK : na, "Higher Low", color=color.green, style=plot.style_cross, linewidth=2)
plot(lowerHighCondition ? currentCrossUnderK : na, "Lower High", color=color.red, style=plot.style_cross, linewidth=2)
// Alert conditions
alertcondition(crossOver, title="Stochastic %K Crossed Over %D", message="Stochastic %K crossed over %D")
alertcondition(crossUnder, title="Stochastic %K Crossed Under %D", message="Stochastic %K crossed under %D")
alertcondition(crossOver and primaryK_tf > 50, title="Stochastic %K Crossed Over %D Above 50", message="Stochastic %K crossed over %D above 50")
alertcondition(crossOver and primaryK_tf > refD_tf, title="Stochastic %K Crossed Over %D Above Reference %D", message="Stochastic %K crossed over %D above Reference %D")
alertcondition(longCondition, title="Long Entry Signal", message="Long entry signal triggered")
alertcondition(shortCondition, title="Short Entry Signal", message="Short entry signal triggered")
alertcondition(shortToLongCondition, title="Short to Long Transition", message="Short to Long transition triggered")
alertcondition(longToShortCondition, title="Long to Short Transition", message="Long to Short transition triggered")
alertcondition(isPrimaryKCrossUnderRefD, title="Primary %K Crossed Under Reference %D", message="Primary %K crossed under Reference %D")
alertcondition(crossOver and primaryK_tf > refD_tf, title="Bullish Crossover Above Ref %D", message="Bull: Dual Stoch")
alertcondition(crossUnder and primaryK_tf < refD_tf, title="Bearish Crossunder Below Ref %D", message="Bear: Dual Stoch")