Меньше кода, больше прока.. пишем советник - страница 4

 
Maxim Kuznetsov:
Ты зачем снёс пост о следующем шаге ?? проект ведётся публично и общедоступно

Гонор пожалуйста прикрутите свой. И правила ресурса прочтите. 

Вы все можете оформлять в постах форума и в описании в КодоБазе.

 
Maxim Kuznetsov:
Ты зачем снёс пост о следующем шаге ?? проект ведётся публично и общедоступно

Видел пост, ничего криминального не увидел. Видимо, плохо смотрел.

 
Maxim Kuznetsov:

Баланс конечно валится вниз Ну а что вы хотели от «пересечения двух МА»


Вы можете взять другую основу для советника - машки далеко не лучший вариант.

 
aleger:

Вы можете взять другую основу для советника - машки далеко не лучший вариант.

если посмотрите чуть-чуть внимательнее, то заметите что уже можно реализовать немало всякого :-)

получается следующее:

* прикладной программист (пользователь библиотеки) объявил что у него micro-excel из нескольких колонок (в use-case это FAST_MA,SLOW_MA,SIGNAL_BUY,SIGNAL_SELL)

* и набросал функцию как он умеет вычислять отдельные ячейки. В примере он обратился к iMA.

* при этом он невозбранно может обращаться к другим ячейкам этой таблицы (DataFrame по возможности разрулит последовательности)

* и отдельно пользователь написал функцию "проверить значения строки, а не пора-ли торговать"

очевидно что этого достаточно, чтобы советник начал торговать. И стратегию можно менять очень гибко - всё что можете представить как табличные вычисления, всё и возможно.
другое дело что это только первые-пол-шага :-) пока-что советник торгует как мартышка-перевёртыш, только минимальным лотом, на одном символе и с одного таймфрейма.

 

В первых двух частях, получен советник который умеет исполнять самые простые стратегии, в просторечии описываемые как "мартышки или переворот по сигналу".
При этом сами по себе сигналы программируются максимально просто, почти как в экселе :-)

Пришла пора научить советник чуть большему. Хотя-бы ставить StopLoss и его тралить.

Дополняем художественное описание стратегии фразой "стоп-лосс выставляется на дистанции STOPLOSS_POINTS и далее тралится по фракталам". И вносим понятные из предыдущего, правки в use-case:

  • новый параметр советника input int STOPLOSS_POINTS=100;
  • два вычислимых поля UPPER_FRACTAL,LOWER_FRACTAL добавляем в ENUM_SERIES
  • и в функцию GetData добавим два "case:" для их вычисления

и предоставить пользователю функцию (метод класса EA), для настройки советника. Простейшая запись видится как

SetStopLoss(STOPLOSS_POINTS,LOWER_FRACTAL,UPPER_FRACTAL);

читается как "выставлять стоп лосс на указанной дистанции, и тралить buy по колонке таблицы LOWER_FRACTAL,sell по UPPER_FRACTAL"; на мой взгляд название у метода очевидное, и  синтаксис более-менее понятен.

Гипотетический пользователь и  так сделал много телодвижений (объявил input, добавил две колонки, и вызвал функцию настройки), будем развивать библиотеку чтобы его действия привели к ожидаемому результату. Придётся и развивать табличные вычисления и закладывать основы для механизма сообщений/событий.  

в copy-paste для компактности удалены лишние коментарии и код MQL5

input ENUM_APPLIED_PRICE FAST_MA_PRICE=PRICE_CLOSE;
input ENUM_MA_METHOD FAST_MA_METHOD=MODE_EMA;
input int FAST_MA_PERIOD=14;
input int FAST_MA_SHIFT=0;

input ENUM_APPLIED_PRICE SLOW_MA_PRICE=PRICE_CLOSE;
input ENUM_MA_METHOD SLOW_MA_METHOD=MODE_SMA;
input int SLOW_MA_PERIOD=54;
input int SLOW_MA_SHIFT=0;

// начальные значения StopLoss, TakeProfit
input int STOPLOSS_POINTS=100;
input int TAKEPROFIT_POINTS=200;

#include "EA/EA.mqh"

enum ENUM_SERIES {
   FAST_MA,       // id. значений FAST_MA
   SLOW_MA,       // id. значений SLOW_MA 
   SIGNAL_BUY,    // сигнал к покупкам
   SIGNAL_SELL,   // сигнал к продажам
   UPPER_FRACTAL,       // верхний фрактал (для трала стопов ордеров sell)
   LOWER_FRACTAL, // нижний фрактал
   TOTAL_SERIES   // последний элемент перечисления = кол-во элементов
};

double GetData(EA *ea,int id,int shift,DataFrame *table)
{
   switch ((ENUM_SERIES)id) {
      case FAST_MA:
         return table[FAST_MA][shift]=iMA(ea.Symbol,ea.Period,FAST_MA_PERIOD,0,FAST_MA_METHOD,FAST_MA_PRICE,shift);
      case SLOW_MA:
         return table[SLOW_MA][shift]=iMA(ea.Symbol,ea.Period,SLOW_MA_PERIOD,0,SLOW_MA_METHOD,SLOW_MA_PRICE,shift);
      case SIGNAL_BUY:
         return table[SIGNAL_BUY][shift]=table.CrossedUp(FAST_MA,SLOW_MA,shift);
      break;
      case SIGNAL_SELL:
         return table[SIGNAL_SELL][shift]=table.CrossedDn(FAST_MA,SLOW_MA,shift);
      break;
      // Расчёт уровней трала
      case UPPER_FRACTAL:
         // верхний фрактал. уровень по которому тралятся sell
         return table[UPPER_FRACTAL][shift]=iFractal(ea.Symbol,ea.Period,MODE_UPPER,shift+2);
      case LOWER_FRACTAL:
         return table[UPPER_FRACTAL][shift]=iFractal(ea.Symbol,ea.Period,MODE_LOWER,shift+2);
   }
   return EMPTY_VALUE;
}
int SignalOfCross(EA *ea,int shift,DataFrame *data)
{
   if (FAST_MA_PRICE!=PRICE_OPEN || SLOW_MA_PRICE!=PRICE_OPEN) shift++;
   if (data[SIGNAL_BUY][shift]==1.0)  return OP_BUY;
   if (data[SIGNAL_SELL][shift]==1.0) return OP_SELL;
   return -1;
}
EA *ea=NULL;

int OnInit()
{
   ea = new EA();
   ea.SetupTimeframe(_Symbol,_Period,TOTAL_SERIES,30,GetData);
   ea.SetupSignal(SignalOfCross);

        // укажем начальный стоп-лосс ордеров и уровни для тралов 
   ea.SetupStopLoss(STOPLOSS_POINTS,LOWER_FRACTAL,UPPER_FRACTAL);
   // и заодно тейк-профит
   ea.SetupTakeProfit(TAKEPROFIT_POINTS);
   // остальная часть одинакова для всех советников
   //................
}

 

 
Maxim Kuznetsov:

Уже сейчас сложно смотреть на такой код. Написать внешне просто - тяжелая задача. Лаконичность важна, но даже с ней простота легко может улетучиться.

Ваше мнение насчет Вашего кода, как и мое мнение насчет своего - очень субъективно. Наблюдатели со стороны гораздо объективнее могут сказать, сложно или просто.

Как наблюдатель Вашего кода - сложно.

 
fxsaber:

Уже сейчас сложно смотреть на такой код. Написать внешне просто - тяжелая задача. Лаконичность важна, но даже с ней простота легко может улетучиться.

Ваше мнение насчет Вашего кода, как и мое мнение насчет своего - очень субъективно. Наблюдатели со стороны гораздо объективнее могут сказать, сложно или просто.

Как наблюдатель Вашего кода - сложно.

предложи более понятную и краткую запись именно для use-case. Или правки текущего.

Это наиболее сложный момент - и как раз он в основном предложен к обсуждению.


 


 
Maxim Kuznetsov:

предложи более понятную и краткую запись именно для use-case. Или правки текущего.

Это наиболее сложный момент - и как раз он в основном предложен к обсуждению.

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

 

А что на выходе хотите получить? Я если честно не понял. Думал сначала, что а-ля фрейворк задумывается, но нет, ни классов оберток на индикаторы, ордера, стандартные алгоритмы принятия решения, ничего. Хотя гораздо читабельнее такие конструкци: fast.Get(2)>=slow.Get(1); (это я так, для примера), а объявление:

CMA fast=new CMA(NULL,0,12,...);

CMA slow=new CMA(NULL,0,100,...);

Вот это можно обсуждать, а у Вас, ИМХО, топтание на месте.

 
fxsaber:

Как наблюдатель Вашего кода - сложно.

Согласен, очень сложно читать Ваш код, даже если знаешь язык.