MQL5中的OOP问题 - 页 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模板本身,这很方便--任何像我这样创建的结构(类),让它在内存中存储数据(构造函数无参数),或者在添加新元素时,将其转储到磁盘(构造函数有参数)。

SZZ:也许我还会做一些别的事情,但总的来说,我对结果感到满意。

附加的文件:
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));
  }
//+------------------------------------------------------------------+

我故意把SymbolInfoDouble()的调用放到单独的函数f1()-f3()中,以解除打印。


而问题本身,这个代码有多少是有效的,哪里会有错误?我 想尽量减少不必要的调用,但这个类不知为何在函数中起作用,一般来说它起作用,但对我来说它不应该起作用!

 
Igor Makanu:

我很少使用const和static修饰符,我不小心尝试将一个类 "插入 "到函数体中,不知道它是如何工作的,但我在测试时没有发现错误

我故意把SymbolInfoDouble()的调用放到单独的函数f1()-f3()中,以解除打印。


而问题本身,这个代码有多少是有效的,哪里会有错误?我 想尽量减少不必要的调用,但这个类在函数中不知怎么就起作用了,一般来说是起作用了,但对我来说不应该起作用!"。

没关系的。它将发挥作用。

 
Vladimir Simakov:

这很好。它将发挥作用。

谢谢你!

我在测试EA的代码中进行了测试,我没有看到任何错误,我转移了TFs,并从图表中卸载了EA,它像我预期的那样工作,所有带有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_变量,它是下订单的代码的一部分,我决定整理我的库

SZZ: 我检查过了,但是vol类的实例的修改器const可能没有写...更少的字母 ))))

 
   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(....)函数是用于程序化风格的,对于原始的EA来说,使用OOP并不总是方便。

我决定一开始只调用最少的SymbolInfoDouble(),然后我决定摆脱额外的调用NormalizeVolume()--我试图将_OrderSend()纳入主体,但目的是一次性接收所有的交易环境,然后,当一个订单打开时,只读取其交易量。

我将尝试一下,总的来说,我对结果感到满意,如果我发现任何错误,我将在主题中报告。