Прогнозируем направление движения цены с эффективностью 60% на минутном графике

image

В данной статье речь пойдет про алгоритм прогнозирования направления движения цены валютных пар на несколько минут вперед. Многие считают, что цена абсолютно случайна, ее движение не поддается прогнозированию, либо что алгоритмическая торговля не способна давать эффективные прогнозы. Я решил провести исследование на большом объеме данных, что позволило выявить островки закономерностей, которые поддаются прогнозированию. В статье будет немного программного кода, описание алгоритма и статистика его тестирования за 34 месяца.

Исходные данные


Прежде чем перейти к основному содержанию статьи, необходимо пояснить некоторые моменты.

  • Важно подчеркнуть, что статья посвящена прогнозированию направления движения цены. Это означает, что алгоритм не знает, на сколько именно пунктов цена пойдет вверх или вниз.
  • Прогноз происходит по цене закрытия, другие цены (high, low, open) не учитываются.
  • Таймфрейм 1 минута был выбран потому, что эффективность прогнозирования направления движения цены почти не возрастает с увеличением таймфрейма, в то время как число сделок падает в разы. По этой причине лучше использовать минутный график — это позволяет совершить наибольшее количество сделок, а также собрать наиболее объемную статистику. При этом важно помнить, что из-за наличия спреда на рынке Форекс большое число верно спрогнозированных направлений движения цены вовсе не означает наличие прибыли.
  • Нейросети не использовались, так как практика показала, что научить их прогнозировать движение цены сложнее, чем кажется на первый взгляд. Поэтому было решено сделать торговую систему на базе индикаторов для технического анализа.
  • Так как данные котировок минутного графика валютных пар, которые находятся в свободном доступе в интернете, обычно имеют баги, данные котировок были получены из терминала MetaTrader.
  • Весь код был написан на C++, так как я не умел программировать MQL C++ удобнее языка MQL и быстрее работает. MQL удобен лишь тем, что в нем уже есть функции для работы с графикой, есть готовые индикаторы, можно тут же получить данные котировок и произвести торговые операции. В остальном же MQL менее удобен для проведения исследований, и некоторые его достоинства легко перекрываются собственным программным кодом.


На что способна простая стратегия?


Для начала проверим простую стратегию, которая использует индикаторы RSI и Bollinger Bands. Данная стратегия показала наилучшие результаты по сравнению со скользящими средними или использованием свечных паттернов и различных сочетаний других индикаторов. Данные тестирования по другим стратегиям приводить не буду (так как перебрал их за полгода исследований великое множество).

Возьмем 25 валютных пар и составим статистику работы стратегии за 1.000.000 минут. Код программы приведен под спойлером, его также можно просмотреть здесь.

