Cómo entrené una IA simple en Python para analizar velas (II)

 

En el artículo pasado (parte I) vimos cómo “desenredé” las estructuras básicas de supergana.com que es una de las IAs más famosas de trading para binarias. Hoy escribiré sobre como se construyen indicadores básicas a partir de las velas usando Python.

Vamos a generar un análisis cuantitativo de velas OHLC con Python.

Las velas japonesas contienen cuatro datos fundamentales del mercado:

  1. Open (apertura).
  2. High (máximo).
  3. Low (mínimo).
  4. Close (cierre).

 

Aunque parecen simples, estos cuatro valores permiten construir una gran cantidad de variables cuantitativas útiles para análisis estadístico, trading algorítmico y modelos de machine learning.

En este artículo construiremos un pipeline completo de análisis de velas usando Python.

 

Vamos con la preparación del entorno

Instalamos librerías necesarias.

pip install pandas numpy matplotlib scikit-learn
Puedes copiar este código libremente

 

Librerías utilizadas:

Pandas nuevamente para la manipulación de datos.

NumPy para el cálculo numérico.

Matplotlib para visualización.

scikit-learn la usaremos para modelos de machine learning.

 

Ahora necesitamos cargar datos OHLC

Supongamos un archivo CSV con estructura:

time,open,high,low,close
Puedes copiar este código libremente

Código:

import pandas as pd

df = pd.read_csv(“candles.csv”)

print(df.head())
print(df.describe())

Puedes copiar este código libremente

Verificar datos faltantes:

print(df.isnull().sum())
Puedes copiar este código libremente

 

Eliminar valores faltantes si existen:

df = df.dropna()
Puedes copiar este código libremente

 

Ahora pasamos a un cálculo del rango de la vela

El rango total mide la volatilidad de cada vela.

Fórmula propuesta: range=high−low

 

Código:

df[“range”] = df[“high”] – df[“low”]
Puedes copiar este código libremente

 

Ahora vamos con el cálculo del cuerpo de la vela

El cuerpo mide la presión compradora o vendedora.

Fórmula propuesta: body=close−open

Código:

df[“body”] = df[“close”] – df[“open”]
Puedes copiar este código libremente

 

Magnitud absoluta:

df[“body_size”] = abs(df[“body”])
Puedes copiar este código libremente

 

Vamos con la generación de sombras superior e inferior

Las sombras representan rechazo del precio.

Para las sombras superiores se propone esta fórmula: upper_shadow=high−max(open,close)

Para las sombras inferiores propongo esta fórmula: lower_shadow=min(open,close)−low

 

Código:

df[“upper_shadow”] = df[“high”] – df[[“open”,”close”]].max(axis=1)

df[“lower_shadow”] = df[[“open”,”close”]].min(axis=1) – df[“low”]

Puedes copiar este código libremente

 

Relación cuerpo/rango

Una métrica útil es qué porcentaje de la vela representa el cuerpo.

df[“body_ratio”] = df[“body_size”] / df[“range”]
Puedes copiar este código libremente

 

Valores cercanos a 1 se considera una vela fuerte y 0 es simplemente indecisión.

 

Pasamos a la dirección de la vela

df[“direction”] = df[“body”].apply(
lambda x: 1 if x > 0 else -1
)
Puedes copiar este código libremente

Opcionalmente:

df[“bullish”] = df[“close”] > df[“open”]
Puedes copiar este código libremente

 

Configurando un cambio porcentual

Movimiento relativo de cada vela.

df[“pct_change”] = (df[“close”] – df[“open”]) / df[“open”]
Puedes copiar este código libremente

 

Pasemos a cómo ver la volatilidad móvil

Usamos desviación estándar.

 

df[“volatility”] = df[“range”].rolling(window=20).std()
Puedes copiar este código libremente

 

Promedio móvil del rango:

df[“range_mean”] = df[“range”].rolling(20).mean()
Puedes copiar este código libremente

 

Detección de velas tipo Doji

Un Doji ocurre cuando el cuerpo es muy pequeño.

