Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 32

 

Ich prüfe, ob der Indikator bereit ist (zu Beginn vonOnCalculate)

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

Sie können auch eine Periodenprüfung hinzufügen

SeriesInfoInteger(_Symbol,ind_period,SERIES_SYNCHRONIZED)
 
Alexey Viktorov:

1. Nur eine Klarstellung. Jetzt ist klar, dass wir über dieselbe Sache sprechen.

2) Ich verstehe das, aber ich stimme nicht zu, dass man dazu Arrays spiegeln muss. Ist ein Indikator für zwei Terminals erforderlich? Es ist fast so, als würde man aus 2in1 eine Sense und eine Axt machen.

3. soweit ich weiß, wird Buffer[] vom Empfänger in der Funktion CopyBuffer() verwendet, um nur einen Indikatorwert zu erhalten.

4. Sie haben das Wichtigste nicht beachtet. Der Beginn des Kopierens des Indikatorwertes sollte nicht durch den Taktindex, sondern durch den Zeitpunkt des i-ten Taktes bestimmt werden.

1. Ok.

2. Ich habe das Array umgedreht, weil ich den Indikator aus den vier umschreibe - alles funktioniert darin richtig und alle Daten sind korrekt. Alles darin ist daran gebunden, die Daten in der genauen Reihenfolge zu erhalten, in der sie in der Schleife gelesen werden. Wenn wir den Puffer nicht umdrehen, müssen wir den Indikator von Grund auf neu schreiben - wozu? Es ist ziemlich kompliziert. Ich habe diesen Indikator nur als Beispiel dafür angeführt, wie fehlerhaft es ist, Daten von einer nicht einheimischen Frau zu erhalten.

Nein. In Buffer[] werden die Daten nacheinander in die Schleife eingefügt - bei jeder Iteration der Schleife wird ein Wert aus AO() eingefügt.

4. Was meinen Sie mit "Beginn des Kopierens"?

 
Artyom Trishkin:

1. gut.

2. Ich drehe das Array um, weil ich den Indikator von vier neu schreibe - darin funktioniert alles richtig, alle Daten sind korrekt. Alles ist daran gebunden, die Daten in der genauen Reihenfolge zu erhalten, in der sie in der Schleife gelesen werden. Wenn wir den Puffer nicht umdrehen, müssen wir den Indikator von Grund auf neu schreiben - wozu? Es ist ziemlich kompliziert. Ich habe diesen Indikator nur als Beispiel dafür angeführt, wie fehlerhaft es ist, Daten aus einer nicht einheimischen Quelle zu erhalten.

Nein. In Buffer[] werden die Daten nacheinander in die Schleife eingefügt - bei jeder Iteration der Schleife wird ein Wert aus AO() eingefügt

4. Was meinen Sie mit "Beginn des Kopierens"?

2. Nichts hindert Sie daran, eine Schleife von 0 bis rates_total-1 zu erstellen.

3. Ja, ich habe irgendwo einen Fehler gemacht.

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

sollte geändert werden in

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

"Von wo aus beginnen" oder "von welchem Datum aus" ist der Beginn des Kopierens der Indikatorwerte in das Empfängerfeld.


 
Alexey Viktorov:

3. Ja, ich habe irgendwo etwas durcheinander gebracht.

4. in Ihrem Code.


sollte geändert werden in

"Wo fangen wir an?" oder "Ab welchem Datum?" Dies ist der Beginn des Kopierens der Indikatorwerte in das Empfängerfeld.


Warum das Datum übergeben, wenn ich den Wert aus dem Schleifenindex lese? Haben Sie diesen Testindikator ausgeführt? Er bezieht AO immer nur aus einem - dem in den Einstellungen angegebenen Stromfaktor. Unabhängig davon, wie Sie den aktuellen Zeitrahmen wechseln, entspricht der AO-Chart immer dem, den Sie in den Einstellungen festgelegt haben.

In diesem Fall werden alle Daten zurückgegeben, aber in meinem Indikator, den ich ändere, werden die Daten nicht von einem nicht-nativen Preis zurückgegeben.

