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 会是一个很好的解决方案。

Heh heh heh...当 "只见树木不见森林 "时,我感到很困惑。

就在这个片段中--一切似乎都是正确的,但没有一个评论,像这样的 "堆积",没有遗漏,伙计,这是多么难以理解......

 
Roman:

我马上删除这种评论,因为它堵塞了眼睛,我是这样写的

在那里!是的。

在我看来,对于短小而简单的功能来说,是最正常的评论风格。

 

我将投入我的五分钱。

至于格式化的问题。你需要输入几种样式。一个是MQ的那个。我提出这个建议。

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

我将投入我的五分钱。

至于格式化的问题。你需要输入几种样式。一个是MQ的那个。我提出这个建议。

我不喜欢目前风格中的所有大括号。我不明白他们为什么要移动它们。我总是将所有大括号对准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:

所以你必须改变代码,但如果你不能改变呢?

那么就没有办法了。这是一个有争议的情况,一方面,优化器是自由的,可以进行进一步的工作,但另一方面,可能会有重叠 - 决定取决于情况。