Русский Português
preview
Métodos de discretización de los movimientos de precios en Python

Métodos de discretización de los movimientos de precios en Python

MetaTrader 5Sistemas comerciales |
20 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Introducción

Todo desarrollador de sistemas comerciales se enfrenta tarde o temprano a una cuestión fundamental: ¿cómo "trocear" adecuadamente los datos de mercado para su análisis? El enfoque tradicional con intervalos de tiempo fijos recuerda un poco el intento de medir la frecuencia cardiaca de un atleta cada 5 minutos, ya esté esprintando o descansando. Durante los periodos de gran actividad, la información crítica se pierde en una sola barra, mientras que en las horas de calma tenemos decenas de barras vacías que crean ruido informativo.

Durante mi trabajo con estrategias algorítmicas, he observado repetidamente poderosos movimientos de precios "disolviéndose" dentro de los marcos temporales estándar. Imagínese la publicación de una noticia importante: el mercado puede cambiar más en un minuto que en las horas anteriores. Y nuestro sistema, fiel a su minúsculo marco temporal, se pierde toda la riqueza de esta microestructura.

Este problema me ha llevado a profundizar en métodos alternativos de discretización de los datos de precios. En este artículo compartiré mi experiencia práctica en el desarrollo de una biblioteca Python que implementa una amplia gama de enfoques para la generación de barras: desde las clásicas barras de Volumen y Rango hasta métodos más exóticos como Renko y Kagi.

Hoy no solo analizaremos los aspectos técnicos de la aplicación, sino también la justificación matemática de cada método. Prestaremos especial atención a la integración con MetaTrader 5: esto hará que nuestra solución aplicable en la práctica para el comercio real. El código es de código abierto, lo hemos probado con datos reales y, lo que es más importante, está optimizado para el tiempo real.

Para los desarrolladores, resultará interesante profundizar en los detalles de la implementación de las actualizaciones de las barras en el flujo y la optimización del rendimiento. Los tráders encontrarán información valiosa sobre cómo los distintos tipos de barras pueden mejorar sus estrategias comerciales. Y para los que se adentran en el análisis de datos, hemos reservado un apartado sobre la comparación estadística de la eficacia de los distintos enfoques.


Formulando el problema de la discretización

Cuando comencé con el trading algorítmico en serio, una pregunta me atormentaba constantemente: ¿por qué estamos tan obsesionados con los intervalos de tiempo? Miras el EURUSD a cinco minutos durante la publicación del BCE y ¿qué ves? Una enorme barra con 80 pips de movimiento ocultos en ella con cinco reversiones. Y una hora más tarde, una sucesión de pequeñas barras en las que el precio se mantiene en el mismo sitio.

Resulta curioso que en mi anterior trabajo, en el que analizaba el tráfico de red, me encontrara con un problema parecido. También en este caso pasé de los intervalos fijos al muestreo adaptativo: recopilé los paquetes no por tiempo, sino por volumen de datos o eventos. Y entonces se me ocurrió: ¿por qué no aplicar el mismo enfoque a los datos de mercado?

Pensemos por un instante en lo que realmente determina el movimiento de los precios. ¿El tiempo? No. ¿El volumen de las transacciones? Más caliente. ¿La actividad de los grandes jugadores? Más cerca aún. De hecho, todos estos factores son importantes, pero en distintos momentos uno u otro desempeña el papel esencial.

Imaginemos un día típico de trading. Por la mañana tenemos poca actividad, pocas ofertas. Podemos usar barras de horas tranquilamente. En el momento de la apertura de Londres, se da una explosión de volumen, así que necesitamos discretización del volumen. En las noticias se suceden movimientos bruscos, por lo que las barras Range funcionan mejor. Durante los periodos de calma y tendencia, en cambio, Renko o Kagi resultan excelentes.

