Статистический арбитраж на коинтегрированных акциях (Часть 2): Советник, тестирование и оптимизация
Введение
Мы взяли на себя задачу разработать систему статистического арбитражного трейдинга, доступную для обычного розничного трейдера. Основная идея заключается в том, чтобы собрать набор статистических функций и методов анализа, которые позволят розничному трейдеру, имеющему в своем распоряжении лишь обычный ноутбук и стандартный брокерский счет, начать заниматься статистическим арбитражем на рынках Форекс, акций, ETF и сырьевых товаров.
Мы начали с простой стратегии парной торговли, основанной на корреляции, которая продемонстрировала отличный потенциал при тестировании на исторических данных, но потерпела полную неудачу на демо-счете. Несложно было прийти к выводу, что мы терпели убытки на этапе исполнения ордеров. То есть наша стратегия в значительной степени зависела от скорости исполнения ордеров, но наша инфраструктура (потребительский ноутбук, медленное интернет-соединение и прототипный код) даже близко не соответствовала требованиям, необходимым для такого вида арбитража. Наши правила входа/выхода в рынок в значительной степени зависели от выбора момента, и возможность арбитража закрывалась ещё до того, как наши ордера поступали на сервер брокера.
Мы могли бы попытаться решить, минимизировать или обойти проблему с временем выполнения, настроив VPN (что мы и сделаем в будущем), открыв профессиональный аккаунт с максимально допустимым проскальзыванием или попытавшись усовершенствовать код нашего прототипа. Каждая из этих очевидных и относительно недорогих мер могла бы оказать некоторую помощь, а их совместное применение, несомненно, вернуло бы нашу стратегию на правильный путь. Однако, поскольку мы хотим сохранить наше первоначальное ограничение — быть полезными для обычного розничного трейдера с минимальными ресурсами, — вместо того, чтобы заниматься вопросами скорости исполнения, мы поставили перед собой цель разработать стратегию, которая не была бы столь зависимой от скорости исполнения. Описанная ниже реализация представляет собой один из возможных вариантов решения этой задачи.
В предыдущей статье мы рассмотрели тесты коинтеграции Энгл-Грейнджера и Йохансена, их обоснование с точки зрения трейдера, а также их основную интерпретацию. Теперь мы будем использовать их для формирования нашего коинтегрированного портфеля.
Формирование портфеля коинтегрированных акций
Пьяница, собака и случайная прогулка*
При изучении коинтеграции очень часто встречается аналогия, которая довольно хорошо объясняет основную особенность коинтегрированных временных рядов — в данном случае коинтегрированных цен на акции. Согласно этой аналогии, два некоинтегрированных временных ряда похожи на пьяницу, выгуливающего собаку. Их пути расходятся совершенно случайно, без какой-либо внутренней, видимой или измеримой логики. Человек и собака могут даже вернуться домой разными путями, а собака может даже потеряться навсегда.
Но два коинтегрированных временных ряда можно было бы сравнить с собакой, которую ведут за ошейник: то есть человек по-прежнему пьян, его шаги по-прежнему шаткие, но их пути всё равно идут вместе, что бы ни случилось. Коинтегрированные акции — это как будто их цены скованы "невидимым" ошейником. В конечном итоге они, как правило, приходят домой вместе. Среднее значение — это среднее арифметическое.
Но как найти эти коинтегрированные акции среди тысяч ценных бумаг? К счастью, мы уже знаем, что некоторые акции одного сектора или отрасли, как правило, движутся синхронно. Эти знания позволяют сократить исходное количество до более управляемого, но оно по-прежнему остается значительным.
Рис.1. Количество символов, доступных на демо-сервере MetaQuotes
Рис.2. Количество биржевых кодов, доступных по странам на демо-сервере коммерческого брокера
В научной литературе уже рассмотрено несколько классических и «новых» методов отбора акций для парной торговли, однако, в конечном счете, ни один из них не дал лучших результатов, чем метод коинтеграции [Brunetti& De Luca, 2023].
Поскольку наша цель здесь заключается не в академическом обзоре, а в тестировании на исторических данных и описании примерной реализации, я использовал простую эвристику для формирования нашего небольшого портфеля.
"Эвристика (...) — это любой подход к решению задач, в котором используется прагматичный метод, не являющийся полностью оптимизированным, усовершенствованным или рационализированным, но тем не менее «достаточно хорошим» в качестве приближения" (Википедия)
- Выберите несколько акций компаний из списка Nasdaq с высокой ликвидностью, все из которых относятся к сектору полупроводников. Можно начать с нескольких десятков.
- Среди них выберите те, которые за последние шесть месяцев или менее демонстрировали наибольшую корреляцию с акциями Nvidia на дневном графике. Не следует использовать длительные периоды анализа, поскольку нас интересуют недавние изменения, а мы имеем дело с очень динамичным рынком (ИИ и полупроводники). Кроме того, мы будем обновлять нашу модель ежемесячно или еженедельно, поэтому использование этого первоначального фильтра в течение шести месяцев или менее может помочь вам встать на правильный путь.
- Проверить небольшую группу — наиболее коррелирующую с Nvidia — на коинтеграцию.
- Как только вы найдете хотя бы один значимый вектор Йохансена, проверьте стационарность коинтегрированного спреда.
- Если у вас есть небольшая группа, содержащая хотя бы один значимый вектор Йохансена со стационарным коинтегрированным спредом, то для получения относительных весов портфеля воспользуйтесь первым собственным вектором Йохансена.
- Имея веса портфеля, вы можете провести бэктестинг коинтегрированной корзины акций.
Используя метод корреляции Пирсона, о котором мы говорили в предыдущей статье, мы сузили наш портфель до трёх акций, перечисленных ниже. Все три компании заинтересованы в спросе на аппаратное обеспечение для искусственного интеллекта и входят в цепочку поставок Nvidia — либо напрямую, либо через смежные рынки.
Microchip Technology, Inc. (MCHP) - Компания MCHP не связана напрямую с графическими процессорами Nvidia, однако она получает выгоду от роста общего спроса в секторе полупроводников на инфраструктуру, связанную с искусственным интеллектом, такую как робототехника и промышленный ИИ, со стороны OEM-производителей и системных интеграторов, работающих с системами на базе Nvidia.
Monolithic Power System Inc (MPWR) - компания MPWR поставляет интегральные схемы управления питанием (PMIC) для серверов и центров обработки данных. Эти PMIC также используются в высокопроизводительных графических процессорах Nvidia, которым требуется высокоспециализированное регулирование питания для обеспечения тепловой и электрической стабильности при высоких нагрузках. Компания MPWR извлекает выгоду из расширения деятельности Nvidia в сфере центров обработки данных и инференса.
Micron Technology Inc. (MU) - Компания MU поставляет продукты памяти, в том числе память с высокой пропускной способностью (HBM), которая имеет решающее значение для ускорителей искусственного интеллекта, таких как H100 от Nvidia. Ее продукты для хранения данных используются в графических процессорах Nvidia, а также в решениях для центров обработки данных. По мере того как Nvidia увеличивает объемы продаж чипов для искусственного интеллекта, спрос на передовую память компании Micron резко растёт. Компания Micron обнародовала оптимистичные прогнозы на 2024–2025 годы, основанные на развитии искусственного интеллекта, напрямую увязав свои перспективы роста с результатами деятельности компании Nvidia.
Выбранные нами акции — это не самая важная информация в данном случае. Вместо этого сосредоточьтесь на выборе показателя, который наиболее тесно коррелирует с тем символом, который вы берете за основу, то есть с основой вашей гипотезы. В нашем случае это был NVDA, но это может быть любой символ, соответствующий вашей гипотезе.
Нам НЕ нужны акции, которые демонстрируют исключительно высокую корреляцию с NVDA и низкую корреляцию между собой. Вместо этого нам нужны акции, которые сильно коррелируют с NVDA и при этом имеют достаточно высокую корреляцию друг с другом. В некотором смысле нам нужна группа акций, коррелирующих с нашим эталоном, поскольку это свойство соответствует нашей гипотезе, когда мы приступаем к отбору: мы ищем коррелирующую корзину.
Нам нужна именно такая матрица корреляции Пирсона
| NVDA | MCHP | MPWR | MU | |
|---|---|---|---|---|
| NVDA | 1.000000 | 0.916887 | 0.894362 | 0.897219 |
| MCHP | 0.916887 | 1.000000 | 0.877042 | 0.941977 |
| MPWR | 0.894362 | 0.877042 | 1.000000 | 0.852675 |
| MU | 0.897219 | 0.941977 | 0.852675 | 1.000000 |
Таблица 1. Матрица корреляции Пирсона между NVDA, MCHP, MPWR и MU
Эти данные проще просматривать в виде тепловой карты в Seaborn.
import seaborn as sns sns.heatmap(corr_matrix, annot=True, cmap="coolwarm")

Рис.3. Матрица корреляции Пирсона для NVDA, MCHP, MPWR и MU, отображенная в виде тепловой карты Seaborn
Следует отметить, что, хотя между показателями MCHP, MPWR и MU и показателем NVDA нет особо высокой корреляции, все они умеренно коррелируют друг с другом.
Обратите внимание, что во время торговли нам понадобятся тики по четырём активам для расчета спреда, который определяет наши точки входа и выхода. Именно это и стало главной причиной, по которой мы изначально начали отбирать активы с высокой ликвидностью. Мы не хотим иметь неликвидные активы, которые могут "выпасть из синхронизации" или отклоняться от нашего обработчика событий OnTick более чем на пару секунд (см. ниже).
После определения данной коррелированной корзины мы проводим тест коинтеграции Энгл-Грэнджера для оценки уровня коинтеграции отдельных пар, а также тест коинтеграции Йохансена для проверки уровня коинтеграции корзины, то есть уровня коинтеграции группы активов. Более подробное описание этих двух тестов вы можете найти в предыдущей статье.
Затем мы получаем коэффициенты хеджирования портфеля из собственного вектора Йохансена.
Веса портфеля (собственный вектор Йохансена):
MCHP-2.505294
Собственный вектор Йохансена представляет собой список чисел, по одному для каждой акции в вашей группе, который показывает вес или значимость каждой акции для поддержания стабильной взаимосвязи, выявленной с помощью теста Йохансена. Эти веса гарантируют, что при объединении акций — путем их покупки или продажи в определённых пропорциях — их совокупные ценовые колебания образуют в целом предсказуемую и более или менее стабильную картину.
Эти показатели будут использоваться для сбалансирования объема наших заказов и минимизации наших рыночных рисков. Помните, что в стратегиях статистического арбитража мы всегда стремимся к рыночной нейтральности. Взвешенный портфель можно рассматривать как усовершенствованную версию той простой методики парной торговли, при которой мы одновременно покупаем/продаем по одной единице каждого инструмента.
Эти веса портфеля вы найдете среди глобальных переменных нашего примера советника.
// Global variables string symbols[] = {"MU", "NVDA", "MPWR", "MCHP"}; // Asset symbols double weights[] = {2.699439, 1.000000, -1.877447, -2.505294}; // Johansen eigenvector
Показатель NVDA равен 1,0, поскольку в нашем коде на Python (прилагается) мы решили выполнить нормализацию по первому элементу списка символов, которым является NVDA. Нормализация позволяет нам получить относительную интерпретацию остальных значений. Вы можете выбрать для нормализации любой другой символ из списка Python. Это произвольная ссылка.
# === FIRST COINTEGRATION VECTOR === v = johansen_result.evec[:, 0] # v = v / v[-1] # Normalize on symbols list last asset v = v / v[0] # Normalize on symbols list first asset
Теперь мы можем проверить многомерную дисперсию на стационарность.

Рис.4. График многомерного коинтегрированного спреда для NVDA, MCHP, MPWR и MU
Визуальный анализ распределения многомерных данных — это надежный способ оценить его пригодность для использования в стратегии возврата к среднему значению. Визуальный осмотр позволяет быстро оценить распределение отклонений вокруг среднего значения, возвращение отклонений к среднему значению, а также его возможную стационарность. Отсутствие видимой тенденции является весомым признаком стационарности, равно как и отсутствие сезонности.
Однако визуального осмотра недостаточно, и его нельзя использовать в автоматизированных моделях и при обновлении портфелей. К счастью, на помощь нам приходят тесты Augmented Dickey Fuller (ADF) и Kwiatkowski-Phillips-Schmidt-Shin (KPSS).
Используйте тесты ADF и KPSS, чтобы подтвердить, что распределение возвращается к среднему значению.
# Augmented Dickey-Fuller Test from statsmodels.tsa.stattools import adfuller adf_result = adfuller(spread, regression='c') # 'ct' for trend and constant print("ADF Test on Spread:") print(f" ADF Statistic : {adf_result[0]:.4f}") print(f" p-value : {adf_result[1]:.4f}") print(f" Critical Values:") for key, value in adf_result[4].items(): print(f" {key}: {value:.4f}") if adf_result[1] < 0.05: print("\n✅ The cointegrated spread is stationary (reject the null hypothesis).") else: print("\n❌ The cointegrated spread is NOT stationary (fail to reject the null hypothesis).")
Тест ADF на рассеяние:
Критические значения:
10%: -2.5761
✅ Коинтегрированный спред является стационарным (отклоняем нулевую гипотезу).
# KPSS Test from statsmodels.tsa.stattools import kpss def run_kpss(series, regression='c'): statistic, p_value, lags, crit_values = kpss(series, regression=regression, nlags='auto') print("KPSS Test on Spread:")
Тест KPSS по темам:
Критические значения:
1%: 0.739
✅ Коинтегрированный спред является стационарным (не удалось опровергнуть нулевую гипотезу о стационарности).
Этот шаг имеет решающее значение. Без стационарного разброса наша гипотеза о возвращении к среднему значению теряет всякую силу. Без фиксированного спреда цены могут продолжать расходиться, и мы можем оказаться с «висящими» позициями, которые так и не закроются должным образом в результате возврата к среднему значению. В рамках подобной стратегии крайне важно исходить из того, что спред является стационарным.
В дальнейшем, по мере развития нашей системы статистического арбитража, мы будем осуществлять ротацию нашего портфеля в автоматическом режиме. Таким образом, наличие этих тестов на стационарность в нашем арсенале инструментов имеет первостепенное значение, поскольку мы не можем полагаться исключительно на визуальную оценку графиков.
Пример реализации
В нашей примерной реализации сначала определяются пороговые значения для точек входа/выхода в виде стандартных отклонений от среднего значения.
// Input parameters input double EntryThreshold = 2.0; // Entry threshold (standard deviations) input double ExitThreshold = 0.3; // Exit threshold (standard deviations) input double LotSize = 10.0; // Fixed lot size per leg input int LookbackPeriod = 252; // Lookback for moving average/standard deviation input int Slippage = 3; // Max allowed slippage
Стандартный размер лота в 10,0 единиц должен упростить проверку весов портфеля в ордерах при тестировании на исторических данных.
Максимально допустимый проскальзывание здесь носит скорее символический характер, поскольку мы разрабатываем продукт для обычного розничного трейдера, а эта функция, как правило, доступна только владельцам профессиональных торговых счетов. Но не помешает иметь это наготове для будущих улучшений. Сервер брокера просто проигнорирует этот параметр, если на торговом счете эта функция отключена.
Период, используемый для расчета скользящего среднего и стандартных отклонений, может совпадать с периодом, применяемым для тестов на корреляцию и коинтеграцию, однако это не является обязательным условием. Как только мы обнаружим коинтеграцию на дневном графике за последние шесть месяцев, можно без проблем перейти к торговле на часовом графике, например, с двухнедельным периодом обратного анализа. Система достаточно гибкая, чтобы давать возможность экспериментировать, и именно в этой гибкости заключается множество возможностей.Несколько замечаний о конкретных функциях кода.
OnInit()
// Check if all symbols are available for(int i = 0; i < ArraySize(symbols); i++) { if(!SymbolSelect(symbols[i], true)) { Print("Error: Symbol ", symbols[i], " not found!"); return(INIT_FAILED); } }
Мы проверяем, доступны ли все символы из нашей корзины в Market Watch для запроса котировок.
// Set a timer for spread, mean, and stdev calculations EventSetTimer(1); // one second
Мы устанавливаем таймер для вычисления диапазона, среднего значения и стандартного отклонения вне функции OnTick(). Это связано с тем, что, как вы, вероятно, знаете, обработчик событий OnTick привязан к графику/символу, на котором запущен советник. Пока для этого символа нет обновлений, событие OnTick не срабатывает. Мы не хотим зависеть от этих обновлений. Используя таймер, в данном случае с интервалом в одну секунду, мы можем быть уверены, что с такой периодичностью будет выполняться проверка наличия новых котировок. Мы переходим от пассивного обновления предложений к активному обновлению предложений.
OnTimer()
void OnTimer(void) { // Calculate current spread value currentSpread = CalculateSpread(); // Update spread buffer (rolling window) static int barCount = 0; if(barCount < LookbackPeriod) { spreadBuffer[barCount] = currentSpread; barCount++; return; // Wait until buffer is filled } // Shift buffer (remove oldest value, add newest) for(int i = 0; i < LookbackPeriod - 1; i++) spreadBuffer[i] = spreadBuffer[i + 1]; spreadBuffer[LookbackPeriod - 1] = currentSpread; // Calculate mean and standard deviation using custom functions spreadMean = CalculateMA(spreadBuffer, LookbackPeriod); spreadStdDev = CalculateStdDev(spreadBuffer, LookbackPeriod, spreadMean); }
В обработчике события OnTimer мы просматриваем историю графика за указанный период, чтобы рассчитать диапазон, среднее значение и стандартное отклонение.
OnTick()
void OnTick() { // Trading logic if(!tradeOpen) { // Check for entry signal (spread deviates from mean) if(currentSpread > spreadMean + EntryThreshold * spreadStdDev) { // Short spread (sell MU/NVDA, buy MPWR/MCHP) ExecuteTrade(ORDER_TYPE_SELL); tradeOpen = true; } else if(currentSpread < spreadMean - EntryThreshold * spreadStdDev) { // Buy spread (buy MU/NVDA, sell MPWR/MCHP) ExecuteTrade(ORDER_TYPE_BUY); tradeOpen = true; } } else { // Check for exit signal (spread reverts to mean) if((currentSpread <= spreadMean + ExitThreshold * spreadStdDev) && (currentSpread >= spreadMean - ExitThreshold * spreadStdDev)) { CloseAllTrades(); tradeOpen = false; } } // Display spread in chart Comment(StringFormat("Spread: %.2f | Mean: %.2f | StdDev: %.2f", currentSpread, spreadMean, spreadStdDev)); }
Обработчик событий OnTick() содержит исключительно торговую логику. Если мы не находимся на рынке (!tradeOpen()), но у нас есть торговый сигнал, мы совершаем покупку или продажу в соответствии с весами портфеля, полученными из собственного вектора Йохансена.
ExecuteTrade(ENUM_ORDER_TYPE orderType)
//+------------------------------------------------------------------+ //| Execute trade with normalized integer lots | //+------------------------------------------------------------------+ void ExecuteTrade(ENUM_ORDER_TYPE orderType) { double volumeArray[]; ArrayResize(volumeArray, ArraySize(symbols)); if(!NormalizeVolumeToIntegerLots(volumeArray, symbols, weights, LotSize)) { Print("Volume normalization failed!"); return; } for(int i = 0; i < ArraySize(symbols); i++) { ENUM_ORDER_TYPE legType = (weights[i] > 0) ? orderType : (orderType == ORDER_TYPE_BUY ? ORDER_TYPE_SELL : ORDER_TYPE_BUY); trade.PositionOpen(symbols[i], legType, volumeArray[i], 0, 0, 0, "NVDA Coint"); } } (...) //+------------------------------------------------------------------+ //| Normalize volumes to integer lots | //+------------------------------------------------------------------+ bool NormalizeVolumeToIntegerLots(double &volumeArray[], const string &symbols_arr[], const double &weights_arr[], double baseLotSize) { MqlTick tick; // Structure to store bid/ask prices double totalDollarExposure = 0.0; double dollarExposures[]; ArrayResize(dollarExposures, ArraySize(symbols_arr)); // Step 1: Calculate dollar exposure for each leg for(int i = 0; i < ArraySize(symbols_arr); i++) { if(!SymbolInfoTick(symbols_arr[i], tick)) // Get latest bid/ask { Print("Failed to get price for ", symbols_arr[i]); return false; } // Use bid price for short legs, ask for long legs double price = (weights_arr[i] > 0) ? tick.ask : tick.bid; dollarExposures[i] = MathAbs(weights_arr[i]) * price * baseLotSize; totalDollarExposure += dollarExposures[i]; } // Step 2: Convert dollar exposure to integer lots for(int i = 0; i < ArraySize(symbols_arr); i++) { double ratio = dollarExposures[i] / totalDollarExposure; double targetDollarExposure = ratio * totalDollarExposure; // Get min/max lot size and step for the symbol double minLot = SymbolInfoDouble(symbols_arr[i], SYMBOL_VOLUME_MIN); double maxLot = SymbolInfoDouble(symbols_arr[i], SYMBOL_VOLUME_MAX); double lotStep = SymbolInfoDouble(symbols_arr[i], SYMBOL_VOLUME_STEP); // Get current price again (for lot calculation) if(!SymbolInfoTick(symbols_arr[i], tick)) return false; double price = (weights_arr[i] > 0) ? tick.ask : tick.bid; double lots = targetDollarExposure / price; lots = MathFloor(lots / lotStep) * lotStep; // Round down to nearest step // Clamp to broker constraints using custom Clamp() volumeArray[i] = Clamp(lots, minLot, maxLot); } return true; }
Бэктест

Рис.5. Кривая капитала, полученная в результате бэктеста коинтегрированной корзины Nasdaq за первые пять месяцев 2025 года на дневном таймфрейме
Кривая капитала показывает, что наша гипотеза является жизнеспособной, хотя для предотвращения некоторых резких падений требуется стратегия управления капиталом, которая пока не реализована.
Рис.6. Сводка результатов бэктеста коинтегрированной корзины Nasdaq за первые пять месяцев 2025 года на дневном таймфрейме
Как вы видите, качество нашей истории цен оставляет желать лучшего, но это всё, что у нас есть в бесплатном доступе для этих четырёх тикеров, поэтому мы работаем с тем, что имеем. При применении этой стратегии в торговле на реальные деньги настоятельно рекомендуется уделять больше внимания качеству ценовой истории.
Рис.7. Результаты бэктеста по периодам, полученные в ходе бэктеста коинтегрированной корзины Nasdaq за первые пять месяцев 2025 года на дневном таймфрейме
Рис.8. Время удержания позиций по результатам бэктеста коинтегрированной корзины Nasdaq за первые пять месяцев 2025 года на дневном таймфрейме
Средняя продолжительность удержания позиции в ~20 минут представляется оптимальной, поскольку мы избегаем тех одно-двухсекундных удержаний позиций, которые были характерны для нашей первой (неудачной) попытки, описанной в первой части этой статьи.
Рис.9. Бэктест коинтегрированной корзины Nasdaq с использованием показателей MFE и MAE за первые пять месяцев 2025 года на дневном таймфрейме
Коинтеграция за пределами фондового рынка
Это вполне удовлетворительные результаты для нашей первой корзины коинтегрированных акций одного сектора. При внедрении некоторых улучшений, таких как грамотное управление капиталом и использование более качественных данных для оптимизации, мы можем рассчитывать на то, что у нас появится подходящий вариант, который можно будет протестировать на демо-счете в течение пары недель.
Но, как вы, вероятно, уже поняли, это весьма общее решение, в котором мы используем лишь очень небольшую подгруппу акций Nasdaq при ещё более ограниченном сочетании периода обратного просмотра для теста коинтеграции и временного интервала. То есть мы используем четыре индекса, коинтеграция которых проверялась за последние шесть месяцев на дневном таймфрейме. Если вы начнете комбинировать эти параметры, то, возможно, обнаружите десятки вариантов, заслуживающих внимания.
Кроме того, вы не ограничены акциями Nasdaq и даже не ограничены только акциями. Вы можете провести тесты на коинтеграцию различных активов, сравнивая акции и ETF или отраслевые индексы.
Несколько примеров
Вот несколько примеров коинтеграции, проверенных за последние шесть месяцев (180 дней) на дневном таймфрейме.
ETF, связанные с золотом
symbols = ['AAAU', 'USGO', 'BGLD']
1. AAAU — ETF на физическое золото от Goldman Sachs
"AAAU — это биржевой инвестиционный фонд, цель которого — отражать динамику цен на золото в слитках. Фонд владеет физическими золотыми слитками, хранящимися в надежных хранилищах, и инвесторы могут обменять свои паи на реальное золото (при соблюдении определенных условий). Фонд AAAU разработан для обеспечения прямого доступа к ценам на золото с минимальной погрешностью отслеживания и без использования производных финансовых инструментов".
2. USGO — ETF на акции компании Abrdn Physical Gold
"USGO — это ETF на золото с физическим обеспечением, управляемый компанией Aberdeen Investments. Подобно AAAU, он стремится отслеживать цену на золотые слитки, удерживая выделенное физическое золото, хранящееся в надежных хранилищах. Это предлагает инвесторам простой и экономичный способ получить доступ к инвестициям в золото, не принимая его на хранение самостоятельно."
3. BGLD — ETF с целевым доходом по стратегии "FT Vest Gold"
"BGLD — это ETF с активно управляемой стратегией, ориентированный на золото, цель которого — обеспечить доход и доступ к инвестициям в золото. В отличие от AAAU и USGO, BGLD не владеет физическим золотом напрямую. Вместо этого он использует сочетание производных инструментов, связанных с золотом (таких как фьючерсы и опционы), и стратегий, направленных на получение дохода, чтобы обеспечить целевую доходность, схожую с динамикой цен на золото, с акцентом на получение ежемесячного дохода.
Index(['AAAU', 'USGO', 'BGLD'], dtype='object')
Результаты теста коинтеграции Энгл-Грейнджера:
USGO и BGLD | p-значение: 0,0144
Наиболее коинтегрированная пара (по Энглу-Грейнджеру): USGO и BGLD | p-значение: 0,0144
Помните, что тест Энгл-Грейнджера проверяет только парные связи. Этот тест не выявит взаимодействий между всеми элементами корзины, которые выявляет тест Йохансена.
Результаты теста Йохансена (статистика следа):
Количество наблюдений: 119Количество переменных: 3
Ранг 2: Показатель Trace = 4,25 | Коэффициент вариации 5 % = 3,84 | Статистически значимо
С помощью теста Йохансена можно определить количество коинтеграционных отношений во всей совокупности для каждого ранга.
На уровне значимости 0 показатель трассировки (30,21) превышает критическое значение на уровне 5% (29,80), что указывает на наличие по крайней мере одного вектора коинтеграции. На 1-м ранге тест не является значимым, но на 2-м ранге он вновь становится значимым (4,25> 3,84), что указывает на наличие второй коинтеграционной связи.
Согласно результатам Энгл-Грейнджера, мы видим, что AAAU-BGLD (p = 0,0209) и USGO-BGLD (p = 0,0144) являются значительно «более коинтегрированными», чем AAAU-USGO (p = 0,1322), что указывает на наличие двух независимых коинтегрирующих векторов среди этих трех активов и, вероятно, на наличие сильной и стабильной долгосрочной равновесной связи в корзине.

Рис.10. График коинтегрированного спреда между USGO и BGLD за последние шесть месяцев на дневном таймфрейме
Тест ADF на рассеяние:
Критические значения:
10%: -2.5800
✅ Распределение является стационарным (отклоняем нулевую гипотезу).
Тест KPSS по темам:
Критические значения:
1%: 0.739
✅ Распределение является стационарным (не удалось опровергнуть нулевую гипотезу о стационарности).
Мы видим, что BGLD имеет сильную коинтеграцию как с AAAU, так и с USGO, и, учитывая подтвержденную стационарность спреда между USGO и BGLD, у нас есть веские основания полагать, что эти активы являются подходящими кандидатами для формирования коинтегрированной корзины, связанной с золотом.

Рис.11. График многомерного коинтегрированного спреда между AAAU, USGO и BGLD за последние шесть месяцев на дневном таймфрейме
Однако их коинтегрированный спред не является стационарным для данного периода и временного интервала.
Тест ADF на рассеяние:
Критические значения:
10%: -2.5800
❌ Коинтегрированный спред НЕ является стационарным (не удалось отвергнуть нулевую гипотезу).
Тест KPSS по темам:
Критические значения:
1%: 0.739
❌ Коинтегрированный спред НЕ является стационарным (гипотеза о стационарности отвергается).
ETF, связанные с серебром
символы = ['CEF', 'SLV', 'SIVR']
1. CEF — Фонд физического золота и серебра Sprott
"Закрытый траст, владеющий как физическим золотом, так и серебром в слитках. Он торгуется с премией или дисконтом по отношению к своей чистой стоимости активов и не является чисто серебряным инструментом, что делает его структурно отличным от SLV и SIVR."
2. SLV — iShares Silver Trust
"ETF на серебро с физическим обеспечением, цель которого — отражать динамику цен на серебряные слитки. Это один из крупнейших и наиболее ликвидных ETF на серебро."
3. SIVR — ETF на физическое серебро в Абердине
"Подобно SLV, SIVR — это ETF на серебро с физическим обеспечением, однако он, как правило, имеет более низкий коэффициент издержек, что делает его привлекательным для инвесторов, ориентированных на стоимость."
Index(['CEF', 'SLV', 'SIVR'], dtype='object')
Результаты теста коинтеграции Энгл-Грейнджера:
CEF и SLV | p-значение: 0,6092
CEF и SIVR | p-значение: 0,6109SLV и SIVR | p-значение: 0,0000
Наиболее коинтегрированная пара (по Энглу-Грейнджеру): SLV и SIVR | p-значение: 0,0000
Результаты теста Йохансена (статистика следа):
Количество наблюдений: 121Количество переменных: 3
Ранг 2: Показатель Trace = 1,95 | Коэффициент вариации 5 % = 3,84 | Незначимое значение
На ранге 0 (62,67> 29,80) статистическая величина трасса является значимой, что указывает на наличие по крайней мере одного вектора коинтеграции среди трёх ETF, связанных с серебром. Однако коэффициенты 1-го и 2-го порядка не значимы, что указывает на наличие лишь одной устойчивой долгосрочной зависимости, характерной для данной корзины.
Результаты анализа Энгл-Грейнджера показывают, что пара переменных SLV и SIVR демонстрирует явный сигнал коинтеграции (p = 0,0000). Показатель CEF не демонстрирует коинтеграции ни с SLV, ни с SIVR (p>> 0,6). Если еще раз обратиться к результатам Йохансена, можно сделать вывод, что коинтеграция, вероятно, обусловлена тесной взаимосвязью между SLV и SIVR, поскольку они являются практически идеальными заменителями — оба эти ETF обеспечены физическим серебром, что и объясняет их коинтеграцию. CEF инвестирует в серебро, но также обеспечивает вложения в золото и является фондом закрытого типа. Таким образом, он ведет себя иначе.

Рис.12. График коинтегрированного спреда между SLV и SIVR за последние шесть месяцев на дневном таймфрейме
Тест ADF на рассеяние:
Критические значения:
10%: -2.5798
✅ Распределение является стационарным (отклоняем нулевую гипотезу).
Тест KPSS по темам:
Критические значения:
1%: 0.739
❌ Спред НЕ является стационарным (отклоняется нулевая гипотеза о стационарности).
В данном случае мы обнаружили, что коинтегрированный спред между SLV и SIVR является стационарным по результатам теста ADF, но нестационарным по результатам теста KPSS. Мы уже рассматривали подобный пример в предыдущей статье, где приводилось соответствующее объяснение из документации библиотеки statsmodels о том, как интерпретировать подобные противоречивые результаты.
"Пример 1: Оба теста показывают, что ряд не является стационарным — ряд не является стационарным
"Пример 2: Оба теста показывают, что ряд является стационарным — ряд является стационарным
Пример 3: Тест KPSS указывает на стационарность, а тест ADF — на нестационарность. Ряды являются трендово-стационарными. Чтобы сделать ряд строго стационарным, необходимо удалить тренд. Проводится проверка стационарности ряда данных, очищенного от тренда.
Пример 4: KPSS указывает на нестационарность, а ADF — на стационарность. Ряды являются стационарными по разностям. Дифференцирование используется для приведения ряда к стационарному состоянию. Проводится проверка стационарности дифференцированного ряда."

Рис.13. График многомерного коинтегрированного спреда между CEF, SLV и SIVR за последние шесть месяцев на дневном таймфрейме
Что касается многомерного коинтегрированного спреда, то есть всей корзины, график показывает, что в данном периоде и на данном временном интервале спред НЕ возвращается к среднему значению. Тест на стационарность это подтвердит.
Тест ADF на рассеяние:
Критические значения:
10%: -2.5799
❌ Коинтегрированный спред НЕ является стационарным (не удалось отвергнуть нулевую гипотезу).
Тест KPSS по темам:
Использованные лаги: 6
Критические значения:
1%: 0.739
❌ Коинтегрированный спред НЕ является стационарным (гипотеза о стационарности отвергается).
Что это значит? Конечно, у нас здесь нет подходящего набора ETF, связанных с серебром, но есть два ETF с высокой степенью коинтеграции (SLV и SIVR), на которые, возможно, стоит обратить пристальное внимание с точки зрения парной торговли — именно этому посвящена наша первая статья из этой серии.
Эти два примера призваны продемонстрировать, что при поиске коинтегрированных активов для статистического арбитража ключевую роль играют эксперименты и исследования. Кроме того, следует помнить, что одни лишь статистические данные не могут заменить ваше понимание отрасли и знание рынка.
Заключение
В данной статье описывается пример советника, прошедшего бэктестинг на небольшой выборке коинтегрированных акций. Это вторая из двух статей, посвященных наиболее распространенным статистическим показателям, используемым при формировании портфелей для статистического арбитража: коэффициентам корреляции и оценке коинтеграции, а также проверке стационарности спредов.
Стоит отметить, что такая стратегия, хотя её практически невозможно применять к валютам (валютным парам) из-за редкости случаев, когда встречаются более двух коинтегрированных валют, также применима к индексам, ETF и сырьевым товарам.
Теперь, когда у нас есть основные инструменты для формирования портфеля на основе коинтеграции, логичным следующим шагом могло бы стать внедрение ротации портфеля в режиме реального времени, что в перспективе может перерасти в подход, основанный на машинном обучении.
Ссылки
Марианна Брунетти и Роберта Де Лука, 2023. "Предварительный отбор в торговле парами на основе коинтеграции," Statistical Methods&Applications, Springer; Società Italiana di Statistica, т. 32(5), стр. 1611-1640, Декабрь.
Примечания
* Хотя эта аналогия, вероятно, и происходит от него, «случайное блуждание» в данном контексте не следует путать со «случайным блужданием Пирсона" — стохастическим процессом, описанным и названным в честь английского математика.
| Файл во вложении | Описание |
|---|---|
| corr_pearson.ypng | Этот файл представляет собой Jupyter-ноутбук, содержащий код на языке Python. Скрипт выполняет тест на корреляцию Пирсона. |
| coint_stocks_ETFs.ypnb | Этот файл также представляет собой Jupyter-ноутбук, содержащий код на языке Python. Скрипт выполняет тесты коинтеграции Энгл-Грейнджера и Йохансена, а также тесты стационарности ADF и KPSS. |
| Nasdaq_NVDA_Coint.mql5 | Этот файл содержит пример советника, использованного в тестировании на исторических данных. |
| Nasdaq_NVDA_Coint.ini | Этот файл представляет собой файл настроек конфигурации (.ini), содержащий параметры, используемые в тестировании на исторических данных. |
| Nasdaq_NVDA_Coint.NVDA.Daily.20250101_20250515.021.ini | Этот файл также является файлом настроек (.ini), содержащим параметры оптимизации, используемые в тестировании на исторических данных. |
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/19052
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Самооптимизирующиеся советники в MQL5 (Часть 11): Введение в основы линейной алгебры
Разработка инструментария анализа Price Action (Часть 25): Пробой фракталов по двум EMA
Торговые инструменты на MQL5 (Часть 17): Изучение векторных скругленных прямоугольников и треугольников
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
К чему все эти сложности?
Это дает:
lots -> ratio * totalDollarExposure / price -> dollarExposures[i] / totalDollarExposure * totalDollarExposure / price -> dollarExposures[i] / price -> MathAbs(weights_arr[i]) * baseLotSizeТакже ваши расчеты не совместимы с символами, котируемыми в валюте, отличной от валюты счета.