Пересечение скользящих средних

Реализуем на языке R простую стратегию, использующую пару скользящих средних: будем открывать длинную позицию, когда быстрая скользящая средняя пересекает медленную снизу вверх, а когда пересекает сверху вниз — будем переворачиваться, т.е. закрывать длинную и открывать короткую позицию.

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

Для примера мы выбрали импорт данных из программы Metatrader 4/5. Откроем архив котировок (команда меню Сервис ‣ Архив котировок); выберем нужную валютную пару (например, EUR/USD) и таймфрейм (например, минутный). Нажмём кнопку Экспорт. Выберем каталог и имя файла (например, EURUSD1.csv на диске D:). Нажмём кнопку Сохранить, затем кнопку Закрыть.

Если у вас не установлена программа MetaTrader, можете скачать файл EURUSD1.zip. После скачивания его надо разархивировать с помощью архиватора WinZip, 7-zip или WinRar.

Теперь перейдём в RStudio и прочитаем данные из этого файла; для проверки выведем на экран 3 первые записи:

> data <- read.table(file="D:/EURUSD1.csv", sep=",", header=F, as.is=T)
> head(data, 3)
          V1    V2      V3      V4      V5      V6  V7
1 2014.10.31 22:17 1.25322 1.25324 1.25322 1.25323  10
2 2014.10.31 22:18 1.25324 1.25340 1.25324 1.25336  13
3 2014.10.31 22:19 1.25336 1.25336 1.25327 1.25329  25

Соединим первые два столбца (строковые представления даты и времени) и преобразуем их во внутренний формат представления даты и времени, зададим часовой пояс EET (восточно-европейской время UTC+2, это часовой пояс терминала, из которого мы взяли котировки):

> tm <- strptime(paste(data[,1], sprintf("%05s",data[,2])), format="%Y.%m.%d %H:%M", tz="EET")
> class(tm)
[1] "POSIXlt" "POSIXt"
> head(tm)
[1] "2014-10-31 22:17:00 EET" "2014-10-31 22:18:00 EET" "2014-10-31 22:19:00 EET"
[4] "2014-10-31 22:20:00 EET" "2014-10-31 22:21:00 EET" "2014-10-31 22:22:00 EET"

Теперь создадим временной ряд — объект класса xts (eXtensible Time-Series):

> library(xts) # Загрузили пакет xts для работы с временными рядами.
> Sys.setenv(TZ='UTC') # Время по Гринвичу (нулевой часовой пояс).
> data2 <- xts(x=data[,c(3:6)], order.by=tm, tzone='UTC') # Преобразовали таблицу во временной ряд.
> colnames(data2) <- c("Open", "High", "Low", "Close")    # Задали заголовки столбцов.
> head(data2, 3) # Вывели первые 3 записи.
                       Open    High     Low   Close
2014-10-31 20:17:00 1.25322 1.25324 1.25322 1.25323
2014-10-31 20:18:00 1.25324 1.25340 1.25324 1.25336
2014-10-31 20:19:00 1.25336 1.25336 1.25327 1.25329

Как видим, время стало на 2 часа меньше, как мы и хотели.

Для преобразования таймфрейма используем функцию to.period из пакета xts:

> data3 = to.period(data2, period='hours', indexAt="startof") # Часовые свечи.
> head(data3, 3)
                    data2.Open data2.High data2.Low data2.Close
2014-10-31 20:17:00    1.25322    1.25340   1.25189     1.25189
2014-11-02 22:00:00    1.25056    1.25131   1.25037     1.25076
2014-11-02 23:00:00    1.25079    1.25106   1.25011     1.25013

Рассмотрим декабрь 2014 года:

> win <- '2014-12-01/2014-12-31'
> data4 <- data3[win]

Рассчитаем две простых скользящих средних (по ценам закрытия) с периодами 5 и 20:

> library(quantmod)
> fastSMA <- SMA(Cl(data4), n=5)
> slowSMA <- SMA(Cl(data4), n=20)

Пометим единицами те часовые свечи, когда быстрая скользящая средняя была выше медленной (это сигнал на покупку и удержание позиции); минус единицами — свечи, когда быстрая скользящая средняя ниже медленной (это сигнал на продажу и удержание позиции); остальные свечи пометим нулями:

> sigup <- ifelse(fastSMA > slowSMA, 1, 0)  # Сигналы на покупку.
> sigdn <- ifelse(fastSMA < slowSMA, -1, 0) # Сигналы на продажу.

Учтём тот факт, что скользящие средние рассчитываются по ценам закрытия, поэтому сигнал на покупку или продажу возникает только после закрытия очередной свечи, т.е. на открытии следующей свечи. Задержим все сигналы на одну свечу:

> sigup <- Lag(sigup, 1)
> sigdn <- Lag(sigdn, 1)

Для самых первых свечей скользящие средние не определены, там хранятся значения NA (не-число), преобразуем их в нули:

> sigup[is.na(sigup)] <- 0
> sigdn[is.na(sigdn)] <- 0

Построим график цены, наложив на него обе скользящие средние (красная и синяя линии):

> chart_Series(data4, name="EUR/USD", TA='add_SMA(n=5,col="red");add_SMA(n=20,col="blue")')

Для каждой свечи рассчитаем прибыль “от открытия до закрытия” (open-to-close return):

> ret <- Delt(data4[,1], data4[, 4], type = "log")  #  натуральный log(Close/Open)

Соединим оба массива сигналов (1 на покупку, -1 на продажу) в один массив, умножим его на массив прибылей за каждый час; в результате те часы, когда мы не торговали, обнулятся, а остальные сложатся с нужным знаком, сформировав общую прибыль. В конце добавим кривую эквити к нашему графику:

> sig = sigup + sigdn
> retsig = ret*sig
> equity <- exp(cumsum(retsig)) # Эквити (баланс торгового счёта с учётом открытых позиций).
> add_TA(equity, col="blue")    # Вывели на тот же график снизу.

Получим график, показанный на рис.1.

../_images/CrossSMA-01.png

Рис. 1. Ценовой график в виде свечей, обе скользящие средние и кривая эквити.

Если в командной строке выполнить, например:

zoom_Chart(subset="2014-12-01/2014-12-15")

то будет отображена соответствующая область графика.

Если мы воспользуемся пакетом PerformanceAnalytics, то сможем вывести не только график прибыли, но также просадку (drawdown) и почасовую прибыль:

> library(PerformanceAnalytics)
> charts.PerformanceSummary(retsig)

Получим графики, показанные на рис.2.

../_images/CrossSMA-02.png

Рис. 2. Кривая эквити, прибыль за каждый час и просадка эквити

Замечание: Если внимательно анализировать совершённые сделки (изучая наборы данных sig, retsig и equity), то можно заметить, что самая первая сделка была открыта с опозданием: не сразу после очередного пересечения средних, а после той свечи, на которой были впервые рассчитаны значения обеих скользящих средних. Подумайте, как изменить программу, чтобы обнулить значения sig для первой сделки, если она должна быть открыта с опозданием относительно точного момента пересечения.


Теги: Язык R, Торговые системы




Комментарии (2)

Вы просматриваете: CrossMA
Facebookdel.icio.usStumbleUponDiggGoogle+Twitter
Gravatar
ProfiTraders говорит...
Мы считали k-period log-return (см. http://profitraders.com/Math/TimeSeries.html#id2 ) от открытия до закрытия каждой свечи. Т.е. например, пока действует сигнал на покупку и удержание длинной позиции, мы покупаем в начале часа и закрываем позицию в конце часа. А в начале следующего часа, если сигнал ещё ... Читать дальше
15th May 2015 1:36pm
Gravatar
Антон говорит...
спасибо за статью, очень интересно.
только я не понял на графике эквити 1,04 мы за месяц всего 4 процента заработали?
15th May 2015 11:09am
Страница 1 из 1

* Обязательные поля
(Не публикуется)
 
Жирный Курсив Подчеркнутый Перечеркнутый Степень Индекс Код PHP Код Кавычки Вставить линию Вставить маркированный список Вставить нумерованный список Вставить ссылку Вставить e-mail Вставить изображение Вставить видео
 
Улыбка Печаль Удивление Смех Злость Язык Возмущение Ухмылка Подмигнуть Испуг Круто Скука Смущение Несерьёзно Шокирован
 
1000
Captcha
Refresh
 
Введите код:
 
Запомнить информацию введенную в поля формы.