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

 

소스 코드에 기계가 생성한 코드를 사용하게 될 줄은 상상도 못했습니다. 특히 성능을 위해 보관하는 곳에서 말이죠.


아래는 생성된 코드입니다.

switch (this.Flag)
{
case 0:
  return(false);
case 1:
  return(Tick.bid >= this.bid.Max);
case 2:
  return(Tick.ask <= this.ask.Min);
case 3:
  return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min));
case 4:
  return(Tick.bid <= this.bid.Min);
case 5:
  return((Tick.bid >= this.bid.Max) || (Tick.bid <= this.bid.Min));
case 6:
  return((Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min));
case 7:
  return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min));
case 8:
  return(Tick.ask >= this.ask.Max);
case 9:
  return((Tick.bid >= this.bid.Max) || (Tick.ask >= this.ask.Max));
case 10:
  return((Tick.ask <= this.ask.Min) || (Tick.ask >= this.ask.Max));
case 11:
  return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min) || (Tick.ask >= this.ask.Max));
case 12:
  return((Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));
case 13:
  return((Tick.bid >= this.bid.Max) || (Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));
case 14:
  return((Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));
case 15:
  return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));
}

생성을 위해 훨씬 더 간결한 스크립트가 작성되었습니다. 가설을 빠르게 테스트하고 인적 오류를 방지하는 데 편리할 수 있습니다.

 
fxsaber #:

소스 코드에 기계가 생성한 코드를 사용하게 될 줄은 상상도 못했습니다. 특히 성능에 있어 기록이 중요한 곳에서 말이죠.


아래는 생성된 코드입니다.

생성을 위해 훨씬 더 간결한 스크립트가 작성되었습니다. 이는 가설을 빠르게 테스트하고 인적 오류를 방지하는 데 유용할 수 있습니다.

동일한 ChatGPT는 구문과 논리 모두에서 많은 실수를 범하므로 모든 것을 다시 확인해야 합니다.

하지만 정말 좋은 도구이며 아이디어를 코드로 표현하는 데 도움이 됩니다.

 
fxsaber #:

아래는 생성된 코드입니다.

생성을 위해 훨씬 더 간결한 스크립트가 작성되었습니다. 이는 가설을 빠르게 테스트하고 인적 오류를 방지하는 데 유용할 수 있습니다.

배경 정보가 충분하지 않습니다: 새 코드가 이전 코드보다 빨라졌는지 아닌지?

그렇지 않다면 이해할 수 있는 기존 코드를 이해할 수 없는 새 코드로 변경한 이유는 무엇인가요?

그렇다면, 채팅보다 훨씬 더 많은 가능성을 가지고 있는데 왜 MQL 컴파일러가 성능 측면에서 최적의 코드를 한 번에 생성하지 못하는가?

 
Aleksey Vyazmikin #:

동일한 ChatGPT가 구문과 논리 모두에서 많은 실수를 저지르기 때문에 모든 것을 다시 확인해야 합니다.

하지만 정말 좋은 피치맨이며 코드에서 아이디어를 표현하는 데 도움이 됩니다.

스크립트 생성하기.

// Генерация switch-кода.
string GetString( const int Num )
{
  static const string Condition[] = {"(Tick.bid >= this.bid.Max)", "(Tick.ask <= this.ask.Min)",
                                     "(Tick.bid <= this.bid.Min)", "(Tick.ask >= this.ask.Max)"};
  string Str = NULL;

  for (int i = 0; i < ArraySize(Condition); i++)
    if ((bool)(Num & (1 << i)))
      Str += ((Str == NULL) ? NULL : " || ") + Condition[i];

  return(Str);
}

void OnStart()
{
  for (int i = 0; i < 16; i++)
    Print("case " + (string)i + ":\n  return(" + GetString(i) + ");");
}
 
A100 #:

배경 정보가 충분하지 않은 경우: 새 코드가 이전 코드보다 빨라졌나요?

새 코드가 더 빠릅니다.

그렇다면 왜 MQL 컴파일러는 채팅보다 훨씬 더 많은 가능성을 가지고 있는데도 성능 측면에서 최적의 코드를 한 번에 생성할 수 없었을까요?

이것은 컴파일러 최적화가 아닌 알고리즘 최적화입니다.

 
fxsaber #:

새 버전이 더 빠릅니다.

이는 컴파일러 최적화가 아닌 알고리즘 최적화입니다.

얼마나 빨라졌나요? 1.5% 또는 1.5배? 마치 더 빠른 것처럼요? 아니면 정확한 측정값을 기반으로 하나요?

코드가 아니라 알고리즘을 제공한 건가요?

 
A100 #:

얼마나 빨라졌나요? 1.5퍼센트 또는 1.5배? 그리고 느낌이나 구체적인 측정값으로?

코드가 아니라 알고리즘을 제공한 건가요?

가상 소스 코드가 사용하는 방식입니다. 각 틱에 대해 네 번 확인해야 합니다.

return((Tick.bid >= this.bid.Max) || (Tick.ask <= this.ask.Min) || (Tick.bid <= this.bid.Min) || (Tick.ask >= this.ask.Max));


하지만 어떤 상황(0~15번 스위치)에서는 0~4번으로 더 적은 수의 확인을 수행할 수 있습니다. TS에 따라 다릅니다.


예를 들어 TS가 시장가 주문으로만 포지션을 개시/청산하고 SL/TP를 사용하지 않는 경우 한 번만 확인할 필요가 없습니다.

그러나 모든 유형의 주문을 동시에 사용하는 경우 네 가지 확인을 모두 수행해야 합니다.


그렇기 때문에 특정 TS를 가져와서 측정 결과를 확인해야 합니다. TS마다 가속도 결과가 다릅니다.


케이스(사례 수)를 더 많은 변종으로 분류할 수 있었습니다. 솔직히 말해서 저는 할 수 없었습니다.

 

MQL5에는 이론적으로 문자열에 대한 메모리 재할당 횟수를 줄일 수 있는 StringReserve 함수가 있는데, 이를 사용하면 한 번에 충분히 큰 버퍼를 할당하고 그 안에서 작업할 수 있습니다.

그러나 실습에서 알 수 있듯이 이 문자열에 값을 나중에 할당하면 버퍼의 크기가 변경됩니다(즉, 분명히 메모리 재할당이 발생함).

결과적으로

string str;
str.Reserve(8192);
str="test";

대신

string str;
str.Reserve(8192);
StringSetLength(str,0);  // или str.SetLen(0); - в документации есть, но у меня в 4073 не поддерживается
str+="test";
 
JRandomTrader #:

를 사용하는 것이 좋습니다.

를 사용하는 것이 좋습니다. 이 메커니즘은 문자열 완성에 매우 효과적입니다. 예를 들어 대용량 HTML 보고서를 생성할 때 유용합니다.

 

심볼에 데이터가 있는지 확인하여 데이터가 없는 경우 [마켓 워치] 창에 남기지 않으려면 어떻게 해야 하나요?

이러한 확인을 반복해서 사용합니다:

ulong first_server_date = (ulong)SeriesInfoInteger(symbol, PERIOD_M1, SERIES_SERVER_FIRSTDATE);

if(first_server_date == NULL) {
  SymbolSelect(symbol, false);
  continue;
}

하지만 그 후에는 전문가 조언자가 차트에 있는 동안에는 [종합시세] 창에서 심볼을 하나씩 또는 한 번에 모두 수동으로 제거할 수 없습니다: