воскресенье, 5 февраля 2017 г.

Тестирование торговых стратегий в R

Тестирование торговых стратегий в R

Перевод. Оригинал здесь.
В предыдущей публикации мы исследовали некоторые возможности использования алгоритма машинного обучения для трейдинга на паре USD/CAD с использованием анализа ассоциативных правил. В этой статье мы собираемся узнать, как тестировать торговые стратегии в R, используя наши правила из предыдущего поста, и выставляя тейк-профиты и стоп-лоссы.

Итак, начнем:


> #Загружаем необходимые библиотеки
> library(RCurl)
> library(quantmod)

> #Устанавливаем мощный набор инструментов для тестирования и оценки торговых стратегий “Systematic Investor Toolbox” от Michael Kapler

> sit = getURLContent('https://github.com/systematicinvestor/SIT/raw/master/sit.gz', binary=TRUE, followlocation = TRUE, ssl.verifypeer = FALSE)
> con = gzcon(rawConnection(sit, 'rb'))
> source(con)
> close(con)

> #Создаем новое окружение
> data <- new.env="" span="">

> #Задаем название актива и местоположение файла csv
> tickers<-spl span="">
> file.path<- span="">

> #Загружаем и чистим данные
> for(n in tickers) { data[[n]] = read.xts(paste(file.path, n, '.csv', sep=''), format='%m / %d / %y %H:%M') }

> #Задаем цены  и создаем список для хранения наших моделей
> prices = data$prices
> models = list()

> #Создаем нашу базовую стратегию "купить и держать"
> data$weight[] = NA
> data$weight[] = 1
> models$buy.hold = bt.run.share(data, clean.signal=T)
Latest weights :
[1] 100

Performance summary :
CAGR Best Worst
3.2 1.4 -2
> #Рассчитываем необходимые для модели индикаторы
> CCI20<-cci prices="" span="">
> RSI3<-rsi prices="" span="">
> DEMA10<-dema n="10," prices="" v="1," wilder="FALSE)</span">
> DEMA10c<-prices -="" dema10="" span="">
> DEMA10c<-dema10c span="">

> #Задаем условия открытия длинной позиции, найденные с помощью нашего алгоритма
> buy.signal<-ifelse 30="" amp="" cci20=""> -290 & CCI20 < -100 & DEMA10c > -40 & DEMA10c < -20,1,NA)

> #Создаем нашу "длинную" модель
> data$weight[] = NA
> data$weight[] = buy.signal
> models$long = bt.run.share(data, clean.signal=T, trade.summary = TRUE)

> #Задаем условия для продажи
> sell.signal<-ifelse c=""> 10 & DEMA10c < 40 & CCI20 > 185 & CCI20 < 325 & RSI3 > 50, -1 ,NA)

> #Создаем нашу "короткую" модель
> data$weight[] = NA
> data$weight[] = sell.signal
> models$short = bt.run.share(data, clean.signal=T, trade.summary = TRUE)

> #Задаем условия открытия длинных и коротких позиций для нашей стратегии
> long.short.strategy<-iif 30="" amp="" cci20=""> -290 & CCI20 < -100 & DEMA10c > -40 & DEMA10c < -20,1,iif(DEMA10c > 10 & DEMA10c < 40 & CCI20 > 185 & CCI20 < 325 & RSI3 > 50, -1 ,NA))

> #Создаем нашу объединенную стратегию
> data$weight[] = NA
> data$weight[] = long.short.strategy
> models$longshort = bt.run.share(data, clean.signal=T, trade.summary = TRUE)
Latest weights :
[1] 100

Performance summary :
CAGR Best Worst
2.9 2 -1.1

> #Выделяем диапазон дат для проверочной выборки (эти данные не используются для обучения модели или создания правил)
> dates = '2014-02-26::2014-09-22'


> #Строим график наших трейдов
> bt.stop.strategy.plot(data, models$longshort, dates = dates, layout=T, main = 'Long Short Strategy', plotX = F)

Примечание: тест построен на 4-часовых барах.

Rplot01.png

> #Выводим кривую капитала и статистику успешности
> strategy.performance.snapshoot(models, T)

Rplot02.png

CAGR (compounded annual growth rate) - это прибыль/убыток в процентах в годовом выражении. Давайте посмотрим, как можно улучшить прибыльность нашей модели с помощью стоп-лоссов и тейк-профитов.

> #Функция стоп-лосса
> stop.loss <- function="" price="" pstop="" span="" tend="" tstart="" weight="">
+  index = tstart : tend
+  if(weight > 0)
+    price[ index ] < (1 - pstop) * price[ tstart ]
+  else
+    price[ index ] > (1 + pstop) * price[ tstart ]}

> #Задаем стоп-лосс как 0,25% движения цены против нашей позиции
> Stoploss = .25/100

> #Наша комбинированная модель с 0,25% стоп-лоссом
> data$weight[] = NA
> data$weight[] = custom.stop.fn(coredata(long.short.strategy), coredata(prices), stop.loss,pstop = Stoploss)
> models$stoploss = bt.run.share(data, clean.signal=T, trade.summary = TRUE)

> #Визуализация нашей торговли
> bt.stop.strategy.plot(data, models$stoploss, dates = dates, layout=T, main = 'Stop Loss', plotX = F)

Rplot03.png

> #И сравниваем с нашей оригинальной моделью
> strategy.performance.snapshoot(models[c(1,4:5)], T)

backtestpng5.png

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

> #Функция тейк-профита
> take.profit<- function="" pprofit="" price="" span="" tend="" tstart="" weight="">
+  index = tstart : tend
+  if(weight > 0)
+    price[ index ] > (1 + pprofit) * price[ tstart ]
+  else
+    price[ index ] < (1 - pprofit) * price[ tstart ]}

> #Будем поддерживать соотношение риск/прибыль 1:1 и установим тейк-профит на уровне изменения цены 0,25%
> Takeprofit = .25/100

> #Наша комбинированная модель с тейк-профитом 0,25%
> data$weight[] = NA
> data$weight[] = custom.stop.fn(coredata(long.short.strategy), coredata(prices), take.profit, pprofit = Takeprofit)
> models$takeprofit = bt.run.share(data, clean.signal=T, trade.summary = TRUE)

> #Визуализация нашей торговли
> bt.stop.strategy.plot(data, models$takeprofit, dates = dates, layout=T, main = 'Take Profit', plotX = F)

Rplot04.png
> #И сравниваем с нашей оригинальной моделью
> strategy.performance.snapshoot(models[c(1,4:6)], T)

backtestpng7.png

Применение тейк-профитов немного увеличивает прибыльность, но не слишком существенно. Теперь объединим тейк-профиты со стоп-лоссами.

> # целевая прибыль
> stop.loss.take.profit<-function pprofit="" price="" pstop="" span="" tend="" tstart="" weight="">
+  index = tstart : tend
+  if(weight > 0) {
+    temp = price[ index ] < (1 - pstop) * price[ tstart ]
+    
+    # целевая прибыль
+    temp = temp | price[ index ] > (1 + pprofit) * price[ tstart ]
+  } else {
+    temp = price[ index ] > (1 + pstop) * price[ tstart ]
+    
+    # Функция стоп-лосса и тейк-профита
+    temp = temp | price[ index ] < (1 - pprofit) * price[ tstart ]
+  }
+  return( temp )
+ }

> #Наша комбинированная модель со стоп-лоссом 0,25% и тейк-профитом 0,25%
> data$weight[] = NA
> data$weight[] = custom.stop.fn(coredata(long.short.strategy), coredata(prices), stop.loss.take.profit,pstop = Stoploss, pprofit = Takeprofit)
> models$stop.loss.take.profit = bt.run.share(data, clean.signal=T, trade.summary = TRUE)

Теперь сравним базовую комбинированную стратегию с только стоп-лоссами, только тейк-профитами, а также с их комбинацией.

> #Визуализация торговли
> layout(1:4)
> bt.stop.strategy.plot(data, models$longshort, dates = dates, layout=T, main = 'Long Short', plotX = F)
> bt.stop.strategy.plot(data, models$stoploss, dates = dates, layout=T, main = 'Long Short .25% SL', plotX = F)
> bt.stop.strategy.plot(data, models$takeprofit, dates = dates, layout=T, main = 'Long Short .25% TP', plotX = F)
> bt.stop.strategy.plot(data, models$stop.loss.take.profit, dates = dates, layout=T, main = 'Long Short .25% SL, .25% TP', plotX = F)

Rplot05.png

> #И сравниваем все созданные нами модели
> strategy.performance.snapshoot(models[c(1,4:7)], T)

backtestpng9.png

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

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

Комментариев нет:

Отправить комментарий