English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Trademinator 3: Ascesa delle macchine di trading

Trademinator 3: Ascesa delle macchine di trading

MetaTrader 5Trading | 17 dicembre 2021, 16:02
92 0
Roman Zamozhnyy
Roman Zamozhnyy

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):

  1. L'Expert Advisor prenderà decisioni di trading al verificarsi di una nuova barra (in qualsiasi intervallo di tempo selezionato).
  2. 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.
  3. 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.
  4. 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.
  5. 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):

  1. 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.
  2. 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.
  3. 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

File allegati |
lic.txt (1.43 KB)
sheme_en.gif (147.11 KB)
gamodule.mqh (7.24 KB)
main.mq5 (4.99 KB)
musthave.mqh (7.79 KB)
strategyma.mqh (5.13 KB)
strategysar.mqh (4.09 KB)
strategystoch.mqh (6.04 KB)
ugalib.mqh (33.36 KB)
Sicurezza del codice MQL5: Protezione con password, generatori di chiavi, limiti di tempo, licenze remote e tecniche avanzate di crittografia delle chiavi di licenza EA Sicurezza del codice MQL5: Protezione con password, generatori di chiavi, limiti di tempo, licenze remote e tecniche avanzate di crittografia delle chiavi di licenza EA
La maggior parte degli sviluppatori ha bisogno di proteggere il proprio codice. Questo articolo presenterà alcuni modi per proteggere il software MQL5: introdurrà metodi per fornire funzionalità di licenza a script MQL5, Expert Advisor e indicatori. Parlerà della protezione tramite password, generatori di chiavi, licenza dell'account, la valutazione dei limiti di tempo e la protezione remota tramite chiamate MQL5-RPC.
Creazione di un Expert Advisor mediante Expert Advisor Visual Wizard Creazione di un Expert Advisor mediante Expert Advisor Visual Wizard
Expert Advisor Visual Wizard per MetaTrader 5 fornisce un ambiente grafico altamente intuitivo con un set completo di blocchi di trading predefiniti, i quali consentono di progettare un Expert Advisor in pochi minuti. L'approccio click, drag and drop di Expert Advisor Visual Wizard ti consente di creare rappresentazioni visive delle strategie e dei segnali di trading forex come faresti con carta e matita. Questi diagrammi di trading vengono analizzati automaticamente dal generatore di codice MQL5 di Molanis che li trasforma in Expert Advisor pronti all'uso. L'ambiente grafico interattivo semplifica il processo di progettazione ed elimina la necessità di scrivere codice MQL5.
Promuovi i tuoi progetti di sviluppo utilizzando le librerie EX5 Promuovi i tuoi progetti di sviluppo utilizzando le librerie EX5
Nascondere i dettagli di implementazione di classi/funzioni in un file .ex5 ti consentirà di condividere i tuoi algoritmi di know-how con altri sviluppatori, impostare progetti comuni e promuoverli nel Web. E mentre il team di MetaQuotes non risparmia alcuno sforzo per realizzare la possibilità di ereditarietà diretta delle classi della libreria ex5, noi lo implementeremo proprio ora.
Previsione delle serie temporali mediante livellamento esponenziale (parte 2) Previsione delle serie temporali mediante livellamento esponenziale (parte 2)
Questo articolo cerca di aggiornare l'indicatore creato in precedenza e tratta brevemente un metodo per stimare gli intervalli di confidenza delle previsioni utilizzando il bootstrap e i quantili. Di conseguenza, otterremo l'indicatore di previsione e gli script da utilizzare per la stima dell'accuratezza della previsione.