Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri - sayfa 30

 

burayı gerçekten anlamıyorum...

Göstergede standart bir AO tanıtıcısı oluşturuyorum, ancak belirli bir zaman dilimiyle. AO'dan mevcut olanla eşleşmeyen bir zaman dilimi ile veri alırken, alıyorum ... Hiçbir şey almıyorum - 4806 hatası.

Soru: Mevcut olanla örtüşmeyen zaman dilimlerinden standart göstergelerden veri nasıl alınır?

 //+------------------------------------------------------------------+
//|                                                      iMTF_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 Label1
#property indicator_label1   "AO"
#property indicator_type1   DRAW_LINE
#property indicator_color1   clrRed
#property indicator_style1   STYLE_SOLID
#property indicator_width1   1
//--- input parameters
sinput    ENUM_TIMEFRAMES    PeriodForWork  =   PERIOD_H4 ;   // Таймфрейм, с которого берём данные AO
//--- indicator buffers
double          Buffer[];
int    handle, error= ERR_SUCCESS ;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit ()
  {
//--- indicator buffers mapping
   SetIndexBuffer ( 0 ,Buffer, INDICATOR_DATA );
   IndicatorSetInteger ( INDICATOR_DIGITS , Digits ());
   handle= iAO ( NULL ,PeriodForWork);
   if (handle== INVALID_HANDLE ) return ( INIT_FAILED );
//---
   return ( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//| 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 (Buffer, true );
   if (rates_total< 1 ) return ( 0 );
   int limit=rates_total-prev_calculated;
   if (limit> 1 ) {
      limit=rates_total- 1 ;
      }
   //---
   static string txt= "" ;
   for ( int i=limit; i>= 0 ; i--) {
      Buffer[i]=AO(i);
       if (i< 11 && i> 0 ) {
         string ao=(Buffer[i]== EMPTY_VALUE ? "EMPTY_VALUE" : DoubleToString (AO(i), Digits ()));
         txt+= "\nAO(" +( string )i+ ")=" +ao;
         }
      }
   Comment ( "handle AO: " ,handle, ", TIMEFRAME AO: " ,GetNameTF(PeriodForWork), ", error: " ,error, "\n-----------" ,txt, "\n-----------" );
//--- return value of prev_calculated for next call
   return (rates_total);
  }
//+------------------------------------------------------------------+
double AO( int shift){
   double array[ 1 ];
   error= ERR_SUCCESS ;
   ResetLastError ();
   if ( CopyBuffer (handle, 0 ,shift, 1 ,array)== 1 ) return (array[ 0 ]);
   else error= GetLastError ();
   return ( EMPTY_VALUE );
}
//+------------------------------------------------------------------+
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" );
   }
}
//+------------------------------------------------------------------+
Dosyalar:
iMTF_AO.mq5  9 kb
 
Artyom Trishkin :

burayı gerçekten anlamıyorum...

Göstergede standart bir AO tanıtıcısı oluşturuyorum, ancak belirli bir zaman dilimiyle. AO'dan mevcut olanla eşleşmeyen bir zaman dilimi ile veri alırken, alıyorum ... Hiçbir şey almıyorum - 4806 hatası.

Soru: Mevcut olanla örtüşmeyen zaman dilimlerinden standart göstergelerden veri nasıl alınır?


INDICATOR'da INDICATOR değerlerinin alınması hakkında:

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Bir göstergede başka bir göstergeden veri nasıl alınır

Vladimir Karputov , 2016.12.27 08:41

MQL5 göstergelerinde varsayılan olarak "0" indeksli çubuğun grafikteki en SOL çubuk olduğunu göz önünde bulundurarak, göstergemizdeki diğer iki göstergeden veri almaya çalışalım - MA ve Timsah (bu örnek " IndicatorFromIndicators .mql5 " göstergesi).

Göstergede, "0", "1" ve "2" indeksli çubuktaki MA ve Timsah'tan veri almaya çalışacağız:

  {
//---
   Comment ( "Проверка: time[0]=" ,time[ 0 ], "\n" ,
           "rates_total-1: " ,rates_total, "\n" ,
           "BarsCalculated(iMA): " , BarsCalculated (handle_iMA), "\n" ,
           "BarsCalculated(iAlligator): " , BarsCalculated (handle_iAlligator), "\n" ,
           "MA[" , 0 , "]=" , StringFormat ( "%." + IntegerToString ( Digits ()+ 1 )+ "f" ,iMAGet( 0 )), "\n" ,
           "MA[" , 1 , "]=" , StringFormat ( "%." + IntegerToString ( Digits ()+ 1 )+ "f" ,iMAGet( 1 )), "\n" ,
           "MA[" , 2 , "]=" , StringFormat ( "%." + IntegerToString ( Digits ()+ 1 )+ "f" ,iMAGet( 2 )), "\n" ,
           "Jaws[" , 0 , "]=" , StringFormat ( "%." + IntegerToString ( Digits ())+ "f" ,iAlligatorGet( GATORJAW_LINE , 0 )), "\n" ,
           "Jaws[" , 1 , "]=" , StringFormat ( "%." + IntegerToString ( Digits ())+ "f" ,iAlligatorGet( GATORJAW_LINE , 1 )), "\n" ,
           "Jaws[" , 2 , "]=" , StringFormat ( "%." + IntegerToString ( Digits ())+ "f" ,iAlligatorGet( GATORJAW_LINE , 2 )));
//--- return value of prev_calculated for next call
   return (rates_total);
  }

" IndicatorFromIndicators.mql5 " test göstergesini grafiğe ekleyin ve artı işaretini en SAĞ çubuğa ayarlayın - yani bu bir sıfır çubuğu değildir. İşte olanlar:

GöstergeGöstergelerden

Artı işareti en SAĞ çubuğa - yani kesinlikle "0" indeksli çubuğa değil, CopyBuffer kullanırken, CopyBuffer'ın geçmişten gelen verileri kopyalayacağını bilmelisiniz, yani çubuğa "0" indeksi, geçerli çubuk anlamına gelir.


CopyBuffer: Kopyalanan verinin öğeleri (buffer_num indeksli gösterge arabelleği), şimdiki zamandan geçmişe başlangıç konumundan sayılır, yani 0'a eşit olan başlangıç konumu, geçerli çubuk (geçerli çubuğun gösterge değeri) anlamına gelir.


Yani, bir MQL5 göstergesinde CopyBuffer işlemlerini kullanıyorsa, diziyi (ArraySetAsSeries) çevirmeniz gerekir, böylece grafikteki en sağdaki çubuk gösterge arabelleğinde (şimdi "iMTF_AO.mq5"te) "0" dizinine karşılık gelir. örneğin, grafikteki en sağdaki çubuk, oranları_toplam-1'e karşılık gelir).

 
Vladimir Karputov :


INDICATOR'da INDICATOR değerleri alma hakkında:


CopyBuffer: Kopyalanan verinin öğeleri (buffer_num indeksli gösterge arabelleği), şimdiki zamandan geçmişe başlangıç konumundan sayılır, yani 0'a eşit olan başlangıç konumu, geçerli çubuk (geçerli çubuğun gösterge değeri) anlamına gelir.


Yani, bir MQL5 göstergesinde CopyBuffer işlemlerini kullanıyorsa, diziyi (ArraySetAsSeries) çevirmeniz gerekir, böylece grafikteki en sağdaki çubuk gösterge arabelleğinde (şimdi "iMTF_AO.mq5"te) "0" dizinine karşılık gelir. örneğin, grafikteki en sağdaki çubuk, oranları_toplam-1'e karşılık gelir).

Sadece bir bar alıyorum . Ve "yerel" zaman dilimindeki gösterge verileri normal şekilde görüntüler. "Yerli olmayan" - boş bir değer. Ampirik olarak, AO'dan veri aldığım zaman dilimi için tüm geçmiş yüklenene kadar boş bir değer döndürüleceği sonucuna vardım.

 //+------------------------------------------------------------------+
//|                                                      iMTF_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 Label1
#property indicator_label1   "AO"
#property indicator_type1   DRAW_LINE
#property indicator_color1   clrRed
#property indicator_style1   STYLE_SOLID
#property indicator_width1   1
//--- input parameters
sinput    ENUM_TIMEFRAMES    PeriodForWork  =   PERIOD_H4 ;   // Таймфрейм, с которого берём данные AO
//--- indicator buffers
double          Buffer[];
int    handle, error= ERR_SUCCESS ;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit ()
  {
//--- indicator buffers mapping
   SetIndexBuffer ( 0 ,Buffer, INDICATOR_DATA );
   IndicatorSetInteger ( INDICATOR_DIGITS , Digits ());
   handle= iAO ( NULL ,PeriodForWork);
   if (handle== INVALID_HANDLE ) return ( INIT_FAILED );
//---
   return ( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//| 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 (Buffer, true );
   int bars= Bars ( NULL ,PeriodForWork);
   datetime time_limit=GetTime( Symbol (),PeriodForWork,bars- 1 );
   int limit_p=GetBarShift( Symbol (), Period (),time_limit);
   if (rates_total< 1 ) return ( 0 );
   int limit=(PeriodForWork== Period ()?rates_total-prev_calculated:limit_p);
   if (limit> 1 ) {
      limit=rates_total- 1 ;
      }
   //---
   static string txt= "" ;
   for ( int i=limit; i>= 0 ; i--) {
      Buffer[i]=AO(i);
       if (i< 6 && i> 0 ) {
         string ao=(Buffer[i]== EMPTY_VALUE ? "EMPTY_VALUE" : DoubleToString (AO(i), Digits ()));
         txt+= "\nAO(" +( string )i+ ")=" +ao;
         }
      }
   Comment ( "handle AO: " ,handle, ", TIMEFRAME AO: " ,GetNameTF(PeriodForWork), ", error: " ,error, "\n-----------" ,(error> 0 ? "\nLoading history" :txt),
           "\n-----------" ,
           "\nAO(1)=" , DoubleToString (AO( 1 ), Digits ()),
           "\nAO(" ,limit_p, ")=" , DoubleToString (AO(limit_p), Digits ())
          );
//--- return value of prev_calculated for next call
   return (rates_total);
  }
//+------------------------------------------------------------------+
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 );
}
//+------------------------------------------------------------------+
datetime GetTime( const string symbol_name, const ENUM_TIMEFRAMES timeframe, const int shift) {
   datetime array[ 1 ];
   ResetLastError ();
   if ( CopyTime (symbol_name,timeframe,shift, 1 ,array)== 1 ) return (array[ 0 ]);
   Print ( __FUNCTION__ , " > Ошибка получения времени бара " ,shift, ": " , GetLastError ());
   return ( 0 );
}
//+------------------------------------------------------------------+
int GetBarShift( const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res= WRONG_VALUE ;
   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" );
   }
}
//+------------------------------------------------------------------+

O zaman soru farklı gelecek: zaman çerçevesi geçmişi yüklenirken döngüye nasıl girilmez? Çok basit - bu sadece bir test, ancak genel olarak gösterge, belirli bir TF'nin geçmişine dayalı olarak hesaplamalar yapar ve geçmiş kalmayıncaya kadar bunları gerçekleştirmeye çalışmanıza gerek yoktur.

Dosyalar:
iMTF_AO.mq5  12 kb
 
Artyom Trishkin :

Sadece bir bar alıyorum . Ve "yerel" zaman dilimindeki gösterge verileri normal şekilde görüntüler. "Yerli olmayan" - boş bir değer. Ampirik olarak, AO'dan veri aldığım zaman dilimi için tüm geçmiş yüklenene kadar boş bir değer döndürüleceği sonucuna vardım.

O zaman soru farklı gelecek: zaman çerçevesi geçmişi yüklenirken döngüye nasıl girilmez? Çok basit - bu sadece bir test, ancak genel olarak gösterge, belirli bir TF'nin geçmişine dayalı olarak hesaplamalar yapar ve geçmiş kalmayıncaya kadar bunları gerçekleştirmeye çalışmanıza gerek yoktur.

Senkronizasyonu denediniz mi? Ayrıca geliştiriciler, gerekli TF/sembolün verilerini bir zamanlayıcı aracılığıyla güncel tutmayı tavsiye eder.
 
Burada:
      Buffer[i]=AO(i);

"i", "0"a değil, çok yüksek bir değere eşittir. Sonuç olarak: diyelim ki M15'te bir örnek başlattık - bu dönemde 5000 barımız var. H4'ten veri istiyoruz - üzerinde sadece 400 çubuk var. Ayrıca "AO(4999)" isteği girişimi de var.

Yani, H4 döneminden, "4999" endeksli bir çubuk talep edilmeye çalışılır - ve H4'te böyle bir çubuk yoktur, "0" çubuğu talep etmeniz gerekse de sadece 400 çubuk vardır ve eğer gösterge CopyBuffer işlemlerini kullanır, grafikteki en sağdaki çubuğun gösterge arabelleğindeki "0" dizinine karşılık gelmesi için diziyi (ArraySetAsSeries ) çevirmeniz gerekir (şimdi "iMTF_AO.mq5" örneğinde, grafikte en sağdaki çubuk oranları_toplam-1'e karşılık gelir).

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Hatalar, hatalar, sorular

fxsaber , 2017.04.12 08:38

Küçük bir hack. Atama atlama
 template < typename T>
struct STRUCT_COPY
{
  T Value;
  
  STRUCT_COPY( const T& tValue)
  {
     this = (STRUCT_COPY)tValue;
  }  
};

struct STRUCT
{
   int i;
  
   void operator =( const STRUCT& )
  {
     this .i = 5 ;
  }
};

#define PRINT(A) :: Print ( #A + " = " + ( string )(A));

void OnStart ()
{
  STRUCT Struct;  
  Struct.i = 1 ;  
  PRINT(Struct.i);
  
  STRUCT StructCopy1 = Struct;
  PRINT(StructCopy1.i);
  
   // Обходим void STRUCT::operator=(const STRUCT&)
  STRUCT_COPY<STRUCT> StructCopy2(Struct);
  PRINT(StructCopy2.Value.i);  
}

Sonuç

 Struct.i = 1
StructCopy1.i = 5
StructCopy2.Value.i = 1
 
Vladimir Karputov :
Burada:

"i", "0"a değil, çok yüksek bir değere eşittir. Sonuç olarak: diyelim ki M15'te bir örnek başlattık - bu dönemde 5000 barımız var. H4'ten veri istiyoruz - üzerinde sadece 400 çubuk var. Ayrıca "AO(4999)" isteği girişimi de var.

Yani, H4 döneminden, "4999" endeksli bir çubuk talep edilmeye çalışılır - ve H4'te böyle bir çubuk yoktur, "0" çubuğu talep etmeniz gerekse de sadece 400 çubuk vardır ve eğer gösterge CopyBuffer işlemlerini kullanır, grafikteki en sağdaki çubuğun gösterge arabelleğindeki "0" dizinine karşılık gelmesi için diziyi (ArraySetAsSeries ) çevirmeniz gerekir (şimdi "iMTF_AO.mq5" örneğinde, grafikte en sağdaki çubuk oranları_toplam-1'e karşılık gelir).

Hayır, tabii ki limiti hesaplamaya çalıştım:

   int bars= Bars ( NULL ,PeriodForWork);                         
   datetime time_limit=GetTime( Symbol (),PeriodForWork,bars- 1 );
   int limit_p=GetBarShift( Symbol (), Period (),time_limit);     
   if (rates_total< 1 ) return ( 0 );
   int limit=(PeriodForWork== Period ()?rates_total-prev_calculated:limit_p);
   if (limit> 1 ) {          
       limit=rates_total- 1 ;
       }                   

... ama acelem olduğunu görüyorum - bu sadece mevcut TF için uygun

 
Artyom Trishkin :

Hayır, tabii ki limiti hesaplamaya çalıştım:

... ama acelem olduğunu görüyorum - bu sadece mevcut TF için uygun


  1. Tampon dizisini çevirin (ArraySetAsSeries) - gösterge CopyBuffer kullanıyorsa bu gereklidir
  2. CopyBuffer'ın: Kopyalanan verinin öğelerinin (buffer_num indeksli gösterge arabelleği ) başlangıç konumundan şimdiki zamandan geçmişe kadar sayılır, yani 0'a eşit başlangıç konumu, geçerli çubuk anlamına gelir (gösterge değeri için gösterge değeri). geçerli çubuk) .
Bundan sonra, AO'da ("0" atmak - SAĞ ÇUBUK anlamına gelir) ve çok yüksek bir değer değil.
 
Vladimir Karputov :

  1. Tampon dizisini çevirin (ArraySetAsSeries) - gösterge CopyBuffer kullanıyorsa bu gereklidir
  2. CopyBuffer'ın: Kopyalanan verinin öğelerinin (buffer_num indeksli gösterge arabelleği ) başlangıç konumundan şimdiki zamandan geçmişe kadar sayılır, yani 0'a eşit başlangıç konumu, geçerli çubuk anlamına gelir (gösterge değeri için gösterge değeri). geçerli çubuk) .
Bundan sonra, AO'da ("0" atmak - SAĞ ÇUBUK anlamına gelir) ve çok yüksek bir değer değil.

Gösterdiğim koda bile baktınız mı? Başlattın mı?

Gösterge arabelleğinin nasıl doldurulacağını değil, neden mevcut çubuktan değil AO'dan değerler alırsanız, boş değerler döndürüldüğünü sordum.
Bunu anladım - geçmiş yok - yükleniyor ve AO'yu yerel olmayan bir TF'den yüklerken "veri yok" hatası veriyor.

Şimdi soru şu: Gösterge döngüsüne girmemek için istenen TF'nin geçmişinin tam olarak yüklendiğini nasıl öğrenebilirim?

 
Bu konuyla ilgili olmayan yorumlar " MQL5 MT5 MetaTrader 5 Yeni Başlayanlardan Sorular " bölümüne taşındı.