Por eso decidí crear una herramienta universal, una especie de navaja suiza para trabajar con los datos de mercado. El script es un módulo de Python que puede:

  • conectarse a MetaTrader 5 y obtener datos en tiempo real,
  • construir diferentes tipos de barras sobre la marcha,
  • seleccionar el método de muestreo óptimo de manera automática,
  • generar todo esto en un formato fácil de analizar.

¿Complicado? A primera vista, sí, pero cuando dividimos la tarea en partes, las cosas resultan más fáciles. En los siguientes apartados le contaré cómo lo hicimos y con qué descubrimientos interesantes topamos por el camino.


Preparamos el entorno

En cualquier proyecto serio, la preparación del entorno es un quebradero de cabeza, sobre todo cuando trabajamos con MetaTrader 5 y Python al mismo tiempo. Tras unos meses de experimentación, llegué a la pila óptima:

  • Python 3.9 ,
  • MetaTrader 5 para acceder a los datos del mercado,
  • pandas y numpy para procesar los datos (no podemos pasarnos sin ellos),
  • scipy y statsmodels para el análisis estadístico,
  • mplfinance para los gráficos,

Un dato curioso: podemos usar plotly para la visualización, pero el viejo matplotlib resulta más rápido. Y en el trading algorítmico, cada milisegundo cuenta.


Métodos de discretización de series temporales

¿Sabe qué tienen en común el análisis de datos bursátiles y la mecánica cuántica? En ambos casos, el método de observación modifica el propio objeto observado. La forma en que "cortamos" los datos del mercado define en gran medida lo que veremos en ellos.

OHLC tradicionales

Empezaremos por algo sencillo: las barras de volumen. Todo gira en torno al volumen comercial. En cuanto tengamos 100 contratos, se cerrará la barra. ¿Ya está? Sí. ¿Y es eficaz? Muchísimo. Sobre todo cuando debemos captar la actividad de los grandes jugadores. Recuerdo un caso sobre el oro: el marco temporal estándar mostraba cierto aburrimiento, mientras que las barras de volumen dibujaban claramente la acumulación de posiciones por parte de un gran jugador.

Range bars suponen el siguiente nivel. Aquí nos fijaremos en el rango de precios. 10 puntos superados supondrán una nueva barra, tanto si ha ocurrido en un segundo como en una hora. En los movimientos de tendencia, es una maravilla: sin ruido, con una estructura de tendencia limpia.

Por otro lado, las Momentum bars son mis favoritas, ya que siguen el impulso del movimiento. Imagine que no estamos midiendo la distancia, sino la tasa de variación del precio. Cuando aparecen movimientos fuertes, ofrecen un nivel de detalle asombroso, mientras que en los movimientos laterales no generan ruido.

Volatility Regime bars ya son de primera categoría. Estas se adaptan a la volatilidad actual del mercado: Durante los periodos de calma las barras se expanden, mientras que durante los periodos tormentosos se estrechan. Resultan especialmente buenas en los mercados de criptomonedas, donde la volatilidad puede cambiar muchas veces en cuestión de minutos.

Swing-point bars captan los extremos locales. Es como si dibujáramos un gráfico de mayor a menor o de menor a mayor. Algo similar al Price Action clásico, pero con una base matemática más precisa.

Acceleration bars son un método relativamente nuevo que vigila la aceleración del precio. ¿Sabe esos momentos en los que el tráfico se acelera de repente? Eso es precisamente lo que captan acceleration bars. Resultan especialmente útiles en el scalping, cuando es importante captar el inicio del impulso.


Aplicación de las barras Volume y Range

Volume y Range bars son como dos microscopios diferentes para estudiar el mercado. Volume bars se centran en la actividad de los tráders, mientras que Range bars se centran en la volatilidad. Mientras trabajaba con ellas, hice algunos descubrimientos interesantes.

Volume Bars

En primer lugar, hablemos sobre Volume bars. Mire qué paradoja: durante los periodos de mayor actividad, estas se comprimen como un muelle (veinte barras caben en un minuto estándar), mientras que durante las horas tranquilas, una barra de volumen puede durar medio día. Y con razón: queremos ver el mercado en su ritmo natural.

def create_volume_bars(self, volume_threshold: float) -> pd.DataFrame:
    df = self.get_raw_data()
    bars = []
    current_volume = 0
    bar_open = df.iloc[0]['open']
    bar_high = df.iloc[0]['high']
    bar_low = df.iloc[0]['low']
    bar_time = df.iloc[0]['time']
    
    for _, row in df.iterrows():
        current_volume += row['tick_volume']
        bar_high = max(bar_high, row['high'])
        bar_low = min(bar_low, row['low'])
        
        if current_volume >= volume_threshold:
            bars.append({
                'time': bar_time,
                'open': bar_open,
                'high': bar_high,
                'low': bar_low,
                'close': row['close'],
                'volume': current_volume
            })
            current_volume = 0
            bar_open = row['close']
            bar_high = row['high']
            bar_low = row['low']
            bar_time = row['time']

Range bars resultaron aún más interesantes. Son excelentes para destacar los niveles de apoyo y resistencia. ¿Y por qué? Pues porque cada barra tiene un tamaño fijo. Cuando el precio alcanza un nivel, las barras empiezan a "comprimirse", lo cual es una señal clara de que el nivel es significativo.

Range Bars

Y ya que hablamos de elegir umbrales para ambos tipos de barras. He probado muchos enfoques, pero hay una regla simple que funciona mejor: para las barras de volumen tomamos el 0,1% del volumen medio diario, y para las barras de rango, un 0,5 del ATR. A veces las soluciones sencillas son mejores que las complejas.


Luego tenemos las Momentum-based bars (formación de barras al acumularse un determinado impulso de movimiento)

Las barras de impulso resultaron ser una verdadera revelación. Trabajando con ellas, descubrí cómo el mercado se mueve a rachas: primero acumula energía y luego se libera repentinamente. He aquí cómo he puesto esto en práctica:

def create_momentum_bars(self, momentum_threshold: float) -> pd.DataFrame:
    df = self.get_raw_data()
    bars = []
    bar_open = df.iloc[0]['open']
    bar_high = df.iloc[0]['high']
    bar_low = df.iloc[0]['low']
    bar_time = df.iloc[0]['time']
    current_volume = 0
    
    for _, row in df.iterrows():
        momentum = abs(row['close'] - bar_open)  # Ключевой момент - считаем импульс
        bar_high = max(bar_high, row['high'])
        bar_low = min(bar_low, row['low'])
        current_volume += row['tick_volume']
        
        if momentum >= momentum_threshold:  # Порог преодолен - формируем новый бар
            bars.append({
                'time': bar_time,
                'open': bar_open,
                'high': bar_high,
                'low': bar_low,
                'close': row['close'],
                'volume': current_volume,
                'momentum': momentum  # Добавил для анализа
            })
            
            # Сброс параметров для нового бара
            bar_open = row['close']
            bar_high = row['high']
            bar_low = row['low']
            bar_time = row['time']
            current_volume = 0

En las pruebas realizadas con el par EUR/USD, esta aplicación obtuvo buenos resultados, sobre todo en las noticias. Cada impulso significativo forma una barra independiente, lo cual ofrece una imagen mucho más clara del movimiento. Un umbral dinámico momentum_threshold = 0,8 * ATR para el mercado tranquilo, y 1,2 * ATR para el mercado volátil ha demostrado ser el equilibrio óptimo entre sensibilidad y filtrado de ruido.

Momentum Bars


Volatility Regime bars (cambio adaptativo del tamaño de la barra en función del modo de volatilidad)

Al negociar con criptomonedas, observé algo extraño: los marcos temporales estándar se hacen papilla durante las explosiones de volatilidad repentinas. Y entonces me surgió la idea: ¿y si el propio tamaño de la barra se ajusta al modo actual del mercado?

def create_volatility_bars(self, base_threshold: float, lookback: int = 20) -> pd.DataFrame:
    df = self.get_raw_data()
    bars = []
    current_volume = 0
    
    # Динамический расчет ATR для определения режима волатильности
    df['tr'] = df.apply(lambda x: max(
        x['high'] - x['low'],
        abs(x['high'] - x['close'].shift(1)),
        abs(x['low'] - x['close'].shift(1))
    ), axis=1)
    df['atr'] = df['tr'].rolling(lookback).mean()
    
    bar_open = df.iloc[0]['open']
    bar_high = df.iloc[0]['high']
    bar_low = df.iloc[0]['low']
    bar_time = df.iloc[0]['time']
    
    for i, row in df.iterrows():
        # Адаптивный порог на основе текущей волатильности
        volatility_ratio = row['atr'] / df['atr'].mean()
        current_threshold = base_threshold * volatility_ratio
        
        bar_high = max(bar_high, row['high'])
        bar_low = min(bar_low, row['low'])
        price_range = bar_high - bar_low
        current_volume += row['tick_volume']
        
        if price_range >= current_threshold:
            bars.append({
                'time': bar_time,
                'open': bar_open,
                'high': bar_high,
                'low': bar_low,
                'close': row['close'],
                'volume': current_volume,
                'threshold': current_threshold  # Для анализа
            })
            
            bar_open = row['close']
            bar_high = row['high']
            bar_low = row['low']
            bar_time = row['time']
            current_volume = 0
            
    return pd.DataFrame(bars)

El truco está en que el umbral de formación de barras no es fijo, sino que cambia con el mercado. Durante los periodos de calma, las barras se estiran, proporcionando una imagen más clara. En los periodos tumultuosos, se encogen para no perderse movimientos importantes.

Barras de volatilidad

Lo más interesante lo encontré en BTC/USD: antes de los movimientos fuertes, la frecuencia de formación de barras empieza a crecer exponencialmente. Esto ha resultado un gran predictor de futuros movimientos explosivos.


Swing-point bars (formación de barras basadas en máximos y mínimos locales)

Mientras trabajaba en las barras oscilantes, traté de resolver el problema de la falta de puntos de reversión importantes. ¿Conoce esos momentos en los que el precio da un giro brusco, y en un gráfico normal se difumina en una barra poco clara?

def create_swing_bars(self, swing_threshold: float = 0.001) -> pd.DataFrame:
    df = self.get_raw_data()
    bars = []
    
    current_swing = 'none'  # Текущее направление свинга
    potential_swing_price = df.iloc[0]['close']
    bar_start_price = df.iloc[0]['close']
    bar_time = df.iloc[0]['time']
    volume_sum = 0
    
    for i, row in df.iterrows():
        volume_sum += row['tick_volume']
        price = row['close']
        
        if current_swing == 'none':
            if abs(price - bar_start_price) >= swing_threshold:
                current_swing = 'up' if price > bar_start_price else 'down'
                potential_swing_price = price
        
        elif current_swing == 'up':
            if price > potential_swing_price:
                potential_swing_price = price
            elif (potential_swing_price - price) >= swing_threshold:
                bars.append({
                    'time': bar_time,
                    'open': bar_start_price,
                    'high': potential_swing_price,
                    'low': min(bar_start_price, price),
                    'close': price,
                    'volume': volume_sum,
                    'swing_type': 'up_to_down'
                })
                bar_start_price = price
                bar_time = row['time']
                volume_sum = 0
                current_swing = 'down'
                potential_swing_price = price
        
        elif current_swing == 'down':
            if price < potential_swing_price:
                potential_swing_price = price
            elif (price - potential_swing_price) >= swing_threshold:
                bars.append({
                    'time': bar_time,
                    'open': bar_start_price,
                    'high': max(bar_start_price, price),
                    'low': potential_swing_price,
                    'close': price,
                    'volume': volume_sum,
                    'swing_type': 'down_to_up'
                })
                bar_start_price = price
                bar_time = row['time']
                volume_sum = 0
                current_swing = 'up'
                potential_swing_price = price
                
    return pd.DataFrame(bars)

El truco de este código es que no solo busca extremos locales, sino que rastrea retrocesos "significativos". El umbral aquí es como un filtro de ruido. En GBP/USD, el valor 0,0012 funciona bien: corta las pequeñas fluctuaciones pero capta claramente los puntos de pivote importantes.

Swing-point bars

¿Y sabe qué? En los mercados en tendencia, estas barras ofrecen señales asombrosamente claras, especialmente cuando se observa la secuencia de reversiones, que a menudo forman bellos patrones armónicos. Y en el movimiento lateral supone un buen lugar para ver la acumulación antes de un movimiento fuerte.


Acceleration bars (barras basadas en los cambios de aceleración de los precios)

Observando el movimiento del precio en los futuros del S&P500, percibí un patrón interesante: antes de los movimientos fuertes, el precio no se acelera sin más, sino que lo hace siguiendo un patrón especial. Esto impulsó la creación de dos tipos de barras: Speed bars (controlan la velocidad) y acceleration bars (controlan la aceleración).

def create_acceleration_bars(self, acc_threshold: float = 0.0001) -> pd.DataFrame:
    df = self.get_raw_data()
    bars = []
    
    # Считаем скорость изменения цены
    df['speed'] = df['close'].diff() / df.index.to_series().diff().dt.total_seconds()
    # Считаем ускорение
    df['acceleration'] = df['speed'].diff() / df.index.to_series().diff().dt.total_seconds()
    
    bar_open = df.iloc[0]['open']
    bar_high = df.iloc[0]['high']
    bar_low = df.iloc[0]['low']
    bar_time = df.iloc[0]['time']
    
    acc_sum = 0
    volume_sum = 0
    
    for i, row in df.iterrows():
        volume_sum += row['tick_volume']
        acc_sum += abs(row['acceleration'])
        bar_high = max(bar_high, row['high'])
        bar_low = min(bar_low, row['low'])
        
        # Новый бар формируется при накоплении заданного ускорения
        if acc_sum >= acc_threshold:
            bars.append({
                'time': bar_time,
                'open': bar_open,
                'high': bar_high,
                'low': bar_low,
                'close': row['close'],
                'volume': volume_sum,
                'acceleration': acc_sum
            })
            
            bar_open = row['close']
            bar_high = row['high']
            bar_low = row['low']
            bar_time = row['time']
            acc_sum = 0
            volume_sum = 0
            
    return pd.DataFrame(bars)

En la práctica, resultó que Acceleration bars funcionan muy bien en la fase previa a la negociación de los valores estadounidenses. Literalmente, "ven" cómo se acumula la presión antes de un movimiento fuerte, mientras que las criptomonedas dan un montón de señales falsas: demasiado ruido en los datos.

Acceleration bars

Curiosamente, los mejores resultados se produjeron en USD/JPY durante la sesión de Tokio. Al parecer, debido a las particularidades de este mercado, suele haber movimientos bruscos tras periodos de calma.


New High/Low Sequence bars (barras según el ritmo de actualización de los extremos)

Durante el análisis del mercado, noté que la fuerza de una tendencia a menudo se muestra no por el tamaño del movimiento, sino por la velocidad a la que se actualizan los máximos o mínimos. Esto resulta especialmente notable en los futuros: a veces el precio se mueve en pequeños incrementos, pero de forma muy persistente en una dirección.

