Планы развития тестера торговых стратегий 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;
};


Вобще, чем специфичнее класс - тем в нем комментариев должно быть больше.

Ну, разве что у тебя мегапамять, как у Петера Конова - тут можно и без комментариев обходиться.


 
Nikolai Semko:

Да, кому что нравиться. Лично у меня в глазах рябит  от такого форматирования кода, что самого кода не вижу

Возможно, освоение Visual  Studio Code будет будет неплохим решением.

Хе-хе-хе... А у меня рябит в глазах, когда "за деревьями леса не видно".

Как раз в приведенном фрагменте - вроде все правильно, но без единого комментария, и вот так "частоколом", без пропусков, блин, как же тяжело разбираться...

 
Roman:

Удаляю сразу такой вид комментария, так как засоряет глаза и пишу так

Во ! Да.

Для коротких и простых функций - самый нормальный стиль комментариев, по-моему.

 

Вставлю и я 5 копеек.

Что касается форматирования. Нужно ввести несколько стилей. Один - тот что от МQ. Я предлагаю такой:

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

Вставлю и я 5 копеек.

Что касается форматирования. Нужно ввести несколько стилей. Один - тот что от МQ. Я предлагаю такой:

В текущем стиле мне больше всего не нравится съехавшие фигурные скобки. Зачем сдвинули их, я не понимаю. Всегда все скобки выравниваю по Tab, как на вашем примере.

 
Georgiy Merts:

Я очень часто и густо использую (Правда, не оформляю в виде "квадратов", пишу "просто так".

Вот мой текущий файл интерфейса истории торгов. И это - не максимум комментариев.


Вобще, чем специфичнее класс - тем в нем комментариев должно быть больше.

Ну, разве что у тебя мегапамять, как у Петера Конова - тут можно и без комментариев обходиться.


У меня схоже, только комментарий меньше :).

//Использование модели
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() для анализа результатов, или просто для сбора данных. Так в этот момент тестер стратегий переходит в состояние как будто всё завершилось, но в это время фоново может ещё долго происходить окончательная обработка данных. При закрытии окна с графиком инструмента работа советника принудительно завершается.

Опишем ещё такую ситуацию, когда в OnTesterDeinit() происходит запись в файл, думая, что текущая оптимизация завершилась, мы запускаем следующую с минимальными диапазонами параметров, что быстро просчитывается. В итоге у нас прежний запуск не завершился и новый находится на такой же стадии, в нашем примере это приводит к ошибке доступа на запись к файлам, или просто мешанина в файле, а визуально это не проследить, только через диспетчер по нагрузке или по файлу.... Хотелось бы иметь возможность видеть в тестере, что данная операция ещё не завершена.

 
Aliaksandr Hryshyn:

Такая ситуация:

Оптимизирую в тестере стратегий, при завершении, выполняется OnTesterDeinit() для анализа результатов, или просто для сбора данных. Так в этот момент тестер стратегий переходит в состояние как будто всё завершилось, но в это время фоново может ещё долго происходить окончательная обработка данных. При закрытии окна с графиком инструмента работа советника принудительно завершается.

Опишем ещё такую ситуацию, когда в OnTesterDeinit() происходит запись в файл, думая, что текущая оптимизация завершилась, мы запускаем следующую с минимальными диапазонами параметров, что быстро просчитывается. В итоге у нас прежний запуск не завершился и новый находится на такой же стадии, в нашем примере это приводит к ошибке доступа на запись к файлам, или просто мешанина в файле, а визуально это не проследить, только через диспетчер по нагрузке или по файлу.... Хотелось бы иметь возможность видеть в тестере, что данная операция ещё не завершена.

При оптимизации открывается новое окно чарта - может можно по id чарта как то выяснить окончание работы? Кажется, что есть возможность закрытия чарта, тогда после окончания расчетов в OnTesterDeinit() можно закрыть окно, а в итоге нам надо просто отслеживать наличие чарта, открытого в момент начала оптимизации, как оно исчезло - тестер готов к новой оптимизации.

 
Aleksey Vyazmikin:

При оптимизации открывается новое окно чарта - может можно по id чарта как то выяснить окончание работы? Кажется, что есть возможность закрытия чарта, тогда после окончания расчетов в OnTesterDeinit() можно закрыть окно, а в итоге нам надо просто отслеживать наличие чарта, открытого в момент начала оптимизации, как оно исчезло - тестер готов к новой оптимизации.

Так это уже код надо менять, а если нету такой возможности?

 
Aliaksandr Hryshyn:

Так это уже код надо менять, а если нету такой возможности?

Тогда никак. Тут спорная ситуация, с одной стороны оптимизатор освободился и готов к дальнейшей работе, но с другой стороны могут быть и накладки, - решение зависит от ситуации.

Причина обращения: