English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Manuale MQL5: Ordini ОСО

Manuale MQL5: Ordini ОСО

MetaTrader 5Esempi | 12 gennaio 2022, 13:00
474 0
Denis Kirichenko
Denis Kirichenko

Introduzione

Questo articolo si concentra sulla gestione di questo tipo di coppia di ordini come OCO. Questo meccanismo è implementato in alcuni terminali di trading in concorrenza con MetaTrader 5. Perseguo due obiettivi attraverso l'esempio della creazione di un EA con un pannello per l'elaborazione degli ordini OCO. Il primo è la descrizione delle caratteristiche della libreria standard, l’altro è la volontà di estendere il set di strumenti di un trader.


1. Essenza degli ordini OCO

Gli ordini OCO (one-cancels-the-other order, in italiano un-ordine-annulla-l'altro) rappresentano una coppia di due ordini in sospeso.

Sono collegati dalla funzione di cancellazione reciproca: se il primo si attiva, il secondo dovrebbe essere rimosso e viceversa.

Fig. 1 Coppia di ordini OCO

Fig. 1 Coppia di ordini OCO

La Fig.1 mostra un semplice schema di interdipendenza dell'ordine. Riflette una definizione essenziale: una coppia esiste finché esistono entrambi gli ordini. In termini di logica, qualsiasi ordine della coppia è una condizione essenziale ma non sufficiente per l'esistenza della coppia.

Alcune fonti dicono che la coppia deve avere un ordine limite e un ordine stop, inoltre gli ordini devono avere una direzione (comprare o vendere). A mio avviso, tale restrizione non può aiutare nella creazione di strategie di trading flessibili. Suggerisco che vari ordini OCO vengano analizzati nella coppia e, soprattutto, cercheremo di programmare questa coppia.


2. Coppia di ordini di programmazione

A mio avviso, il set di strumenti ООP è adatto per la programmazione di attività connesse al controllo degli ordini OCO nel miglior modo possibile.

Le sezioni seguenti sono dedicate a nuovi tipi di dati che serviranno al nostro scopo. La classe CiOcoObject viene prima di tutto.


2.1. CiOcoObject Classe

Quindi, abbiamo bisogno di trovare qualche oggetto software responsabile del controllo su due ordini interconnessi.

Tradizionalmente, creiamo un nuovo oggetto sulla base della classe astratta CObject.

Questa nuova classe può avere l'aspetto seguente:

//+------------------------------------------------------------------+
//| Class CiOcoObject                                                |
//| Purpose: a class for OCO orders                                  |            
//+------------------------------------------------------------------+
class CiOcoObject : public CObject
  {
   //--- === Data members === --- 
private:
   //--- tickets of pair
   ulong             m_order_tickets[2];
   //--- initialization flag
   bool              m_is_init;
   //--- id
   uint              m_id;

   //--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CiOcoObject(void){m_is_init=false;};
   void             ~CiOcoObject(void){};
   //--- copy constructor
   void              CiOcoObject(const CiOcoObject &_src_oco);
   //--- assignment operator
   void              operator=(const CiOcoObject &_src_oco);

   //--- initialization/deinitialization
   bool              Init(const SOrderProperties &_orders[],const uint _bunch_cnt=1);
   bool              Deinit(void);
   //--- get id
   uint              Id(void) const {return m_id;};

private:
   //--- types of orders
   ENUM_ORDER_TYPE   BaseOrderType(const ENUM_ORDER_TYPE _ord_type);
   ENUM_BASE_PENDING_TYPE PendingType(const ENUM_PENDING_ORDER_TYPE _pend_type);
   //--- set id
   void              Id(const uint _id){m_id=_id;};
  };

Ogni coppia di ordini OCO avrà il proprio identificatore. Il suo valore è impostato per mezzo del generatore di numeri casuali (oggetto della classe CRandom).

I metodi di inizializzazione e deistizializzazione delle coppie sono di preoccupazione nel contesto dell'interfaccia. Il primo crea (inizializza) la coppia, e il secondo la rimuove (la deinitializza).

Il metodoCiOcoObject::Init() accetta come argomento la matrice di strutture di tipo SOrderProperties. Questo tipo di struttura rappresenta le proprietà dell'ordine nella coppia, cioè l'ordine OCO.


2.2 Struttura SOrderProperties

Consideriamo i campi della suddetta struttura.

//+------------------------------------------------------------------+
//| Order properties structure                                       |
//+------------------------------------------------------------------+
struct SOrderProperties
  {
   double                  volume;           // order volume   
   string                  symbol;           // symbol
   ENUM_PENDING_ORDER_TYPE order_type;       // order type   
   uint                    price_offset;     // offset for execution price, points
   uint                    limit_offset;     // offset for limit price, points
   uint                    sl;               // stop loss, points
   uint                    tp;               // take profit, points
   ENUM_ORDER_TYPE_TIME    type_time;        // expiration type
   datetime                expiration;       // expiration
   string                  comment;          // comment
  }

Quindi, per far funzionare il metodo di inizializzazione, dovremmo in precedenza riempire l'array di strutture costituito da due elementi. In parole semplici, dobbiamo spiegare al programma quali ordini eseguirà.

L'enumerazione di ENUM_PENDING_ORDER_TYPE tipo viene utilizzata nella struttura:

//+------------------------------------------------------------------+
//| Pending order type                                               |
//+------------------------------------------------------------------+
enum ENUM_PENDING_ORDER_TYPE
  {
   PENDING_ORDER_TYPE_BUY_LIMIT=2,       // Buy Limit
   PENDING_ORDER_TYPE_SELL_LIMIT=3,      // Sell Limit
   PENDING_ORDER_TYPE_BUY_STOP=4,        // Buy Stop
   PENDING_ORDER_TYPE_SELL_STOP=5,       // Sell Stop
   PENDING_ORDER_TYPE_BUY_STOP_LIMIT=6,  // Buy Stop Limit
   PENDING_ORDER_TYPE_SELL_STOP_LIMIT=7, // Sell Stop Limit
  };

In generale, ha lo stesso aspetto dell'ENUM _ORDER_TYPE enumerazione standard, ma consente di selezionare solo gli ordini in sospeso o, più esattamente, i tipi di tali ordini.

Protegge dagli errori durante la selezione del tipo di ordine corrispondente nei parametri di input (Fig.2).

Fig. 2. Il campo "Tipo" con un elenco a discesa dei tipi di ordine disponibili

Fig. 2. Il campo "Tipo" con un elenco a discesa dei tipi di ordine disponibili

Se tuttavia utilizziamo ENUM _ORDER_TYPE enumerazione standard, potremmo impostare un tipo di ordine di mercato (ORDER_TYPE_BUY o ORDER_TYPE_SELL), che non è richiesto in quanto abbiamo a che fare solo con ordini in sospeso.


2.3. Inizializzazione della coppia

Come notato sopra, il metodo CiOcoObject::Init() è impegnato nell'inizializzazione della coppia di ordini.

Infatti posiziona la coppia di ordini stessa e registra il successo o il fallimento dell'emergere di nuove coppie. Devo dire che questo è un metodo attivo, in quanto esegue operazioni di trading da solo. Possiamo anche creare un metodo passivo. Si collegherà semplicemente a una coppia di ordini in sospeso già attivi che sono stati effettuati in modo indipendente.

Non fornirò un codice dell'intero metodo. Ma vorrei notare che è importante calcolare tutti i prezzi (apertura, stop, profitto, limite), quindi il metodo di classe commerciale CTrade::OrderOpen() può eseguire un ordine commerciale. A tal fine dovremmo considerare due cose: la direzione dell'ordine (acquisto o vendita) e la posizione di un prezzo di esecuzione dell'ordine rispetto a un prezzo corrente (sopra o sotto).

Questo metodo chiama un paio di metodi privati: BaseOrderType() e PendingType(). Il primo definisce la direzione dell'ordine, il secondo determina il tipo di ordine in sospeso.

Se l'ordine viene effettuato, il relativo ticket viene registrato nella matrice m_order_tickets[].

Ho usato un semplice script Init_OCO.mq5 per testare questo metodo.

#property script_show_inputs
//---
#include "CiOcoObject.mqh"
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
sinput string Info_order1="+===--Order 1--====+";   // +===--Order 1--====+
input ENUM_PENDING_ORDER_TYPE InpOrder1Type=PENDING_ORDER_TYPE_SELL_LIMIT; // Type
input double InpOrder1Volume=0.02;                  // Volume
input uint InpOrder1PriceOffset=125;                // Offset for execution price, points
input uint InpOrder1LimitOffset=50;                 // Offset for limit price, points
input uint InpOrder1SL=250;                         // Stop loss, points
input uint InpOrder1TP=455;                         // Profit, points
input string InpOrder1Comment="OCO Order 1";        // Comment
//---
sinput string Info_order2="+===--Order 2--====+";   // +===--Order 2--====+
input ENUM_PENDING_ORDER_TYPE InpOrder2Type=PENDING_ORDER_TYPE_SELL_STOP; // Type
input double InpOrder2Volume=0.04;                  // Volume    
input uint InpOrder2PriceOffset=125;                // Offset for execution price, points
input uint InpOrder2LimitOffset=50;                 // Offset for limit price, points
input uint InpOrder2SL=275;                         // Stop loss, points
input uint InpOrder2TP=300;                         // Profit, points
input string InpOrder2Comment="OCO Order 2";        // Comment

//--- globals
CiOcoObject myOco;
SOrderProperties gOrdersProps[2];
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- property of the 1st order
   gOrdersProps[0].order_type=InpOrder1Type;
   gOrdersProps[0].volume=InpOrder1Volume;
   gOrdersProps[0].price_offset=InpOrder1PriceOffset;
   gOrdersProps[0].limit_offset=InpOrder1LimitOffset;
   gOrdersProps[0].sl=InpOrder1SL;
   gOrdersProps[0].tp=InpOrder1TP;
   gOrdersProps[0].comment=InpOrder1Comment;

//--- property of the 2nd order
   gOrdersProps[1].order_type=InpOrder2Type;
   gOrdersProps[1].volume=InpOrder2Volume;
   gOrdersProps[1].price_offset=InpOrder2PriceOffset;
   gOrdersProps[1].limit_offset=InpOrder2LimitOffset;
   gOrdersProps[1].sl=InpOrder2SL;
   gOrdersProps[1].tp=InpOrder2TP;
   gOrdersProps[1].comment=InpOrder2Comment;

//--- initialization of pair
   if(myOco.Init(gOrdersProps))
      PrintFormat("Id of new OCO pair: %I32u",myOco.Id());
   else
      Print("Error when placing OCO pair!");
  }

Qui puoi impostare varie proprietà degli ordini futuri della coppia. MetaTrader 5 ha sei diversi tipi di ordini in sospeso.

In questo contesto, ci possono essere 15 varianti (combinazioni) di coppie (a condizione che ci siano ordini diversi nella coppia).

C(k;N) = C(2,6) = 15

Tutte le varianti sono state testate con l'aiuto dello script. Farò un esempio per la coppia Buy Stop - Buy Stop Limit.

I tipi di ordini devono essere specificati nei parametri di script (Fig.3).


Fig. 3. Coppia di ordini "Buy Stop" con ordine "Buy Stop Limit"

Fig. 3. Coppia di ordini "Buy Stop" con ordine "Buy Stop Limit"

Le seguenti informazioni appariranno nel registro "Esperti":

QO      0       17:17:41.020    Init_OCO (GBPUSD.e,M15) Code of request result: 10009
JD      0       17:17:41.036    Init_OCO (GBPUSD.e,M15) New order ticket: 24190813
QL      0       17:17:41.286    Init_OCO (GBPUSD.e,M15) Code of request result: 10009
JH      0       17:17:41.286    Init_OCO (GBPUSD.e,M15) New order ticket: 24190814
MM      0       17:17:41.379    Init_OCO (GBPUSD.e,M15) Id of new OCO pair: 3782950319

Ma non possiamo lavorare con gli ordini OCO al massimo con l'aiuto della sceneggiatura senza ricorrere al looping.


2.4. Deinitializzazione della coppia

Questo metodo è responsabile del controllo sulla coppia di ordini. La coppia "morirà" quando un ordine lascia l'elenco degli ordini attivi.

Suppongo che questo metodo dovrebbe essere inserito nei gestori OnTrade() o OnTradeTransaction() del codice EA. In tal modo, l'EA sarà in grado di elaborare l'attivazione di qualsiasi ordine di coppia senza indugio.

//+------------------------------------------------------------------+
//| Deinitialization of pair                                         |
//+------------------------------------------------------------------+
bool CiOcoObject::Deinit(void)
  {
//--- if pair is initialized
   if(this.m_is_init)
     {
      //--- check your orders 
      for(int ord_idx=0;ord_idx<ArraySize(this.m_order_tickets);ord_idx++)
        {
         //--- current pair order
         ulong curr_ord_ticket=this.m_order_tickets[ord_idx];
         //--- another pair order
         int other_ord_idx=!ord_idx;
         ulong other_ord_ticket=this.m_order_tickets[other_ord_idx];

         //---
         COrderInfo order_obj;

         //--- if there is no current order
         if(!order_obj.Select(curr_ord_ticket))
           {
            PrintFormat("Order #%d is not found in active orders list.",curr_ord_ticket);
            //--- attempt to delete another order                 
            if(order_obj.Select(other_ord_ticket))
              {
               CTrade trade_obj;
               //---
               if(trade_obj.OrderDelete(other_ord_ticket))
                  return true;
              }
           }
        }
     }
//---
   return false;
  }

Vorrei menzionare un dettaglio. Il flag di inizializzazione della coppia viene controllato nel corpo del metodo class. Il tentativo di controllare gli ordini non verrà effettuato se il flag viene cancellato. Questo approccio impedisce di eliminare un ordine attivo quando non ne è stato ancora inserito un altro.

Aggiungiamo funzionalità allo script in cui sono stati effettuati un paio di ordini. A tale scopo, creeremo Control_OCO_EA.mq5 test EA.

In generale, l'EA differirà dallo script solo dal blocco di gestione degli eventi Trade() nel suo codice:

//+------------------------------------------------------------------+
//| Trade function                                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
//--- OCO pair deinitialization
   if(myOco.Deinit())
     {
      Print("No more order pair!");
      //--- clear  pair
      CiOcoObject new_oco;
      myOco=new_oco;
     }
  }

Il video mostra il lavoro di entrambi i programmi nel terminale MetaTrader 5.


Tuttavia, entrambi i programmi di test hanno punti deboli.

Il primo programma (script) può solo creare attivamente la coppia, ma poi perde il controllo su di essa.

Il secondo programma (Expert Advisor) controlla però la coppia, ma non può creare ripetutamente altre coppie dopo la creazione della prima. Per rendere il programma di ordini OCO (script) completo, dobbiamo espandere il suo set di strumenti dandogli la possibilità di effettuare ordini. Lo faremo nella prossima sezione.


3. Controllo di EA

Creiamo il pannello di gestione degli ordini OCO sul grafico per posizionare e impostare i parametri degli ordini di coppia.

Farà parte dell'EA di controllo (Fig.4). Il codice sorgente si trova in Panel_OCO_EA.mq5.

Fig. 4. Pannello per la creazione di ordini OCO: stato iniziale

Fig. 4. Pannello per la creazione di ordini OCO: stato iniziale


Dovremmo selezionare un tipo di ordine futuro e compilare i campi per inserire la coppia di ordini OCO.

Quindi l'etichetta sull'unico pulsante del pannello verrà modificata (proprietà text, Fig.5).

Fig. 5. Pannello per la creazione ordini OCO: nuova coppia

Fig. 5. Pannello per la creazione di ordini OCO: nuova coppia


Le seguenti classi della Libreria Standard sono state utilizzate per costruire il nostro Pannello:

  • CAppDialog è la finestra di dialogo principale dell'applicazione;
  • CPanel è un'etichetta rettangolare;
  • CLabel è un'etichetta di testo;
  • CComboBox è un campo con un elenco a discesa;
  • CEdit è un campo di input;
  • CButton è un pulsante.

Naturalmente, i metodi di classe dei genitori sono stati chiamati automaticamente.

Ora passiamo al codice. Va detto che la parte della Libreria Standard che è stata dedicata alla creazione di pannelli di indicazione e dialoghi è piuttosto grande.

Ad esempio, se vuoi catturare un evento di chiusura dell'elenco a discesa, dovrai approfondire la pila di chiamate (Fig. 6).

Fig. 6. Pila di chiamate

Fig. 6. Pila di chiamate


Uno sviluppatore imposta macro e una notazione nel file %MQL5\Include\Controls\Defines.mqh per eventi specifici.

Ho creato ON_OCO evento personalizzato per creare la coppia OCO.

#define ON_OCO (101) // OCO pair creation event 

I parametri degli ordini futuri vengono compilati e la coppia viene generata nel corpo del gestore OnChartEvent(). 

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- handling all chart events by main dialog
   myDialog.ChartEvent(id,lparam,dparam,sparam);

