Development plans for the MetaTrader 5 Strategy Tester - page 8

 
Aliaksandr Hryshyn:
I wonder, how many people use comments to functions (classes, structures...) using exactly this design on the left?

I use it very often and densely (True, I don't format it as "squares", I write it "just so".

Here's my current bidding history interface file. And that's not the maximum number of comments.

// С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;
};


In general, the more specific class - the more comments it should have.

Well, unless you have mega-memory, like Peter Konov, you can do without comments.


 
Nikolai Semko:

Yes, who likes what they like. Personally, I can't see the code so well formatted that I can't see the code itself.

Perhaps masteringVisual Studio Code would be a good solution.

Heh heh heh... I get confused when "you can't see the forest for the trees".

Just in this fragment - everything seems to be correct, but without a single comment, and like this "pile-up", without omissions, man, how hard it is to understand...

 
Roman:

I delete this kind of comment at once, as it clogs the eyes and I write like this

There! Yes.

For short and simple functions, the most normal commentary style, in my opinion.

 

I'll put in my five cents.

As for the formatting. You need to enter several styles. One is the one from MQ. I propose this one:

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

I'll put in my five cents.

As for the formatting. You need to enter several styles. One is the one from MQ. I propose this one:

I don't like most of all the curly brackets in the current style. I don't understand why they moved them. I always align all braces to Tab, as in your example.

 
Georgiy Merts:

I use it very often and densely (True, I don't format it as "squares", I write it "just so".

Here's my current bidding history interface file. And that's not the maximum number of comments.


In general, the more specific a class is, the more comments it should have.

Well, unless you have a mega-memory like Peter Konov - you can do without comments there.


Mine is similar, only less comments :).

//Использование модели
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);

"Smearing" comments all over the listing, as is supposed to me, is not to my liking.

It would be nice if there was an option to turn this off:

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

Can you tell me exactly how you put comments in them? Do you manually edit it? Is there a secret combination?

 

Here's the situation:

I optimize in a strategy tester, on completion, OnTesterDeinit() is executed to analyze results, or just to collect data. At this moment, the strategy tester switches to the state as if everything is finished, but at this time, the final data processing can still take place in the background for a long time. When the window with the symbol chart is closed, the Expert Advisor will be closed forcibly.

Let's also describe the situation when OnTesterDeinit() is writing into a file thinking the current optimization is over, we start the next one with minimal ranges of parameters that are quickly calculated. As a result we have previous run is not completed and new one is on the same stage, in our example it leads to error of write access to files, or just mishmash in file, and visually it is not traceable, only through load manager or file.... I would like to be able to see in the tester that this operation is not yet complete.

 
Aliaksandr Hryshyn:

Here's the situation:

I optimize in a strategy tester, on completion, OnTesterDeinit() is executed to analyze results, or just to collect data. At this moment, the strategy tester switches to the state as if everything is finished, but at this time, the final data processing can still take place in the background for a long time. When the window with the symbol chart is closed, the Expert Advisor will be closed forcibly.

Let's also describe the situation when OnTesterDeinit() is writing into a file thinking the current optimization is over, we start the next one with minimal ranges of parameters that are quickly calculated. As a result we have previous run is not completed and new one is on the same stage, in our example it leads to error of write access to files, or just mishmash in file, and visually it is not traceable, only through load manager or file.... I would like to be able to see in the tester that this operation is not yet complete.

When optimizing a new chart window opens - can we use chart id to figure out the end of the operation? It seems that there is an option of closing the chart, then after the end of calculations in OnTesterDeinit() the window can be closed and eventually we just need to monitor the presence of the chart open at the start of optimization, as soon as it has disappeared - the tester is ready for a new optimization.

 
Aleksey Vyazmikin:

When optimizing opens a new chart window - is there any way to find out the end of work by chart id? It seems that there is an option of closing the chart, then after the end of calculations in OnTesterDeinit() the window can be closed, and in the end we just need to monitor the presence of the chart open at the start of optimization, when it has disappeared - the tester is ready for a new optimization.

So, this code must be changed, but what if there is no such a possibility?

 
Aliaksandr Hryshyn:

So you have to change the code, but what if you can't?

Then there is no way. This is a controversial situation, on the one hand the optimizer is free and ready for further work, but on the other hand there can be an overlap - the decision depends on the situation.

Reason: