
Trademinator 3: Ascesa delle macchine di trading
Prologo
C'erano una volta su un forum lontano (MQL5) due articoli: "Algoritmi Genetici - È Facile!" di joo e "Dr. Tradelove..." scritto da me, entrambi pubblicati. Nel primo articolo, l'autore ci ha dotato di un potente strumento per ottimizzare tutto ciò di cui hai bisogno, comprese le strategie di trading - un algoritmo genetico implementato tramite il linguaggio MQL5.
Utilizzando questo algoritmo, nel secondo articolo ho cercato di sviluppare un Expert Advisor auto-ottimizzante basato su di esso. L'articolo si concludeva con la formulazione del seguente compito: creare un Expert Advisor (auto-ottimizzante, ovviamente) che non solo può selezionare i migliori parametri per un particolare sistema di trading, ma anche scegliere la migliore strategia di tutte le strategie sviluppate. Vediamo se è possibile e, se lo è, come.
Storie di robot di trading
In primo luogo, formuliamo i requisiti generali per un Expert Advisor auto-ottimizzante.
Dovrebbe essere in grado di (sulla base di dati cronologici):
- selezionare la migliore strategia tra quelle descritte
- scegliere il miglior strumento finanziario
- scegliere la migliore dimensione di deposito per il trading con la correzione della leva
- scegliere i migliori parametri di indicatori nella strategia selezionata
Inoltre, nella vita reale, dovrebbe essere in grado di:
- aprire e chiudere posizioni
- scegliere la dimensione della posizione
- decidere se è necessaria una nuova ottimizzazione
La figura seguente mostra un diagramma schematico dell'Expert Advisor proposto.
Uno schema dettagliato con limiti si trova nel file allegato Scheme_en.
Tenendo presente che è impossibile coglierne l'immensità, introduciamo le restrizioni nella logica di Expert Advisor. Siamo d'accordo che (IMPORTANTE):
- L'Expert Advisor prenderà decisioni di trading al verificarsi di una nuova barra (in qualsiasi intervallo di tempo selezionato).
- Sulla base di p.1, ma non solo, l'Expert Advisor chiuderà le operazioni di trading solo sui segnali dell’indicatore non utilizzando Take Profit e Stop Loss e, di conseguenza, non utilizzando Trailing Stop.
- La condizione per iniziare una nuova ottimizzazione: un drawdown del saldo è superiore al valore preimpostato durante l'inizializzazione del livello. Si prega di notare che questa è la mia condizione personale e ognuno di voi può selezionare la propria condizione specifica.
- Una funzione di fitness modella il trading sulla cronologia e massimizza il saldo modellato, a condizione che il drawdown relativo del saldo delle operazioni simulate sia inferiore a un certo livello preimpostato. Nota anche che questa è la mia funzione di fitness personale e puoi selezionare quella specifica.
- Limitiamo il numero di parametri da ottimizzare, ad eccezione dei tre generali (strategia, strumento e quota di deposito), a cinque per i parametri dei buffer degli indicatori. Questa limitazione deriva logicamente dal numero massimo di buffer di indicatori per gli indicatori tecnici incorporati. Se hai intenzione di descrivere le strategie che utilizzano indicatori personalizzati con un gran numero di buffer di indicatori, è sufficiente modificare la variabile OptParamCount nel file main.mq5 alla quantità desiderata.
Ora che i requisiti sono specificati e le limitazioni selezionate è possibile esaminare il codice che implementa tutto questo.
Iniziamo con la funzione, dove tutto funziona.
void OnTick() { if(isNewBars()==true) { trig=false; switch(strat) { case 0: {trig=NeedCloseMA() ; break;}; //The number of case strings must be equal to the number of strategies case 1: {trig=NeedCloseSAR() ; break;}; case 2: {trig=NeedCloseStoch(); break;}; default: {trig=NeedCloseMA() ; break;}; } if(trig==true) { if(GetRelDD()>maxDD) //If a balance drawdown is above the max allowed value: { GA(); //Call the genetic optimization function GetTrainResults(); //Get the optimized parameters maxBalance=AccountInfoDouble(ACCOUNT_BALANCE); //Now count the drawdown not from the balance maximum... //...but from the current balance } } switch(strat) { case 0: {trig=NeedOpenMA() ; break;}; //The number of case strings must be equal to the number of strategies case 1: {trig=NeedOpenSAR() ; break;}; case 2: {trig=NeedOpenStoch(); break;}; default: {trig=NeedOpenMA() ; break;}; } Print(TimeToString(TimeCurrent()),";","Main:OnTick:isNewBars(true)", ";","strat=",strat); } }
Cosa c'è qui? Come disegnato nel diagramma, guardiamo ogni segno di spunta, se c'è una nuova barra. Se c'è, quindi, sapendo quale strategia verrà ora scelta, chiamiamo la sua funzione specifica per verificare se c'è una posizione aperta e chiuderla, se necessario. Supponiamo che ora la migliore strategia innovativa sia SAR, rispettivamente sarà chiamata la funzione NeedCloseSAR:
bool NeedCloseSAR() { CopyBuffer(SAR,0,0,count,SARBuffer); CopyOpen(s,tf,0,count,o); Print(TimeToString(TimeCurrent()),";","StrategySAR:NeedCloseSAR", ";","SAR[0]=",SARBuffer[0],";","SAR[1]=",SARBuffer[1],";","Open[0]=",o[0],";","Open[1]=",o[1]); if((SARBuffer[0]>o[0]&&SARBuffer[1]<o[1])|| (SARBuffer[0]<o[0]&&SARBuffer[1]>o[1])) { if(PositionsTotal()>0) { ClosePosition(); return(true); } } return(false); }
Qualsiasi funzione di chiusura della posizione deve essere booleana e restituire true quando si chiude una posizione. Ciò consente al blocco di codice successivo della funzione OnTick() di decidere se è necessaria una nuova ottimizzazione:
if(trig==true) { if(GetRelDD()>maxDD) //If the balance drawdown is above the max allowed one: { GA(); //Call the genetic optimization function GetTrainResults(); //Get optimized parameters maxBalance=AccountInfoDouble(ACCOUNT_BALANCE); //Now count the drawdown not from the balance maximum... //...but from the current balance } }
Ottieni il drawdown del saldo corrente e confrontalo con quello massimo consentito. Se ha superato il valore massimo, esegui una nuova ottimizzazione (GA()). La funzione GA(), a sua volta, chiama il cuore dell'Expert Advisor - la funzione di fitness FitnessFunction(int chromos) del modulo GAModule.mqh:
void FitnessFunction(int chromos) //A fitness function for the genetic optimizer:... //...selects a strategy, symbol, deposit share,... //...parameters of indicator buffers;... //...you can optimize whatever you need, but... //...watch carefully the number of genes { double ff=0.0; //The fitness function strat=(int)MathRound(Colony[GeneCount-2][chromos]*StratCount); //GA selects a strategy //For EA testing mode use the following code... z=(int)MathRound(Colony[GeneCount-1][chromos]*3); //GA selects a symbol switch(z) { case 0: {s="EURUSD"; break;}; case 1: {s="GBPUSD"; break;}; case 2: {s="USDCHF"; break;}; case 3: {s="USDJPY"; break;}; default: {s="EURUSD"; break;}; } //..for real mode, comment the previous code and uncomment the following one (symbols are selected in the MarketWatch window) /* z=(int)MathRound(Colony[GeneCount-1][chromos]*(SymbolsTotal(true)-1));//GA selects a symbol s=SymbolName(z,true); */ optF=Colony[GeneCount][chromos]; //GA selects a deposit share switch(strat) { case 0: {ff=FFMA( Colony[1][chromos], //The number of case strings must be equal to the number of strategies Colony[2][chromos], Colony[3][chromos], Colony[4][chromos], Colony[5][chromos]); break;}; case 1: {ff=FFSAR( Colony[1][chromos], Colony[2][chromos], Colony[3][chromos], Colony[4][chromos], Colony[5][chromos]); break;}; case 2: {ff=FFStoch(Colony[1][chromos], Colony[2][chromos], Colony[3][chromos], Colony[4][chromos], Colony[5][chromos]); break;}; default: {ff=FFMA( Colony[1][chromos], Colony[2][chromos], Colony[3][chromos], Colony[4][chromos], Colony[5][chromos]); break;}; } AmountStartsFF++; Colony[0][chromos]=ff; Print(TimeToString(TimeCurrent()),";","GAModule:FitnessFunction", ";","strat=",strat,";","s=",s,";","optF=",optF, ";",Colony[1][chromos],";",Colony[2][chromos],";",Colony[3][chromos],";",Colony[4][chromos],";",Colony[5][chromos]); }
A seconda della strategia attualmente selezionata, viene chiamato il modulo di calcolo della funzione di fitness specifico per una particolare strategia. Ad esempio, il GA ha scelto uno stocastico, quindi verrà chiamato FFStoch () e l'ottimizzazione dei parametri dei buffer degli indicatori verrà trasferita ad esso:
double FFStoch(double par1,double par2,double par3,double par4,double par5) { int b; bool FFtrig=false; //Is there an open position? string dir=""; //Direction of the open position double OpenPrice; //Position Open price double t=cap; //Current balance double maxt=t; //Maximum balance double aDD=0.0; //Absolute drawdown double rDD=0.000001; //Relative drawdown Stoch=iStochastic(s,tf,(int)MathRound(par1*MaxStochPeriod)+1, (int)MathRound(par2*MaxStochPeriod)+1, (int)MathRound(par3*MaxStochPeriod)+1,MODE_SMA,STO_CLOSECLOSE); StochTopLimit =par4*100.0; StochBottomLimit=par5*100.0; dig=MathPow(10.0,(double)SymbolInfoInteger(s,SYMBOL_DIGITS)); leverage=AccountInfoInteger(ACCOUNT_LEVERAGE); contractSize=SymbolInfoDouble(s,SYMBOL_TRADE_CONTRACT_SIZE); b=MathMin(Bars(s,tf)-1-count-MaxMAPeriod,depth); for(from=b;from>=1;from--) //Where to start copying of history { CopyBuffer(Stoch,0,from,count,StochBufferMain); CopyBuffer(Stoch,1,from,count,StochBufferSignal); if((StochBufferMain[0]>StochBufferSignal[0]&&StochBufferMain[1]<StochBufferSignal[1])|| (StochBufferMain[0]<StochBufferSignal[0]&&StochBufferMain[1]>StochBufferSignal[1])) { if(FFtrig==true) { if(dir=="BUY") { CopyOpen(s,tf,from,count,o); if(t>0) t=t+t*optF*leverage*(o[1]-OpenPrice)*dig/contractSize; else t=0; if(t>maxt) {maxt=t; aDD=0;} else if((maxt-t)>aDD) aDD=maxt-t; if((maxt>0)&&(aDD/maxt>rDD)) rDD=aDD/maxt; } if(dir=="SELL") { CopyOpen(s,tf,from,count,o); if(t>0) t=t+t*optF*leverage*(OpenPrice-o[1])*dig/contractSize; else t=0; if(t>maxt) {maxt=t; aDD=0;} else if((maxt-t)>aDD) aDD=maxt-t; if((maxt>0)&&(aDD/maxt>rDD)) rDD=aDD/maxt; } FFtrig=false; } } if(StochBufferMain[0]>StochBufferSignal[0]&&StochBufferMain[1]<StochBufferSignal[1]&&StochBufferMain[1]>StochTopLimit) { CopyOpen(s,tf,from,count,o); OpenPrice=o[1]; dir="SELL"; FFtrig=true; } if(StochBufferMain[0]<StochBufferSignal[0]&&StochBufferMain[1]>StochBufferSignal[1]&&StochBufferMain[1]<StochBottomLimit) { CopyOpen(s,tf,from,count,o); OpenPrice=o[1]; dir="BUY"; FFtrig=true; } } Print(TimeToString(TimeCurrent()),";","StrategyStoch:FFStoch", ";","K=",(int)MathRound(par1*MaxStochPeriod)+1,";","D=",(int)MathRound(par2*MaxStochPeriod)+1, ";","Slow=",(int)MathRound(par3*MaxStochPeriod)+1,";","TopLimit=",StochTopLimit,";","BottomLimit=",StochBottomLimit, ";","rDD=",rDD,";","Cap=",t); if(rDD<=trainDD) return(t); else return(0.0); }
La funzione fitness dello stocastico restituisce un saldo simulato alla funzione principale, che lo passerà all'algoritmo genetico. Ad un certo punto nel tempo il GA decide di terminare l'ottimizzazione e, utilizzando la funzione GetTrainResults(), restituiamo i migliori valori correnti della strategia (ad esempio - medie mobili), il simbolo, la quota di deposito e i parametri dei buffer degli indicatori al programma di base, oltre a creare indicatori per ulteriori trading reali:
void GetTrainResults() //Get the best parameters { strat=(int)MathRound(Chromosome[GeneCount-2]*StratCount); //Remember the best strategy //For EA testing mode use the following code... z=(int)MathRound(Chromosome[GeneCount-1]*3); //Remember the best symbol switch(z) { case 0: {s="EURUSD"; break;}; case 1: {s="GBPUSD"; break;}; case 2: {s="USDCHF"; break;}; case 3: {s="USDJPY"; break;}; default: {s="EURUSD"; break;}; } //...for real mode, comment the previous code and uncomment the following one (symbols are selected in the MarketWatch window) /* z=(int)MathRound(Chromosome[GeneCount-1]*(SymbolsTotal(true)-1)); //Remember the best symbol s=SymbolName(z,true); */ optF=Chromosome[GeneCount]; //Remember the best deposit share switch(strat) { case 0: {GTRMA( Chromosome[1], //The number of case strings must be equal to the number of strategies Chromosome[2], Chromosome[3], Chromosome[4], Chromosome[5]) ; break;}; case 1: {GTRSAR( Chromosome[1], Chromosome[2], Chromosome[3], Chromosome[4], Chromosome[5]) ; break;}; case 2: {GTRStoch(Chromosome[1], Chromosome[2], Chromosome[3], Chromosome[4], Chromosome[5]) ; break;}; default: {GTRMA( Chromosome[1], Chromosome[2], Chromosome[3], Chromosome[4], Chromosome[5]) ; break;}; } Print(TimeToString(TimeCurrent()),";","GAModule:GetTrainResults", ";","strat=",strat,";","s=",s,";","optF=",optF, ";",Chromosome[1],";",Chromosome[2],";",Chromosome[3],";",Chromosome[4],";",Chromosome[5]); } void GTRMA(double par1,double par2,double par3,double par4,double par5) { MAshort=iMA(s,tf,(int)MathRound(par1*MaxMAPeriod)+1,0,MODE_SMA,PRICE_OPEN); MAlong =iMA(s,tf,(int)MathRound(par2*MaxMAPeriod)+1,0,MODE_SMA,PRICE_OPEN); CopyBuffer(MAshort,0,from,count,ShortBuffer); CopyBuffer(MAlong, 0,from,count,LongBuffer ); Print(TimeToString(TimeCurrent()),";","StrategyMA:GTRMA", ";","MAL=",(int)MathRound(par2*MaxMAPeriod)+1,";","MAS=",(int)MathRound(par1*MaxMAPeriod)+1); }
Ora tutto è tornato al punto in cui tutto è in esecuzione (OnTick()): sapendo quale strategia è ora la migliore, si controlla se è il momento di andare al mercato:
bool NeedOpenMA() { CopyBuffer(MAshort,0,0,count,ShortBuffer); CopyBuffer(MAlong, 0,0,count,LongBuffer ); Print(TimeToString(TimeCurrent()),";","StrategyMA:NeedOpenMA", ";","LB[0]=",LongBuffer[0],";","LB[1]=",LongBuffer[1],";","SB[0]=",ShortBuffer[0],";","SB[1]=",ShortBuffer[1]); if(LongBuffer[0]>LongBuffer[1]&&ShortBuffer[0]>LongBuffer[0]&&ShortBuffer[1]<LongBuffer[1]) { request.type=ORDER_TYPE_SELL; OpenPosition(); return(false); } if(LongBuffer[0]<LongBuffer[1]&&ShortBuffer[0]<LongBuffer[0]&&ShortBuffer[1]>LongBuffer[1]) { request.type=ORDER_TYPE_BUY; OpenPosition(); return(false); } return(true); }
Il cerchio si chiuse.
Controlliamo come funziona. Ecco un rapporto del 2011 sull'intervallo di tempo di 1 ora con quattro coppie principali: EURUSD, GBPUSD, USDCHF, USDJPY:
Rapporto dello strategy tester | ||||||||||||
InstaForex-Server (Build 567) | ||||||||||||
Impostazioni | ||||||||||||
Expert: | Principale | |||||||||||
Simbolo: | EURUSD | |||||||||||
Periodo: | H1 (2011.01.01 - 2011.12.31) | |||||||||||
Parametri di Input: | trainDD=0.50000000 | |||||||||||
maxDD=0.20000000 | ||||||||||||
Broker: | Gruppo di società InstaForex | |||||||||||
Valuta: | USD | |||||||||||
Deposito iniziale: | 10 000,00 | |||||||||||
Leva finanziaria: | 1:100 | |||||||||||
Risultati | ||||||||||||
Qualità della cronologia: | 100% | |||||||||||
Barre: | 6197 | Tick: | 1321631 | |||||||||
Utile netto totale: | -538,74 | Profitto lordo: | 3 535,51 | Perdita lorda: | -4 074,25 | |||||||
Fattore di profitto: | 0,87 | Profitto previsto: | -89,79 | Livello di margine: | 85,71% | |||||||
Fattore di recupero: | -0,08 | Indice di Sharpe: | 0,07 | Risultato OnTester: | 0 | |||||||
Drawdown del saldo: | ||||||||||||
Saldo Drawdown Assoluto: | 4 074,25 | Saldo Drawdown Maximal: | 4 074,25 (40,74%) | Saldo Drawdown Relativo: | 40,74% (4 074,25) | |||||||
Prelievo di capitale: | ||||||||||||
Equità Drawdown Assoluto: | 4 889,56 | Equità Drawdown Massimo: | 6 690,90 (50,53%) | Equità Drawdown Relativo: | 50,53% (6 690,90) | |||||||
Totale operazioni: | 6 | Short Trades (vincita %): | 6 (16,67%) | Long Trades (vincita %): | 0 (0,00%) | |||||||
Totale operazioni: | 12 | Operazioni di profitto (% del totale): | 1 (16,67%) | Operazioni di perdita (% del totale): | 5 (83,33%) | |||||||
Il più grande trading di profitto: | 3 535,51 | Il più grande trading in perdita: | -1 325,40 | |||||||||
Profitto di trading medio: | 3 535,51 | Perdita media di trading: | -814,85 | |||||||||
Vincite massime consecutive: | 1 (3 535,51) | Massime perdite consecutive: | 5 (-4 074,25) | |||||||||
Profitto massimo consecutivo (conteggio): | 3 535,51 (1) | Massime perdite consecutive (conteggio): | -4 074,25 (5) | |||||||||
Media vittorie consecutive: | 1 | Media perdite consecutive: | 5 | |||||||||
Ordini | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Orario di apertura | Ordine | Simbolo | Tipo | Volume | Prezzo | S / L | T / P | Ora | Stato | Commento | ||
2011.01.03 01:00 | 2 | USDCHF | Vendita | 28,21 / 28,21 | 0,9321 | 2011.01.03 01:00 | Pieno | |||||
2011.01.03 03:00 | 3 | USDCHF | Acquista | 28,21 / 28,21 | 0,9365 | 2011.01.03 03:00 | Pieno | |||||
2011.01.03 06:00 | 4 | USDCHF | Vendita | 24,47 / 24,47 | 0,9352 | 2011.01.03 06:00 | Pieno | |||||
2011.01.03 09:00 | 5 | USDCHF | Acquista | 24,47 / 24,47 | 0,9372 | 2011.01.03 09:00 | Pieno | |||||
2011.01.03 13:00 | 6 | USDCHF | Vendita | 22,99 / 22,99 | 0,9352 | 2011.01.03 13:00 | Pieno | |||||
2011.01.03 16:00 | 7 | USDCHF | Acquista | 22,99 / 22,99 | 0,9375 | 2011.01.03 16:00 | Pieno | |||||
2011.01.03 18:00 | 8 | USDJPY | Vendita | 72,09 / 72,09 | 81,57 | 2011.01.03 18:00 | Pieno | |||||
2011.01.03 21:00 | 9 | USDJPY | Acquista | 72,09 / 72,09 | 81,66 | 2011.01.03 21:00 | Pieno | |||||
2011.01.04 01:00 | 10 | USDJPY | Vendita | 64,54 / 64,54 | 81,67 | 2011.01.04 01:00 | Pieno | |||||
2011.01.04 02:00 | 11 | USDJPY | Acquista | 64,54 / 64,54 | 81,78 | 2011.01.04 02:00 | Pieno | |||||
2011.10.20 21:00 | 12 | USDCHF | Vendita | 56,30 / 56,30 | 0,8964 | 2011.10.20 21:00 | Pieno | |||||
2011.10.21 12:00 | 13 | USDCHF | Acquista | 56,30 / 56,30 | 0,8908 | 2011.10.21 12:00 | Pieno | |||||
Operazioni | ||||||||||||
Ora | Operazione | Simbolo | Tipo | Direzione | Volume | Prezzo | Ordine | Commissione | Swap | Profitto | Saldo | Commento |
2011.01.01 00:00 | 1 | Saldo | 0,00 | 0,00 | 10 000,00 | 10 000,00 | ||||||
2011.01.03 01:00 | 2 | USDCHF | Vendita | In entrata | 28,21 | 0,9321 | 2 | 0,00 | 0,00 | 0,00 | 10 000,00 | |
2011.01.03 03:00 | 3 | USDCHF | Acquista | In uscita | 28,21 | 0,9365 | 3 | 0,00 | 0,00 | -1 325,40 | 8 674,60 | |
2011.01.03 06:00 | 4 | USDCHF | Vendita | In entrata | 24,47 | 0,9352 | 4 | 0,00 | 0,00 | 0,00 | 8 674,60 | |
2011.01.03 09:00 | 5 | USDCHF | Acquista | In uscita | 24,47 | 0,9372 | 5 | 0,00 | 0,00 | -522,19 | 8 152,41 | |
2011.01.03 13:00 | 6 | USDCHF | Vendita | In entrata | 22,99 | 0,9352 | 6 | 0,00 | 0,00 | 0,00 | 8 152,41 | |
2011.01.03 16:00 | 7 | USDCHF | Acquista | In uscita | 22,99 | 0,9375 | 7 | 0,00 | 0,00 | -564,02 | 7 588,39 | |
2011.01.03 18:00 | 8 | USDJPY | Vendita | In entrata | 72,09 | 81,57 | 8 | 0,00 | 0,00 | 0,00 | 7 588,39 | |
2011.01.03 21:00 | 9 | USDJPY | Acquista | In uscita | 72,09 | 81,66 | 9 | 0,00 | 0,00 | -794,53 | 6 793,86 | |
2011.01.04 01:00 | 10 | USDJPY | Vendita | In entrata | 64,54 | 81,67 | 10 | 0,00 | 0,00 | 0,00 | 6 793,86 | |
2011.01.04 02:00 | 11 | USDJPY | Acquista | In uscita | 64,54 | 81,78 | 11 | 0,00 | 0,00 | -868,11 | 5 925,75 | |
2011.10.20 21:00 | 12 | USDCHF | Vendita | In entrata | 56,30 | 0,8964 | 12 | 0,00 | 0,00 | 0,00 | 5 925,75 | |
2011.10.21 12:00 | 13 | USDCHF | Acquista | In uscita | 56,30 | 0,8908 | 13 | 0,00 | -3,78 | 3 539,29 | 9 461,26 | |
0,00 | -3,78 | -534,96 | 9 461,26 | |||||||||
Copyright 2001-2011, MetaQuotes Software Corp. |
Lascia che ti spieghi la zona che è segnata sul grafico (le spiegazioni sono tratte dall'analisi del log):
- Dopo l'avvio dell'Expert Advisor, l'algoritmo genetico ha selezionato la strategia innovativa SAR su USDCHF con una quota del deposito in trade pari al 28%, vi ha fatto trading fino alla sera del 3 gennaio, ha perso oltre il 20% del saldo e ha iniziato a ri-ottimizzare.
- Quindi l'Expert Advisor ha deciso di fare trading sull’innovativa SAR su USDJPY, ma con l'intero deposito (98%). Naturalmente, non poteva fare trading a lungo e quindi ha iniziato la sua terza ottimizzazione la mattina del 4 gennaio.
- Questa volta ha deciso, ancora una volta, di fare trading su golden e dead cross delle medie mobili su USDCHF per l'intero deposito. Ha aspettato la prima dead cross fino al 20 ottobre, l'ha venduta al massimo e ha riconquistato tutto ciò che ha perso. Dopodiché, fino alla fine dell'anno, l'Expert Advisor non ha visto condizioni favorevoli per entrare nel mercato.
Continuerà?
Si può continuare? Quale sarebbe la prossima generazione di Expert Advisor? L'Expert Advisor che inventa strategie e seleziona la migliore tra queste. E, inoltre, può gestire il denaro acquistando hardware più potenti, canali e così via ...
Avviso di rischio:
Questa breve dichiarazione non rivela completamente tutti i rischi e altri aspetti significativi del trading di valute forex a margine. Devi capire la natura del trading e l'entità della tua esposizione al rischio. Devi considerare attentamente se il trading è appropriato per te alla luce della tua esperienza, dei tuoi obiettivi, risorse finanziarie e altre circostanze rilevanti.
Il Forex non è solo un mercato redditizio, ma anche altamente rischioso. In termini di trading a margine, fluttuazioni di cambio relativamente piccole possono avere un impatto significativo sul conto del trader, con conseguente perdita pari al deposito iniziale e ad eventuali fondi ulteriormente depositati sul conto per mantenere le posizioni aperte. Non devi investire denaro che non puoi permetterti di perdere. Prima di decidere di fare trading, assicurati di comprendere tutti i rischi e di tenere conto del tuo livello di esperienza. Se necessario, chiedi una consulenza indipendente.
Licenze:
Il modulo UGAlib.mqh è sviluppato e distribuito sotto licenza BSD da Andrey Dik alias joo.
L'Expert Advisor e i moduli ausiliari allegati a questo articolo sono sviluppati e distribuiti sotto licenza BSD dall'autore Roman Rich. Il testo della licenza è disponibile nel file Lic.txt.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/350





- 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