Блог им. Quantrum

Парный трейдинг: 1 из 3 способов поиска пар на Python

Первый из трех способов автоматического поиска пар на Python для торговли по стратегии «Парного трейдинга». Исходя из результатов предыдущей статьи, во всех примерах мы будем использовать только поиск коинтеграции.

Кратко о «Парном трейдинге»: в основе стратегии лежит предположение, что есть две акции, которые имеют глубокую экономическую связь друг с другом, и их цена движется в одном направлении с разной скоростью. Когда отстает акция А, мы ее покупаем и одновременно продаем в короткую акцию Б. И наоборот.

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

Подготовка к поиску

Для правильной работы необходимо соблюсти следующие условия:

  1. Истории цен должны быть равной длины. (Результат сравнения историй за 200 дней и за 20 дней может быть непредсказуем).
  2. Значения должны быть переведены в относительные величины. (Тяжело сравнивать активы за $200 и за $1).
  3. Каждая история не должна обладать стационарностью сама по себе. (Важна именно стационарность спреда пары, а не отдельного актива в ней).

Коинтеграцию каждого времянного ряда будем проверять с помощью метода Дики-Фуллера из библиотеки statsmodels. Код подготовки ниже: Исходный код на Quantrum.me.

Выбор акций для поиска

Искать пары будем среди активов торгующихся на рынке, включая ETF, ограничив следующими условиями:

  • Цена более $10.
  • Средний объем более 500 тыс. акций в день.
  • ATR за 13 дней более $0.40.

Проверяем на ликвидных активах с хорошим движением внутри дня. Из 6 тысяч американских акций, торгующихся на биржах, нам подходят ~1500 активов. Тестировать будем предыдущий год (360 календарных дней).

1 из 3: Простой коинтеграционный тест

Использую самую первую попавшуюся на глаза функцию для проверки пары на стационарность.  Это тест на наличие единичных корней найден в библиотеке statsmodels.

Функция проверки стационарности: statsmodels.tsa.stattools.coint(X, Y)

Функция поиска пар получает словарь с историей относительного изменения цен и последовательно проверяет каждую пару. Для 1500 активов это примерно 1.1 миллиона вариантов.

Выбираем пары с оценкой ниже 5% уровня ошибки и p-значением меньше 0,001. Код поиска пар ниже: Исходный код на Quantrum.me.

На момент написания статьи тест нашел 6400 пар (~0.6%), поиск загружал 1 ядро процессора и длился порядка 45 минут. Вот первые несколько пар с наименьшим p-значением:

  • XIV, SVXY
  • IWB, SPY
  • IVV, SPY
  • DUST, GDX
  • SPY, SPXU

Видно, что это ETF на индексы и первые два действительно имеют стационарный спред, а вот начиная с IVV и SPY найти проблемы нам помогут графики.

Проверка найденных пар

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

  • XIV, SVXY
  • DUST, GDX
  • XLK, QQQ
  • PRU, C
  • TMUS, WCG

XIV, SVXY

XIV — ETN (аналог ETF) обратный индексу страха $VIX.
VSXY — ETF обратный индексу страха $VIX.

На графике история цен и сигнальная линия z-оценки. SVXY домножен на коэффициент для приведения цен к единой величине. Видно, что график хорош, но два месяца назад (ноябрь-декабрь 2016) спред уменьшился. Причина в моем поставщике данных. Ранее была бо́льшая погрешность в цене, которую нивелировали.

Парный трейдинг: 1 из 3 способов поиска пар на Python

Код z-оценки: Исходный код на Quantrum.me.

DUST, GDX

DUST — 3х-кратный обратный ETF к GDX.
GDX — ETF компаний-золотодобытчиков.

График разочаровывает и подобных графиков в результатах много. Данные активы обратно-скоррелированы — этот факт в их природе существования. Функция coint(X, Y) на вход получает два времянных ряда и сама проверяет их стационарность. Видимо эта функция использует в основе проверку корреляции и дополнительно подгоняет ряды.

Парный трейдинг: 1 из 3 способов поиска пар на Python

XLK, QQQ

XLK — ETF на индекс технологических компаний.
QQQ — ETF на индекс NASDAQ-100, где преимущественно технологические компании.

Здесь результаты лучше, но так как в QQQ также много компаний из XLV (здравоохранение), то в январе 2017 XLK сумел вырваться вперед.

Парный трейдинг: 1 из 3 способов поиска пар на Python

PRU, C

Копнем поглубже и возьмем несколько компаний.

PRU — Prudential Financials, страховая компания.
C — Citibank, банк.

Большую часть года компании шли в ногу, что не удивительно, так как обе в XLF (финансовый сектор) и обе выигрывают от роста ставок. Но за январь 2017 появилось расхождение.

Парный трейдинг: 1 из 3 способов поиска пар на Python

TMUS, WCG

TMUS — T-Mobile US, американский сотовый оператор.
WCG — WellCare Health Plans, компания из сектора здравоохранения.

Связь данной пары меня удивляет, но с графиком не поспоришь, они идут нога в ногу и обладают хорошим спредом.
Парный трейдинг: 1 из 3 способов поиска пар на Python

Вывод

Данный метод имеет право на существование. Удается найти хорошие пары, которые достойны участия в бэктестинге. Но одновременно к нам приходит большое количество шлака, что заставляет отсматривать результаты вручную. Лучше себя проявил поиск с помощью метода Дики-Фуллера, о котором я буду писать в следующей статье.

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

Обучение «Парному трейдингу» у профессионалов.
★19
31 комментарий
это зачет........++++++++
avatar
на рутикере есть парный трейдинг кстати 

avatar
StockChart.ru, что такое рутикер? 
Александр Румянцев, сервис для трейдеров номер 1
ru-ticker.com
avatar
StockChart.ru, спасибо.
когда то давно тоже искал такие зависимости, но, похоже что на практике это слишком опасно применять, расходятся на длительное время и не сходятся, или в одном периоде есть зависимость, а потом пропадает, потом снова появляется, и по какой причине это происходит непонятно.
avatar
alexKa, на моих глазах так уже достаточно таких трейдеров ушли в прошлое. Порвало на парах.
avatar
Андрей К, важно проверять состояние пары ежедневно. 
alexKa, вы правы, пары часто разбегаются. Я это рассматриваю в будущих статьях. На бэктестах от просадок спасает ежедневный контроль стационарности. Можно вовремя закрыть позиции. 
Вы не могли бы добавить сравнение GDX и NUGT (Bull 3x GDX) ?

Графики, по идее, тоже будут расходиться на средне и долгосрочном периоде, хотя и в меньшей степени… На первый взгляд это может показаться парадоксальным, но несмотря на 3-е плечо в NUGT, его график почти всегда будет под GDX.
Впрочем, если рассмотреть изолировано период только первой половины 2016 года, то NUGT на какое-то время обгонит свою базу.

А долгосрочное расхождение будет формироваться как раз из-за маржинальной природы NUGT, поскольку на падающих днях, особенно на падающих резко, его Net Assets Value регулярно как бы утрамбовывается, и практически уже не восстанавливается до прежних значений (что, кстати, лишний раз напоминает о пагубности плечей).
avatar
avento (О.К.), я размещаю весь исходный код. Вы можете самостоятельно проверить интересующие пары и провести бэктестинг. Смотрите статьи по ссылкам. 
Каким образом устанавливать стоп на сделку и стоп на стратегию?
Какова вероятность что порвет сильнее, чем заработаешь?
avatar
baron_samedi, рискованно торговать одной парой. Необходимо работать с 80-100 парами одновременно. 
Александр Румянцев, 
это уже растрата семени в союзе с кулачеством.
avatar
baron_samedi, важен масштаб. Если работать со счётом в $10-100К, то можно поиграться одной парой. А вот припарковать $1М в одну пару не вижу возможности. 
надеюсь понимаете что на живых деньгах это все исключительно к убытку приведет?
avatar
Vitty, прошу подробно описать причины исключительности. 
российские бы акции 
avatar
Igr, слишком мало ликвидных активов. 
Бывает и рвет. Мани и риск менеджмент никто не отменял. Скрин реальной торговли на фортсе.
avatar
RomSunZ, у пары пропала стационарность. Это видно на графике. Пары не вечны. 
было такое уже... 
выкинь гадость сразу… не трать время… на дневках тестить нельзя, т.к дневки содержат сделки за пределами торговой сессии… т.е один актив не торгуется уже а по второму идут сделки… и эти сделки входят в дневные цены… ты как бы заглядываешь в будущее...
это легко можно проверить… берешь дневки смотришь цены открытия закрыти хая и лоя… затем смотришь 15ти минутку за тот же день и смотришь что было реально внутри торговой сессии
avatar
ves2010, ни разу не встречал учёт цен внеторговой сессии в дневной истории. Дайте примеры. На дневках можно искать. А торговать можно на любом таймфрейме. 
Александр Румянцев, не спорь… просто проверь… и деньги сохранишь и время
avatar
ves2010, спасибо, просто проверил. Взял минутную историю NFLX (на днях был отчет), взял дневную, взял внеторговую сессию. Подписка на данные в Interactive Brokers. Сравнил дневную историю на quandl, Yahoo, stockcharts.com. Внеторговой сессии нет. 
Александр Румянцев, если у тя IB то делай еще проще там в настройках TWS галочка есть игнорировать данные вне торговой сессии… кстати мож она у тебя стоит… и просто смотри дневки с этой галочкой и без нее
avatar
ves2010, спасибо. Люблю галочки.
Нельзя акции из разных секторов брать, даже если у них очень красивый спред. Обязательно разорвет, убытки будут огромные.
Александр Акулов, никто не отменял взаимодействие секторов. Всегда надо следить за состоянием пары. Умирают даже в одном секторе. 
Александр Румянцев, ок,
Допустим спред отклонился от среднего уровня на величину входа, которая у вас определена системой. Вы вошли по направлению возврата к среднему уровню. Но спред идет дальше против вашей позы. При этом вы постоянно следите за состоянием пары.
Что будете делать в такой ситуации для минимизации убытка?
Александр Акулов, в тестах я закрываю пару после потери стационарности и больше не торгую, пока стационарность не вернётся. 

теги блога Александр Румянцев

....все тэги



UPDONW
Новый дизайн