Discussão do artigo "Desenvolvendo um EA multimoeda (Parte 2): Transição para posições virtuais de estratégias de trading" - página 5

[Excluído]  
mytarmailS #:
Não é um fato que, no mercado, a complicação do modelo funcionará melhor do que uma cesta de TSs simples
Bem, não é necessário beber cada TS no cocho, mas apenas adicionar uma nova TS após várias passagens do otimizador.
 
Maxim Dmitrievsky bagging (cesta) de estratégias, mas sim boosting. Isso ocorre quando uma estratégia é otimizada primeiro, depois seus sinais são substituídos como um parâmetro para a segunda estratégia, a segunda estratégia é otimizada e assim por diante.

Parece-me que a implementação do destaque é uma tarefa nada trivial. Normalmente, os parâmetros da estratégia são definidos no início, e os sinais de abertura/fechamento são determinados por algum algoritmo enquanto a estratégia está sendo executada. Se salvarmos o histórico de aberturas em alguma forma unificada, tudo isso terá de ser alimentado na entrada da segunda estratégia.... Será que é assim? Se fornecermos essas informações na forma de um algoritmo (função) e seus parâmetros fixos, não descobriremos que chegamos ao mesmo ensacamento, mas com uma porta dos fundos?

 

Muito obrigado, li com interesse. Quero fazer algo semelhante, só que com mais automação, e para isso pretendo colocar em operação, sem piedade, suas bibliotecas para trabalhar com arquivos *.opt e *.tst do testador.

[Excluído]  
Yuriy Bykov #:

Parece-me que a implementação do destaque é uma tarefa não trivial. Normalmente, os parâmetros da estratégia são definidos na inicialização, e os sinais de abertura/fechamento são determinados por algum algoritmo enquanto a estratégia está em execução. Se salvarmos o histórico de aberturas em alguma forma unificada, então tudo isso terá de ser alimentado na entrada da segunda estratégia.... Será que é assim? Se fornecermos essas informações na forma de um algoritmo (função) e seus parâmetros fixos, não descobriremos que chegamos ao mesmo ensacamento, mas com uma porta dos fundos?

Não pensei em como fazer isso por meio do otimizador. Não, deve acontecer que cada estratégia seguinte melhore a anterior, ou seja, seja construída em cima dela. A maneira exata de visualizar isso é uma questão de tempo. Você pode simplesmente pesquisar como as árvores impulsionadas funcionam na Internet e usá-las como base para o seu design. Pode haver muitas nuances, sim. Mas eu mesmo não farei isso, porque tudo isso já está nos algoritmos do MO. E não é uma panaceia, mas pode ser melhor do que um portfólio TC em termos de suas propriedades.

 
Maxim Dmitrievsky #:

Não tinha pensado em como fazer isso por meio do otimizador.

Essa é uma rotina que pode ser totalmente automatizada por meio da conexão do mqh apropriado ao mq5.


O algoritmo é o seguinte.

  1. A pasta contém as passagens anteriores (se não houver passagens - vazia) na forma de arquivos.
  2. Uma nova otimização é iniciada: o próprio TS é negociado + a negociação do ponto 1 é adicionada. Nesse caso, a MM é distribuída igualmente entre p.1 e TS.
  3. A melhor aprovação (OnTester de qualquer tipo) da otimização é registrada no item 1.
  4. Em p.2. quantas vezes o TS quiser no portfólio.

Portanto, você pode misturar o que quiser. É óbvio que, mesmo com uma pesquisa completa, o resultado final dependerá da sequência em que os TSs são lançados.

Também está claro que, mesmo no SB, haverá uma melhoria dos indicadores a cada passagem, mas será um ajuste.

 
Yuriy Bykov #:

Muito obrigado, dei uma olhada no código. Analisarei a passagem de parâmetros de entrada mais tarde. Se não for possível adotar essa abordagem completamente, alguns pontos provavelmente serão muito úteis.

Apliquei os resultados atuais do meu trabalho com entradas novamente (no apêndice) ao código deste artigo.

Aqui está um exemplo do que o SimpleVolumesExpertSingle.mq5 se tornou.

#define  INPUT_STRUCT_ADDON
#include "Advisor.mqh"
#include "SimpleVolumesStrategy.mqh"
#include "VolumeReceiver.mqh"

input string      symbol_              = "EURGBP";    // Instrumento de negociação (símbolo)
input group "=== Parâmetros do conselheiro."
input ulong       magic_              = 27181; // Magic

CAdvisor     *expert;         // Ponteiro para o objeto especialista

