Documentação

Aplicações

Última atualização em 18. 5. 2020 por Mark Fric

Indicador ForceIndex

Vamos adicionar novos indicadores personalizados ao StrategyQuant X. Ao contrário do SQ3, o SQX permite estender o programa criando seus próprios indicadores personalizados e blocos de construção - semelhante a como você pode adicionar novos indicadores às plataformas normais de negociação como MetaTrader 4/5, Tradestation e assim por diante.

Passaremos por este processo passo a passo para explicar tudo o que é necessário.

No final, teremos um novo indicador personalizado adicionado à StrategyQuant e você poderá adicioná-lo à lista de blocos de construção para a geração de estratégias.

Vamos usar Índice de Força indicador um exemplo. Este indicador já está embutido no Metatrader, você pode encontrar seu código fonte aqui: https://www.mql5.com/en/code/8013

Esta é a aparência do indicador no gráfico:

 

Há quatro passos a seguir para adicionar um novo indicador ao SQ X:

  1. Adicionando novo bloco de construção de indicadores
  2. (Opcional, recomendado) Teste de novo indicador no SQ X vs dados da MT
  3. (Opcional, recomendado) Adicionar novo(s) bloco(s) de sinal baseado(s) no indicador
  4. Acréscimo da tradução do bloco Indicador no idioma da plataforma de destino

 

Passo 1 - Criação de novo indicador personalizado no Editor de Código

O primeiro passo é criar nosso indicador no Editor de Código. StrategyQuant usa internamente a linguagem de programação Java, e os indicadores personalizados devem ser programados em Java.

Você não pode pegar seu código MQL e simplesmente copiá-lo e colá-lo para StrategyQuant, ele não funcionaria. Você deve reescrever o indicador na linguagem Java.

Primeiro temos que abrir o Editor de Código:

No Editor de Código você pode criar, editar e modificar trechos, então criaremos um novo trecho para nosso novo indicador.

Uma vez no Editor de Código, clicamos em Criar novo botão na barra de ferramentas superior.

Isto abrirá um diálogo, onde poderemos nomear nosso novo snippet e escolher seu tipo. Nós lhe daremos o nome ".ForceIndex" e escolha Indicador como um tipo de bocadinho.

Depois de clicarmos OK, será criada uma nova pasta ForceIndex em Snippets -> SQ -> Blocos -> Indicadores e um novo arquivo de snippet ForceIndex.java nesta pasta.

A convenção em StrategyQuant é que cada indicador está em sua própria pasta - é porque mais tarde poderemos querer criar sinais para este indicador, e todos os trechos relacionados estarão na mesma pasta.

Esta ação criou um novo arquivo para nosso indicador ForceIndex e o abriu no editor. Você pode ver que o indicador é uma classe e já tem alguma estrutura.

Cada indicador é estendido da classe IndicatorBlock e ele deve implementar um método:

  • EmBarUpdate() - onde o valor do indicador é computado e armazenado em um dos amortecedores de saída. É chamado para cada barra no gráfico.

Quando você verificar o código fonte, você deve notar poucas coisas.

Primeiro, trechos em StrategyQuant usam muito anotações - @Parameter, @Output, @BuildingBlock - estas anotações são usadas para declarar uma propriedade especial de uma determinada variável ou classe - que a variável é um parâmetro público ou valor de saída, ou que a classe é um bloco indicador.

Em segundo lugar, uma vez que você cria e compila um indicador, você pode chamá-lo de outros métodos ou indicadores usando Indicadores.SeuIndicador(YourIndicatorParameters). É assim que nosso novo indicador é chamado no método OnBlockEvaluate().

Vamos percorrer passo a passo o código fonte da classe indicadora padrão criada a partir do modelo:

pacote SQ.Blocos.Indicadores.ForceIndex;
 
import com.strategyquant.lib.*; import com.strategyquant.datalib.*; import com.strategyquant.tradinglib.*;
 
importação SQ.Internal.IndicatorBlock;

esta é a declaração padrão Java de um pacote e importação de classes requeridas - as que usamos em nossa própria classe.

@BuildingBlock(name=""(XXX) ForceIndex ", display="ForceIndex (#Period#)[#Shift#]", returnType = ReturnTypes.Price)
@Help("ForceIndex help text")

Definição anotada de nossa classe indicadora, dizendo ao sistema que se trata de um bloco de construção com nome dado.

  • nome campo é o que é exibido na IU ao escolher os blocos de construção.
  • exibir campo é o que é exibido em Wizard com parâmetros. Você pode controlar quais parâmetros são mostrados e em qual lugar
  • returnType é um tipo de indicador, ele diz que tipo de valor este indicador calcula. Ele é usado para que StrategyQuant saiba quais tipos devem ser comparados com o quê. Por exemplo, ele não compararia CCI (que retorna Número) com Bandas de Bolinger (que retorna Preço).

Existem basicamente três tipos de retorno que um indicador pode ter:

  • Preço - O indicador calcula o preço e é exibido na tabela de preços - como Bandas de Bollinger, Média Móvel, etc.
  • Número - O indicador calcula o número que é exibido em seu próprio gráfico - como CCI, RSI, MACD, etc.
  • Intervalo de preços - indicador calcula a faixa de preços (diferença de dois preços) - como ATR

Outros tipos de retorno são utilizados em outros tipos de blocos de construção.

Em nosso caso, o ForceIndex NÃO é exibido na tabela de preços, portanto, seu tipo de retorno é Número, não Preço. Nós o modificaremos na próxima etapa.

@Parameter Public DataSeries Input;
 
@Parameter(defaultValue = "10", isPeriod = true, minValue=1, maxValue=10000, step=1) public int Period;
 
@Output public DataSeries Value;

o que se segue são parâmetros indicadores. Cada indicador pode ter vários parâmetros de entrada, o modelo cria apenas dois deles como exemplo. Cada parâmetro é anotado com @Parameter anotação, que poderia ter vários atributos.

O primeiro parâmetro é EntradaÉ o conjunto de séries de dados a partir do qual o indicador é calculado - pode ser, por exemplo, Preço Aberto, Alto, Baixo ou Fechado.

O segundo parâmetro é PeríodoOs indicadores geralmente têm algum período no qual são computados.

A terceira variável é Valor, observe que tem anotação diferente @Output. Isto significa que esta variável não é um parâmetro indicador, mas seu buffer de saída. Os indicadores geralmente têm apenas um buffer de saída, mas podem ter mais - por exemplo, a banda Bollinger tem buffer superior e inferior.

Há mais um parâmetro oculto Turno - é por padrão em todos os indicadores e diz ao motor de negociação qual o valor de volta que ele deve procurar. Geralmente não é preciso se preocupar com este parâmetro, ele é usado automaticamente.

Depois há um método:

nulo protegido No BarUpdate() {...}

Este é o método onde os valores indicadores são computados. Ele é chamado internamente pelo SQ para cada barra e deve calcular o valor do indicador para esta barra e salvá-lo no buffer de saída.

Este é o código fonte do modelo de indicador padrão. Na próxima etapa, mostraremos as mudanças que devem ser feitas para implementar nosso indicador ForceIndex.

 

Passo 2 - Modificando o modelo padrão gerado e implementando o acusador

O indicador criado na etapa 1 é um modelo de indicador padrão, ele ainda não computa o ForceIndex . Para implementar o ForceIndex, devemos fazer algumas coisas:

 

Atualizar sua anotação @BuildingBlocks

Atualizaremos a anotação deste indicador da seguinte forma:

@BuildingBlock(name="(FI) ForceIndex ", display="ForceIndex (#Nbr_Periods#, #Multiplier)[#Shift#]", returnType = ReturnTypes.Number)

Esta é a parte mais simples. Vamos apenas atualizar nome do indicador e adicionar os novos parâmetros reais (ver abaixo) ao exibir atributo.

Também mudamos o ReturnType para Number, porque este indicador calcula os números exibidos em um gráfico separado, não produz algum valor de preço.

 

Definir parâmetros ForceIndex

A primeira coisa a fazer é pouco complicada - devemos mudar o tipo de padrão Entrada parâmetro. No modelo padrão ele é definido da seguinte forma:

@Parameter Public DataSeries Input;

é um parâmetro chamado Entradacom tipo Série DataSeries. Isto é válido para uma grande parte dos indicadores que são computados a partir de apenas um preço. Por exemplo, os indicadores CCI, RSI, etc. são geralmente computados a partir de Close price. Você pode configurá-los para serem computados a partir de preços diferentes, por exemplo, a partir de preço Aberto, mas ainda assim é apenas uma matriz de preços.

O tipo DataSeries é um conjunto de valores tipo que contém valores para preços Fechados, ou para preços Abertos, ou para preços Típicos, etc.
Entretanto, se você olhar o código fonte do ForceIndex MQL, verá que ele calcula seus valores a partir de um dos valores de preço e a partir do Volume.

Para poder acessar várias matrizes de preços de uma só vez, usaremos tipos diferentes para a produção:

@Parameter Public ChartData Chart;


ChartData
tipo é um objeto que representa todo o gráfico - você terá acesso aos preços Aberto, Alto, Baixo, Fechado, Volume no gráfico dado.


Nota rápida - escolha o tipo certo para a variável de dados de entrada :
Se o indicador for calculado a partir de um preço, use a série DataSeries.
Se for calculado a partir de múltiplos preços - por exemplo, Alto, Baixo, Fechado, etc. - use ChartData.

Depois há um parâmetro Período, podemos deixá-lo inalterado também:

@Parameter(defaultValue="10", isPeriod=true, minValue=2, maxValue=1000, step=1) public int Period; 

O terceiro parâmetro é o método da média móvel:

@Parameter(name="Method", defaultValue="0") @Editor(type=Editors.Selection, values="Simple=0,Exponential=1,Smoothed=2,Linear weighted=3") public int MAMethod;

Isto é um pouco mais complexo, porque definimos uma lista de seleção (controle de caixa combinada) como controle de edição deste parâmetro. Assim, ao editar no Wizard, o usuário poderá escolher entre os valores pré-definidos.

O último parâmetro é o preço aplicado - preço que deve ser usado no cálculo da média móvel:

@Parameter(defaultValue="0") @Editor(type=Editors.Selection, values="Close=0,Open=1,High=2,Low=3,Median=4,Typical=5,Weighted=6") public int Applied Price;

Note que usamos alguns atributos no @Parameter anotação:

  • defaultValue define o valor padrão deste parâmetro
  • isPeriodo=true diz à SQ que este parâmetro é um período - eles são tratados de forma especial, na configuração do Builder você pode configurar o valor mínimo e máximo para períodos, portanto a SQ precisa saber quais parâmetros são períodos.
  • minValor, maxValor, passo são valores mínimos e máximos que serão gerados para este parâmetro durante o processo de geração aleatória.

Definir as saídas ForceIndex

O indicador ForceIndex tem apenas uma saída, portanto, podemos deixá-lo também inalterado:

@Output public DataSeries Value;

A anotação @Output significa que este é um buffer de saída para este indicador. Note que é do tipo DataSeries, o que significa que é uma matriz de valores duplos.

Implementar o método OnBarUpdate()

Se você olhar o código MQL da ForceIndex, verá que ele é bastante simples, seu código MQL é:

int start() {
  int nLimit;
  int nCountedBars=IndicatorCounted();

  //---- dados insuficientes
  if(BarsExtForcePeriod) nCountedBars--;
  nLimit=Bars-nCountedBars;

  //---- Índice de força contada
  for(int i=0; i<nLimit; i++)
    ExtForceBuffer[i] = Volume[i] * (iMA(NULL,0,ExtForcePeriod,0,ExtForceMAMethod,ExtForceMethod,i+1)) - iMA(NULL,0,ExtForcePeriod,0,ExtForceMAMethod,ExtForceMethod,i+1))

  //---- feito
  retorno(0);
}

Analisando o algoritmo, podemos ver que o valor do Índice de Força em determinada vela é computado como:

ForceIndex[i] = Volume[i] *(MovAvg(Período, MAMethod, Preço Aplicado)[i] - MovAvg(Período, MAMethod, Preço Aplicado)
[i+1]

 

Podemos implementá-lo em Java desta forma:

vazio protegido Na BarUpdate() lança a TradingException {
    DataSeries computedFrom = Chart.getSeries(AppliedPrice);
 
    valor.indiValor duplo = Chart.Volume.get(0) * (Indicadores.MA(computadosDe, Período, Método MAM).Valor.get(0) - Indicadores.MA(computadosDe, Período, Método MAM).Valor.get(1))
 
    Valor.set(0, valor indireto);
} 

Neste caso, o indicador é bastante simples e seu cálculo requer praticamente apenas uma linha em StrategyQuant.

Primeiro obtemos o preço para calcular o indicador a partir de - chamando Chart.getSeries(Preço Aplicado).
Em seguida, calculamos o novo valor indicador como uma diferença da média do valor do preço atual e do valor do preço anterior multiplicado pelo volume atual.

 

Isso é tudo, agora que atingimos Compilação e depois reiniciar o SQ, veremos nosso novo indicador ForceIndex na seção Sinais de Indicadores Aleatórios.

Código fonte completo de nosso novo indicador:

pacote SQ.Blocos.Indicadores.ForceIndex;

import com.strategyquant.lib.*;
import com.strategyquant.datalib.*;
import com.strategyquant.tradinglib.*;

importação SQ.Internal.IndicatorBlock;

/**
 * Nome do indicador como será exibido na IU, e seu tipo de retorno.
 * Possíveis tipos de retorno:
 * Tipos de retorno. Preço - indicador é desenhado na tabela de preços, como SMA, Bandas de Bollinger, etc.
 * ReturnTypes.Price - indicador é desenhado em tabela separada, como CCI, RSI, MACD
 * ReturnTypes.PriceRange - indicador é a faixa de preços, como ATR.
 */
@BuildingBlock(name=""(FI) ForceIndex ", display="ForceIndex (#Period#)[#Shift#]", returnType = ReturnTypes.Number)
@Help("ForceIndex help text")
classe pública ForceIndex estende IndicatorBlock {

  @Parameter
  gráfico público Gráfico de dados;

  @Parameter(defaultValue="10", isPeriod = true, minValue=2, maxValue=1000, step=1)
  período de intenção pública;

  @Parameter(name="Method", defaultValue="0")
  @Editor(tipo=Editores.Seleção, valores="Simples=0,Exponencial=1,Alisado=2,Linear ponderado=3")
  público no MAMethod;

  @Parameter(defaultValue="0")
  @Editor(tipo=Editores.Seleção, valores="Fechado=0,Aberto=1,Alto=2,Baixo=3,Mediana=4,Típico=5,Ponderado=6")
  público int. Preço aplicado;

  @Output
  valor público da DataSeries;

  //------------------------------------------------------------------------
  //------------------------------------------------------------------------
  //------------------------------------------------------------------------

  /**
   * Este método é chamado em cada atualização de barra e aqui o valor do indicador é computado.
   *
   * Ao contrário do MT4, você não computa valores indicadores para barras múltiplas em um loop,
   * você precisa computar o valor somente para a última barra (atual).
   * O motor de negociação se encarregará de chamar este método para cada barra no gráfico.
   *
   * A barra real para a qual o valor do indicador é calculado é armazenada na variável Barra de Corrente.
   * Se 0, significa que é a primeira barra do gráfico.
   */
  @Override
  vazio protegido Na BarUpdate() lança a TradingException {
    	duplo valor indiVal;

    	valor.ind = Gráfico.Volume.get(0) * (Indicadores.MA(Gráfico.Fechar, Período, MAMétodo).Valor.get(0) - Indicadores.MA(Gráfico.Fechar, Período, MAMétodo).Valor.get(1))

      	Valor.set(0, valor indireto);
  }

}

Este artigo foi útil? O artigo foi útil O artigo não foi útil

Assine
Notificação de
5 Comentários
Mais antigo
Novidades Mais Votados
Feedbacks em linha
Ver todos os comentários
Pieter Kotzee
Pieter Kotzee
21. 6. 2020 8:56 am

Olá. Copiei o código exatamente como indicado acima, mas recebo 2 erros ao tentar compilar. Ambos estão na linha 55 e ambos têm a mesma descrição. Uma é a coluna 54 e a outra é a 114:
não encontra símbolo: método MA(com.strategyquant.datalib.Dataseries,int,int) localização: variável Indicadores do tipo SQ>Internal.Indicators
 

Última edição 3 anos atrás por Pieter Kotzee
tomas262
tomas262
Responder a  Pieter Kotzee
29. 6. 2020 10:06 pm

O método MA não faz parte do pacote. Por favor, encontre-o aqui https://strategyquant.com/codebase/forceindex/

Emmanuel2
21. 9. 2021 7:37 pm

Muito obrigado, este exemplo está ajudando muito

Matthew Nowlis
Matthew Nowlis
26. 2. 2022 7:09 pm

Consegui adicionar com sucesso o código java para o indicador do Índice de Força e os blocos de sinal. Ele se compila com sucesso sem erros. Entretanto, quando eu gero estratégias em StrategyQuant com o indicador, recebo um erro porque faltam os modelos de código (MT4, MT5, pseudocódigo, etc.). Ele diz no código de estratégia:

Erro! Um ou mais blocos nos quais a estratégia não é implementada (MT4, MT5, pseudocódigo, etc.)

A inclusão do modelo falhou (para valor do parâmetro "blocks/ForceIndex.tpl"):
Modelo não encontrado para nome "PseudoCode/blocks/ForceIndex.tpl".
O nome foi interpretado por este TemplateLoader: MultiTemplateLoader(loader1 = FileTemplateLoader(baseDir="C: Código de estratégiaQuantXextensão interna"), loader2 = FileTemplateLoader(baseDir="C: Código de usuário da estratégiaQuantXextender")).

—-
FTL stack trace (“~” significa relacionado ao nestingo):
    - Falha em: #incluindo "blocos/" + BlockKey + ".tpl".  [em modelo "PseudoCode/pseudoBlocks.inc" em macro "printBlock" na fila 122, coluna 20]
    - Alcançado através: @printBlock block?crianças[0], turno [em modelo "PseudoCode/pseudoBlocks.inc" em macro "printBlock" na fila 107, coluna 9]
    - Alcançado através: @printBlock c, turno [em modelo "PseudoCode/pseudoBlocks.inc" em macro "printBlockChild" na fila 148, coluna 14]
    - Alcançado através: @printBlockChild block, "#Left#"  [em modelo "PseudoCódigo/blocos/IsGreater.tpl" na fila 1, coluna 2]
    - Alcançado através de: #incluindo "blocos/" + BlockKey + ".tpl".  [em modelo "PseudoCode/pseudoBlocks.inc" em macro "printBlock" na fila 122, coluna 20]
    - Alcançado através: @printBlock block?crianças[0], turno [em modelo "PseudoCode/pseudoBlocks.inc" em macro "printBlock" na fila 107, coluna 9]
    - Alcançado através: @printBlock bloco [em modelo "PseudoCódigo/blocos/AND.tpl" na fila 5, coluna 38]
    - Alcançado através de: #incluindo "blocos/" + BlockKey + ".tpl".  [em modelo "PseudoCode/pseudoBlocks.inc" em macro "printBlock" na fila 122, coluna 20]
    - Alcançado através: @printBlock block?crianças[0], turno [em modelo "PseudoCode/pseudoBlocks.inc" em macro "printBlock" na fila 107, coluna 9]
    ... (Tinha 18 mais, escondido para tersenes) (Escondido 4 “~” linhas para concisão)

Como adicionar os modelos de código para os respectivos idiomas de código de estratégia?

tomas262
Admin
Responder a  Matthew Nowlis
28. 2. 2022 1:53 pm

Você pode tentar importar o pacote a partir desta página em vez https://strategyquant.com/codebase/forceindex/

O pseudo-código e o MT4 são implementados e funcionam para mim quando testados