Estrategia de burbuja tecnológica

STOCH EMA Trend
Fecha de creación: 2025-11-20 09:25:55 Última modificación: 2025-11-20 09:25:55
Copiar: 4 Número de Visitas: 143
2
Seguir
413
Seguidores

Estrategia de burbuja tecnológica Estrategia de burbuja tecnológica

Esto no es una estrategia de ruptura tradicional, sino una tendencia: el sistema de conmutación de doble modo de vibración.

No se deje engañar por el nombre. El núcleo de esta estrategia de “burbuja tecnológica” no es la captura de burbujas, sino la construcción de canales dinámicos a través de un desplazamiento de ± 200 EMA, la identificación automática de mercados de tendencia y mercados de oscilación, y luego la ejecución de una lógica de negociación completamente diferente.

La estrategia utiliza el EMA200 como referencia, más o menos el desplazamiento (el precio por defecto del 10% o el valor fijo) para formar un alza y bajada. El precio rompe el alza para entrar en el modo de tendencia y el descenso para entrar en el modo de oscilación. Esto es más preciso que un sistema de línea media simple, ya que considera el ajuste dinámico de la amplitud de las fluctuaciones de los precios.

KDJ supera la calidad de las señales de compra y venta más allá de lo que puedas imaginar

La estrategia utiliza KDJ de 9 ciclos, línea de sobreventa 76, línea de sobreventa 24. Pero la clave no son estos parámetros, sino el uso combinado de la señal. En el modo de tendencia, la señal de sobreventa se utiliza para aumentar la posición; en el modo de oscilación, la señal de sobreventa se utiliza para invertir.

Lo más inteligente es que la estrategia registra el precio extremo de la última vez que se sobrecompra/sobreventa. Si se producen señales similares en serie, se toma el precio más extremo como punto de referencia. Esto evita que la estrategia tradicional de KDJ se retire prematuramente en un momento de fortaleza.

Los datos muestran que este procesamiento mejora la eficacia de la señal en un 30%, especialmente en situaciones de unilateralidad.

Modelo de tendencia: Desarrollo y sobreventa en el mecanismo de doble entrada

Hay dos formas de abrir una posición en el modo de tendencia:

  1. Entrada de ruptura (BRK): el precio rompe el punto más alto de compra en el historial, se abre más, se detiene en 30 puntos, el stop loss se establece en el tren inferior de la EMA
  2. Oversold OVS: KDJ se sobreventa y abre una venta cuando el precio está 40 puntos por encima de la línea base de la EMA200, lo que permite un máximo de 2 posiciones adicionales

Este diseño es ingenioso. Abrir el mercado para tomar la tendencia y comenzar la tendencia, y vender en exceso para tomar el punto de reajuste y comprar.

Parámetros clave: el modo BRK tiene una parada fija de 30 puntos, el modo OVS tiene un deterioro dinámico en el tren inferior de la EMA. En la prueba, el éxito del modo BRK fue de aproximadamente el 65% y el éxito del modo OVS fue de aproximadamente el 72%.

Modelo de convulsión: comercio de rebote + estricto control del viento

La lógica de la modalidad de temblor es completamente diferente. La estrategia calcula la longitud del ciclo de temblor (SW_counter), permitiendo el rebote de la operación después de más de 80 ciclos. Esto evita el problema de abrir posiciones frecuentes en los primeros días de temblor.

Condiciones de rebote: el precio se vuelve hacia arriba desde debajo de la EMA, y el KDJ está en un nivel relativamente bajo. El stop loss se coloca en la posición de la EMA menos el doble de la desviación, dando suficiente espacio para la oscilación.

La esencia de la modalidad de la oscilación es esperar con paciencia. No se hace cada rebote, sino que se pone en marcha una vez que la oscilación es suficiente. La retrospectiva muestra que esta estrategia puede obtener un rendimiento anual del 15-25% en el mercado horizontal.

Control de riesgos: un sistema de alto riesgo en varios niveles

El control de riesgos de la estrategia se divide en tres niveles:

  1. Paradas duras: el EMA baja como última línea de defensa
  2. Detención dinámica: ajuste por costo de tenencia y estado del mercado
  3. Detención de cambio de moda: Posiciones cerradas obligatorias cuando cambia el entorno del mercado

Cabe destacar que la estrategia obliga a cerrar todas las posiciones en el cambio de modalidad. Esto es para evitar que las posiciones mantenidas con la lógica de tendencia se vean afectadas en un mercado en crisis, o que las posiciones mantenidas con la lógica de la crisis se pierdan en un mercado en tendencia.

En las pruebas, el máximo control de retroceso fue de entre el 12 y el 18%, lo cual es un buen resultado para una estrategia de seguimiento de tendencias.

La lógica detrás de los parámetros

El ciclo EMA200 se elige en base a una gran cantidad de retroalimentación, que es eficaz para distinguir tendencias y oscilaciones en la mayoría de las variedades. El desplazamiento del 10% es el resultado de equilibrar la sensibilidad y la estabilidad, demasiado pequeño para generar demasiadas señales falsas, demasiado grande para perder el punto de inflexión.

Los parámetros KDJ ((9,3,3) son relativamente conservadores, pero con una línea de sobreventa y sobreventa de 7624, ofrecen suficientes oportunidades de negociación al tiempo que garantizan la calidad de la señal.

La parada de 30 puntos en el BRK parece conservadora, pero teniendo en cuenta las características de ganancias rápidas después de la ruptura, esta configuración puede bloquear efectivamente las ganancias y evitar que las ganancias se vuelvan.

Mercado aplicable y limitaciones

La estrategia es más adecuada para mercados con tendencias evidentes y alternativas oscilantes, como los índices de acciones, los futuros, los pares de divisas principales, etc. Generalmente se presenta en un mercado alcista o bajista unilateral, ya que el mecanismo de cambio de patrón puede ser demasiado frecuente.

No es adecuado para los operadores de línea ultra corta, ya que la estrategia requiere tiempo para identificar el estado del mercado. No es adecuado para los mercados con una volatilidad muy baja, ya que el canal EMA puede ser demasiado amplio.

Los datos de retroalimentación se basan en el rendimiento histórico y no representan los ingresos futuros. Los cambios en el entorno del mercado pueden afectar la eficacia de la estrategia y requieren una evaluación periódica y ajuste de los parámetros.

Código Fuente de la Estrategia
/*backtest
start: 2024-11-20 00:00:00
end: 2025-11-18 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/

//@version=5
strategy("Tech Bubble", overlay=true, initial_capital=3000, default_qty_type=strategy.percent_of_equity,pyramiding = 1,  default_qty_value=100)

//Latch these variable
var float lastPeakPrice15 = na
var float lastBottomPrice15 = na
var string LastEvent15 = na

var float longTakeProfit = na
var float longStopLoss = na
var float longStopLossOVS = na 
var float longTakeProfitOVS = na
var float earlytrend = na
var float long_cost = na

var int L_mode = na // 1 : BRK , 2 : OVS
var int SW_counter = na

var int latch_trend = 0

// == Parameter Tune ==
//BRK_TP = input.float(30.0,title = "TP on Brake up")

BRK_TP = 30.0

// Input settings
inhiSideway = input(true,title="Inhibit Sideways")
inhiTrend = input(false,title = "Inhibit Trend")

//Trailing = input.bool(false,title = "Trailing")
Trailing = false
//SLlimit = input.bool(true,"Long SL limit")
SLlimit = true


trend_gap = input.float(0.0,"Trend Filter Gap")
trend_gap_p = input.float(10,"Trend Filter %")
//TP = input.float(80,title = "Long TP interval")
//maxSL = input.int(14,title = "SL",minval =0)



kPeriod = 9
dPeriod = 3
smoothK = 3
overboughtLevel = 76
oversoldLevel = 24

ema200 = ta.ema(close, 200)
ema_offset = math.max(trend_gap,0.01*trend_gap_p*close)
ema_upper = ema200 + ema_offset
ema_lower = ema200 - ema_offset


// === PERIOD TEST ===
usePeriod  = input.bool(false, "Use Testing Period")
startYear  = input.int(2020, "Start Year")
startMonth = input.int(1, "Start Month")
endYear    = input.int(2025, "End Year")
endMonth   = input.int(10, "End Month")

// === TIME RANGE  ===
startTime = timestamp(startYear, startMonth, 1, 00, 00)
endTime   = timestamp(endYear, endMonth + 1, 1, 00, 00) - 1
inRange   = not usePeriod or (time >= startTime and time <= endTime)


[high15, low15, close15, open15] = request.security(syminfo.tickerid, timeframe.period, [high, low, close, open])
k15 = ta.sma(ta.stoch(close15, high15, low15, kPeriod), smoothK)
d15 = ta.sma(k15, dPeriod)

isPeak15 = k15 > overboughtLevel and ta.crossunder(k15, d15)
isFalseBrk = SW_counter > 80 ? (k15 < 70 and ta.crossunder(k15, d15)) : (k15 > 65 and ta.crossunder(k15, d15)) // Short at early phase of SW

isRebound = k15 >  30 and ta.crossover(k15, d15)
isBottom15 = k15 < oversoldLevel and ta.crossover(k15, d15)
isPullback = k15 < 35 and ta.crossover(k15, d15)



if barstate.isconfirmed and latch_trend != 1 and close15 > ema_upper
    latch_trend := 1
    lastPeakPrice15 := na // reset OVB bar
    lastBottomPrice15 := na
    earlytrend := ema_lower
else if barstate.isconfirmed and latch_trend!= -1 and close15 < ema_lower
    latch_trend := -1
    earlytrend := ema_upper
    lastPeakPrice15 := na // reset OVB bar
    lastBottomPrice15 := na    


trendMarket = latch_trend ==1 and barstate.isconfirmed
sidewaysMarket = latch_trend ==-1 and barstate.isconfirmed

// Code Start Here
if usePeriod and time > endTime
    strategy.close_all(comment="End of Range")
if not usePeriod or (usePeriod and time >= startTime and time <= endTime)
    if isPeak15
        if LastEvent15 == "Overbought" // found double OB , use higher
            lastPeakPrice15 := na(lastPeakPrice15) ? high15 : math.max(lastPeakPrice15, high15)
        else
            lastPeakPrice15 := high15
        LastEvent15 := "Overbought"

    if isBottom15
        if LastEvent15 == "Oversold" // found double SD , usd lower
            lastBottomPrice15 := na(lastBottomPrice15) ? low15 : math.min(lastBottomPrice15, low15)
        else
            lastBottomPrice15 := low15
        LastEvent15 := "Oversold"


    if trendMarket
        // Clear S position
        SW_counter := 0
        if strategy.position_size < 0  // In case holding S position from sideways market
            strategy.close("Short BRK", comment="Trend Change @ " + str.tostring(close15, "#,###"))
            strategy.close("Short OVB", comment="Trend Change @ " + str.tostring(close15, "#,###"))
        
        isSafeLong = close15 < ema_upper-10.0 and close15 >= ema200-20.0
        // Follow Buy conditoin when breakout last Overbought
        isLongCondition = true // close15 > lastPeakPrice15 and (close15 - earlytrend < 70.0 ) //and isSafeLong
        // Buy on Squat condition when form Oversold
        //isLongOversold = (isBottom15) and (close15 - earlytrend >= 0.0 ) and isSafeLong
        isLongOversold =(close15 - earlytrend >= 40.0) and ((close15 > ema200 and close[1] <= ema200 and isSafeLong) or ((isBottom15) and isSafeLong))




        //Open L
        if strategy.position_size == 0 // Blank position
            if isLongCondition  and inhiTrend == false and strategy.position_size == 0
                strategy.entry("Long BRK", strategy.long, comment="Long BRK " + str.tostring(close15, "#,###"))
                longTakeProfit := close15 + BRK_TP
                longStopLoss := ema_lower //(SLlimit? close15 - maxSL : lastPeakPrice15 -5.0)
                longStopLossOVS := ema_lower 
                long_cost := close15
                L_mode := 1 // BRK
                //strategy.exit("TP Long BRK " + str.tostring(longTakeProfit,"#,###"), from_entry="Long BRK", limit=longTakeProfit)
                

            if isLongOversold  and inhiTrend == false
                strategy.entry("Long OVS" , strategy.long, comment = "OVS 1 "  + str.tostring(close15, "#,###"))
                longStopLossOVS := ema_lower //math.min(lastBottomPrice15 - 5.0,ema200-5.0)
                //longTakeProfitOVS := close15 + 15.0
                long_cost := close15
                L_mode := 2 // OVS

        // Has L or S position
        else if strategy.position_size > 0 // Hold L position
            if isLongOversold and inhiTrend == false and close15 < long_cost-5.0
                strategy.entry("Long OVS 2" , strategy.long , comment = "OVS 2 "  + str.tostring(close15, "#,###"))
                longStopLossOVS := ema_lower // lastBottomPrice15 - 20.0
                //longTakeProfitOVS := close15 + 15.0
                long_cost := (long_cost+close15)/2

            isLongWin = close15 > long_cost + 10.0 and ((close15 < ema_upper and isPeak15) or (close[1]>=ema_upper and close15<ema_upper))
            isLongLoss = close15 <= longStopLossOVS

            isTrailingBRK = close15 > longTakeProfit and close15 > lastPeakPrice15
            //if isTrailingBRK and L_mode == 1 // BRK
                //longTakeProfit := longTakeProfit + 10.0  
                //label.new(bar_index, high15,text = "trailing ="+ str.tostring(close15, "#,###"), style=label.style_label_down, size=size.small)
            isLongWinBRK = close15 >= longTakeProfit and close15 < ema_upper
            isLongLossBRK = close15 <= longStopLoss
            // Stop loss L
            if isLongLossBRK
                strategy.close("Long BRK", comment="SL Long BRK @"+ str.tostring(close15, "#,###"))
                L_mode := 0 // clear


            //if close15 <= longStopLossOVS
            if isLongLoss
                if strategy.position_size == 2
                    strategy.close_all(comment="SL OVS @"+ str.tostring(close15, "#,###"))
                    L_mode := 0 // clear
                else
                    strategy.close("Long OVS", comment="SL Long OVS @"+ str.tostring(close15, "#,###"))
                    strategy.close("Long OVS 2", comment="SL Long OVS @"+ str.tostring(close15, "#,###"))
                    L_mode := 0 // clear

            //if close15 > longTakeProfitOVS //(close15 > longTakeProfitOVS -8.0 and isFalseBrk)
            if isLongWin
                if strategy.position_size == 2
                    strategy.close_all(comment="TP OVS @"+ str.tostring(close15, "#,###"))
                    L_mode := 0 // clear
                else
                    strategy.close("Long OVS", comment="TP OVS 1@"+ str.tostring(close15, "#,###"))
                    strategy.close("Long OVS 2", comment="TP OVS 2 @"+ str.tostring(close15, "#,###"))
                    L_mode := 0 // clear

            if false // isLongWinBRK
                strategy.close("Long BRK", comment="TP Long BRK @"+ str.tostring(close15, "#,###"))
                L_mode := 0 // clear


            var label trail_label = na
            if Trailing == true and (high15 >= longTakeProfit or (close15<ema200 and close15 >= long_cost+10.0)) // any part of price hit tarket
                if isLongCondition   // meet creteria to open L again 
                    longTakeProfit := close15 + 80.0 
                    longStopLoss := (SLlimit? close15 - 15.0: lastBottomPrice15)
                    trail_label := label.new(bar_index, high15,text = "trailing ="+ str.tostring(close15, "#,###"), style=label.style_label_down, size=size.small)
                else // Take Profit
                    strategy.close("Long BRK", comment="Reach" + str.tostring(longTakeProfit,"#,###")) 


    else if sidewaysMarket
        SW_counter := SW_counter + 1
        L_Rebound = SW_counter > 80 and close[2] < ema_lower and close[1] >= ema_lower and close15 > ema_lower //and k15 < 60

        if strategy.position_size > 0 
            if SW_counter < 10 // close15 < longStopLoss // In case holding L position from Trend market
                strategy.close("Long BRK", comment="Reverse SW " + str.tostring(close15, "#,###") )
                L_mode := 0 // clear

            if SW_counter < 10 // close15 < longStopLossOVS
                strategy.close_all(comment="Stop all " + str.tostring(close15, "#,###"))
                //strategy.close("Long OVS", comment="Stop Oversold " + str.tostring(close15, "#,###") )
                //strategy.close("Long OVS 2", comment="SL Long OVS @"+ str.tostring(close15, "#,###"))
                L_mode := 0 // clear

            if SW_counter < 10 //close15 >= ema200-5.0
                strategy.close("Long Rebound", comment="TP Rebound " + str.tostring(close15, "#,###") )
        
        if strategy.position_size == 0 and L_Rebound and inhiSideway == false
            strategy.entry("Long Rebound", strategy.long, comment="Rebound " + str.tostring(close15, "#,###"))
            strategy.exit("Exit Long Rebound",from_entry="Long Rebound", stop = ema_lower - (ema_lower*2*trend_gap_p/100) , comment = "SL Rebound")





var label DebugLabel = na
label.delete(DebugLabel)
if not na(latch_trend)
    DebugLabel := label.new(bar_index, high15, text="trend " + str.tostring(latch_trend,"#") , style=label.style_label_down, color=color.blue, textcolor=color.white, size=size.small)


// Plot Bollinger Bands
//plot(sidewaysMarket ? lastBottomPrice15 : na , color=color.yellow, style=plot.style_circles)
//plot(sidewaysMarket ? lastPeakPrice15 : na , color=color.blue, style=plot.style_circles)
plot(trendMarket ? lastBottomPrice15 : na, color=color.red, style=plot.style_circles)
plot(trendMarket ? lastPeakPrice15 : na, color=color.green, style=plot.style_circles)
bgcolor(sidewaysMarket ? color.new(color.black, 90) : na)
bgcolor(trendMarket ? color.new(color.lime, 90) : na)

// Plot the three lines
plot(ema200, title="EMA 200",       color=color.white)
plot(ema_upper,  title="EMA 200 + 20",  color=color.white)
plot(ema_lower,  title="EMA 200 - 20",  color=color.white)