Вопросы по ООП в MQL5 - страница 17

 
Вы меня пугаете. 
 
Смысл, не форма, а смысл. 
 
fxsaber:

Посмотрите формат записи CList. Вы его игнорируете.

точно! спасибо, буду разбираться дальше

...................

кажется "УРА! заработало!" (С)

#include <IgorM\CDataBase.mqh>
//+------------------------------------------------------------------+
class COrderBase : public CObject
  {
public: COrderBase(){};
   //-------------------------------------
   int               OrderTicket;
   double            OrderLots;
   string            OrderComment;
                     COrderBase(int ival,double dval);
   virtual bool      Save(const int file_handle);
   virtual bool      Load(const int file_handle);
  };
//+------------------------------------------------------------------+
void COrderBase::COrderBase(int ival,double dval)
  {
   this.OrderTicket=ival;
   this.OrderLots=dval;
   OrderComment="qwerty_"+IntegerToString(ival,2);
  }
//|                                                                  |
//+------------------------------------------------------------------+
bool COrderBase::Save(const int file_handle)
  {
   uint len=StringLen(OrderComment);
   return(::FileWriteInteger (file_handle,this.OrderTicket) &&
          ::FileWriteDouble  (file_handle,this.OrderLots)   &&
          ::FileWriteInteger( file_handle,len,INT_VALUE)    &&
          (len>0 ? ::FileWriteString(file_handle,OrderComment,len)==len : true)
          );
  }
//-------------------------------------
bool COrderBase::Load(const int file_handle)
  {
   ::ResetLastError();
   this.OrderTicket=::FileReadInteger(file_handle);
   this.OrderLots=::FileReadDouble(file_handle);
   uint len=FileReadInteger(file_handle,INT_VALUE);
   this.OrderComment=len>0 ? FileReadString(file_handle,len) : "";
   return(!::GetLastError());
  }
//+------------------------------------------------------------------+
void OnStart()
  {
   int i;
   CDataBase<COrderBase>data(31);
   for(i=0; i<5; i++) data.AddValue(new COrderBase(i,i*2.0));     // сюда вообще только тикет ордера нужно передавать!!!
   Print("1. Тип БД : ",data.TypeName()," , количествоо записей = ",data.ArraySize(),",  чтение данных :");
   for(i=0; i<data.ArraySize(); i++) Print(i," : ",data[i].OrderTicket," , ",data[i].OrderLots,",",data[i].OrderComment);
  }
//+------------------------------------------------------------------+
//2019.07.09 17:26:14.829	tst_CDataBase (EURUSD,H1)	1. Тип БД : COrderBase , количествоо записей = 5,  чтение данных :
//2019.07.09 17:26:14.829	tst_CDataBase (EURUSD,H1)	0 : 0 , 0.0,qwerty_ 0
//2019.07.09 17:26:14.829	tst_CDataBase (EURUSD,H1)	1 : 1 , 2.0,qwerty_ 1
//2019.07.09 17:26:14.829	tst_CDataBase (EURUSD,H1)	2 : 2 , 4.0,qwerty_ 2
//2019.07.09 17:26:14.829	tst_CDataBase (EURUSD,H1)	3 : 3 , 6.0,qwerty_ 3
//2019.07.09 17:26:14.829	tst_CDataBase (EURUSD,H1)	4 : 4 , 8.0,qwerty_ 4

сам шаблон CDataBase приатачил, по моему будет удобно - любую структуру (класс) создал по аналогии с моим и пусть или в памяти хранит данные ( конструктор без параметра) или при добавлении нового элемента сбрасывает на диск  ( конструктор с параметром)  

ЗЫ: возможно что то допилю еще, но в целом результат меня устраивает

Файлы:
CDataBase.mqh  10 kb
 

редко пользуюсь модификаторами const и static да и вот еще попробовал случайно в тело функции "воткнуть" класс, даже не представляют как оно работает, но ошибки при тестировании не нашел

#property strict
//+------------------------------------------------------------------+
void OnStart()
  {
   double lot=0.0;
   for(int i=0;i<50; i++)
     {
      Print(lot," = ",_OrderSend(lot));
      lot+=0.003;
     }
  }
//+------------------------------------------------------------------+
double _OrderSend(double lot_)
  {
   class CDig
     {
   public:
                        CDig(double vs){long i=10000000,k=long(vs/0.0000001);dig=0;while(dig<7 && k%i>0){i/=10;dig++;}Print(__FUNCSIG__);}
      int               dig;
     };
   const static double vol_step_= f1();
   const static double vol_max_ = f2();
   const static double vol_min_ = f3();
   const static CDig ld_(vol_step_);
   const static int vol_dig_=ld_.dig;
   double l_=NormalizeDouble(fmax(fmin(vol_step_*round(lot_/vol_step_),vol_max_),vol_min_),vol_dig_);
   return(l_);
  }
