воскресенье, 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()

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

> #Загружаем и чистим данные
> 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,20)
> RSI3<-RSI(prices,3)
> DEMA10<-DEMA(prices,n = 10, v = 1, wilder = FALSE)
> DEMA10c<-prices - DEMA10
> DEMA10c<-DEMA10c/.0001

> #Задаем условия открытия длинной позиции, найденные с помощью нашего алгоритма
> buy.signal<-ifelse(RSI3 < 30 & 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(DEMA10c > 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(RSI3 < 30 & 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(weight, price, tstart, tend, pstop) {
+ 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(weight, price, tstart, tend, pprofit) {
+ 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(weight, price, tstart, tend, pstop, pprofit) {
+ 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


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


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

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

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