Код для проверки стратегии
int main() {
    std::vector vPairName(25);
    vPairName[0] = "..//..//train2018//EURAUD1.csv";
    vPairName[1] = "..//..//train2018//EURJPY1.csv";
    vPairName[2] = "..//..//train2018//EURGBP1.csv";
    vPairName[3] = "..//..//train2018//EURCAD1.csv";
    vPairName[4] = "..//..//train2018//EURNZD1.csv";
    vPairName[5] = "..//..//train2018//EURCHF1.csv";
    vPairName[6] = "..//..//train2018//EURUSD1.csv";

    vPairName[7] = "..//..//train2018//AUDCAD1.csv";
    vPairName[8] = "..//..//train2018//AUDNZD1.csv";
    vPairName[9] = "..//..//train2018//AUDCHF1.csv";
    vPairName[10] = "..//..//train2018//AUDJPY1.csv";
    vPairName[11] = "..//..//train2018//AUDUSD1.csv";

    vPairName[12] = "..//..//train2018//CADCHF1.csv";
    vPairName[13] = "..//..//train2018//CADJPY1.csv";

    vPairName[14] = "..//..//train2018//GBPAUD1.csv";
    vPairName[15] = "..//..//train2018//GBPCHF1.csv";
    vPairName[16] = "..//..//train2018//GBPJPY1.csv";
    vPairName[17] = "..//..//train2018//GBPUSD1.csv";

    vPairName[18] = "..//..//train2018//NZDCAD1.csv";
    vPairName[19] = "..//..//train2018//NZDJPY1.csv";
    vPairName[20] = "..//..//train2018//NZDUSD1.csv";

    vPairName[21] = "..//..//train2018//USDCAD1.csv";
    vPairName[22] = "..//..//train2018//USDCHF1.csv";
    vPairName[23] = "..//..//train2018//USDJPY1.csv";

    vPairName[24] = "..//..//train2018//CHFJPY1.csv";

    int expTime = 3; // время экспирации
    double start = 0.0; // начало данных
    double stop = 1.0; // конец данных

    StrategyEffectiveness iEffAll; // эффективность стратегии по всем валютным парам

    for(int n = 0; n < (int)vPairName.size(); n++) {
        CurrencyQuote TestData(vPairName[n],
                               CurrencyQuote::DTYYYYMMDD_TIME_OPEN_HIGH_LOW_CLOSE_VOL);

        int startPos = TestData.close.size() * start; // начало данных
        int stopPos = TestData.close.size() * stop; // конец данных
        std::cout << "Source: " << vPairName[n]
            << " data size: " << TestData.close.size() << std::endl;

        StrategyEffectiveness iEff; // эффективность стратегии
        Indicators::BollingerBands iBB(20, 2.0); // индикатор боллинджер
        Indicators::WRSI iRSI(5); // индикатор RSI
        const double RSI_UP = 70; // верхняя граница индикатора RSI
        const double RSI_DN = 30; // нижняя граница индикатора RSI
        for(int i = startPos; i < stopPos - expTime; i++) {
            // цена закрытия бара
            double& close = TestData.close[i];
            // цена закрытия бара из будущего на expTime баров вперед
            double& closeFuture = TestData.close[i + expTime];
            // получим данные индикатора Bollinger Bands
            iBB.updata(close);
            // получим данные индикатора RSI
            double rsiData = iRSI.updata(close);
            // состояние торговой стратегии,
            // 0 - нет прогнозов, 1 или -1 - прогноз с направлением вверх или вниз
            int stateStrategy = 0;
            if(rsiData > RSI_UP && close > iBB.tl) {
                stateStrategy = -1;
            } else
            if(rsiData < RSI_DN && close < iBB.bl) {
                stateStrategy = 1;
            }

            if(stateStrategy == 1) {
                if(closeFuture > close) {
                    iEff.setWin(); iEffAll.setWin();
                } else {
                    iEff.setLoss(); iEffAll.setLoss();
                }
            } else
            if(stateStrategy == -1) {
                if(closeFuture < close) {
                    iEff.setWin(); iEffAll.setWin();
                } else {
                    iEff.setLoss(); iEffAll.setLoss();
                }
            }
        } // for i
        std::cout << "eff: " << iEff.getEff()
            << " num: " << (iEff.win + iEff.loss) << std::endl;
        std::cout << "eff all: " << iEffAll.getEff()
            << " num: " << (iEffAll.win + iEffAll.loss) << std::endl;
    } // for n

    return 0;
}



image

После того как тестирование стратегии закончено, мы получаем 2.418.153 сделок и 54% эффективности прогнозирования направления цены. Какие выводы можно сделать? Первый вывод, что цена не совсем случайна, ведь мы получили не 50% верных прогнозов, а 54%. Большое количество сделок (больше двух миллионов) говорит о том, что статистика отражает реальную ситуацию, это средний результат по всем 25-ти валютным парам за 2,5 года тестирования (1.000.000 минут — это 694,4 рабочих дня, выходные дни в торговле не участвуют).

Однако, 54% — это не самый лучший результат. К тому же неизвестно, как именно эти 54% распределены во времени. Вдруг в какие-то часы торговли эффективность выше, а в какие-то часы ниже? Вопрос о том, какие валютные пары лучше прогнозируются, а какие хуже, рассмотрим позже.

Распределение эффективности прогнозирования цены по торговым часам


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

Для первого периода тестирования получим следующую картину:

image
Статистика эффективности и количества сделок по минутам дня для первого периода тестирования

Для второго периода тестирования получим почти тоже самое:

image
Статистика эффективности и количества сделок по минутам дня для второго периода тестирования

