Perguntas sobre OOP em MQL5 - página 28

 
Dmitry Fedoseev:

E se você não usa aulas, você fica cansado de escrever constantemente algo como SymbolInfoDouble(_Symbol,MODE_BID). Tais danças toda vez - tanto parênteses e sublinhados, e você não sabe se deve pressionar o capslock (e depois em outro lugar sem olhar, digite toda uma corda capitalizada e digite-a novamente) ou manter o shifter pressionado. Pelo menos é aí que o OOP é útil. Se pelo menos criar classes para todas essas funções, então sim - elas são enormes. Se você o escreve por si mesmo, não é um problema. Quanto a trabalhar com pedidos, não há tantas funções usadas com freqüência, podemos simplesmente colocar algumas funções em uma biblioteca. Mas em geral, ainda não foi encontrada uma abordagem ideal.

Aqui está minha visão da classe que pode abrir/fechar/pararar perda e mais tarde exibiro status da ordem

class CConstVolume
{
protected:
   static const double  VolumeMAX;
   static const double  VolumeMIN;
   static const double  VolumeSTEP;
   static const double  ZerroPrice;
   static const int     VolumeDIGITS;
   static int           GetDigitsInVolumeStep(); };
//___________________________________________________________________________
static int CConstVolume::GetDigitsInVolumeStep()
{  int result = 0;
   long i = 10000000, k = long(::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP) / 0.0000001);
   while(result < 7 && k % i > 0)
   {  i /= 10;
      result++; }
   return(result); }
//____________________________________________________________________
static const double CConstVolume::VolumeMAX = ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
//____________________________________________________________________
static const double CConstVolume::VolumeMIN = ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
//____________________________________________________________________
static const double CConstVolume::VolumeSTEP = ::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
static const double CConstVolume::ZerroPrice = ::NormalizeDouble(0.0, _Digits);
//____________________________________________________________________
static const int CConstVolume::VolumeDIGITS = CConstVolume::GetDigitsInVolumeStep();
//____________________________________________________________________




//+------------------------------------------------------------------+
//|   class COrder                                                   |
//+------------------------------------------------------------------+
class COrder : private CConstVolume
{
private:
   SOrderInfo        m_info;        //структура для инициализации класса, и хранения информации о ордере, тип, цена отркытия, лот, и состояние ордера
   CError            error;         //класс с описание ошибок на 2-х языках
   int               sl_error_count;//счетчик ошибок установки стоплосса/тейка
   bool              m_needstoploss;//флаг для установки стоплосса, сбросим когда все ОК
   bool              CheckMarginRequirements();
   bool              ServerDisable();
   int               Ordersend();
   int               CheckOrderByMagicnumber(int magic_);   //метод нужен для поиска открытого ордера по магику, использую в конструкторе
   void              SetStoploss();
   void              NULLOrder()             { ZeroMemory(m_info); m_info.cmd = -1; m_info.status = ErrorOrder; m_needstoploss = false;   }
   void              PrintError(string func) { Print(func); error.GetLastError();                                                         }
public:
                     COrder():m_needstoploss(false) { NULLOrder();                                                                        }
                     COrder(SOrderInfo &ordersetting);
   SOrderInfo        GetOrderInfo(); 
   bool              Orderclose();};
//________________________________

e observe o uso em um símbolo - especialmente uma classe estática para usar

no total, tudo funciona como pretendido.... mas não gosto disso, como escrevi acima é incômodo e supérfluo

 
Dmitry Fedoseev:

E se você não usar aulas, você vai se cansar de escrever constantemente algo como SymbolInfoDouble(_Symbol,SYMBOL_BID). Isto dança cada vez ...

Você poderia fazer embalagens mais convenientes e concisas para estas funções, mantendo-as em estilo de procedimento. Especialmente levando em conta o fato de que em construções recentes eles finalmente adicionaram espaço de nomes, tudo é ótimo. Antes você tinha que implementá-los como métodos estáticos, mas agora tudo é muito mais fácil:

namespace SymbolInfo
{
  double Bid(string symbol) { return SymbolInfoDouble(symbol, SYMBOL_BID); }
  double Ask(string symbol) { return SymbolInfoDouble(symbol, SYMBOL_ASK); }
};
 
Alexey Navoykov:

Você pode fazer embalagens mais convenientes e concisas para estas funções, mantendo-se dentro do estilo de procedimento. Especialmente porque finalmente adicionaram espaço de nomes nas últimas construções, isso é ótimo. Antes, você tinha que implementá-las como métodos estáticos, mas agora tudo é muito mais simples:

É realmente importante ficar dentro dos limites? Se for importante ficar dentro dos limites, você pode escrever funções.

 
Igor Makanu:

bem, não muito, eu diria muitas ações para estabelecer uma ordem, aqui está minha visão para uma classe que sabe como abrir/fechar/estabelecer explosões/e mais status de ordem de saída

e observe o uso em um símbolo - especialmente uma classe estática para usar

no total, tudo funciona como pretendido.... mas não gosto disso, como escrevi acima é incômodo e supérfluo

Sim, aqui está outra pergunta que continua a surgir e que não tem uma resposta inequívoca. Quando você precisar herdar sua própria classe - o que é melhor fazer, herdá-la ou escrever uma nova versão estendida de sua classe.

 
Alexey Navoykov:

É possível fazer invólucros mais convenientes e concisos para estas funções, mantendo-se dentro do estilo de procedimento. Especialmente porque finalmente adicionaram espaço de nomes nas últimas construções, isso é ótimo. Antes, era preciso implementá-los como métodos estáticos, agora as coisas são muito mais simples:

Você não tem uma notação sucinta, se não houver cheques, é mais fácil de escrever como está:

#define  Ask SymbolInfoDouble(_Symbol,SYMBOL_ASK)
#define  Bid SymbolInfoDouble(_Symbol,SYMBOL_BID)

void OnStart()
  {
   Print("Ask = ",Ask);
   Print("Bid = ",Bid);
  }
 
Igor Makanu:

e note que para ser usado em um único personagem - especificamente uma classe estática utilizada

O que impede que você passe o nome do símbolo ao construtor, tornando a classe flexível e versátil? Você não considera a possibilidade de negociação de portfólio como uma questão de princípio?
 
Igor Makanu:

Sua entrada não é concisa, se não houver cheques, é mais fácil de escrever como está:

Há muitas funções como SymbolInfoDouble. É um incômodo criar nomes curtos para todos eles. Ao reuni-los em classes, você não precisa se preocupar com a singularidade dos nomes.

 

Eu tenho o seguinte circuito onde não tive problemas.

  1. Eu escrevo TC somente para o Testador. Sem registros, manipuladores de erros ou qualquer outra porcaria. O código é muito conciso, compreensível e passível de revisões, se feito através do OOP (mas não fundamental). Já coloquei o exemplo no KB. O bônus é a rápida otimização.
  2. O principal é que ele deve estar disponível para o testador e em blocos independentes. A geração de sinais comerciais - um bloco. Comércio de sinais - outro bloco.
  3. A transferência para a conta real é sempre feita em várias jogadas de uma só vez. O TS é colocado em um ambiente virtual sem nenhuma mudança de código. Vários TS podem ser colocados em um ambiente ou cada TS em seu próprio ambiente, então o OOP se torna especialmente conveniente. Depois pegamos uma copiadora (o mercado está cheio delas, por isso as pessoas são boas em fotocopiadoras-lógica), que simplesmente copia negócios/encomendas do ambiente virtual para o real.
  4. Com este esquema, escrever TS é rápido e fácil. A transferência para o real (o que de fato é raro) é sempre feita de maneira uniforme, rápida e clara.
 
Igor Makanu:

sua entrada não é sucinta, se não houver cheques, é mais fácil escrevê-la como ela é:

Não é assim que se faz. Você precisa pelo menos chamar tanto Bid() quanto Ask(). Sua entrada parece apenas uma variável, dando a aparência de que seu valor permanece inalterado, quando na realidade não o é.
 
Alexey Navoykov:
O que impede que você passe o nome do símbolo ao construtor, tornando a classe flexível e versátil? Você fundamentalmente não considera a possibilidade de negociação de portfólio?

O que impede isso é que, na maioria dos casos, são escritos EAs com um único caractere, e passar um símbolo seria uma ação desnecessária (e exaustiva)). Outra coisa é fazer com que o símbolo do gráfico seja automaticamente selecionado por padrão e, se necessário, você pode substituir o símbolo por um tempo. Mas novamente surge a questão, que é melhor - usar uma instância da classe e substituir o símbolo conforme necessário, ou criar uma instância separada para cada símbolo.