
Contratti future continui in MetaTrader 5
Introduzione
Il trader non può creare i propri grafici in MetaTrader 5 poiché il grafico può essere costruito solo con i simboli del broker. Il trader richiede un prodotto sintetico: il contratto future continuo. Il problema è che solo un broker può effettuare lo splicing dei contratti e solo il broker decide se collegherà i future sul dato simbolo.
Fortunatamente, la cronologia dei future chiusi è sempre disponibile nel terminale. Usa questa cronologia per unire i contratti future nel terminale.
Convenzioni:
- Tutti i dati, i disegni e gli screenshot nell'articolo si basano sui reali future dell'indice azionario ucraino.
- Le sezioni di codice sostituite o aggiunte nell'articolo verranno contrassegnate con un colore. Per esempio:
//+------------------------------------------------------------------+ //| This is an example | //| of the edited code | //+------------------------------------------------------------------+
Il primo problema: le date si sovrappongono
I future vicini vengono negoziati con date che si sovrappongono.
Significa che il future viene messo in negoziazione mentre un altro future ha ancora due mesi da chiudere.
Fig. 1. Le date si sovrappongono nei contratti future
La figura mostra che 2013.09.16 è la data di inizio del trading di future UX-3.14, sebbene i future UX-12.13 siano ancora aperti.
Il secondo problema: scegliere il metodo di splicing
Esistono due metodi di splicing:
- La semplice aggiunta – quando la data di circolazione dello strumento corrente è scaduta e lo strumento successivo viene aperto in un'altra barra. Durante la semplice aggiunta i prezzi sul grafico corrisponderanno ai loro valori storici, ma allo stesso tempo ci saranno sempre dei gap di prezzo nei punti di splicing, cioè il grafico non sarà liscio.
Fig. 2. Splicing. Semplice aggiunta
- aggiunta con shift: lo strumento attuale ha 5-10 giorni prima di essere chiuso e cominciamo a sostituire queste 5-10 barre con le prossime barre dello strumento. L'intervallo di 5-10 barre è chiamato periodo di transizione. Durante l'addizione con shift i prezzi mostreranno valori errati (non corrisponderanno allo strumento corrente) ma rispetto al metodo di addizione semplice, il grafico risulterà più fluido.
Fig. 3. Splicing. Addizione con spostamento
Impostazioni nel terminale
Nella finestra "Market watch" i future devono essere collocati in ordine decrescente:
Fig. 4. Market Watch
Creare un indicatore
L'indicatore predefinito dovrebbe essere posizionato nella cartella terminal_data_folder\MQL5\Indicators. Crea la cartella Sintetici in MyIndicators (che apri in \Indicators). Consente di risparmiare spazio nella cartella \Indicators nella Libreria Standard e facilita la sincronizzazione degli indicatori all'avvio di MQL5 Storage. Il percorso finale della cartella è simile al seguente: terminal_data_folder\MQL5\Indicators\MyIndicators\Synthetics
Nella cartella Synthetics crea un nuovo file:
Fig. 5. L'indicatore di creazione di nuovi file
Imposta il nuovo tipo di file - "Indicatore personalizzato":
Fig. 6. Il nuovo tipo di file - "Indicatore personalizzato"
Premere "Avanti" e aprire la finestra "Proprietà generali dell'indicatore personalizzato". Inserisci il nome dell'indicatore - "SYNT", aggiungi due opzioni. La prima opzione "Numero di future per splicing" determina il numero degli strumenti da collegare. Nota che 2 è il valore minimo possibile del "Numero di future per lo splicing". La seconda opzione "Tipo di incollaggio" determina il tipo di splicing nell'indicatore predefinito - "aggiunta semplice":
Fig. 7. I parametri dell'indicatore personalizzato
Prestare attenzione all'opzione "Tipo di incollaggio": la splicing può essere "semplice aggiunta" o "addizione con spostamento". In questa fase non è possibile aggiungere l'elenco di questi due tipi di splicing. Ecco perché lasciare l'impostazione predefinita "semplice aggiunta". Durante la scrittura del codice dell'indicatore "SYNT" attivare l'opzione Later per visualizzare l'elenco a tendina con i tipi di splicing.
Nella finestra successiva seleziona i gestori di eventi dell'indicatore:
Fig. 8. I gestori di eventi dell'indicatore
Notare che la funzione OnTimer() verrà utilizzata nell'indicatore "SYNT". La funzionalità principale dell'indicatore è impostata in OnTimer(). L'indicatore può essere collegato sia al grafico dei simboli con l'operazione finita (questo simbolo non includerà gli eventi OnCalculate), sia al grafico dei simboli con un'operazione attiva.
Premere "Avanti" e nelle "Proprietà generali del programma indicatore personalizzato" selezionare "Indicatore in una finestra separata":
Fig. 9. Opzione "Indicatore in una finestra separata"
Premi il pulsante "Fatto" e vedrai il modello di indicatore "SYNT".
Organizzare l'elenco a tendina
Per vedere l'elenco dei tipi di splicing come elenco a tendina è necessario dichiarare l'enumerazione ENUM_GLUING_TYPE nelle opzioni dell'indicatore.
Dichiarare l'enumerazione nell'area globale all'inizio del blocco dei parametri di ingresso:
#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 | //+------------------------------------------------------------------+
Ora puoi controllare come viene visualizzato l'elenco a tendina.
Dovresti compilare il file indicatore (F7). Ora, dopo aver allegato l'indicatore, puoi vedere nelle opzioni che si avvia l'elenco a tendina:
Fig. 10. Ora hai l’
elenco a tendina nei parametri
Aggiungi la descrizione dell'indicatore che verrà visualizzato nella scheda "Generale" quando verrà allegato al grafico per la prima volta o quando le sue proprietà verranno modificate:
#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
Il metodo di costruzione dell'indicatore - DRAW_COLOR_CANDLES - candele colorate.
Sono necessari 4 buffer indicatori e 1 buffer per l'archivio dell'indice del colore. Lo stile della linea, indicatore - STYLE_SOLID - linea continua. Visualizza tutto nel codice dell'indicatore:
#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 | //+------------------------------------------------------------------+
Inserisci il parametro di input "number_future_gluing" - numero di strumenti necessari per la costruzione. Il valore predefinito "number_future_gluing" è uguale a 2:
//--- input parameters || input parameters input int numder_futures_gluing=2; input ENUM_GLUING_TYPE gluing_type=simple_addition;
Dichiarare 4 buffer indicatori, 1 buffer per l'archiviazione dell'indice di colore e l'array ausiliario 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 | //+------------------------------------------------------------------+
Collega i buffer degli indicatori agli array dinamici unidimensionali, imposta l'indicizzazione dei buffer come nelle serie temporali:
//--- 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);
Per visualizzare il nome della serie di indicatori ("Apri", "Alto", "Basso" e "Chiudi") nella "Finestra dati" è necessaria la variabile 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 | //+------------------------------------------------------------------+
Per attivare l'indicatore hai bisogno della variabile shft_array e due flag 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 | //+------------------------------------------------------------------+
Quindi imposta l'indicatore e collega l'indice di colore del buffer al colore scelto:
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);
Aggiungi l'inizializzazione del timer con intervallo di 3 secondi e il generatore di numeri casuali nella funzione 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);
Sono necessari almeno due simboli per elaborare lo splicing.
Controlla il numero di strumenti per la splicing nella funzione 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);
Dopo aver controllato il numero di simboli per la splicing, controlla se l'indicatore è già stato disegnato. Se l'indicatore viene disegnato, puoi uscire da OnCalculate() :
Comment(comm); return(0); } if(indicator_rendered==true) return(rates_total); //--- return value of prev_calculated for next call return(rates_total);
Poiché l'indicatore "SYNT" viene utilizzato principalmente per analizzare la tendenza allo sviluppo delle barre giornaliere, ritengo che non sia necessario procedere a ricalcoli in ogni tick. Non ci saranno calcoli dell'indicatore "SYNT" su ogni tick.
Inoltre, è necessario calcolare l'indicatore solo nei seguenti casi:
- se l'indicatore è stato lanciato la prima volta;
- se la cronologia è stata modificata (ad esempio, ci sono state aggiunte).
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);
Inizializzazione forzata dei buffer degli indicatori
I buffer dell'indicatore "SYNT" sono array dinamici collegati.
Quando l'indicatore viene lanciato per la prima volta, i buffer vengono inizializzati in modo forzato. Procedere con l'inizializzazione in OnCalculate(). Perché è necessario eseguirlo in OnCalculate(), non in OnInit? La spiegazione è nella figura seguente:
Fig. 11. L'inizializzazione dell'array in OnCalculate()
Come si può vedere in Fig.11, l'evento OnCalculate() si verificherà in ogni caso, mentre l'OnInit() è abilitato quando si avvia l'aggiornamento del grafico tramite il comando "Update". Pertanto, l'inizializzazione degli array verrà condotta in 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);
La funzione ArrayInitialize() inizializza il buffer dell'indicatore. In questo caso l'inizializzazione mostra degli zeri.
Se provi a inizializzare l'indicatore del buffer con EMPTY_VALUE , non sarai in grado di unire gli indicatori su "SYNT".
Algoritmo di addizione semplice
Fig. 12. Algoritmo di addizione semplice
Le date nella foto sono le date di inizio e fine della circolazione dei future UX-9.13, UX-12.13 e UX-3.14. Questi dati sono presentati nella tabella:
Simbolo | Inizia la circolazione | La circolazione finisce |
---|---|---|
UX-9.13 | 2013.03.15 | 2013.09.16 |
UX-12.13 | 2013.06.17 | 2013.12.16 |
UX-3.14 | 2013.09.16 | 2014.03.17 |
Nella Fig. 10 data 2013.12.25 - è una vera data di calendario. Il simbolo UX-3.14 è ancora valido.
Il metodo di splicing "Semplice aggiunta" sarà implementato nella funzione 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 sono i future up, simbDOWN sono i future down, entrambi si trovano nella finestra "Market review". Colore - colore utilizzato per disegnare i future.
Il codice completo della funzione SimpleAddition() è riportato di seguito:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Addizione con algoritmo di spostamento
Fig. 13. Addizione con algoritmo di splicing a scorrimento
Lo splicing in questo algoritmo, rispetto alla semplice aggiunta, inizia 10 giorni prima della chiusura del simbolo. Il metodo di splicing "Addition with shift" viene elaborato nella funzione 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); } //+------------------------------------------------------------------+
La differenza tra le funzioni AdditionWithShift() e SimpleAddition() è in due righe: sottrai 10 giorni dalle date:
. . . expiration_time_UP=int(SymbolInfoInteger(simbUP,SYMBOL_EXPIRATION_TIME))-86400*10; . . . expiration_time_DOWN=int(SymbolInfoInteger(simbDOWN,SYMBOL_EXPIRATION_TIME))-86400*10; . . .
A causa della piccola differenza nei codici, non mostrerò il codice completo della funzione AdditionWithShift(), puoi trovare il codice nel file indicatore dell'articolo.
Nonostante questa piccola differenza tra le funzioni AdditionWithShift() e SimpleAddition(), è meglio non unirle per creare una funzione universale (in caso di ulteriori modifiche nell'algoritmo o, ad esempio, lanci di test).
Precaricamento della cronologia dei simboli
La funzione CheckLoadHistory() copia tutta la cronologia dei simboli nel buffer ausiliario tmp_rates.
Se il processo di copia ha esito positivo, il valore true viene assegnato al flag good_history, il che significa che puoi iniziare a disegnare l'indicatore:
//--- 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); } //+------------------------------------------------------------------+
Puoi copiare tutta la cronologia dei simboli poiché la vita futura è molto breve e tutta la copia della cronologia non richiederà molto spazio.
OnTimer: la funzione principale dell'indicatore
Ora hai il codice per due metodi di splicing e il codice per il caricamento della cronologia, quindi puoi modificare la funzione 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); } } } //+------------------------------------------------------------------+
L'indicatore è costruito. Puoi compilarlo e allegare alla tabella. È meglio scegliere il simbolo del commercio chiuso e impostare il periodo H1.
Uscita iniziale dell'indicatore "SYNT"
Dopo aver allegato al grafico i due modelli di indicatori "SYNT" di diversi metodi di splicing, è possibile confrontare questi metodi:
Fig. 14. Due metodi di confronto di splicing dei future
La possibilità di giuntare indicatori (standard e personalizzati)
Gli indicatori personalizzati possono essere uniti con la prima chiamata OnCalculate e l'indicatore "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 );
Nella finestra "Navigatore" aprire l'elenco "Indicatori personalizzati". Quindi apri l'elenco "Esempi", scegli l'indicatore e posizionalo in "SYNT". Nella scheda "Parametri" scegli "Dati indicatori precedenti" nell'elenco a tendina.
Ecco l'elenco con gli indicatori che puoi unire sull'indicatore "SYNT", si avviano sul "SYNT" senza errori:
- AMA (Adaptive Moving Average);
- BB (Bollinger Bands);
- Media mobile personalizzata;
- Double Exponential Moving Average
- Fractal Adaptive Moving Average
- Triple Exponential Moving Average
L'indicatore "SYNT" che ha unito tre future con l'indicatore della media mobile personalizzata allegato:
Fig. 15. Un esempio di tre simboli uniti
Conclusione
È più facile analizzare il comportamento dei simboli dei grafici più vecchi aperti in intervalli di tempo giornalieri. Sebbene il numero degli indicatori tecnici sia limitato, questo metodo aiuta a tracciare l'andamento dei prezzi sui future continui.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/802





- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso