Estrategia cuantitativa de supertendencia MACD


Fecha de creación: 2023-12-26 11:13:24 Última modificación: 2023-12-26 11:13:24
Copiar: 0 Número de Visitas: 792
1
Seguir
1621
Seguidores

Estrategia cuantitativa de supertendencia MACD

Descripción general

La estrategia utiliza la combinación de las señales potenciales de cambio de tendencia del indicador de tendencia y el indicador MACD, junto con las señales de compra y venta del indicador RSI, para formar un sistema de señales de apertura y de cierre de posición más estable y eficiente. La estrategia se llama estrategia de cuantificación de la tendencia MACD.

Principio de estrategia

La lógica central de esta estrategia es la combinación de la utilización de los indicadores de hipertrend y MACD como criterios para la apertura de posiciones.

En la parte de ultratrend, la estrategia utiliza el cambio de dirección del indicador de ultratrend como una señal de reversión potencial. Cuando la dirección del indicador de ultratrend cambia de arriba hacia abajo, genera una señal de compra; cuando la dirección del indicador de ultratrend cambia de abajo hacia arriba, genera una señal de venta.

En la parte del MACD, la estrategia utiliza la pendiente y el cruce del eje cero del indicador MACD en un marco de tiempo más bajo (la línea del sol) para juzgar la oportunidad de una posible reversión. Se produce una señal cuando la pendiente del MACD es mayor que el valor absoluto (mayor que el umbral) y la pendiente se mantiene igual al alza; también se produce una señal auxiliar si el indicador MACD cruza el eje cero.

En la señal de apertura de posición, la estrategia requiere que la señal de tendencia superior y la señal MACD se mantengan en la misma dirección para que se emita la instrucción de apertura de posición.

Además, la estrategia en la parte de posición baja también introduce una señal de sobreventa y sobreventa en el indicador RSI. Cuando el indicador RSI es mayor que 80, genera una señal de venta, y cuando es menor que 20, genera una señal de compra, para ayudar a determinar el momento de la reversión.

Análisis de las ventajas

La mayor ventaja de esta estrategia reside en la diversidad de las señales indicadoras. Las diferentes señales pueden complementarse entre sí, lo que hace que la señal general sea más estable y confiable.

La señal de reversión de un indicador de tendencia super puede capturar una tendencia a corto plazo más fuerte; la pendiente MACD puede determinar la fuerza de la tendencia a medio y largo plazo y evitar ser engañada por una falsa reversión; y el RSI puede indicar el mejor momento para abrir una posición y una posición para comprar y vender en un período de oscilación. La superposición de varias señales de indicadores puede filtrar algunos intercambios ruidosos y obtener una mayor tasa de ganancia.

Además, el marco de tiempo de la estrategia también es más razonable. La supertrend utiliza un marco de tiempo de horas, y el indicador MACD utiliza un reloj de sol, lo que garantiza la frecuencia de negociación y la estabilidad de los juicios de tendencia.

Análisis de riesgos

El principal riesgo de esta estrategia es la alta probabilidad de que se produzcan señales de confusión entre los indicadores. Por ejemplo, una tendencia hiper puede generar un falso reverso, mientras que la señal MACD no se produce en sincronía. Esto puede causar pérdidas innecesarias.

Además, el RSI puede ser usado para determinar el momento de la posición baja demasiado pronto o demasiado tarde, lo que hace que la estrategia no pueda maximizar el tiempo de mantenimiento de la posición.

Por último, el exceso de ajuste del umbral de inclinación del MACD también puede conducir a la pérdida de una oportunidad de reversión más débil.

Dirección de optimización

La estrategia puede ser optimizada en los siguientes aspectos:

  1. Introducción de un mecanismo de suspensión de pérdidas cuando las pérdidas superan una cierta proporción.

  2. La inclinación del MACD se determina mediante la inclinación de la inclinación de la inclinación de la inclinación.

  3. Para el indicador RSI, se incluye la condición de reajuste para determinar la posición en equilibrio. Es decir, se requiere una reajuste obvio y se considera la posición en equilibrio una vez que el RSI supera los 80.

  4. Testing MACD with volume and see if it improves signal reliability

  5. Trying automated parameter tuning to find optimal settings

Resumir

La estrategia cuantitativa MACD de trayectoria por encima de la tendencia combina varios indicadores para proporcionar señales de apertura de posición y de posición. Sus ventajas son la estabilidad de la señal, la alta tasa de victoria, que se puede mejorar aún más mediante la optimización de los parámetros. La dirección de riesgo y optimización también se centra principalmente en el problema de la configuración de parámetros de overfitting. En general, la estrategia tiene un gran valor de aplicación en la guerra.

Código Fuente de la Estrategia
/*backtest
start: 2022-12-19 00:00:00
end: 2023-12-25 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5

strategy("SuperTrend.MACD Strategy", overlay=false, default_qty_type=strategy.percent_of_equity, default_qty_value=100, initial_capital=100000, pyramiding=5, process_orders_on_close=true)

// ---------------- Utility Functions ----------------
getArrayValue(float[] arr, int ago) =>
    if ago >= 0
        array.get(arr, ago >= array.size(arr) ? na: array.size(arr) + -1 * ago -1)
    else
        na

filterNA(float[] a, s, int y) =>
    int x = 0
    if not na(s[0])
        array.push(a, s[0])
        if array.size(a) > y
            array.shift(a)
    a

pine_rsi(float[] x, int y) =>
    x0 = getArrayValue(x, 0)
    x1 = getArrayValue(x, 1)

    u = math.max(x0 - x1, 0) // upward ta.change
    d = math.max(x1 - x0, 0) // downward ta.change
    rs = ta.rma(u, y) / ta.rma(d, y)
    res = 100 - 100 / (1 + rs)
    res

turnAround(float[] arr) =>
    int isTurnAround = 0
    
    now = getArrayValue(arr, 0)
    p1 = getArrayValue(arr, 1)
    p2 = getArrayValue(arr, 2)

    if p1 > now and p1 > p2
        isTurnAround := -1
    else if p1 < now and p1 < p2
        isTurnAround := 1

intergerizeSignal(i) =>
    i>0 ? 1 : i<0 ? -1 : 0

linreg(float[] y, int n, int offset=0) => 
    float slope = na
    float intercept = na

    int endcursor = offset + n - 1

    if array.size(y) > endcursor
        float sumX = 0
        float sumX2 = 0
        float sumY = 0
        float sumY2 = 0
        float sumXY = 0

        for i=offset to endcursor
            yv = array.get(y, i)
            sumY += yv
            sumY2 += math.pow(yv, 2)
            sumX += i
            sumX2 += math.pow(i, 2)
            sumXY += i*yv

        // Pearson correlation coefficient
        r = (n * sumXY - sumX * sumY) / math.sqrt((n * sumY2 - math.pow(sumY, 2)) * (n * sumX2 - math.pow(sumX, 2)))

        // Coefficient of determination
        r2 = math.pow(r, 2)

        meanX = sumX / n
        meanY = sumY / n

        slope := (n * sumXY - sumX * sumY) / (n * sumX2 - math.pow(sumX, 2))
        intercept := meanY - slope * meanX

    [slope, intercept]

isStartOfDay() => dayofweek != dayofweek[1]

// ---------------- Variables ----------------

varip float st_signal = 0
varip float macd_signal = 0
varip float macd_close_signal = 0
varip float histo_signal = 0

var int openSignal = 0
var int closeSignal = 0

// -------------------------------- Supertrend Signal (Open) --------------------------------

// ST calculation
atrPeriod = input(10, "Supertrend ATR Length")
factor = input.float(2.0, "Supertrend Factor", step = 0.01)

[_, direction] = ta.supertrend(factor, atrPeriod)

st_direction_change = ta.change(direction)
if st_direction_change < 0
    st_signal := 4
if st_direction_change > 0
    st_signal := -4

// -------------------------------- MACD Signal (Open + Close) --------------------------------

// MACD Calculation
fastLength = input(12, title="MACD Fast Length")
slowLength = input(26, title="MACD Slow Length")
signalLength = input(9, title="MACD Signal Length")
macdSlowTimeframe = input.timeframe("D", "MACD Timeframe")
macdSlopeLookbackOpen = input(7, title="MACD Slope Lookback - Open")
macdSlopeLookbackClose = input(3, title="MACD Slope Lookback - Close")

dailyClose = request.security(syminfo.tickerid, macdSlowTimeframe, close, barmerge.gaps_on)
[macdLine, signalLine, _] = ta.macd(dailyClose, fastLength, slowLength, signalLength)

// MACD Slope calculation

varip macdHistory = array.new<float>(0)
varip macdSlowSlopeArr = array.new<float>(0)
varip float macdSlowSlope = na
varip float macdCloseSlope = na

if not na(macdLine[0])
    array.push(macdHistory, macdLine[0])
    if array.size(macdHistory) > macdSlopeLookbackOpen
        array.shift(macdHistory)
    [s1, _] = linreg(macdHistory, macdSlopeLookbackOpen)
    macdSlowSlope := s1

    array.push(macdSlowSlopeArr, macdSlowSlope)
    if array.size(macdSlowSlopeArr) > macdSlopeLookbackClose
        array.shift(macdSlowSlopeArr)
    [s2, _] = linreg(macdSlowSlopeArr, macdSlopeLookbackClose)
    macdCloseSlope := s2

// MACD Signal Calculation
// > open signal
threshold_macdSlowSlope = input.float(0.75, "MACD Slope Open Threshold", step = 0.05)

macdSlowSlopeOverThreshold = math.abs(macdSlowSlope) >= threshold_macdSlowSlope
macdSlowSlopeTrend = macdSlowSlope - getArrayValue(macdSlowSlopeArr, 1)
macdSlowSlopeTrendConfirm = macdSlowSlope*macdSlowSlopeTrend >0

if (macdSlowSlopeOverThreshold and macdSlowSlopeTrendConfirm)
    macd_signal := 3*macdSlowSlope/math.abs(macdSlowSlope)
else
    macd_signal := 0

// > close signal
int macdCloseSignal = 0
macdCloseSignal := intergerizeSignal(macdCloseSlope)

// Histogram signal Calculation
histSlow = macdLine - signalLine

if (ta.crossover(histSlow, 0))
	histo_signal := 2
if (ta.crossunder(histSlow, 0))
	histo_signal := -2

// -------------------------------- RSI Signal (Close) --------------------------------
int rsiCloseSignal = 0
varip float rsiSlow = na

rsiPeriod = input(14, title="RSI Period")

varip dailyCloseRSIFilter = array.new_float()

// rewrite pine_rsi to remove NaN value from series at calculation
dailyCloseRSIFilter := filterNA(dailyCloseRSIFilter, dailyClose, rsiPeriod)

if not na(dailyClose[0])
    rsiSlow := pine_rsi(dailyCloseRSIFilter, rsiPeriod)

if rsiSlow > 80
    rsiCloseSignal := -1
else if rsiSlow < 20
    rsiCloseSignal := 1
else
    rsiCloseSignal := 0

// -------------------------------- Overall Signal --------------------------------

// Close signal
closeSignals = array.from(macdCloseSignal, rsiCloseSignal)
closeSignal := array.includes(closeSignals, 1) ? 1 : array.includes(closeSignals, -1) ? -1 : 0
closeSignal := closeSignal * 5

// Open signal
if (macd_signal * st_signal > 0) and (macd_signal * macd_close_signal >= 0)
    openSignal := intergerizeSignal(st_signal)
    openSignal := openSignal * 6
else
    openSignal := 0

// -------------------------------- Order --------------------------------
// if strategy.position_size == 0
if openSignal * closeSignal >=0
    if openSignal > 0
        strategy.entry("Long Entry", strategy.long)
    else if openSignal < 0
        strategy.entry("Short Entry", strategy.short)

if strategy.position_size != 0
    if closeSignal < 0
        strategy.close("Long Entry")
    if closeSignal > 0
        strategy.close("Short Entry")


// -------------------------------- Plot --------------------------------

plot(closeSignal, title="Close Signal", color=color.red, linewidth = 1, style=plot.style_area)
plot(openSignal, title="Open Signal", color=color.green, linewidth = 1, style=plot.style_area)
plot(st_signal, title="ST Signal", color=color.black, linewidth = 1, style=plot.style_circles)
plot(macd_signal, title="MACD Signal", color=color.blue, linewidth = 1, style=plot.style_circles)
// plot(macdSlowSlope, title="macd slow slope", color=color.purple, linewidth = 1, style=plot.style_line)
// plot(macdCloseSlope, title="macd slow slope", color=color.lime, linewidth = 1, style=plot.style_line)

hline(0, "Zero Line", color=color.gray)