На приведенных изображениях синяя линия обозначает эффективность торговой стратегии в данную минуту. Голубая линия обозначает сглаженную скользящей средней эффективность с периодом 60. Зеленая линия обозначает уровень числа сделок в данную минуту относительно максимального числа сделок. Желтая линия обозначает уровень 0. Белые вертикальные линии разделяют промежутки длиной в один час. Белые горизонтальные линии обозначают уровни эффективности 60% и 50%. Время на графике отличается от Московского времени — минус 2 часа.

Проанализируем график. По сглаженной линии эффективности видно, что с 3:00 эффективность возрастает и остается высокой до 7:00, дальше она падает и возрастает ближе к 21:00. С 22:00 до 1:00 эффективность особенно высокая. Кривая средней эффективности зависит от выбранного параметра — периода скользящей средней. Эмпирическим путем было выявлено, что данную торговую стратегию при использовании оптимизации ее параметров лучше применять в 5:00 и 6:00, а в вечернее время — с 21:00 до 22:00. Некоторые валютные пары могут показывать хорошие результаты и в другое время. Ночное время с 22:00 до 1:00 дальше в статье для использования не рассматривается, хотя оно дает самый высокий винрейт. Торговлю в данное время можно осуществлять только на Форексе при наличии очень низкого спреда. Брокеры же бинарных опционов не дают заработать в данное время совсем, либо снижая процент выплат, либо закрывая торговлю.

Создаем самооптимизирующуюся торговою систему


Приводить исходный код самооптимизирующейся торговой системы я не буду, но опишу, как она работает.

Идея самооптимизации заключается в том, чтобы перед началом торговли подбирать оптимальные параметры индикаторов, чтобы стратегия давала наиболее высокую эффективность прогнозирования. Параметры индикаторов можно подобрать, тестируя стратегию на исторических данных. Однако, на практике не все так просто, приходится сталкиваться со следующими проблемами:

  • Может возникнуть переоптимизация, и стратегия начнет давать плохие результаты во время торговли. При этом на участке истории, где она была оптимизирована, результаты прогнозирования будут хорошими;
  • Чем больше участок истории, на котором мы оптимизируем стратегию, тем она получается устойчивее, но эффективность прогнозирования может начать падать, так как, увеличивая период тестирования, мы начинаем затрагивать большое число состояний рынка, и стратегия настраивается не самым оптимальным образом. Уменьшая период тестирования, мы рискуем создать переоптимизацию, стратегия может настроиться на конкретное состояние рынка и стать не способной к прогнозированию во время реальной торговли;
  • Процесс оптимизации может длиться очень долго и потреблять большие ресурсы системы для вычислений.


Для борьбы с переоптимизацией обычно период оптимизации разделяют на две части: in sample period и out sample period. На участке in sample period мы находим оптимальные параметры, а на out sample period мы проверяем стратегию на эффективность прогнозирования. Если стратегия показывает хорошие результаты на out sample period, значит найденные параметры индикаторов можно использовать. Также стоит отметить, что параметры индикаторов подбираются с определенным шагом, который не стоит брать минимально возможным, так как чрезмерная детализация параметров индикаторов тоже может привести к переоптимизации. Кроме того, такая детализация потребляет много вычислительных ресурсов и при этом не дает никакого результата.

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

Во время исследований последних 8 месяцев исторических данных котировок валютных пар эмпирическим путем было выявлено, что для оптимизации приведенной в статье стратегии лучше всего брать несколько дней (in sample period), и при этом столько же дней — для предварительного тестирования стратегии (out sample period). Чтобы ускорить процесс оптимизации, все данные индикаторов записываются, и поэтому их не приходится вычислять повторно. Процесс оптимизации происходит каждый день перед началом торговли. Оптимизация на участках истории происходит только в торговые часы, время между торговыми часами в оптимизации не участвует. Оптимизация периода тестирования и шага между периодами оптимизации не происходит, так как это занимает много вычислительных ресурсов.

Проведем тестирование алгоритма за 34 месяца в следующие торговые часы по Московскому времени: 7:00 и 8:00.

Эффективность самооптимизирующейся торговой системы в 7:00 и 8:00
image


