Анализ фьючерса на Brent с помощью Pandas, Sklearn, Hmmlearn

Фьючерсы на Brent являются международным эталоном для мировых цен на нефть, их мониторят нефтяные трейдеры во всем мире. Они представляют собой контракты, которые обязывают покупателя приобрести, а продавца продать определенное количество нефти в будущем по цене, согласованной сегодня.

Профессиональный анализ фьючерсов на нефть Brent может дать значительное преимущество трейдерам и инвесторам, особенно если применять современные методы анализа данных и машинного обучения. В этой статье я поделюсь методами анализа фьючерсов на нефть Brent с использованием Python и библиотек Pandas, Sklearn, Hmmlearn, которые я успешно применяю в своей работе с биржевыми данными.

Традиционные подходы к анализу фьючерсов на Brent, такие как технический анализ с использованием скользящих средних или индикаторов вроде RSI, часто оказываются недостаточно эффективными. Вместо этого, я предпочитаю использовать многофакторные модели, анализ временных рядов с учетом фундаментальных факторов и методы машинного обучения для выявления скрытых паттернов в данных.

Настройка окружения

Прежде чем углубиться в анализ, необходимо создать эффективное рабочее окружение с необходимыми инструментами. Я часто использую Jupyter Notebook для исследования данных и Python с библиотеками Pandas, NumPy, scikit-learn и PyTorch для анализа и моделирования.

Вот пример базовой настройки окружения:

# Импортируем необходимые библиотеки
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
from datetime import datetime, timedelta
import statsmodels.api as sm
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import warnings

# Отключаем предупреждения для более чистого вывода
warnings.filterwarnings('ignore')

# Настройка визуализации
plt.style.use('seaborn-v0_8-darkgrid')
plt.rcParams['figure.figsize'] = (14, 8)
plt.rcParams['font.size'] = 12
sns.set_palette('viridis')

# Настройка вывода Pandas
pd.set_option('display.max_columns', None)
pd.set_option('display.width', 200)
pd.set_option('display.float_format', '{:.4f}'.format)

Эта настройка позволяет эффективно работать с биржевыми данными и получать информативные визуализации.

Получение и предварительная обработка данных

Первым шагом в анализе фьючерсов является получение качественных исторических данных. Я обычно использую API Yahoo Finance через библиотеку yfinance, так как она обеспечивает доступ к историческим данным с достаточной частотой для большинства аналитических задач.

Вот пример кода для получения данных фьючерсов на Brent:

# Определяем период анализа - последние 5 лет
end_date = datetime.now()
start_date = end_date - timedelta(days=365*5)

# Используем тикер BZ=F для фьючерсов на нефть Brent
brent_data = yf.download('BZ=F', start=start_date, end=end_date)

# Выводим информацию о полученных данных
print(f"Период данных: {brent_data.index.min()} - {brent_data.index.max()}")
print(f"Количество торговых дней: {len(brent_data)}")
print(f"Процент пропущенных значений: {brent_data.isnull().mean().mean() * 100:.2f}%")
print("\nПервые 5 строк данных:")
print(brent_data.head())
Период данных: 2020-05-04 00:00:00 - 2025-05-01 00:00:00
Количество торговых дней: 1258
Процент пропущенных значений: 0.00%

Первые 5 строк данных:
Price Close High Low Open Volume
Ticker BZ=F BZ=F BZ=F BZ=F BZ=F
Date
2020-05-04 27.2000 28.0800 25.4800 26.2100 30309
2020-05-05 30.9700 31.6900 27.8000 27.9400 38518
2020-05-06 29.7200 32.4900 28.6700 31.8800 37505
2020-05-07 29.4600 31.8400 29.0700 30.1200 36701
2020-05-08 30.9700 31.1300 29.4000 29.4300 20277

После получения данных необходимо провести их предварительную обработку для обеспечения качества анализа. Данный этап включает в себя:

  1. Обработку пропущенных значений;
  2. Обнаружение и устранение выбросов;
  3. Проверку на стационарность;
  4. Создание дополнительных признаков.

Вот пример кода для предварительной обработки данных:

def preprocess_brent_data(df):
    # Создаем копию данных для безопасной обработки
    brent = df.copy()
    
    # Обработка пропущенных значений
    brent.fillna(method='ffill', inplace=True)
    
    # Создание дополнительных признаков
    # Логарифмические доходности
    brent['log_return'] = np.log(brent['Close'] / brent['Close'].shift(1))
    
    # Волатильность (скользящее стандартное отклонение)
    brent['volatility_20d'] = brent['log_return'].rolling(window=20).std() * np.sqrt(252)
    
    # Относительная сила (отношение к среднему за последние 60 дней)
    brent['relative_strength'] = brent['Close'] / brent['Close'].rolling(window=60).mean()
    
    # Индикатор объема (нормализованный объем)
    brent['volume_norm'] = brent['Volume'] / brent['Volume'].rolling(window=20).mean()
    
    # Временные признаки
    brent['day_of_week'] = brent.index.dayofweek
    brent['month'] = brent.index.month
    brent['quarter'] = brent.index.quarter
    
    # Удаление первых строк с NaN из-за сдвига
    brent.dropna(inplace=True)
    
    return brent

# Предобработка данных
brent_processed = preprocess_brent_data(brent_data)

# Выводим информацию о предобработанных данных
print("Статистика предобработанных данных:")
print(brent_processed.describe())
Статистика предобработанных данных:
Price      Close      High       Low      Open      Volume log_return volatility_20d relative_strength volume_norm day_of_week     month   quarter
Ticker      BZ=F      BZ=F      BZ=F      BZ=F        BZ=F                                                                                        
count  1199.0000 1199.0000 1199.0000 1199.0000   1199.0000  1199.0000      1199.0000         1199.0000   1199.0000   1199.0000 1199.0000 1199.0000
mean     78.7179   79.9293   77.4107   78.6838  30250.9199     0.0003         0.3246            1.0140      1.0119      2.0284    6.5830    2.5271
std      16.3957   16.8537   15.9536   16.4009  13297.4775     0.0219         0.1274            0.0822      0.3641      1.3961    3.5100    1.1378
min      37.4600   38.0200   35.7300   37.4200      0.0000    -0.1411         0.1268            0.8408      0.0000      0.0000    1.0000    1.0000
25%      72.2250   73.2050   71.1300   72.1000  22392.5000    -0.0112         0.2280            0.9562      0.8017      1.0000    3.0000    1.0000
50%      79.2100   80.3800   78.0800   79.2300  29152.0000     0.0020         0.3108            1.0044      1.0212      2.0000    7.0000    3.0000
75%      86.1950   87.2250   85.1850   86.3000  36260.0000     0.0135         0.3907            1.0626      1.2076      3.0000   10.0000    4.0000
max     127.9800  137.0000  122.5000  129.5700 127044.0000     0.0843         0.9174            1.4401      3.0108      4.0000   12.0000    4.000

При работе с фьючерсами важно также учитывать структуру контрактов и «контанго» (ситуация, когда цены фьючерсных контрактов с более длительным сроком истечения выше, чем с более коротким) или «бэквордацию» (обратная ситуация).

Читайте также:  Основы оценки рисков и доходности биржевого портфеля

Исследовательский анализ данных фьючерсов на Brent

После предварительной обработки данных необходимо провести всесторонний исследовательский анализ для выявления характеристик и паттернов в данных фьючерсов на нефть марки Brent. Этот этап позволяет лучше понять природу движения цен на нефть и выявить потенциальные факторы, влияющие на рынок.

Вот примеры визуализаций и анализа, которые я обычно выполняю:

def exploratory_analysis(df):
    # Визуализация изменения цены закрытия
    plt.figure(figsize=(16, 8))
    plt.plot(df.index, df['Close'], color='blue', linewidth=2)
    plt.title('Динамика цены фьючерса на Brent', fontsize=16)
    plt.xlabel('Дата', fontsize=14)
    plt.ylabel('Цена (USD)', fontsize=14)
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.show()
    
    # Анализ дневных логарифмических доходностей
    plt.figure(figsize=(16, 10))
    
    plt.subplot(2, 1, 1)
    plt.plot(df.index, df['log_return'], color='green', linewidth=1)
    plt.title('Дневные логарифмические доходности', fontsize=16)
    plt.xlabel('Дата', fontsize=14)
    plt.ylabel('Лог. доходность', fontsize=14)
    plt.grid(True, alpha=0.3)
    
    plt.subplot(2, 1, 2)
    sns.histplot(df['log_return'], kde=True, bins=50, color='green')
    plt.title('Распределение логарифмических доходностей', fontsize=16)
    plt.xlabel('Лог. доходность', fontsize=14)
    plt.ylabel('Частота', fontsize=14)
    plt.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.show()
    
    # Анализ волатильности
    plt.figure(figsize=(16, 6))
    plt.plot(df.index, df['volatility_20d'], color='red', linewidth=2)
    plt.title('20-дневная волатильность фьючерса на Brent (годовая)', fontsize=16)
    plt.xlabel('Дата', fontsize=14)
    plt.ylabel('Волатильность', fontsize=14)
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.show()
    
    # Анализ сезонности
    plt.figure(figsize=(16, 12))
    
    plt.subplot(2, 1, 1)
    monthly_returns = df.groupby(df.index.month)['log_return'].mean() * 21  # приблизительно 21 торговый день в месяце
    months = ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек']
    sns.barplot(x=months, y=monthly_returns.values, palette='viridis')
    plt.title('Средняя месячная доходность', fontsize=16)
    plt.xlabel('Месяц', fontsize=14)
    plt.ylabel('Доходность (%)', fontsize=14)
    plt.grid(True, alpha=0.3)
    
    plt.subplot(2, 1, 2)
    dow_returns = df.groupby(df.index.dayofweek)['log_return'].mean() * 100  # в процентах
    days = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт']
    sns.barplot(x=days, y=dow_returns.values, palette='viridis')
    plt.title('Средняя дневная доходность по дням недели', fontsize=16)
    plt.xlabel('День недели', fontsize=14)
    plt.ylabel('Доходность (%)', fontsize=14)
    plt.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.show()
    
    # Автокорреляция доходностей
    plt.figure(figsize=(16, 6))
    pd.plotting.autocorrelation_plot(df['log_return'])
    plt.title('Автокорреляция логарифмических доходностей', fontsize=16)
    plt.xlabel('Лаг (дни)', fontsize=14)
    plt.ylabel('Автокорреляция', fontsize=14)
    plt.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.show()
    
    # Корреляция между признаками
    plt.figure(figsize=(12, 10))
    corr_matrix = df[['Close', 'log_return', 'volatility_20d', 'relative_strength', 'volume_norm']].corr()
    sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1, linewidths=0.5)
    plt.title('Корреляционная матрица признаков', fontsize=16)
    plt.tight_layout()
    plt.show()

# Проводим исследовательский анализ
exploratory_analysis(brent_processed)

График динамики цены фьючерса на Brent

Рис. 1: График динамики цены фьючерса на Brent

Дневные логарифмические доходности фьючерса на Brent

Рис. 2: Дневные логарифмические доходности фьючерса на Brent

График 20-дневной аннуализированной волатильности фьючерса на Brent

Рис. 3: График 20-дневной аннуализированной волатильности фьючерса на Brent

Средняя месячная и средняя дневная доходность фьючерса на Brent

Рис. 4: Средняя месячная и средняя дневная доходность фьючерса на Brent

Автокорреляция логарифмических доходностей

Рис. 5: Автокорреляция логарифмических доходностей

Корреляционная матрица признаков

Рис. 6: Корреляционная матрица признаков

Этот анализ дает ценную информацию о характеристиках данных фьючерсов на Brent, включая:

  1. Общую динамику цен;
  2. Распределение доходностей;
  3. Изменение волатильности во времени;
  4. Наличие сезонных паттернов;
  5. Автокорреляцию доходностей;
  6. Взаимосвязь между различными признаками.

На основе этого анализа можно делать первые выводы о характере рынка и возможных стратегиях торговли.

Анализ рыночных режимов фьючерсов

Одним из наиболее мощных подходов к анализу рынка фьючерсов на Brent является выявление различных рыночных режимов. Вместо того, чтобы рассматривать рынок как единый непрерывный процесс, я анализирую его как смесь нескольких состояний или режимов, каждый из которых имеет свои уникальные характеристики.

Для этого я использую скрытые марковские модели (Hidden Markov Models, HMM), которые позволяют идентифицировать скрытые состояния на основе наблюдаемых данных. Это особенно полезно для рынка нефти, который часто демонстрирует различные режимы в зависимости от геополитической ситуации, состояния мировой экономики и других факторов.

!pip install hmmlearn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from hmmlearn import hmm

def analyze_market_regimes(df, n_states=3):
    # Подготовка данных для HMM
    X = np.column_stack([df['log_return'].values, df['volatility_20d'].values])
    X = StandardScaler().fit_transform(X)  # Стандартизация данных
    
    # Обучение HMM
    model = hmm.GaussianHMM(n_components=n_states, covariance_type="full", 
                           n_iter=1000, random_state=42)
    model.fit(X)
    
    # Определение скрытых состояний
    hidden_states = model.predict(X)
    
    # Создание DataFrame с состояниями
    df_with_states = df.copy()
    df_with_states['regime'] = hidden_states
    
    # Анализ характеристик каждого режима
    regime_stats = {}
    for i in range(n_states):
        regime_data = df_with_states[df_with_states['regime'] == i]
        
        if regime_data.empty:
            print(f"Режим {i} не найден в данных. Пропускаем.")
            continue
        
        regime_stats[i] = {
            'count': len(regime_data),
            'mean_return': regime_data['log_return'].mean() * 252,
            'volatility': regime_data['log_return'].std() * np.sqrt(252),
            'sharpe': (regime_data['log_return'].mean() * 252) / (regime_data['log_return'].std() * np.sqrt(252)),
            'mean_price': float(regime_data['Close'].mean()),
            'price_range': (float(regime_data['Close'].min()), float(regime_data['Close'].max()))
        }
    
    # Визуализация режимов
    plt.figure(figsize=(16, 12))
    
    plt.subplot(3, 1, 1)
    for i in range(n_states):
        regime_data = df_with_states[df_with_states['regime'] == i]
        if not regime_data.empty:
            plt.scatter(regime_data.index, regime_data['Close'], label=f'Режим {i+1}', s=15, alpha=0.7)
    plt.title('Цены фьючерсов на Brent с выделенными рыночными режимами', fontsize=16)
    plt.xlabel('Дата', fontsize=14)
    plt.ylabel('Цена (USD)', fontsize=14)
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.subplot(3, 1, 2)
    for i in range(n_states):
        regime_data = df_with_states[df_with_states['regime'] == i]
        if not regime_data.empty:
            plt.scatter(regime_data.index, regime_data['log_return'], label=f'Режим {i+1}', s=15, alpha=0.7)
    plt.title('Доходности фьючерсов на Brent с выделенными рыночными режимами', fontsize=16)
    plt.xlabel('Дата', fontsize=14)
    plt.ylabel('Лог. доходность', fontsize=14)
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.subplot(3, 1, 3)
    for i in range(n_states):
        regime_data = df_with_states[df_with_states['regime'] == i]
        if not regime_data.empty:
            plt.scatter(regime_data.index, regime_data['volatility_20d'], label=f'Режим {i+1}', s=15, alpha=0.7)
    plt.title('Волатильность фьючерсов на Brent с выделенными рыночными режимами', fontsize=16)
    plt.xlabel('Дата', fontsize=14)
    plt.ylabel('Волатильность', fontsize=14)
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.show()
    
    # Анализ переходов между режимами
    transition_probs = model.transmat_
    
    plt.figure(figsize=(10, 8))
    sns.heatmap(transition_probs, annot=True, cmap='viridis', 
               xticklabels=[f'Режим {i+1}' for i in range(n_states)],
               yticklabels=[f'Режим {i+1}' for i in range(n_states)])
    plt.title('Матрица переходов между рыночными режимами', fontsize=16)
    plt.xlabel('Конечный режим', fontsize=14)
    plt.ylabel('Начальный режим', fontsize=14)
    plt.tight_layout()
    plt.show()
    
    return df_with_states, regime_stats, model


# Пример использования функции:
brent_with_regimes, regime_statistics, hmm_model = analyze_market_regimes(brent_processed)

# Вывод статистики по режимам
print("Статистика рыночных режимов:")
for regime, stats in regime_statistics.items():
    print(f"\nРежим {regime+1}:")
    print(f"Количество дней: {stats['count']}")
    print(f"Средняя годовая доходность: {stats['mean_return']*100:.2f}%")
    print(f"Годовая волатильность: {stats['volatility']*100:.2f}%")
    print(f"Коэффициент Шарпа: {stats['sharpe']:.2f}")
    print(f"Средняя цена: ${stats['mean_price']:.2f}")
    print(f"Диапазон цен: ${stats['price_range'][0]:.2f} - ${stats['price_range'][1]:.2f}")

Цены фьючерсов на нефть Brent, их доходность и волатильность с выделенными режимами рынка методом HMM

Рис. 7: Цены фьючерсов на нефть Brent, их доходность и волатильность с выделенными режимами рынка методом HMM

Матрица переходов между рыночными режимами (начальным и конечным)

Рис. 8: Матрица переходов между рыночными режимами (начальным и конечным)

Статистика рыночных режимов:

Читайте также:  Изучаем опционы на Netflix: комплексный анализ и стратегии

Режим 1:
Количество дней: 323
Средняя годовая доходность: 26.82%
Годовая волатильность: 20.39%
Коэффициент Шарпа: 1.32
Средняя цена: $76.33
Диапазон цен: $42.66 — $96.55

Режим 2:
Количество дней: 231
Средняя годовая доходность: 44.62%
Годовая волатильность: 25.73%
Коэффициент Шарпа: 1.73
Средняя цена: $76.55
Диапазон цен: $43.22 — $96.48

Режим 3:
Количество дней: 645
Средняя годовая доходность: -15.87%
Годовая волатильность: 42.31%
Коэффициент Шарпа: -0.38
Средняя цена: $80.69
Диапазон цен: $37.46 — $127.98

Анализ фьючерсов с помощью библиотеки hmmlearn дает представление о различных рыночных режимах. Например, можно выделить режимы с высокой волатильностью и отрицательной доходностью (кризисные периоды), режимы с низкой волатильностью и положительной доходностью (стабильный рост) и т.д.

Понимание текущего рыночного режима и вероятности перехода между режимами может дать значительное преимущество в прогнозировании будущего движения цен.

Анализ межрыночных взаимосвязей фьючерсов

Для полного понимания динамики фьючерсов на нефть Brent важно также анализировать их взаимосвязи с другими финансовыми инструментами и рынками. Я часто исследую корреляции между фьючерсами на Brent и индексами акций, валютными парами, другими товарами и процентными ставками.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
from statsmodels.tsa.vector_ar.var_model import VAR


def load_market_data(start_date, end_date):
    tickers = {
        'brent': 'BZ=F',
        'sp500': '^GSPC',
        'eurusd': 'EURUSD=X',
        'gold': 'GC=F',
        'natgas': 'NG=F',
        'treasury': '^TNX'
    }
    raw = yf.download(
        tickers=list(tickers.values()),
        start=start_date,
        end=end_date + pd.Timedelta(days=1),
        progress=False,
        group_by='ticker',
        auto_adjust=True
    )
    closes = pd.DataFrame()
    for name, ticker in tickers.items():
        try:
            closes[name] = raw[(ticker, 'Close')]
        except KeyError:
            print(f"[!] No data for {name} ({ticker})")
    return closes


def analyze_cross_market_relationships(start_date='2020-01-01', end_date=None):
    if end_date is None:
        end_date = pd.Timestamp.today().normalize()

    prices = load_market_data(pd.to_datetime(start_date), end_date).dropna()
    returns = np.log(prices / prices.shift(1)).dropna()
    returns.columns = [f"{c}_return" for c in returns.columns]

    # Correlation heatmap
    plt.figure(figsize=(12, 10))
    sns.heatmap(returns.corr(), annot=True, cmap='coolwarm', vmin=-1, vmax=1, linewidths=0.5)
    plt.title('Correlation matrix of log-returns', fontsize=16)
    plt.tight_layout()
    plt.show()

    # Rolling correlations
    window = 60
    rolling_corrs = pd.DataFrame(index=returns.index)
    for col in returns.columns:
        if col != 'brent_return':
            rolling_corrs[f"corr_brent_{col}"] = (
                returns['brent_return'].rolling(window).corr(returns[col])
            )
    plt.figure(figsize=(16, 10))
    for col in rolling_corrs:
        plt.plot(rolling_corrs.index, rolling_corrs[col], label=col.replace('corr_brent_', '').replace('_return', ''))
    plt.axhline(0, color='black', linestyle='--', alpha=0.3)
    plt.title(f'Rolling correlation with Brent ({window} days)', fontsize=16)
    plt.legend()
    plt.grid(alpha=0.3)
    plt.tight_layout()
    plt.show()

    # VAR analysis (min lags = 1)
    var_cols = ['brent_return', 'sp500_return', 'gold_return', 'natgas_return']
    var_df = returns[var_cols].dropna()

    if len(var_df) > 60:
        model = VAR(var_df)
        selected = model.select_order(maxlags=10).selected_orders['aic']
        # enforce at least 1 lag
        lag = max(selected, 1)
        print(f"Selected lags (AIC): {selected}. Using lag = {lag}.")

        results = model.fit(lag)
        print(results.summary())

        irf = results.irf(10)
        for imp in var_cols:
            irf.plot(impulse=imp)
            plt.suptitle(f"IRF: Shock to {imp}", fontsize=16)
            plt.tight_layout()
            plt.show()
    else:
        print("Not enough data for VAR model (need >60 observations).")
        results = None

    merged = prices.join(returns)
    return merged, rolling_corrs, results

# Run function
df, rolling, var_res = analyze_cross_market_relationships(start_date='2024-10-01')

Корреляционная матрица лог-доходностей между фьючерсом на Brent, индексом SP500, валютной парой EUR-USD, ценами на золото, фьючерсами на газ, 10-летними гос. облигациями США

Рис. 9: Корреляционная матрица лог-доходностей между фьючерсом на Brent, индексом SP500, валютной парой EUR-USD, ценами на золото, фьючерсами на газ, 10-летними гос. облигациями США

График скользящей 60-дневной корреляции фьючерса на нефть Brent с индексом SP500, валютной парой EUR-USD, ценами на золото, фьючерсами на газ, 10-летними гос. облигациями США

Рис. 10: График скользящей 60-дневной корреляции фьючерса на нефть Brent с индексом SP500, валютной парой EUR-USD, ценами на золото, фьючерсами на газ, 10-летними гос. облигациями США

Selected lags (AIC): 0. Using lag = 1.
  Summary of Regression Results   
==================================
Model:                         VAR
Method:                        OLS
Date:           Thu, 01, May, 2025
Time:                     19:11:32
--------------------------------------------------------------------
No. of Equations:         4.00000    BIC:                   -31.0238
Nobs:                     143.000    HQIC:                  -31.2698
Log likelihood:           1456.20    FPE:                2.22139e-14
AIC:                     -31.4382    Det(Omega_mle):     1.93607e-14
--------------------------------------------------------------------
Results for equation brent_return
===================================================================================
                      coefficient       std. error           t-stat            prob
-----------------------------------------------------------------------------------
const                   -0.001456         0.001640           -0.888           0.375
L1.brent_return         -0.015895         0.095397           -0.167           0.868
L1.sp500_return         -0.087754         0.122993           -0.713           0.476
L1.gold_return           0.110820         0.148056            0.749           0.454
L1.natgas_return         0.025362         0.032547            0.779           0.436
===================================================================================

Results for equation sp500_return
===================================================================================
                      coefficient       std. error           t-stat            prob
-----------------------------------------------------------------------------------
const                   -0.000113         0.001193           -0.095           0.925
L1.brent_return          0.023886         0.069371            0.344           0.731
L1.sp500_return         -0.078986         0.089438           -0.883           0.377
L1.gold_return           0.044156         0.107664            0.410           0.682
L1.natgas_return        -0.040390         0.023668           -1.707           0.088
===================================================================================

Results for equation gold_return
===================================================================================
                      coefficient       std. error           t-stat            prob
-----------------------------------------------------------------------------------
const                    0.001492         0.000996            1.497           0.134
L1.brent_return         -0.019540         0.057949           -0.337           0.736
L1.sp500_return          0.161808         0.074713            2.166           0.030
L1.gold_return          -0.064105         0.089937           -0.713           0.476
L1.natgas_return         0.011137         0.019771            0.563           0.573
===================================================================================

Results for equation natgas_return
===================================================================================
                      coefficient       std. error           t-stat            prob
-----------------------------------------------------------------------------------
const                    0.000831         0.004269            0.195           0.846
L1.brent_return         -0.142671         0.248269           -0.575           0.566
L1.sp500_return          0.015541         0.320088            0.049           0.961
L1.gold_return           0.299757         0.385314            0.778           0.437
L1.natgas_return        -0.165157         0.084704           -1.950           0.051
===================================================================================

Correlation matrix of residuals
                 brent_return  sp500_return  gold_return  natgas_return
brent_return         1.000000      0.335626     0.373030       0.119037
sp500_return         0.335626      1.000000     0.151260       0.090234
gold_return          0.373030      0.151260     1.000000       0.013505
natgas_return        0.119037      0.090234     0.013505       1.000000

Анализ функций импульсного отклика - отклик всех переменных на шок в Brent

Рис. 11: Анализ функций импульсного отклика — отклик всех переменных на шок в ценах нефти Brent

Отклик всех активов на шок в котировках SP500

Рис. 12: Отклик всех активов на шок в котировках SP500

Отклик всех активов на шок в ценах на золото

Рис. 13: Отклик всех активов на шок в ценах на золото

Отклик всех активов на шок в ценах на природный газ

Рис. 14: Отклик всех активов на шок в ценах на природный газ

Данный тип анализа помогает выявить, как фьючерсы на Brent взаимодействуют с другими рынками, что может быть использовано для прогнозирования цен и хеджирования рисков.

Читайте также:  Что такое алгоритмическая торговля и как она работает?

Заключение

В данной статье мы провели комплексный анализ фьючерсов на нефть марки Brent с использованием современных методов обработки данных. Применяя библиотеки Pandas, Sklearn и Hmmlearn, мы смогли выявить ключевые характеристики и закономерности в поведении цен на нефтяные фьючерсы.

Исследование показало, что рынок фьючерсов Brent не является однородным и характеризуется наличием различных рыночных режимов, которые можно эффективно идентифицировать с помощью скрытых марковских моделей.

Выделенные три режима демонстрируют существенные различия по уровню волатильности, средней доходности и коэффициенту Шарпа. Особенно интересно наблюдать контраст между режимом 2 с высокой годовой доходностью (44.62%) и положительным коэффициентом Шарпа (1.73), и режимом 3 с отрицательной доходностью (-15.87%) и более высокой волатильностью (42.31%). Понимание текущего режима рынка и вероятностей перехода между ними может дать трейдерам значительное преимущество при принятии торговых решений.

Проведенный межрыночный анализ выявил динамические взаимосвязи между фьючерсами Brent и другими финансовыми инструментами. Скользящие корреляции продемонстрировали изменчивость взаимоотношений нефтяных фьючерсов с индексом S&P 500, золотом, валютными парами и другими товарами, что подтверждает необходимость регулярного пересмотра стратегий хеджирования и диверсификации. Примененный VAR-анализ позволил оценить эффекты распространения шоков между рынками и выявить статистически значимые взаимосвязи.

Результаты исследовательского анализа данных показали наличие сезонных паттернов в доходности фьючерсов Brent как по месяцам, так и по дням недели, что может быть использовано при разработке краткосрочных торговых стратегий.

Представленные в статье методы и результаты демонстрируют, что современные технологии анализа данных открывают новые горизонты для понимания и прогнозирования рынка нефтяных фьючерсов, позволяя преодолеть ограничения традиционных подходов к техническому и фундаментальному анализу.