Новая версия платформы MetaTrader 5 build 5260: улучшения в Algo Forge, расширение OpenBLAS и новые правила наследования в MQL5 - страница 10

 
 HistorySelect(0, TimeCurrent());
        int startFor = HistoryDealsTotal() - 1;
        int endFor = 0;
        for (int Index = startFor ; Index >= endFor; Index--) {
         
   
          ulong posTicket = HistoryDealGetTicket(Index);
         //ulong posTicket = PositionGetTicket(Index);
          ulong posMagic = HistoryDealGetInteger(posTicket, DEAL_MAGIC);
          //string symb = PositionGetString(POSITION_SYMBOL);
          string symb = HistoryDealGetString(posTicket, DEAL_SYMBOL);
      
          if(posTicket > 0) {
      
             if (symb == secF) {
                string orderComment = HistoryDealGetString(posTicket, DEAL_COMMENT);
                //Print("orderComment:" +orderComment+ " magic:"+magic+" ===" + (orderComment == magic));
                //if(magic != "" && isMagicContain(orderComment, magic) == false) continue;
                if(orderComment == "") {
                 // Print("orderCommen1231234231543252436457653686t");
                } else {
                  if(orderComment == magic)  {
                     //Print("999999999999999999999999999999999999999999999999");
                    // if(magic.Find("789000") >= 0)  {
                         double lot = HistoryDealGetDouble(posTicket, DEAL_VOLUME);
                         double posProfit = HistoryDealGetDouble(posTicket, DEAL_PROFIT);
                        //profitToday += posProfit;
                        //levelsDealsNum++;
                        //levelsDealsContract += lot;
                   // }
                  }
                }
                //if(orderComment != "" && magic != "" && (orderComment != magic)) continue;
                //Print("orderComment:" +orderComment+ " magic:"+magic+" ===" + (orderComment == magic));
                //ulong posMagic = HistoryDealGetInteger(posTicket, DEAL_TYPE);
                
                //ENUM_DEAL_ENTRY type = (ENUM_DEAL_ENTRY) HistoryDealGetInteger(posTicket, DEAL_ENTRY);
                //if (type != DEAL_ENTRY_OUT) continue;
                
                if(orderComment != "") continue;
                //Print("orderComment:" +orderComment+ " magic:"+magic+" ===" + (orderComment == magic));
                //int posType = PositionGetInteger(POSITION_TYPE);
                //double posOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                //if(orderComment.Find("_", 0) >= 0)  {
                if(true)  {
                     double lot = HistoryDealGetDouble(posTicket, DEAL_VOLUME);
                     double posProfit = (double) HistoryDealGetDouble(posTicket, DEAL_PROFIT);
                     profitToday += posProfit;
                     levelsDealsNum++;
                     levelsDealsContract += lot;
                    //Print("posProfit:" +posProfit + " levelsDealsNum:"+levelsDealsNum+" lot:" + lot);
                }
             }
          }          
          
        }
        
        Print("             +++++++++++++++++++++ secF:" +secF); 
        Print("             +++++++++++++++++++++ profitToday:" +profitToday); 

        Print("             +++++++++++++++++++++ levelsDealsNum:" +levelsDealsNum); 

Вот исходный код поиска профита по нужным комментам.
специально оставил закомментированные строки что бы было видно что я пробовал разные варианты😁

 
Artyom Trishkin #:
В справке всë есть. 
Справкой пользовался. 
Там ХисториГет выдает ордера с комментариями, а не пустыми строчками вместо комментов.
В этом лишь разница!



 
Sergei Samokhin #:
Справкой пользовался. 
Там ХисториГет выдает ордера с комментариями, а не пустыми строчками вместо комментов.
В этом лишь разница!

Комментарии могут быть у тех сделок, у которых в торговом запросе(ордере) записаны комментарии.

Судя по всему, вы открывали позиции с комментариями, а закрывали без оных.

Профит только у закрывающих сделок, а вы им коммент не прописали. 

Вот здесь удобная библиотека, для работы со сделками. 

 
Aleksandr Slavskii #:

Комментарии могут быть у тех сделок, у которых в торговом запросе(ордере) записаны комментарии.

Судя по всему, вы открывали позиции с комментариями, а закрывали без оных.

Профит только у закрывающих сделок, а вы им коммент не прописали. 

Вот здесь удобная библиотека, для работы со сделками. 

а куда их вписывать при закрытии?

bool isClose = trade.PositionClose(posTicket, dSpread);
 
Sergei Samokhin #:
а куда их вписывать при закрытии?

bool isClose = trade.PositionClose(posTicket, dSpread);

Увы, там не прописать. Но можно изменить немного код в Trade.mqh. Затем сохранить файл под другим названием, чтоб при обновлении не перезаписался дефолтным.

Типа так. 

//+------------------------------------------------------------------+
bool CTrade::PositionClose(const ulong ticket, const ulong deviation, const string comment)
  {
//--- check stopped
   if(IsStopped(__FUNCTION__))
      return(false);
//--- check position existence
   if(!PositionSelectByTicket(ticket))
      return(false);
   string symbol = PositionGetString(POSITION_SYMBOL);
//--- clean
   ClearStructures();
//--- check filling
   if(!FillingCheck(symbol))
      return(false);
//--- check
   if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
     {
      //--- prepare request for close BUY position
      m_request.type = ORDER_TYPE_SELL;
      m_request.price = _NormalizePrice(symbol, SymbolInfoDouble(symbol, SYMBOL_BID));
     }
   else
     {
      //--- prepare request for close SELL position
      m_request.type = ORDER_TYPE_BUY;
      m_request.price = _NormalizePrice(symbol, SymbolInfoDouble(symbol, SYMBOL_ASK));
     }
//--- setting request
   m_request.action   = TRADE_ACTION_DEAL;
   m_request.position = ticket;
   m_request.symbol   = symbol;
   m_request.volume   = PositionGetDouble(POSITION_VOLUME);
   m_request.magic    = m_magic;
   m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation;
   m_request.comment = comment;
//--- close position
   return(OrderSend(m_request, m_result));
  }
//+------------------------------------------------------------------+
 
Aleksandr Slavskii #:

Увы, там не прописать. Но можно изменить немного код в Trade.mqh. Затем сохранить файл под другим названием, чтоб при обновлении не перезаписался дефолтным.

Типа так. 

спасибо за подсказку, но честно говоря это все как то выглядит бредово)) не оч охото в системные файлы лезть для того что бы стандартный функционал исправлять 😁😁

это не доработка разработчиков или сознательно "убрали" или "забыли" комментарии в ордерах?

скорее всего баг, потому что зачем тогда оставили возможность комментарий в ордере при открытии если по факту програмно нельзя отловить ордер по комменту??

причем в режиме визуализации в тестере все корректно отлавливается и считается статистика торгов !

может кто из разработчиков пояснит? 

 
Sergei Samokhin #:

 если по факту програмно нельзя отловить ордер по комменту??

Почему нельзя? Можно. Ничего там сложного в справке всё подробно описано. 

Я вам предложил как попроще. 

 
Roman Konopelko #:

Добрый день! Приложите пожалуйста более кокретный код на котором вы словили ошибки.

При вызове CChartCanvas::VScaleParams(const double max,const double min,const uint grid) 

  • grid = 0 метод игнорирует такой вызов
  • grid = 1 метод работает нормально на простых примерах

Добрый день. Изменяйте параметр i_shift на 100, -200. Должна сдвигаться только шкала, т.к. происходит подгонка под минимум и максимум.

#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <Canvas\\Charts\\LineChart.mqh>

input int i_shift=50;

CLineChart g_chart;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   g_chart.CreateBitmapLabel("trade_hist",10,40,1000,400,COLOR_FORMAT_ARGB_NORMALIZE);
   MathSrand(10);

   double dd[];
   ArrayResize(dd,64);
   for(int i1=0;i1<64;i1++)
      dd[i1]=MathRand()%100+i_shift;

//g_chart.VScaleMin(dd[ArrayMinimum(dd)]);
//g_chart.VScaleMax(dd[ArrayMaximum(dd)]);
//g_chart.NumGrid(25);//1=висим 0=не отображает график

   g_chart.VScaleParams(dd[ArrayMaximum(dd)],dd[ArrayMinimum(dd)],25);//Последний параметр: 1=висим 0=не отображает график
   g_chart.SeriesAdd(dd);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void  OnDeinit(const int  reason)
  {
   g_chart.Destroy();
   ChartRedraw();
  }
 

Моё исправление такое, файл LineChart:

строка 232:

//int y2=(int)(m_y_0-data[0]*m_scale_y);
int y2=(int)(m_y_min-(data[0]-m_v_scale_min)*m_scale_y);

строка 245:

//y2=(int)(m_y_0-value*m_scale_y);
y2=(int)(m_y_min-(value-m_v_scale_min)*m_scale_y);
 

что поменять в коде (конструкторов добавить, или ещё класс прокладку) чтобы не было 

но поведении (метод базового класса может вернуть экземпляр потомка)

и конечный синтаксис (чтобы писать в цепочку)

остался прежним ?

class Base;
class Holder;
class ExtHolder;

// base class
class Base {
public:
   int m_value;
public:
   Base():m_value(0) {
   }
   Base(int value):m_value(value) {
   }
   ~Base() {
   }
   virtual Base *clone() const {
      return new Base(m_value);
   }
   virtual int Hello(int x) const {
      PrintFormat("x=%d",x);
      return x;
   }
   // Get holder
   virtual ExtHolder GetHolder(int ext) {
      return ExtHolder(ext,this);
   }
};
// holder - contain copy, route methods to it
class Holder: public Base {
public:
   Base *m_hold;
public:
   Holder(Base &b):Base() {
      m_hold=b.clone();
   }
   ~Holder() {
      delete m_hold;
   }
   virtual Base *clone() const {
      return new Holder(*m_hold);
   }
   virtual int Hello(int x) const override {
      return m_hold.Hello(x);
   }
   
};
// extended holder
class ExtHolder:public Holder {
public:
   int m_ext;
public:
   ExtHolder(int ext,Base &b):Holder(b),m_ext(ext) {
   }
   ~ExtHolder() {
   }
   virtual Base *clone() const {
      return new ExtHolder(m_ext,*m_hold); /// <--- invalid pointer access
   }
   virtual int Hello(int x) const override {
      return Holder::Hello(x+m_ext);
   }
};

void OnStart()
{
   Base *test1 = ExtHolder(1,Base(1)).clone(); //<--- ok
   test1.Hello(1);
   Base *test2 = Base(1).GetHolder(1).clone(); //<--- err
   test2.Hello(2);
   delete test2;
   delete test1;
}