English 中文 Español Deutsch 日本語 Português
Особенности написания экспертов

Особенности написания экспертов

MetaTrader 4Примеры | 13 сентября 2005, 16:18
12 302 4
MetaQuotes
MetaQuotes

Написание и тестирование экспертов в торговой системе MetaTrader имеет ряд особенностей.

  • Перед открытием позиции необходимо проверить, есть ли свободные деньги на счете. Если денег на счете недостаточно, то операция по открытию позиции закончится неудачно. При этом только при тестировании значение "FreeMargin" должно быть обязательно не меньше 1000, поскольку при тестировании цена одного лота составляет 1000.

    if(AccountFreeMargin() < 1000) return(0); // денег нет - выходим
  • Доступ к историческим данным можно получить, используя индексированные предопределенные массивы Time, Open, Low, High, Close, Volume. Исторически сложилось так, что индекс в этих массивах растет от конца к началу. Т.е., самые последние данные имеют индекс 0. Индекс 1 означает данные со смещением один период назад, индекс 2 - два периода назад, 3 - три периода назад и т.д.

    // если Close на прошлом баре меньше, чем 
    // Close на позапрошлом баре
    if(Close[1] < Close[2]) return(0);
  • Возможна также организация доступа к историческим данным по другим временным интервалам и даже по другим валютным парам. Для получения таких данных следует предварительно определить одномерный массив и выполнить операцию копирования с помощью функции "ArrayCopySeries". Причем при вызове функции можно передавать меньшее количество параметров и не указывать параметры по умолчанию.

    double eur_close_m1[];
    int number_copied = ArrayCopySeries(eur_close_m1, MODE_CLOSE, 
                                        "EURUSD", PERIOD_M1);
  • При написании эксперта так же, как и при создании любой другой программы, бывает необходим вывод некоторой дополнительной отладочной информации. Язык MQL4 предоставляет несколько возможностей для вывода такой информации.

    • Функция "Alert" выводит на экран диалоговое окно, содержащее определённые пользователем данные.

      Alert("FreeMargin grows to ", AccountFreeMargin(), "!");
    • Функция "Comment" выводит в левый верхний угол графика определённые пользователем данные. Символьная последовательность "\n" используется для перевода строки.

      Comment("FreeMargin is ", AccountFreeMargin(), ".");
    • Функция "Print" печатает определённые пользователем данные в системный журнал.

      Print("FreeMargin is ", AccountFreeMargin(), ".");
  • Для получения информации об ошибках в программах очень полезной является функция "GetLastError". Например, операция с ордером всегда возвращает номер тикета. Если номер тикета равен 0 (возникла какая-то ошибка при выполнении операции), то для определения дополнительной информации об ошибке необходимо вызвать функцию "GetLastError":

    int iTickNum = 0;
    int iLastError = 0;
    ...
    iTickNum = OrderSend(Symbol(), OP_BUY, g_Lots, Ask, 3, 0, 
                         Ask + g_TakeProfit * g_Points);
    if(iTickNum <= 0) 
      {
        iLastError = GetLastError();
        if(iLastError != ERR_NO_ERROR) 
            Alert("Some Message");  }
    Следует помнить, что вызов функции "GetLastError" выдает код последней ошибки и обнуляет ее значение. Поэтому повторный последовательный вызов этой функции всегда будет возвращать значение 0.
  • Как определить начало очередного бара? (Это бывает необходимо, чтобы узнать, что предыдущий бар только что сформировался.) Существует несколько способов.


    Первый способ основан на проверке количества баров:

    static int prevbars = 0;
    ...
    if(prevbars == Bars) return(0);
    prevbars = Bars;
    ...

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

    Следующий способ основан на том, что значение "Volume" формируется на основе количества тиков, пришедших для каждого бара, и первый тик означает, что у вновь формирующегося бара значение "Volume" равно 1:

    if( Volume[0] > 1) return(0);
    ...

    Этот способ может не сработать при слишком интенсивном поступлении ценовых тиков. Дело в том, что обработка приходящих ценовых тиков производится в отдельном потоке. И если этот поток занят во время поступления очередного тика, то во избежание излишней загрузки вычислительных ресурсов этот пришедший тик не обрабатывается! В этом случае можно также усложнить проверку, используя сохранение предыдущего значения "Volume".

    Третий способ основан на времени открытия бара:

    static datetime prevtime=0;
    ...
    if(prevtime == Time[0]) return(0);
    prevtime = Time[0];
    ...

    Это - самый надежный способ. Он сработает при любых обстоятельствах.

  • Пример работы с файлом типа "CSV":

    int h1;
    h1 = FileOpen("my_data.csv", MODE_CSV | MODE_WRITE, ";");
    if(h1 < 0)
      {
       Print("Unable to open file my_data.csv");
       return(false);
      }
    FileWrite(h1, High[1], Low[1], Close[1], Volume[1]);  
    FileClose(h1);

    Некоторые пояснения к коду. Сначала открывается файл формата "CSV". В случае ошибки открытия файла происходит выход из программы. В случае успешного открытия файла производится стирание его содержимого, запись данных в файл и последующее закрытие файла. Если необходимо сохранить содержимое открываемого файла, то следует использовать режим открытия MODE_READ:

    int h1;
    h1 = FileOpen("my_data.csv", MODE_CSV | MODE_WRITE | MODE_READ, ";");
    if(h1 < 0)
      {
       Print("Unable to open file my_data.csv");
       return(false);
      }
    FileSeek(h1, 0, SEEK_END);
    FileWrite(h1, High[1], Low[1], Close[1], Volume[1]);  
    FileClose(h1);

    В этом примере запись производится в конец файла. Для этого сразу после его открытия мы воспользовались функцией "FileSeek".

Последние комментарии | Перейти к обсуждению на форуме трейдеров (4)
Sergey
Sergey | 2 мар. 2009 в 19:36
Что то не понял что значит: "В этом случае можно усложнить проверку на разницу между значениями, равную единице." - кто нибудь может прокомментировать?
alex
alex | 2 мая 2010 в 17:17
boing9267:
Что то не понял что значит: "В этом случае можно усложнить проверку на разницу между значениями, равную единице." - кто нибудь может прокомментировать?

не заморачивайся - используй Третий способ. )
Вадим Цурков
Вадим Цурков | 22 нояб. 2015 в 17:04
Sergey:
Что то не понял что значит: "В этом случае можно усложнить проверку на разницу между значениями, равную единице." - кто нибудь может прокомментировать?
Поддерживаю вопрос, тоже очень интересно! Так как трейди спобой слишком избыточен, особенно если расчет делается для верхнего ТФ
Stanislav Korotky
Stanislav Korotky | 22 нояб. 2015 в 18:06
Sergey:
Что то не понял что значит: "В этом случае можно усложнить проверку на разницу между значениями, равную единице." - кто нибудь может прокомментировать?
Вадим Цурков:
Поддерживаю вопрос, тоже очень интересно! Так как трейди спобой слишком избыточен, особенно если расчет делается для верхнего ТФ

Элементарно:

if(prevbars == Bars - 1) // значит сформировался новый бар
{
  // обработка нового бара
  ...
  prevbars = Bars;
}

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


Особенности написания Пользовательских Индикаторов Особенности написания Пользовательских Индикаторов
Написание пользовательских индикаторов в торговой системе MetaTrader 4
Разработка и тестирование торговых систем Aroon Разработка и тестирование торговых систем Aroon
В этой статье мы узнаем, как построить торговую систему Aroon, изучив основы индикаторов и необходимые шаги для создания торговой системы на основе индикатора Aroon. После создания этой торговой системы мы проверим, может ли она быть прибыльной или требует дополнительной оптимизации.
Strategy Tester: режимы моделирования при тестировании торговых стратегий Strategy Tester: режимы моделирования при тестировании торговых стратегий
Многие программы технического анализа позволяют проводить тестирование торговых стратегий на исторических данных...
Создаем простой мультивалютный советник с использованием MQL5 (Часть 6): Два индикатора RSI пересекают линии друг друга Создаем простой мультивалютный советник с использованием MQL5 (Часть 6): Два индикатора RSI пересекают линии друг друга
Под мультивалютным советником в этой статье понимается советник, или торговый робот, который использует два индикатора RSI с пересекающимися линиями - быстрый RSI, который пересекается с медленным.