Implementando el Patrón Taza con Asa en Amibroker y Python

por | Jun 1, 2025 | Amibroker, Indicadores, Premium | 0 Comentarios

En los artículos anteriores, exploramos el patrón de Taza con Asa y cómo podemos utilizar regresiones polinómicas para identificarlo de manera objetiva.

Ahora es momento de llevar esto a la práctica y programarlo en Amibroker y Python.

En este artículo, veremos cómo combinar estas herramientas para detectar automáticamente la formación de una Taza con Asa en gráficos de precios, permitiéndonos ahorrar tiempo y evaluar múltiples activos sin depender de la observación manual.

En el próximo artículo y último de esta saga, programaremos un sistema de trading, analizaremos los resultados del backtest y ajustaremos la estrategia.

🛠️ Paso 1: Configuración en Python

Desgraciadamente, si bien Amibroker dispone de varias funciones para trabajar con regresión lineal (o polinomio de grado 1) no dispone de funciones para calcular de manera directa regresiones polinómicas de mayor grado.

Para ello podemos recurrir a Python y la librería Amipy que nos permite importar funciones creadas previamente y utilizarlas directamente en nuestro código afl de Amibroker.

Para ello recordemos que será necesario disponer de la versión profesional de Amibroker así como el plugin Amipy.

Una vez que estamos en Python vamos a utilizar la librería Numpy que nos permite trabajar con un gran número de funciones numéricas asociadas a arrays.

En nuestro caso, vamos a utilizar la función polyfit para buscar la función de grado dos que más se asemeje con la evolución del precio. Veamos un ejemplo comentado en el que utilizaremos la librería de Yahoo Finance (yfinance) para importar los datos de Tesla en unas determinadas fechas.

También hacemos uso de otras librerías como pandas (para trabajar con dataframes importados de Yahoo Finance), matplotlib (para la representación gráfica) o sklearn.metrics que nos permitirá calcular el r cuadrado de la serie respecto a la función obtenida.

Como podemos ver en el ejemplo descargamos los datos de Tesla en un dataframe (df). Posteriormente, como vamos a trabajar a trabajar con arrays generamos un array x con las fechas y otro array y con el precio.

Mediante la definición de “valores” definimos los coeficientes de la función polinómica. Es decir a, b y c. Para ello le damos el valor x (fechas), y (precio) y 2 que sería el grado del polinomio que queremos buscar.

En una variable llamada ecuación definimos la ecuación completa con la función poly1d en la que a partir de los coeficientes almacenados en valores nos da la ecuación.

En “myline”  pasamos de fechas a un array de números consecutivos o barras correspondientes a los días de mercado.

Finalmente representamos la evolución del precio, la propia ecuación e imprimimos los valores, la propia ecuación y el cálculo de R al cuadrado que hemos calculado con la función r2_score.

Como vemos se representa el polinomio de grado 2 que más se ajusta a la curva y posteriormente se imprime en pantalla los coeficientes y la propia ecuación, así como el R cuadrado que nos está dando una fiabilidad de 0.6 respecto a un máximo de 1.

📈 Paso 2: Integración en Amibroker

Vamos a basar nuestra estrategia en calcular el R cuadrado de la función polinómica que obtendríamos respecto a dos máximos.

Para ello vamos a verificar cada vez que el precio supere un máximo anterior no reciente que vamos a llamar pivot2, siendo pivot1 el primer máximo (inicio de la taza).

Con todo esto, tendremos un array llamado pivot2 que valdrá 0 en todas las barras excepto en aquellas en la que se produce la condición deseada y le daremos el valor del precio máximo ese día.

