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

 

Göstergenin hazır olup olmadığını bu şekilde kontrol ediyorum ( OnCalculate'in en başında)

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

ayrıca bir dönem kontrolü de ekleyebilirsiniz

 SeriesInfoInteger ( _Symbol ,ind_period, SERIES_SYNCHRONIZED )
 
Alexey Viktorov :

1. Sadece bir açıklama. Şimdi aynı şeyden bahsettiğimiz açık.

2. Bunu anladım, ancak bunun için dizileri çevirmenin gerekli olduğuna katılmıyorum. İki terminal için bir göstergeye sahip olmak gerekli mi??? 2'si 1 arada tırpan ve balta yapmakla neredeyse aynı.

3. Buffer[] anladığım kadarıyla CopyBuffer() işlevinde alıcı tarafından sadece 1 gösterge değeri almak için kullanılıyor.

4. En önemli şeye dikkat etmediniz. Gösterge değerinin kopyalanmasının başlangıcı, çubuk indeksine göre değil, i-inci çubuğun zamanına göre belirlenmelidir.

1. İyi.

2. Diziyi çeviriyorum çünkü göstergeyi dörtten yeniden yazıyorum - içindeki her şey olması gerektiği gibi çalışıyor, tüm veriler doğru şekilde elde ediliyor. İçindeki her şey, verileri tam olarak döngüde okundukları sırayla almaya bağlıdır. Tamponu çevirmezseniz, göstergeyi sıfırdan yazmanız gerekecek - neden? Oldukça karmaşık. Bu gösterge yalnızca yerel olmayan bir TF'den veri alma hatasına bir örnek olarak verilmiştir.

3. Hayır. Veriler, döngüde birer birer Tampon[]'a girilir - döngünün her yinelemesinde, AO()'dan elde edilen bir değer girilir

4. "Kopyalamaya başla" ile ne demek istiyorsunuz?

 
Artyom Trishkin :

1. İyi.

2. Diziyi çeviriyorum çünkü göstergeyi dörtten yeniden yazıyorum - içindeki her şey olması gerektiği gibi çalışıyor, tüm veriler doğru şekilde elde ediliyor. İçindeki her şey, verileri tam olarak döngüde okundukları sırayla almaya bağlıdır. Tamponu çevirmezseniz, göstergeyi sıfırdan yazmanız gerekecek - neden? Oldukça karmaşık. Bu gösterge yalnızca yerel olmayan bir TF'den veri alma hatasına bir örnek olarak verilmiştir.

3. Hayır. Veriler, döngüde birer birer Tampon[]'a girilir - döngünün her yinelemesinde, AO()'dan elde edilen bir değer girilir

4. "Kopyalamaya başla" ile ne demek istiyorsunuz?

2. Hiçbir şey 0'dan Rate_total-1'e bir döngü oluşturmayı engellemez

3. Evet, bir yerde bir şeyler karıştırdım.

4. Kodunuzda

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

ile değiştirilmelidir

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

"Nereden başlıyoruz" veya "hangi tarihten itibaren" gösterge değerlerinin alıcı dizisine kopyalanmasının başlangıcıdır.


 
Alexey Viktorov :

3. Evet, bir yerde bir şeyler karıştırdım.

4. Kodunuzda


ile değiştirilmelidir

"Nereden başlıyoruz" veya "hangi tarihten itibaren" gösterge değerlerinin alıcı dizisine kopyalanmasının başlangıcıdır.


Değeri döngü indeksine göre okuyorsam neden tarihi geçeyim? Bu test göstergesini çalıştırdınız mı? Ayarlarda her zaman yalnızca bir verilen TF'den AO çekiyor. Mevcut TF'yi nasıl değiştirirseniz değiştirin, AO grafiği her zaman ayarlarda verilen TF'ye karşılık gelir.

Ve tam o sırada tüm veriler yarı yarıya bir günahla döndürülür, ancak yeniden yaptığım göstergemde, veriler yerel olmayan bir TF'den döndürülmez - ve en azından çatlak ...

Bu test göstergesine artık ihtiyaç yoktur - zaten yerel olmayan bir TF'den veri döndürür. Ama benimkinde - hayır, ama verileri tamamen aynı şekilde alıyorum.


 
Artyom Trishkin :

Değeri döngü indeksine göre okuyorsam neden tarihi geçeyim? Bu test göstergesini çalıştırdınız mı? Ayarlarda her zaman yalnızca bir verilen TF'den AO çekiyor. Mevcut TF'yi nasıl değiştirirseniz değiştirin, AO grafiği her zaman ayarlarda verilen TF'ye karşılık gelir.

Ve tam o sırada tüm veriler yarı yarıya bir günahla döndürülür, ancak yeniden yaptığım göstergemde, veriler yerel olmayan bir TF'den döndürülmez - ve en azından çatlak ...

Bu test göstergesine artık ihtiyaç yoktur - zaten yerel olmayan bir TF'den veri döndürür. Ama benimkinde - hayır, ama verileri tamamen aynı şekilde alıyorum.


Sıfır çubuğu H4, DÖRT çubuk H1 içerdiğinden. Ve H4 dönemi için gösterge değerini H1 döneminin 2. indeksine göre talep ederseniz, H4 dönemi için 2. çubuktaki gösterge değerini alırsınız.

Yazdıklarımı anlamakta güçlük çekiyorum...

Şu anki saat 13:35. Mevcut çubuğun açılma zamanı H1 = 13:00. Gösterge değerlerini bar indeksi =1, yani mevcut H1 döneminin bar 12:00'sine göre kopyalamaya çalışıyorsunuz. Ve saat 8:00'in H4 zamanında 12:00 yerine alırsınız.

H1 için ilk bar 12:00

H4 için ilk çubuk 8:00

Ve burada ve orada çubuğun indeksi ilk ...

 
Normal ArrayCopy aynı operatörü atlar.
 

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

Eski TF'den gösterge verileri alınamıyor

Artyom Trishkin , 2017.04.14 01:23

Göstergedeki dördüncü gün için, standart AO göstergesinin verilerini daha yüksek zaman diliminden almaya çalışıyorum ve hala hiçbir şey...

Döngüde AO verilerini okudum, ancak döngüde tarihsel veri yok. Mevcut çubukta veri var. Amaç ne? Neyi yanlış yapıyorum?

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

Bana gelince, birçok şeyi "yanlış" yapıyorsun. Lütfen ne yapılması gerektiğini açıklayın: sırayla, nokta nokta.
 

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

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

fxsaber , 2017.02.27 18:40

Bahşiş için teşekkürler! Vahşi doğada, bu SymbolInfoMarginRate'dir. Yani şimdi
// Размер свободных средств, необходимых для открытия 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 );
}

MT5'te farklı yönlerde tamamen farklı marj gereksinimleri olabileceği açıkça anlaşılmalıdır. Onlar. tek MT4 seçeneği yuvarlanmayabilir. Forex, elbette, bu olmayacak. Ama hatırlaman gerek. Bu nedenle, genel olarak, böyle yazmanız gerekir.
// Альтернатива 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);  
}

Bir seçim 0 döndürebilir. BCS çarpıştı.

Böyle mi yaptı:

 //+------------------------------------------------------------------+
//| Альтернатива стандартному 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 :
Bana gelince, birçok şeyi "yanlış" yapıyorsun. Lütfen ne yapılması gerektiğini açıklayın: sırayla, nokta nokta.

Tam olarak yanlış olan nedir? Kulağa gelen soru buydu - yerel olmayan bir zaman diliminden gösterge verilerini almak için neyi yanlış yapıyorum?

Örnek: gösterge M1'de başlatılır ve AO'dan gelen veriler M5'ten alınmalıdır. Yani - sınırımız> 1 iken (geçmişi yeniden hesaplamamız gerekiyor), o zaman M5'li AO, veri eksikliği hatasıyla sıfırları döndürür. Tüm geçmiş hesaplanır hesaplanmaz (limit==0), M5 ile AO'dan gelen veriler gelmeye başlar.