Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 32

 

Controllo se l'indicatore è pronto (all'inizio diOnCalculate)

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

si può anche aggiungere un Controllo del periodo

SeriesInfoInteger(_Symbol,ind_period,SERIES_SYNCHRONIZED)
 
Alexey Viktorov:

1. Solo un chiarimento. Ora è chiaro che stiamo parlando della stessa cosa.

2. Lo capisco, ma non sono d'accordo che si debbano capovolgere gli array per farlo. È necessario avere un indicatore per due terminali? È quasi come fare 2in1 una falce e un'ascia.

3. come ho capito Buffer[] è usato dal ricevitore nella funzione CopyBuffer() per ottenere solo 1 valore di indicatore.

4. Non avete prestato attenzione alla cosa più importante. L'inizio della copia del valore dell'indicatore non dovrebbe essere determinato dall'indice della barra, ma dal tempo della barra i-esima.

1. Ok.

2. Ho invertito l'array perché riscrivo l'indicatore dai quattro - tutto funziona correttamente in esso e tutti i dati sono corretti. Tutto in esso è legato all'ottenimento di dati nell'esatta sequenza in cui vengono letti nel ciclo. Se non giriamo il buffer, dovremo scrivere l'indicatore da zero - per quale motivo? È abbastanza complicato. Ho citato questo indicatore solo come esempio di quanto sia errato ottenere dati da un cf non nativo.

No. In Buffer[], i dati vengono inseriti nel ciclo uno per uno - ad ogni iterazione del ciclo, viene inserito un valore preso da AO().

4. Cosa intende per "inizio della copia"?

 
Artyom Trishkin:

1. Bene.

2. Sto capovolgendo l'array perché sto riscrivendo l'indicatore da quattro - tutto funziona correttamente in esso, tutti i dati sono corretti. Tutto è legato all'ottenimento dei dati nell'esatta sequenza in cui vengono letti nel ciclo. Se non giriamo il buffer, dovremo scrivere l'indicatore da zero - per quale motivo? È abbastanza complicato. Ho citato questo indicatore solo come esempio di quanto sia errato ottenere dati da un cf non nativo.

No. In Buffer[] i dati sono inseriti nel ciclo uno per uno - ad ogni iterazione del ciclo viene inserito un valore preso da AO()

4. Cosa intendete per "inizio della copiatura"?

2. Niente vi impedisce di costruire un ciclo da 0 a rates_total-1

3. Sì, ho sbagliato qualcosa da qualche parte.

4.

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[]              // массив, куда будут скопированы данные
   );

dovrebbe essere cambiato in

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

"Da dove iniziare" o "da quale data" questo è l'inizio della copia dei valori dell'indicatore nell'array del ricevitore.


 
Alexey Viktorov:

3. Sì, ho sbagliato qualcosa da qualche parte.

4. Nel vostro codice.


dovrebbe essere cambiato in

"Da dove cominciamo" o "da quale data" questo è l'inizio della copia dei valori dell'indicatore nell'array del ricevitore.


Perché passare la data se sto leggendo il valore dall'indice del ciclo? Avete eseguito questo indicatore di prova? Trae sempre AO solo da uno - il fattore di corrente specificato nelle impostazioni. Non importa come cambiate il timeframe corrente, il grafico AO corrisponde sempre a quello che avete impostato nelle impostazioni.

In questo caso tutti i dati vengono restituiti, ma nel mio indicatore che sto modificando, i dati non vengono restituiti da un prezzo non nativo.

Non avete bisogno di questo indicatore di prova - i dati di una corrente non nativa sono già restituiti. Ma i dati non vengono restituiti nel mio, ma li ottengo allo stesso modo.


 
Artyom Trishkin:

Perché passare la data se sto leggendo il valore dall'indice del ciclo? Avete eseguito questo indicatore di prova? Traccia sempre AO da uno solo - il setff nelle impostazioni. Non importa come cambiate il timeframe corrente, il grafico AO corrisponde sempre a quello che avete impostato nelle impostazioni.

In questo caso tutti i dati vengono restituiti, ma nel mio indicatore che sto modificando, i dati non vengono restituiti da un prezzo non nativo.

Non avete bisogno di questo indicatore di prova - i dati di una corrente non nativa sono già restituiti. Ma il mio no, ma ricevo i dati esattamente allo stesso modo.


Perché la barra zero H4 contiene QUATTRO barre H1. E se richiedete l'indice 2 del periodo H1, otterrete il valore dell'indicatore sulla barra 2 del periodo H4.

Faccio fatica a capire cosa sono riuscito a scrivere.

Al momento sono le 13:35. Tempo di apertura della barra H1 corrente = 13:00. Si cerca di copiare i valori dell'indicatore per l'indice della barra = 1, cioè la barra 12:00 del periodo H1 corrente. Ma invece delle 12:00 si ottengono le 8:00 al tempo H4 del periodo

Per H1 la prima barra è 12:00

Per H4 la prima barra è 8:00

Sia lì che lì l'indice della barra è il primo...

 

Forum sul trading, sistemi di trading automatico e test di strategie di trading

Non posso ottenere i dati dell'indicatore dal timeframe alto

Artyom Trishkin, 2017.04.14 01:23

Per quattro giorni ho cercato di ottenere i dati dell'indicatore AO standard dal timeframe senior nell'indicatore, e ancora nessun modo...

Sto leggendo i dati AO nel loop, ma esattamente nel loop non ci sono dati storici. Ci sono dati sulla barra corrente. Qual è il problema? Cosa sto facendo di sbagliato?

//+------------------------------------------------------------------+
//|                                                       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:

Mi sembra che stiate facendo molte cose "sbagliate". Descrivete ciò che deve essere fatto: in modo sequenziale, punto per punto.
 

Forum sul trading, sistemi di trading automatico e test di strategie di trading

Caratteristiche del linguaggio mql5, consigli e trucchi

fxsaber, 2017.02.27 18:40

Grazie per il suggerimento! Nel deserto è SymbolInfoMarginRate. Quindi ora è così
// Размер свободных средств, необходимых для открытия 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);
}

Dobbiamo essere chiari sul fatto che ci possono essere requisiti di margine molto diversi in MT5 in diverse direzioni. Cioè una singola variante di MT4 potrebbe non funzionare. Sul Forex, ovviamente, questo non sarà il caso. Ma dovete ricordare. Quindi, in generale, si dovrebbe scrivere così
// Альтернатива 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);  
}

Evidenziato può restituire 0. BKS si è imbattuto in questo.

Fatto così:

//+------------------------------------------------------------------+
//| Альтернатива стандартному 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:
Credo che stiate facendo molte cose "sbagliate". Per favore, descrivete quello che dovete fare: passo per passo, punto per punto.

Cosa c'è esattamente che non va? Questa era la domanda - cosa sto facendo di sbagliato per ottenere i dati degli indicatori da un timeframe non nativo?

Esempio: l'indicatore funziona su М1, mentre i dati di AO dovrebbero essere ottenuti da М5. Così, mentre abbiamo limite>1 (la storia deve essere ricalcolata), AO da M5 restituisce zero con assenza di errore di dati. Non appena tutta la storia è calcolata (limit==0), allora cominciano ad arrivare i dati di AO con M5.