Perguntas sobre OOP em MQL5 - página 17

 
Você está me assustando.
 
O ponto, não a forma, mas o significado.
 
fxsaber:

Veja o formato de registro da CList. Você está ignorando isso.

Certo! Obrigado, vou investigar mais a fundo.

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

Eu acho que "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

Anexei o modelo CDataBase em si, seria conveniente - qualquer estrutura (classe) criada como a minha e deixá-la armazenar dados na memória(construtor sem parâmetro) ou, ao adicionar um novo elemento, despejá-lo em disco(construtor com parâmetro)

SZZ: provavelmente algo mais eu vou dopar, mas em geral estou satisfeito com o resultado

Arquivos anexados:
CDataBase.mqh  10 kb
 

Eu raramente uso modificadores constantes e estáticos, e tentei acidentalmente "ligar" uma classe ao corpo funcional, não tenho idéia de como funciona, mas não encontrei nenhum erro ao testar

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

Eu coloquei intencionalmente chamadas de SymbolInfoDouble() em funções separadas f1()-f3() para desimprimi-lo


E a pergunta em si, quanto deste código funciona, onde podem estar os bugs? Eu quero minimizar chamadas desnecessárias, mas a classe de alguma forma funciona dentro da função, em geral funciona, mas para mim não deve funcionar!

 
Igor Makanu:

Eu raramente uso modificadores constantes e estáticos, e tentei acidentalmente "ligar" uma classe ao corpo funcional, não tenho idéia de como funciona, mas não encontrei nenhum erro ao testar

Eu coloquei intencionalmente chamadas de SymbolInfoDouble() em funções separadas f1()-f3() para desimprimi-lo


E a pergunta em si, quanto deste código funciona, onde podem estar os bugs? Eu quero minimizar chamadas desnecessárias, mas a classe de alguma forma funciona dentro da função, em geral funciona, mas para mim não deve funcionar!

Está tudo bem. Funcionará.

 
Vladimir Simakov:

Está tudo bem. Funcionará.

Obrigado!

testei no código de teste EA, não vi nenhum bug, mudei TFs e descarreguei EA do gráfico, funciona como eu esperava, todas as variáveis com modificador estático constante são inicializadas uma vez (é interessante, que a inicialização é feita antes de iniciar OnItin() - eu não assinei todas as chamadas)

Eu melhorei o código, talvez alguém precise normalizar o volume de pedidos com arredondamento(não funcionará para Consultores Especialistas com várias moedas!!!)

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

Você também poderia escrevê-lo desta forma. O significado é o mesmo, mas há menos letras. A variável l_ será removida pelo compilador.

 
Vladimir Simakov:

Você também pode escrevê-lo dessa forma. O sentido é o mesmo, mas há menos letras. O compilador removerá a própria variável l_.

Acabo de escrever meu posto e aqui está... Eu acho que os códigos são quase idênticos )))) a variável L_ é necessária abaixo, é uma parte do código para fazer um pedido, eu decidi arrumar minha biblioteca

SZZ: Eu verifiquei, mas o modificador const para um exemplo de classe vol pode não ser escrito... menos cartas ))))

 
   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 o número de caracteres em um lote e o tamanho do próprio lote.

 
Vladimir Simakov:


Para encontrar o número de caracteres em um lote e o tamanho do próprio lote.

Já vi soluções similares, mas minha função _OrderSend(....) é para estilo de procedimento, nem sempre conveniente usar o OOP para EAs primitivos,

Decidi fazer um número mínimo de chamadasSymbolInfoDouble( ) no início, e depois decidi me livrar de chamadas adicionais NormalizeVolume() - tentei incluir _OrderSend() no corpo, mas o objetivo era receber todo o ambiente comercial uma vez e depois, quando uma ordem é aberta, ler apenas seu volume,

Vou tentar e, em geral, estou satisfeito com o resultado, se eu encontrar algum bug, vou relatá-lo no tópico