def is_doji(row):

body = abs(row[“close”] – row[“open”])

total_range = row[“high”] – row[“low”]

if total_range == 0:
return False

return body < total_range * 0.1

Puedes copiar este código libremente

 

Aplicación:

 

df[“doji”] = df.apply(is_doji, axis=1)
Puedes copiar este código libremente

 

Opción para la detección de velas martillo

def is_hammer(row):

body = abs(row[“close”] – row[“open”])

lower_shadow = min(row[“open”],row[“close”]) – row[“low”]

upper_shadow = row[“high”] – max(row[“open”],row[“close”])

if lower_shadow > body * 2 and upper_shadow < body:
return True

return False

Puedes copiar este código libremente

Aplicación:

df[“hammer”] = df.apply(is_hammer, axis=1)
Puedes copiar este código libremente

 

Escudriñando la secuencias de velas

Muchas estrategias usan contexto de varias velas.

Creamos features retrasadas.

 

df[“prev_close”] = df[“close”].shift(1)

df[“prev_body”] = df[“body”].shift(1)

df[“prev_range”] = df[“range”].shift(1)

Puedes copiar este código libremente

 

Tres velas anteriores:

 

for i in range(1,4):

df[f”close_lag_{i}”] = df[“close”].shift(i)

Puedes copiar este código libremente

 

Creando dataset para Machine Learning

 

Definimos variables predictoras.

features = [

“body”,
“body_size”,
“upper_shadow”,
“lower_shadow”,
“range”,
“body_ratio”,
“pct_change”

]

Puedes copiar este código libremente

Dataset:

X = df[features]

Target:

df[“target”] = (df[“close”].shift(-1) > df[“close”]).astype(int)

y = df[“target”]

Puedes copiar este código libremente

 

División de datos

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(

X,
y,
test_size=0.2,
shuffle=False

)

Puedes copiar este código libremente

 

Entrenar modelo simple

from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(

n_estimators=200,
max_depth=6,
random_state=42

)

model.fit(X_train,y_train)

Puedes copiar este código libremente

 

Evaluar el modelo

from sklearn.metrics import accuracy_score

pred = model.predict(X_test)

accuracy = accuracy_score(y_test,pred)

print(“Accuracy:”,accuracy)

Puedes copiar este código libremente

 

Importancia de variables

Podemos ver qué características son más relevantes.

import numpy as np

importance = model.feature_importances_

for i,v in enumerate(importance):

print(features[i],v)

Puedes copiar este código libremente

 

Visualización de resultados

import matplotlib.pyplot as plt

plt.figure(figsize=(10,5))

plt.plot(df[“close”])

plt.title(“Serie de precios”)

plt.show()

Visualizar volatilidad:

[wpbch language='html']plt.figure(figsize=(10,5))

plt.plot(df[“volatility”])

plt.title(“Volatilidad”)

plt.show()

Puedes copiar este código libremente

 

Pipeline completo

Podemos encapsular todo el proceso.

 

def prepare_features(df):

df[“range”] = df[“high”] – df[“low”]

df[“body”] = df[“close”] – df[“open”]

df[“body_size”] = abs(df[“body”])

df[“upper_shadow”] = df[“high”] – df[[“open”,”close”]].max(axis=1)

df[“lower_shadow”] = df[[“open”,”close”]].min(axis=1) – df[“low”]

df[“body_ratio”] = df[“body_size”] / df[“range”]

df[“pct_change”] = (df[“close”] – df[“open”]) / df[“open”]

return df

Puedes copiar este código libremente

Uso:

df = prepare_features(df)
Puedes copiar este código libremente

 

Y si, todo artículo debería tener una conclusión

A partir de los cuatro valores básicos de una vela: apertura, cierre, máximo y mínimo, es posible construir docenas de variables cuantitativas que capturan información sobre volatilidad, momentum, presión compradora/vendedora y patrones de velas.

Estas variables pueden utilizarse para análisis estadístico, trading algorítmico y modelos de machine learning.

Agradecimientos para todo el equipo de supergana.com