//+------------------------------------------------------------------+
//| Função de inicialização de especialista|
//+------------------------------------------------------------------+
int OnInit() {
   expert = new CAdvisor(new CVolumeReceiver(magic_));

   // Adicionar uma instância da estratégia
   expert.Add(new CSimpleVolumesStrategy( symbol_, inStrategyInput + inSimpleVolumesStrategyInput));

   return(INIT_SUCCEEDED);
}


Consegui obter uma prescrição única de inputs(SimpleVolumesStrategyInput.mqh) no código.

// https://www.mql5.com/pt/code/47932
// Use essa string para encontrar todos os Inputs mqh.
// #include <fxsaber\Input_Struct\Input_Struct.mqh> // Original

#define  TYPENAME_INPUT SimpleVolumesStrategyInput

#define  MACROS_MULTI                    \
  MACROS(signalPeriod, int, 13)         \ // Número de velas para cálculo da média de volume
  MACROS(signalDeviation, double, 0.3)  \ // Desvio relativo da média para a abertura da primeira ordem
  MACROS(signaAddlDeviation, double, 1) \ // Desvio relativo da média para a abertura da segunda ordem e das ordens subsequentes
  MACROS(openDistance, int, 0)          \ // Distância do preço até a ordem pendente
  MACROS(stopLevel, double, 10500)      \ // Stop Loss (em pontos)
  MACROS(takeLevel, double, 465)        \ // Take Profit (em pips)
  MACROS(ordersExpiration, int, 1000)   \ // Tempo de expiração das ordens pendentes (em minutos)
  MACROS(maxCountOfOrders, int, 3)        // Número máximo de ordens abertas simultaneamente

Arquivos anexados:
 
fxsaber #:

Apliquei os resultados atuais do meu trabalho com insumos novamente (no apêndice) ao código deste artigo.

Um exemplo do que o SimpleVolumesExpertSingle.mq5 se tornou.


Consegui obter uma prescrição única de inputs(SimpleVolumesStrategyInput.mqh) no código.

Isso me pareceu, de alguma forma, visivelmente mais fácil do que a variante anterior. No entanto, talvez seja apenas o fato de que, quando você olha para o código de outra pessoa mais uma vez, ele se torna mais claro e mais simples a cada vez. Muito obrigado! Enquanto estudava, surgiu uma dúvida: o código que vem depois de "// Copie e cole a atualização daqui:" não pode ser colocado em um arquivo de inclusão e anexado em vez de colado? Não é conveniente fazer um experimento agora, então pensei em perguntar.

