mql5 언어의 특징, 미묘함 및 작업 방법 - 페이지 30

 

여기 진짜 이해가 안감...

표시기에서 표준 AO 핸들을 생성하지만 지정된 시간 프레임을 사용합니다. 현재 시간과 일치하지 않는 시간 프레임으로 AO에서 데이터를 수신하면 다음과 같이 수신됩니다. 아무 것도 수신하지 않습니다 - 오류 4806.

질문: 현재 시간과 일치하지 않는 시간대의 표준 지표에서 데이터를 가져오는 방법은 무엇입니까?

 //+------------------------------------------------------------------+
//|                                                      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" );
   }
}
//+------------------------------------------------------------------+
파일:
iMTF_AO.mq5  9 kb
 
Artyom Trishkin :

여기 진짜 이해가 안감...

표시기에서 표준 AO 핸들을 생성하지만 지정된 시간 프레임을 사용합니다. 현재 시간과 일치하지 않는 시간 프레임으로 AO에서 데이터를 수신하면 다음과 같이 수신됩니다. 아무 것도 수신하지 않습니다 - 오류 4806.

질문: 현재 시간과 일치하지 않는 시간대의 표준 지표에서 데이터를 가져오는 방법은 무엇입니까?


INDICATOR에서 INDICATOR 값 가져오기 정보:

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

지표의 다른 지표에서 데이터를 가져오는 방법

블라디미르 카르푸토프 , 2016.12.27 08:41

MQL5 지표에서 기본적으로 인덱스 "0"이 있는 막대는 차트의 맨 왼쪽 막대라는 점을 염두에 두고 지표의 다른 두 지표인 MA 및 Alligator에서 데이터를 가져오도록 합시다 (이 예는 " IndicatorFromIndicators .mql5 " 표시기).

표시기에서 인덱스 "0", "1" 및 "2"가 있는 막대의 MA 및 Alligator에서 데이터를 가져오려고 합니다.

  {
//---
   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 "를 차트에 연결하고 십자선을 가장 오른쪽 막대로 설정합니다. 즉, 0 막대가 아닙니다. 다음은 일어난 일입니다.

IndicatorFromIndicators

십자선이 가장 오른쪽 막대로 설정되어 있지만, 즉 인덱스 "0"이 있는 막대는 절대 아닙니다. CopyBuffer 를 사용할 때 CopyBuffer 가 현재에서 과거로 데이터를 복사한다는 점을 알아야 합니다. 인덱스 "0"은 현재 막대를 의미합니다.


CopyBuffer: 복사된 데이터의 요소(인덱스 buffer_num이 있는 표시기 버퍼)는 시작 위치에서 현재부터 과거까지 계산됩니다. 즉, 시작 위치가 0이면 현재 막대(현재 막대의 표시기 값)를 의미합니다.


즉, MQL5 표시기에서 CopyBuffer 작업을 사용하는 경우 차트의 맨 오른쪽 막대가 표시기 버퍼의 인덱스 "0"에 해당하도록 배열(ArraySetAsSeries)을 뒤집어야 합니다(현재 "iMTF_AO.mq5" 예를 들어 차트의 맨 오른쪽 막대는 Rates_total-1)에 해당합니다.

 
블라디미르 카르푸토프 :


INDICATOR에서 INDICATOR 값 가져오기 정보:


CopyBuffer: 복사된 데이터의 요소(인덱스 buffer_num이 있는 표시기 버퍼)는 시작 위치에서 현재부터 과거까지 계산됩니다. 즉, 시작 위치가 0이면 현재 막대(현재 막대의 표시기 값)를 의미합니다.


즉, MQL5 표시기에서 CopyBuffer 작업을 사용하는 경우 차트의 맨 오른쪽 막대가 표시기 버퍼의 인덱스 "0"에 해당하도록 배열(ArraySetAsSeries)을 뒤집어야 합니다(현재 "iMTF_AO.mq5" 예를 들어 차트의 맨 오른쪽 막대는 Rates_total-1)에 해당합니다.

나는 단지 하나의 바를 얻 습니다. 그리고 "기본" 기간의 표시기는 데이터를 정상적으로 표시합니다. "비 네이티브"에서 - 빈 값. 경험적으로 AO에서 데이터를 수신한 기간 동안 전체 히스토리가 로드될 때까지 빈 값이 반환될 것이라고 추론했습니다.

 //+------------------------------------------------------------------+
//|                                                      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" );
   }
}
//+------------------------------------------------------------------+

그러면 질문이 다르게 들릴 것입니다. 기간 기록이 로드되는 동안 주기에 들어가지 않는 방법은 무엇입니까? 간단합니다. 이것은 단지 테스트일 뿐이지만 일반적으로 지표는 주어진 TF의 이력을 기반으로 계산을 수행하며 이력이 없을 때까지 계산을 수행하려고 할 필요가 없습니다.

파일:
iMTF_AO.mq5  12 kb
 
Artyom Trishkin :

나는 단지 하나의 바를 얻 습니다. 그리고 "기본" 기간의 표시기는 데이터를 정상적으로 표시합니다. "비 네이티브"에서 - 빈 값. 경험적으로 AO에서 데이터를 수신한 기간 동안 전체 히스토리가 로드될 때까지 빈 값이 반환될 것이라고 추론했습니다.

그러면 질문이 다르게 들릴 것입니다. 기간 기록이 로드되는 동안 주기에 들어가지 않는 방법은 무엇입니까? 간단합니다. 이것은 단지 테스트일 뿐이지만 일반적으로 지표는 주어진 TF의 이력을 기반으로 계산을 수행하며 이력이 없을 때까지 계산을 수행하려고 할 필요가 없습니다.

동기화를 시도 했습니까? 또한 개발자는 타이머를 통해 필요한 TF/심볼의 데이터를 최신 상태로 유지하는 것이 좋습니다.
 
여기:
      Buffer[i]=AO(i);

"i"는 "0"이 아니라 하늘 높이 값입니다. 결과적으로: M15에서 예제를 시작했다고 가정해 보겠습니다. 이 기간에 5000개의 막대가 있습니다. H4에서 데이터를 요청합니다. 여기에는 막대가 400개뿐입니다. 또한 "AO(4999)" 요청을 시도합니다.

즉, H4 기간부터 인덱스가 "4999"인 막대를 요청하려고 시도합니다. H4에는 이러한 막대가 전혀 없으며 막대 "0"을 요청해야 하지만 표시기가 CopyBuffer 작업을 사용하는 경우 차트의 맨 오른쪽 막대 가 표시기 버퍼의 인덱스 "0"에 해당하도록 배열(ArraySetAsSeries)을 뒤집어야 합니다(현재 "iMTF_AO.mq5" 예에서 차트의 맨 오른쪽 막대). rate_total-1)에 해당합니다.

 

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

오류, 버그, 질문

fxsaber , 2017.04.12 08:38

약간의 해킹. 할당 우회
 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);  
}

결과

 Struct.i = 1
StructCopy1.i = 5
StructCopy2.Value.i = 1
 
블라디미르 카르푸토프 :
여기:

"i"는 "0"이 아니라 하늘 높이 값입니다. 결과적으로: M15에서 예제를 시작했다고 가정해 보겠습니다. 이 기간에 5000개의 막대가 있습니다. H4에서 데이터를 요청합니다. 여기에는 막대가 400개뿐입니다. 또한 "AO(4999)" 요청을 시도합니다.

즉, H4 기간부터 인덱스가 "4999"인 막대를 요청하려고 시도합니다. H4에는 이러한 막대가 전혀 없으며 막대 "0"을 요청해야 하지만 표시기가 CopyBuffer 작업을 사용하는 경우 차트의 맨 오른쪽 막대 가 표시기 버퍼의 인덱스 "0"에 해당하도록 배열(ArraySetAsSeries)을 뒤집어야 합니다(현재 "iMTF_AO.mq5" 예에서 차트의 맨 오른쪽 막대). rate_total-1)에 해당합니다.

아니요, 물론 제한을 계산 하려고 했습니다.

   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 ;
       }                   

...하지만 나는 서둘러 망친 것을 보았습니다. 이것은 현재 TF에만 적합합니다.

 
Artyom Trishkin :

아니요, 물론 제한을 계산 하려고 했습니다.

...하지만 나는 서둘러 망친 것을 보았습니다. 이것은 현재 TF에만 적합합니다.


  1. 버퍼 배열(ArraySetAsSeries) 뒤집기 - 표시기가 CopyBuffer를 사용하는 경우 필요합니다.
  2. CopyBuffer: 복사된 데이터의 요소( buffer_num 인덱스가 있는 표시기 버퍼 )는 시작 위치 에서 현재부터 과거까지 계산됩니다. 즉, 시작 위치가 0이면 현재 막대(표시기 값 현재 막대) .
그 후, AO("0" 던지기 - 오른쪽 막대를 의미함)에서 하늘 높은 값이 아닙니다.
 
블라디미르 카르푸토프 :

  1. 버퍼 배열(ArraySetAsSeries) 뒤집기 - 표시기가 CopyBuffer를 사용하는 경우 필요합니다.
  2. CopyBuffer: 복사된 데이터의 요소( buffer_num 인덱스가 있는 표시기 버퍼 )는 시작 위치 에서 현재부터 과거까지 계산됩니다. 즉, 시작 위치가 0이면 현재 막대(표시기 값 현재 막대) .
그 후, AO("0" 던지기 - 오른쪽 막대를 의미함)에서 하늘 높은 값이 아닙니다.

내가 보여주는 코드를 본 적이 있습니까? 런칭하셨나요?

표시기 버퍼를 채우는 방법을 묻는 것이 아니라 현재 막대가 아닌 AO에서 값을 가져오면 빈 값이 반환되는 이유를 묻습니다.
나는 이것을 이해했습니다. 히스토리가 없습니다. 로드되고 있으며, 네이티브가 아닌 TF에서 AO를 로드하는 동안 "데이터 없음" 오류를 반환합니다.

이제 질문은 다음과 같습니다. 원하는 TF에 대한 기록이 표시기 주기에 들어가지 않도록 완전히 로드되었는지 확인하는 방법은 무엇입니까?

 
이 주제와 관련이 없는 댓글은 " MQL5 MT5 MetaTrader 5 초보자의 질문 "으로 이동되었습니다.