//+------------------------------------------------------------------+
double f1()
  {
   Print(__FUNCSIG__);
   return(SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP));
  }
//+------------------------------------------------------------------+
double f2()
  {
   Print(__FUNCSIG__);
   return(SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX));
  }
//+------------------------------------------------------------------+
double f3()
  {
   Print(__FUNCSIG__);
   return(SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN));
  }
//+------------------------------------------------------------------+

специально вынес в отдельные функции f1()-f3() вызовы SymbolInfoDouble(), чтобы распринтовать


ну и сам вопрос, насколько это работоспособный код, где могут быть баги ? , хочу минимизировать лишние вызовы, да вот класс как то работает внутри функции, в общем работает, но по мне так не должно это работать!

 
Igor Makanu:

редко пользуюсь модификаторами const и static да и вот еще попробовал случайно в тело функции "воткнуть" класс, даже не представляют как оно работает, но ошибки при тестировании не нашел

специально вынес в отдельные функции f1()-f3() вызовы SymbolInfoDouble(), чтобы распринтовать


ну и сам вопрос, насколько это работоспособный код, где могут быть баги ? , хочу минимизировать лишние вызовы, да вот класс как то работает внутри функции, в общем работает, но по мне так не должно это работать!

Нормально все. Будет работать.

 
Vladimir Simakov:

Нормально все. Будет работать.

Спасибо!

тестировал в коде тестового жксперта, не увидел каких багов, и ТФ переключал и выгружал эксперта с графика, работает как и задумывал, все переменные с модификатором const static инициализируются один раз (причем интересно, что инициализация до запуска OnItin() - распринтовал все вызовы)

причесал код, может кому пригодится нормализация обьема ордера с округлением (для мультивалютных экспертов не будет работать!!!)

double _OrderSend2(double lot_)
  {
   const static double vol_step_= SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   const static double vol_max_ = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   const static double vol_min_ = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   static class CDig{public:int digits(double v){long i=10000000,k=long(v/0.0000001);int d=0;while(d<7 && k%i>0){i/=10;d++;}return(d);}}vol;
   const static int vol_dig_=vol.digits(vol_step_);
   double l_=NormalizeDouble(fmax(fmin(vol_step_*round(lot_/vol_step_),vol_max_),vol_min_),vol_dig_);
// еуе код открытия ордера
   return(l_);
  }
 
double _OrderSend(double lot_)
  {
   const static double vol_step_= f1();
   const static double vol_max_ = f2();
   const static double vol_min_ = f3();
   const static class CDig
     {
   public:
                        CDig(double vs){long i=10000000,k=long(vs/0.0000001);dig=0;while(dig<7 && k%i>0){i/=10;dig++;}Print(__FUNCSIG__);}
      int               dig;
     } ld_(vol_step_);
   const static int vol_dig_=ld_.dig;
   return NormalizeDouble(fmax(fmin(vol_step_*round(lot_/vol_step_),vol_max_),vol_min_),vol_dig_);
  }

Можно так еще записать. Смысл тот-же, букв меньше. Переменную l_ компилятор и сам уберет.

 
Vladimir Simakov:

Можно так еще записать. Смысл тот-же, букв меньше. Переменную l_ компилятор и сам уберет.

только свой пост написал, а тут Вы... по моему коды почти один в один ))) , переменная L_ нужна ниже, это часть кода для выставления ордера, свою библиотеку решил причесать

ЗЫ: проверял, но модификатор const для экземпляра класса vol можно не писать... букв меньше )))

 
   lotDigits=MathMax(-(int)MathFloor(MathLog10(lotStep)),0);


double CBaseTrade::NormalizeVolume(double mVolume,bool mMinIsAlways=true){
   double x=MathPow(10,_lotDigits);
   mVolume=MathFloor(MathRound(mVolume*x)/_lotStep/x)*_lotStep;
   if (mVolume<_lotMin) return mMinIsAlways?_lotMin:0.0;
   if (mVolume>_lotMax) return _lotMax;
   return NormalizeDouble(mVolume,_lotDigits);}

Для нахождения количества знаков в лоте и собственно сам размер лота.

 
Vladimir Simakov:


Для нахождения количества знаков в лоте и собственно сам размер лота.

я видел похожие решения, но моя функция _OrderSend(....) для процедурного стиля, не всегда удобно ООП для примитивных экспертов использовать,

вот и решил сделать минимальное кол-во вызовов SymbolInfoDouble() сначала, а потом что то разошелся и решил избавиться от дополнительного вызова NormalizeVolume() - попробовал включить в тело _OrderSend(), но цель была чтобы один раз все торговое окружение получать, а затем при открытии ордера только объем ордера считать,

потестирую, в целом я доволен результатом, если обнаружу баги, то напишу в топик