//--- drop-down list handling
   if(id==CHARTEVENT_CUSTOM+ON_CHANGE)
     {
      //--- if it is Panel list
      if(!StringCompare(StringSubstr(sparam,0,7),"myCombo"))
        {
         static ENUM_PENDING_ORDER_TYPE prev_vals[2];
         //--- list index
         int combo_idx=(int)StringToInteger(StringSubstr(sparam,7,1))-1;

         ENUM_PENDING_ORDER_TYPE curr_val=(ENUM_PENDING_ORDER_TYPE)(myCombos[combo_idx].Value()+2);
         //--- remember order type change
         if(prev_vals[combo_idx]!=curr_val)
           {
            prev_vals[combo_idx]=curr_val;
            gOrdersProps[combo_idx].order_type=curr_val;
           }
        }
     }

//--- handling input fields
   else if(id==CHARTEVENT_OBJECT_ENDEDIT)
     {
      //--- if it is Panel's input field
      if(!StringCompare(StringSubstr(sparam,0,6),"myEdit"))
        {
         //--- find object
         for(int idx=0;idx<ArraySize(myEdits);idx++)
           {
            string curr_edit_obj_name=myEdits[idx].Name();
            long curr_edit_obj_id=myEdits[idx].Id();
            //--- if names coincide
            if(!StringCompare(sparam,curr_edit_obj_name))
              {
               //--- get current value of field
               double value=StringToDouble(myEdits[idx].Text());
               //--- define gOrdersProps[] array index
               int order_num=(idx<gEditsHalfLen)?0:1;
               //--- define gOrdersProps structure field number
               int jdx=idx;
               if(order_num)
                  jdx=idx-gEditsHalfLen;
               //--- fill up gOrdersProps structure field
               switch(jdx)
                 {
                  case 0: // volume
                    {
                     gOrdersProps[order_num].volume=value;
                     break;
                    }
                  case 1: // execution
                    {
                     gOrdersProps[order_num].price_offset=(uint)value;
                     break;
                    }
                  case 2: // limit
                    {
                     gOrdersProps[order_num].limit_offset=(uint)value;
                     break;
                    }
                  case 3: // stop
                    {
                     gOrdersProps[order_num].sl=(uint)value;
                     break;
                    }
                  case 4: // profit
                    {
                     gOrdersProps[order_num].tp=(uint)value;
                     break;
                    }
                 }
              }
           }
         //--- OCO pair creation flag
         bool is_to_fire_oco=true;
         //--- check structure filling 
         for(int idx=0;idx<ArraySize(gOrdersProps);idx++)
           {
            //---  if order type is set 
            if(gOrdersProps[idx].order_type!=WRONG_VALUE)
               //---  if volume is set  
               if(gOrdersProps[idx].volume!=WRONG_VALUE)
                  //---  if offset for execution price is set
                  if(gOrdersProps[idx].price_offset!=(uint)WRONG_VALUE)
                     //---  if offset for limit price is set
                     if(gOrdersProps[idx].limit_offset!=(uint)WRONG_VALUE)
                        //---  if stop loss is set
                        if(gOrdersProps[idx].sl!=(uint)WRONG_VALUE)
                           //---  if take profit is set
                           if(gOrdersProps[idx].tp!=(uint)WRONG_VALUE)
                              continue;

            //--- clear OCO pair creation flag 
            is_to_fire_oco=false;
            break;
           }
         //--- create OCO pair?
         if(is_to_fire_oco)
           {
            //--- complete comment fields
            for(int ord_idx=0;ord_idx<ArraySize(gOrdersProps);ord_idx++)
               gOrdersProps[ord_idx].comment=StringFormat("OCO Order %d",ord_idx+1);
            //--- change button properties
            myButton.Text("New pair");
            myButton.Color(clrDarkBlue);
            myButton.ColorBackground(clrLightBlue);
            //--- respond to user actions 
            myButton.Enable();
           }
        }
     }
//--- handling click on button
   else if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- if it is OCO pair creation button
      if(!StringCompare(StringSubstr(sparam,0,6),"myFire"))
         //--- if to respond to user actions
         if(myButton.IsEnabled())
           {
            //--- generate OCO pair creation event
            EventChartCustom(0,ON_OCO,0,0.0,"OCO_fire");
            Print("Command to create new bunch has been received.");
           }
     }
//--- handling new pair initialization command 
   else if(id==CHARTEVENT_CUSTOM+ON_OCO)
     {
      //--- OCO pair initialization
      if(gOco.Init(gOrdersProps,gOcoList.Total()+1))
        {
         PrintFormat("Id of new OCO pair: %I32u",gOco.Id());
         //--- copy pair
         CiOcoObject *ptr_new_oco=new CiOcoObject(gOco);
         if(CheckPointer(ptr_new_oco)==POINTER_DYNAMIC)
           {
            //--- add to list
            int node_idx=gOcoList.Add(ptr_new_oco);
            if(node_idx>-1)
               PrintFormat("Total number of bunch: %d",gOcoList.Total());
            else
               PrintFormat("Error when adding OCO pair %I32u to list!",gOco.Id());
           }
        }
      else
         Print("OCO-orders placing error!");

      //--- clear properties
      Reset();
     }
  }

Il codice del gestore non è piccolo. Vorrei porre l'accento su diversi blocchi.

La prima gestione di tutti gli eventi del grafico viene data alla finestra di dialogo principale.

Di seguito sono i blocchi di vari eventi che gestiscono:

  • Modifica degli elenchi a discesa per la definizione di un tipo di ordine;
  • Modifica dei campi di input per riempire le proprietà degli ordini;
  • Fare clic sul pulsante per ON_OCO generazione di eventi;
  • ON_OCO risposta all'evento: creazione di coppie di ordini.

L'EA non verifica la correttezza della compilazione dei campi del pannello. Questo è il motivo per cui dobbiamo controllare i valori da soli, altrimenti l'EA mostrerà l'errore di inserimento degli ordini OCO.

La necessità di rimuovere la coppia e chiudere l'ordine rimanente viene verificata nel corpo del gestore OnTrade().


Conclusione

Ho cercato di dimostrare le ricchezze delle classi Standard Library che possono essere utilizzate per l'adempimento di alcuni compiti specifici.

In particolare, avevamo a che fare con un problema di gestione degli ordini OCO. Spero che il codice dell'EA con Panel per la gestione degli ordini OCO sia un punto di partenza per la creazione di coppie di ordini più complicate.


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

File allegati |
ciocoobject.mqh (27.71 KB)
crandom.mqh (5.19 KB)
init_oco.mq5 (6.42 KB)
control_oco_ea.mq5 (7.88 KB)
panel_oco_ea.mq5 (30.25 KB)
Creazione di un'applicazione interattiva per visualizzare feed RSS in MetaTrader 5 Creazione di un'applicazione interattiva per visualizzare feed RSS in MetaTrader 5
In questo articolo esaminiamo la possibilità di creare un'applicazione per la visualizzazione di feed RSS. L'articolo mostrerà come gli aspetti della Libreria Standard possono essere utilizzati per creare programmi interattivi per MetaTrader 5.
Sui metodi di analisi tecnica e previsione di mercato Sui metodi di analisi tecnica e previsione di mercato
L'articolo dimostra le capacità e il potenziale di un noto metodo matematico abbinato al pensiero visivo e a una prospettiva di mercato "fuori dagli schemi". Da un lato, esso è scritto per attirare l'attenzione di un vasto pubblico, per convincere le menti creative a riconsiderare il paradigma di trading in quanto tale. E dall'altro, può dare origine a sviluppi alternativi e implementazioni di codice di programma per una vasta gamma di strumenti per l'analisi e la previsione.
Idee di trading basate sulla direzione dei prezzi e sulla velocità di movimento Idee di trading basate sulla direzione dei prezzi e sulla velocità di movimento
L'articolo fornisce la revisione di un'idea basata sull'analisi della direzione del movimento dei prezzi e della loro velocità. Abbiamo eseguito la sua formalizzazione nel linguaggio MQL4 presentato come Expert Advisor per esplorare la fattibilità della strategia in esame. Determiniamo anche i migliori parametri tramite controllo, esame e ottimizzazione dell’esempio fornito nell'articolo.
La regola d'oro dei trader La regola d'oro dei trader
Per realizzare profitti basati su aspettative elevate, dobbiamo comprendere tre principi di base del buon trading: 1) conoscere il tuo rischio quando entri nel mercato; 2) minimizzare le perdite in anticipo e continuare ad avere profitti; 3) conoscere le aspettative del sistema - testarlo e regolarlo ad intervalli regolari. Questo articolo fornisce un codice di programma che segue le posizioni aperte e attualizza il secondo principio d'oro, in quanto consente al profitto di correre per il livello più alto possibile.