![Contratos futuros contínuos em MetaTrader 5](https://c.mql5.com/i/articles/overlay.png)
Contratos futuros contínuos em MetaTrader 5
Introdução
O trader não pode criar seus próprios gráficos em MetaTrader 5, pois somente podem ser construídos com os ativos da corretora. O trader necessita de um produto sintético - os contratos futuros contínuos. O problema é que somente a corretora pode fazer emendas de contratos e somente a corretora decide se vai ligar os contratos futuros sobre o símbolo dado.
Felizmente, o histórico dos futuros fechados está sempre disponível no terminal. Use este histórico para emendar os contratos futuros no terminal.
Convenções:
- Todos os dados, desenhos e imagens no artigo baseiam-se no contrato futuro real do índice de Ações Ucraniana.
- Seções de código substituídos ou adicionados no artigo serão marcado com cores.Por exemplo:
//+------------------------------------------------------------------+ //| This is an example | //| of the edited code | //+------------------------------------------------------------------+
O primeiro problema: sobrepor dados
Os contratos futuros próximos são negociados com datas sobrepostas,
isso significa que o futuro é colocado em negociação enquanto outros futuros ainda tem dois meses para serem fechados.
Fig. 1. Datas se sobrepõem em contratos de futuros
A figura mostra que 09.16.2013 é a data de início da negociação do contrato futuro UX-3.14, embora o contrato futuro UX-12.13 ainda está em aberto.
O segundo problema: escolher a forma de emendar
Existem dois métodos de emendar:
- A adição simples – quando a data de circulação do instrumento em vigor expira e o próximo instrumento é aberto em outra barra. Os preços durante a adição simples no gráfico irão coincidir com seus valores do histórico, mas ao mesmo tempo sempre haverá gaps de preços nos lugares emendados, ou seja, o gráfico não será suave.
Fig. 2. Emendando. Adição simples
- adição com deslocamento: o instrumento em vigor tem entre 5 a 10 dias antes de ser fechado, então começamos a substituir essas 5-10 barras com as próximas barras do instrumento. O intervalo de 5-10 barras é chamado de período de transição. Os preços durante a adição com deslocamento irão mostrar valores errados (que não correspondem ao atual instrumento), mas o gráfico será mais suave em comparação com o método de adição simples.
Fig. 3. Emendando. Adição com deslocamento
Configurações no terminal
O contrato futuro deve ser colocado em ordem descendente:
Fig. 4. Observação do mercado
Escrevendo um indicador
O indicador padrão deve ser colocado na pasta "indicators" no seguinte caminho de diretório: terminal_data_folder\MQL5\Indicators. Criar a pasta Synthetics em MyIndicators (que você vai abrir na pasta \Indicators). Permitirá que você salve o espaço na pasta \Indicators na Biblioteca Padrão (Standard Library) e facilitará o lançamento sincronizado dos indicadores na seção Armazenamento MQL5. O caminho final da pastas fica assim: terminal_data_folder\MQL5\Indicators\MyIndicators\Synthetics.
Na pasta Synthetics criamos um novo arquivo:
Fig. 5. O novo arquivo criado do indicador
Defina o novo tipo de arquivo - "Indicador Personalizado":
Fig. 6. Defina o novo tipo de arquivo - "indicador personalizado"
Pressione o botão "Avançar" e abra a janela "propriedades gerais do indicador personalizado". Digite o nome do indicador - "SYNT", adicione dois parâmetros O primeiro parâmetro "Number_futures_gluing" (Número de futuros para colagem) determina o número de instrumentos a serem conectados. Note que 2 é o menor valor possível de "Number_futures_for_gluing". A segunda opção "Gluing type" (Tipo de colagem) determina o tipo de emenda no indicador padrão - "simple addition"(adição simples):
Fig. 7. Os parâmetros do indicador personalizado
Preste atenção para a opção "Gluing type": a emenda pode ser "simples adição" ou "adição com deslocamento". Nesta fase você não pode adicionar na lista os dois tipos de emenda. É por isso que deixamos a "simples adição" como padrão. Durante o processo de escrever o código do indicador "SYNT", mais tarde será ativada a opção para ver a lista dropdown (suspensa) com os tipos de emendas.
Na janela seguinte, selecione os handlers (manipuladores) dos eventos do indicador:
Fig. 8. Os handlers de eventos do indicador
Note que a função OnTimer() será usada pelo indicador "SYNT". A principal funcionalidade do indicador situa-se no OnTimer() . O indicador pode ser anexado ao gráfico do ativo com o trade finalizado (este ativo não incluirá o evento OnCalculate) ou com o gráfico do ativo com um trade em andamento.
Pressione o botão "Avançar" e nas "Propriedades gerais do programa indicador personalizado" assinale "Indicador em janela separada":
Fig. 9. opção "indicador em janela separada"
Pressione o botão "Concluído" e você vai ver o modelo do indicador "SYNT".
Organizar a lista dropdown (suspensa)
Para ver os tipos de emendas como uma lista suspensa você precisa declarar a enumeração ENUM_GLUING_TYPE nas opções dos indicadores.
Declarar enumeração na área global no início do bloco dos parâmetros de entrada:
#property indicator_separate_window //+------------------------------------------------------------------+ //| Splicing types enumeration | //+------------------------------------------------------------------+ enum ENUM_GLUING_TYPE { simple_addition, // simple addition||simple addition addition_with_shift // addition with shift||addition with shift }; //--- input parameters || input parameters input ENUM_GLUING_TYPE gluing_type=simple_addition; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+
Agora você pode verificar como a lista suspensa é exibida.
Você deve compilar o arquivo do indicador (F7). Agora, depois de ter anexado o indicador, você pode ver as opções da lista suspensa:
Fig. 10. Agora você tem a
lista dropdown nos parâmetros
Adicionar a descrição do indicador que será exibido na guia "Geral" quando for anexado ao gráfico pela primeira vez ou quando as suas propriedades forem alteradas:
#property version "1.00" //+------------------------------------------------------------------+ //| version "1.00": The timer history swapping | //+------------------------------------------------------------------+ #property description "Indicator for several futures splicing." #property description "Is drawn in the latest futures window" #property description "Uses N first symbols for drawing" #property description "which were taken from the \"Market review\"." #property indicator_separate_window
O método de construção do indicador - DRAW_COLOR_CANDLES - candles coloridos.
Você precisa de 4 buffers para o indicador e um buffer para o índice de armazenamento de cor. O estilo de linha do indicador - STYLE_SOLID - linha contínua. Mostrar tudo no código do indicador:
#property description "taken from the \"Market review\"." //--- indicator settings || indicator settings #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 1 //--- plot Bars || bars plotting #property indicator_label1 "SYNT" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //+------------------------------------------------------------------+ //| enumeration of splicing methods | //+------------------------------------------------------------------+
Digite o parâmetro de entrada "number_futures_gluing" - o número de instrumentos necessários para a construção. O valor padrão do "number_futures_gluing" é igual a 2:
//--- input parameters || input parameters input int numder_futures_gluing=2; input ENUM_GLUING_TYPE gluing_type=simple_addition;
Declarar os 4 buffers para o indicador, um buffer para o índice de armazenamento de cor e um array auxiliar LoadHistory[].
#property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- indicator buffers || indicator buffers double OpenBuffer[]; double HighBuffer[]; double LowBuffer[]; double CloseBuffer[]; double ColorCandlesColors[]; double LoadHistory[]; //+------------------------------------------------------------------+ //| enumeration of splicing methods | //+------------------------------------------------------------------+
Anexar os buffers do indicador aos arrays dinâmicos de uma dimensão, definir a indexação dos buffers como nas timeseries:
//--- indicator buffers mapping //--- indicator buffers mapping SetIndexBuffer(0,OpenBuffer,INDICATOR_DATA); SetIndexBuffer(1,HighBuffer,INDICATOR_DATA); SetIndexBuffer(2,LowBuffer,INDICATOR_DATA); SetIndexBuffer(3,CloseBuffer,INDICATOR_DATA); SetIndexBuffer(4,ColorCandlesColors,INDICATOR_COLOR_INDEX); SetIndexBuffer(5,LoadHistory,INDICATOR_CALCULATIONS); //--- set buffer indexing as timeseries //--- set buffer indexing as in timeseries ArraySetAsSeries(OpenBuffer,true); ArraySetAsSeries(HighBuffer,true); ArraySetAsSeries(LowBuffer,true); ArraySetAsSeries(CloseBuffer,true); ArraySetAsSeries(ColorCandlesColors,true); //--- return(INIT_SUCCEEDED);
Para exibir o nome das séries do indicador ("Open", "High", "Low" e "Close") na "janela de dados" é necessário a variável s_symbol:
input int numder_futures_gluing=2; input ENUM_GLUING_TYPE gluing_type=simple_addition; //--- symbol name string s_symbol; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+
Para ativar o indicador você precisa da variável shft_array e duas flags, good_history e indicator_rendered:
input ENUM_GLUING_TYPE gluing_type=simple_addition; //--- symbol name string s_symbol; int shift_array=0; bool good_history=false; //history is not prepared||history not prepared bool indicator_rendered=false; // indicator is not drawn //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+
Em seguida, configure o indicador e conecte o buffer do índice de cor para a cor escolhida:
ArraySetAsSeries(CloseBuffer,true); ArraySetAsSeries(ColorCandlesColors,true); //--- set accuracy || accuracy of the indicator values IndicatorSetInteger(INDICATOR_DIGITS,0); //--- set drawing line empty value || empty value of the drawing line PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); //--- set labels for the line || displayed name in the DataWindow PlotIndexSetString(0,PLOT_LABEL,s_symbol+" Open;"+s_symbol+" High;"+s_symbol+" Low;"+s_symbol+" Close"); IndicatorSetString(INDICATOR_SHORTNAME,"SYNT"); //--- set number of colors in color buffer || number of colors in the buffer PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,9); //--- set line color || set the line color PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,clrBlue); PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrOrange); PlotIndexSetInteger(0,PLOT_LINE_COLOR,2,clrRed); PlotIndexSetInteger(0,PLOT_LINE_COLOR,3,clrGreen); PlotIndexSetInteger(0,PLOT_LINE_COLOR,4,clrPink); PlotIndexSetInteger(0,PLOT_LINE_COLOR,5,clrIndigo); PlotIndexSetInteger(0,PLOT_LINE_COLOR,6,clrPaleVioletRed); PlotIndexSetInteger(0,PLOT_LINE_COLOR,7,clrDarkViolet); PlotIndexSetInteger(0,PLOT_LINE_COLOR,8,clrDimGray); //--- return(INIT_SUCCEEDED);
Adicionar a inicialização do temporizador com intervalos de 3 segundos e o gerador de números aleatórios na função OnInit() :
PlotIndexSetInteger(0,PLOT_LINE_COLOR,7,clrDarkViolet); PlotIndexSetInteger(0,PLOT_LINE_COLOR,8,clrDimGray); //--- EventSetTimer(3); //--- random number generator initializor MathSrand(GetTickCount()); //--- return(INIT_SUCCEEDED);
É necessário pelo menos dois símbolos (ativos) para processar a emenda.
Verifique o número de instrumentos (ativos) para emendar na função OnCalculate():
const long &tick_volume[], const long &volume[], const int &spread[]) { //--- checking the number of instruments || checking the number of instruments if(numder_futures_gluing<=1) { //--- create the message line string comm=StringFormat("For the indicator choose not less than %d symbols",numder_futures_gluing); //--- display the message in comment in the chart main window Comment(comm); return(0); } //--- return value of prev_calculated for next call return(rates_total);
Depois de ter verificado o número de ativos para a emenda, verificar se o indicador já foi desenhado. Se o indicador foi desenhado, então você pode sair do OnCalculate() :
Comment(comm); return(0); } if(indicator_rendered==true) return(rates_total); //--- return value of prev_calculated for next call return(rates_total);
Como o indicador "SYNT" é usado principalmente para analisar a tendência de desenvolvimento de barras diárias, considero que não há necessidade de proceder novos cálculos em cada tick. Não haverá cálculos do indicador "SYNT" a cada tick.
Você precisa calcular o indicador apenas nos seguintes casos:
- Se o indicador foi lançado pela primeira vez;
- se o histórico foi alterado (por exemplo, se houveram adições).
if(indicator_rendered==true) return(rates_total); //--- if calculations were started the first time //--- or if we need to calculate the indicator for two or more bars (changes in history) //--- remember, that the "0" bar - is the left-most if(prev_calculated==0 || rates_total>prev_calculated+1) { } //--- return value of prev_calculated for next call return(rates_total);
Inicialização forçada dos buffers do indicador
Os buffers do indicador "SYNT" são conectados nos arrays dinâmicos
Quando o indicador é lançado pela primeira vez, os buffers são inicializados forçadamente. Prosseguir com a inicialização no OnCalculate(). Por que você precisa conduzir-lo no OnCalculate() e não no OnInit? A explicação está na figura abaixo:
Fig. 11. A inicialização do array no OnCalculate()
Como você pode ver na Fig.11, o evento OnCalculate() irá ocorrer em qualquer caso, enquanto que o OnInit() é ativado quando você faz a atualização do gráfico por meio do comando "Update". Portanto, a inicialização dos arrays serão conduzidas no OnCalculate():
//--- remember, that the "0" bar - is the left-most if(prev_calculated==0 || rates_total>prev_calculated+1) { //--- arrays initialization ArrayInitialize(OpenBuffer,0); ArrayInitialize(HighBuffer,0); ArrayInitialize(LowBuffer,0); ArrayInitialize(CloseBuffer,0); } //--- return value of prev_calculated for next call return(rates_total);
A função ArrayInitialize() inicializa o buffer do indicador Neste caso a inicialização mostra zeros.
Se você tentar inicializar o indicador de buffer pelo EMPTY_VALUE , você não poderá emendar os indicadores sobre o "SYNT".
Algoritmo da Adição simples
Fig. 12. Algoritmo da Adição simples
As datas na imagem são o início e fim da circulação dos contratos futuros UX-9.13, UX-12.13 e UX-3.14. Estes dados são apresentados na tabela:
Símbolo (Ativo) | Início da circulação | Final da circulação |
---|---|---|
UX-9.13 | 03.15.2013 | 09.16.2013 |
UX-12.13 | 06.17.2013 | 12.16.2013 |
UX-3.14 | 09.16.2013 | 03.17.2014 |
Na Fig. 10, data 12.25.2013 - é uma data do calendário real. O ativo UX-3.14 ainda é válido.
O método de emenda "Adição Simples" será implementado na função SimpleAddition:
//+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { //--- } //+------------------------------------------------------------------+ //| Simple addition | //| Simple addition. Add in the indicator array | //| sibmUP symbol | //+------------------------------------------------------------------+ bool SimpleAddition(string simbUP,string simbDOWN,ENUM_TIMEFRAMES period,int Color) { } //+------------------------------------------------------------------+
simbUP é o contrato futuro de alta, simbDOWN é contrato futuro de baixa, ambos estão localizados na janela de "Análise do mercado". Color - cor usada para desenhar os contratos futuros.
O código completo da função SimpleAddition() é descrita abaixo:
//+------------------------------------------------------------------+ //| Simple addition | //| Simple addition. Add in the indicator array | //| sibmUP symbol | //+------------------------------------------------------------------+ bool SimpleAddition(string simbUP,string simbDOWN,ENUM_TIMEFRAMES period,int Color)////// { datetime expiration_time_UP; // simbUP symbol expiration date datetime expiration_time_DOWN; // simbDOWN expiration date expiration_time_UP=int(SymbolInfoInteger(simbUP,SYMBOL_EXPIRATION_TIME)); if(expiration_time_UP>TimeLocal()) { expiration_time_UP=TimeLocal(); } if(simbDOWN!="") { expiration_time_DOWN=int(SymbolInfoInteger(simbDOWN,SYMBOL_EXPIRATION_TIME)); } else { expiration_time_DOWN=int(SymbolInfoInteger(simbUP,SYMBOL_START_TIME)); } //--- Open, High, Low and Close prices will be copied in the rates[] array MqlRates rates[]; ArraySetAsSeries(rates,true); int copied=0; //--- copied number copied=CopyRates(simbUP,period,expiration_time_DOWN,expiration_time_UP,rates); if(copied>0) { for(int j=shift_array;j<shift_array+copied;j++) { //--- write prices in buffers OpenBuffer[j]=rates[j-shift_array].open; HighBuffer[j]=rates[j-shift_array].high; LowBuffer[j]=rates[j-shift_array].low; CloseBuffer[j]=rates[j-shift_array].close; ColorCandlesColors[j]=Color; } shift_array=shift_array+copied; indicator_rendered=true; ChartRedraw(); } else { Print("Unable to get the symbol history data",simbUP); indicator_rendered=false; return(false); } //--- Simple addition end return(true); } //+------------------------------------------------------------------+
Algoritmo da Adição com deslocamento
Fig. 13. Algoritmo da emenda Adição com deslocamento
Este algoritmo de emenda em comparação com a adição simples, começa 10 dias antes fechar o ativo. O método de emenda "Adição com deslocamento" é processado na função AdditionWithShift():
//--- Simple addition end return(true); } //+------------------------------------------------------------------+ //| Addition With Shift | //| Addition with Shift. Add in the indicator array only | //| sibmUP symbol | //+------------------------------------------------------------------+ bool AdditionWithShift(string simbUP,string simbDOWN,ENUM_TIMEFRAMES period,int Color) { //--- return(true); } //+------------------------------------------------------------------+
A diferença entre as funções AdditionWithShift() e SimpleAddition() está em duas linhas - vai subtrair 10 dias a contar das datas:
. . . expiration_time_UP=int(SymbolInfoInteger(simbUP,SYMBOL_EXPIRATION_TIME))-86400*10; . . . expiration_time_DOWN=int(SymbolInfoInteger(simbDOWN,SYMBOL_EXPIRATION_TIME))-86400*10; . . .
Devido à pequena diferença de códigos, não vou mostrar o código completo da função AdditionWithShift(), você pode encontrar o código no arquivo do indicador no artigo.
Apesar das diferenças entre as funções AdditionWithShift() e SimpleAddition(), é melhor você não uni-las para fazer uma função universal (no caso de novas mudanças no algoritmo ou, por exemplo, executando testes).
Histórico do pré-carregamento dos ativos
A função CheckLoadHistory() copia todo o histórico dos símbolos no buffer auxiliar tmp_rates.
Se o processo de cópia for bem sucedido, o valor true é atribuído a flag good_history, significando que se pode começar a desenhar o indicador:
//--- Addition With Shift end return(true); } //+------------------------------------------------------------------+ //| Request to receive all history from a trade server | //| Request to recieve all history from a trade server | //+------------------------------------------------------------------+ bool CheckLoadHistory(string symbol,ENUM_TIMEFRAMES period) { MqlRates tmp_rates[]; // the Open, High, Low and Close prices will be copied in the rates[]array datetime start_time; // start time of the instrument trades datetime expiration_time; // expiration time of the instrument trade start_time=int(SymbolInfoInteger(symbol,SYMBOL_START_TIME)); expiration_time=int(SymbolInfoInteger(symbol,SYMBOL_EXPIRATION_TIME)); if(CopyRates(symbol,period,start_time,expiration_time,tmp_rates)>0) { good_history=true; } else { good_history=false; } //--- return(true); } //+------------------------------------------------------------------+
Você pode copiar todo o histórico dos contratos futuros, onde o histórico copiado não ocupará muito espaço.
OnTimer - a função principal do indicador
Agora você tem o código para dois métodos de emendas e o código para carregar o histórico de modo que você pode mudar a função OnTimer():
//+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { if(indicator_rendered==true) return; if(good_history==true) { int t=0; // color || color int number; switch(gluing_type) { case simple_addition: for(int n=0;n<numder_futures_gluing;n++) { //--- get the random number number=MathRand(); //--- get the color index as the modulo t=number%(PlotIndexGetInteger(0,PLOT_COLOR_INDEXES)-1); SimpleAddition(SymbolName(n,true),SymbolName(n+1,true),PERIOD_D1,t); } break; case addition_with_shift: for(int n=0;n<numder_futures_gluing;n++) { //--- get random number number=MathRand(); //--- get the color index as the modulo t=number%(PlotIndexGetInteger(0,PLOT_COLOR_INDEXES)-1); AdditionWithShift(SymbolName(n,true),SymbolName(n+1,true),PERIOD_D1,t); } break; } } else { for(int n=0;n<numder_futures_gluing;n++) { CheckLoadHistory(SymbolName(n,true),PERIOD_D1); } } } //+------------------------------------------------------------------+
O indicador esta concluído. Você pode compilar e anexar ao gráfico. É melhor escolher o ativo com o negócio fechado e definir o período em H1.
Saída inicial do indicador "SYNT"
Depois de ter anexado os dois modelos de indicadores "SYNT" de diferentes métodos de emenda ao gráfico, você pode comparar esses métodos:
Fig. 14. Comparando os dois métodos de emendas de contratos futuros
A possibilidade de juntar indicadores (padrão e personalizado)
Indicadores personalizados podem ser emendados com a primeira chamada OnCalculate e o indicador "SYNT":
int OnCalculate (const int rates_total, // size of the array price[] const int prev_calculated, // calculated bars during the previous call const int begin, // tangible data starting point const double& price[] // calculation array );
Na janela "Navegador" abra a lista "Indicadores personalizados". Em seguida, abra a lista de "Exemplos", escolha e coloque o indicador "SYNT" no ativo. Na aba "Parâmetros", escolha "Dados do indicador anterior" na lista suspensa.
Aqui está a lista com os indicadores que você pode emendar no indicador "SYNT" que será executado sem erros.
- AMA (Adaptive Moving Average);
- BB (Bollinger Bands);
- Custom Moving Average;
- DEMA (Double Exponential Moving Average);
- FrAMA (Fractal Adaptive Moving Average);
- TEMA (Triple Exponential Moving Average).
O indicador "SYNT" emendando três contratos futuros com o indicador Custom Moving Average anexado:
Fig. 15. Um exemplo de três ativos emendados
Conclusão
É mais fácil analisar o comportamento dos ativos mais antigos no gráfico aberto dentro do timeframe diário. Embora o número de indicadores técnicos é restrito, este método ajuda a traçar o comportamento dos preços nos contratos futuros contínuos.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/802
![SQL e MQL5: Trabalhando com Banco de Dados SQLite](https://c.mql5.com/2/0/MQL5_SQLite_avatar.png)
![Trabalhando com modem GSM a partir de um Expert Advisor MQL5](https://c.mql5.com/2/0/P2090169__.png)
![Contos de Robôs de Negociação: É Mais ou Menos?](https://c.mql5.com/2/0/tales.png)
![Indicador para gráfico Renko](https://c.mql5.com/2/0/LOGO__2.png)
![MQL5 - Linguagem para estratégias de negociação inseridas no terminal do cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso