Mas você não pode programar com OOP em MQL4, por isso ainda é mais popular.
Eu já mostrei meu código e vou mostrá-lo novamente:
class CTradeProcessorI : public CMyObject
{
public:
void CTradeProcessorI() { SetMyObjectType(MOT_TRADE_PROCESSOR_I); };
virtualvoid ~CTradeProcessorI() {};
// Настроечный интерфейсvirtualvoid SetSlippage(uint uiSlippage) = 0;
// Торговый интерфейс// Все функции возвращают код возврата торгового сервераvirtualint Buy(long & lTicket,ECurrencySymbol csSymbol,double dVolume,double dTP=0,double dSL=0,ulong ulMagic = 0,string strComment = NULL) = 0; // Всегда по цене Ask, если успешно - возвращается lTicketvirtualint Sell(long & lTicket,ECurrencySymbol csSymbol,double dVolume,double dTP=0,double dSL=0,ulong ulMagic = 0,string strComment = NULL) = 0; // Всегда по цене Bid, если успешно - возвращается lTicket virtualint ModifyTPSL(CTradePosComponentI* ptpcComponent,double dTP=0,double dSL=0) = 0;
virtualint ModifyTPSL(long lTPCTicket,double dTP=0,double dSL=0) = 0;
virtualint CloseTradeComponent(CTradePosComponentI* ptpcComponent,double dCloseVolume=EMPTY_VALUE) = 0; // dCloseVolume - закрываемый объем. Если равен EMPTY_VALUE или равен или больше, чем объем торговой компоненты с указанным тикетом - закрывается вся торговая компонента. virtualint CloseTradeComponent(long lTPCTicket,double dCloseVolume=EMPTY_VALUE) = 0; // dCloseVolume - закрываемый объем. Если равен EMPTY_VALUE или равен или больше, чем объем торговой компоненты с указанным тикетом - закрывается вся торговая компонента. virtualint PendingSet(long & lTicket,ECurrencySymbol csSymbol,ENUM_ORDER_TYPE otOrderType,double dSetPrice,double dVolume,double dTP=0,double dSL=0,ulong ulMagic = 0,string strComment = NULL) = 0; // если успешно - возвращается lTicketvirtualint PendingDelete(long lTicket) = 0;
virtualint PendingDelete(COrderInfoCore* poiOrder) = 0;
virtualint PendingModify(long lTicket,double dSetPrice,double dTP=0,double dSL=0) = 0;
virtualint PendingModify(COrderInfoCore* poiOrder,double dSetPrice,double dTP=0,double dSL=0) = 0;
// Проверка кода возвратаvirtualbool TradeOperationWasSuccessful(int iTradeResCode) = 0;
// Если функция возвращает true, то при возникновении пользовательских ошибок (iTradeResCode > ERR_USER_ERROR_FIRST) советник прекратит работу// В случае false - работа будет продолженаvirtualbool IsUserErrorsFalal() = 0;
};
Esta é a interface do processador comercial - é exatamente a mesma tanto para o MT4 quanto para o MT5.
O usuário apenas obtém esta interface - e ele tem todas as possibilidades de ações comerciais. Você nem precisa saber se está no MT4 ou MT5. Você precisa comprar - ligue para a função Comprar, que preencherá o ticket do componente de negociação aberto (para MT4 é uma ordem, para MT5 é uma posição), e retornará o código de retorno do servidor de negociação.
Você não precisa nem pensar na diferença entre os protocolos MT4 e MT5 - a interface fornece tudo o que você precisa.
Bem, digamos, aqui está minha função enviando pedido de mudança de TP-SL para processador comercial:
EEAWorkRetcode CChngTPSLRequest::_ProceedRequestInto(CTradeProcessorI* ptpProcessor)
{
ASSERT_MYPOINTER(ptpProcessor);
m_uiServerRetCode = ptpProcessor.ModifyTPSL(m_lComponentTicket,m_dTP,m_dSL);
if(ptpProcessor.TradeOperationWasSuccessful(m_uiServerRetCode) != true)
{
Print("Торговый запрос на изменение ТП-СЛ компоненты отработал с ошибкой, код возврата: ",m_uiServerRetCode);
TRACE_INTEGER("Торговый запрос на изменение ТП-СЛ компоненты отработал с ошибкой, код возврата: ",m_uiServerRetCode);
return(WR_SERVER_PROCEED_ERROR);
};
return(WR_SUCCEEDED);
};
Primeiro, os objetos da parte EA - formam pedidos de ação comercial (aqui, um desses pedidos é para mudar o TP-SL). Depois disso, a função ProceedRequestInto() é chamada para todos os pedidos de envio de informações sobre uma ação comercial para o processador comercial.
O próprio processador comercial é um objeto da seguinte classe:
// СTradeProcessor - переносимый класс торгового процессора// Именно этот класс необходимо использовать для торговли. // Класс реализует интерфейс CTradeProcessorI#ifdef __MQL5__#include <MyLib\Trade\MT5TradeProcessor.mq5>
#else // __MQL5__#include <MyLib\Trade\MT4TradeProcessor.mq5>
#endif //__MQL5__#ifdef __MQL5__class CTradeProcessor : public CMT5TradeProcessor
#else // __MQL5__class CTradeProcessor : public CMT4TradeProcessor
#endif //__MQL5__
{
public:
void CTradeProcessor(uint uiSlippage = DEFAULT_TRADE_POINT_SLIPPAGE);
void ~CTradeProcessor() {};
// Функции отложенных ордеров, которые используют платформоспецифические virtualint PendingDelete(COrderInfoCore* poiOrder);
virtualint PendingModify(COrderInfoCore* poiOrder,double dSetPrice,double dTP=0,double dSL=0);
};
Isto é, dependendo da plataforma - a classe CTradeProcessor é herdada da classe CMT5TradeProcessor ou da classe CMT4TradeProceccor.
É claro que tudo isso poderia ser feito sem OOP, com a ajuda de interruptores e ifdefs. Mas, para mim, a abordagem OOP é mais conveniente e clara, e o principal é que ela permite isolar as entidades umas das outras e se livrar da massa de variáveis globais.
A propósito, outro "eco do OOP" está apenas nas funções adicionais de trabalhar com as ordens pendentes. O processador comercial - trabalha com bilhete de negócios, o que é inconveniente - a referência ao bilhete em MT4 e MT5 é diferente. É por isso que existe a classe comum COrderInfoCore - descendente da interface do pedido. É muito mais conveniente passar para o processador apenas um ponteiro para este objeto. Desta forma, contornamos assim os fragmentos dependentes da plataforma.
Bem, digamos, aqui está minha função enviando pedido de mudança de TP-SL para processador comercial:
Primeiro, os objetos da parte EA - formam pedidos de ação comercial (aqui, um desses pedidos é para mudar o TP-SL). Então a função ProceedRequestInto() é chamada para todas as solicitações para enviar informações sobre uma ação comercial a um processador comercial.
Parece-me complicado demais para entender o que está realmente acontecendo ali. E se você não entende o que está acontecendo dentro dele, é improvável que você o use... Não é mais fácil escrever uma versão separada para o MT5 e ligá-lo quando necessário?
Andrei: Acho que é muito complicado entender o que realmente se passa lá dentro... E sem entender como funciona, acho que ninguém vai usá-lo... Não é mais fácil escrever uma versão separada para o MT5 e conectá-la quando você precisar dela?
Por que eu preciso "entender o que está realmente dentro"? Há uma interface fixa que realiza uma ação, independentemente da plataforma - é o que usamos. E o que existe, a um nível baixo - que diferença faz?
Mas, na minha opinião, a abordagem OOP é muito mais conveniente e clara. E o mais importante - ela permite isolar entidades umas das outras, e se livrar de massas de variáveis globais.
Esse é o ponto, tendo isolado tudo de tudo, será muito mais difícil lidar com tal código, sem mencionar a impossibilidade de depuração adequada do código quando você precisar conhecer os valores atuais de todas as variáveis necessárias...
Porque minha conta principal está aberta no MT4, e meu testador de estratégia é muito melhor no MT5.
É um pedido comum dos clientes em Freelance - "deve funcionar tanto no MT4 quanto no MT5" - significa que há uma razão para isso. Eu mesmo não vejo a razão de trabalhar em Freelance, mas você pode perguntar àqueles que trabalham lá por que os clientes solicitam uma plataforma cruzada.
George Merts: Por que precisamos "entender o que está realmente sendo feito por dentro"? Há uma interface fixa que realiza uma ação, independentemente da plataforma - é o que usamos. E o que existe, a um nível baixo - que diferença faz?
Não se trata do nível baixo, trata-se da lógica do que está fluindo lá onde e em quê em todos os momentos possíveis, incluindo o conhecimento de todas as variáveis internas... Sem entender toda essa lógica redundante, o significado de usar esse código para um não-autor desaparece completamente...
Mas você não pode programar com OOP em MQL4, por isso ainda é mais popular.
Eu já mostrei meu código e vou mostrá-lo novamente:
Esta é a interface do processador comercial - é exatamente a mesma tanto para o MT4 quanto para o MT5.
O usuário apenas obtém esta interface - e ele tem todas as possibilidades de ações comerciais. Você nem precisa saber se está no MT4 ou MT5. Você precisa comprar - ligue para a função Comprar, que preencherá o ticket do componente de negociação aberto (para MT4 é uma ordem, para MT5 é uma posição), e retornará o código de retorno do servidor de negociação.
Você não precisa nem pensar na diferença entre os protocolos MT4 e MT5 - a interface fornece tudo o que você precisa.
Todas estas são capacidades do OOP.
Eu já mostrei meu código antes e vou mostrá-lo novamente:
Esta é a interface do processador comercial - é exatamente a mesma tanto para o MT4 quanto para o MT5.
O usuário simplesmente recebe esta interface - e ele tem todas as possibilidades de ações comerciais. Ele nem precisa saber se está no MT4 ou MT5.
E tudo isso graças ao OOP.
Há alguns exemplos de uso para casos típicos?
Se sua teoria fosse que MQL4=MQL5, então a MQL4 poderia ser executada no MT5 e vice-versa.
Você tem exemplos de uso para casos típicos?
Bem, digamos, aqui está minha função enviando pedido de mudança de TP-SL para processador comercial:
EEAWorkRetcode CChngTPSLRequest::_ProceedRequestInto(CTradeProcessorI* ptpProcessor) { ASSERT_MYPOINTER(ptpProcessor); m_uiServerRetCode = ptpProcessor.ModifyTPSL(m_lComponentTicket,m_dTP,m_dSL); if(ptpProcessor.TradeOperationWasSuccessful(m_uiServerRetCode) != true) { Print("Торговый запрос на изменение ТП-СЛ компоненты отработал с ошибкой, код возврата: ",m_uiServerRetCode); TRACE_INTEGER("Торговый запрос на изменение ТП-СЛ компоненты отработал с ошибкой, код возврата: ",m_uiServerRetCode); return(WR_SERVER_PROCEED_ERROR); }; return(WR_SUCCEEDED); };Primeiro, os objetos da parte EA - formam pedidos de ação comercial (aqui, um desses pedidos é para mudar o TP-SL). Depois disso, a função ProceedRequestInto() é chamada para todos os pedidos de envio de informações sobre uma ação comercial para o processador comercial.
O próprio processador comercial é um objeto da seguinte classe:
Isto é, dependendo da plataforma - a classe CTradeProcessor é herdada da classe CMT5TradeProcessor ou da classe CMT4TradeProceccor.
É claro que tudo isso poderia ser feito sem OOP, com a ajuda de interruptores e ifdefs. Mas, para mim, a abordagem OOP é mais conveniente e clara, e o principal é que ela permite isolar as entidades umas das outras e se livrar da massa de variáveis globais.
A propósito, outro "eco do OOP" está apenas nas funções adicionais de trabalhar com as ordens pendentes. O processador comercial - trabalha com bilhete de negócios, o que é inconveniente - a referência ao bilhete em MT4 e MT5 é diferente. É por isso que existe a classe comum COrderInfoCore - descendente da interface do pedido. É muito mais conveniente passar para o processador apenas um ponteiro para este objeto. Desta forma, contornamos assim os fragmentos dependentes da plataforma.
Bem, digamos, aqui está minha função enviando pedido de mudança de TP-SL para processador comercial:
Primeiro, os objetos da parte EA - formam pedidos de ação comercial (aqui, um desses pedidos é para mudar o TP-SL). Então a função ProceedRequestInto() é chamada para todas as solicitações para enviar informações sobre uma ação comercial a um processador comercial.
Meu código funciona completamente inalterado em MT4 e MT5.
Por que funcionar em terminais diferentes?
Acho que é muito complicado entender o que realmente se passa lá dentro... E sem entender como funciona, acho que ninguém vai usá-lo... Não é mais fácil escrever uma versão separada para o MT5 e conectá-la quando você precisar dela?
George Merts:
Mas, na minha opinião, a abordagem OOP é muito mais conveniente e clara. E o mais importante - ela permite isolar entidades umas das outras, e se livrar de massas de variáveis globais.
Esse é o ponto, tendo isolado tudo de tudo, será muito mais difícil lidar com tal código, sem mencionar a impossibilidade de depuração adequada do código quando você precisar conhecer os valores atuais de todas as variáveis necessárias...
Por que funcionar em terminais diferentes?
Porque minha conta principal está aberta no MT4, e meu testador de estratégia é muito melhor no MT5.
É um pedido comum dos clientes em Freelance - "deve funcionar tanto no MT4 quanto no MT5" - significa que há uma razão para isso. Eu mesmo não vejo a razão de trabalhar em Freelance, mas você pode perguntar àqueles que trabalham lá por que os clientes solicitam uma plataforma cruzada.
Por que precisamos "entender o que está realmente sendo feito por dentro"? Há uma interface fixa que realiza uma ação, independentemente da plataforma - é o que usamos. E o que existe, a um nível baixo - que diferença faz?