Исходный код
Ложные пробои уровней поддержки (или сопротивления) являются одной из самых коварных ловушек для трейдеров. Они выглядят как сильный сигнал к открытию позиции, но быстро разворачиваются, приводя к убыткам. Эффективное распознавание таких паттернов может значительно улучшить результаты торговой стратегии. В этом руководстве мы покажем, как интегрировать мощную градиентную бустинговую библиотеку CatBoost в ваш торговый бот на Python для классификации ложных пробоев.
CatBoost, разработанный Яндексом, отличается высокой производительностью, отличной обработкой категориальных признаков и устойчивостью к переобучению, что делает его идеальным выбором для финансовых временных рядов. Мы создадим упрощенный пример, который включает генерацию данных, обучение модели и ее применение в симулированном торговом цикле.
Для реальной работы вам потребуется подключение к биржевым API (например, через CCXT для OKX) для получения исторических и текущих данных, а также, возможно, дополнительные данные, такие как исторические ликвидации с Coinglass API для обогащения признаков.
import pandas as pd
import numpy as np
from catboost import CatBoostClassifier, Pool
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import random
# 1. Генерация фиктивных данных для демонстрации
def generate_dummy_data(num_samples=1000):
data = {
'price': np.cumsum(np.random.randn(num_samples) * 0.1 + 0.05) + 100, # Симулируем цену
'volume': np.random.rand(num_samples) * 1000 + 100,
'rsi': np.random.rand(num_samples) * 70 + 15,
'macd_hist': np.random.randn(num_samples) * 2,
'volatility': np.random.rand(num_samples) * 2 + 0.5
}
df = pd.DataFrame(data)
# Симулируем ложные пробои (1) и истинные пробои/отскоки (0)
# Это очень упрощенная логика, в реальной жизни требуется сложный анализ
df['is_false_breakout'] = 0
for i in range(50, num_samples - 50):
# Упрощенное определение поддержки: локальный минимум
if df['price'].iloc[i] < df['price'].iloc[i-5:i].min() and \
df['price'].iloc[i] < df['price'].iloc[i+1:i+6].min():
# Если цена быстро восстанавливается после пробоя
if df['price'].iloc[i+10] > df['price'].iloc[i] * 1.005:
df.loc[i, 'is_false_breakout'] = 1 # Ложный пробой
elif df['price'].iloc[i+10] < df['price'].iloc[i] * 0.995:
df.loc[i, 'is_false_breakout'] = 0 # Истинный пробой (или продолжение падения)
return df
# 2. Извлечение признаков для классификации пробоя
def extract_features(df, index):
if index < 20:
return None # Недостаточно данных для признаков
features = {
'price_change_1h': (df['price'].iloc[index] - df['price'].iloc[index-5]) / df['price'].iloc[index-5], # 5 баров = 1 час
'price_change_4h': (df['price'].iloc[index] - df['price'].iloc[index-20]) / df['price'].iloc[index-20], # 20 баров = 4 часа
'volume_avg_5h': df['volume'].iloc[index-20:index].mean(),
'rsi_current': df['rsi'].iloc[index],
'rsi_prev_5h_avg': df['rsi'].iloc[index-20:index].mean(),
'macd_hist_current': df['macd_hist'].iloc[index],
'volatility_5h': df['volatility'].iloc[index-20:index].std(),
'is_support_level': 1 if df['price'].iloc[index] < df['price'].iloc[index-10:index].min() else 0 # Упрощенный детектор поддержки
}
return pd.Series(features)
# 3. Обучение модели CatBoost
def train_catboost_model(X, y):
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
model = CatBoostClassifier(
iterations=100, # Количество деревьев
learning_rate=0.1, # Скорость обучения
depth=6, # Глубина деревьев
loss_function='Logloss', # Функция потерь для бинарной классификации
eval_metric='Accuracy', # Метрика для оценки
random_seed=42,
verbose=False, # Отключение подробного вывода
early_stopping_rounds=10 # Ранняя остановка для предотвращения переобучения
)
model.fit(X_train, y_train, eval_set=(X_test, y_test))
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Точность модели на тестовой выборке: {accuracy:.4f}")
return model
# 4. Функция для предсказания ложного пробоя в реальном времени
def predict_false_breakout(model, current_features):
# CatBoost ожидает 2D массив, даже для одной выборки
features_df = pd.DataFrame([current_features])
prediction_proba = model.predict_proba(features_df)[0][1] # Вероятность класса 1 (ложный пробой)
return prediction_proba
# 5. Симуляция торгового бота
def main_trading_bot_loop(model, historical_data, threshold=0.7):
print("\n--- Запуск симуляции торгового бота ---")
trade_signals = []
for i in range(len(historical_data)):
current_price = historical_data['price'].iloc[i]
# В реальном боте здесь были бы получение новых данных с биржи
# Например, через CCXT: exchange.fetch_ohlcv('BTC/USDT', '1h', limit=20)
features = extract_features(historical_data, i)
if features is None:
continue
# Если текущий бар является потенциальным пробоем поддержки
if features['is_support_level'] == 1:
proba_false_breakout = predict_false_breakout(model, features)
print(f"Время: {i}, Цена: {current_price:.2f}, Вероятность ложного пробоя: {proba_false_breakout:.2f}")
if proba_false_breakout > threshold: # Если высокая вероятность ложного пробоя
signal = {'time': i, 'price': current_price, 'type': 'BUY_ON_FALSE_BREAKOUT', 'proba': proba_false_breakout}
trade_signals.append(signal)
print(f" -> СИГНАЛ: Покупка на ожидаемом ложном пробое! Вероятность: {proba_false_breakout:.2f}")
else:
print(f" -> Пробой поддержки, но не классифицирован как ложный. Вероятность: {proba_false_breakout:.2f}")
print("\n--- Результаты симуляции ---")
for signal in trade_signals:
print(f"Сигнал: {signal['type']} по цене {signal['price']:.2f} в момент {signal['time']} (proba: {signal['proba']:.2f})")
if __name__ == "__main__":
# 1. Генерация или загрузка данных
print("Генерация фиктивных данных...")
df_historical = generate_dummy_data(num_samples=2000)
# 2. Извлечение признаков и меток
print("Извлечение признаков...")
features_list = []
labels_list = []
for i in range(len(df_historical)):
features = extract_features(df_historical, i)
if features is not None:
features_list.append(features)
labels_list.append(df_historical['is_false_breakout'].iloc[i])
X = pd.DataFrame(features_list)
y = pd.Series(labels_list)
# Удаляем строки с NaN, которые могли появиться из-за std() на малом окне
X.dropna(inplace=True)
y = y[X.index] # Синхронизируем метки
# Убедимся, что есть оба класса для обучения
if len(y.unique()) < 2:
print("Недостаточно классов для обучения. Сгенерируйте больше данных или проверьте логику.")
else:
# 3. Обучение модели
print("Обучение модели CatBoost...")
catboost_model = train_catboost_model(X, y)
# 4. Запуск симуляции торгового бота
main_trading_bot_loop(catboost_model, df_historical, threshold=0.6)
Разбор параметров
В представленном коде используются различные параметры для настройки модели CatBoost и логики торгового бота. Понимание этих параметров критически важно для адаптации решения к вашим потребностям.
num_samples(вgenerate_dummy_data): Количество генерируемых точек данных. В реальном сценарии это будет объем исторических данных, которые вы загружаете.iterations(вCatBoostClassifier): Максимальное количество деревьев решений, которые будут построены. Большее количество итераций может улучшить точность, но увеличивает время обучения и риск переобучения.learning_rate(вCatBoostClassifier): Скорость, с которой каждый новый ансамбль деревьев корректирует ошибки предыдущих. Меньшее значение требует больше итераций, но может привести к лучшей обобщающей способности.depth(вCatBoostClassifier): Максимальная глубина каждого дерева решений. Более глубокие деревья могут улавливать более сложные зависимости, но также увеличивают риск переобучения.loss_function(вCatBoostClassifier): Функция потерь, используемая для оптимизации модели. Для бинарной классификации обычно используется'Logloss'.eval_metric(вCatBoostClassifier): Метрика, используемая для оценки качества модели на валидационном наборе во время обучения.'Accuracy'(точность) подходит для сбалансированных классов.random_seed(вCatBoostClassifier): Зерно для генератора случайных чисел, обеспечивающее воспроизводимость результатов обучения.verbose(вCatBoostClassifier): ЕслиTrue, CatBoost будет выводить информацию о процессе обучения. Установлено вFalseдля краткости.early_stopping_rounds(вCatBoostClassifier): Количество итераций без улучшения на валидационном наборе, после которых обучение будет остановлено. Помогает предотвратить переобучение.threshold(вmain_trading_bot_loop): Порог вероятности, выше которого модель классифицирует событие как ложный пробой. Настройка этого параметра критична для баланса между точностью и количеством торговых сигналов.price_change_1h,price_change_4hи другие (вextract_features): Признаки, извлекаемые из ценовых данных и индикаторов. Их выбор и расчет должны быть тщательно продуманы на основе вашей торговой стратегии и анализа рынка.
Как запустить
Чтобы запустить и адаптировать этот код для вашей торговой стратегии, выполните следующие шаги:
-
Установка зависимостей: Убедитесь, что у вас установлены все необходимые библиотеки. Вы можете установить их с помощью pip:
pip install pandas numpy scikit-learn catboost -
Подготовка исторических данных: Замените функцию
generate_dummy_dataна реальную загрузку исторических данных с биржи. Вам понадобятся OHLCV (Open, High, Low, Close, Volume) данные, а также, возможно, данные по индикаторам (RSI, MACD), объему, волатильности и даже данные по ликвидациям (например, используя Coinglass API) или данные из стакана заявок. Важно, чтобы ваши данные были размечены: для каждого потенциального пробоя вы должны знать, был ли он ложным или истинным. Это самая трудоемкая часть. -
Разработка признаков (Feature Engineering): Функция
extract_featuresсодержит примеры признаков. Вам необходимо разработать более сложные и релевантные признаки, которые действительно помогут модели отличить ложный пробой от истинного. Это могут быть: скорость изменения цены, объем на пробое, отклонение от скользящих средних, паттерны свечей, данные из книги ордеров, а также агрегированные данные по ликвидациям. -
Обучение и валидация модели: Обучите модель CatBoost на ваших подготовленных данных. Используйте кросс-валидацию и тщательно оцените производительность модели на отложенных данных. Экспериментируйте с гиперпараметрами CatBoost (как описано в разделе «Разбор параметров») для достижения оптимальной точности и устойчивости.
-
Интеграция в торговый бот: Замените симуляцию в
main_trading_bot_loopна реальное подключение к биржевому API. Используйте библиотеки вроде CCXT для получения потоковых данных и отправки ордеров. При получении нового бара или тика, извлекайте признаки, подавайте их в обученную модель и используйте предсказание для принятия торгового решения. -
Бэктестинг и бумажная торговля: Перед развертыванием бота на реальных деньгах, проведите тщательный бэктестинг на исторических данных, а затем запустите его в режиме бумажной торговли (paper trading) на реальном рынке. Это позволит выявить потенциальные проблемы и настроить параметры без финансового риска.
-
Управление рисками и этика: Всегда внедряйте строгие механизмы управления рисками. Устанавливайте стоп-лоссы, тейк-профиты и контролируйте размер позиции. Также важно помнить о этических аспектах и избегать практик, таких как wash trading, которые могут быть вредны для рынка и привести к блокировке аккаунта.
Интеграция ML-моделей, таких как CatBoost, в торговые боты открывает новые возможности для создания более интеллектуальных и адаптивных стратегий. Однако это требует глубокого понимания как машинного обучения, так и динамики рынка.