Торговая система с самооптимизацией показала среднюю эффективность прогнозирования 57,2% на 103.458 сделок. Для сравнения: стратегия без оптимизации параметров показывает эффективность прогнозирования 54,7% и 195.637 сделок на тех же данных для тестирования. Сделок у самооптимизирующейся торговой системы стало меньше почти в 2 раза, зато эффективность прогнозирования повысилась в среднем на 2,5%.

Стоит отметить, что эффективность прогнозирования 57,2% является средней, отдельно взятые валютные пары могут иметь эффективность прогнозирования выше, например, AUDCAD имеет 58,3% и 4.195 сделок, а EURCHF имеет 61,8% и 3.988 сделок. Более подробно про эффективность торговли на конкретных валютных парах можно посмотреть выше в таблице под спойлером.

Вечерние часы торговли 22:00 и 23:00 показывают следующие результаты: эффективность прогнозирования 56,3% и 105.648 сделок. Простая стратегия дает в это же время 54,2% и 195.195 сделок. Итого общий прирост эффективности составил 2,1%.

Наилучшие результаты в 22:00 и 23:00 показали следующие валютные пары:

  • AUDCAD 58,3% 4.365
  • AUDCHF 57,2% 4.153
  • AUDNZD 58,0% 4.107
  • CHFJPY 57,7% 4.609
  • EURCHF 58,6% 3.966
  • EURGBP 58,3% 4.100
  • EURJPY 58,1% 4.399
  • EURNZD 57,0% 4.760
  • GBPCHF 58,1% 4.606
  • GBPJPY 58,1% 4.789


Ночью, в 0:00 и 1:00 по Московскому времени, эффективность еще выше. Средняя эффективность по всем валютным парам составила 59,4%, сделок 106.540.

Эффективность самооптимизирующейся торговой системы в 0:00 и 1:00
  • AUDCAD 60,5% 4.494
  • AUDCHF 62,5% 4.450
  • AUDJPY 59,5% 4.362
  • CADCHF 60,5% 4.250
  • CHFJPY 60,4% 4.569
  • EURAUD 61,1% 4.378
  • EURCHF 63,3% 4.337
  • EURGBP 62,3% 4.303
  • EURJPY 59,9% 4.263
  • GBPAUD 61,0% 4.524
  • GBPCHF 63,4% 4.256
  • GBPJPY 59,4% 4.075
  • GBPUSD 59,3% 3.815
  • USDCHF 59,0% 3.609


Одной из самых стабильных и хорошо прогнозируемых валютных пар оказалась EURCHF. Она показывает высокие результаты в любое торговое время, приведенное в статье. При тестировании на периоде с 09.11.2012 до 13.04.2018 в 7:00 и 8:00 эта валютная пара показала винрейт 62,4% и 7.861 сделок.

Тестирование торговли самооптимизирующегося алгоритма на исторических данных


Протестируем торговлю при использовании самооптимизирующегося алгоритма в 7:00 и 8:00 по Московскому времени. Для тестирования была взята случайная валютная пара, которая показывает хорошие результаты в данное время — EURCAD. Тестирование происходит одновременно для Форекс и для бинарных опционов. Возьмем исторические данные за 2 года 8 месяцев (с 08.06.2015 по 07.02.2018). Так как мы используем скальпинг, необходимо, чтобы спред был как можно меньше. Были использованы следующие параметры. Кредитное плечо: 1000. Спред равен 0,5 пунктов. Ордер для Форекса имеет тейк профит и стоп лосс, которые равны 3 и 30 пунктов соответственно. Ордер сначала проверяется на срабатывание по стоп лоссу, затем проверяется срабатывание тейк профита. Размер контракта всегда составляет 1% от депозита. Начальный депозит: 100.000. Для примера возьмем размер выплаты брокера 84%, а не максимальный встречающийся — 90%. Размер ставки составляет всегда 1% от депозита. Ниже представлено видео с тестированием торговли.


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

Фильтруем сигналы самооптимизирующейся торговой системы


Самооптимизация позволяет заметно повысить эффективность прогнозирования. Даже если кажется, что прирост в 2% — это мало, на графике баланса депозита 2% эффективности вносят существенный вклад. Однако результаты торговой системы с самооптимизацией — это не предел эффективности прогнозирования. Сигналы можно фильтровать различными способами, например, использовать уровень индикатора ADX, ATR или StdDev, или научить нейросеть определять ложные сигналы. Но все гениальное просто. Поэтому попробуем, например, до 15 числа каждого месяца вести подсчет верных прогнозов и, если эффективность прогнозирования в начале месяца превышает некоторый порог, после 15 числа начинать торговать.

