Автор: Александр Кургузкин (mehanizator).
Поскольку далее я периодически буду приводить графики результатов парной стратегии, нелишне будет привести метод, с помощью которого они получаются.
Итак, на входе имеем два массива цен (закрытия дней, например). Для каждого дня сначала считаем волатильности каждой из ног пары скользящим окном в N дней, берем стандартное отклонение помноженное на sqrt(252) для приведения к годовой волатильности. Имея волатильность, считаем нормировочные коэффициенты, приводящие позиции каждой из ног к одной волатильности. Затем уже получаем результат составленной таким образом пары за день. Складывая последовательно результаты дней в итоге получаем конечную эквити стратегии.
Таким образом позиция получается не только маркет-нейтральной, но и приведенной к одному риску по всему периоду времени. По оси значений — единицы среднегодовой волатильности. Полученный таким образом график результатов стратегии может служить индикатором относительных приведенных к риску результатов для разных, например, рынков или секторов. Грубо говоря — можно отследить переток доходности (и рисков) с рынка на рынок.
Если верить CAPM, то, раз обе состовляющих пары приведены к одному риску, доходности обоих ног пары должны быть примерно одинаковы. А значит, в долгосрочном периоде пара не должна формировать долгосрочного тренда, а ходить вокруг одних и тех же уровней.
Раз так, можно было бы назвать этот индикатор осциллятором, но поскольку у нас нет какой-то привязки к некому абсолютному уровню, осциллятором это может оказаться довольно приблизительным. Не исключено, что из-за постоянной перенормировки волатильности будет накапливаться какой-то систематический сдвиг, хотя вряд ли он будет существенным на горизонте в несколько лет.
Примеры искользования индикатора перетока рисков
Россия против Америки, RTSI vs. SPX
Америка против развивающихся рынков, SPY vs. EEM
Германия против Италии, EWG vs. EWI
Код на Java, используются библиотеки Guava и Apache Common Math. Коэффициент ratio для маркет нейтральной пары должен быть 1.0, но иногда бывают случаи когда не нужен полный хедж, тогда ratio < 1.0.
public static Map<Date, Double> pairTrade(
Map<Date, Double> closes1,
Map<Date, Double> closes2,
int window,
double ratio) {
Preconditions.checkArgument(!closes1.isEmpty(), «closes1 is empty»);
Preconditions.checkArgument(!closes2.isEmpty(), «closes2 is empty»);
Preconditions.checkArgument(window > 3, «window is too small, should be > 3»);
final Set<Date> dates = Sets.intersection(closes1.keySet(), closes2.keySet());
final List<Double> changes1 = Lists.newArrayList(), changes2 = Lists.newArrayList();
final List<Date> ds = Lists.newArrayList();
double last1 = 0, last2 = 0;
for (Date d : dates) {
double c1 = closes1.get(d);
double c2 = closes2.get(d);
if (last1 > 0 && last2 > 0) {
changes1.add(c1 / last1);
changes2.add(c2 / last2);
ds.add(d);
}
last1 = c1;
last2 = c2;
}
int sz = ds.size();
final Map<Date, Double> results = Maps.newTreeMap();
double result = 0;
double yearly = Math.sqrt(252);
for (int i = window; i < sz; ++i) {
final SummaryStatistics stat1 = new SummaryStatistics(), stat2 = new SummaryStatistics();
for (int j = i — window; j < i; ++j) {
stat1.addValue(Math.log(changes1.get(j)));
stat2.addValue(Math.log(changes2.get(j)));
}
double sd1 = yearly * stat1.getStandardDeviation();
double sd2 = yearly * stat2.getStandardDeviation();
double k1 = 1.0 / sd1;
double k2 = -ratio / sd2;
result += k1 * changes1.get(i) + k2 * changes2.get(i) — (k1 + k2);
results.put(ds.get(i), result);
}
return results;
}
Автор: mehanizator
Другие статьи по теме:
Парный трейдинг посредством ETF
CAPM и индикатор перетока рисков
Перетоки рисков: развивающиеся рынки, BRIC и Россия
Комментарии:
dobrachev: А какое, интересно, должно быть число дней в скользящем окне? Понятно, что лучше подбирать с учётом параметров стратегии. Но ведь и стратегию нужно для начала на каких-то данных оптимизировать…
А так, конечно, это очень правильно — приводить каждую ногу в паре к одинаковой волатильности.
ЗЫ: Код на Java выкладывать — это не аналитические обзоры писать. Большой респект! 🙂
mehanizator: я использую 20 (месяц) или 60 (квартал)
mehanizator: но вообще думаю, что правильней брать 20. если брать больше, то данные остаются локально неоднородными.
dobrachev: Ясно, спасибо!
Наверное, если бы мне никто не ответил, я бы тоже взял за месяц 🙂
Nanonix: А через что график строился?
mehanizator: http://trac.erichseifert.de/gral/
Nanonix: О,спасибо! смотрел еще в сторону http://www.jfree.org/jfreechart/
mehanizator: jfreechart конечно лучше. но у них документации открытой нет, только за бабло 🙂
Nanonix: Засада (, а так у них ,по демке, конечно дофига чего уже готового и нужного
mehanizator: да вот и я думаю придется таки не пожалеть и потратиться на доку
GreenBear: уже все чарты есть
http://docs.oracle.com/javafx/2/charts/jfxpub-charts.htm
mehanizator: это JavaFX
GreenBear: ? mehanizator ?? ну да, там же написано! с блэк джеком и прочим…
mehanizator: но чтобы ей пользоваться, нужно сначала освоить JavaFX.
GreenBear: да там осваивать 2 дня.
mehanizator: ну я смысла просто не вижу. есть же замечательные jfreechart.
GreenBear: никто же не заставляет 😉 мне тут давече надо было по пол миллиона значений на графики выводить. удалось это сделать на fx. с другими как-то грустно все получалось. ну ладно, хватит спамить. кому, что нравится, это я так, ради альтернативы…
mehanizator: чем меньше разных технологий в проекте, тем лучше 🙂
Yaroslav Alexeev: Лучше SPX vs Russel или SPX vs DJX посмотреть, вола близкая, маржа сальдируется.