일반 클래스 라이브러리 - 버그, 설명, 질문, 사용 기능 및 제안 사항 - 페이지 14

 
세르게이 주블리크 :

저 같은 경우 객체가 특정 인터페이스나 메소드를 구현하지 않으면 조용히 은폐하는 것보다 명시적으로 예외를 던지는 것이 더 낫고, 문제의 원인을 얼마나 찾아봐야 할지 막막합니다.

  • MQL5에는 인터페이스가 없습니다.
  • MQL5에는 예외가 없습니다.

결과적으로 예, 고귀한 석궁과 코드 문제에 대한 명백한 침묵이 나타납니다.

 
바실리 소콜로프 :

같은 이유로 비교가 잘못되었습니다. 사용자 정의 CHashMap을 비교하고 시스템 기능을 사용하여 거래 환경을 얻으려면 어떻게 해야 합니까?

철인 주장을 받아들이지 않기 때문에 최적이 아닌 코드를 계속 작성하십시오.

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

일반 클래스 라이브러리 - 버그, 설명, 질문, 사용법 및 제안

fxsaber , 2017.12.08 22:46

보다 현실적인 테스트 사례(2000개의 거래 및 1,000,000개의 단일 기록 액세스)의 경우 결과는 다음과 같습니다.

 2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitFull))] = 122969
2017.12 . 05 00 : 00 : 00    Time [SetHashMap()] = 816
2017.12 . 05 00 : 00 : 00    4829800340.792288
2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitHashClear))] = 23852
2017.12 . 05 00 : 00 : 00    Time [ HistorySelect ( 0 , INT_MAX )] = 1
2017.12 . 05 00 : 00 : 00    4829800340.792288
2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitClear))] = 114427

패스당 거의 100ms 절약! 예를 들어 10,000개의 전체 패스에 대해 최적화를 수행하면 해시 버전이 15분 더 빨리 종료됩니다.

바실리 소콜로프 :

결과적으로 예, 고귀한 석궁과 코드 문제에 대한 명백한 침묵이 나타납니다.

둘 다 현재 형태의 HashMap이 구조체와 공용체에 대해 작동하지 않는다는 단일 그램을 이해하지 못하는 일종의 넌센스를 작성했습니다.
 
fxsaber :

철인 주장을 받아들이지 않기 때문에 최적이 아닌 코드를 계속 작성하십시오.

둘 다 현재 형태의 HashMap이 구조체와 공용체에 대해 작동하지 않는다는 단일 그램을 이해하지 못하는 일종의 넌센스를 작성했습니다.

친애하는, 담배를 피우고 대담한 사람의 게시물 을주의 깊게 읽을 수 없다면 이것이 당신의 문제이며 다른 모든 사람이 아니라 환자 만 치료해야합니다.
우리는 반복합니다: 아무도 구조체와 합집합에 대해 연설을 하지 않았고 아무도 이 문제에 대해 당신의 아이디어에 이의를 제기하지 않았습니다 ....


특히 코드의 이러한 조건에 관한 것이었습니다.
표준 라이브러리에서:

 //+------------------------------------------------------------------+
//| Returns a hashcode for custom object.                            |
//+------------------------------------------------------------------+
template < typename T>
int GetHashCode(T value)
  {
//--- try to convert to equality comparable object  
   IEqualityComparable<T>*equtable= dynamic_cast <IEqualityComparable<T>*>(value);
   if (equtable)
     {
       //--- calculate hash by specied method   
       return equtable.HashCode();
     }
   else
     {
       //--- calculate hash from name of object
       return GetHashCode( typename (value));
     }
  }
//+------------------------------------------------------------------+



그리고 추가:

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

일반 클래스 라이브러리 - 버그, 설명, 질문, 사용법 및 제안

fxsaber , 2017.12.08 21:17

다른 오버로드 추가됨

 template < typename T>
int GetHashCode(T &value)
  {
     return GetHashCode( typename (value));
  }


무엇을 전달하려고 했습니까?
해시는 컨테이너의 요소 검색 속도를 높이는 데 사용됩니다. O(1) 속도 - 컨테이너에 추가된 요소 수에 의존하지 않습니다.
상황 - 사용자는 자신의 클래스를 키로 사용합니다.
1) 인터페이스의 다중 상속이 없기 때문에( MQL5에는 인터페이스가 없음 ) 사용자는 IEqualityComparable에서 상속할 수 없습니다 .
2) 사용자는 또한 GetHashCode 템플릿 기능에 대한 명시적 사양을 지정하는 것을 잊었습니다.

결과 - 사용자는 어떤 식으로든 그가 무언가를 생략하고 예외를 던지지 않고 코드가 성공적으로 실행되었음을 알리지 않습니다( MQL5에는 예외가 없습니다 ).
평균 해시 계산 상수가 있는 O(1)에서 비교를 위해 충분히 큰 상수가 있는 O(n)으로 속도가 떨어집니다.
컨테이너에 많은 수의 요소가 있고 구현에서 병목 현상을 찾는 데 많은 시간을 할애하는
경우에만 사용자는 문제의 원인, 즉 클래스에 대한 명시적 GetHashCode 사양의 부족을 찾을 수 있습니다.
불쾌하지 않습니다. 감사합니다.

 
그럼에도 불구하고 거래를 위한 이 모든 부정할 수 없는 멋진 이유는 무엇입니까?
글쎄, 내 인생에서 나는 역사상 수천 건의 거래를 선택하고 거래를 일으킨 주문을 찾는 등의 일을 한 적이 없습니다.
 
세르게이 주블리크 :

친애하는, 담배를 피우고 대담한 사람의 게시물 을주의 깊게 읽을 수 없다면 이것이 당신의 문제이며 다른 모든 사람이 아니라 환자 만 치료해야합니다.

벙어리 장갑은 분명히 티토탈러가 닫을 수 없습니다.

 #include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280
#include <crc64.mqh>       // https://www.mql5.com/en/blogs/post/683577

template < typename T>
int GetHashCode( T &value )
{
   ulong crc = 0 ;

   return (( int )crc64(crc, _R(value).Bytes, sizeof (T)));
}

template < typename T>
int GetHashCode( T &value[] )
{
   ulong crc = 0 ;

   return (( int )crc64(crc, _R(value).Bytes, ArraySize (value) * sizeof (T)));
}
 
이 주제와 관련이 없는 댓글은 " 알고리즘, 결정 방법, 성능 비교 "로 이동되었습니다.
 

원래 브랜치에서 예제 모음을 만들 계획은 아니었지만, 알고리즘을 실제로 사용하지 않는 사람들이 알고리즘이 왜 편리하고 무엇보다 간단하다는 것을 이해할 수 있도록 몇 가지 예제를 추가해야 할 필요성을 여전히 느끼고 있습니다.

 

예 1: 런타임 오류 를 문자열 설명과 연결

종종 숫자 상수를 문자열 리터럴로 변환해야 합니다. 예를 들어 오류의 본질을 나타내는 명확한 비문으로 오류 코드를 복제하는 것이 좋습니다. 이것은 그다지 어려운 작업이 아니며 일반적으로 다음과 같은 특수 기능이나 스위치 케이스 또는 일련의 if를 통해 해결됩니다.

 string ErrorDescription( int error_code)
   if (error_code == 40001 )
       return ( "Неожиданная внутренняя ошибка" );
   //...
}

그러한 결정에는 생명권이 있습니다. 그러나 우리는 CHashMap 기반의 솔루션을 설명하고 그것이 제공하는 이점을 보여줄 것입니다.

이 알고리즘은 다음과 같습니다.

  • <오류 코드 - 오류 설명> 형식의 연관 배열을 만듭니다.
  • 가능한 오류 코드와 해당 설명을 이 사전에 추가합니다.
  • 중개자 없이 직접 사전을 찾아 코드로 오류에 대한 설명을 얻습니다.
이 코드는 다음과 같습니다.

 //+------------------------------------------------------------------+
//|                                                     OrdersID.mq5 |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link        "http://www.mql5.com"
#property version    "1.00"
#include <Generic\HashMap.mqh>
input ulong FindTicketOrder = 82479995 ;

