초보자의 질문 MQL5 MT5 MetaTrader 5 - 페이지 575

 

다음은 반복 찾기 문제에 대한 나의 해결책입니다.

 //+------------------------------------------------------------------+
//|                                              FindRetryPrices.mq5 |
//|                                 Copyright 2016, Vasiliy Sokolov. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Vasiliy Sokolov."
#property link        "http://www.mql5.com"
#property version    "1.00"
#include <Dictionary.mqh>

input int RatesPeriod = 10 ;                         // Период за который ищутся повторения
input int RoundPoints = 10 ;                         // Загрубление цены в прайсстепах
class CBar : public CObject
{
private :
   MqlRates m_bar;
public :
            CBar( MqlRates & bar){m_bar = bar;}
   datetime Date(){ return m_bar.time;}
   double Open (){ return m_bar.open;}
   double High (){ return m_bar.high;}
   double Low (){ return m_bar.low;}
   double Close (){ return m_bar.close;}
};
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart ()
{
   // Нахождение повторяющихся баров
   MqlRates rates[];
   int total = CopyRates ( Symbol (), Period (), 0 , RoundPoints, rates);
   CDictionary* BarsCollections = new CDictionary(total);
   for ( int i = 0 ; i < total; i++)
   {
       double price = PriceToLevel(rates[i].high);
      CBar* bar = new CBar(rates[i]);
       if (!BarsCollections.ContainsKey(price))
         BarsCollections.AddObject(price, new CList());
      CList* equal_bars = BarsCollections.GetObjectByKey(price);
      equal_bars.Add(bar);
   }
   // Вывод повторов
   FOREACH_DICT(BarsCollections)
   {
      CList* list = node;
       if (list.Total() < 2 ) continue ;
       string retry_bars = "" ;
       for (CBar* bar = list.GetFirstNode(); bar != NULL ; bar = list.GetNextNode())
         retry_bars += " [" + TimeToString (bar.Date()) + ", " + DoubleToString (bar. High (), Digits ()) + "]" ;
       printf ( "Обнаружено совпадение баров:" + retry_bars);
   }
   delete BarsCollections;
}
//+------------------------------------------------------------------+
//| Округляет цену в соответствии с параметром RoundPoints           |
//+------------------------------------------------------------------+
double PriceToLevel( double price)
{
   double price_step = RoundPoints* Point ();
   double mn = MathFloor (price/price_step);
   return mn * price_step;
}

//+------------------------------------------------------------------+

스크립트가 작동하려면 사전 파일을 MQL5\Include에 복사하십시오.

실제 조회는 단일 패스 for 루프에서 수행되며 노란색으로 강조 표시됩니다. 결과 목록에는 반복이 포함되지 않습니다(A가 B를 반복하고 B가 A를 반복하는 경우 두 개의 {A, B} 및 {B, A} 대신 한 세트 {A, B}가 표시됨).

이 스크립트의 출력은 다음을 보여줍니다.

 2016.05 . 10 11 : 09 : 06.730 FindRetryPrices (Si Splice,M1)  Обнаружено совпадение баров: [ 2016.05 . 10 11 : 02 , 67149 ] [ 2016.05 . 10 11 : 03 , 67147 ] [ 2016.05 . 10 11 : 04 , 67144 ]
2016.05 . 10 11 : 09 : 06.730 FindRetryPrices (Si Splice,M1)  Обнаружено совпадение баров: [ 2016.05 . 10 11 : 01 , 67160 ] [ 2016.05 . 10 11 : 05 , 67161 ]
2016.05 . 10 11 : 09 : 06.730 FindRetryPrices (Si Splice,M1)  Обнаружено совпадение баров: [ 2016.05 . 10 11 : 00 , 67132 ] [ 2016.05 . 10 11 : 06 , 67139 ]
파일:
Dictionary.mqh  18 kb
 
Artyom Trishkin :

도움말에서:

바실리 소콜로프 :

다음은 반복 찾기 문제에 대한 나의 해결책입니다.


모두 정말 감사합니다!! 오늘 나는 모든 것을 알아 내려고 노력할 것입니다. 나에게는 코드 조각을 Expert Advisor에 복사하는 것뿐만 아니라 코드가 있는 그대로 작성된 이유를 파악하는 것이 중요하므로 더 많은 질문을 하게 될 것입니다.
 

표준 RSI를 계산하기 위한 함수를 찾는 데 도움을 요청합니다. 요구 사항은 간단합니다.

1. 주어진 막대의 RSI 값을 반환합니다.

2. 요청된(바람직한) 막대(필요한 경우)에 대해서만 지표를 계산합니다.

3. 주어진 TF를 믿을 수 있어야 합니다.

4. 포인트 2 더 빠른 표시기로 인해 작동

어드바이저에 기능을 통합하고 싶은데 준비된 사람이 있으면 공유해 주시기 바랍니다.

지표가 너무 흔하고 비밀이 아니라서 여쭤봅니다.

 
-Aleks- :

표준 RSI를 계산하기 위한 함수를 찾는 데 도움을 요청합니다. 요구 사항은 간단합니다.

1. 주어진 막대의 RSI 값을 반환합니다.

2. 요청된(바람직한) 막대(필요한 경우)에 대해서만 지표를 계산합니다.

3. 주어진 TF를 믿을 수 있어야 합니다.

4. 포인트 2 더 빠른 표시기로 인해 작동합니다.

어드바이저에 기능을 통합하고 싶은데 준비된 사람이 있으면 공유해 주시기 바랍니다.

지표가 너무 흔하고 비밀이 아니라서 여쭤봅니다.

표준 iRSI가 마음에 들지 않는 이유는 무엇입니까? 충분히 비밀스럽지 않습니까?
 
Vasiliy Sokolov :
표준 iRSI가 마음에 들지 않는 이유는 무엇입니까? 충분히 비밀스럽지 않습니까?
함수에 적용해야 하는 변경 사항이 있습니다...
 
-Aleks- :
함수에 적용해야 하는 변경 사항이 있습니다...

그런 다음 완성된 것을 가져 와서 요구 사항에 따라 수정하십시오.

 //+------------------------------------------------------------------+
//|                                                          RSI.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright    "2009, MetaQuotes Software Corp."
#property link          "http://www.mql5.com"
#property description "Relative Strength Index"
//--- indicator settings
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1 30
#property indicator_level2 70
#property indicator_buffers 3
#property indicator_plots    1
#property indicator_type1   DRAW_LINE
#property indicator_color1  DodgerBlue
//--- input parameters
input int InpPeriodRSI= 14 ; // Period
//--- indicator buffers
double     ExtRSIBuffer[];
double     ExtPosBuffer[];
double     ExtNegBuffer[];
//--- global variable
int        ExtPeriodRSI;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit ()
  {
//--- check for input
   if (InpPeriodRSI< 1 )
     {
      ExtPeriodRSI= 12 ;
       Print ( "Incorrect value for input variable InpPeriodRSI =" ,InpPeriodRSI,
             "Indicator will use value =" ,ExtPeriodRSI, "for calculations." );
     }
   else ExtPeriodRSI=InpPeriodRSI;
//--- indicator buffers mapping
   SetIndexBuffer ( 0 ,ExtRSIBuffer, INDICATOR_DATA );
   SetIndexBuffer ( 1 ,ExtPosBuffer, INDICATOR_CALCULATIONS );
   SetIndexBuffer ( 2 ,ExtNegBuffer, INDICATOR_CALCULATIONS );
//--- set accuracy
   IndicatorSetInteger ( INDICATOR_DIGITS , 2 );
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger ( 0 , PLOT_DRAW_BEGIN ,ExtPeriodRSI);
//--- name for DataWindow and indicator subwindow label
   IndicatorSetString ( INDICATOR_SHORTNAME , "RSI(" + string (ExtPeriodRSI)+ ")" );
//--- initialization done
  }
//+------------------------------------------------------------------+
//| Relative Strength Index                                          |
//+------------------------------------------------------------------+
int OnCalculate ( const int rates_total,
                 const int prev_calculated,
                 const int begin,
                 const double &price[])
  {
   int     i;
   double diff;
//--- check for rates count
   if (rates_total<=ExtPeriodRSI)
       return ( 0 );
//--- preliminary calculations
   int pos=prev_calculated- 1 ;
   if (pos<=ExtPeriodRSI)
     {
       //--- first RSIPeriod values of the indicator are not calculated
      ExtRSIBuffer[ 0 ]= 0.0 ;
      ExtPosBuffer[ 0 ]= 0.0 ;
      ExtNegBuffer[ 0 ]= 0.0 ;
       double SumP= 0.0 ;
       double SumN= 0.0 ;
       for (i= 1 ;i<=ExtPeriodRSI;i++)
        {
         ExtRSIBuffer[i]= 0.0 ;
         ExtPosBuffer[i]= 0.0 ;
         ExtNegBuffer[i]= 0.0 ;
         diff=price[i]-price[i- 1 ];
         SumP+=(diff> 0 ?diff: 0 );
         SumN+=(diff< 0 ?-diff: 0 );
        }
       //--- calculate first visible value
      ExtPosBuffer[ExtPeriodRSI]=SumP/ExtPeriodRSI;
      ExtNegBuffer[ExtPeriodRSI]=SumN/ExtPeriodRSI;
       if (ExtNegBuffer[ExtPeriodRSI]!= 0.0 )
         ExtRSIBuffer[ExtPeriodRSI]= 100.0 -( 100.0 /( 1.0 +ExtPosBuffer[ExtPeriodRSI]/ExtNegBuffer[ExtPeriodRSI]));
       else
        {
         if (ExtPosBuffer[ExtPeriodRSI]!= 0.0 )
            ExtRSIBuffer[ExtPeriodRSI]= 100.0 ;
         else
            ExtRSIBuffer[ExtPeriodRSI]= 50.0 ;
        }
       //--- prepare the position value for main calculation
      pos=ExtPeriodRSI+ 1 ;
     }
//--- the main loop of calculations
   for (i=pos;i<rates_total && ! IsStopped ();i++)
     {
      diff=price[i]-price[i- 1 ];
      ExtPosBuffer[i]=(ExtPosBuffer[i- 1 ]*(ExtPeriodRSI- 1 )+(diff> 0.0 ?diff: 0.0 ))/ExtPeriodRSI;
      ExtNegBuffer[i]=(ExtNegBuffer[i- 1 ]*(ExtPeriodRSI- 1 )+(diff< 0.0 ?-diff: 0.0 ))/ExtPeriodRSI;
       if (ExtNegBuffer[i]!= 0.0 )
         ExtRSIBuffer[i]= 100.0 - 100.0 /( 1 +ExtPosBuffer[i]/ExtNegBuffer[i]);
       else
        {
         if (ExtPosBuffer[i]!= 0.0 )
            ExtRSIBuffer[i]= 100.0 ;
         else
            ExtRSIBuffer[i]= 50.0 ;
        }
     }
//--- OnCalculate done. Return new prev_calculated.
   return (rates_total);
  }
//+------------------------------------------------------------------+
 
Vasiliy Sokolov :

그런 다음 완성된 것을 가져 와서 요구 사항에 따라 수정하십시오.

그래서 코드에 표시가 있다는 것을 알고 있습니다 ... 질문은 누가 이미 변경할 수 있었는지였습니다 ...
 
Vasiliy Sokolov :

다음은 반복 찾기 문제에 대한 나의 해결책입니다.

Vasily, #include <Dictionary.mqh>를 열면 EA 본문에서와 같은 것이 열립니다. 그래야만 합니까? 아니면 내부에 다른 코드가 있습니까?

내가 보는 코드에서 반복을 찾는 방법이 명확하지 않기 때문에((

 
Artyom Trishkin :

 // строку int searchPeriod=(Search_Period<1)?1:Search_Period;
// можно расписать так:

input int Search_Period= 10 ; // Количество копируемых свечей ... эту строку вы видите в настройках
int searchPeriod;           // Сюда будем записывать входной параметр
if (Search_Period< 1 ) searchPeriod= 1 ; // Если во входном параметре ввели ноль или меньше нуля, то параметр будет равен нулю
else searchPeriod=Search_Period;     // иначе примем входной параметр

// соответственно и строку int delta=(Delta<0)?0:Delta;
// можно расписать точно так же

이것이 오타라고 생각하는 것이 맞습니까? 1이 아닌 0이어야 합니다.

int searchPeriod=(Search_Period<1)?0:Search_Period;

실행 가능한 스크립트에서 더 나아가:

int copy_bars=(int)fmin( Search_Period ,Bars(Symbol(),Period())); // 복사된 양초의 수

바로 거기에 이론적으로 이미 변수 searchPeriod 를 사용해야 합니다. 그래서?

------

또 다른 질문, 이 줄은 무엇을 합니까? 무엇을 위해 필요합니까? 구조의 각 요소가 재설정됨을 발견했습니다. 그리고 이론적으로 방금 이 데이터를 기록했고 계속 사용해야 한다면 왜 그리고 무엇을 재설정하는지 이해할 수 없습니다.

제로메모리( dataCandle ); // 구조체의 데이터를 0으로 만듭니다.

 
Andrey Koldorkin :

이것이 오타라고 생각하는 것이 맞습니까? 1이 아닌 0이어야 합니다.

int searchPeriod=(Search_Period<1)?0:Search_Period;

실행 가능한 스크립트에서 더 나아가:

int copy_bars=(int)fmin( Search_Period ,Bars(Symbol(),Period())); // 복사된 양초의 수

바로 거기에 이론적으로 이미 변수 searchPeriod 를 사용해야 합니다. 그래서?

------

또 다른 질문, 이 줄은 무엇을 합니까? 무엇을 위해 필요합니까? 구조의 각 요소가 재설정됨을 발견했습니다. 그리고 이론적으로 방금 이 데이터를 기록했고 계속 사용해야 한다면 왜 그리고 무엇을 재설정하는지 이해할 수 없습니다.

제로메모리(dataCandle); // 구조체의 데이터를 0으로 만듭니다.


"이렇게: int searchPeriod=(Search_Period<1)?0:Search_Period; "

아니 이런 식으로. 따라서 (말 그대로): Search_Period 가 설정에서 사용자에 의해 설정되면 1보다 작으면 searchPeriod 는 0과 같을 것이고, 그렇지 않으면 searchPeriod 는 설정에서 사용자가 설정한 Search_Period 의 값과 같을 것입니다 . 이것은 사실이 아닙니다. 0과 같은 검색 범위는 필요하지 않습니다. 따라서 사용자가 이 범위를 0 또는 0보다 작은(1보다 작은) 설정하면 이 범위를 최소값 - 1과 동일하게 설정합니다.


"int copy_bars=(int)fmin( Search_Period ,Bars(Symbol(),Period())); // 복사된 양초의 수
바로 거기에 이론적으로 이미 변수 searchPeriod 를 사용해야 합니다. 그래서? "

네, 오타가 있었습니다.


"또 다른 질문입니다. 이 선은 무엇을 합니까? 무엇을 위한 것입니까? 구조의 각 요소가 0으로 재설정된다는 것을 발견했습니다. 그리고 이론적으로 방금 작성한 경우 왜 그리고 무엇을 재설정하는지 이해할 수 없습니다. 이 데이터를 계속 사용해야 합니다. ZeroMemory ( dataCandle); // 구조체의 데이터를 0으로 만듭니다."

구조를 데이터로 채우기 전에 이 작업을 수행합니다. 먼저 재설정한 다음에만 채웁니다. 봐 - 우리는 루프 전에 제로 아웃합니다. 그런 다음 루프에서 구조를 데이터로 채웁니다.