В прошлом материале мы поговорили об использовании неэффективностей рынка на примере истории с ценовым ограничением для швейцарского франка. В этот раз автор блога Financial Hacker решил разобраться в том, как выглядят стратегии, ориентированные на определенную модель. Мы представляем вашему вниманию главные тезисы второй статьи из цикла.
Как уже упоминалось в прошлый раз, есть два основных метода построения стратегий онлайн-трейдинга. Первый ориентирован на определенную модель (model-based), второй – на интеллектуальный анализ данных (data-mining). Сегодня речь пойдет о первом варианте. Построенные на его основе алгоритмы на удивление просты. Но процесс их создания имеет свои подводные камни (иначе бы их писали все, кому не лень). Даже очевидная неэффективность рынка дает системе лишь небольшой зазор, куда можно проникнуть со своим алгоритмом. А самая пустячная ошибка при его написании превратит выигрышную стратегию в неудачу. И этот сбой не всегда можно разглядеть на пробном прогоне.
Для начала необходимо выбрать одну из неэффективностей рынка, которую трейдер хочет использовать в своей стратегии. Неэффективность производит ценовую аномалию или ценовой паттерн, который возможно описать с помощью количественной или качественной модели. Эта модель призвана предсказывать текущую цену yt, основываясь на предыдущем значении цены yt-1, к которому добавляется некая функция f от ограниченного числа предыдущих значений, плюс переменная шума ε.
Очевидно, что чем выше значение предсказуемой функции перед непредсказуемым шумом, тем надежней стратегия. Некоторые трейдеры любят говорить, что их метод не предсказывает поведение рынка, а «реагирует на его изменения». Но системы, не базирующиеся на прогнозировании рынка, определенно должны рассчитывать на удачу. Они лишь перераспределяют риски. Меняют, к примеру, высокий риск от небольших потерь на терпимый от крупных потерь. Но вероятность прибыли остается негативной.
Не все ценовые аномалии годятся к употреблению. Ограничение котировок 1/16 доллара – очевидная неэффективность, но автор статьи честно признается, что не понимает, как ее можно использовать для получения прибыли. Как бы то ни было, известные ему работающие стратегии, основанные на моделях, можно разделить на несколько категорий. О каждой из них по порядку.
Следование тренду
Моментум или динамика изменения цены – пожалуй, самая очевидна и чаще других используемая аномалия. Существует множество методов стратегии следования тренду. Классический вариант – пересечение скользящих средних (moving average crossover). По ссылке можно посмотреть скрипты для нее на R и C.
Есть одна проблема: моментум не действует на всех рынках все время. Любые активы могут не торговаться в течение длительного периода. Случайное отклонение может быть положительным или отрицательным, но при этом сам моментум может отсутствовать. Как бы то ни было, несомненная польза в фильтре, который опознает режим реального рынка, есть. Вот пример использования фильтра нижних частот для обнаружения обратного тренда в стратегии, написанной на скриптовом языке Zorro. Индикатор MMI нужен для фиксации момента вхождения в тренд.
function run()
{
vars Price = series(price());
vars Trend = series(LowPass(Price,500));
vars MMI_Raw = series(MMI(Price,300));
vars MMI_Smooth = series(LowPass(MMI_Raw,500));
if(falling(MMI_Smooth)) {
if(valley(Trend))
reverseLong(1);
else if(peak(Trend))
reverseShort(1);
}
}
Кривая дохода данной стратегии:
Возврат к среднему значению (mean reversion)
Вера в то, что рынок возвращается к среднему значению, подразумевает наличие «реальной» или «честной» цены. Трейдеры покупают, когда текущая цена ниже той, которая, по их мнению, должна быть. И продают при более высоком ее значении. Это, якобы, заставляет цену возвращаться к среднему значению более часто, чем это бы происходило при случайных отклонениях. Есть данные, что возврат к среднему происходит в 75% случаев (некоторые доводы «за» перечислены здесь — на английском). Поэтому все, что выше 75%, должно иметь отношение к неэффективности рынка. Модель расчета:
,
Где yt, — цена на шкале t, y^ — честная цена, λ – коэффициент полураспада (half-life factor), ε – шум.
Чем выше half-life factor, тем менее вероятен возврат к среднему. Обычно среднее значение в ценовой серии достигается в интервале от 50 до 200 баров. λ можно подсчитать через линейную регрессию между yt-1 и (yt-1-yt). Для достижения среднего значения ценовые серии могут не быть статичными поскольку честная цена вольна меняться. Просто это изменения должно быть менее существенным, чем при случайном отклонении. Обычно возврат к среднему используют, убирая тренд из ценовой кривой и нормализуя итоговый результат. Таким образом, мы получаем сигнал колебания, который будет инициировать сделки при достижении верхних или нижних значений. Вот скрипт простой системы, использующей этот метод:
function run()
{
vars Price = series(price());
vars Filtered = series(HighPass(Price,30));
vars Signal = series(FisherN(Filtered,500));
var Threshold = 1.0;
if(Hurst(Price,500) < 0.5) { // do we have mean reversion?
if(crossUnder(Signal,-Threshold))
reverseLong(1);
else if(crossOver(Signal,Threshold))
reverseShort(1);
}
}
Фильтр высоких частот ослабляет влияние всех циклов со значением более 30 тактов, таким образом, исключая тренд из ценовой кривой. Результат нормализуется через преобразование Фишера, что приводит к гаусовскому распределению. Это позволяет определить фиксированные границы значений при 1 и -1, для того чтобы отделить «хвост» нормального распределения. Когда цена достигает дроби в любом направлении, инициируется сделка в ожидании того, что в ближайшее время она вернется к нормальным значениям. Для вхождения в режим возврата к средним значениям, в скрипте использован показатель Херста, установленный на значении 0,5 для случайного отклонения.
Статистический арбитраж
В стратегии может быть использована схожесть двух и более активов. Это позволяет хеджировать первый актив через обратную позицию во втором. Прибыль возникает благодаря возврату к среднему значению разницы их цены.
,
Где y1 и y2 – это цены двух активов, коэффициенты h1 и h2 определяют соотношение для хеджирования. Они рассчитываются, исходя из предположения, что разница между стоимостью активов равна нулю или является константой. Самый простой способ расчета – это линейная регрессия между y1 и y2. Далее здесь также может быть применена стратегия возврата к средним значениям, которую мы разбирали выше.
Понятно, что активы должны быть одного типа. Стандартная система арбитража может быть основана на ценовой разнице индекса ETF и его главных акций. Если y не статична, то есть ее среднее значение меняется медленно, может быть применен коэффициент хеджирования для возмещения в реальном времени.
Вот простой пример системы арбитража из туториала по R:
require(quantmod)
symbols <- c("AAPL", "QQQ")
getSymbols(symbols)
#define training set
startT <- "2007-01-01"
endT <- "2009-01-01"
rangeT <- paste(startT,"::",endT,sep ="")
tAAPL <- AAPL[,6][rangeT]
tQQQ <- QQQ[,6][rangeT]
#compute price differences on in-sample data
pdtAAPL <- diff(tAAPL)[-1]
pdtQQQ <- diff(tQQQ)[-1]
#build the model
model <- lm(pdtAAPL ~ pdtQQQ - 1)
#extract the hedge ratio (h1 is assumed 1)
h2 <- as.numeric(model$coefficients[1])
#spread price (in-sample)
spreadT <- tAAPL - h2 * tQQQ
#compute statistics of the spread
meanT <- as.numeric(mean(spreadT,na.rm=TRUE))
sdT <- as.numeric(sd(spreadT,na.rm=TRUE))
upperThr <- meanT + 1 * sdT
lowerThr <- meanT - 1 * sdT
#run in-sample test
spreadL <- length(spreadT)
pricesB <- c(rep(NA,spreadL))
pricesS <- c(rep(NA,spreadL))
sp <- as.numeric(spreadT)
tradeQty <- 100
totalP <- 0
for(i in 1:spreadL) {
spTemp <- sp[i]
if(spTemp < lowerThr) {
if(totalP <= 0){
totalP <- totalP + tradeQty
pricesB[i] <- spTemp
}
} else if(spTemp > upperThr) {
if(totalP >= 0){
totalP <- totalP - tradeQty
pricesS[i] <- spTemp
}
}
}
Ограничения цены
Ценовые ограничения вызывают устойчивый дрейф цены или устанавливают ее предельные нижние или верхние значения. Самый известный пример здесь это история с парой EUR/CHF (евро/франк), о которой мы подробно говорили в прошлый раз. Но даже после отмены лимита, ограничения в паре остались. На этот раз они были обусловлены не политикой швейцарского Центробанка, а серьезной асимметрией в покупательной способности каждой из валют. Подобные вещи можно использовать в торговой стратегии. Обычно они дают высокую отдачу на коротких временных отрезках при использовании сетки.
Циклы
Если мы говорим не о сезонных циклах, то они могут быть вызваны обратной реакцией ценовой кривой на действия трейдеров. Когда большинство игроков верит в некую честную цену акций, они открывают позиции по покупке или продаже, если цена достигает определенного значения при отклонении от этой стоимости. Или же они закрывают выигрышные позиции, когда предпочтительная динамика начинает замедляться. Таким образом, достаточное число трейдеров может синхронизировать свои циклы по входу-выходу и вызвать устойчивые колебания цены на протяжении определенного периода. Часто многие подобные циклы накладываются на кривую. Например:
Если вам известен период Ci и фаза Di доминантного цикла, трейдер сможет определить оптимальные моменты для открытия и закрытия позиций, пока сам цикл устойчив. Определить действие циклов можно через функции спектрального анализа. Ну, например, через быстрое преобразование Фурье или через набор полосовых фильтров (bandpass filters). Вот диапазон частот для пары евро/доллар на октябрь 2015:
Управляться с циклами сложнее, чем использовать тренд или возврат к среднему значению. Нужно учитывать не только продолжительность цикла, но и его фазу и амплитуду (чтобы понимать, стоит ли вообще обращать на него внимание). Вот пример базового скрипта для этих целей:
function run()
{
vars Price = series(price());
var Phase = DominantPhase(Price,10);
vars Signal = series(sin(Phase+PI/4));
vars Dominant = series(BandPass(Price,rDominantPeriod,1));
ExitTime = 10*rDominantPeriod;
var Threshold = 1*PIP;
if(Amplitude(Dominant,100) > Threshold) {
if(valley(Signal))
reverseLong(1);
else if(peak(Signal))
reverseShort(1);
}
}
Функция DominantPhase
определяет фазу и продолжительность цикла основного максимума в спектре. Он обозначен переменной rDominantPeriod
. Фаза преобразуется в синусоиду, сдвинутую на значение π/4
. Так мы получаем кривую, идущую над ценовой кривой. Вопрос лишь в том, будет ли цена следовать нашим прогнозам. Это мы проверяем через полосовые фильтры, центрированные по доминантному циклу на ценовой кривой, и измеряем их амплитуду (ai в формуле). Если амплитуда превышает предельное значение, значит, цикл, достаточно устойчив. Так как циклы короткие, время открытия позиции ограничено ExitTime
с максимальным значением в 10 циклов.
На этом графике видно, что для пары евро/доллар в 2012 и 2014 не было продолжительных периодов, где бы имели место устойчивые циклы.
Кластеры
Тот же эффект, заставляющий цены колебаться, может привести к их объединению в группы на определенных уровнях. В своем крайнем выражение это даже может дать линии спроса и предложения (или поддержки и сопротивления) – любимые объекты рассмотрения на трейдерских семинарах. Эксперты на таких семинарах могут выявить линии поддержки и сопротивления на любых диаграммах, не помышляя о кластерах, будь то реальные акции или результаты бейсбольного сезона. Для всех остальных очевидность существования этих линий остается под вопросом. Есть лишь несколько стратегий, нацеленных на их выявление и использование. Еще меньше приносят реальный доход. Теоретически кластеры на ценовых кривых могут быть обнаружены с помощью гистограммы, схожей со спектограммой, что мы использовали для выявления циклов.
Паттерны ценовой кривой
Такие паттерны берут начало в повторяющемся поведении трейдеров. На биржах не только производят определенные шаблоны, но и верят в существование таковых. Большинство из них, например, знаменитый «голова и плечи», фигура движения цен в техническом анализе, который, якобы, предсказывает изменение тренда, являются мифами. По крайней мере, автору статьи не встречалось ни одного статистического подтверждения этому паттерну. Однако некоторые шаблоны, типа «чашка» (cup) и «получашка» (half-cup), действительно имеют место быть и могут предсказывать движение кривой вниз и вверх. Паттерны кривой не следует путать со свечными паттернами. В целом их можно эксплуатировать с помощью методов определения шаблонов. Например, алгоритма Фречета.
Особый случай – паттерн пробития (breakout), обозначающий внезапный моментум после длительного движения в узких пределах значений. Он может быть вызван, к примеру, желанием трейдеров размещать свои ордера стоп-лосс на коротком расстоянии над или под текущим плато. Первое закрытие ускоряет движение цены, пока все больше таких закрытий не будет инициировано. Этот эффект можно использовать, создав систему, которая фиксирует период небольших колебаний и переходит в режим ожидания до первого движения в любом направлении.
Сезонность
Сезон в нашем случае не всегда означает время года. Спрос и предложение могут следовать за месячными, недельными паттернами или даже паттернами одного дня. Для примера, индекс S&P500, как принято считать, идет вверх в первые дни каждого месяца или в начале открытия торгов ежедневно. Такие вещи легко использовать в своих целях. Но зачастую они кратковременны, ненадежны, их нельзя распознать, просто вглядываясь в кривую цен. Но при желании для каждого дня, месяца и недели можно создать свой профиль средних ценовых изменений.
Гэпы
Если у участников рынка есть достаточно времени на размышления о том, когда открывать или закрывать позицию, они чаще всего приходят к одинаковому мнению. Время на подумать у них появляется ночью и по выходным. Это может привести к тому, что при открытии торгов, стартовая цена окажется на новом уровне. Цена на открытии и после выходных более предсказуема, чем в течение операционного дня. Данное обстоятельство также можно использовать в стратегии.
Авторегрессия и гетероскедастичность
Последнее слово означает, согласно Википедии, неоднородность наблюдений, выражающуюся в неодинаковой (непостоянной) дисперсии случайной ошибки регрессионной (эконометрической) модели. Или в нашем случае то, что цены судорожно меняются, и эти изменения варьируются во времени.
Модели ARIMA и GARCH – это первые модели, с которыми имеешь дело в матанализе финансовой сферы. Они исходят из предположения, что будущая прибыль или будущая волатильность могут быть определены через линейную комбинацию прошлых доходов и прошлой волатильности. Они имеют статус теоретических моделей. Но вы можете найти им практическое применение. С их помощью можно предсказывать завтрашнюю цену, ничуть не хуже, чем с помощью любых других. Изучите на досуге коррелограмму со статистикой корреляции текущих и прошлых доходов. Возможно, ARIMA можно приспособить под конкретные ценовые серии. Есть две статьи по использованию этих моделей в действующих трейдинговых стратегиях: «Трейдинговая стратегия ARIMA/ GARCH для S&P500» и «Можно ли предсказывать цены через ARIMA/ GARCH?»
Новости
Ценовая встряска обычно случается по понедельникам и пятницам, когда многие компании или организации публикуют хорошие или не очень хорошие новости для рынка. Даже не зная их содержание, можно предугадать с помощью стратегии первую ценовую реакцию и оказаться на стороне победителей. Но высший пилотаж, разумеется, это когда трейдеру удается интерпретировать эти новости. Некоторые информационные сервисы выпускают новости с пометкой «хорошо» или «плохо». Для того чтобы разобраться как можно использовать публичную информацию более творчески и эффективно, следует познакомиться с блестящей книгой «Индекс страха» Роберта Харриса, обязательным чтивом в библиотеке любого продвинутого финансиста.
Автор: ITinvest