MetaTrader 5 거래 전략 테스터 개발 계획 - 페이지 8

 
Aliaksandr Hryshyn :
왼쪽과 똑같은 디자인을 사용하는 함수(클래스, 구조체...)에 주석을 사용하는 사람이 많은지 궁금합니다.

굵고 자주 사용합니다(사실, '사각형'으로 그리지 않고 '그냥' 이라고 씁니다.

다음은 현재 거래 내역 인터페이스 파일입니다. 그리고 이것은 최대 댓글이 아닙니다.

 // СTradeHistoryI переносимый интерфейс торговой истории 

// История состоит из компонент-наследников интерфейса CHistoryPosComponentI
// 
// Реально для МТ4 имплементацией интерфейса является объект CMT4TradeHistory, для МТ5 - объект CMT5TradeHistory
// CMT4TradeHistory представляет из себя массив объектов CMT4HistoryOrderInfo, наследников интерфейса CHistoryPosComponentI.
// Фактически это массив исторических МТ4-ордеров.
// CMT5TradeHistory представляет из себя массив объектов CMT5HistoryPositionInfoCore, наследников интерфейса CHistoryPosComponentI.
// Объект CMT5HistoryPositionInfoCore не имеет прямого аналога в МТ5-терминах, это два массива ордеров и сделок, а также структура данных,
// имеющуая идентификатор позиции (m_lPosID или POSITION_IDENTIFIER), тикет магик, вид позиции, и так далее, по аналогии с МТ4-ордером,
// фактически, массивы ордеров и сделок - это аналоги ордеров и сделок обычной неттинговой МТ5-позиции, а структура данных - относится
// к хеджевой позиции, и имеет аналог МТ4-ордера. 
//
// Реально при запросе у позиции компоненты CHistoryPosComponentI в МТ4 мы получаем указатель на ордер (класс CMT4HistoryOrderInfo),
// а в МТ5 - на ядро позиции (класс CMT5HistoryPositionInfoCore) 

#include <MyLib\DebugOrRelease\DebugSupport.mqh>
#include <MyLib\Common\MyObject.mqh>
#include <MyLib\Common\CurSymEnum.mq5>
#include <MyLib\Common\TrendEnums.mqh>
#include <MyLib\Trade\TradePosComponentI.mqh>
#include <MyLib\Trade\SortTradePosComponentT.mqh>

class CTSContainerI;

class CROTradeHistoryI: public CMyObject
{
public :

   void CROTradeHistoryI() {    SetMyObjectType(MOT_TRADE_READONLY_HISTORY_I); };
   virtual void ~CROTradeHistoryI() {};
   
   virtual uint GetTotalComponents() const = 0 ;   // Получение общего числа компонент
   virtual CHistoryPosComponentI* GetComponent( uint uiComponentIdx) const = 0 ;
   virtual CHistoryPosComponentI* GetOldestOpenComponent() const = 0 ; // Может вернуть NULL !!!
   virtual CHistoryPosComponentI* GetNewestCloseComponent() const = 0 ; // Может вернуть NULL !!!
   
   // Функция ищет внутри истории компоненту с указанным тикетом. 
   // В случае, если ее нет - возвращается false.
   // Если компонента найдена - возвращается true, и uiComponentIdx устанавливается на индекс компоненты внутри позиции.
   virtual bool FindComponentByTicket( long lTicket, uint &uiComponentIdx) const = 0 ;
   
   // Функция анализирует историю и возвращает символ, по которому совершены сделки.
   // Если все выбранные сделки имеют один и тот же символ - возвращается этот символ.
   // Если сделки имеют разные символы или сделок нет - возвращается CS_CURRENT.
   // Если хотя бы один символ CS_UNKNOWN  - возвращается CS_UNKNOWN
   virtual ECurrencySymbol GetSymbols() const = 0 ;
};


class CTradeHistoryI: public CROTradeHistoryI
{
public :
   void CTradeHistoryI() {    SetMyObjectType(MOT_TRADE_HISTORY_I); };
   virtual void ~CTradeHistoryI() {};
   
   // Выбор существующей истории. 
   // Указывается магик и символ, по которому выбираются исторические ордера, а также промежуток времени, в котором необходимо искать их.
   // Если ulMagic = 0 - выбираются все позиции по всем магикам.
   // Если ECurrencySymbol = CS_UNKNOWN - выбираются все позиции по всем символам
   // Если ECurrencySymbol = CS_CURRENT - запрашивается функция Symbol(), и выбираются все позиции по этому символу
   // ptcTSContainer - указатель на контейнер таймсерий, по которому можно определять просад для каждой позиции. Может быть NULL, в этом случае просад устанавливается нулевым.
   // Возвращает число компонент позиции внутри истории (может быть нулевым если ничего не найдено) или WRONG_VALUE в случае ошибок
   // NOTE !!! 
   // При выборе - отложенные ордера не учитываются.
   virtual int Select( ulong ulMagic = 0 ,ECurrencySymbol csSymbol = CS_CURRENT, datetime dtFrom = MIN_DATETIME, datetime dtTill = NEVER_EXPIRES,CTSContainerI* ptcTSContainer = NULL ) = 0 ;

   
   // Расширенный интерфейс
   virtual void Sort(ESortTPCMode stmMode = STM_BY_OPEN_TIME_A) = 0 ;
};


일반적으로 클래스가 더 구체적일수록 더 많은 설명이 있어야 합니다.

글쎄, Peter Konov와 같은 메가 메모리가 있다는 점을 제외하고는 여기에서 코멘트 없이 할 수 있습니다.


 
Nikolai Semko :

예, 누가 무엇을 좋아합니까? 개인적으로 코드 자체가 보이지 않는 코드 형식에 눈이 부시다.

아마도 Visual Studio Code 를 마스터하는 것이 좋은 해결책이 될 것입니다.

헤헤헤... 그리고 "나무 때문에 숲을 볼 수 없다"는 말에 눈시울이 붉어진다.

위의 단편에서 - 모든 것이 올바른 것처럼 보이지만 한 마디도 언급하지 않고이 "방벽"과 같이 간격없이 젠장, 그것을 알아내는 것이 얼마나 어려운지 ...

 
Roman :

이런 댓글은 눈이 막혀서 바로 삭제하고 이렇게 씁니다

에! 네.

짧고 간단한 기능의 경우 - 내 의견으로는 가장 일반적인 스타일의 주석입니다.

 

나도 5센트 넣어줄게.

포맷에 관해서. 여러 스타일을 입력해야 합니다. 하나 - MQ에서 하나. 나는 이것을 제안한다:

 if (.....)
{
   ..............
}
else
if (.........)
{
   ......
   for (.....)
   {
      .....
   }
)
else    ......
 
Сергей Таболин :

나도 5센트 넣어줄게.

포맷에 관해서. 여러 스타일을 입력해야 합니다. 하나는 MQ에서 하나입니다. 나는 이것을 제안한다:

현재 스타일에서 내가 가장 싫어하는 것은 중괄호가 사라진 것입니다. 그들이 왜 그들을 옮겼는지, 나는 이해하지 못합니다. 귀하의 예에서와 같이 항상 모든 대괄호를 Tab으로 정렬합니다.

 
Georgiy Merts :

굵고 자주 사용합니다(사실, '사각형'으로 그리지 않고 '그냥' 이라고 씁니다.

다음은 현재 거래 내역 인터페이스 파일입니다. 그리고 이것은 최대 댓글이 아닙니다.


일반적으로 클래스가 더 구체적일수록 더 많은 설명이 있어야 합니다.

글쎄, Peter Konov와 같은 메가 메모리가 있다는 점을 제외하고는 여기에서 코멘트 없이 할 수 있습니다.


나는 비슷한 것을 가지고 있지만 주석 만 더 작습니다. :).

 //Использование модели
class Catboost
  {
private :
   static int         lng_id; //
public :
   //Правило сплита: предиктор больше указанного значения(true/false)
   struct sSplit_rule
     {
       uint               predictor_id;   //Индекс предиктора
       double             border;         //С чем сравнивается он
     };
   //Набор правил, при соответствии которым получим результат листа leaf
   struct sLeaf
     {
       double             leaf;           //Значение листа
      sSplit_rule       split_rules[]; //Набор правил
     };
   uint               TreeDepth[];       //Глубины деревьев, глубина означает колчиство правил. В каждом правиле используется один бинарный признак.
   uint               TreeSplits[];     //Какие бинарные признаки использует каждое дерево
   uint               BorderCounts[];   //На сколько бинарных признаков будет разбит каждый предиктор
   float              Borders[];         //Пороговые значения для всех предикторов, они определяют значения бинарных признаков(0/1). Если предиктор выше значения в массиве, будет 1, иначе 0.
   double             LeafValues[];     //Результаты деревьев для каждого сочетания используемых бинарных признаков
   uint               features_pos[];   //Откуда взялась бинарная фича.Указывается индекс.

                    ~Catboost( void );
                     Catboost();
   //Создание экземпляра класса (инициализация конкретной модели)
                     Catboost( uint &TreeDepth_[], uint &TreeSplits_[], uint &BorderCounts_[], float &Borders_[], double &LeafValues_[]);
   //Приеменение модели
   //features     -предикторы
   double             ApplyCatboostModel( const double &features[]);
   //Приеменение модели.Модель передаётся через массивы
   static double      ApplyCatboostModel( const double &features[], uint &TreeDepth_[], uint &TreeSplits_[], uint &BorderCounts_[], float &Borders_[], double &LeafValues_[]);
   //Применение модели с сохранением данных о влиянии предикторов на результат
   double             ApplyCatboostModel_data( const double &features[], datetime time);

   long               data_counter;           //Счётчик выполнения функции ApplyCatboostModel_data
   CSV               *csv_tree_rules;         //Сюда сохраняются все сработанные правила, результаты деревьев
   CSV               *csv_model_rules;        //Сюда сохраняются правила, которые сработали во всей модели.перекрывающиеся правила будут удаляться
   //Перобразование модели CatBoost с исходников C++ в MQL
   static bool        CatBoost_model_to_MQL( string input_file_cpp, string output_file_mql);
   //Чтение модели с файла исходника C++
   bool               Model_read_from_file( string input_file_cpp);
   //Получение полного списка правил для каждого листа leaf_rules_out
   void               Get_leaf_rules(sLeaf &leaf_rules_out[]);
  };
int Catboost::lng_id=cLng::Set_users_errors_messages( "Catboost" ,Catboost_lngs,Catboost_strings);

나는 내가 해야 하는 것처럼 목록 전체에 "번지는" 댓글을 좋아하지 않습니다.

이것을 비활성화할 수 있으면 좋을 것입니다:

 //+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

댓글을 어떻게 달았는지 정확히 알려주실 수 있나요? 수동으로 수정하시나요? 비밀 조합이 있습니까?

 

그러한 상황:

나는 전략 테스터 에서 최적화하고, 완료되면 OnTesterDeinit()가 실행되어 결과를 분석하거나 데이터를 수집합니다. 그래서 이 순간에 전략 테스터는 모든 것이 끝난 것 같은 상태로 들어가지만, 이 때 백그라운드에서 데이터의 최종 처리가 오래 걸릴 수 있습니다. 기기 차트가 있는 창을 닫으면 Expert Advisor의 작업이 강제 종료됩니다.

OnTesterDeinit()가 파일에 쓰는 또 다른 상황을 설명하자면 현재 최적화가 끝났다고 생각하고 최소 매개변수 범위로 다음 최적화를 시작하여 빠르게 계산됩니다. 결과적으로 이전 출시가 완료되지 않았고 새 출시가 같은 단계에 있습니다. 이 예에서는 파일 쓰기 액세스 오류가 발생하거나 파일의 해시만 발생하지만 시각적으로 추적할 수는 없습니다. 로드 관리자 또는 파일.... 테스터에서 이 작업이 아직 완료되지 않았음을 확인할 수 있기를 바랍니다.

 
Aliaksandr Hryshyn :

그러한 상황:

나는 전략 테스터 에서 최적화하고, 완료되면 OnTesterDeinit()가 실행되어 결과를 분석하거나 데이터를 수집합니다. 그래서 이 순간에 전략 테스터는 모든 것이 끝난 것 같은 상태로 들어가지만, 이 때 백그라운드에서 데이터의 최종 처리가 오래 걸릴 수 있습니다. 기기 차트가 있는 창을 닫으면 Expert Advisor의 작업이 강제 종료됩니다.

OnTesterDeinit()가 파일에 쓰는 또 다른 상황을 설명하자면 현재 최적화가 끝났다고 생각하고 최소 매개변수 범위로 다음 최적화를 시작하여 빠르게 계산됩니다. 결과적으로 이전 출시가 완료되지 않았고 새 출시가 같은 단계에 있습니다. 이 예에서는 파일 쓰기 액세스 오류가 발생하거나 파일의 해시만 발생하지만 시각적으로 추적할 수는 없습니다. 로드 관리자 또는 파일.... 테스터에서 이 작업이 아직 완료되지 않았음을 확인할 수 있기를 바랍니다.

최적화할 때 새 차트 창이 열립니다. 차트 ID로 작업의 끝을 어떻게든 알 수 있을까요? 차트를 닫는 것이 가능한 것 같습니다. 그런 다음 OnTesterDeinit()에서 계산이 완료된 후 창을 닫을 수 있으며 결국 우리는 당시 열려 있던 차트의 존재를 추적하기만 하면 됩니다. 최적화 시작, 어떻게 사라졌는지 - 테스터는 새로운 최적화를 위한 준비가 되었습니다.

 
Aleksey Vyazmikin :

최적화할 때 새 차트 창이 열립니다. 차트 ID로 작업의 끝을 어떻게든 알 수 있을까요? 차트를 닫을 수 있을 것 같긴 한데, OnTesterDeinit()에서 계산이 완료된 후 창을 닫을 수 있고, 결국 해당 시점에 열려 있던 차트의 존재만 추적하면 됩니다. 최적화 시작, 사라진 방법 - 테스터는 새로운 최적화를 위한 준비가 되었습니다.

그래서 이것은 변경되어야 하는 코드이며, 그러한 가능성이 없다면?

 
Aliaksandr Hryshyn :

그래서 이것은 변경되어야 하는 코드이며, 그러한 가능성이 없다면?

그럼 안돼. 여기에는 논란의 여지가 있는 상황이 있습니다. 한편으로는 옵티마이저가 무료이며 추가 작업이 준비되어 있지만 다른 한편으로는 오버레이가 있을 수 있습니다. 결정은 상황에 따라 다릅니다.