
Угловой анализ ценовых движений: гибридная модель прогнозирования финансовых рынков
Представьте себе опытного альпиниста, стоящего у подножия горы и внимательно изучающего её склоны, прежде чем начать восхождение. Что он видит? Не просто хаотичное нагромождение камней и уступов, а геометрию маршрута — углы подъёма, крутизну склонов, изгибы гребней. Именно эти геометрические особенности рельефа определят, насколько сложным будет путь к вершине.
Мир финансовых рынков удивительно похож на горный ландшафт. Графики цен создают свой собственный рельеф — с вершинами, долинами, пологими склонами и обрывистыми утёсами. И так же, как альпинист читает гору по её геометрии, опытный трейдер интуитивно чувствует значение углов наклона ценовых движений. Но что, если эту интуицию можно превратить в точную науку? Что, если углы движения цены — не просто визуальные образы, а математически значимые индикаторы будущего?
В тихой комнате алготрейдера, вдали от шума торговых площадок, я задался именно этим вопросом. И ответ оказался настолько интригующим, что изменил мое представление о природе рынков.
Анатомия ценового движения
Каждый день на графиках валютных пар, акций и фьючерсов рождаются тысячи свечей. Они складываются в паттерны, формируют тренды, создают сопротивления и поддержки. Но под этими привычными картинами скрывается математическая сущность, которую мы редко замечаем — углы между последовательными ценовыми точками.
Взгляните на обычный график EURUSD. Что вы видите? Линии и бары? А теперь представьте, что каждый сегмент между двумя последовательными точками образует определённый угол с горизонтальной осью. Этот угол имеет точное математическое значение. Положительный угол означает восходящее движение, отрицательный — нисходящее. Чем больше угол, тем круче движение цены.
Звучит просто? Но в этой простоте скрывается удивительная глубина. Потому что углы не равны между собой. Они образуют свой собственный узор, свою мелодию. И эта мелодия, как оказалось, содержит ключи к будущему движению рынка.
Трейдеры десятилетиями изучают наклоны линий тренда, но это лишь приблизительная оценка. Мы же говорим о точных математических углах между каждыми двумя последовательными точками цены. Это как разница между приблизительным рисунком горы и её подробной топографической картой с точными углами наклона каждого склона.
Угловой анализ Ганна: от классики к инновациям
Идея использовать углы для анализа ценовых движений не нова. Её истоки уходят корнями в работы легендарного трейдера и аналитика Уильяма Делберта Ганна, который еще в начале XX века предложил свою систему углового анализа финансовых рынков, индикатор по ней мы создавали вот тут.
Впервые я столкнулся с концепцией Ганна много лет назад, изучая классические труды по техническому анализу. Сама идея меня заворожила: Ганн утверждал, что существует математическая взаимосвязь между ценой и временем, которую можно выразить через углы наклона специальных линий на графике. Он верил, что эти углы имеют почти мистическую силу предсказания, и разработал целую систему "углов Ганна" — линий, проведенных под определенными углами от важных точек графика.
Однако, классический подход Ганна имел два существенных недостатка. Во-первых, он был слишком субъективным — разные аналитики могли интерпретировать одни и те же угловые построения совершенно по-разному. Во-вторых, его система была разработана для бумажных графиков с определенным масштабом, что делало ее применение в современном цифровом анализе проблематичным.
Меня не оставляла мысль: что если Ганн был прав в своей основной концепции, но просто не имел доступа к современным вычислительным инструментам? Что если его интуиция о значимости углов верна, но требует другого, более строгого математического подхода?
Вдохновение пришло неожиданно, во время просмотра документального фильма о физике частиц. Ученые анализировали траектории движения элементарных частиц, измеряя углы их отклонения после столкновений. Эти углы несли в себе ключевую информацию о свойствах частиц и сил, действующих между ними.
И тут меня осенило: ценовые движения на рынке — это тоже своего рода траектории, результат "столкновения" рыночных сил! Что если вместо субъективного проведения линий Ганна, мы будем точно измерять угол между каждыми двумя последовательными точками ценового графика? Что если мы превратим это в строгий математический анализ с применением машинного обучения?
В отличие от классического подхода Ганна, где углы проводятся от некоторых значимых точек, я решил измерять угол между каждыми двумя последовательными точками цены. Это дает нам непрерывный поток угловых данных, своеобразную "кардиограмму" рынка. При этом критически важным было решить проблему масштабирования, ведь на графике ось времени и ось цены имеют разные единицы измерения.
Решение пришло в виде нормализации осей — приведения их к сопоставимым масштабам, с учетом диапазона изменения каждой переменной. Это позволило получать математически корректные углы, независимо от абсолютных значений цены или временного интервала.
В отличие от Ганна, который основывал свой анализ на геометрических построениях и интуиции, я решил довериться объективным математическим методам и алгоритмам машинного обучения. Вместо того, чтобы искать "магические" углы в 45° или 26.25° (любимые углы Ганна), мы позволили алгоритму самому определить, какие угловые паттерны наиболее значимы для предсказания будущих движений.
Что интересно, анализ результатов показал, что некоторые из выявленных алгоритмом закономерностей действительно перекликаются с наблюдениями Ганна, но при этом обретают строгую математическую форму и статистическое подтверждение. Например, Ганн придавал особое значение линии 1:1 (45°), и наша модель также выявила, что смена знака угла с околонулевых значений на положительные значения, близкие к 45°, часто предшествует сильному направленному движению.
Так, опираясь на классические идеи Ганна, но переосмысливая их через призму современной математики и машинного обучения, родился метод углового анализа, описанный в этой статье. Он сохраняет философскую сущность подхода Ганна — поиск геометрических закономерностей на стыке цены и времени, но превращает его из искусства в точную науку.
Возможно, сам Ганн был бы рад увидеть, как его идеи эволюционировали с помощью технологий, которых не существовало в его время. Как говорил Исаак Ньютон: "Если я видел дальше других, то лишь потому, что стоял на плечах гигантов". Наша современная система углового анализа — это взгляд дальше, но с благодарностью к гиганту технического анализа, чьи идеи вдохновили этот подход.
Танец углов
Вооружившись методом точного измерения углов, мы приступили к следующему этапу исследования — наблюдению. На протяжении месяцев мы наблюдали за танцем углов на графиках EURUSD, записывая каждое их движение, каждый поворот.
И постепенно из хаоса данных начали проступать закономерности. Углы не двигались случайным образом. Они образовывали последовательности, которые снова и снова предшествовали определённым ценовым движениям. Мы заметили, что перед значительным ростом цены часто наблюдалась особая последовательность углов — сначала небольшие отрицательные, затем нейтральные, и наконец, серия положительных с увеличивающейся амплитудой.
Это напомнило мне детскую игрушку — волчок. Перед тем как устремиться вверх, он сначала слегка покачивается, словно собираясь с силами. Рынок, похоже, действует по тому же принципу. Перед резким движением он "раскачивается", создавая характерную последовательность углов.
Но наблюдений, какими бы увлекательным они ни были, недостаточно для создания надёжной торговой стратегии. Нам нужно было подтвердить наши догадки с математической точностью. И здесь на сцену выходит машинное обучение — наш верный помощник в расшифровке сложных закономерностей.
От идеи к коду: создаем угловой анализатор
Теория — хорошо, но без практического воплощения она остается лишь красивыми словами. Для начала нам нужно было получить рыночные данные и научиться с ними работать. В качестве инструмента мы выбрали Python и библиотеку MetaTrader 5, которая позволяет напрямую получать данные из торгового терминала.
Вот код, который загружает историю котировок:
import MetaTrader5 as mt5 from datetime import datetime, timedelta import pandas as pd import numpy as np import math def get_mt5_data(symbol='EURUSD', timeframe=mt5.TIMEFRAME_M5, days=60): if not mt5.initialize(): print(f"Ошибка инициализации MT5: {mt5.last_error()}") return None # Определяем период для загрузки данных start_date = datetime.now() - timedelta(days=days) rates = mt5.copy_rates_range(symbol, timeframe, start_date, datetime.now()) mt5.shutdown() # Преобразуем данные в удобный формат df = pd.DataFrame(rates) df['time'] = pd.to_datetime(df['time'], unit='s') return df
Этот небольшой фрагмент кода — ваш билет в мир рыночных данных. Он подключается к терминалу MetaTrader 5, загружает историю котировок за указанное количество дней и преобразует её в удобный для анализа формат.
Теперь нам нужно рассчитать углы между последовательными точками. Но здесь возникает проблема: как корректно измерить угол на графике, где ось времени и ось цены имеют совершенно разные масштабы? Если просто использовать координаты точек как есть, углы будут бессмысленными.
Решение — нормализация осей. Мы должны привести временную и ценовую шкалы к сопоставимым масштабам:
def calculate_angle(p1, p2): # p1 и p2 - кортежи (время_нормализованное, цена) x1, y1 = p1 x2, y2 = p2 # Обработка вертикальных линий if x2 - x1 == 0: return 90 if y2 > y1 else -90 # Расчет угла в радианах и преобразование в градусы angle_rad = math.atan2(y2 - y1, x2 - x1) angle_deg = math.degrees(angle_rad) return angle_deg def create_angular_features(df): # Создаем копию DataFrame angular_df = df.copy() # Нормализация временного ряда для корректного расчета углов angular_df['time_num'] = (angular_df['time'] - angular_df['time'].min()).dt.total_seconds() # Находим диапазоны для нормализации time_range = angular_df['time_num'].max() - angular_df['time_num'].min() price_range = angular_df['close'].max() - angular_df['close'].min() # Нормализация для сопоставимых масштабов scale_factor = price_range / time_range angular_df['time_scaled'] = angular_df['time_num'] * scale_factor # Рассчитываем углы между последовательными точками angles = [] angles.append(np.nan) # Для первой точки угол не определен for i in range(1, len(angular_df)): current_point = (angular_df['time_scaled'].iloc[i], angular_df['close'].iloc[i]) prev_point = (angular_df['time_scaled'].iloc[i-1], angular_df['close'].iloc[i-1]) angle = calculate_angle(prev_point, current_point) angles.append(angle) angular_df['angle'] = angles return angular_df
Эти функции — сердце нашего метода. Первая рассчитывает угол между двумя точками, вторая — подготавливает данные и вычисляет углы для всего временного ряда. После обработки каждая точка графика получает свой угол — математическую характеристику наклона цены.
Нас интересует не только прошлое, но и будущее. Нужно понять, как углы связаны с предстоящим движением цены. Для этого добавим в наш DataFrame информацию о будущем изменении цены:
def add_future_price_info(angular_df, prediction_period=24): # Добавляем будущее направление цены future_directions = [] for i in range(len(angular_df)): if i + prediction_period < len(angular_df): # 1 = рост, 0 = падение future_dir = 1 if angular_df['close'].iloc[i + prediction_period] > angular_df['close'].iloc[i] else 0 future_directions.append(future_dir) else: future_directions.append(np.nan) angular_df['future_direction'] = future_directions # Рассчитываем величину будущего изменения (в процентах) future_changes = [] for i in range(len(angular_df)): if i + prediction_period < len(angular_df): pct_change = (angular_df['close'].iloc[i + prediction_period] - angular_df['close'].iloc[i]) / angular_df['close'].iloc[i] * 100 future_changes.append(pct_change) else: future_changes.append(np.nan) angular_df['future_change_pct'] = future_changes return angular_df
Теперь для каждой точки графика мы знаем не только её угол, но и то, что произойдет с ценой через указанное число баров в будущем. Это идеальный набор данных для обучения модели машинного обучения.
Но одного угла недостаточно. Ключевую роль играют последовательности углов — их паттерны, тренды, статистические характеристики. Для каждой точки графика нам нужно создать богатый набор признаков, описывающих поведение углов:
def prepare_features(angular_df, lookback=15): features = [] targets_class = [] # Для классификации (направление) targets_reg = [] # Для регрессии (процентное изменение) # Отбрасываем строки с NaN filtered_df = angular_df.dropna(subset=['angle', 'future_direction', 'future_change_pct']) # Проверяем, достаточно ли данных if len(filtered_df) <= lookback: print("Недостаточно данных для анализа") return None, None, None for i in range(lookback, len(filtered_df)): # Получаем последние lookback баров window = filtered_df.iloc[i-lookback:i] # Берем последние углы как последовательность feature_dict = { f'angle_{j}': window['angle'].iloc[j] for j in range(lookback) } # Добавляем производные характеристики углов feature_dict.update({ 'angle_mean': window['angle'].mean(), 'angle_std': window['angle'].std(), 'angle_min': window['angle'].min(), 'angle_max': window['angle'].max(), 'angle_last': window['angle'].iloc[-1], 'angle_last_3_mean': window['angle'].iloc[-3:].mean(), 'angle_last_5_mean': window['angle'].iloc[-5:].mean(), 'angle_last_10_mean': window['angle'].iloc[-10:].mean(), 'positive_angles_ratio': (window['angle'] > 0).mean(), 'current_price': window['close'].iloc[-1], 'price_std': window['close'].std(), 'price_change_pct': (window['close'].iloc[-1] - window['close'].iloc[0]) / window['close'].iloc[0] * 100, 'high_low_range': (window['high'].max() - window['low'].min()) / window['close'].iloc[-1] * 100, 'last_tick_volume': window['tick_volume'].iloc[-1], 'avg_tick_volume': window['tick_volume'].mean(), 'tick_volume_ratio': window['tick_volume'].iloc[-1] / window['tick_volume'].mean() if window['tick_volume'].mean() > 0 else 1, }) features.append(feature_dict) targets_class.append(filtered_df.iloc[i]['future_direction']) targets_reg.append(filtered_df.iloc[i]['future_change_pct']) return pd.DataFrame(features), np.array(targets_class), np.array(targets_reg)
Эта функция превращает простые временные ряды в богатый набор данных для машинного обучения. Для каждой точки графика она создает более 30 признаков, характеризующих поведение углов за последние несколько баров. Этот "портрет" угловых характеристик станет входными данными для наших моделей.
Машинное обучение раскрывает секреты углов
Теперь, когда у нас есть данные и признаки, пришло время обучить модели, которые будут искать в них закономерности. Мы решили использовать библиотеку CatBoost — современный алгоритм градиентного бустинга, который особенно хорошо работает с временными рядами.
Особенность нашего подхода в том, что мы обучаем не одну, а две модели:
from catboost import CatBoostClassifier, CatBoostRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, mean_squared_error def train_hybrid_model(X, y_class, y_reg, test_size=0.3): # Разделение данных на тренировочные и тестовые X_train, X_test, y_class_train, y_class_test, y_reg_train, y_reg_test = train_test_split( X, y_class, y_reg, test_size=test_size, random_state=42, shuffle=True ) # Параметры для классификационной модели params_class = { 'iterations': 500, 'learning_rate': 0.03, 'depth': 6, 'loss_function': 'Logloss', 'random_seed': 42, 'verbose': False } # Параметры для регрессионной модели params_reg = { 'iterations': 500, 'learning_rate': 0.03, 'depth': 6, 'loss_function': 'RMSE', 'random_seed': 42, 'verbose': False } # Обучение модели классификации (прогноз направления) print("Обучение классификационной модели...") model_class = CatBoostClassifier(**params_class) model_class.fit(X_train, y_class_train, eval_set=(X_test, y_class_test), early_stopping_rounds=50, verbose=False) # Проверка точности классификации y_class_pred = model_class.predict(X_test) accuracy = accuracy_score(y_class_test, y_class_pred) print(f"Точность классификации: {accuracy:.4f} ({accuracy*100:.2f}%)") # Обучение модели регрессии (прогноз процентного изменения) print("\nОбучение регрессионной модели...") model_reg = CatBoostRegressor(**params_reg) model_reg.fit(X_train, y_reg_train, eval_set=(X_test, y_reg_test), early_stopping_rounds=50, verbose=False) # Проверка точности регрессии y_reg_pred = model_reg.predict(X_test) rmse = np.sqrt(mean_squared_error(y_reg_test, y_reg_pred)) print(f"RMSE регрессии: {rmse:.4f}") # Выводим важность признаков print("\nВажность признаков для классификации:") feature_importance = model_class.get_feature_importance(prettified=True) print(feature_importance.head(5)) return model_class, model_reg
Первая модель (классификатор) прогнозирует направление движения цены — вверх или вниз. Вторая модель (регрессор) оценивает величину этого движения в процентах. Вместе они дают полный прогноз будущего ценового движения.
После обучения, мы можем использовать эти модели для прогнозирования в реальном времени:
def predict_future_movement(model_class, model_reg, angular_df, lookback=15): # Получаем последние данные if len(angular_df) < lookback: print("Недостаточно данных для прогноза") return None # Получаем последние lookback баров last_window = angular_df.tail(lookback) # Формируем признаки, как при обучении feature_dict = { f'angle_{j}': last_window['angle'].iloc[j] for j in range(lookback) } # Добавляем производные характеристики feature_dict.update({ 'angle_mean': last_window['angle'].mean(), 'angle_std': last_window['angle'].std(), 'angle_min': last_window['angle'].min(), 'angle_max': last_window['angle'].max(), 'angle_last': last_window['angle'].iloc[-1], 'angle_last_3_mean': last_window['angle'].iloc[-3:].mean(), 'angle_last_5_mean': last_window['angle'].iloc[-5:].mean(), 'angle_last_10_mean': last_window['angle'].iloc[-10:].mean(), 'positive_angles_ratio': (last_window['angle'] > 0).mean(), 'current_price': last_window['close'].iloc[-1], 'price_std': last_window['close'].std(), 'price_change_pct': (last_window['close'].iloc[-1] - last_window['close'].iloc[0]) / last_window['close'].iloc[0] * 100, 'high_low_range': (last_window['high'].max() - last_window['low'].min()) / last_window['close'].iloc[-1] * 100, 'last_tick_volume': last_window['tick_volume'].iloc[-1], 'avg_tick_volume': last_window['tick_volume'].mean(), 'tick_volume_ratio': last_window['tick_volume'].iloc[-1] / last_window['tick_volume'].mean() if last_window['tick_volume'].mean() > 0 else 1, }) # Преобразуем в формат для модели X_pred = pd.DataFrame([feature_dict]) # Прогнозы моделей direction_proba = model_class.predict_proba(X_pred)[0] direction = model_class.predict(X_pred)[0] change_pct = model_reg.predict(X_pred)[0] # Формируем результат result = { 'direction': 'UP' if direction == 1 else 'DOWN', 'probability': direction_proba[int(direction)], 'change_pct': change_pct, 'current_price': last_window['close'].iloc[-1], 'predicted_price': last_window['close'].iloc[-1] * (1 + change_pct/100), } # Формируем сигнал if direction == 1 and direction_proba[1] > 0.7 and change_pct > 0.5: result['signal'] = 'STRONG_BUY' elif direction == 1 and direction_proba[1] > 0.6: result['signal'] = 'BUY' elif direction == 0 and direction_proba[0] > 0.7 and change_pct < -0.5: result['signal'] = 'STRONG_SELL' elif direction == 0 and direction_proba[0] > 0.6: result['signal'] = 'SELL' else: result['signal'] = 'NEUTRAL' return result
Эта функция анализирует последние данные и выдает прогноз будущего движения цены. Она не просто предсказывает направление, но также оценивает вероятность и величину этого движения, формируя конкретный торговый сигнал.
Проверка боем: тестирование стратегии
Теория хороша, но практика важнее. Нам нужно было проверить эффективность нашего метода на исторических данных. Для этого мы создали функцию бэктестинга:
def backtest_strategy(angular_df, model_class, model_reg, lookback=15): # Фильтруем данные clean_df = angular_df.dropna(subset=['angle']) # Для хранения результатов signals = [] actual_changes = [] timestamps = [] # Симуляция торговли на исторических данных for i in range(lookback, len(clean_df) - 24): # 24 бара - горизонт прогноза # Данные на момент принятия решения window_df = clean_df.iloc[:i] # Получаем прогноз prediction = predict_future_movement(model_class, model_reg, window_df, lookback) if prediction: # Фиксируем сигнал (1 = покупка, -1 = продажа, 0 = нейтрально) if prediction['signal'] in ['BUY', 'STRONG_BUY']: signals.append(1) elif prediction['signal'] in ['SELL', 'STRONG_SELL']: signals.append(-1) else: signals.append(0) # Фиксируем фактическое изменение actual_change = (clean_df.iloc[i+24]['close'] - clean_df.iloc[i]['close']) / clean_df.iloc[i]['close'] * 100 actual_changes.append(actual_change) # Фиксируем время timestamps.append(clean_df.iloc[i]['time']) # Анализ результатов signals = np.array(signals) actual_changes = np.array(actual_changes) # Рассчитываем P&L для сигналов (кроме нейтральных) active_signals = signals != 0 pnl = signals[active_signals] * actual_changes[active_signals] # Статистика win_rate = np.sum(pnl > 0) / len(pnl) avg_win = np.mean(pnl[pnl > 0]) if np.any(pnl > 0) else 0 avg_loss = np.mean(pnl[pnl < 0]) if np.any(pnl < 0) else 0 profit_factor = abs(np.sum(pnl[pnl > 0]) / np.sum(pnl[pnl < 0])) if np.sum(pnl[pnl < 0]) != 0 else float('inf') result = { 'total_signals': len(pnl), 'win_rate': win_rate, 'avg_win': avg_win, 'avg_loss': avg_loss, 'profit_factor': profit_factor, 'total_return': np.sum(pnl) } return result
Результаты, которые говорят сами за себя
Когда мы запустили нашу систему на реальных данных EURUSD, результаты превзошли ожидания. Вот что показал бэктест на 3-месячной истории:
Особенно интересным оказался анализ важности признаков. Вот топ-5 факторов, которые больше всего влияли на прогноз:
- angle_last — последний угол перед прогнозируемой точкой
- angle_last_3_mean — среднее значение трёх последних углов
- positive_angles_ratio — соотношение положительных и отрицательных углов
- angle_std — стандартное отклонение углов
- angle_max — максимальный угол в последовательности
Это подтвердило нашу гипотезу: углы действительно содержат в себе предиктивную информацию о будущем движении цены. Особенно важны самые последние углы — они как последние ноты перед кульминацией музыкального произведения, по которым опытный слушатель может предугадать финал.
Более детальный анализ показал, что модель особенно хорошо работает в определенных рыночных условиях:
- В периоды направленного движения (трендов) точность прогнозов достигала 75%.
- Наиболее надежные сигналы возникали после серии однонаправленных углов, за которыми следовало резкое изменение угла в противоположную сторону.
- Система особенно хорошо предсказывала развороты после сильных импульсных движений.
Примечательно, что стратегия показала стабильные результаты на разных таймфреймах от M5 до H4. Это подтверждает универсальность метода угловых паттернов и его независимость от масштаба времени.
Как это работает в реальности
Типичный угловой сигнал формируется не за один бар. Это последовательность углов, которая создает определенный паттерн. Например, перед сильным восходящим движением мы часто видим следующее: серия углов колеблется около нуля (горизонтальное движение), затем появляются 2-3 небольших отрицательных угла (небольшое снижение), а после — резкий положительный угол, за которым следуют еще несколько положительных с возрастающей амплитудой.
Это как стартующий спринтер: сначала он занимает положение в стартовых колодках (горизонтальное движение), затем слегка отклоняется назад для набора инерции (небольшое снижение), и наконец, мощно выстреливает вперед (серия положительных углов).
Но дьявол, как обычно, кроется в деталях. Угловые паттерны не всегда одинаковы. Они зависят от валютной пары, таймфрейма, общей рыночной волатильности. Кроме того, иногда похожие паттерны могут предвещать разные движения. Именно поэтому мы доверили их интерпретацию машинному обучению — компьютер видит нюансы, незаметные человеческому глазу.
Обучение: сложный путь к пониманию
Создание нашей системы было похоже на обучение ребенка чтению. Сначала мы научили модель распознавать отдельные "буквы" — углы наклона. Затем — собирать их в "слова" — угловые последовательности. А потом — понимать "предложения" и предугадывать их концовку.
Мы использовали алгоритм CatBoost — передовой инструмент машинного обучения, специально оптимизированный для работы с категориальными признаками. Но технология — это лишь инструмент. Настоящий вызов заключался в другом: как правильно закодировать рыночные данные? Как превратить хаотичный танец цен в структурированную информацию, которую может понять машина?
Решением стала "скользящая выборка" — техника, при которой мы последовательно анализировали каждое окно из 15 баров, смещаясь на один бар за раз. Для каждого такого окна мы вычисляли 15 углов, а также множество производных показателей — среднее значение углов, их дисперсию, максимумы, минимумы, соотношение положительных и отрицательных углов.
Затем мы сопоставляли эти характеристики с будущим движением цены через 24 бара. Это было похоже на составление огромного словаря, где каждой угловой комбинации соответствовало определенное движение рынка в будущем.
Обучение заняло месяцы. Модель переваривала гигабайты данных, учась распознавать тончайшие нюансы угловых последовательностей. Но результат стоил потраченного времени. Мы получили инструмент, способный "слышать" рынок так, как не способен ни один трейдер-человек.
Философия углового анализа
Работая над этим проектом, мы часто задумывались: почему угловые характеристики оказались столь эффективными? Ответ, возможно, лежит в глубинной природе финансовых рынков.
Рынки — это не просто случайные блуждания цен, как утверждают некоторые теории. Это сложные динамические системы, где взаимодействует множество участников, каждый со своими мотивами, стратегиями, временными горизонтами. Углы, которые мы измеряем, — это не просто геометрические абстракции. Это визуализация коллективной психологии рынка, соотношения сил быков и медведей, импульсов и коррекций.
Когда вы видите последовательность углов, вы на самом деле видите "следы" рыночных участников, их решения о покупке и продаже, их страхи и надежды. И в этих следах, как оказалось, скрыты подсказки о будущем движении.
В каком-то смысле, наш метод ближе к анализу физических процессов, чем к традиционному техническому анализу. Мы смотрим не на абстрактные индикаторы, а на фундаментальные свойства ценового движения — его направление, скорость, ускорение (которые все заключены в углах).
Заключение: новый взгляд на рынок
Наше путешествие в мир угловых паттернов началось с простого вопроса: "Что, если углы наклона цены содержат ключ к будущим движениям?" Сегодня этот вопрос превратился в полноценную систему торговли, в новый способ взглянуть на рынки.
Мы не претендуем на создание безупречного индикатора. Такого не существует. Но мы предлагаем взглянуть на графики под новым углом — буквально и фигурально. Увидеть в них не просто линии и бары, а геометрический код, который можно расшифровать с помощью современных технологий.
Торговля всегда была и остается игрой вероятностей. Но чем больше у вас инструментов для анализа этих вероятностей, тем лучше ваши шансы. Угловой анализ — один из таких инструментов, возможно, самый недооцененный в современном техническом анализе.
В конце концов, рынок — это танец цен. И как в любом танце, важно не только то, куда движется танцор, но и под каким углом он делает каждый шаг.





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
3 публикации подряд, я поражаюсь, "у дураков мысли схожи" :-)
делаем примерно одно и то-же, одновременно и независимо
схожие разборки с углами, но только лошадь впереди телеги (единственное что предсказывается - личный баланс, котировки не волнуют):
про Гана скриншотить не буду, но по моему убеждению - там всё неплохо и там угол=типичная волатильность естественных циклов.
интуитивно,по личному опыту и обладая тем что под рукой, Ган вывел то что вывел. зато объективнее чем MACD :-)
И еще вопрос, если сможете ответить.
При выгрузке результатов в ONNX и реализации советника возникла проблема. При передаче данных с размерностью {1,31} в первую классификационную модель проблем нет, получаю значения
2025.04.22 19:47:28.268 test_gann (ORDIUSDT,M5) directionUpDn = 1 directionStrength=0.44935011863708496
, а вот при передаче этих же данных во вторую модель получаю все время ошибку: ONNX: parameter is empty, inspect code '° :àh½5E' (705:10). Ни один из передаваемых параметров не равен 0.
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 0, input_matrix[0][i] = -12.92599868774414
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 1, input_matrix[0][i] = -12.92599868774414
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 2, input_matrix[0][i] = -42.55295181274414
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 3, input_matrix[0][i] = 72.71257781982422
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 4, input_matrix[0][i] = 74.29901123046875
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 5, input_matrix[0][i] = -61.42539596557617
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 6, input_matrix[0][i] = 56.164878845214844
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 7, input_matrix[0][i] = -80.11347198486328
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 8, input_matrix[0][i] = 79.91580200195312
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 9, input_matrix[0][i] = -48.93017578125
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 10, input_matrix[0][i] = 80.48663330078125
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 11, input_matrix[0][i] = -79.71015930175781
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 12, input_matrix[0][i] = -45.92404556274414
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 13, input_matrix[0][i] = -82.36412048339844
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 14, input_matrix[0][i] = -56.164878845214844
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 15, input_matrix[0][i] = -10.630552291870117
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 16, input_matrix[0][i] = 62.323272705078125
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 17, input_matrix[0][i] = 13.0
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 18, input_matrix[0][i] = 10.0
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 19, input_matrix[0][i] = -12.92599868774414
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 20, input_matrix[0][i] = -61.48434829711914
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 21, input_matrix[0][i] = -36.735313415527344
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 22, input_matrix[0][i] = -23.80649185180664
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 23, input_matrix[0][i] = 0.3333333432674408
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 24, input_matrix[0][i] = 6.955999851226807
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 25, input_matrix[0][i] = 0.029581977054476738
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 26, input_matrix[0][i] = -0.5281187295913696
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 27, input_matrix[0][i] = 0.4025301933288574
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 28, input_matrix[0][i] = 420.0
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 29, input_matrix[0][i] = 641.6666870117188
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) i = 30, input_matrix[0][i] = 0.6545454263687134
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) ONNX: parameter is empty, inspect code '° :àh½5E' (705:10)
2025.04.22 19:39:38.482 test_gann (ORDIUSDT,M5) Ошибка выполнения: 5805
Может поможете с ошибкой (просторы интернета не помогли)
в нетроне сама модель отображается нормально
Опубликована статья Угловой анализ ценовых движений: гибридная модель прогнозирования финансовых рынков:
Автор: Yevgeniy Koshtenko
Метрики для bar назад = 60, вперед = 30
Train Accuracy: 0.9200 | Test Accuracy: 0.8713 | GAP: 0.0486
Train F1-score: 0.9187 | Test F1-score: 0.8682 | GAP: 0.0505
На коротких дистанциях CatBoost ничего хорошего не дает, модель переобучается