Помните тот момент, когда в очередной раз разваливается сборка 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)