Features of the mql5 language, subtleties and tricks - page 32

 

I check if the indicator is ready (at the beginning ofOnCalculate)

   int calculated=BarsCalculated(IND_handle);
   if(calculated<=0 || !SymbolIsSynchronized(_Symbol) || rates_total<=0 || rates_total-prev_calculated<0) 
      { 
      Comment("Calculate...");
      return(0);
      }

You can also add a Period check

SeriesInfoInteger(_Symbol,ind_period,SERIES_SYNCHRONIZED)
 
Alexey Viktorov:

1. Just a clarification. Now it is clear that we are talking about the same thing.

2) I understand that, but I do not agree that it is necessary to flip arrays. Is it necessary to have one indicator for two terminals? It's almost like making a 2in1 scythe and an axe.

3. as I understand Buffer[] is used by the receiver in the CopyBuffer() function to get only 1 indicator value.

4. You have not paid attention to the main thing. The start of copying of the indicator values should not be determined by the bar index, but by the time of the i-th bar.

Okay.

2. I reversed the array because I rewrote the indicator from the 4 because everything is working properly in it and all data is correct. It's all about getting data in the exact sequence in which they are read in the loop. If you don't flip the buffer, you have to write the indicator from scratch - what for? It's quite complicated. This indicator was given only as an example of how erroneous is the reception of data from a non-native cf.

No. You write data into Buffer[] in the loop one by one - at each iteration of the loop you write one value taken from AO().

4. What do you mean by "start of copying"?

 
Artyom Trishkin:

1. okay.

2. I'm flipping the array because I'm rewriting the indicator from the four - everything works properly in it and all the data are correct. It's all about getting data in the exact sequence in which they are read in the loop. If you don't flip the buffer, you have to write the indicator from scratch - what for? It's quite complicated. This indicator was given only as an example of how erroneous is the reception of data from a non-native cf.

No. In Buffer[] data is inserted into the loop one by one - at each iteration of the loop one value taken from AO() is inserted

4. What do you mean by "start of copying"?

2. Nothing prevents you from building a loop from 0 to rates_total-1

3. Yes, I messed something up somewhere.

4.In your code

double AO(int shift){
   double array[];
   ArrayResize(array,1);
   ArrayInitialize(array,EMPTY_VALUE);
   error=ERR_SUCCESS;
   ResetLastError();
   if(CopyBuffer(handle,0,shift,1,array)==1) {
      ArraySetAsSeries(array,false);
      return(array[0]);
      }
   else error=GetLastError();
   return(EMPTY_VALUE);
}


int  CopyBuffer(
   int       indicator_handle,     // handle индикатора
   int       buffer_num,           // номер буфера индикатора
   int       start_pos,            // откуда начнем 
   int       count,                // сколько копируем
   double    buffer[]              // массив, куда будут скопированы данные
   );

should be changed to

int  CopyBuffer( 
   int       indicator_handle,     // handle индикатора 
   int       buffer_num,           // номер буфера индикатора 
   datetime  start_time,           // с какой даты 
   int       count,                // сколько копируем 
   double    buffer[]              // массив, куда будут скопированы данные 
   );

"Where do we start from" or "from what date" this is the start of copying the indicator values into the receiver array.


 
Alexey Viktorov:

3. Yes, I messed something up somewhere.

4.In your code.


should be changed to

"Where do we start from" or "from what date" this is the start of copying the indicator values into the receiver array.


Why pass the date, if I read the value by the loop index? Did you run this test indicator? It always draws AO only from one - the specified timeframe in the settings. No matter how you switch the current timeframe, the AO chart always corresponds to the one specified in the settings.

In my indicator, which I am modifying, the data doesn't come back from the non-native current price, despite the fact that it's coming back.

This test indicator is not needed anymore - data from nonnative cf is already returned. But data in mine are not, but I get them the same way.


 
Artyom Trishkin:

Why pass the date if I'm reading the value from the loop index? Did you run this test indicator? It always plots AO only from one - the specifiedfactor in the settings. No matter how you switch the current timeframe, the AO chart always corresponds to the one specified in the settings.

In my indicator, which I am modifying, the data doesn't come back from the non-native current price, despite the fact that it's coming back.

This test indicator is not needed anymore - data from nonnative cf is already returned. But data in mine is not, but I get it the same way.


Because the zero bar H4 contains FOUR H1 bars. And if you request index 2 of period H1 to get the indicator value at period H4, then you will get the indicator value at bar 2 at period H4.

I hardly understand what I was able to write...

At the moment it is 13:35. Opening time of the current bar H1 = 13:00. You try to copy the indicator values of the bar index = 1, i.e. the bar 12:00 of the current H1 period. But instead of the 12:00 of the H4 period you get the 8:00

For H1 the first bar is 12:00

For H4 the first bar is 8:00

Both of them have the first bar index...

 
The built-in ArrayCopy bypasses the same operator.
 

Forum on trading, automated trading systems and trading strategies testing

I can't get indicator data from older timeframe

Artyom Trishkin, 2017.04.14 01:23

For the fourth day in the indicator I'm trying to get the data of the standard AO indicator from the senior timeframe, and still nothing...

I read AO data in the loop, but exactly in the loop there is no historical data. There is data on the current bar. What is the problem? What am I doing wrong?

//+------------------------------------------------------------------+
//|                                                       MTF AO.mq5 |
//|              Copyright 2017, Artem A. Trishkin, Skype artmedia70 |
//|                       https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70"
#property link      "https://login.mql5.com/ru/users/artmedia70"
#property version   "1.00"

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot AO
#property  indicator_label1  "AO MTF"
#property  indicator_type1   DRAW_SECTION
#property  indicator_color1  clrRed
#property  indicator_style1  STYLE_SOLID
#property  indicator_width1  1

//--- indicator buffers
double         BufferAO[];
//+------------------------------------------------------------------+
//|  Enums                                                           |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|  Input Variables                                                 |
//+------------------------------------------------------------------+
sinput   ENUM_TIMEFRAMES   PeriodForWork  =  PERIOD_M5;  // Таймфрейм, на котором искать дивергенции
//+------------------------------------------------------------------+
//|  Global Variables                                                |
//+------------------------------------------------------------------+
string            Prefix, symbol;
int               handle_ao;                 // Хэндл AO
int               size_ao=0;                 // Количество скопированных данных AO
double            array_ao[];                // Массив данных АО
ENUM_TIMEFRAMES   periodForWork;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BufferAO);
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
   ArrayInitialize(BufferAO,0);
   
   //--- проверка рабочего периода и его смена, если выбран рабочий период меньше текущего
   periodForWork=PeriodForWork;
   if(Period()>periodForWork && PeriodForWork!=PERIOD_CURRENT) {
      Alert("Выбран не корректный период: ",GetNameTF(PeriodForWork),"\nМеняю рабочий период на ",GetNameTF(Period()));
      periodForWork=PERIOD_CURRENT;//GetTFasEnum(Period());
      }

   //--- имена
   symbol=Symbol();                                                        // Symbol()
   Prefix="MTFdiv";                                                        // Префикс имён объектов
   IndicatorSetString(INDICATOR_SHORTNAME,Prefix);                         // Короткое имя индикатора
   
   //--- хэндл AO
   handle_ao=iAO(symbol,periodForWork);
   if(handle_ao==INVALID_HANDLE) {
      Print("Не удалось создать хэндл AO");
      return(INIT_FAILED);
      }
   int count=(int)SeriesInfoInteger(symbol,periodForWork,SERIES_BARS_COUNT);
   size_ao=CopyBuffer(handle_ao,0,0,count,array_ao);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- delete graphics
   ObjectsDeleteAll(0,Prefix);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   ArraySetAsSeries(BufferAO,true);
   ArraySetAsSeries(array_ao,true);
   //---
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
   
   int count=(int)SeriesInfoInteger(symbol,periodForWork,SERIES_BARS_COUNT);
   //---
   if(rates_total<1) return(0);
   //---
   int limit=rates_total-prev_calculated;
   if(limit>1) {
      limit=rates_total-1;
      ArrayInitialize(BufferAO,0);
      }
   
   int periodSeconds=PeriodSeconds(periodForWork); // Количество секунд в рабочем периоде
   static datetime lastTime=0;
   int bar_first=TerminalInfoInteger(TERMINAL_MAXBARS);
   //--- основной цикл индикатора
   for(int i=limit; i>=0; i--) {
      //--- Пропускаем отсутствующие бары
      if(i>bar_first) continue;
      
      //--- Получаем данные АО
      ResetLastError();
      size_ao=CopyBuffer(handle_ao,0,0,count,array_ao);
      if(size_ao<0) Print("Ошибка копирования данных AO ",GetLastError());
      
      //--- время открытия бара на рабочем периоде, соответствующее времени бара i на текущем периоде
      datetime timePeriod=GetTimeOpen(symbol,periodForWork,i);
      //--- если нашли открытие нового бара на рабочем таймфрейме (текущее время больше прошлого)
      if(timePeriod>0 && timePeriod>lastTime) { 
         //---
         datetime time_work=GetTimeOpen(symbol,periodForWork,i);                 // время открытия i на рабочем таймфрейме
         int bar_work_to_current=GetBarShift(symbol,PERIOD_CURRENT,time_work);   // бар открытия времени time_work на текущем периоде графика
         double ao_work=GetDataAO(time_work);                                    // значение АО на баре i
         //---
         if(i<5) {
            Print("Work period: ",GetNameTF(periodForWork),
                  ",i=",i,", bar_work_to_current=",bar_work_to_current,
                  ", time_work=",TimeToString(time_work,TIME_MINUTES),
                  ", ao_work=",DoubleToString(ao_work,Digits())
                 );
            }
         BufferAO[bar_work_to_current]=ao_work;
         //--- конец обработки текущего бара
         lastTime=timePeriod; // запомним прошлое время для дальнейшего сравнения с временем следующего бара
         }
      //--- конец цикла индикатора
      }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Functions                                                        |
//+------------------------------------------------------------------+
double GetDataAO(int shift) {
   double array[1];
   if(CopyBuffer(handle_ao,0,shift,1,array)==1) return(array[0]);
   return(0);
}
//+------------------------------------------------------------------+
double GetDataAO(datetime shift) {
   double array[1];
   if(CopyBuffer(handle_ao,0,shift,1,array)==1) return(array[0]);
   return(0);
}
//+------------------------------------------------------------------+
datetime GetTimeOpen(string symbol_name, ENUM_TIMEFRAMES timeframe, int index) {
   datetime array[1]={-1};
   ResetLastError();
   if(CopyTime(symbol_name,timeframe,index,1,array)==1) return(array[0]);
   Print(__FUNCTION__," > Ошибка получения времени бара ",index,"(",GetNameTF(timeframe),"): ",GetLastError());
   return(-1);
}
//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res=-1;
   datetime last_bar;
   if(SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar)) {
      if(time>last_bar) res=0;
      else {
         const int shift=Bars(symbol_name,timeframe,time,last_bar);
         if(shift>0) res=shift-1;
         }
      }
   return(res);
}
//+------------------------------------------------------------------+
string GetNameTF(int timeframe=PERIOD_CURRENT) {
   if(timeframe==PERIOD_CURRENT) timeframe=Period();
   switch(timeframe) {
      //--- MQL4
      case 1: return("M1");
      case 5: return("M5");
      case 15: return("M15");
      case 30: return("M30");
      case 60: return("H1");
      case 240: return("H4");
      case 1440: return("D1");
      case 10080: return("W1");
      case 43200: return("MN");
      //--- MQL5
      case 2: return("M2");
      case 3: return("M3");
      case 4: return("M4");      
      case 6: return("M6");
      case 10: return("M10");
      case 12: return("M12");
      case 16385: return("H1");
      case 16386: return("H2");
      case 16387: return("H3");
      case 16388: return("H4");
      case 16390: return("H6");
      case 16392: return("H8");
      case 16396: return("H12");
      case 16408: return("D1");
      case 32769: return("W1");
      case 49153: return("MN");      
      default: return("UnknownPeriod");
   }
}
//+------------------------------------------------------------------+


 
Artyom Trishkin:

Sounds to me like you are doing a lot of things "wrong". Please describe what needs to be done: sequentially, point by point.
 

Forum on trading, automated trading systems and trading strategies testing

Peculiarities of mql5 language, tips and tricks

fxsaber, 2017.02.27 18:40

Thanks for the tip! In the wilderness it is SymbolInfoMarginRate. So now it's like this
// Размер свободных средств, необходимых для открытия 1 лота на покупку
double GetMarginRequired( const string Symb )
{
  MqlTick Tick;
  double MarginInit, MarginMain;

  return((SymbolInfoTick(Symb, Tick) && SymbolInfoMarginRate(Symb, ORDER_TYPE_BUY, MarginInit, MarginMain)) ? MarginInit * Tick.ask *
          SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_VALUE) / (SymbolInfoDouble(Symb, SYMBOL_TRADE_TICK_SIZE) * AccountInfoInteger(ACCOUNT_LEVERAGE)) : 0);
}

You have to clearly understand that in MT5 there may be completely different margin requirements in different directions. That is, a single MT4 variant may not work. On Forex, of course, this will not be the case. But you have to remember. Therefore, in the general case it should be written like this
// Альтернатива OrderCalcMargin
bool MyOrderCalcMargin( const ENUM_ORDER_TYPE action, const string symbol, const double volume, const double price, double &margin )
{
  double MarginInit, MarginMain;

  const bool Res = SymbolInfoMarginRate(symbol, action, MarginInit, MarginMain);
  
  margin = Res ? MarginInit * price * volume * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE) /
                 (SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE) * AccountInfoInteger(ACCOUNT_LEVERAGE)) : 0;
  
  return(Res);  
}

Highlighted can return 0. In BCS encountered.

Made it like this:

//+------------------------------------------------------------------+
//| Альтернатива стандартному OrderCalcMargin()                      |
//+------------------------------------------------------------------+
//--- 
bool CGetClass::OrderCalcMargin(const ENUM_ORDER_TYPE action,const string symbol_name,const double volume,const double price,double &margin){
   double margin_init=0,margin_main=0;
   const bool res=SymbolInfoMarginRate(symbol_name,action,margin_init,margin_main);
   int liverage=int(AccountInfoInteger(ACCOUNT_LEVERAGE)==0?1:AccountInfoInteger(ACCOUNT_LEVERAGE));
   margin=res?margin_init*price*volume*SymbolInfoDouble(symbol_name,SYMBOL_TRADE_TICK_VALUE)/
                 (SymbolInfoDouble(symbol_name,SYMBOL_TRADE_TICK_SIZE)*liverage):0;
   
   return(res);  
}
//+------------------------------------------------------------------+


 
Alexey Kozitsyn:
I think you are doing a lot of things "wrong". Please describe what you need to do: step by step, point by point.

What exactly is wrong? That was the question - what am I doing wrong to get indicator data from a non-native timeframe?

Example: The indicator is running on М1, while the data from AO should be obtained from М5. So - while we have limit>1 (history needs to be recalculated), then АО from M5 returns zeros with error of no data. As soon as all the history is calculated (limit==0), the data from AO from M5 starts to arrive.

Reason: