Saltar al contenido

Wyckoff: Detección del creek y su rotura

    Portada

    Muchos me habéis pedido si era posible sacar el creek de Wyckoff programando, así que ya tocaba hacer un artículo explicando como hacerlo y, lógicamente, que funcione para cualquier valor con el que estemos trabajando.

    He conocido varias personas que hacen trading utilizando Wyckoff con muy buenos resultados. Uno de ellos es Rubén Villarmosa que tiene varios libros sobre Wyckoff y un canal de Youtube sobre el tema que no os podéis perder; y otro es Ferran Font que lo usa mucho en sus cursos y que tiene un magnífico video explicando qué es el creek de y como usarlo.

    He de decir que para calcular el creek nos vamos a basar un poco en conceptos matemáticos pero estar tranquilos, son muy simples, de los que dan los niños en el colegio, así que no preocuparse.

    No me entretengo más, vamos al lio.

    ¿Qué es el creek de Wyckoff?

    El creek es una formación de velas que se observa en los gráficos de precios de las acciones. Richard Wyckoff le puso este nombre, creek, que significa arroyo o rio en inglés, debido a que su formación se asemeja a los meandros que hace un rio.

    He encontrado un gráfico en PCBolsa en el que se ve muy bien qué es el creek y el momento de la rotura, que es donde entraríamos:

    Gráfica con análisis de Wyckoff

    Al final son roturas de canales, con suficientemente volumen para entender que va a haber un cambio de tendencia. No voy a entrar a explicar en detalle como se hace trading con esta técnica ya que, como os dije, hay grandes expertos en este tema que lo explican mucho mejor que yo. Así que si no tenéis claro como funciona os recomiendo los enlaces que he puesto en la introducción.

    Para hacer trading con el creek lo primero es identificar cual es el creek lo que parece difícil hacerlo mediante programación, pero es vital si queremos crear un robot que lo haga, así que vamos a ver como nos apañamos no solo para dibujarlo sino para tener una forma de usarlo en el trading algorítmico.

    Librerías y descarga de datos

    Vamos a empezar como siempre, con las librerías que necesitaremos para hacer nuestro código, y también descargando los datos necesarios para poder hacer nuestros cálculos con las gráficas.

    Las librerías que vamos a necesitar son estas:

    import yfinance as yf
    import matplotlib.pyplot as plt
    import numpy as np
    import scipy.signal

    La que más nos puede llamar la atención de todas ellas es “scipy.signal” que es la que utilizaremos para determinar cuando hay un pico significativo, pero eso lo veremos más adelante.

    Para descargar los datos utilizamos yfinance, así que lo vamos a hacer así:

    TICKER = "AAPL"
    ticker_values = yf.Ticker(TICKER)
    data = ticker_values.history(period="3mo")

    Vamos a usar nuestro querido Apple para hacer las pruebas, así que nos descargamos los datos diarios de tres meses, que considero el margen necesario para determinar un creek (podéis probar con más o menos datos, pero yo en gráfico diario me parece el más acertado).

    Ahora vamos a quedarnos con las columnas necesarias para este ejercicio:

    # Quitamos las fechas para hacerlo más fácil
    data = data.reset_index()
    data = data[['Close']]

    Hacemos un reset del index, ya que en este caso no me interesa para nada la fecha, pero si tener un índice con una numeración seguida (también entenderemos el por qué más adelante), así que hacemos el reset del index y quedan ya los datos como los necesito.

    Por otro lado, aunque podía coger la información del volumen para determinar si la rotura del creek es consistente, ahora me voy a centrar solo en conseguir determinar si un precio puede romper el creek o no, así que me quedo solo con el precio de cierre.

    Vamos a dibujar la gráfica así tenemos claro que es lo que tenemos:

    plt.plot(data)
    plt.title(TICKER)
    plt.xlabel('Unidades de tiempo')
    plt.ylabel('Precio')
    plt.show()

    Y nos devuelve esto:

    grafica normal

    Perfecto, ya tenemos los datos que necesitamos así que ahora vamos a intentar sacar cual sería el creek, empezaremos por el canal alcista.

    Buscamos los picos

    Aquí es donde utilizamos la librería de Scipy que hemos importado al principio.

    picos, picos_dict = scipy.signal.find_peaks(data['Close'], width=1)
    print(f"Picos: {(picos)}")

    Como veis usamos la función “find_peaks” al que le pasamos nuestros precios de cierre y al que también le pasamos como argumento “width=1” para decirle que queremos una secuencia de un array. El resultado sería así:

    picos

    Además como podéis ver, también nos devuelve otra variable con unos valores en un diccionario:

    picos dict

    De todos los valores que vemos en el diccionario el que nos interesa a nosotros es el de “prominences” que nos devuelve cuanto destaca un pico de la linea base que tiene alrededor, y se mide como la distancia vertical que tiene entre su pico el valor más bajo.

    Sabiendo esto vamos a coger los dos valores más prominentes para poder trazar una recta:

    indice_pico1 = picos[np.argmax(picos_prominentes)]
    indice_pico2 = picos[np.argpartition(picos_prominentes,-2)[-2]]

    Y aquí ya tendremos la posición de los dos picos dentro del array de picos prominentes (que en este caso son las posiciones 18 y 45). Así que ya tendremos dos puntos que es lo que siempre necesitamos para trazar una recta.

    Ecuación de la recta

    Ahora vamos un poco con las matemáticas y a refrescar como se hacía una recta de forma matemática. Esto es lo que nos va a servir a nosotros para poder dibujar una recta y luego conseguir cualquier valor a través de esa ecuación.

    La ecuación de la recta se representa comúnmente como:

    (1)   \begin{equation*} y = mx +b \end{equation*}

    Para entenderlo mejora ya sabemos que tanto la x como la y son las coordenadas en las cuales estará siempre definida la recta. La m es la pendiente de la recta y b es el punto donde la recta corta con el eje y.

    Si por ejemplo tenemos esta recta:

    eje coordenadas

    La ecuación de la recta sería muy sencilla ya que tenemos dos puntos cuando la x es cero, que la y es uno (0,1), y cuando la y es cero que la x es 2. Lo primero sería calcular la pendiente que se calcula con esta fórmula:

    (2)   \begin{equation*} m = \frac{y_2-y_1}{x_2-x_1} \end{equation*}

    Así que sustituyendo valores con los puntos que tenemos A(0,1) y B(2,0) sería así:

    (3)   \begin{equation*} m = \frac{0-1}{2-0} = \frac{-1}{2} = -0.5 \end{equation*}

    Y ahora sustituyendo, por ejemplo la A, en la fórmula que ya conocemos podemos calcular la b:

    (4)   \begin{equation*} y = mx +b \\ 1 = -0.5 \cdot 0+b \\ b=1 \end{equation*}

    Con lo cual la ecuación de esta recta sería:

    (5)   \begin{equation*} y = -0,5x + 1 \end{equation*}

    Con esto ya podemos saber cualquier punto de la recta en cualquier momento. Es decir (y por hacer un cálculo redondo), si queremos saber que valor tomará y en el punto x -2 solo tendremos que sustituir.

    (6)   \begin{equation*} y = -0,5\cdot(-2) + 1 \\ y = 2 \end{equation*}

    Supongo que ahora ya entendéis también por qué he prescindido de las fechas y he colocado números, es mucho más facil de seguir para un eje de coordenadas y para el cálculo de la recta.

    Pues bien siguiendo esa lógica vamos a trazar nuestras propias rectas en nuestro gráfico.

    Implementación para la línea de tendencia superior

    Vamos a crear una función que pasándole los dos puntos nos devuelva la m y la b para calcular la recta:

    def encontrar_linea_entre_puntos(punto1, punto2):
        x1, y1 = punto1
        x2, y2 = punto2
    
        if x2 - x1 != 0:
    	# calculamos la m
            m = (y2 - y1) / (x2 - x1)
    	# calculamos la b
            b = y1 - m * x1
            return m, b
        else:
            # Error
            return None

    Perfecto, ahora vamos a transformar los dos puntos en tuplas y se los pasamos a la función:

    # Define los dos puntos como tuplas (x, y)
    punto1 = (indice_pico1, data.iloc[indice_pico1]['Close'])
    punto2 = (indice_pico2, data.iloc[indice_pico2]['Close'])
    
    # Encuentra la línea entre los dos puntos
    linea = encontrar_linea_entre_puntos(punto1, punto2)
    m, b = linea
    print(f"La ecuación de la línea es: y = {m}x + {b}")

    Si ejecutamos esto vemos que nos devolverá la ecuación de la recta, que es lo que estamos buscando:

    ecuacion

    Y ahora vamos a dibujarla para ver que realmente lo está haciendo bien:

    x_values = [data.index[0], data.index[-1]]
    y_values = [m * x + b for x in x_values]
    plt.plot(x_values, y_values, label=f'Línea entre puntos', color='red')
    plt.plot(data)
    plt.title(TICKER + " linea de tendencia superior")
    plt.xlabel('Unidades de tiempo')
    plt.ylabel('Precio')
    plt.legend()
    plt.show()

    Y la gráfica que nos muestra es esta:

    linea superior

    Parece que lo ha hecho perfecto, así que vamos a ver ahora como lo haríamos para capturar la inferior.

    Implementación para la línea de tendencia inferior

    El código sería el mismo exactamente, solo cambia que a la hora de conseguir los valles en vez de los picos se pasan los datos negados:

    valles, valles_dict = scipy.signal.find_peaks(-data['Close'], width=1)
    print('Valles: %s' % (valles))

    El resto del código no lo pongo porque básicamente es idéntico no hace falta, solo copia y pega y conseguirás sacar esta gráfica:

    Linea inferior

    Rotura del creek

    Una vez que ya hemos calculado la recta con los datos que teníamos, ahora tenemos que ir comprobando en cada nuevo tick que nos llegue si el nuevo valor esta por debajo del valor que nos da la y de la ecuación de la recta. Haciéndolo con los datos históricos sería así:

    rotura = 0
    for x in range(punto1[0], data.index[-1]):
        if data.iloc[x]['Close'] > (m*x+b) and rotura == 0:
            print(f"Rotura del creek en {x} con valor {data.iloc[x]['Close']}")
            x_rotura = x
            y_rotura = data.iloc[x]['Close']
            rotura=1

    He puesto alguna línea más para dibujarlo bien, pero ya os podéis hacer a la idea de como se haría en tiempo real. Si lo graficamos se vería así:

    rotura

    En la gráfica vemos donde sería el primer punto donde se detecta que se ha roto el creek, y en el cual sería posible entrar en una estrategia con esta temporalidad (podríamos bajar la temporalidad para hilar más fino y entrar más rápido).

    Más pruebas

    Para probar que funciona bien, lo lógico es hacer más pruebas con más valores a ver si funciona correctamente en todos los casos. Así que he probado con unas cuantas acciones famosas en las que se pudiera ver una rotura del creek y parece que funciona correctamente:

    AMD

    amd

    UBER

    uber

    Microsoft

    microsoft

    Conclusión

    Como podéis ver con unos conceptos matemáticos muy simples hemos sido capaces de encontrar como ver la línea de tendencia y saber cuando el precio rompe el creek. Recordar que no solo hay que mirar la rotura del creek sino también el volumen, e incluso hay gente que prefiere usar más indicadores para confirmar.

    Como habéis visto he hecho las pruebas con varios valores para ver que graficaba correctamente y parece que siempre detecta correctamente las líneas de tendencia y cuando rompe el creek, pero si encontráis algún valor que este funcionando mal me lo comentáis y corrijo el código.

    Como siempre, si tenéis cualquier duda o mejora del artículo no dudéis en poneros en contacto conmigo y os contestaré lo antes posible.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *