Поделиться ... Twitter Facebook Содержание Советник - данные Интерфейс Реализация Шаблон Краткое резюме « СоветникКак делаются стратегии » Советник - данные Постепенно отделяем мух от котлет и в первую очередь организуем вычислительную часть советника и доступ к данным индикаторов. Заодно сформируем типовой шаблон для EA ea, advisor, robot Чтобы было на чём тренироваться - для начала реализуем простую стратегию «торговля по пересечению двух скользящих средних». Правила элементарнейшие: если первая (быстрая) средняя пересекает вторую снизу вверх то покупаем, а если пересекает сверху вниз то продаём. Интерфейс CrossMA.class.mqh #include <EA.mqh> class CrossMA:public EA { public: //// параметры советника // первая MA ENUM_MA_METHOD ma1_method; ENUM_APPLIED_PRICE ma1_applied; int ma1_period,ma1_shift; // вторая MA ENUM_MA_METHOD ma2_method; ENUM_APPLIED_PRICE ma2_applied; int ma2_period,ma2_shift; //// используемые данные - просто перечисление enum ENUM_DATA { MA1, MA2 }; Data *ma1,*ma2; // синонимы - указатели (для простого доступа) public: // в конструктор передаётся все параметры CrossMA(ENUM_MA_METHOD _ma1_method,ENUM_APPLIED_PRICE ma1_applied,int ma1_period,int ma1_shift, ENUM_MA_METHOD ma2_method,ENUM_APPLIED_PRICE ma2_applied,int ma2_period,int ma2_shift, int magic ); ~CrossMA(); // OnInit() - играет ту-же роль что и стандартный, проверка параметров и настройка к окружению virtual int OnInit(); // пока все операции проводим при открытии баров - в методе OnBar() virtual void OnBar(); // функция для вычисления требуемых данных virtual double Calc(int data_id,int bar); }; просто и понятно, но кто такие Data * и функция Calc ? не вдаваясь в подробности - базовый класс EA автоматически организует вычисления и буферизует результаты. Когда требуются значения данных он вызывает метод Calc для непосредственных расчётов. Тип Data как-раз и есть автоматический буфер. Доступ к данным получается очень простой: в нашем случае чтобы получить значение 1-й MA, на 3-м баре (0-текущий) достаточно обратится this[MA1][3] или ma1[3]. Реализация CrossMA.impl.mqh // подключаем интерфейс #include "CrossMA.class.mqh" // конструктор - просто запоминаем все требуемые параметры CrossMA::CrossMA( ENUM_MA_METHOD _ma1_method,ENUM_APPLIED_PRICE _ma1_applied,int _ma1_period,int _ma1_shift, ENUM_MA_METHOD _ma2_method,ENUM_APPLIED_PRICE _ma2_applied,int _ma2_period,int _ma2_shift, int _magic):EA(_magic) { ma1_method=_ma1_method;ma1_applied=_ma1_applied;ma1_period=_ma1_period;ma1_shift=_ma1_shift; ma2_method=_ma2_method;ma2_applied=_ma2_applied;ma2_period=_ma2_period;ma2_shift=_ma2_shift; } CrossMA::~CrossMA() { } // аналог системной OnInit - основную работу по инициализации проводим тут int CrossMA::OnInit() { // проверить параметры // ... для краткости - опущено // настроить синонимы, в принципе это можно делать и в конструкторе ma1=this[MA1]; ma2=this[MA2]; return INIT_SUCCEEDED; } // вычисление значений // в параметрах получаем ид.набора данных которые надо расчитать // и номер бара для расчёта (0-текущий бар) double CrossMA::Calc(int id,int bar) { double d=EMPTY_VALUE; switch(id) { case MA1: d=iMA(_Symbol,_Period,ma1_period,ma1_shift,ma1_method,ma1_applied,bar);break; case MA2: d=iMA(_Symbol,_Period,ma2_period,ma2_shift,ma2_method,ma2_applied,bar);break; } return d; } // работаем по открытию баров void CrossMA::OnBar() { if (CrossUp(ma1,ma2,1)) { // первая MA пересекла вторую снизу ВВЕРХ // покупаем Buy(); } else if (CrossDown(ma1,ma2,1)) { // первая MA пересекла вторую сверху ВНИЗ // продаём Sell(); } } если потребуется добавить например среднее значение двух MA, достаточно в перечисление добавить ид. AVG, синоним Data *avg, и функцию Calc формулу вычисления «case AVG: d=(ma1[bar]+ma2[bar])/2;break;». При этом заботится о предварительном вычислении ma1,ma2 ненадо - об этом позаботится система. Общее правило - все вычисления проводить через функцию Calc, а торговая логика должна опираться на простые сравнения больше/меньше, пересеклись/нет, убывает/возрастает и подобными. Шаблон Для того чтобы полученный советник совместить со стандартным интерфейсом, надо воспользоваться например таким шаблоном: CrossMA.mq4 /** простой эксперт для демонстрации библиотеки EA торговля по пересечению двух MA **/ #property copyright "Maxim A.Kuznetsov" #property link "http://luxtrade.tk" #property version "1.00" #property description "GenEA demonstration" #property description "simple advisor: CrossMA" #property strict //--- input parameters input ENUM_MA_METHOD MA1_METHOD=MODE_SMA; input ENUM_APPLIED_PRICE MA1_APPLIED=PRICE_CLOSE; input int MA1_PERIOD=7; input int MA1_SHIFT=0; input ENUM_MA_METHOD MA2_METHOD=MODE_SMA; input ENUM_APPLIED_PRICE MA2_APPLIED=PRICE_CLOSE; input int MA2_PERIOD=5; input int MA2_SHIFT=0; input int MAGIC=0x11bc; //---- // файлы класса (интерфейс и имплементацию) // #include "CrossMA.class.mqh" #include "CrossMA.impl.mqh" CrossMA *ea; // экземпляр эксперта int OnInit() { // создать экземпляр эксперта ea=new CrossMA( MA1_METHOD,MA1_APPLIED,MA1_PERIOD,MA1_SHIFT, MA2_METHOD,MA2_APPLIED,MA2_PERIOD,MA2_SHIFT, MAGIC); if (ea==NULL) { return INIT_FAILED; } // инициализовать его return ea.Init(); // важно чтобы именно .Init, а не OnInit } void OnDeinit(const int reason) { ea.Deinit(reason); // сообщить эксперту о выгрузке delete ea; // удалить экземпляр } /// прочие методы как правило не требуют изменений void OnTick() { ea.Tick(); } void OnTimer() { ea.Timer(); } void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { ea.ChartEvent(id,lparam,dparam,sparam); } Шаблон и реализация класса очень простые и вполне могут генерироваться внешними средствами. И кстати советник вполне работоспособен ! По умолчаниям: торговые операции проводятся на по текущему символу чарта, при вычислениях берётся текущий таймфрейм, торговля ведётся 1 лотом стоп-лосс и тейк-профит не используются 1 рыночный ордер на позицию (если есть попутный рыночный ордер, то новый не открывается) единственная позиция (то есть при открытии ордера все встречные закрываются) Краткое резюме Каких целей добились? расчётная часть отделена от всего остального, и это позволяет : легко и унифицированно обращаться к данным. Действительно обращение this[MA1][i] или ma1[i] проще и естественней чем постоянное упоминание формул, ввод лишних переменных или копирование массивов (как в MT5) отчасти оптимизировать вычисления и кешировать их результаты - система сама определяет когда надо производить вычисления, а когда использовать прежние результаты все вычисление сведены в одну функцию и это вполне естественное место для точек останова или записей в журнал отладки. Отлаживать стало проще открыт путь к интеграции с внешними средствами, например можно использовать механизм RTD для передачи данных и on-line транслировать данные в Excel сделали элементарный советник и его код довольно компактен и ясен чтобы : использовать его как шаблон для советников возможна авто-генерация о том как организованы торговые функции, как делать мультисимвол, мультитаймфрейм, мани-менеджмент и прочее - в следующих сериях