No terceiro artigo, ainda não cheguei aos parâmetros de entrada :(. Mas com certeza isso acontecerá.

 
Yuriy Bykov #:

Enquanto estudava, surgiu uma dúvida: é possível colocar o código que vem depois de "// Copie e cole a atualização daqui:" em um arquivo de inclusão e conectá-lo em vez de colá-lo? Não é conveniente fazer um experimento neste momento, então decidi perguntar.

Infelizmente, não é possível, porque o #include do mesmo arquivo acontece apenas uma vez - no primeiro encontro. Depois disso, ele é ignorado.

Esse é um dos motivos pelos quais você teve que criar um arquivo completamente idêntico com um nome diferente aqui.


Mas, em geral, a opção Copiar e Colar está a apenas alguns cliques. Não é necessário entender esse código.

PriceChannel
PriceChannel
  • www.mql5.com
Ценовой канал произвольной длительности (таймфрейм) бара.
 
Yuriy Bykov #:

No terceiro artigo, os parâmetros de entrada ainda não alcançaram os parâmetros de entrada :(. Mas com certeza isso acontecerá.

Sua arquitetura é um pouco diferente da minha, portanto, não forneci ao INPUT_STRUCT muitas coisas que seriam úteis nesse projeto.

É bom que você não o tenha publicado, porque eu o refiz novamente - na versão mais concisa e conveniente (parece ser a versão final).

Acrescentei group, string-inputs e algumas outras pequenas coisas para conveniência futura.

#define  TYPENAME_INPUT StrategyInput

#define  MACROS_MULTI                           \
  INPUT(symbol, string, "EURGBP")              \ // Instrumento de negociação (símbolo)
  INPUT(timeframe, ENUM_TIMEFRAMES, PERIOD_H1) \ // Período do gráfico (timeframe)
  GROUP("=== Opções de gerenciamento de capital") \
  INPUT(fixedLot, double, 0.01)                  // Tamanho das posições abertas (fixo)
#define  TYPENAME_INPUT SimpleVolumesStrategyInput

#define  MACROS_MULTI                           \
  GROUP("=== Parâmetros do sinal de abertura")   \
  INPUT(signalPeriod, int, 13)                 \ // Número de velas para cálculo da média de volume
  INPUT(signalDeviation, double, 0.3)          \ // Desvio relativo da média para a abertura da primeira ordem
  INPUT(signaAddlDeviation, double, 1)         \ // Desvio relativo da média para a abertura da segunda ordem e das ordens subsequentes
  GROUP("=== Parâmetros de pedidos pendentes.")   \
  INPUT(openDistance, int, 0)                  \ // Distância do preço até a ordem pendente
  INPUT(stopLevel, double, 10500)              \ // Stop Loss (em pontos)
  INPUT(takeLevel, double, 465)                \ // Take Profit (em pips)
  INPUT(ordersExpiration, int, 1000)           \ // Tempo de expiração das ordens pendentes (em minutos)
  GROUP("=== Opções de gerenciamento de capital") \
  INPUT(maxCountOfOrders, int, 3)                // Número máximo de ordens abertas simultaneamente


Partes do código do aplicativo para demonstrar como ele é usado.

#define  INPUT_STRUCT_ADDON
#include "Advisor.mqh"
#include "SimpleVolumesStrategy.mqh"
#include "VolumeReceiver.mqh"

input group "=== Parâmetros do conselheiro."
input ulong       magic_              = 27181; // Magic

CAdvisor     *expert;         // Ponteiro para o objeto especialista

//+------------------------------------------------------------------+
//| Função de inicialização de especialista|
//+------------------------------------------------------------------+
int OnInit() {
   expert = new CAdvisor(new CVolumeReceiver(magic_));

   // Adicionar uma instância da estratégia
   expert.Add(new CSimpleVolumesStrategy(inStrategyInput + inSimpleVolumesStrategyInput));

   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Construtor|
//+------------------------------------------------------------------+
CSimpleVolumesStrategy::CSimpleVolumesStrategy( const string sInputs ) : CStrategy(sInputs)
{
   this.Input = sInputs;

   ArrayResize(m_orders, this.Input.maxCountOfOrders);

   // Carregar o indicador para obter volumes de ticks
   iVolumesHandle = iVolumes(this.InputStrategy.symbol, this.InputStrategy.timeframe, VOLUME_TICK);

// Defina o tamanho da matriz receptora de volumes de ticks e o endereçamento necessário
   ArrayResize(volumes, this.Input.signalPeriod);
   ArraySetAsSeries(volumes, true);
}
//+------------------------------------------------------------------+
//|| Construtor|
//+------------------------------------------------------------------+
CStrategy::CStrategy( const string sInputs ) : m_isChanged(false)
{
  this.InputStrategy = sInputs;
}
//+------------------------------------------------------------------+
//| Função de inicialização de especialista|
//+------------------------------------------------------------------+
int OnInit() {
// Verificar se os parâmetros estão corretos
   if(startIndex_ < 0 || startIndex_ + totalStrategies_ > 9) {
      return INIT_PARAMETERS_INCORRECT;
   }

// Criar e preencher uma matriz de instâncias de estratégia
   CStrategy *strategies[9];

   StrategyInput InputBase;
   SimpleVolumesStrategyInput Input;

   InputBase.timeframe = PERIOD_H1;

   // A primeira forma de configuração é por meio da inicialização.
   const StrategyInput InputBase0 = {"EURGBP", PERIOD_H1, NormalizeDouble(0.01 / 0.16 * depoPart_, 2)};
   const SimpleVolumesStrategyInput Input0 = {13, 0.3, 1.0, 0, 10500, 465, 1000, 3};
   strategies[0] = new CSimpleVolumesStrategy(InputBase0 + Input0);

   // A segunda maneira de especificar é por meio de string e array.
   InputBase.fixedLot = NormalizeDouble(0.01 / 0.09 * depoPart_, 2);
   const double Array1[] = {17, 1.7, 0.5, 0, 16500, 220, 1000, 3};
   strategies[1] = new CSimpleVolumesStrategy(InputBase["symbol = EURGBP"] + "," + Input[Array1]);

   // A terceira maneira de especificar é por meio da atribuição de campo.
   InputBase.fixedLot = NormalizeDouble(0.01 / 0.16 * depoPart_, 2);
   InputBase.symbol = "EURGBP";
   const double Array2[] = {51, 0.5, 1.1, 0, 19500, 370, 22000, 3};
   strategies[2] = new CSimpleVolumesStrategy(InputBase + Input[Array2]);
Arquivos anexados:
 
fxsaber #:

É bom que eles não tenham postado, pois eu o refiz novamente, na versão mais concisa e fácil de usar (parece ser a versão final).

Sim, uma situação muito familiar. Tudo parece estar lá, e então você refaz e fica ainda melhor. Acho que essa também não é a versão final, porque você se orientou nos cenários de uso de parâmetros no código que já foram publicados. No que diz respeito à criação de parâmetros em conjuntos e, mais ainda, à criação automática em conjuntos, você provavelmente descobrirá que também pode melhorar/simplificar.

Obrigado!!!