Discussão do artigo "Desenvolvendo um EA multimoeda (Parte 3): Revisão da arquitetura"

 

Novo artigo Desenvolvendo um EA multimoeda (Parte 3): Revisão da arquitetura foi publicado:

Nós já avançamos um pouco no desenvolvimento de um EA multimoeda com várias estratégias funcionando em paralelo. Com base na experiência acumulada, vamos revisar a arquitetura da nossa solução e tentar melhorá-la, antes que avancemos muito.

Destacamos um objeto especialista (classe CAdvisor ou seus derivados), que é um agregador de objetos de estratégias de negociação (classe CStrategy ou seus derivados). No início do trabalho do EA no manipulador OnInit(), ocorre o seguinte:

  • Cria-se o objeto especialista.
  • Criam-se objetos de estratégias de negociação e adicionam-se ao especialista no seu array de estratégias de negociação.

No EA, no manipulador de eventos OnTick(), ocorre o seguinte:

  • Chama-se o método CAdvisor::Tick() para o objeto especialista.
  • Este método percorre todas as estratégias e chama seu método CStrategy::Tick().
  • As estratégias, no contexto do CStrategy::Tick(), realizam todas as operações necessárias para abrir e fechar posições de mercado.

Esquematicamente, isso pode ser representado assim:

Fig. 1. Operation mode from the first article

Fig. 1. Esquema de funcionamento do primeiro artigo

A vantagem desse esquema era que, tendo o código-fonte do EA, operando com uma única estratégia de negociação, era possível, com operações não muito complexas, modificá-lo para trabalhar conjuntamente com outros exemplares de estratégias de negociação.

Mas logo se descobriu a principal desvantagem: ao combinar várias estratégias, somos obrigados a reduzir, de alguma forma, o tamanho das posições abertas por cada exemplar de estratégia. Isso pode levar à exclusão completa da negociação de alguns ou até de todos os exemplares de estratégias. Quanto mais exemplares de estratégias incluímos no trabalho paralelo ou quanto menor o depósito inicial escolhido para negociação, mais provável é esse desfecho, já que o tamanho mínimo das posições de mercado abertas é fixo.

Autor: Yuriy Bykov

 
FOREACH(m_orders, if(m_orders[i].IsOpen()) { m_ordersTotal += 1; })

Às vezes, algo dentro de você o estimula a escrever dessa forma.

FOREACH(m_orders, m_ordersTotal += m_orders[i].IsOpen())
 
Ainda não li tudo até o fim. Mas a sensação é de que o trabalho com os pendentes (não no Tester) não se encaixa realmente nessa arquitetura, de fato, muito aprimorada.
 

Seria bom adicionar uma máscara de ativação/desativação de uma estratégia para levar em conta o volumetrista (destinatário de volumes virtuais).

Por exemplo, você precisa desativar alguma TS do portfólio por um tempo: ela continua a ser negociada virtualmente, mas não afeta o ambiente real. Da mesma forma, com sua ativação inversa.

 
Não consigo pensar em uma maneira de refinar essa arquitetura logo de cara. Essa é a única maneira de fazer isso agora.
//+------------------------------------------------------------------+
//|| Classe base de especialista|
//+------------------------------------------------------------------+
class CAdvisor {
protected:
   CStrategy         *m_strategies[];  // Conjunto de estratégias de negociação

Mas em algum lugar deve haver uma incorporação competente de algo semelhante.

 CAdvisor *m_advisors[];  // Matriz de portfólios virtuais

com seus próprios magos.

 
Оповещение получателя и стратегии должно происходить только при открытии или закрытии виртуальной позиции.

Você poderá ter dificuldades com isso, mesmo no Testador, se a sessão de cotação estiver fora da sessão de negociação.

O sinalizador de que a sincronização de volume foi bem-sucedida pode salvá-lo.

 
//+------------------------------------------------------------------+
//| Classe de ordens e posições virtuais
//+------------------------------------------------------------------+
class CVirtualOrder {
private:
//--- Campos estáticos ...
   
//--- Objetos relacionados de destinatário e estratégia
   CVirtualReceiver  *m_receiver;
   CVirtualStrategy  *m_strategy;

É uma solução questionável inserir uma entidade completamente diferente em um pedido virtual.

Parece que, ao criar a arquitetura, o problema de desempenho foi resolvido em paralelo. Eu mesmo tenho esse pecado.


Provavelmente, ainda é correto projetar sem levar em conta o desempenho. Depois, pense em como você pode acelerar o processo.

 
fxsaber #:
Ainda não li tudo até o fim. Mas tenho a sensação de que trabalhar com ordens pendentes (não no Tester) não se encaixa realmente nessa arquitetura, de fato, muito aprimorada.

Não trabalho com ordens pendentes reais, parece ser suficiente apenas abrir posições de mercado quando as ordens pendentes virtuais são acionadas. Sei que isso pode estar repleto de entradas não muito precisas devido a derrapagens e recotações em negociações reais. Mas, na prática, ainda não me deparei com isso. O suporte para ordens pendentes virtuais estará na próxima parte.

Se você ainda quiser se preocupar com ordens pendentes reais, então, em princípio, a arquitetura permite isso: você terá de escrever outra implementação da classe CVirtualSymbolReceiver. A implementação atual simplesmente ignora as ordens pendentes virtuais.

 
fxsaber #:

Seria uma boa ideia adicionar uma máscara de estratégia de ativação/desativação para levar em conta o volumetrician (destinatário de volumes virtuais).

Por exemplo, você precisa desativar uma TS do portfólio por um tempo: ela continua a ser negociada virtualmente, mas não afeta o ambiente real. Da mesma forma, com sua ativação inversa.

Não é difícil realizar tal coisa, mas sem usá-la, você precisará de critérios claros de ativação/desativação para cada estratégia. Essa é uma tarefa mais complexa, que ainda não abordei e provavelmente não abordarei.

 
fxsaber #:

E deve haver uma incorporação competente de algo como isso em algum lugar.

CAdvisor *m_advisors[];  // Matriz de portfólios virtuais

com seus próprios magos.

Não há planos para isso. A fusão em portfólios ocorrerá em um nível intermediário entre o CAdvisor e o CStrategy. Há uma solução preliminar, mas é provável que ela mude muito durante a refatoração em andamento.

 
fxsaber sessão de negociação.

O sinalizador de que a sincronização de volume foi bem-sucedida pode salvá-lo.

Parece que ele já está lá:

class CVirtualSymbolReceiver : public CReceiver {
  ...
   bool              m_isChanged;      // Há alguma mudança na composição das posições virtuais?

Ele é redefinido somente quando o volume real necessário é aberto com sucesso para cada símbolo.