consulente esperto - domande varie - pagina 24

 

È già nell'esempio.

Quando si chiude l'ordine si usa il valore booleano di ritorno della funzione OrderClose(), e se la funzione ha avuto successo, si possono rimuovere gli oggetti relativi all'ordine.

                           bool close=OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,clrBlue);
                             {
                              if(close==0)
                                {
                                 Alert(" Order Close Error! # "+IntegerToString(OrderTicket()));
                                }
                              if(close==1)
                                {
                                 Alert(" Order: "+IntegerToString(OrderTicket())+" Closed due to TP Profit = "+DoubleToString(OrderProfit(),2));
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
                                }
                             }
 
Marco vd Heijden:

È già nell'esempio.
Quando chiudi l'ordine usi il valore booleano di ritorno della funzione OrderClose(), e se la funzione ha avuto successo, puoi rimuovere gli oggetti relativi all'ordine.

Lo so già, ho già provato. Forse ho fatto qualcosa di sbagliato. Proverò ancora una volta, ma prima di chiedere non vorrei usare OrderClose(). ( a volte chiudo gli ordini manualmente )
D: Quindi, posso cancellare gli oggetti ordine dopo che l'ordine è stato chiuso senza OrderClose()?

Grazie in anticipo.

 

Bene, il valore di ritorno della funzione Order Close() decide se l'azione ha avuto successo o meno, quindi se chiudi l'ordine manualmente dovrai progettare e usare un meccanismo leggermente diverso.

Puoi fare una copia ombra dell'elenco degli ordini e confrontarla con l'elenco attuale, e ogni volta che qualcosa cambia perché hai chiuso un ordine manualmente, cercare cosa è cambiato e poi rimuovere quegli oggetti.

Ma un modo più semplice potrebbe essere quello di controllare se l'OrderTicket() esiste ancora nel pool degli ordini attivi, così quando sparisce perché hai chiuso l'ordine manualmente, gli oggetti saranno automaticamente rimossi.

Quindi dipende da come vuoi impostare la cosa.

A questo punto direi che dovresti cercare di guardare oltre a ciò che vuoi farci alla fine perché la direzione che prendi è in qualche modo legata a compiti aggiuntivi che potresti voler aggiungere in seguito.


Dato che la creazione degli oggetti è già completamente automatizzata, ti suggerisco di fare lo stesso per la rimozione degli oggetti, così non dovrai preoccupartene in futuro.

Per questo puoi semplicemente usare

OrdersHistoryTotal()

E il pool della storia

MODE_HISTORY

È semplice, il pool della storia degli ordini viene scansionato, e ad ogni ciclo il codice cercherà di vedere se esiste qualche oggetto collegato al numero OrderTicket(), e se c'è una corrispondenza, gli oggetti vengono automaticamente cancellati.

Per fare questo basta aggiungere un altro ciclo, ma questa volta sul pool della storia.

Vedi esempio.

//+------------------------------------------------------------------+
//|                                                ObjectsRemove.mq4 |
//|      Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

static input int takeprofit=500;// Take Profit
static input int stoploss=500;  // Stop Loss
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(1);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   for(int order=OrdersTotal(); order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS);
        {
         if(selected==1)
           {
            if(Symbol()==OrderSymbol()) // only for current chart symbol
              {
               switch(OrderType())
                 {
                  case OP_BUY: // for buy order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()+takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()-stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;

                  case OP_SELL: // for sell order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()+stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;
                 }
              }
           }
        }
     }
//+------------------------------------------------------------------+
//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
              }
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
              }
           }
        }
     }
//+------------------------------------------------------------------+    
  } // end OnTimer() function
//+------------------------------------------------------------------+

Così ora avete l'aggiunta completamente automatizzata di linee di take profit e stoploss virtuali, e anche la rimozione completamente automatizzata di queste linee.

Naturalmente questo esempio scansiona continuamente lo storico...

Inoltre si potrebbe aggiungere un intero che contiene il numero di ordini, che viene poi confrontato con OrdersTotal(), e ogni volta che qualcosa cambia si esegue il codice di rimozione dell'oggetto.

Oppure, si potrebbe aggiungere un semplice contatore (60) e poi il codice controllerà solo una volta al minuto, se qualcosa deve essere rimosso.

 

Ehi, amico! Funziona perfettamente! Grazie mille!

Ho solo cambiato un po'. Finora funziona senza problemi.

//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            ObjectsDeleteAll( 0, "#" + IntegerToString( OrderTicket() ) ); // for arrows
            ObjectsDeleteAll( 0, _prefix + " #" + IntegerToString( OrderTicket() ) ); // order, sl, tp, price objects
           }
        }
     }

Se c'è qualcosa che non va fammelo sapere.
Ancora una volta grazie mille, amico!

 

Forse nessuno capisce la mia domanda. Ma ho ancora bisogno di un buon commento per questo. Così ora sto cercando di chiarire la mia domanda con l'immagine.
Domanda: Anche Stop Loss, Take Profit Lines davanti agli oggetti del Trade Panel. So che è stato causato dall'ultima volta che ha creato l'oggetto. Ma se mi capite, per favore fatemi sapere come posso fare l'oggetto Trade Panel dovrebbe essere davanti a tutti gli altri oggetti senza linee "Stop Loss e Take Profit".

Oggetti mescolati

So che posso usare OBJPROP_BACK, ma non voglio usarlo. Ho solo bisogno di vedere linea e prezzo come entrambi. Spero di ottenere un buon commento per questo.


Aprire, Stop Loss, Take Profit, linee di prezzo "Crea e cancella" che sono tutte in una funzione. Così ora sto cercando di dividerlo, perché ho bisogno di mettere quella funzione in OnChartEvent(). Ma prima ho bisogno di chiedere.
D: Se metto quella funzione in OnChartEvent() - così quella funzione non potrebbe avere effetti sui miei ordini manualmente?

Ci sto lavorando ora.

Per favore aiutatemi, grazie in anticipo.

 

No Onchartevent() eseguirà il codice solo quando c'è un evento del grafico, non è come la funzione OnTImer().

Quindi devi sapere esattamente cosa stai facendo.

Per esempio se stai usando il codice di scansione:

if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))

Per controllare se il prezzo ha attraversato la vostra linea questo non funzionerà in OnChartEvent().

Anche se vuoi usare l'esempio automatico

if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
   {
     ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
     ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
   }

Questo non funzionerà e non creerà gli oggetti.

Dovrete riscrivere il codice.

Inoltre, puoi impostare gli oggetti H_LINE su OBJPROP_BACK questo non è un problema li vedrai ancora e saranno sotto il tuo pannello.

 

Commento davvero bello e utile, ora so per certo che dovrei provare almeno una volta per sapere cosa potrei fare in più.

Grazie per la tua rapida risposta e il tuo utile commento.

 
Marco vd Heijden:

Dovrete riscrivere il codice.

( Ho già letto attentamente il tuo commento ma volevo solo provare una volta - alla fine come hai detto tu non funziona come OnTimer(). )

Omg! Devo cambiare tutto in quel codice di blocco?
Ora ho quattro funzioni. Cerco solo di metterle in OnChartEvent(). Ho già provato, vedo solo una cosa che si aggiorna questo è solo Print() per i prezzi di stop loss, take profit.
OrderModify() non funziona in esso.

Inizierò a provare di nuovo qualcosa per questo problema in 8 - 10 ore.
Ho solo bisogno di buoni commenti, spero di ottenerli.

Grazie mille in anticipo.

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG) // I already tried with take profit object - there was not any effects
     {
      SL_TPcreateobjects();
      SL_TPdrags();
      SL_TPmodify();
      deleteobjs();
     }
  }
// if objects not found - create them
SL_TPcreateobjects()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
        {
         ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,takeprofit);
        }
     }
  }
// if objects exist
SL_TPdrags()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
        {
         if(TP_Price!=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
           {
            TP_drag=1;
            TP_Price=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0);
           }
         if(TP_drag==1)
           {
            if(TP_Price==ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
              {
               Print("Take Profit Price:",DoubleToString(TP_Price,Digits));
               TP_drag=0;
              }
           }
        }
     }
  }
// order closed - delete junks
deleteobjs()
{
  for(int i=OrdersHistoryTotal()-1; i>=0; i--)
    {
     bool Selected=OrderSelect(i,SELECT_BY_POS,MODE_HISTORY);
     if(Selected==1)
       {
        ObjectsDeleteAll(0,"#"+IntegerToString(OrderTicket())+"-TP");
       }
    }
}
// ordermodify()
SL_TPmodify()
{
  Order_Modify=OrderModify(OrderTicket(),OrderOpenPrice(),SL_Price,TP_Price,0,CLR_NONE);
}
//+------------------------------------------------------------------+
 

Queste funzioni saranno eseguite solo quando si verifica un chartevent.

Almeno questo è quello che state mostrando qui.

Il chartevent è solo un trigger per una routine di interrupt quando qualcuno preme un pulsante o qualcos'altro sul grafico.

Ora avete preso l'esempio completamente automatizzato e l'avete messo sotto un pulsante, non succederà nulla se nessuno lo preme.

 
Marco vd Heijden:

Queste funzioni saranno eseguite solo quando si verifica un evento grafico.
Almeno questo è quello che state mostrando qui.
Il chartevent è solo un trigger per una routine di interrupt quando qualcuno preme un pulsante o qualcos'altro sul grafico.
Ora avete preso l'esempio completamente automatizzato e l'avete messo sotto un pulsante, non succederà nulla se nessuno lo preme.

È possibile che il tuo ultimo commento sembri così semplice, ma in realtà quel commento mi ha mostrato la strada giusta.
Così ora risolvo il mio problema che cerco di usare il trascinamento.

E ora sto iniziando a fare ricerche su alcuni altri oggetti grafici che si muovono con l'oggetto HLine.

Grazie ancora tanto amico!
Tutto il meglio per te!


honest_knave:

Inoltre, pensa a quanto spesso muovi la linea. È una volta al secondo? Probabilmente no.
Mettete il vostro codice in OnChartEvent():

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG && sparam=="line") // the chart event of dragging the line
Grazie mille amico! Così che il tuo commento mi ha davvero aiutato molto!