Mediante la librería Amipy podemos hacer el llamamiento a un archivo de Python y utilizar PyEvalFunction para hacer uso de una función que previamente habremos creado en el código de Python. Tenemos varias opciones para trabajar con PyEvalFunction.

  1. Mediante una función a partir de la cual le proporcionemos unos valores desde Amibroker y nos devuelva, a partir de unos cálculos determinados, un valor numérico concreto. Recordamos que Amibroker trabaja con arrays con lo que para utilizar esta opción deberíamos hacer un bucle que recorra cada una de las barras y establecer el cálculo para cada barra. Esta operación puede resultar un poco lenta para un backtest.
  2. Mediante una función en la cual le proporcionamos un array (por ejemplo, el precio al cierre de cada barra) y nos devuelva:
    • Un valor concreto y numérico a partir de un análisis del array completo proporcionado.
    • Otro array de tal manera que en cada una de las barras tendríamos un valor proporcionado por el array calculado.
    • Una matriz. Recordamos que un array no deja de ser una matriz unidimensional (o de dos dimensiones si consideramos el número de barras como una dimensión adicional). Es decir, podríamos considerar que una matriz multidimensional está formada por varios arrays unidimensionales.

En nuestro caso vamos a utilizar una función que nos devuelva una matriz de dos filas con el valor de R cuadrado en los puntos donde tengamos un pivot 2 y con el valor de la regresión polinómica calculada cuando se den las condiciones de una taza. De esta forma podremos representar en Amibroker la parábola definida en Python.

En definitiva, en nuestro código de Amibroker deberá aparecer:

PyLoadFromFile("C:\\pruebas\\taza_con_asa.py");

Donde se especifica la localización del archivo desde donde vamos a importar nuestra función o funciones. Y por otro lado:

MATRIZ = PyEvalFunction("tazaconasa", C,pivot2,duraciontaza,R2MIN);

De esta forma utilizaremos la función tazaconasa que vamos a definir en Python en el directorio previamente especificado y que, tal como habíamos comentado, nos va a proporcionar una matriz de dos dimensiones. Para el cálculo necesitaremos darle los siguientes valores:

  • Array Close (C) con todos los precios al cierre o otras opciones como el precio típico de cada barra. (promedio del máximo, mínimo y cierre)
  • Array pivot2 que tendrá el valor del precio máximo cuando se haya superado un máximo anterior no reciente (posible creación de la taza). En el resto de barras el array tendrá el valor 0
  • Array duraciontaza. En las barras en las que el pivot2 sea superior a 0 (posible taza) tendrá el valor del número de barras desde el último máximo.
  • R2MIN. Valor numérico del mínimo que exigimos al R cuadrado para considerar que el precio entre el pivot1 y el pivot2 realmente se corresponde con un polinomio de segundo grado y por tanto una formación de taza.

Para el programa en Python crearemos un archivo de texto guardado como “taza con asa.py” en el directorio especificado posteriormente en PyLoadFromFile.

En nuestro código vamos a definir la función tazaconasa mediante la instrucción def. A esta instrucción deberemos proporcionarle el listado de parámetros anteriores.

Finalmente programamos la función para que nos devuelva una matriz de dos filas que vamos a llamar array. La primera de las filas, el array[0] nos devolverá el valor de R al cuadrado en aquellos puntos donde haya un pivote de formación de taza con el mínimo exigible. En el resto de puntos el valor será 0.

La segunda fila de la matriz, o array[1], nos dará el valor de la curva de regresión polinómica entre los pivotes que forman la taza. Esto nos servirá para representar la taza en Amibroker-

Nótese también que estamos estableciendo dos condiciones para registrar el array[1] con la taza. La primera de ellas sería obvia y es que debemos tener un valor de R al cuadrado superior al mínimo exigible y predeterminado por LIMR2. La segunda condición consiste en que sólo consideramos aquellas parábolas en las que el coeficiente a sea positivo.

Eso implica que el vértice o mínimo de la parábola estaría en la parte inferior En caso contrario, si tuviéramos un valor negativo de la constante a, tendríamos una parábola invertida con un máximo en la parte central de la figura.

Por tanto, este sería el código que debemos guardar con formato .py para importarlo desde Amibroker

Desbloquea todos los contenidos con la Zona Premium

Ahora que tenemos nuestra función podemos centrarnos en el código de Amibroker y hacer uso de ella.  Para ello vamos a plantear lo siguiente:

Buscaremos un posible máximo que represente el vértice derecho de nuestra figura de taza. Lo llamaremos PIVOT2 y para ello buscaremos que se supere un máximo no reciente. Este máximo no reciente sería el PIVOT1 y representaría el vértice izquierdo de la taza. Es de suponer que de cumplirse las condiciones, todos los valores entre PIVOT1 Y PIVOT2 tendrían una disposición de tipo parabólico.

Estableceremos unas condiciones configurables. Por ejemplo, el mínimo exigible a los valores de R al cuadrado así como la duración máxima en la que vamos a buscar el máximo anterior con posibilidades de ser pivot1. Lo llamaremos maximo1.

maximo1=Ref(HHV(H,duracion_max),-1);

También establecemos una duración mínima de la taza. Hemos considerado 15 barras por tomar un valor razonable.

A partir de ahí vamos a establecer una serie de condiciones para verificar si al vértice le damos la categoría de pivot2. Serían las siguientes:

  • El máximo en este punto superaría al máximo1 (el mayor máximo anterior en el periodo de duración máxima establecido)
  • El número de barras entre el máximo1 y este punto debiera ser mayor que el mínimo de barras establecido (15)
  • Finalmente, recordamos que las figuras de taza con asa son de continuación alcista. Como una tendencia alcista es una sucesión de máximos y mínimos crecientes vamos a realizar una suposición. Si la distancia entre pivot1 y pivot2 son n velas. El mínimo que transcurre en las  n velas anteriores a pivot1 debería estar por debajo del mínimo de la posible taza. Es decir, mínimos crecientes.
  • En caso de cumplirse estas condiciones al array pivot2 le daremos el valor del máximo de esa barra. En caso contrario le daremos el valor Null.

Por otra parte vamos a establecer otro array llamado tazabars que nos va a dar el número de barras que dura la taza. Este array tendrá un valor concreto en las mismas velas que tengamos un pivot2.

Para calcular el array pivot1 con el vértice izquierdo de la posible taza vamos a usar un bucle que recorra todas las velas desde el final hasta la primera de las velas. En cuanto el bucle encuentre un valor de pivot2 positivo, esperará a que se cumplan las velas de duración establecidas para marcar en el array pivot1 el valor correspondiente al máximo en ese punto.

De esta forma, ya tenemos los arrays pivot1 y pivot2 con valores null en todas las barras excepto en aquellas en las que podría haber una figura de taza.

Ahora es el momento de dejar que Python haga su magia y utilizamos la función PyEvalFunction para importar la función que tenemos en nuestro archivo de Python. Para ello le damos los valores C (calculamos la regresión polinómica con los valores al cierre), los pivot2, la duración de la taza y el R2MIN.

Con esto tendremos una matriz en la cual, en la primera de las filas obtenemos los valores de R al cuadrado y en la segunda fila los valores de la regresión polinómica.

Como Amibroker trabaja con matrices vamos a definir R2 y RP mediante un bucle que recoja los valores de la matriz. Con esto ya tenemos importados los datos para usarlos en nuestro sistema con normalidad.

🚀 Conclusión

Hemos automatizado la detección de la Taza con Asa combinando Amibroker y Python, eliminando la subjetividad del análisis visual y optimizando la búsqueda de oportunidades.

En el próximo artículo, realizaremos un backtest para evaluar la rentabilidad de la estrategia y ajustar sus parámetros. ¡No te lo pierdas! 📊

Este artículo fue cortesía de Sergio Meana para MKTSignals.

La newsletter de MKTSignals

Si quieres estar al tanto de todas nuestras novedades, suscríbete a nuestra newsletter. ¡Es gratis!

¡Puntúa este artículo!

Total votos: 5. Promedio: 5

También te puede interesar:

¿Quieres acceder a todo el contenido Premium HOY?

+50 códigos de Amibroker

0 comentarios

Enviar un comentario

Loading...
logo factura v1
Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.

Tienes una explicación más detallada en nuestra política de privacidad