CHashMap< int , string > ErrorDescription;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void AddDescriptionInfo( void )
{
   // Добавим коды системных ошибок
   ErrorDescription.Add( 0 ,     "Операция выполнена успешно" );
   ErrorDescription.Add( 4001 , "Неожиданная внутренняя ошибка" );
   ErrorDescription.Add( 4002 , "Ошибочный параметр при внутреннем вызове функции клиентского терминала" );
   ErrorDescription.Add( 4003 , "Ошибочный параметр при вызове системной функции" );
   ErrorDescription.Add( 4004 , "Недостаточно памяти для выполнения системной функции" );
   // Можно добавлять константные значения вместо чисел
   ErrorDescription.Add( ERR_STRUCT_WITHOBJECTS_ORCLASS , "Структура содержит объекты строк и/или динамических массивов и/или структуры с такими объектами и/или классы" );
   ErrorDescription.Add( ERR_INVALID_ARRAY , "Массив неподходящего типа, неподходящего размера или испорченный объект динамического массива" );   
   ErrorDescription.Add( ERR_ARRAY_RESIZE_ERROR , "Недостаточно памяти для перераспределения массива либо попытка изменения размера статического массива" );
   //...
}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart ()
{
   AddDescriptionInfo();
   string last_error = "" ;
   ErrorDescription.TryGetValue( GetLastError (), last_error);
   printf ( "Последняя ошибка: " + last_error);
}
//+------------------------------------------------------------------+

오류 코드를 입력한 후 다른 기능을 사용하지 않고 한 줄로 액세스합니다. 또한 어떤 경우에는 이 코드가 수십 개의 if보다 훨씬 빠르게 작동한다는 것을 상기시켜 드리겠습니다. 원하는 오류에 대한 주소 지정은 O(1)의 평균 속도로 직접 발생합니다.

 
바실리 소콜로프 :

오류 코드를 입력한 후 다른 기능을 사용하지 않고 한 줄로 액세스합니다.

어쨌든 ErrorToString을 작성해야 합니다. 따라서 주장은 플러스로서 약합니다.

또한 어떤 경우에는 이 코드가 수십 개의 if보다 훨씬 빠르게 작동한다는 것을 상기시켜 드리겠습니다. 원하는 오류에 대한 주소 지정은 O(1)의 평균 속도로 직접 발생합니다.

그러나 이것은 확실한 장점입니다.

 

사전을 통해 제안된 솔루션에는 몇 가지 장점이 있으며, 그 중 주요 장점은 언뜻 보기에는 완전히 명확하지 않습니다. 다음과 같은 코드를 작성할 때:

 string ErrorDescription( int error_code)
   if (error_code == 40001 )
       return ( "Неожиданная внутренняя ошибка" );
   //...
}

그런 다음 오류 코드를 EA 코드 자체에 단단히 꿰매었습니다. 사전을 채울 때 동적으로 수행합니다. 프로그램 실행 시 . 동적 접근 방식은 우리에게 큰 유연성을 제공합니다. 예를 들어 오류 코드는 ErrorsCode.txt와 같은 특수 파일에 포함될 수 있습니다.

 4001 ;Операция выполнена успешно
4002 ;Неожиданная внутренняя ошибка
4003 ;Ошибочный параметр при вызове системной функции
...

실행 시 프로그램은 이 파일을 읽고 사전에 필요한 코드를 채운 다음 원하는 버전의 문자열을 사용자에게 반환할 수 있습니다. 이러한 파일이 여러 개 있을 수 있습니다. 각 언어에 대해 하나의 파일입니다. 이러한 방식으로 사용자의 언어에 따라 오류 코드가 사용자의 언어로 표시되는 지역화를 수행할 수 있습니다. 또한 사용자 자신이 이러한 오류 코드를 자신의 모국어로 한 번 번역할 수 있으며 프로그램 자체는 원하는 메시지를 자신의 언어로 표시하도록 "학습"합니다. 이것은 메뉴 번역이 텍스트 파일에 포함되어 있고 설정에 따라 프로그램이 그것을 로드할 때 대부분의 프로그램의 현지화가 수행되는 방식입니다. 저것들. 프로그램을 재컴파일하거나 알고리즘을 변경하지 않고도 결과 표시에 상당한 영향을 미칠 수 있습니다.

사유: