В прошлой статье мы рассмотрели простую портфельную стратегию ротации глобальных рынков. Результаты, которые привел автор статьи, были впечатляющими, однако он не опубликовал алгоритм своих расчетов, а только его общее описание. Ilya Kipnis в своем блоге решил проверить указанную стратегию и воспроизвел алгоритм на языке программирования R.
Для проверки был взят несколько иной набор биржевых фондов, чем у автора оригинальной статьи, но поведение этих активов идентично исходным. Итак, используется 5 ETF: MDY, ILF, FEZ, EEM, и EPP, совместно с облигационным фондом TLT в качестве защитного актива. Каждый месяц происходит инвестирование в фонд, показавший больший ценовой импульс на исторических данных. Автору не удалось получить такой же доходности, которая была обещана в оригинале, но и воспроизведен алгоритм был не со 100% точностью — вместо изменяемого исторического периода, по которому принимается решение о выборе, он использовал фиксированный трехмесячный период, так как не до конца понял принцип его формирования.
Ниже приведен код на языке R для бэктеста:
require(quantmod) require(PerformanceAnalytics) symbols <- c("MDY", "TLT", "EEM", "ILF", "EPP", "FEZ") getSymbols(symbols, from="1990-01-01") prices <- list() for(i in 1:length(symbols)) { prices[[i]] < - Ad(get(symbols[i])) } prices <- do.call(cbind, prices) colnames(prices) <- gsub("\\.[A-z]*", "", colnames(prices)) returns <- Return.calculate(prices) returns <- na.omit(returns) logicInvestGMR <- function(returns, lookback = 3) { ep <- endpoints(returns, on = "months") weights <- list() for(i in 2:(length(ep) - lookback)) { retSubset <- returns[ep[i]:ep[i+lookback],] cumRets <- Return.cumulative(retSubset) rankCum <- rank(cumRets) weight <- rep(0, ncol(retSubset)) weight[which.max(cumRets)] <- 1 weight <- xts(t(weight), order.by=index(last(retSubset))) weights[[i]] <- weight } weights <- do.call(rbind, weights) stratRets <- Return.portfolio(R = returns, weights = weights) return(stratRets) } gmr <- logicInvestGMR(returns) charts.PerformanceSummary(gmr)
И в результате работы программы получены следующие показатели производительности стратегии:
> rbind(table.AnnualizedReturns(gmr), maxDrawdown(gmr), CalmarRatio(gmr)) portfolio.returns Годовая доходность 0.287700 Годовое ср.кв.отклонение 0.220700 Коэффициент Шарпа (Rf=0%) 1.303500 Наибольшая просадка 0.222537 Коэффициент Калмара 1.292991
Эквити бэктеста приведено в заглавии поста. Как видите, обещанные в оригинале 34% годовой доходности не получилось, но и результат в 28,7% очень даже неплох, так же как и солидный коэффициент Шарпа = 1,3. Скорее всего разница объясняется не совсем точным воспроизведением алгоритма, и мы сделаем вывод, что данная стратегия вполне применима для широкого круга инвесторов, в силу ее простоты и хорошей производительности.
Другие алгоритмы и их применение смотрите на моем сайте.