Для торговли в 7:00 и 8:00 по Московскому времени получаем среднюю эффективность прогнозирования 58,6% и 31.551 сделок. После фильтрации сделок стало в 3 раза меньше, а средняя эффективность повысилась на 1,4%. Если посмотреть статистику отдельно взятых валютных пар, мы увидим, что появилось гораздо больше валютных пар, дающих эффективность прогнозирования от 60% и выше, а те валютные пары, которые изначально показывали плохие результаты, лучше не стали.

  • AUDCAD 59,4% 1.678
  • AUDCHF 60,8% 1.222
  • AUDJPY 57,3% 1.128
  • AUDUSD 58,6% 1.266
  • CADCHF 61,3% 1.374
  • CADJPY 57,4% 888
  • CHFJPY 59,6% 1.520
  • EURAUD 60,0% 1.343
  • EURCAD 60,4% 1.705
  • EURCHF 63,4% 1.782
  • EURGBP 61,5% 1.180
  • EURJPY 57,9% 1.136
  • EURNZD 58,3% 1.324
  • GBPAUD 58,1% 1.306
  • GBPCHF 62,4% 1.062
  • GBPJPY 58,8% 1.357


В 22:00 и 23:00 торговая система с фильтрацией показала эффективность прогнозирования 56,4% и 33.260 сделок. Прироста средней эффективности почти не произошло, а сделок стало также в 3 раза меньше. Однако, после фильтрации некоторые валютные пары стали обладать гораздо большей эффективностью прогнозирования.

  • AUDCAD 58,3% 1.686
  • AUDNZD 57,9% 1.458
  • CHFJPY 58,3% 1.164
  • EURCHF 60,4% 1.475
  • EURGBP 61,6% 1.166
  • EURNZD 57,2% 1.423
  • GBPAUD 58,7% 1.253
  • GBPCHF 57,9% 1.919
  • GBPJPY 57,9% 1.841


Программа для визуализации сигналов


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

Внешний вид программы
image
Главное окно для отображения прогнозов и котировок валютных пар
image
Окно для настроек программы
image
Окно для тестирования


Данную программу можно использовать для ручной торговли. Для удобства тестер торговли был встроен в саму программу, а также добавлены настройки самооптимизирующегося алгоритма. Скачать программу, которая позволяет тестировать валютные пары и прогнозировать движение цены на EURGBP, можно по ссылке.

Итоги


Существуют различные мнения касательно трейдинга. Первое мнение, что рынок абсолютно случаен, и больше чем в 50% случаев удачных прогнозов быть не может. Второе мнение, что нормально торговать на рынке могут только люди, а любые автоматические системы могут лишь сливать депозиты. Как мы могли убедиться, оба эти мнения не являются абсолютно верными. В данной статье тестирование простой стратегии показало, что совершив 2.418.153 сделок можно получить 54% верных прогнозов, что еще не является гарантией получения дохода, но, во всяком случае, говорит о неполной случайности рынка. Касательно же второго мнения: автоматические торговые системы, по сравнению с трейдером, имеют как свои минусы, так и свои плюсы. Если человек может видеть на графике котировок линии поддержки и сопротивления, определять линии тренда, распознавать фигуры технического анализа или чувствовать рынок, наблюдая за тем, как движется цена, то торговые системы пока что плохо справляются с данными задачами. Тем не менее, в отличии от человека, торговая система может иметь большую статистику работы, по которой можно судить о потенциальной прибыли и убытках. Торговые системы могут обрабатывать большой объем данных по различным индикаторам и использовать закономерности, которые не может использовать человек, ввиду ограничений по воспринимаемому объему информации. Поэтому алготрейдинг, в случае наличия эффективного алгоритма, дает больше шансов на успешную торговлю, нежели ручная торговля на рынке.

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

P.S.
Для самостоятельного использования можно использовать индикаторы и другие функции из моего репозитория.

© Geektimes