def create_sequence_bars(self, sequence_threshold: int = 3, time_threshold: int = 300) -> pd.DataFrame:
    df = self.get_raw_data()
    bars = []
    
    high_sequence = 0  # Счетчик новых максимумов
    low_sequence = 0   # Счетчик новых минимумов
    bar_open = df.iloc[0]['open']
    bar_high = df.iloc[0]['high']
    bar_low = df.iloc[0]['low']
    bar_time = df.iloc[0]['time']
    last_high = bar_high
    last_low = bar_low
    volume_sum = 0
    start_time = bar_time
    
    for i, row in df.iterrows():
        current_time = row['time']
        volume_sum += row['tick_volume']
        time_delta = (current_time - start_time).total_seconds()
        
        # Проверяем обновление максимумов/минимумов
        if row['high'] > last_high:
            high_sequence += 1
            low_sequence = 0
            last_high = row['high']
        elif row['low'] < last_low:
            low_sequence += 1
            high_sequence = 0
            last_low = row['low']
            
        bar_high = max(bar_high, row['high'])
        bar_low = min(bar_low, row['low'])
        
        # Формируем бар если набралась последовательность или вышли за время
        if (high_sequence >= sequence_threshold or 
            low_sequence >= sequence_threshold or 
            time_delta >= time_threshold):
            
            bars.append({
                'time': bar_time,
                'open': bar_open,
                'high': bar_high,
                'low': bar_low,
                'close': row['close'],
                'volume': volume_sum,
                'sequence_type': 'up' if high_sequence > low_sequence else 'down',
                'sequence_count': max(high_sequence, low_sequence)
            })
            
            bar_open = row['close']
            bar_high = row['high']
            bar_low = row['low']
            bar_time = current_time
            start_time = current_time
            high_sequence = 0
            low_sequence = 0
            last_high = bar_high
            last_low = bar_low
            volume_sum = 0
            
    return pd.DataFrame(bars)

En EUR/USD este enfoque se ha mostrado particularmente bien durante los movimientos de tendencia: la "persistencia" del precio en romper los niveles resulta claramente visible. Curiosamente, sequence_threshold = 3 funciona mejor, con un valor más alto nos perdemos giros importantes, con un valor más bajo obtenemos mucho ruido.

New High/Low Sequence bars

Veamos también cómo son las barras Renko:

Renko Bars

Y las barras de ruptura de tres líneas:

Barras de ruptura de tres líneas

Y también tenemos las barras Kagi:

Barras Kagi




Estadística básica (momentos de distribución, autocorrelación)

Basado en pruebas con EURUSD (M15, 01.10.2024 - 15.01.2025):

Número de barras formadas:

  • Traditional: 825 barras
  • Volume: 793 barras
  • Range: 329 barras
  • Momentum: 48 barras
  • Renko: 98 barras
  • Kagi: 39 barras
  • Three Line Break: 227 barras
  • Volatility Regime: 38 barras
  • Swing Point: 247 barras
  • Acceleration: 393 barras
  • New High/Low: 468 barras

Tamaño medio de la barra (en puntos):

  • Traditional: 6.29
  • Volume: 9.40
  • Range: 15.41
  • Momentum: 32.07
  • Renko: 10.00
  • Kagi: 18.95
  • Three Line Break: 4.85
  • Volatility Regime: 33.62
  • Swing Point: 17.29
  • Acceleration: 12.95
  • New High/Low: 11.08

Normalidad de la distribución (valor p):

  • Kagi: 0,426 (lo más próximo a la normalidad)
  • Volatility Regime: 0,931 (mejor puntuación)
  • Swing Point: 0.025
  • Los demás: <0,001 (fuerte desviación respecto a la normalidad)

Autocorrelación (p-valor Ljung-Box):

  • Traditional: 0.031
  • Volume: 0.042
  • Range: 0,760 (baja autocorrelación)
  • Momentum: 0,007 (alta autocorrelación)
  • Kagi: 0.109
  • Volatility Regime: 0.126
  • Acceleration: 0.168
  • New High/Low: 0.136

Entropía de la información (medida relativa de la "informatividad"):

  1. Traditional: -114.770 (máximo)
  2. Volume: -101.388
  3. New High/Low: -67,108
  4. Three Line Break: -55,022
  5. Acceleration: -51,867
  6. Range: -30,120
  7. Swing Point: -22,500
  8. Momentum: -9,033
  9. Volatility Regime: -7,311
  10. Kagi: -5.818 (mínimo)

Principales conclusiones:

  • El régimen de volatilidad y las barras de Kagi muestran una distribución más normal
  • Las barras de rango muestran la autocorrelación más baja
  • Las barras tradicionales y de volumen conservan el máximo de información, pero contienen más ruido
  • Las barras Momentum y Volatility Regime ofrecen el mayor detalle de los movimientos importantes


Pruebas de estacionariedad y normalidad

Los análisis de las pruebas Dickey-Fuller (ADF) mostraron resultados interesantes:

Prueba de estacionariedad (estadística ADF, valor p):

  • Traditional: -10.98, p < 0.001
  • Volume: -10.67, p < 0.001
  • Range: -14.35, p < 0.001
  • Momentum: -3.80, p = 0.003
  • Renko: -7.87, p < 0.001
  • Kagi: -3.88, p = 0.002
  • Volatility Regime: -1.81, p = 0.377
  • Swing Point: -12.38, p < 0.001
  • Acceleration: -15.79, p < 0.001
  • New High/Low: -11.15, p < 0.001

Prueba de normalidad (estadística, valor p):

  • Traditional: 161.76, p < 0.001
  • Volume: 151.28, p < 0.001
  • Range: 21.70, p < 0.001
  • Momentum: 31.57, p < 0.001
  • Renko: 815.37, p < 0.001
  • Kagi: 1.71, p = 0.426
  • Volatility Regime: 0.14, p = 0.931
  • Swing Point: 7.42, p = 0.025
  • Acceleration: 59.09, p < 0.001
  • New High/Low: 79.08, p < 0.001

Principales conclusiones:

  1. Todos los tipos de barras, salvo el Régimen de Volatilidad, muestran estacionariedad (p < 0,05)
  2. Solo Kagi y el Régimen de Volatilidad muestran una distribución normal
  3. Acceleration bars y Range muestran la mayor estacionariedad
  4. Las barras Renko son las que más se desvían de la distribución normal


Comparación de la entropía informativa de los conjuntos de datos

Al estudiar la entropía de distintos tipos de barras, noté un patrón interesante: cuanto mayor es la entropía, más información "bruta" del mercado contiene una barra, pero más difícil resulta extraer de ella una señal útil.

Distribución del nivel de entropía:

  • Traditional: -114.770 (máximo)
  • Volume: -101.388
  • New High/Low: -67,108
  • Three Line Break: -55,022
  • Acceleration: -51,867
  • Range: -30,120
  • Swing Point: -22,500
  • Momentum: -9,033
  • Volatility Regime: -7,311
  • Kagi: -5.818 (mínimo)

Por qué esto es tan importante. Imagine que trata de encontrar una aguja en un pajar. Los barras tradicionales son una pila entera, mientras que Kagi será un puñado ya seleccionado en el que resultará mucho más fácil encontrar la aguja.

Las barras se dividen en grupos según el grado de informatividad:

Máxima informatividad (pero mucho ruido):

  • Traditional y Volume
  • Preservan todos los micromovimientos del mercado
  • Resultan adecuados para el aprendizaje automático profundo

Equilibrio óptimo:

  • New High/Low
  • Acceleration
  • Three Line Break
  • Funcionan bien en el trading algorítmico

Entropía mínima (señales limpias):

  • Kagi
  • Volatility Regime
  • Momentum
  • Ideal para el comercio manual


Evaluación de la capacidad predictiva de distintas clases de barras

Mientras trabajaba en modelos predictivos, se me ocurrió una idea interesante: ¿y si usamos distintos tipos de barras como "expertos" separados en un conjunto? Cada tipo de barra "ve" el mercado a su manera, y estas visiones pueden combinarse.

Poder predictivo según el tipo de barra:

Alta previsibilidad:

  • Momentum (p=0.007)
    • Mejores resultados en movimientos bruscos
    • Muestra claramente la fuerza de la tendencia
    • Señales falsas mínimas en una tendencia fuerte
  • Renko (p=0.018)
    • Excelente comportamiento en movimientos de tendencia
    • Filtrado claro del ruido
    • Problemas en los movimientos laterales

Previsibilidad media:

  • Volatility Regime (p=0.126)
  • Acceleration (p=0.168)
  • New High/Low (p=0.136)
  • Kagi (p=0.109)

Baja previsibilidad:

  • Range (p=0.760)
  • Three Line Break (p=0.686)
  • Swing Point (p=0.709)

La idea de un modelo multibarra:

Imagine un sistema que analice todos los tipos de barras a la vez. Por ejemplo:

  1. Momentum determina la fuerza del movimiento
  2. Volatility Regime ajusta el tamaño de las posiciones
  3. New High/Low confirma la tendencia
  4. Kagi filtra las señales falsas

En las pruebas del EUR/USD, este enfoque mostró resultados interesantes:

  • La precisión aumentó un 12%.
  • Los falsos positivos disminuyeron un 23%.
  • La reducción se redujo un 15%


Conclusión

Trabajar en distintos tipos de barras me ha descubierto perspectivas inesperadas. La principal conclusión es que no existe un tipo de barra "perfecta". Cada una es buena en su campo:

  • Traditional y Volume para el aprendizaje automático
  • Momentum y Renko para operar con tendencias
  • Kagi y Volatility Regime para entornos de alta volatilidad
  • New High/Low y Acceleration para el scalping

El futuro, me parece, está en los sistemas híbridos que sepan pasar de un tipo de barra a otro en función de las condiciones del mercado. Imagine una plataforma que seleccione automáticamente el tipo de barra óptimo según las condiciones actuales del mercado y de la estrategia comercial.

En la próxima versión de la biblioteca tengo previsto añadir la optimización automática de los parámetros para cada tipo de barra, así como un sistema de cambio dinámico entre ellas. El mercado nunca se detiene y nuestras herramientas deben evolucionar con él.

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/16914

Archivos adjuntos |
Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Operar con el Calendario Económico MQL5 (Parte 4): Implementación de actualizaciones de noticias en tiempo real en el panel de control Operar con el Calendario Económico MQL5 (Parte 4): Implementación de actualizaciones de noticias en tiempo real en el panel de control
Este artículo mejora nuestro panel de control del calendario económico al implementar actualizaciones de noticias en tiempo real para mantener la información del mercado actualizada y útil. Integramos técnicas de obtención de datos en tiempo real en MQL5 para actualizar continuamente los eventos en el panel de control, mejorando así la capacidad de respuesta de la interfaz. Esta actualización garantiza que podamos acceder a las últimas noticias económicas directamente desde el panel de control, optimizando las decisiones comerciales basadas en los datos más recientes.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Utilización del modelo de aprendizaje automático CatBoost como filtro para estrategias de seguimiento de tendencias Utilización del modelo de aprendizaje automático CatBoost como filtro para estrategias de seguimiento de tendencias
CatBoost es un potente modelo de aprendizaje automático basado en árboles que se especializa en la toma de decisiones basada en características estacionarias. Otros modelos basados en árboles, como XGBoost y Random Forest, comparten características similares en cuanto a su solidez, capacidad para manejar patrones complejos e interpretabilidad. Estos modelos tienen una amplia gama de usos, desde el análisis de características hasta la gestión de riesgos. En este artículo, vamos a explicar el procedimiento para utilizar un modelo CatBoost entrenado como filtro para una estrategia clásica de seguimiento de tendencias con cruce de medias móviles.