Sie brauchen diesen Testindikator nicht - Daten aus einem nicht nativen Strom werden bereits zurückgegeben. In meinem Fall werden die Daten jedoch nicht zurückgegeben, aber ich erhalte sie auf die gleiche Weise.


 
Artyom Trishkin:

Warum das Datum übergeben, wenn ich den Wert aus dem Schleifenindex lese? Haben Sie diesen Testindikator ausgeführt? Es wird immer nur ein AO geplottet - das Setff in den Einstellungen. Unabhängig davon, wie Sie den aktuellen Zeitrahmen wechseln, entspricht der AO-Chart immer dem, den Sie in den Einstellungen festgelegt haben.

In diesem Fall werden alle Daten zurückgegeben, aber in meinem Indikator, den ich ändere, werden die Daten nicht von einem nicht-nativen Preis zurückgegeben.

Sie brauchen diesen Testindikator nicht - Daten aus einem nicht nativen Strom werden bereits zurückgegeben. Bei mir ist das nicht der Fall, aber ich erhalte die Daten auf genau die gleiche Weise.


Denn der Null-Balken H4 enthält VIER H1-Balken. Und wenn Sie den Index 2 der Periode H1 abfragen, erhalten Sie den Wert des Indikators in Takt 2 der Periode H4.

Ich verstehe kaum, was ich schreiben konnte.

Im Moment ist es 13:35 Uhr. Öffnungszeit des aktuellen H1-Balkens = 13:00. Sie versuchen, die Werte des Indikators mit dem Index von bar = 1 zu kopieren, d.h. bar 12:00 der aktuellen H1-Periode. Aber statt 12:00 Uhr erhalten Sie 8:00 Uhr in H4 der Periode

Für H1 ist der erste Takt 12:00

Für H4 ist der erste Takt 8:00

Sowohl dort als auch dort steht der Balkenindex an erster Stelle...

 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Ich kann keine Indikatordaten vom hohen Zeitrahmen erhalten

Artyom Trishkin, 2017.04.14 01:23

Seit vier Tagen versuche ich, die Daten des Standard-AO-Indikators aus dem älteren Zeitrahmen in den Indikator zu bekommen, und immer noch keine Möglichkeit...

Ich lese AO-Daten in der Schleife, aber genau in der Schleife gibt es keine historischen Daten. Auf dem aktuellen Balken befinden sich Daten. Was ist das Problem? Was mache ich falsch?

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

Für mich klingt das so, als ob Sie eine Menge Dinge "falsch" machen. Bitte beschreiben Sie, was zu tun ist: nacheinander, Punkt für Punkt.
 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Merkmale der Sprache mql5, Tipps und Tricks

fxsaber, 2017.02.27 18:40

Danke für den Tipp! In der Wildnis ist es SymbolInfoMarginRate. Jetzt sieht es also so aus
// Размер свободных средств, необходимых для открытия 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);
}

Wir müssen uns darüber im Klaren sein, dass es im MT5 sehr unterschiedliche Margin-Anforderungen in verschiedenen Richtungen geben kann. D.h. eine einzige MT4-Variante kann nicht funktionieren. Auf dem Forex ist dies natürlich nicht der Fall. Aber Sie müssen daran denken. Daher sollten Sie ihn im Allgemeinen wie folgt schreiben
// Альтернатива 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);  
}

Hervorgehoben kann 0 zurückgeben. BKS ist darauf gestoßen.

Ich habe es so gemacht:

//+------------------------------------------------------------------+
//| Альтернатива стандартному 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:
Ich glaube, Sie machen eine Menge Dinge "falsch". Bitte beschreiben Sie, was Sie tun müssen: Schritt für Schritt, Punkt für Punkt.

Was genau ist falsch? Das war die Frage - was mache ich falsch, um Indikatordaten aus einem nicht nativen Zeitrahmen zu erhalten?

Beispiel: Der Indikator läuft auf М1, während die Daten von AO auf М5 bezogen werden sollen. Während wir also einen Grenzwert>1 haben (die Historie muss neu berechnet werden), liefert AO von M5 Nullen, ohne dass ein Datenfehler vorliegt. Sobald die gesamte Historie berechnet ist (Limit==0), beginnen die Daten von AO mit M5 zu kommen.