Мт4 Конец поддержке. - страница 27

 
Реter Konow:
Линейный, нелинейный... Вы опять про оперу в программировании?

никак нет

 
Реter Konow:

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

Я только начал разбиратся в этой теме, но никаких сложностей не вижу.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Мт4 Конец поддержке.

Artyom Trishkin, 2017.09.10 22:27

Я же знаю как получать котировки :)

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

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

И, понимаете, что это вы один так бы делать не стали. Остальные делают так, как правильно и надёжно. Но это, конечно же, только ваше личное дело.

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

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


 
Galina Bobro:

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

А так кажется тут больше некуда экономить операции и память - всего по минимуму

void OnTimer(){

   Alert(Fn_new_bar("EURUSD", PERIOD_D1)); }

//+------------------------------------------------------------------+

uint Sp_Adler32(string line){

   ulong s1 = 1;

   ulong s2 = 0;

   uint buflength=StringLen(line);

   uchar char_array[];

   ArrayResize(char_array, buflength,0);

   StringToCharArray(line, char_array, 0, -1, CP_ACP);

   for (uint n=0; n<buflength; n++){

      s1 = (s1 + char_array[n]) % 65521;

      s2 = (s2 + s1)     % 65521;}

   return ((s2 << 16) + s1);}

//+------------------------------------------------------------------+

bool Fn_new_bar(string symb, ENUM_TIMEFRAMES tf){

   static datetime st_time[]; 

   static uint     st_id[];

   

   //---- set

   datetime new_time = iTime(symb, tf, 0);     if(new_time==0) return(false); 

   uint     new_id   = Sp_Adler32(StringConcatenate(symb,EnumToString(tf))); 

   datetime old_time = 0; 

   uint     old_id   = 0;

   

   //---- find

   int size = ArraySize(st_time); 

   for(int i=0; i<size; i++){

      if(st_id[i]!=new_id) continue; 

      old_id   = st_id  [i]; 

      old_time = st_time[i];

      break;}

   

   //----add new element

   if(old_time==0){

      ArrayResize(st_time, size+1); st_time[size]=new_time;

      ArrayResize(st_id,   size+1); st_id  [size]=new_id; }

   

   //----

   return(old_time>0 && old_time<new_time);}


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

с уважением.

P.S. единственную мелочь, которую можно было бы сюда добавить, это объединить массивы st_time и st_id в структуру, так как они взаимосвязаны, это сократило бы количество операций приращения массива в коде.

 
Artyom Trishkin:

У меня была цель, чтобы в конечном результате его код в процедурном стиле работал в таком цикле:

 ENUM_TIMEFRAMES array_timeframes[]=
      {
      PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M30,
      PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1,PERIOD_W1,PERIOD_MN1
      };
   int total=SymbolsTotal(true), total_tf=ArraySize(array_timeframes);
   for(int i=0; i<total; i++){
      string symbol_name=SymbolName(i,true);
      for(int j=0; j<total_tf; j++){
         if(IsNewBar(symbol_name,array_timeframes[j])){
            Print("Новый бар на ",symbol_name," ",EnumToString(array_timeframes[j]));
            }
         }
      }


ну что-то вроде того (код для MQL5):

int OnInit()
  {
   IsNewBar();  // сбор информации - можно включить здесь, но не обязательно
   EventSetMillisecondTimer(100);
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   EventKillTimer();
  }

void OnTimer()
  {
   IsNewBar();   // сбор информации - можно включить здесь, но не обязательно
                 // различные варианты проверки новых баров
   if(IsNewBar(true)) Print("Пришел новый бар текущего ТФ текущего инструмента");   // режим вывода информации
   if(IsNewBar(true,PERIOD_H4)) Print("Пришел новый бар H4 текущего инструмента");  // режим вывода информации
   if(IsNewBar(true,PERIOD_D1)) Print("Пришел новый бар D1 текущего инструмента");  // режим вывода информации
   if(IsNewBar(true,PERIOD_M1,"GBPUSD.m")) Print("Пришел новый бар M1 GBPUSD");     // режим вывода информации
   if(IsNewBar(true,PERIOD_M3,"GBPUSD.m")) Print("Пришел новый бар M3 GBPUSD");     // режим вывода информации
   if(IsNewBar(true,PERIOD_M2,"USDCHF.m")) Print("Пришел новый бар M2 USDCHF");     // режим вывода информации
  }

void OnTick()
  {
   IsNewBar();   // сбор информации - можно включить здесь, но не обязательно
                 // различные варианты проверки новых баров
   if(IsNewBar(true)) Print("Пришел новый бар текущего ТФ текущего инструмента");   // режим вывода информации
   if(IsNewBar(true,PERIOD_H4)) Print("Пришел новый бар H4 текущего инструмента");  // режим вывода информации
   if(IsNewBar(true,PERIOD_D1)) Print("Пришел новый бар D1 текущего инструмента");  // режим вывода информации
   if(IsNewBar(true,PERIOD_M1,"GBPUSD.m")) Print("Пришел новый бар M1 GBPUSD");     // режим вывода информации
   if(IsNewBar(true,PERIOD_M3,"GBPUSD.m")) Print("Пришел новый бар M3 GBPUSD");     // режим вывода информации
   if(IsNewBar(true,PERIOD_M2,"USDCHF.m")) Print("Пришел новый бар M2 USDCHF");     // режим вывода информации
  }
//+---------------------------------------------------------------------------------------------------+
//|   Функция определения нового бара по всем ТФ всех инструментов в окне "Обзор рынка"               |
//|   два режима работы:                                                                              |
//|   - режим сбора информации, out=false (значение по умолчанию). Достаточно запустить IsNewBar();   |
//|   - режим вывода информации, out=true                                                             |
//|   tf - период таймфрейма, по умолчанию текущий ТФ (необходим только при выводе информации)        |
//|   Sym - символ инструмента, по умолчанию текущий символ (необходим только при выводе информации)  |
//+---------------------------------------------------------------------------------------------------+
bool IsNewBar(bool out=false, ENUM_TIMEFRAMES tf=PERIOD_CURRENT, string Sym="") 
  {
   static const ENUM_TIMEFRAMES TF[22]=
     {
      PERIOD_CURRENT,PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,PERIOD_M30,
      PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1,PERIOD_W1,PERIOD_MN1
     };
   static bool newbar[];
   static long acb[]; // array of current bars
   static int N_Sym=0;
   if(Sym=="") Sym=Symbol();
   int total=SymbolsTotal(true);
   int n_cur=-1;
   for(int i=0; i<total; i++) if(Sym==SymbolName(i,true)){ n_cur=i; break;}
   if(n_cur<0) { Print("данного символа нет в списке MarketWatch(окошко слева - Обзор рынка)"); return(false);}
   if(out && N_Sym>0) // если режим вывода информации 
     {
      int curtf=0;
      while(TF[curtf]!=tf) curtf++;
      return (newbar[n_cur*22+curtf]);
     }
// режим сбора информации
   if (total!=N_Sym) {ArrayResize(acb,22*total);ArrayInitialize(acb,0); ArrayResize(newbar,22*total); ArrayInitialize(newbar,false); N_Sym=total;}
   for(int j=0,j1=0; j<total; j++,j1+=22)
      for(int i=0;i<22;i++)
        {
         long CurBars=SeriesInfoInteger(SymbolName(j,true),TF[i],SERIES_LASTBAR_DATE);
         if(acb[j1+i]<CurBars) // пришел новый бар
           {
            //if (acb[j1+i]>0) Print ("Новый бар: "+SymbolName(j,true)+"   "+EnumToString(TF[i]));
            acb[j1+i]=CurBars;
            newbar[j1+i]=true;
           }
         else
           {
            newbar[j1+i]=false;
            if(i==1) for(;i<22;i++) newbar[j1+i]=false;   // если минутный бар тот же, то нет смысла продолжать проверять старшие ТФ
           }
        }
   return(false);
  }

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

 
Andrey Kisselyov:
речь идет не о вызове функции в советнике, а о написании универсальных интерфейсов(обработчиков).

у вас есть 1000 техзаданий на написание роботов, по сути каждый из них состоит из
1 функция получения сигнала на открытие
2 функция открытия ордера
3 функция сопровождения ордера
4 функция получения сигнала на закрытие
и так далее.
для каждого робота это свои функции, но в рамках 1000 проектов они повторяются. как следствие можно объединять функции в универсальные модули и в зависимости от задачи вызывать нужный.

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

 
Nikolai Semko:

ну что-то вроде того (код для MQL5):

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

А в принципе такой пример есть? Пусть не Ваш? У меня есть глубокие сомнения. В начале двухтысячных я перестал подсчитывать количество написанных мной отлаженных и работающих строк программного кода потому, что оно превысило миллион, стало неинтересно. И ни разу не встречалась необходимость создавать свой класс, хотя разнообразие и масштабы задач были самыми разными. Переменные процедурного типа использовать приходилось, когда надо было распараллелить работу на несколько человек, но не более. Почему так?

Кстати, а почему в качестве альтернативы ООП Вы говорите о процедурном программировании? Есть языки без ООП, принципиально непроцедурные (SQL), есть даже направление развития языков - функциональное программирование https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5: "Некоторые концепции и парадигмы специфичны для функционального программирования и в основном чужды императивному программированию (включая объектно-ориентированное программирование)", "Ещё одним преимуществом функциональных программ является то, что они предоставляют широчайшие возможности для автоматического распараллеливания вычислений." Выходит, ООП препятствует автоматическому распараллеливанию вычислений. Сейчас уже следует считать это очень серъезным недостатком, перспектива не за ООП.

 
Vladimir:

А в принципе такой пример есть? Пусть не Ваш? У меня есть глубокие сомнения. 


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

 
Andrei:

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

Да нет. Речь была не о "совершенно неприменим", а "нет смысла в применении".

Интерфейсы - это вовсе не "чисто косметическая процедура, применимая к готовому коду".

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

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

 

Все ничего, если не считать, что функции isNewBar() вообще в природе быть не должно. Забавно, что вокруг такой мелочи столько танцев.

Просто переменная, и просто она сравнивается со временем бара, если все дела прошли успешно, то переменной в конце присваивается время нового бара. Иначе на все дела выделяется только одна попытка. 

 
Dmitry Fedoseev:

Все ничего, если не считать, что функции isNewBar() вообще в природе быть не должно. Забавно, что вокруг такой мелочи столько танцев.

Просто переменная, и просто она сравнивается со временем бара, если все дела прошли успешно, то переменной в конце присваивается время нового бара. Иначе на все дела выделяется только одна попытка. 


+1

Причина обращения: