Estrategia de trading de tendencias de impulso de sentimiento de velas japonesas basada en indicadores cuantitativos

CEI ADX RSI MACD VOLUME SMA
Fecha de creación: 2025-02-21 13:23:51 Última modificación: 2025-02-21 13:23:51
Copiar: 1 Número de Visitas: 361
2
Seguir
319
Seguidores

Estrategia de trading de tendencias de impulso de sentimiento de velas japonesas basada en indicadores cuantitativos Estrategia de trading de tendencias de impulso de sentimiento de velas japonesas basada en indicadores cuantitativos

Descripción general

La estrategia se basa en el análisis de la emoción del mercado en forma de gráficos para cuantificar la psicología del mercado a través de tres osciladores centrales: los osciladores de renuencia, los osciladores de miedo y los osciladores de avaricia. La estrategia integra indicadores de dinámica y tendencia, al tiempo que combina la confirmación de la transacción para construir un sistema de negociación completo. La estrategia es adecuada para los operadores que desean identificar oportunidades de negociación de alta probabilidad a través del análisis de la emoción del mercado.

Principio de estrategia

El núcleo de la estrategia es la construcción de tres oscilladores emocionales a través del análisis de las diferentes formas de los gráficos:

  1. Osciladores de indecisión - Medir la incertidumbre del mercado a través de las formas de las estrellas cruzadas y los giros
  2. Osciladores de miedo - para rastrear la emoción de la cabeza a través de los meteoritos, las líneas de suspensión y las formas de absorción de la caída
  3. Los oscilantes de la codicia - detección de la emoción múltiple a través de rayos de sol en la cabeza desnuda, cordones de cuello, tragos de avestruz y tres soldados blancos

El promedio de estos tres osciladores constituye el índice de emoción de los precios (CEI). Cuando el CEI supera diferentes valores, se activa una señal de negociación de más de un hueco y se confirma mediante el volumen de transacciones.

Ventajas estratégicas

  1. Análisis de la emoción sistematizado - Transformación del análisis subjetivo en indicadores objetivos a través de la forma de gráficos de coordenadas cuantitativas
  2. Mejora en la gestión de riesgos - incluye mecanismos como plazos máximos de tenencia, paradas de pérdidas y períodos de enfriamiento
  3. Mecanismo de recuperación flexible - cuando las operaciones se pierden, la estrategia intenta recuperarse mediante la ruptura del punto de equilibrio
  4. Aplicabilidad en varios mercados, como acciones, divisas y criptomonedas
  5. Alta fiabilidad de la señal - mejora la precisión mediante la confirmación de la cantidad de transacciones y la verificación de múltiples indicadores técnicos

Riesgo estratégico

  1. Sensibilidad de los parámetros - los ajustes de las diferentes clases de valores límite deben ser bien probados y optimizados
  2. Dependencia del entorno del mercado - puede generar señales erróneas en mercados convulsionados
  3. Riesgo de deslizamiento - riesgo de ejecución en mercados con poca liquidez
  4. Riesgo de exceso de transacciones - Se requiere un período de enfriamiento razonable para evitar transacciones frecuentes
  5. Riesgo sistémico - la posibilidad de sufrir grandes pérdidas en eventos importantes en el mercado

Dirección de optimización de la estrategia

  1. Las pérdidas dinámicas - ajuste automático de las pérdidas en función de la volatilidad del mercado
  2. Clasificación del estado del mercado - Mecanismo de identificación de mercados con aumento de tendencias y movimientos
  3. Optimización de aprendizaje automático - combinación de parámetros optimizados con algoritmos de aprendizaje automático
  4. Mejoras en la gestión de riesgos - agregado módulo de gestión de fondos y control de posiciones
  5. Filtración de señales - Integración de más indicadores técnicos para filtrar señales falsas

Resumir

Se trata de una estrategia innovadora que combina análisis técnico con operaciones cuantitativas. A través de un análisis de sentimiento sistematizado y una estricta gestión de riesgos, la estrategia es capaz de proporcionar señales de negociación confiables a los operadores. Si bien existe cierto espacio de optimización, el marco básico de la estrategia es sólido y adecuado para el desarrollo posterior y la aplicación en el mercado.

Código Fuente de la Estrategia
/*backtest
start: 2024-03-09 18:40:00
end: 2025-02-19 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Binance","currency":"SOL_USDT"}]
*/

//@version=6
strategy("Candle Emotion Index Strategy", shorttitle="CEI Strategy", overlay=true)

// User Inputs
length = input.int(14, title="Lookback Period", minval=1)
dojiThreshold = input.float(0.1, title="Doji Threshold", minval=0.01, maxval=0.5)
spinningTopThreshold = input.float(0.3, title="Spinning Top Threshold", minval=0.1, maxval=0.5)
shootingStarThreshold = input.float(0.5, title="Shooting Star Threshold", minval=0.1, maxval=1.0)
hangingManThreshold = input.float(0.5, title="Hanging Man Threshold", minval=0.1, maxval=1.0)
engulfingThreshold = input.float(0.5, title="Engulfing Threshold", minval=0.1, maxval=1.0)
marubozuThreshold = input.float(0.9, title="Marubozu Threshold", minval=0.5, maxval=1.0)
hammerThreshold = input.float(0.5, title="Hammer Threshold", minval=0.1, maxval=1.0)
threeWhiteSoldiersThreshold = input.float(0.5, title="Three White Soldiers Threshold", minval=0.1, maxval=1.0)

// Volume Multiplier Input
volumeMultiplier = input.float(1.5, title="Volume Multiplier", minval=1.0)

// Cooldown Period Input
cooldownPeriod = input.int(10, title="Cooldown Period (Candles)", minval=1)

// Maximum Holding Period Inputs
maxHoldingPeriod = input.int(20, title="Maximum Holding Period (Candles)", minval=1)
lossHoldingPeriod = input.int(10, title="Loss Exit Holding Period (Candles)", minval=1)
lossThreshold = input.float(0.02, title="Loss Threshold (as % of Entry Price)", minval=0.01, maxval=1.0)

// --- Indecision Oscillator Functions ---
isDoji(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    rangeSize = high - low
    bodySize / rangeSize < threshold

isSpinningTop(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    rangeSize = high - low
    bodySize / rangeSize < threshold and bodySize / rangeSize >= dojiThreshold

indecisionOscillator() =>
    var float dojiScore = 0.0
    var float spinningTopScore = 0.0
    for i = 1 to length
        if isDoji(open[i], close[i], high[i], low[i], dojiThreshold)
            dojiScore := dojiScore + 1.0
        if isSpinningTop(open[i], close[i], high[i], low[i], spinningTopThreshold)
            spinningTopScore := spinningTopScore + 1.0
    dojiScore := dojiScore / length
    spinningTopScore := spinningTopScore / length
    (dojiScore + spinningTopScore) / 2

// --- Fear Oscillator Functions ---
isShootingStar(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    upperWick = high - math.max(open, close)
    lowerWick = math.min(open, close) - low
    upperWick / bodySize > threshold and lowerWick < bodySize

isHangingMan(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    upperWick = high - math.max(open, close)
    lowerWick = math.min(open, close) - low
    lowerWick / bodySize > threshold and upperWick < bodySize

isBearishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)
    prevBodySize = math.abs(closePrev - openPrev)
    close < openPrev and open > closePrev and bodySize / prevBodySize > threshold

fearOscillator() =>
    var float shootingStarScore = 0.0
    var float hangingManScore = 0.0
    var float engulfingScore = 0.0
    for i = 1 to length
        if isShootingStar(open[i], close[i], high[i], low[i], shootingStarThreshold)
            shootingStarScore := shootingStarScore + 1.0
        if isHangingMan(open[i], close[i], high[i], low[i], hangingManThreshold)
            hangingManScore := hangingManScore + 1.0
        if isBearishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)
            engulfingScore := engulfingScore + 1.0
    shootingStarScore := shootingStarScore / length
    hangingManScore := hangingManScore / length
    engulfingScore := engulfingScore / length
    (shootingStarScore + hangingManScore + engulfingScore) / 3

// --- Greed Oscillator Functions ---
isMarubozu(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    totalRange = high - low
    bodySize / totalRange > threshold

isHammer(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    lowerWick = math.min(open, close) - low
    upperWick = high - math.max(open, close)
    lowerWick / bodySize > threshold and upperWick < bodySize

isBullishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)
    prevBodySize = math.abs(closePrev - openPrev)
    close > openPrev and open < closePrev and bodySize / prevBodySize > threshold

isThreeWhiteSoldiers(open, close, openPrev, closePrev, openPrev2, closePrev2, threshold) =>
    close > open and closePrev > openPrev and closePrev2 > openPrev2 and close > closePrev and closePrev > closePrev2

greedOscillator() =>
    var float marubozuScore = 0.0
    var float hammerScore = 0.0
    var float engulfingScore = 0.0
    var float soldiersScore = 0.0
    for i = 1 to length
        if isMarubozu(open[i], close[i], high[i], low[i], marubozuThreshold)
            marubozuScore := marubozuScore + 1.0
        if isHammer(open[i], close[i], high[i], low[i], hammerThreshold)
            hammerScore := hammerScore + 1.0
        if isBullishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)
            engulfingScore := engulfingScore + 1.0
        if isThreeWhiteSoldiers(open[i], close[i], open[i+1], close[i+1], open[i+2], close[i+2], threeWhiteSoldiersThreshold)
            soldiersScore := soldiersScore + 1.0
    marubozuScore := marubozuScore / length
    hammerScore := hammerScore / length
    engulfingScore := engulfingScore / length
    soldiersScore := soldiersScore / length
    (marubozuScore + hammerScore + engulfingScore + soldiersScore) / 4

// --- Final Calculations ---
indecision = indecisionOscillator()
fear = fearOscillator()
greed = greedOscillator()

// Calculate the average of the three oscillators
averageOscillator = (indecision + fear + greed) / 3

// --- Combined Strategy Logic ---
var float entryPriceLong = na
var float entryPriceShort = na
var int holdingPeriodLong = 0
var int holdingPeriodShort = 0
var int cooldownCounter = 0

// Buy Signal Logic for Long and Short
longBuySignal = ta.crossover(averageOscillator, 0.1)
shortBuySignal = ta.crossover(averageOscillator, 0.2)

// Calculate average volume over the lookback period
avgVolume = ta.sma(volume, length)

// Take Profit Conditions
longTakeProfitCondition = close > open and volume > avgVolume * volumeMultiplier
shortTakeProfitCondition = close < open and volume > avgVolume * volumeMultiplier

// Buy Logic for Long Positions
if longBuySignal and strategy.position_size == 0 and cooldownCounter <= 0
    entryPriceLong := close
    strategy.entry("Long Entry", strategy.long)
    cooldownCounter := cooldownPeriod
    holdingPeriodLong := 0

// Increment holding period if in a long position
if strategy.position_size > 0
    holdingPeriodLong := holdingPeriodLong + 1

// Sell Logic for Long Positions
if longTakeProfitCondition and strategy.position_size > 0 and close > entryPriceLong
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodLong >= maxHoldingPeriod and strategy.position_size > 0 and close >= entryPriceLong
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodLong >= lossHoldingPeriod and strategy.position_size > 0 and close < entryPriceLong * (1 - lossThreshold)
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// Short Logic for Short Positions
if shortBuySignal and strategy.position_size == 0 and cooldownCounter <= 0
    entryPriceShort := close
    strategy.entry("Short Entry", strategy.short)
    cooldownCounter := cooldownPeriod
    holdingPeriodShort := 0

// Increment holding period if in a short position
if strategy.position_size < 0
    holdingPeriodShort := holdingPeriodShort + 1

// Cover Logic for Short Positions
if shortTakeProfitCondition and strategy.position_size < 0 and close < entryPriceShort
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodShort >= maxHoldingPeriod and strategy.position_size < 0 and close <= entryPriceShort
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodShort >= lossHoldingPeriod and strategy.position_size < 0 and close > entryPriceShort * (1 + lossThreshold)
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// Decrement the cooldown counter each candle
if cooldownCounter > 0
    cooldownCounter := cooldownCounter - 1