Помните тот момент, когда в очередной раз разваливается сборка Docker-контейнера из-за капризной нативной зависимости? Когда на кону деплой торгового бота в AWS Lambda, а сервер упорно падает с ошибкой компиляции C-расширения, счёт идёт на минуты. (Хотя мы-то знаем, что «работает на моей машине» — это не баг, а состояние души). Технический анализ финансовых рынков невозможно представить без классических японских свечей. Модели разворота и продолжения тренда, такие как «Молот», «Дожи», «Поглощение» или «Утренняя звезда», десятилетиями используются трейдерами для алгоритмической торговли. Когда разработчики сталкиваются с необходимостью автоматизировать этот процесс на Python, стандартным индустриальным решением традиционно становится библиотека TA-Lib.

Однако на практике TA-Lib, представляющая собой обертку над бинарной библиотекой на языке C, часто становится источником инфраструктурной боли. Установка TA-Lib в облачных средах (например, AWS Lambda), на чипах архитектуры ARM (например, Apple Silicon M1/M2/M3/M4) или в легковесных Docker-контейнерах на базе Alpine Linux часто превращается в квест со сборкой через компилятор. По статистике внутренних DevOps-метрик крупных финтех-компаний, до 15% времени онбординга новых разработчиков уходит на настройку локального окружения именно из-за подобных нативных зависимостей.

Именно поэтому всё больше алгоритмических трейдеров и дата-сайентистов отказываются от TA-Lib в пользу чистого Python и экосистемы Pandas/NumPy. В этой статье мы разберем, как реализовать эффективное векторное распознавание популярных паттернов без тяжелых C-расширений, обеспечив высокую производительность и абсолютную кроссплатформенность.

Подготовка данных и математическая база свечей

Оставив позади головную боль с компиляторами и архитектурами процессоров, перейдем к фундаменту нашего решения — чистым данным. Представьте, что вы пишете бэктестер для криптовалютной биржи, где за секунду прилетают тысячи тиков: здесь каждая миллисекунда обработки DataFrame на счету. Прежде чем писать код для поиска паттернов, стандартизируем входные данные. Исторические котировки должны быть представлены в виде Pandas DataFrame, содержащего как минимум четыре колонки: Open, High, Low и Close.

Для эффективного поиска паттернов на чистом Python без TA-Lib нам понадобятся базовые метрики каждой свечи, которые мы рассчитаем векторизованным способом:

  • Тело свечи (Body): абсолютная разница между ценой открытия и закрытия.
  • Верхняя тень (Upper Shadow): расстояние от максимума до верхней границы тела.
  • Нижняя тень (Lower Shadow): расстояние от нижней границы тела до минимума.
  • Общий размах (Range): полная высота свечи (High - Low).
  • Направление (Direction): бычья (Close > Open) или медвежья (Close < Open) свеча.

Реализуем базовый класс для расчёта этих метрик с использованием NumPy, что позволит обрабатывать миллионы строк за доли секунды:

import pandas as pd
import numpy as np

class CandleMetrics:
    def __init__(self, df: pd.DataFrame):
        self.df = df.copy()
        
    
    def calculate(self) -> pd.DataFrame:
        df = self.df
        body = (df['Close'] - df['Open']).abs()
        upper_shadow = df['High'] - df[['Open', 'Close']].max(axis=1)
        lower_shadow = df[['Open', 'Close']].min(axis=1) - df['Low']
        candle_range = df['High'] - df['Low']
        is_bullish = df['Close'] > df['Open']
        
        metrics = pd.DataFrame({
            'body': body,
            'upper_shadow': upper_shadow,
            'lower_shadow': lower_shadow,
            'range': candle_range,
            'is_bullish': is_bullish
        }, index=df.index)
        
        return pd.concat([df, metrics], axis=1)

Векторная реализация поиска паттернов