Preguntas sobre POO en MQL5 - página 17

 
Me estás asustando.
 
La cuestión, no es la forma, sino el significado.
 
fxsaber:

Mira el formato de registro de CList. Lo estás ignorando.

¡Claro! Gracias, lo investigaré más a fondo.

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

Pienso "¡Yay! ¡Está funcionando!" (С)

#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

He adjuntado la plantilla de CDataBase propiamente dicha, sería conveniente - cualquier estructura (clase) creada como la mía y dejar que almacene los datos en memoria(constructor sin parámetro) o que, al añadir un nuevo elemento, los vuelque al disco(constructor con parámetro)

SZZ: probablemente algo más que voy a dopar, pero en general estoy satisfecho con el resultado

Archivos adjuntos:
CDataBase.mqh  10 kb
 

Rara vez uso modificadores const y static, y accidentalmente intenté "enchufar" una clase en el cuerpo de la función, no tengo idea de cómo funciona, pero no encontré ningún error al probar

#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));
  }
//+------------------------------------------------------------------+

He puesto intencionadamente las llamadas a SymbolInfoDouble() en funciones separadas f1()-f3() para no imprimirlas


Y la pregunta en sí, ¿cuánto de este código funciona, dónde puede haber errores? ¡Quiero minimizar las llamadas innecesarias, pero la clase de alguna manera funciona dentro de la función, en general funciona, pero para mí no debería funcionar!

 
Igor Makanu:

Rara vez uso modificadores const y static, y accidentalmente intenté "enchufar" una clase en el cuerpo de la función, no tengo idea de cómo funciona, pero no encontré ningún error al probar

He puesto intencionadamente las llamadas a SymbolInfoDouble() en funciones separadas f1()-f3() para no imprimirlas


Mi pregunta es, ¿qué tan bien funciona este código, dónde puede haber errores? ¡Quiero minimizar las llamadas innecesarias, pero la clase de alguna manera funciona dentro de la función, en general funciona, pero para mí no debería funcionar!

Está bien. Funcionará.

 
Vladimir Simakov:

Está bien. Funcionará.

Gracias.

He probado en el código del EA de prueba, no he visto ningún error, he desplazado los TFs y descargado el EA del gráfico, funciona como esperaba, todas las variables con modificador estático const se inicializan una vez (es interesante, que la inicialización se hace antes de iniciar OnItin() - yo sin firmar todas las llamadas)

He mejorado el código, puede ser que alguien necesite la normalización del volumen de la orden con el redondeo(¡¡no funcionará para los Asesores Expertos multidivisa!!)

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_);
  }

También puedes escribirlo así. El significado es el mismo, pero hay menos letras. La variable l_ será eliminada por el compilador.

 
Vladimir Simakov:

También puede escribirlo así. El sentido es el mismo, pero hay menos letras. El compilador eliminará la propia variable l_.

Acabo de escribir mi post y aquí está... Creo que los códigos son casi idénticos )))) La variable L_ es necesaria a continuación, es una parte del código para realizar un pedido, decidí ordenar mi biblioteca

SZZ: Lo he comprobado, pero el modificador const para una instancia de la clase vol no se puede escribir... menos letras ))))

 
   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);}

Para encontrar el número de caracteres de un lote y el tamaño del mismo.

 
Vladimir Simakov:


Para encontrar el número de caracteres de un lote y el tamaño del mismo.

He visto soluciones similares, pero mi función _OrderSend(....) es de estilo procedimental, no siempre es conveniente usar OOP para EAs primitivos,

Decidí hacer un número mínimo de llamadasSymbolInfoDouble() al principio, y luego decidí deshacerme de la llamada adicional NormalizeVolume() - Traté de incluir _OrderSend() en el cuerpo, pero el propósito era recibir todo el entorno de negociación una vez y luego, cuando una orden se abre, leer su volumen solamente,

Voy a probarlo y en general estoy satisfecho con el resultado, si encuentro algún fallo, lo reportaré en el tema

Razón de la queja: