English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Simulink: una Guida per gli Sviluppatori di Expert Advisor

Simulink: una Guida per gli Sviluppatori di Expert Advisor

MetaTrader 5Sistemi di trading | 16 dicembre 2021, 11:03
197 0
Denis Kirichenko
Denis Kirichenko

Introduzione

Ci sono diversi articoli che descrivono le vaste possibilità di Matlab. Per essere più precisi, il modo in cui questo software è in grado di espandere gli strumenti del programmatore, che utilizza per lo sviluppo di un Expert Advisor. In questo articolo, cercherò di illustrare il lavoro di un pacchetto matlab così potente come il Simulink.

Vorrei offrire un modo alternativo per sviluppare un sistema di trading automatizzato per i trader. Sono stato ispirato a rivolgermi a questo tipo di metodo a causa della complessità del problema che il trader deve affrontare: la creazione, la verifica e il test del sistema di trading automatizzato. Non sono un programmatore professionista. E così, il principio di "passare dal semplice al complesso" è di primaria importanza per me nello sviluppo del sistema di trading automatizzato. Cosa esattamente è semplice per me? Prima di tutto, questa è la visualizzazione del processo di creazione del sistema e la logica del suo funzionamento. Inoltre, è un minimo di codice scritto a mano. Queste aspettative sono silenziose e coerenti con le capacità del pacchetto Simulink®, un noto prodotto MATLAB, che è leader mondiale tra gli strumenti per la visualizzazione di calcoli matematici.

In questo articolo, tenterò di creare e testare il sistema di trading automatizzato, basato su un pacchetto Matlab, e quindi scrivere un Expert Advisor per MetaTrader 5. Inoltre, tutti i dati storici per il backtesting verranno utilizzati da MetaTrader 5.

Per evitare confusione terminologica, chiamerò il sistema di trading, che funziona in Simulinik, con una parola capiente MTS, e quello che funziona in MQL5, semplicemente un Expert Advisor.


1. Le basi di Simulink e Stateflow

Prima di procedere con azioni specifiche, è necessario introdurre una qualche forma di minimo teorico.

Con l'aiuto del pacchetto Simulink®, che fa parte di MATLAB, l'utente può modellare, simulare e analizzare sistemi dinamici. Inoltre, è possibile sollevare la questione sulla natura del sistema, simularlo e quindi osservare ciò che accade.

Con Simulink, l'utente può costruire un modello da zero o modificare un modello già esistente. Il pacchetto supporta il sviluppo di sistemi lineari e non lineari, che vengono creati sulla base di comportamenti discreti, continui e ibridi.

Le proprietà principali del pacchetto sono presentate sul sito dello sviluppatore:

  • Librerie estese ed espandibili di blocchi predefiniti;
  • Editor grafico interattivo per l'assemblaggio e la gestione di diagrammi a blocchi intuitivi;
  • Capacità di gestire progetti complessi segmentando i modelli in gerarchie di componenti di progettazione;
  • Model Explorer per navigare, creare, configurare e cercare tutti i segnali, i parametri, le proprietà e il codice generato associati al modello;
  • API (Application Programming Interface) che consentono di connettersi con altri programmi di simulazione e incorporare il codice scritto a mano;
  • Blocchi funzionali Embedded MATLAB™ per portare gli algoritmi MATLAB in Simulink e nelle implementazioni di sistemi incorporati;
  • Modalità di simulazione (Normal, Accelerator e Rapid Accelerator) per l'esecuzione di simulazioni interpretative o a velocità di codice C compilate utilizzando risolutori a passo fisso o variabile;
  • Debugger grafico e profiler per esaminare i risultati della simulazione e, quindi, diagnosticare le prestazioni e il comportamento imprevisto nel progetto;
  • Accesso completo a MATLAB per analizzare e visualizzare i risultati, personalizzare l'ambiente di modeling e definire segnali, parametri e dati di test;
  • Strumenti di analisi e diagnostica del modello per garantire la coerenza del modello e identificare gli errori di modeling.

Iniziamo quindi la revisione immediata dell'ambiente Simulink. Viene inizializzato da una finestra Matlab già aperta in due dei seguenti modi:

  1. utilizzando il comando Simulink nella finestra di comando;
  2. utilizzando l'icona Simulink sulla barra degli strumenti.

Figura 1. Inizializzazione di Simulink

Figura 1. Inizializzazione di Simulink

Quando il comando viene eseguito, viene visualizzata la finestra di esplorazione delle librerie (Simulink Library Browser). 

Figura 2. Browser della Libreria

Figura 2. Browser della Libreria


La finestra del browser contiene un albero di componenti delle librerie Simulink. Per visualizzare una particolare sezione della libreria, è sufficiente selezionarla con il mouse, dopodiché una serie di componenti icona, della sezione attiva della libreria, apparirà nella sezione destra della finestra Simulink Library Browser. La Fig. 2 mostra la sezione principale della libreria Simulink.

Utilizzando il menu del browser o i pulsanti della sua barra degli strumenti, è possibile aprire una finestra per creare un nuovo modello o per caricarne uno esistente. Devo notare che tutto il lavoro con Simulink avviene insieme a un sistema MATLAB aperto, in cui è possibile monitorare l'esecuzione delle operazioni, purché il loro output sia fornito dal programma di modeling.


Figura 3. La finestra vuota di Simulink

Figura 3. Finestra vuota Simpulink


Prima di tutto, cambiamo alcuni parametri del nostro modello. Apriamo Simulation Parametri di Configurazione. Questa finestra ha un numero di tab con molti parametri. Siamo interessati al tab predefinito Solver, in cui è possibile impostare i parametri del solver del sistema di modeling Simulink.

Nel tempo di simulazione il tempo di modeling è impostato dall'ora di inizio - Ora di inizio (di solito 0) e l'ora di fine - Ora di arresto.

Per la nostra attività, assegniamo all'ora di inizio un valore pari a 1. Lasceremo il tempo di Stop così com’è.

Nelle opzioni del solver, ho anche cambiato il tipo in Fixed-step, il solver stesso in discreto e il passo (dimensione a passo fisso) in 1.

Figura 4. Finestra Parametri di Configurazione


L'ambiente Simulink viene completato con successo dal subsystem Stateflow che è un pacchetto di modeling basato su eventi, sulla teoria degli automatizzi a stati finiti. Ci permette di rappresentare il lavoro del sistema, basato su una catena di regole, che specificano gli eventi e le azioni come risposta a questi eventi.

L'interfaccia utente grafica del pacchetto Stateflow ha i seguenti componenti:

  • Un Editor Grafico di grafici SF;
  • Stateflow Explorer;
  • Stateflow Finder per cercare gli oggetti necessari nei grafici SF;
  • Un debugger di modelli SF;
  • Real Time Workshop, un generatore di codice in tempo reale.

Il diagramma a blocchi più comunemente usato (grafico), che si trova nella sezione Stateflow. Esaminiamolo.

Spostiamo il blocco dalla libreria e facciamo doppio clic su di esso per aprire il diagramma. Apparirà una finestra vuota di un editor di grafici SF. Può essere utilizzato per creare grafici SF e il loro debug, al fine di ottenere le funzioni necessarie.

La barra degli strumenti si trova in posizione verticale sul lato sinistro. Ci sono 9 pulsanti:

  1. Stato;
  2. Cronologia Junction;
  3. Transizione Predefinita;
  4. Junction Connettiva;
  5. Tabella Truth;
  6. Funzione;
  7. Funzione MATLAB incorporata;
  8. Box;
  9. Chiamata alla Funzione Simulink.

Sfortunatamente, è impossibile considerare ogni elemento in dettaglio nel contesto di questo articolo. Pertanto, mi limiterò a una breve descrizione di quegli elementi, di cui avremo bisogno per il nostro modello. Informazioni più dettagliate sono disponibili nella sezione Aiuto di Matlab o sul sito web dello sviluppatore.

Figura 5. Visualizzazione del grafico SF nell'editor

Figura 5. La visualizzazione del grafico SF nell'editor

L'oggetto chiave delle carte SF è lo Stato. È presentato da un rettangolo con angoli arrotondati.

Può essere esclusivo o parallelo. Ogni stato può essere il genitore e ha eredi. Gli stati possono essere attivi o non attivi, gli stati possono eseguire determinate procedure.

La transizione è rappresentata come una linea curva, con una freccia e collega gli stati e altri oggetti. Una transizione può essere effettuata facendo clic con il pulsante sinistro del mouse sull'oggetto di origine e indirizzando il cursore sull'oggetto di destinazione. La transizione può avere le sue condizioni, che sono registrate tra parentesi. La procedura di transizione è indicata tra parentesi, verrà eseguita se la condizione è soddisfatta. La procedura, eseguita durante la conferma dell'oggetto di destinazione, è indicata da una barra.

Il nodo alternativo (giunzione connettiva) ha la forma di un cerchio e consente la transizione attraverso i diversi percorsi, ognuno dei quali è definito uno da una condizione specifica. In tal caso, viene selezionata la transizione che corrisponde alla condizione specificata.

Funzione rappresentata come grafico di flusso con le istruzioni del linguaggio procedurale Stateflow. Un grafico di flusso riflette la struttura logica di utilizzo delle transizioni e dei nodi alternativi.

Un evento è un altro importante oggetto di Stateflow, appartenente al gruppo di oggetti non grafici. Questo oggetto può avviare le procedure del grafico SF.

La procedura (azione) è anche un oggetto non grafico. Può chiamare la funzione, assegnare un evento specifico, una transizione, ecc.

I dati nel modello SF sono rappresentati da valori numerici. I dati non sono rappresentati come oggetti grafici. Possono essere creati a qualsiasi livello della gerarchia del modello e avere proprietà.

2. Descrizione della Strategia di Trading

Ora, brevemente sul trading. Per i nostri scopi formativi, l'Expert Advisor sarà molto semplice, se non per così dire primitivo.

Il sistema di trading automatizzato praticamente aprirà posizioni sulla base del segnale dopo l'incrocio delle Medie Esponenziali, con un periodo di 21 e 55 (numeri di Fibonacci), mediato sui prezzi di chiusura. Quindi, se l'EMA 21 attraversa l'EMA 55 dal basso, viene aperta una posizione lunga, altrimenti - una corta.

Per il filtraggio del rumore, la posizione verrà aperta alla barra K-th dal prezzo di apertura della barra dopo la comparsa della croce 21/55. Faremo trading sull'EURUSD H1. Verrà aperta una sola posizione. Sarà chiuso solo al raggiungimento del livello Take Profit o Stop Loss.

Vorrei ricordare che durante lo sviluppo del sistema di trading automatizzato e il backtesting della cronologia, sono ammesse alcune semplificazioni del quadro commerciale generale.

Ad esempio, il sistema non controllerà l'esecuzione del broker di un segnale. Inoltre aggiungeremo le restrizioni di trading al nucleo del sistema in MQL5.


3. Il modeling di una strategia di trading in Simulink

Per cominciare, dobbiamo caricare i dati storici sui prezzi nell'ambiente Matlab. Lo faremo usando uno script MetaTrader 5, che li salverà (testClose.mq5).

In Matlab, questi dati (Open, High, Low, Close, Spread) verranno caricati anche utilizzando un semplice m-script (priceTxt.m).

Utilizzando il movavg (funzione standard Matlab) creeremo array di Medie Mobili Esponenziali:

[ema21, ema55] = movavg(close, 21, 55, 'e');

Oltre a una matrice ausiliaria degli indici delle barre:

num=1:length(close);

Creiamo le seguenti variabili:

K=3; sl=0.0065; tp=0.0295;

Iniziamo il processo di modeling.

Crea una finestra vuota Simulink e chiamala mts quando la salvi. Tutte le seguenti azioni sono state duplicate in formato video. Se qualcosa non è abbastanza chiaro, o addirittura non lo è proprio, puoi guardare le mie azioni guardando il video.

Quando si salva il modello, il sistema potrebbe stampare il seguente errore:

??? Il file "C:\\Simulink\\mts.mdl" contiene caratteri incompatibili con la codifica dei caratteri corrente, windows-1251. Per evitare questo errore, eseguire una delle operazioni seguenti:
1) Utilizzare la funzione slCharacterEncoding per modificare la codifica dei caratteri corrente in uno dei seguenti: Shift_JIS, windows-1252, ISO-8859-1.
2) Rimuovere i caratteri non supportati. Il primo carattere non supportato si trova alla riga 23, con offset byte 15.

Per eliminarlo, è sufficiente chiudere tutte le finestre dei modelli e modificare la codifica utilizzando i seguenti comandi:

bdclose all
set_param(0, 'CharacterEncoding', 'windows-1252');

Specifichiamo la fonte di informazioni del nostro modello.

Il ruolo di tale fonte di informazioni saranno i dati storici di MetaTrader 5, che contengono i prezzi di apertura, massimo, minimo e chiusura. Inoltre, prenderemo in considerazione lo Spread, anche se è diventato relativamente fluttuante di recente. Infine, registriamo l'orario di apertura del bar. Ai fini del modeling, alcune matrici di dati iniziali saranno interpretate come un segnale, cioè come un vettore di valori di una funzione temporale in punti discreti nel tempo.

Creiamo un subsystem "FromWorkspace" per recuperare i dati dall'area di lavoro Matlab. Selezionare la sezione Ports e Subsystems nel browser delle librerie Simulink. Trascinare il blocco "Subsystem" nella finestra del modello Simulink, utilizzando il mouse. Rinominarlo in "FromWorkspace", facendo clic sul Subsystem. Quindi, accedi facendo doppio clic sul pulsante sinistro del mouse sul blocco, al fine di creare le variabili di input e output e le costanti per il sistema.

Per creare le sorgenti di segnale nel Browser della Libreria, scegliere il set di blocchi per l'elaborazione del segnale e le sorgenti (Sorgenti di Elaborazione del Segnale). Utilizzando il mouse, trascinare il blocco "Segnale dall'Area di Lavoro" nella finestra del subsystem del modello FromWorkspace. Poiché il modello avrà 4 segnali di ingresso, duplichiamo semplicemente il blocco e creiamo altre 3 copie di esso. Specifichiamo subito quali variabili verranno elaborate per blocco. A tale scopo, fare clic due volte sul blocco e immettere il nome della variabile nelle proprietà. Queste variabili saranno: open, ema21, ema55, num. Chiameremo i blocchi come segue: segnale aperto, segnale ema21, segnale ema55, segnale num.

Ora, dalla sezione Simulink "Blocchi comunemente usati", aggiungeremo un blocco per la creazione di un canale (Bus Creator). Aprire il blocco e modificare il numero di ingressi su 4. Collegare il segnale aperto, il segnale ema21, il segnale ema55, i blocchi di segnale num con gli ingressi del blocco Bus Creator.

Inoltre, avremo altre 5 costanti di input. Il blocco "Costante" viene aggiunto dalla sezione "Blocchi comunemente usati". Come valore (valore costante), specifichiamo i nomi delle variabili: spread, high, low, tp, sl:

  • spread - questa è un array di valori di spread;
  • alto - questa è una serie di valori massimi di prezzo;
  • basso - questo è un array di valori di prezzo minimo;
  • tp - Valore Take Profit in termini assoluti;
  • sl - il valore Stop Loss in termini assoluti.

Chiameremo i blocchi come segue: spread array, high array, low array, Take Profit, Stop Loss.

Selezionare il blocco della porta di output (Out1) nella sezione Simulink "Ports e Subsystems" e spostarlo nella finestra del subsystem. Crea 5 copie della porta di output. Il primo, ci connetteremo con il blocco Bus Creator e altri - in alternativa con i blocchi spread degli array, high, low, Take Profit e Stop Loss.

Rinomineremo la prima porta in price e le altre con il nome della variabile di output.

Per creare un segnale di trading, inseriamo il blocco di addizione (Aggiungi) dalla sezione Simulink "Operazioni matematiche". Lo chiameremo emas differenziale. All'interno del blocco cambieremo l'elenco dei segni, c + + a + -. Utilizzando la combinazione di tasti Ctrl + K, ruotare il blocco di 90 ° in senso orario. Collegare il blocco di segnale ema21 all'ingresso "+" e il segnale ema55 con il "-". 

Quindi inserire il blocco Delay, dalla sezione Signal Processing Blockset, di Signal Operations. Lo chiameremo K Delay. Nel campo Delay (samples) di questo blocco inseriamo il nome della variabile K. Collegalo con il blocco precedente.

I blocchi differenziali emas e K Delay formattano la parte anteriore (differenza di livello) del segnale di controllo per i calcoli solo per la fase di modeling, dove c'è stato un cambiamento. Il subsystem, che creeremo un po’ più tardi, verrà attivato se almeno un elemento ha un cambiamento nel suo livello di segnale.

Quindi, dalla sezione "Blocchi comunemente usati" di Simulink, aggiungeremo un multiplexer con e (Mux) blocco. Allo stesso modo, ruotare il blocco di 90 ° in senso orario. Divideremo la linea del segnale del blocco di ritardo in due e la collegheremo con i multiplex.

Dalla sezione Stateflow inserire un blocco Grafico. Inserisci il grafico. Aggiungi 2 eventi in entrata (Buy e Sell) e 2 eventi in uscita (OpenBuy e OpenSell). Il valore trigger (Trigger) per l'evento Buy, lo impostiamo su Falling (attivazione del subsystem da parte di un fronte negativo), e per gli eventi Sell, lo impostare su Rising (attivazione del subsystem da parte di un fronte positivo). Il valore di trigger (Trigger) per gli eventi OpenBuy e OpenSell, lo impostiamo sulla posizione di Function call (Calling), (l'attivazione del subsystem sarà determinata dalla logica del lavoro della funzione S data).

Creeremo una transizione per impostazione predefinita con 3 nodi alternativi. Il primo nodo lo collegheremo tramite una transizione al secondo nodo, impostando le condizioni e la procedura su Buy {OpenBuy;}, e per il terzo, impostando la procedura su Vendi {OpenSell;}. Collega l'input del grafico con il multiplex e le due uscite - con un altro multiplex che può essere copiato dal primo. L'ultimo blocco sarà collegato alla porta di uscita, che copieremo da una analoga e la chiameremo Buy/ Sell.

E quasi dimenticavo! Affinché il modello funzioni correttamente, dobbiamo creare un oggetto canale virtuale, che si troverà nell'area di lavoro Matlab. Per farlo, entriamo nell'Editor Bus tramite il menu Strumenti. Nell'editor, selezionare la voce Aggiungi Bus. Chiamatelo InputBus.

Inserire gli elementi in base ai nomi delle variabili di input: open, ema21, ema55 e num. Aprire Bus Creator e selezionare la casella di controllo accanto a Specifica proprietà tramite oggetto bus (Imposta le proprietà tramite l'oggetto bus). In altre parole, abbiamo collegato il nostro blocco con l'oggetto canale virtuale che abbiamo creato. Il canale virtuale significa che i segnali sono combinati solo graficamente senza influire sulla distribuzione della memoria.

Salvare le modifiche nella finestra del subsystem. Questo conclude il nostro lavoro con il subsystem FromWorkspace.


Ora arriva il momento di creare la "Scatola Nera". Sarà un blocco, basato sui segnali in arrivo, elaborerà le informazioni e prenderà decisioni di trading. Certo, deve essere creato da noi, piuttosto che da un programma per computer. Dopotutto, solo noi possiamo decidere le condizioni in base alle quali il sistema dovrebbe fare uno scambio. Inoltre, il blocco dovrà visualizzare le informazioni sulle offerte completate sotto forma di segnali.

Il blocco necessario è chiamato Grafico e si trova nella sezione Stateflow. Lo abbiamo già conosciuto, non è vero? Usando il "drag and drop" lo spostiamo nella nostra finestra del modello.

Figura 6. I blocchi del subsystem di input e il grafico StateFlow

Figura 6. I blocchi del subsystem di input e il grafico StateFlow


Apri il grafico e inserisci i nostri dati in esso. Prima di tutto, creiamo un canale oggetto, come abbiamo fatto nel subsystem FromWorkspace. Ma a differenza del primo, che ci ha fornito i segnali dallo spazio di lavoro, questo restituirà il risultato ottenuto. E così, chiameremo l'oggetto OutputBus. I suoi elementi diventeranno: barOpen, OpenPrice, TakeProfit, StopLoss, ClosePrice, barClose, Comment, PositionDir, posN, AccountBalance.

Ora inizieremo a costruire. Nella finestra del grafico, visualizzeremo la transizione predefinita (# 1).

Per le condizioni e le procedure indicheremo:

[Input.num>=56 && Input.num>Output.barClose] {Output.barOpen=Input.num;i = Input.num-1;Output.posN++;}

Questa condizione significa che i dati verranno elaborati se il numero di barre di input sarà almeno 56, nonché se la barra di input sarà superiore alla barra di chiusura della posizione precedente. Quindi, alla barra di apertura (Output.barOpen) viene assegnato il numero della barra in entrata da una variabile di indice di i - l'indice (a partire da 0) e il numero delle posizioni aperte aumenta di 1.

La 2a transizione viene eseguita solo se la posizione aperta non sarà la prima. In caso contrario, viene eseguita la terza transizione che assegnerà alla variabile di saldo del conto (Output.AccountBalance) il valore 100000.

La 4a transizione viene eseguita se il grafico è stato avviato dall'evento OpenBuy. In tal caso, la posizione sarà diretta all'acquisto (Output.PositionDir = 1), il prezzo di apertura diventerà uguale al prezzo della barra di apertura, tenendo conto dello spread (Output.OpenPrice = Input.open + spread [i] * 1e-5). Verranno inoltre specificati i valori dei segnali di uscita StopLoss e TakeProfit.

Se si verifica un evento OpenSell, il flusso seguirà la 5a transizione e ne imposti i valori per i segnali di uscita.

La 6a transizione si realizza se la posizione è lunga, altrimenti il flusso segue alla 7a transizione.

L'8a transizione verifica se il prezzo massimo della barra ha raggiunto o meno il livello Take Profit o se il prezzo minimo della barra ha raggiunto il livello di Stop Loss. In caso contrario, il valore della variabile indice i viene aumentato di uno (9a transizione).

La 10a transizione verifica le condizioni che si verificano allo Stop Loss: il prezzo minimo della barra ha superato il livello di Stop Loss. Se confermato, il flusso seguirà alla 11a transizione, e poi alla 12a, dove sono definiti i valori delle differenze di prezzo delle posizioni di chiusura e apertura, il saldo delle partite correnti e l'indice della barra di chiusura.

Se la 10a transizione non viene confermata, la posizione verrà chiusa al Take Profit (13a transizione). E poi, dal 14 il flusso seguirà alla 12a transizione.

Le procedure e le condizioni per le transizioni per una posizione corta sono l'opposto.

Infine, abbiamo creato nuove variabili nel grafico. Per integrarli automaticamente nel nostro modello, dobbiamo eseguire il modello direttamente nella finestra del grafico, facendo clic sul pulsante "Avvia simulazione". Sembra simile al pulsante "Riproduci" sui lettori musicali. A questo punto, verrà avviata la procedura guidata Stateflow Symbol (oggetti master SF) che suggerirà di salvare gli oggetti creati. Premere il pulsante SelectAll e, quindi, fare click sul pulsante Crea. Gli oggetti sono stati creati. Apriamo ora il Browser del modello. A sinistra, fai clic sul nostro grafico nella gerarchia del modello. Ordinare gli oggetti in modo che siano di tipo dati (DataType).

Aggiungi altri dati utilizzando i comandi di menu "Aggiungi" e "Dati". Chiameremo la prima variabile Input. Modificare il valore degli ambiti in Input e type - in "Bus: nome oggetto <bus> . E poi inserisci il nome del canale creato in precedenza, InputBus, direttamente in questo campo. Quindi la nostra variabile Input avrà il tipo di InputBus. Impostiamo il valore della Porta su uno.

Completare la stessa operazione con la variabile Output. Solo esso deve avere l'ambito di output e il tipo di bus di output.

Cambiamo l'ambito per le variabili high, low, sl, tp e spread al valore di "Input". Rispettivamente, impostiamo i numeri di porta nel seguente ordine: 3, 4, 6, 5, 2.

Cambiamo anche l'ambito della variabile Lots in Costant. Nel tab "Attributi valore" inseriamo gli eventi 1, OpenBuy e OpenSell - per l'Input nel campo "Initial" (a destra).  Negli eventi, modificare il valore di trigger per la "Chiamata di funzione").

Creare una variabile interna len, con un ambito Constant. Nella scheda "Attributi valore", nel campo "Valore iniziale", inseriremo una lunghezza della funzione m (close). Quindi sarà uguale alla lunghezza dell'array vicino che si trova nell'area di lavoro Matlab.

Per le variabili alta e bassa inseriremo un valore di [len 1] nel campo Dimensione. Quindi, nella memoria, abbiamo riservato le dimensioni dell'array di alto e basso come valore di [len 1].

Inoltre, indichiamo per la variabile K nella scheda "Attributi valore", nel campo "Valore iniziale" (a destra) la variabile effettiva di K presa dal workspace.

Di conseguenza, abbiamo un subsystem Grafico, con 7 porte di ingresso e una porta di output. Posizioniamo il blocco in questo modo, in modo che la porta degli eventi di input () si trovi in basso. Rinomineremo il blocco "gestione Position". Nel grafico stesso mostreremo anche il nome del blocco. Combina i blocchi del subsystem FromWorkspace e la "gestione Position" attraverso le porte appropriate. Pertanto cambia il colore dei blocchi.

Va notato che il subsystem "gestione Position" funzionerà solo se viene "svegliato" dagli eventi OpenBuy o OpenSell in arrivo. In questo modo, ottimizziamo il funzionamento del subsystem per evitare calcoli non necessari.

Figura 7. Subsystem di gestione FromWorkspace e Position


Ora dobbiamo creare un subsystem per stampare i risultati dell'elaborazione nell'area di lavoro Matlab e combinarlo con il subsystem "gestione Position". Sarà il compito più semplice.

Creiamo un subsystem "ToWorkspace" per ottenere i risultati nell'area di lavoro. Ripeti i passaggi che abbiamo fatto quando abbiamo creato il subsystem "FromWorkspace". Nel browser della libreria, selezionare la sezione Ports e Subsystems Simulink. Utilizzando il mouse, trascinare il blocco "Subsystem" nella finestra del modello Simulink. Rinominarlo in "ToWorkspace" facendo clic su "Subsystem". Combinare il blocco con il subsystem "gestione Position".

Per creare le variabili accedi ad esso facendo doppio clic sul blocco con il tasto sinistro del mouse,

Poiché il subsystem riceverà dati dall'oggetto OutputBus, che è un bus non virtuale, è necessario selezionare i segnali da questo canale. Per farlo, selezioniamo la sezione Simulink "Blocchi comunemente usati" nel browser della libreria e aggiungiamo un "Selettore bus". Il blocco avrà 1 segnale di ingresso e 2 di uscita, mentre abbiamo bisogno di avere 10 di tali segnali.

Colleghiamo il blocco alla porta di ingresso. Premi il pulsante "Avvia simulazione" (questo è il nostro pulsante "Riproduci"). Il compilatore inizierà a compilare il modello. Non sarà costruito con successo, ma creerà segnali di ingresso per il blocco di selezione del bus. Se entriamo nel blocco, vedremo apparire i segnali necessari sul lato sinistro della finestra, che vengono trasmessi tramite OutputBus. Devono essere tutti selezionati, utilizzando il pulsante "Seleziona" e spostarli sul lato destro - "Segnali selezionati".

Figura 8. Parametri del blocco del Bus Selector

Figura 8. Parametri di blocco del Bus Selector


Facciamo di nuovo riferimento alla sezione "Blocchi comunemente usati" del browser delle librerie Simulink e aggiungiamo il blocco Mux multiplex. Indica il numero di ingressi che è pari a 10.

Quindi accedere alla sezione "Sinks" del browser della libreria Simulink e spostare il blocco ToWorkspace nella finestra del subsystem. Lì indicheremo il nuovo nome della variabile "AccountBalance" e cambieremo il formato di output (Salva formato) da "Struttura" a "Array". Combina il blocco con il multiplex. Eliminare la porta di output, poiché non sarà più necessaria. Personalizza il colore dei blocchi. Salvare la finestra. Il subsystem è pronto.

Prima di costruire il modello, è necessario verificare la presenza delle variabili nell'area di lavoro. Devono essere presenti le seguenti variabili: InputBus, K, OutputBus, close, ema21, ema55, high, low, num, open, sl, spread, tp.

Impostiamo il valore Stop Time come parametro per definire num (end). Ciò significa che il vettore elaborato avrà la lunghezza che è stata impostata dall'ultimo elemento della matrice num.

Prima di iniziare a costruire un modello, dobbiamo scegliere un compilatore, usando il seguente comando:

mex-setup

Scegli il tuo compilatore per la creazione di un'interfaccia esterna (MEX) file:
Desideri che mex localizza i compilatori installati [y] / n? y

Selezionare un compilatore:

[1] Lcc-win32 C 2.4.1 in C:\PROGRA~2\MATLAB\R2010a\sys\lcc
[2] Microsoft Visual C++ 2008 SP1 in C:\Programmi (x86)\Microsoft Visual Studio 9.0
[0] None

Compilatore: 2

Come puoi vedere, ho selezionato il compilatore Microsoft Visual C ++ 2008 SP1.

Iniziamo a costruire. Premere il pulsante "Avvia simulazione". Si è visualizzato un errore: Errore di interfaccia Stateflow: Mancata corrispondenza della larghezza della porta. Input "spread" (#139) prevede uno scalare. Il segnale è il vettore unidimensionale con 59739 elementi.

La variabile "spread" non dovrebbe avere il tipo double, ma piuttosto ereditare il suo tipo dal segnale di Simulink.

Nel Modello Browser, per questa variabile, specifichiamo "Inherit: Come Simulink", e nel campo Dimensioni, e specificare "-1". Salvare le modifiche.

Eseguiamo di nuovo il modello. Ora il compilatore funziona. Mostrerà alcune piccole avvertenze. E in meno di 40 secondi il modello elaborerà i dati di quasi 60.000 barre. Il commercio viene effettuato da '2001 .01.01 00:00 'a '2010 .08.16 11:00'. Il numero totale di posizioni aperte è 461. Potete osservare come funziona il modello nella clip seguente.



4. Attuazione dello Strategy in MQL5

E così, il nostro sistema di trading automatizzato è compilato in Simulink. Ora dobbiamo trasferire questa idea di trading nell'ambiente MQL5. Abbiamo avuto a che fare con blocchi e oggetti Simulink, attraverso i quali abbiamo espresso la logica del nostro Expert Advisor di trading. Il compito attuale è quello di trasferire il sistema di trading logico nell’Expert Advisor MQL5.

Tuttavia, va notato che alcuni blocchi non devono necessariamente essere in qualche modo definiti nel codice MQL5, perché le loro funzioni potrebbero essere nascoste. Cercherò di commentare con una quantità massima di dettagli su quale riga si riferisce a quale blocco, nel codice effettivo. A volte questa relazione può essere indiretta. E a volte può riflettere una connessione di interfaccia di blocchi o oggetti.

Prima di iniziare questa sezione, permettetemi di attirare la tua attenzione su un articolo "Guida Passo per Passo alla scrittura di Expert Advisor in MQL5 per Principianti". Questo articolo fornisce una descrizione facilmente comprensibile delle idee principali e delle regole di base per scrivere un Expert Advisor in MQL5. Ma non mi soffermerò su di loro ora. Userò alcune righe di codice MQL5 da lì.

4.1 Subsystem "FromWorkspace"

Ad esempio, abbiamo un blocco "segnale aperto" nel subsystem "FromWorkspace". In Simulink, è necessario per ottenere il prezzo della barra di apertura durante il backtesting e per aprire una posizione a questo prezzo nel caso in cui venga ricevuto un segnale di trading. Questo blocco non è ovviamente presente nel codice MQL5, perché l'Expert Advisor richiede le informazioni sul prezzo subito dopo aver ricevuto il segnale di trading.

Nell'Expert Advisor dovremo elaborare i dati ricevuti dalle medie mobili. Pertanto, creeremo per loro array dinamici e variabili ausiliarie corrispondenti come gli handle.

int ma1Handle;  // Moving Average 1 indicator handle: block "ema21 signal"
int ma2Handle;  // indicator handle Moving Average 2: block "ema55 signal"

ma1Handle=iMA(_Symbol,_Period,MA1_Period,0,MODE_EMA,PRICE_CLOSE); // get handle of Moving Average 1 indicator 
ma2Handle=iMA(_Symbol,_Period,MA2_Period,0,MODE_EMA,PRICE_CLOSE); // get handle of Moving Average 2 indicator

double ma1Val[]; // dynamic array for storing the values of Moving Average 1 for every bar: block "ema21 signal"
double ma2Val[]; // dynamic array for storing the values of Moving Average 2 for every bar: block "ema55 signal"

ArraySetAsSeries(ma1Val,true);// array of indicator values MA 1: block "ema21 signal"
ArraySetAsSeries(ma2Val,true);// array of indicator values MA 2: block "ema55 signal"

Tutte le altre righe, che in qualche modo influenzano il movimento ema21 ed ema55, possono essere considerate ausiliarie.

"Take Profit" e "Stop Loss" sono definiti come variabili di input:

input int TakeProfit=135;   // Take Profit: Take Profit in the FromWorkspace subsystem
input int StopLoss=60;      // Stop Loss:  Stop Loss in the FromWorkspace subsystem
Tenendo conto del fatto che ci sono 5 cifre significative per EURUSD, il valore di TakeProfit e StopLoss dovrà aggiornarsi nel modo seguente:
int sl,tp;
sl = StopLoss;
tp = TakeProfit;
if(_Digits==5)
 {
  sl = sl*10;
  tp = tp*10;
 }

Gli array "spread", "high" e "low" vengono utilizzati per servire i valori, poiché sono responsabili della fornitura di dati storici, sotto forma di una matrice dei dati di prezzo rilevanti, al fine di identificare le condizioni di trading.

Non sono rappresentati in modo esplicito nel codice. Tuttavia, si può sostenere che l'array "spread", ad esempio, è necessario per formare un flusso di prezzi ask. E gli altri due sono necessari per determinare le condizioni per la chiusura di una posizione, che non sono specificate nel codice, poiché vengono eseguite automaticamente in MetaTrader 5, al raggiungimento di un certo livello di prezzo.

Il blocco "segnale num" è ausiliario e non viene visualizzato nel codice dell'Expert Advisor.

Il blocco "differenziale emas" controlla le condizioni per l'apertura di posizioni corte o lunghe trovando le differenze. Il "K Delay" crea un ritardo per gli array, che sono nella media del valore di K.

Viene creato l'evento Buy o Sell, è un evento di input per il subsystem di apertura della Position.

Nel codice, è tutto espresso come segue:

// event Buy (activation by the negative front)
bool Buy=((ma2Val[1+K]-ma1Val[1+K])>=0 && (ma2Val[K]-ma1Val[K])<0) ||
         ((ma2Val[1+K]-ma1Val[1+K])>0 && (ma2Val[K]-ma1Val[K])==0);

// event Sell (activation by the positive front)
bool Sell=((ma2Val[1+K]-ma1Val[1+K])<=0 && (ma2Val[K]-ma1Val[K])>0)||
         ((ma2Val[1+K]-ma1Val[1+K])<0 && (ma2Val[K]-ma1Val[K])==0);
Il subsystem di apertura della Position crea gli eventi "OpenBuy" e "OpenSell", che vengono elaborati nel subsystem "gestione Position", utilizzando le condizioni e le procedure.

 

4.2 Subsystem "Gestione Posizione"

Il subsystem inizia a funzionare elaborando gli eventi OpenBuy OpenSell.

Per la prima transizione del subsystem una delle condizioni è la presenza di non meno di 56 barre, che è indicata nel codice tramite il controllo di tali condizioni:

if(Bars(_Symbol,_Period)<56) // 1st transition of the «Position handling»subsystem : condition [Input.num>=56]
      {
        Alert("Not enough bars!");
        return(-1);
      }

Seconda condizione per la transizione: il numero della barra di apertura deve essere superiore alla barra di chiusura (Input.num; Output.barClose), cioè la position è stata chiusa.

Nel codice è indicato come segue:

//--- 1st transition of the «Position handling» subsystem: condition [Input.num>Output.barClose]

bool IsBought = false;  // bought
bool IsSold = false;    // sold
if(PositionSelect(_Symbol)==true) // there is an opened position
 {
   if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
     {
      IsBought=true;  // long
     }
   else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
     {
      IsSold=true;    // short
     }
  }
// check for opened position
if(IsTraded(IsBought,IsSold))
 {
   return;
 }

//+------------------------------------------------------------------+
//| Function of the check for opened position                        |
//+------------------------------------------------------------------+
bool IsTraded(bool IsBought,bool IsSold)
  {
   if(IsSold || IsBought)
     {
      Alert("Transaction is complete");
      return(true);
     }
   else
      return(false);
  }

La 4a transizione è responsabile dell'apertura di una posizione lunga.

È rappresentato come segue:

// 4th transition procedures of the «Position handling» subsystem: open long position
 mrequest.action = TRADE_ACTION_DEAL;                                  // market buy
 mrequest.price = NormalizeDouble(latest_price.ask,_Digits);           // latest ask price
 mrequest.sl = NormalizeDouble(latest_price.bid - STP*_Point,_Digits);  // place Stop Loss
 mrequest.tp = NormalizeDouble(latest_price.bid + TKP*_Point,_Digits);  // place Take Profit
 mrequest.symbol = _Symbol;                                           // symbol
 mrequest.volume = Lot;                                              // total lots
 mrequest.magic = EA_Magic;                                          // Magic Number
 mrequest.type = ORDER_TYPE_BUY;                                       // order to buy
 mrequest.type_filling = ORDER_FILLING_FOK;                            // the specified volume and for a price, 
                                                                               // equal or better, than specified
 mrequest.deviation=100;                                             // slippage
 OrderSend(mrequest,mresult);
 if(mresult.retcode==10009 || mresult.retcode==10008) // request completed or order placed
    {
     Alert("A buy order has been placed, ticket #:",mresult.order);
    }
 else
    {
     Alert("A buy order has not been placed; error:",GetLastError());
     return;
    }

La 5a transizione è responsabile dell'apertura di una posizione corta.

È rappresentato come segue:

// 5th transition procedures of the «Position handling» subsystem: open a short position
 mrequest.action = TRADE_ACTION_DEAL;                                  // market sell
 mrequest.price = NormalizeDouble(latest_price.bid,_Digits);           // latest bid price
 mrequest.sl = NormalizeDouble(latest_price.ask + STP*_Point,_Digits);  // place a Stop Loss
 mrequest.tp = NormalizeDouble(latest_price.ask - TKP*_Point,_Digits);  // place a Take Profit
 mrequest.symbol = _Symbol;                                          // symbol
 mrequest.volume = Lot;                                             // lots
 mrequest.magic = EA_Magic;                                         // Magic Number
 mrequest.type= ORDER_TYPE_SELL;                                      // sell order
 mrequest.type_filling = ORDER_FILLING_FOK;                           // in the specified volume and for a price, 
                                                                              // equal or better, than specified in the order
 mrequest.deviation=100;                                             // slippage
 OrderSend(mrequest,mresult);
 if(mresult.retcode==10009 || mresult.retcode==10008) // request is complete or the order is placed
    {
     Alert("A sell order placed, ticket #:",mresult.order);
    }
 else
    {
     Alert("A sell order is not placed; error:",GetLastError());
     return;
    }

Altre transizioni nelle sottocategorie non sono chiaramente presentate nell'Expert Advisor, poiché le procedure appropriate (attivazione di stop o raggiungimento di un livello di Take Profit), vengono eseguite automaticamente in MQL5.

Il subsystem "ToWorkspace" non è rappresentato nel codice MQL5 perché il suo compito è quello di presentare l'output nelle aree di lavoro Matlab.


Conclusioni

Usando una semplice idea di trading come esempio, ho creato il sistema di trading automatizzato in Simulink, in cui ho effettuato un backtesting su dati storici. All'inizio ero infastidito dalla domanda: "Ha senso essere coinvolti in tutto questo trambusto quando è possibile implementare rapidamente un sistema di trading attraverso il codice MQL5?"

Naturalmente puoi farlo senza la visualizzazione del processo di creazione del sistema e la logica del suo lavoro. Ma il più delle volte, questo è solo per programmatori esperti o semplicemente persone di talento. Quando il sistema di trading si estende con nuove condizioni e funzioni, la presenza del diagramma a blocchi e il suo lavoro saranno chiaramente il compito del trader.

Vorrei anche ricordare che non ho cercato di opporre le capacità linguistiche simulink contro il linguaggio MQL5. Ho semplicemente illustrato come è possibile creare un sistema di trading automatizzato utilizzando un design a blocchi. Forse, in futuro, gli sviluppatori MQL5 creeranno un constructor visivo di strategie che faciliterà il processo di scrittura di Expert Advisor.


Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/155

File allegati |
matlab.zip (28.68 KB)
mts.mq5 (9.93 KB)
testclose.mq5 (3.49 KB)
L'Handler dell'Evento "Nuova Barra" L'Handler dell'Evento "Nuova Barra"
Il linguaggio di programmazione MQL5 è in grado di risolvere i problemi a un livello completamente nuovo. Anche quei compiti, che hanno già tali soluzioni, grazie alla programmazione orientata agli oggetti possono salire ad un livello superiore. In questo articolo prendiamo un esempio particolarmente semplice di controllo della nuova barra su un grafico, che è stato trasformato in uno strumento piuttosto potente e versatile. Quale strumento? Scoprilo in questo articolo.
Ricerca di Errori e Registrazione Ricerca di Errori e Registrazione
MetaEditor 5 ha la funzione di debug. Tuttavia quando scrivi i tuoi programmi MQL5, spesso non vuoi visualizzare solo i singoli valori, ma tutti i messaggi che appaiono durante i test e il lavoro online. Quando il contenuto del file del log è di grandi dimensioni, è ovvio automatizzare il recupero rapido e semplice del messaggio richiesto. In questo articolo considereremo i modi per trovare errori nei programmi MQL5 e i metodi di logging. Inoltre semplificheremo l'accesso ai file e conosceremo un semplice programma LogMon per una comoda visualizzazione dei log.
Growing Neural Gas: Implementazione in MQL5 Growing Neural Gas: Implementazione in MQL5
L'articolo mostra un esempio di come sviluppare un programma MQL5 che implementa l'algoritmo adattivo di clustering chiamato Growing neural gas (GNG). L'articolo è destinato agli utenti che hanno studiato la documentazione linguistica e hanno determinate capacità di programmazione e conoscenze di base nell'area della neuro informatica.
Come Creare Rapidamente un Expert Advisor per l’Automated Trading Championship 2010 Come Creare Rapidamente un Expert Advisor per l’Automated Trading Championship 2010
Al fine di sviluppare un expert per partecipare all'Automated Trading Championship 2010, usiamo un modello di pronto dell’expert advisor. Anche il programmatore MQL5 alle prime armi sarà in grado di questo compito, perché per le tue strategie le classi di base, le funzioni, i modelli sono già sviluppati. Basta scrivere una quantità minima di codice per implementare la tua idea di trading.