Торговая стратегия для SPY, использующее восстановления после сильного падения » Элитный трейдер
Элитный трейдер


Торговая стратегия для SPY, использующее восстановления после сильного падения

В недавней статье я показал, что изменение SPY на следующий день после сильных падений в среднем имеет положительное матожидание. То есть - сильные падения в основном выкупаются. Попробуем собрать торговую стратегию, которая будет использовать эту рыночную закономерность.
13 ноября 2013 long-short.ru mehanizator
Как обычно, будем рассматривать ценовые изменения в нормированном виде, где в качестве нормы возьмем волатильность предыдущего месяца, т.е. в скользящем окне 21 торговых дней.

Если сегодня SPY упал, будем заходить в позицию, пропорциональную этому падению, нормированному на волатильность. Коэффициент пропорциональности определим из формулы для коэффициента Келли, с понижающим коэффициентом 0.33.

Смотрим что получилось, шкала логарифмическая:

Торговая стратегия для SPY, использующее восстановления после сильного падения


Результат 40 за 11 лет это 3.6 в год в среднем, то есть +260% без реинвестирования. Просадки, конечно, будут нечеловеческими, поэтому как это обычно бывает, вряд ли кто решится торговать с "плечами по келли".

Шарп 1.03

Оборот стратегии за все время 50000, если оценить торговые издержки на SPY 0.01% в одну сторону, получается 5, т.е. где-то 8% доходности будут уходить в издержки.

В общем, как первое приближение пойдет, но для реальной жизни хорошо бы добавить еще один параметр. Напрашивается очевидный кандидат - само значение локальной волатильности. Из-за эффекта плеча можно ожидать, что стратегия будет лучше работать, когда волатильность низкая.

Код рисеча на Котлине:

fun main(args: Array) {

val spy = Sec("spy", Date(103, 0, 1))
val normDays = 21
val norms = spy.getNormalization(normDays, NormalizationType.ABS)!!
val changesPast = spy.getPastLogChanges(1)!!
val changesFuture = spy.getFutureLogChanges(1)!!

// KELLY

val normalizedChangesFuture = Util.commonDates(norms, changesFuture)!!.map { date ->
date to changesFuture[date]!! / norms[date]!!
}.toSortedMap()

val variation = normalizedChangesFuture.values().fold(0.0, { v, x -> v + x * x }) / normalizedChangesFuture.size
val kelly = 0.33 / variation

// POSITIONS

val positions = Util.commonDates(norms, changesFuture, changesPast)!!.map { date ->
val normalizedPastChange = changesPast[date]!! / norms[date]!!
val position = if (normalizedPastChange
val (d, p) = e
p * changesFuture[d]!! / norms[d]!!
}.toSortedMap()

val eq = Util.cumulativeLogChanges(equityLogReturns)
val sharpe = Equity.getSharpe(equityLogReturns, 0.0)

"turnover: %7.4f, sharpe: %7.4f".f(turnover, sharpe).p()
Chart.showCharts("", eq, 2.0)

}

http://www.long-short.ru/ (C) Источник
Не является индивидуальной инвестиционной рекомендацией
При копировании ссылка обязательна Нашли ошибку: выделить и нажать Ctrl+Enter