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

 
Marat Sultanov #:
이전 컴파일러 빌드에서도 클래스가 선언되기 전에 클래스를 사용할 수 있었습니다:
하지만 이제 컴파일할 때 오류가 발생합니다:
정의되지 않은 클래스 'A'를 사용할 수 없습니다.

작동이 멈추면 올바른지 알아두면 좋을 것 같습니다.

객체 대신 포인터를 만들면 이전 버전도 작동합니다.

 
fxsaber #:

작동이 멈췄다면 올바른 조치인지 알아두는 것이 좋습니다.

객체 대신 포인터를 만들면 이전 버전도 작동합니다.

좋은 지적이고 팁을 주셔서 감사합니다!

예, 실제로 포인터를 사용하면 상황이 완벽하게 해결됩니다:

class A;

class B
{
   public: A * a;
   public: int Val;
};

class A
{
   public: B * b;
   public: int Test() {return b.Val + 1;}
};

//+------------------------------------------------------------------+
//|                                                                                |
//+------------------------------------------------------------------+
void OnStart()
{
   B b;
   A a;
   
   b.a = GetPointer(a);
   b.a.b = GetPointer(b);
   b.Val = 1;
   
   Print(b.a.Test());
}
 

빠른 알고리즘을 좋아하는 분들. 나노초를 위해 싸우는 사람들 :)


과제: 주어진 시간과 TF에 따라 현재 바가 존재하는 것으로 알려진 바의 개장 시간을 찾습니다. 예를 들어, 포지션을 열고 닫는 시간까지.

대부분의 프로그래머는 iTime과 iBarShift를 조합하여 사용합니다. 이는 가장 느린 구현이며, 특히 이러한 구현에는 업로드된 데이터의 최신 기록 또는 컴바인드 배열이 필요합니다. 또한 이 접근 방식은 필요한 기록이 누락된 경우 오류가 발생할 수 있습니다.

고급 프로그래머는 MqlDateTime 구조와 TimeToStruct() 함수를 통해 이 문제를 해결합니다. 이것은 나쁘지 않은 해결책이며 충분히 빠릅니다.

그러나 이전 솔루션보다 몇 배 더 생산적인 세 번째 솔루션이 있습니다:

//+------------------------------------------------------------------+
// получает время открытия виртуального бара по входному времени и Таймфрейму, вне зависимости от того, существует реальный бар или нет.
// корректно считает только до 28.02.2100 !!!!
// не является заменой iBarShift!!! Не зависит от истории баров.  
datetime getStartTimeOfBarFast(ENUM_TIMEFRAMES tf, datetime t) {
   if (tf==0) tf=_Period;

   int ts=0;
   if (tf<PERIOD_MN1) {
      ushort i_tf= ushort(tf);
      uchar _i =uchar(i_tf>>14);
      int n = i_tf & 0x0FFF;
      ts = (_i==0)?n*60:(_i==1)?n*60*60:60*60*24*7;
   }
   if (tf<PERIOD_W1) return t-t%ts;
   if (tf==PERIOD_W1) return t-(t+4*24*60*60)%ts;
   else { // Period MN1
      static int dm[12] = {0,31,61,92,122,153,184, 214, 245, 275, 306, 337};
      static int last_days = 0;
      static datetime last_result = 0;
      int days = int(t/(24*60*60));
      if (last_days!=days) {
         last_days = days;
         int d1 = (days+306+365)%1461;
         int y = d1/365;
         datetime t1 = t - t%(24*60*60) - d1*24*60*60;
         int m = 0;
         if (d1==1460) {
            m=11;
            y--;
         };
         int d = d1-y*365+1;
         if (d!=31) if (d==276) m = 9;
            else m = int (d/30.68);
         if (m<0 || m>11) return -1;
         last_result = t1+y*365*24*60*60+dm[m]*24*60*60;
      }
      return last_result;
   }
}
//+------------------------------------------------------------------+

이 알고리즘의 가장 큰 어려움은 월 초의 시간을 계산하는 것입니다(녹색으로 강조 표시됨) 알고리즘의 작동을 이해하려고 하지 마세요. 단순한 것에서 복잡한 것으로 바뀌는 마법이 일어나고 있습니다. 복잡한 것에서 단순한 것으로의 역경로는 통과하기가 훨씬 더 어려울 것입니다.

노란색으로 강조 표시된 표준 PeriodSeconds() 함수 대신 TF에서 막대에서 초를 가져오는 알고리즘을 통해 성능 향상도 이루어집니다.


세 가지 방법의 성능을 계산하고 비교하는 테스트 스크립트를 첨부합니다:

2023.11.14 12:15:29.145 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_MN1========
2023.11.14 12:15:29.146 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 21.20 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:29.146 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 6.10 наносекунд - Быстрый расчет
2023.11.14 12:15:29.147 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 142.00 наносекунд - Расчет через iBarShift
2023.11.14 12:15:29.147 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:34.226 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_MN1========
2023.11.14 12:15:34.227 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 19.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:34.227 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 6.70 наносекунд - Быстрый расчет
2023.11.14 12:15:34.228 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 127.50 наносекунд - Расчет через iBarShift
2023.11.14 12:15:34.228 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_W1========
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 2.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:39.857 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 98.30 наносекунд - Расчет через iBarShift
2023.11.14 12:15:39.857 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:52.770 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H2========
2023.11.14 12:15:52.771 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000355999200, время выполнения 1 иттерации = 4.10 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:52.771 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000355999200, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:54.255 timeToStartMonth (EURUSD,M1)    контрольная сумма - 0, время выполнения 1 иттерации = 148466.50 наносекунд - Расчет через iBarShift
2023.11.14 12:15:54.255 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000391999920, время выполнения 1 иттерации = 3.60 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000391999920, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:59.864 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000017286960, время выполнения 1 иттерации = 110555.70 наносекунд - Расчет через iBarShift
2023.11.14 12:15:59.864 timeToStartMonth (EURUSD,M1)    ========================================================================

iBarShift는 실제 막대에서 작동하기 때문에 체크섬이 일치하지 않습니다. 이러한 막대의 기록에는 구멍이 없기 때문에 체크섬은 MN1 및 W1 시간 프레임에서만 일치합니다.
알고리즘이 이전 계산을 저장하기 위해 작업을 시작할 때 루프에서 작은 시간 단계(하루 미만)를 사용하는 경우 성능이 더 높아집니다:

2023.11.14 12:14:10.714 timeToStartMonth (EURUSD,M1)    =====LOOP=1000000========STEPS=1000 seconds======PERIOD_MN1========
2023.11.14 12:14:10.722 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 8.03 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:14:10.723 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 1.18 наносекунд - Быстрый расчет
2023.11.14 12:14:10.860 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 136.80 наносекунд - Расчет через iBarShift
2023.11.14 12:14:10.860 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:14:17.502 timeToStartMonth (EURUSD,M1)    =====LOOP=1000000========STEPS=1000 seconds======PERIOD_MN1========
2023.11.14 12:14:17.510 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 7.70 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:14:17.511 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 1.18 наносекунд - Быстрый расчет
2023.11.14 12:14:17.648 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 137.54 наносекунд - Расчет через iBarShift
2023.11.14 12:14:17.648 timeToStartMonth (EURUSD,M1)    ========================================================================


iBarShift를 통한 알고리즘의 과도한 값(파란색으로 강조 표시됨)은 현재 필요한 히스토리 또는 업로드를 시작하는 배열에 의해 계산된 TF가 부족하기 때문에 발생합니다.
업로드 후 결과는 다음과 같습니다:

2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H2========
2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000379996800, время выполнения 1 иттерации = 4.60 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000379996800, время выполнения 1 иттерации = 2.60 наносекунд - Быстрый расчет
2023.11.14 12:47:06.159 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000009103200, время выполнения 1 иттерации = 129.10 наносекунд - Расчет через iBarShift
2023.11.14 12:47:06.159 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000411199920, время выполнения 1 иттерации = 2.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000411199920, время выполнения 1 иттерации = 1.40 наносекунд - Быстрый расчет
2023.11.14 12:47:13.903 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000038634480, время выполнения 1 иттерации = 381.30 наносекунд - Расчет через iBarShift
2023.11.14 12:47:13.903 timeToStartMonth (EURUSD,M1)    ========================================================================

파일:
 
Nikolai Semko #:

빠른 알고리즘을 좋아하는 분들. 나노초를 위해 싸우는 사람들 :)

...

😮😲😳🥴🤪

...

아...

mmm....

oooh....

gkghm... 간단한 질문이 이렇게 나올 줄은 몰랐네요.

바로 그거야. 오.

 
Artyom Trishkin #:

😮😲😳🥴🤪

...

아...

음..

ohhhh....

아헴. 간단한 질문이 이렇게 나올 줄은 몰랐네요.


네, 아르템, 당신은 잠시 저를 속였습니다.
스포츠에 대한 관심사였습니다.
저를 포함한 누군가에게 도움이되기를 바랍니다. :))

 
Nikolai Semko #:

네, 아르템, 당신은 한동안 나를 속였습니다.
나는 스포츠 관심사에 대해 일했습니다.
누군가에게, 그리고 다른 사람들에게 도움이되기를 바랍니다. :))

물론 그럴 것입니다. 좋아요. 다시 한번 감사드립니다!

"28.02.2100까지만 올바르게 계산됩니다 !!!!".

그 이후에는 어떻게 해야 하나요?

 
Artyom Trishkin #:

물론 유용하게 사용할 수 있습니다. 좋아요. 다시 한 번 감사드립니다!

"28.02.2100까지만 올바르게 계산됩니다 !!!!".

그 이후에는 어떻게 해야 하나요?

하하.
이 알고리즘이 75년 동안 수요가 있을지는 의문입니다. 양자 컴퓨터는 아마도 완전히 다른 프로그래밍으로 이미 세상을 지배할 것입니다.
솔직히 말해서 그레고리력을 고려하는 것은 게으른 일이었습니다. 2000년은 위험 부담이 컸지만 2100년은 더 이상 그렇지 않습니다.

 
Nikolai Semko #:

하하.
이 알고리즘이 75년 동안 수요가 있을지는 의문입니다. 양자 컴퓨터는 아마도 완전히 다른 프로그래밍으로 이미 세상을 지배 할 것입니다.
솔직히 말해서 그레고리력을 완전히 고려하는 것은 게으른 일이었습니다. 2000년은 위험 부담이 컸지만 2100년은 더 이상 그렇지 않습니다.

MN의 경우 미리 계산된 배열을 사용할 수 있으며, 거기에는 거의 아무것도 없습니다.

Ln2(12개월 * 100년)...11 if`'와 이진 검색에서 비교를 사용하지만 다른 계산은 하지 않습니다.

 
Maxim Kuznetsov #:

MN에는 미리 계산된 배열을 사용할 수 있으며, 데이터가 거의 없습니다.

Ln2(12개월 * 백년)...11 if`'와 이진 검색에서 비교를 사용하지만 다른 계산은 하지 않습니다.

어려움은 없습니다. 구현하는 방법을 알고 있습니다.
다만 절대 유용하지 않을 것이라고 100% 확신하는 작업을 하고 싶지 않을 뿐입니다.
 
Maxim Kuznetsov #:

MN에는 미리 계산된 배열을 사용할 수 있으며, 데이터가 거의 없습니다.

Ln2(12개월 * 100년)...11 if`'와 이진 검색에서 비교를 사용하지만 다른 계산은 하지 않습니다.

아, 처음에 잘못 읽었네요.
아니요, 틀렸습니다. 성능 향상은 작동하지 않습니다. 여전히 계산에 갇혀 있을 것입니다. 그리고 배열 요소에 액세스하면 알고리즘 속도가 매우 느려집니다.