Creatore di griglie 1.1 - pagina 4

 
Scusa Cori, ho solo un ordine per ogni posizione della griglia e ho testato quasi tutte le variazioni, per diverse settimane.

Di tanto in tanto cancello tutti gli ordini aperti in modo che i nostri amici di MT4 non si arrabbino.

avrai questo problema nel backtesting ma questo non è un problema di script... ma un problema di backtesting di MT4.

Se continua, per favore fammi sapere o mandami qualche report che mostri il problema...

grazie e reagrds,

hugues
 
L'ho trovato. E la cosa non mi diverte.

Il consulente sta creando la griglia con il mio commento "GridEURUSD". Questo commento rimane nel campo di commento finché l'ordine è in attesa. Se l'ordine viene attivato, il commento cambia in "activate/auto". Dopo tutto è chiaro che questo comportamento porta al problema descritto.

Faccio trading con Alpari. Supportano MT4 nei conti demo.

Controllerò se posso aggirare questo comportamento, cioè usare la magia dell'ordine come identificatore per la griglia e vi farò sapere i risultati.

Durante il test di questo, ho anche apportato modifiche allo script di pulizia della griglia. Ho aggiunto anche la funzionalità per chiudere gli ordini aperti. Purtroppo ottengo l'errore 129 che significa Ordine bloccato, se provo a chiudere un ordine aperto. Ma cancella tutti gli ordini in sospeso per la griglia data.

//+------------------------------------------------------------------+ //| RemoveGrid.mq4 | //| Copyright © 2005, hdb | //| http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" extern string GridName = "Grid"; extern bool closeOpen = false; //+------------------------------------------------------------------+ //| funzione inizio programma script | //+------------------------------------------------------------------+ int start() { #property show_inputs // mostra i parametri - grazie Slawa... 

//---- int total = OrdersTotal(); int i ; for(i=total-1; i>=0;i--) { OrderSelect(i, SELECT_BY_POS); int type = OrderType(); if ( OrderSymbol()==Symbol() && OrderComment() == GridName ) { bool result = false; switch(type) { case OP_BUY : if ( closeOpen ) { result = OrderClose( OrderTicket(), OrderLots(), Ask, 0, Blue ); } break; case OP_SELL : if ( closeOpen ) { result = OrderClose( OrderTicket(), OrderLots(), Bid, 0, Blue ); } break; //Chiude gli ordini in sospeso case OP_BUYLIMIT : result = OrderDelete( OrderTicket() ); break; case OP_BUYSTOP : result = OrderDelete( OrderTicket() ); break; case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); break; case OP_SELLSTOP : result = OrderDelete( OrderTicket() ); break; } if(result == false) { Print("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() ); // Sleep(3000); } }  
        } } //---- return(0); } //+------------------------------------------------------------------+




cori

 
ok cori, grazie ...

fammi sapere se funziona e userò la magia ... perché non sapevo che il broker fa cose strane come questa!

grazie e saluti,

hugues
 
Ecco, questo è quanto.

Ho cambiato il gridMaker per usare l'OrderMagicNumber invece del commento. Ho anche fatto qualche piccola modifica sulla costruzione del commento.

Ecco il risultato.

//+------------------------------------------------------------------+ //| MakeGrid.mq4 | //| Copyright © 2005, hdb | //| http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" //#property version "1.4beta" // modificato da cori. Usare OrderMagicNumber per identificare i trade della griglia extern int uniqueGridMagic = 11111; // numero magico dei trade. deve essere unico per identificare // i trade di una griglia extern double Lots = 0.1; // extern double GridSize = 6; // pip tra gli ordini - dimensione della griglia o della maglia extern double GridSteps = 12; // numero totale di ordini da piazzare extern double TakeProfit = 6 ; // numero di tick per prendere profitto. normalmente è = dimensione della griglia ma si può sovrascrivere extern double StopLoss = 0; // se si vuole aggiungere uno stop loss. le griglie normali non usano stop loss extern double UpdateInterval = 1; // aggiorna gli ordini ogni x minuti extern bool wantLongs = true; // vogliamo posizioni long extern bool wantShorts = true; // vogliamo posizioni short extern bool wantBreakout = true;       // vogliamo posizioni lunghe sopra il prezzo, corte sotto il prezzo extern bool wantCounter = true; // vogliamo posizioni lunghe sotto il prezzo, corte sopra il prezzo extern bool limitEMA34 = false; // vogliamo posizioni lunghe solo sopra l'ema, corte solo sotto l'ema // modificato da cori. solo variabili interne double LastUpdate = 0; // contatore usato per annotare l'ora dell'ultimo aggiornamento double GridMaxOpen = 0; // numero massimo di posizioni aperte string GridName = "Grid"; // identifica la griglia. permette diverse griglie coesistenti //+------------------------------------------------------------------+ //| funzione di inizializzazione esperto | //+------------------------------------------------------------------+ int init() { //---- #property show_inputs // mostra i parametri - grazie Slawa...    
 if ( TakeProfit <= 0 ) // { TakeProfit = GridSize; } //---- GridName = StringConcatenate( "Grid", Symbol() ); return(0);
  } //+------------------------------------------------------------------------+ //| testa se c'è una posizione aperta o un ordine nella regione di atRate | //| controllerà per i long se checkLongs è vero, altrimenti controllerà | //| per gli short | //+------------------------------------------------------------------------+ bool IsPosition(double atRate, double inRange, bool checkLongs ) { int totalorders = OrdersTotal(); for(int j=0;j<totalorders;j++) // scansiona tutti gli ordini e posizioni... { OrderSelect(j, SELECT_BY_POS); // modificato da cori. Usare OrderMagicNumber per identificare i trade della griglia if ( OrderSymbol()==Symbol() && OrderMagicNumber() == uniqueGridMagic )  // cerca solo se mygrid e simbolo... { int type = OrderType(); if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // non cerca il prezzo esatto ma la prossimità del prezzo (meno di gridsize) { if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT || type == OP_SELLSTOP ) ) ) { return(true); } } } } 

   return(false); } //+------------------------------------------------------------------+ //| funzione inizio programma script | //+------------------------------------------------------------------+ int start() { //---- int i, j,k, ticket, entermode, totalorders; bool doit; double point, startrate, traderate; //---- if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) // aggiorniamo la prima volta che viene chiamata e ogni minuto di UpdateInterval { LastUpdate = CurTime();
   Print("Updating"); point = MarketInfo(Symbol(),MODE_POINT); startrate = ( Ask + point*GridSize/2 ) / point / GridSize; // arrotonda a un numero di tick divisibile per GridSize k = startrate ; k = k * GridSize ; startrate = k * point - GridSize*GridSteps/2*point ;          // calcola il punto di entrata più basso double EMA34=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE,0); for( i=0;i<GridSteps;i++) { traderate = startrate + i*point*GridSize; if ( wantLongs && (!limitEMA34 || traderate > EMA34)) { if ( IsPosition(traderate,point*GridSize,true) == false )           // testate se non ho ordini aperti vicino al mio prezzo: se sì, mettetene uno { double myStopLoss = 0; if ( StopLoss > 0 ) { myStopLoss = traderate-point*StopLoss ; } if ( traderate > Ask ) { entermode = OP_BUYSTOP; } 
              else { entermode = OP_BUYLIMIT ; } 
              
              if ( ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter)) ) 

              { // modificato da cori. Usando OrderMagicNumber per identificare i trade della griglia ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green); } } } if ( wantShorts && (!limitEMA34 || traderate < EMA34)) { if (IsPosition(traderate,point*GridSize,false)== false )           // testate se non ho ordini aperti vicino al mio prezzo: se sì, mettetene uno { myStopLoss = 0; if ( StopLoss > 0 ) { myStopLoss = traderate+point*StopLoss ; } if ( traderate > Bid ) { entermode = OP_SELLLIMIT; } 
              else { entermode = OP_SELLSTOP ; } 
              
              if ( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) ) 
               { // modificato da cori. Usando OrderMagicNumber per identificare le operazioni della griglia ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red); } } } } return(0); } //+------------------------------------------------------------------+



con i saluti, cori

 
grazie cori...

dato che avevo già fatto alcune modifiche io stesso, ho integrato le tue modifiche nella versione più recente.

Ho fatto 1 piccola variazione: per mantenere attive le mie attuali griglie, ho messo un test su magic OR gridname...

puoi controllare se ho fatto bene?



//+------------------------------------------------------------------+ //| MakeGrid.mq4 | //| Copyright © 2005, hdb | //| http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" //#property version "1.6beta" // modificato da cori. Usare OrderMagicNumber per identificare i trade della griglia extern int uniqueGridMagic = 11111; // numero magico dei trade. deve essere unico per identificare // i trade di una griglia extern double Lots = 0.1; // extern double GridSize = 6; // pip tra gli ordini - dimensione della griglia o della maglia extern double GridSteps = 12; // numero totale di ordini da piazzare extern double TakeProfit = 12 ; // numero di tick per prendere profitto. normalmente è = dimensione della griglia ma si può sovrascrivere extern double StopLoss = 0; // se si vuole aggiungere uno stop loss. le griglie normali non usano stop loss extern double UpdateInterval = 1; // aggiorna gli ordini ogni x minuti extern bool wantLongs = true; // vogliamo posizioni long extern bool wantShorts = false; // vogliamo posizioni short extern bool wantBreakout = true;     // vogliamo posizioni lunghe sopra il prezzo, corte sotto il prezzo extern bool wantCounter = true; // vogliamo posizioni lunghe sotto il prezzo, corte sopra il prezzo extern bool limitEMA34 = true; // vogliamo posizioni lunghe solo sopra l'ema, corte solo sotto l'ema extern double GridMaxOpen = 0; // numero massimo di posizioni aperte : non ancora implementato.. extern bool UseMACD = true; // se true, userà macd >0 solo per i long, macd >0 solo per i short // su crossover, cancellerà tutti gli ordini pendenti. Questo sovrascriverà qualsiasi // impostazione di wantLongs e wantShort - almeno per ora. extern bool CloseOpenPositions = false;// se UseMACD, chiudiamo anche le posizioni aperte con una perdita? // modificato da cori. solo variabili interne string GridName = "Grid"; // identifica la griglia. permette di avere diverse griglie coesistenti double LastUpdate = 0; // contatore usato per annotare il tempo dell'ultimo aggiornamento //+------------------------------------------------------------------+ //| funzione di inizializzazione esperta | //+------------------------------------------------------------------+ int init() { //---- #property show_inputs // mostra i parametri - grazie Slawa...    
 if ( TakeProfit <= 0 ) // { TakeProfit = GridSize; } //---- // aggiunto il mio corri e rimosso da hdb!! lol.. solo per rimanere compatibile con le griglie aperte...
// GridName = StringConcatenate( "Grid", Symbol() ); return(0); } //+------------------------------------------------------------------------+ //| testa se c'è una posizione aperta o un ordine nella regione di atRate | //| controllerà i long se checkLongs è vero, altrimenti controllerà | //| gli short | //+------------------------------------------------------------------------+ bool IsPosition(double atRate, double inRange, bool checkLongs ) { int totalorders = OrdersTotal();
     for(int j=0;j<totalorders;j++) // scansiona tutti gli ordini e le posizioni... { OrderSelect(j, SELECT_BY_POS); // modificato da cori. Utilizzando OrderMagicNumber per identificare i trade della griglia // hdb aggiunto o gridname per compatibilità if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // cerca solo se mygrid e simbolo... { int type = OrderType(); if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // non cerca il prezzo esatto ma la prossimità del prezzo (meno di gridsize) { if ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT || type == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT || type == OP_SELLSTOP ) ) ) { return(true); } } } } 
   return(false); } //+------------------------------------------------------------------------+ //| cancella tutti gli ordini pendenti | //+------------------------------------------------------------------------+ void CloseAllPendingOrders( ) { int totalorders = OrdersTotal(); for(int j=totalorders-1;j>=0;j--) // analizza tutti gli ordini e le posizioni... { OrderSelect(j, SELECT_BY_POS); // modificato come da cori. Utilizzando OrderMagicNumber per identificare i trade della griglia // hdb aggiunto o gridname per compatibilità if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // guarda solo se mygrid e symbol...
         { int type = OrderType(); bool result = false; switch(type) { case OP_BUY : result = true ; case OP_SELL : result = true ; //Chiude gli ordini in sospeso case OP_BUYLIMIT : result = OrderDelete( OrderTicket() ); case OP_BUYSTOP : result = OrderDelete( OrderTicket() ); case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); case OP_SELLSTOP : result = OrderDelete( OrderTicket() ); } } } 
   return; } //+------------------------------------------------------------------------+ //| cancella tutti gli ordini pendenti e chiude le posizioni aperte | //+------------------------------------------------------------------------+ void CloseOpenOrders() { int total = OrdersTotal(); for(int i=total-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS); int type = OrderType(); bool result = false; // modificato da cori. Utilizzando OrderMagicNumber per identificare i trade della griglia // hdb aggiunto o gridname per compatibilità if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // guarda solo se mygrid e symbol...
     { // Print("Closing 2 ",type); switch(type) { //Chiude le posizioni lunghe aperte caso OP_BUY : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red ); break; //Chiude le posizioni corte aperte caso OP_SELL : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red ); break; //Chiude gli ordini pendenti caso OP_BUYLIMIT : caso OP_BUYSTOP :
           case OP_SELLLIMIT : case OP_SELLSTOP : result = OrderDelete( OrderTicket() ); } } if(result == false) { // Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() ); // Sleep(3000); } }  
  } return; } //+------------------------------------------------------------------+ //| funzione inizio programma script | //+------------------------------------------------------------------+ int start() { //---- int i, j,k, ticket, entermode, totalorders; bool doit; double point, startrate, traderate; //---- if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) // aggiorniamo la prima volta che viene chiamata e ogni minuto di UpdateInterval { LastUpdate = CurTime();
   point = MarketInfo(Symbol(),MODE_POINT); startrate = ( Ask + point*GridSize/2 ) / point / GridSize; // arrotonda a un numero di tick divisibile per GridSize k = startrate ; k = k * GridSize ;
   startrate = k * punto - GridSize*GridSteps/2*punto ; // calcola il punto di entrata più basso double EMA34=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE,0); if ( UseMACD ) { double Macd0=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
      double Macd1=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); double Macd2=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,2); if( Macd0>0 && Macd1>0 && Macd2<0) // cross up { CloseAllPendingOrders();
         if ( CloseOpenPositions == true ) { CloseOpenOrders(); } } if( Macd0<0 && Macd1<0 && Macd2>0) // cross down { CloseAllPendingOrders(); if ( CloseOpenPositions == true ) { CloseOpenOrders(); } } } wantLongs = false; wantShorts = false; if( Macd0>0 && Macd1>0 && Macd2>0) // è ben sopra lo zero { wantLongs = true; } if( Macd0<0 && Macd1<0 && Macd2<0) // è ben al di sotto dello zero { wantShorts = true; } } for( i=0;i<GridSteps;i++) { traderate = startrate + i*point*GridSize; if ( wantLongs && (!limitEMA34 || traderate > EMA34)) { if ( IsPosition(traderate,point*GridSize,true) == false )           // testate se non ho ordini aperti vicino al mio prezzo: se sì, mettetene uno { double myStopLoss = 0; if ( StopLoss > 0 ) { myStopLoss = traderate-point*StopLoss ; } if ( traderate > Ask ) { entermode = OP_BUYSTOP; } 
              else { entermode = OP_BUYLIMIT ; } 
              if ( ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter)) ) 
              { // modificato da cori. Usando OrderMagicNumber per identificare le operazioni della griglia ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green); } } } if ( wantShorts && (!limitEMA34 || traderate < EMA34)) { if (IsPosition(traderate,point*GridSize,false)== false )           // testate se non ho ordini aperti vicino al mio prezzo: se sì, mettetene uno { myStopLoss = 0; if ( StopLoss > 0 ) { myStopLoss = traderate+point*StopLoss ; } if ( traderate > Bid ) { entermode = OP_SELLLIMIT; } 
              else { entermode = OP_SELLSTOP ; } 
              
              if ( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) ) 
                { // modificato da cori. Usando OrderMagicNumber per identificare le operazioni della griglia ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red); } } } } return(0); } //+------------------------------------------------------------------+
 
Ciao hdb,

sembra ok. Ma dovresti definire il GridName come extern, che ho cambiato, perché non mi serviva come parametro.

saluti, cori
 
ATTENZIONE a tutti gli utenti di GridMaker - c'è un bug nella funzione IsPosition - il risultato è che non tutti gli slot della griglia sono riempiti.

Potete cambiare la linea:

if (MathAbs( OrderOpenPrice() - atRate ) < inRange) // non cercare il prezzo esatto ma la prossimità del prezzo (meno della gridsize)

a

if (MathAbs( OrderOpenPrice() - atRate ) < (inRange*0.9)) // non cercare il prezzo esatto ma la vicinanza del prezzo (meno della dimensione della griglia) - aggiunto 0.9 a causa di errori di pont fluttuante


e questo corregge il problema.

Mi dispiace per qualsiasi inconveniente...

abbracci
 
Ciao hugues,

Questo problema è già presente?

Ho trovato qualcosa di simile nel vecchio MQL2.

Il modo davvero sicuro per aggirare questo problema è quello di fare qualcosa come

intOOP = MathRound( OrdeOpenPrice() / Point );

per tutte le vostre variabili doppie. Allora avete tutte le variabili int diritte che sono comparabili senza errori.

È un po' più da scrivere per mantenerlo chiaro e comprensibile, ma è meno difettoso.

con i saluti,

cori
 
Hai ragione Cori, è molto più elegante! Sono solo io che sono pigro!

saluti,
abbracci
 
Ecco un aggiornamento del GridMaker EA. In questa versione ho:

1) cambiato la logica per UseMACD, wantLongs, wantShorts. In precedenza, se useMACD era impostato, l'EA prendeva long e short, indipendentemente dai flag wnatLongs e wantShorts. Ora, useMACD non sovrascrive queste bandiere in modo da poter essere solo long con useMACD o solo short.

2) Ho aggiunto un ulteriore controllo per assicurarmi che non ci fossero ordini aperti dalla parte sbagliata dell'EMA se il limitEMA34 era impostato. Quello che succedeva era che gli ordini erano ben piazzati sopra o sotto l'EMA ma dopo qualche ora l'EMA si spostava... quindi c'erano ordini su entrambi i lati dell'EMA.

3) Sembra che ci sia un bug nell'istruzione switch su OrderType()... non sono sicuro di cosa sia ma si comporta in modo strano. Ho semplicemente eliminato le istruzioni di switch e le ho sostituite con "if"... non mi piace ma funziona!

4) Ho reso il periodo EMA variabile... bello per il backtesting...

Ho anche alcuni script di accompagnamento se qualcuno vuole:

1) per rimuovere gli ordini aperti non completati per una coppia
2) per rimuovere tutti gli ordini aperti per tutte le coppie in una sola volta
3) per chiudere tutte le posizioni e rimuovere gli ordini aperti.
4) per ottenere alcune semplici statistiche sul comportamento della griglia dalle posizioni aperte e dallo storico.

Ecco il codice della V1.08:


//+------------------------------------------------------------------+ //| MakeGrid.mq4 | //| Copyright © 2005, hdb | //|
http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" //#property version "1.8" // DISCLAIMER ***** NOTA IMPORTANTE ***** LEGGERE PRIMA DI UTILIZZARE ***** // Questo expert advisor può aprire e chiudere posizioni reali e quindi fare operazioni reali e perdere denaro reale.
// Questo non è un 'trading system' ma un semplice robot che piazza operazioni secondo regole fisse. // L'autore non ha alcuna pretesa sulla redditività di questo sistema e non suggerisce l'uso // di questo EA se non per scopi di test in conti demo. // L'uso di questo sistema è gratuito - ma non si può rivenderlo - e non è garantito per quanto riguarda la sua // idoneità a qualsiasi scopo.
// Usando questo programma riconoscete implicitamente di aver capito cosa fa e accettate che // l'autore non si assume alcuna responsabilità per eventuali perdite. // Prima di usarlo, controllate anche con il vostro broker che i suoi sistemi siano adatti alle operazioni più frequenti // associate a questo esperto. // 1.8 changes // made wantLongs and wantShorts into local variables. In precedenza, se si impostava UseMACD su true, // faceva long e short e ignorava semplicemente i flag wantLongs e wantShorts. 
// Ora, questi flag non sono ignorati. // aggiunto un ciclo per controllare se ci sono ordini aperti 'illeciti' sopra o sotto l'EMA quando viene usato il flag limitEMA34 // . Questi si accumulano nel tempo e non vengono mai rimossi ed è dovuto al movimento dell'EMA. // rimossa l'istruzione switch in quanto non sembra funzionare - sostituita con istruzioni if // reso il periodo EMA variabile // // // modificato da cori. Utilizzando OrderMagicNumber per identificare i trade della griglia extern int uniqueGridMagic = 11111; // numero magico dei trade. deve essere unico per identificare // i trade di una griglia extern double Lots = 0.1; // extern double GridSize = 6; // pip tra gli ordini - dimensione della griglia o della maglia extern double GridSteps = 12; // numero totale di ordini da piazzare extern double TakeProfit = 12 ; // numero di tick per prendere profitto. normalmente è = dimensione della griglia ma si può sovrascrivere extern double StopLoss = 0; // se si vuole aggiungere uno stop loss. le griglie normali non usano stop loss extern double UpdateInterval = 1; // aggiorna gli ordini ogni x minuti extern bool wantLongs = true; // vogliamo posizioni long extern bool wantShorts = true; // vogliamo posizioni short extern bool wantBreakout = true;     // vogliamo posizioni lunghe sopra il prezzo, corte sotto il prezzo extern bool wantCounter = true; // vogliamo posizioni lunghe sotto il prezzo, corte sopra il prezzo extern bool limitEMA = true; // vogliamo posizioni lunghe solo sopra l'ema, corte solo sotto l'ema extern int EMAperiod = 34; // la lunghezza dell'EMA.. era precedentemente fissata a 34 extern double GridMaxOpen = 0; // numero massimo di posizioni aperte: non ancora implementato... extern bool UseMACD = true; // se true, userà macd >0 solo per i long, macd >0 solo per gli short // su crossover, cancellerà tutti gli ordini pendenti. Questo sovrascriverà qualsiasi // impostazione di wantLongs e wantShort - almeno per ora. extern bool CloseOpenPositions = false;// se UseMACD, chiudiamo anche le posizioni aperte con una perdita? extern bool doHouseKeeping = true; // solo un test // modificato da cori. solo variabili interne string GridName = "Grid"; // identifica la griglia. permette diverse griglie coesistenti double LastUpdate = 0; // contatore usato per notare il tempo dell'ultimo aggiornamento //+------------------------------------------------------------------+ //| funzione di inizializzazione esperta | //+------------------------------------------------------------------+ int init() { //---- #property show_inputs // mostra i parametri - grazie Slawa...    
//---- // aggiunto il mio corri e rimosso da hdb!! lol.. solo per rimanere compatibile con le griglie aperte...
// GridName = StringConcatenate( "Grid", Symbol() ); return(0); } //+------------------------------------------------------------------------+ //| testa se c'è una posizione aperta o un ordine nella regione di atRate | //| controllerà i long se checkLongs è vero, altrimenti controllerà | //| gli short | //+------------------------------------------------------------------------+ bool IsPosition(double atRate, double inRange, bool checkLongs ) { int totalorders = OrdersTotal();
     for(int j=0;j<totalorders;j++) // scansiona tutti gli ordini e le posizioni... { OrderSelect(j, SELECT_BY_POS); // modificato da cori. Utilizzando OrderMagicNumber per identificare i trade della griglia // hdb aggiunto o gridname per compatibilità if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // cerca solo se mygrid e simbolo... { int type = OrderType(); if (MathAbs( OrderOpenPrice() - atRate ) < (inRange*0.9)) // non cercare il prezzo esatto ma la prossimità del prezzo (meno di gridsize) - aggiunto 0.9 a causa di errori in virgola mobile { if ( ( checkLongs && ( tipo == OP_BUY || tipo == OP_BUYLIMIT || tipo == OP_BUYSTOP ) )  || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT || type == OP_SELLSTOP ) ) ) { return(true); } } } } 
   return(false); } //+------------------------------------------------------------------------+ //| cancella tutti gli ordini pendenti | //+------------------------------------------------------------------------+ void CloseAllPendingOrders( ) { int totalorders = OrdersTotal(); for(int j=totalorders-1;j>=0;j--) // analizza tutti gli ordini e le posizioni... { OrderSelect(j, SELECT_BY_POS); // modificato come da cori. Utilizzando OrderMagicNumber per identificare i trade della griglia // hdb aggiunto o gridname per compatibilità if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // guarda solo se mygrid e symbol... { int type = OrderType(); if ( type > 1 ) bool result = OrderDelete( OrderTicket() ); } } } 
   return; } //+------------------------------------------------------------------------+ //| cancella tutti gli ordini pendenti e chiude le posizioni aperte | //+------------------------------------------------------------------------+ void CloseOpenOrders() { int total = OrdersTotal(); for(int i=total-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS); int type = OrderType(); bool result = false; // modificato da cori. Utilizzando OrderMagicNumber per identificare i trade della griglia // hdb aggiunto o gridname per compatibilità if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // guarda solo se mygrid e simbolo...
     { //Chiude le posizioni lunghe aperte if ( type == OP_BUY ) result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red );
           //Chiude le posizioni short aperte if ( type == OP_SELL ) result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red ); //Chiude gli ordini pendenti if ( type > 1 ) result = OrderDelete( OrderTicket() ); } } return;
} //+------------------------------------------------------------------------+ //| cancella tutti gli ordini aperti che cadono sul lato sbagliato dell'EMA | //+------------------------------------------------------------------------+ void CloseOrdersfromEMA( double theEMAValue ) { int totalorders = OrdersTotal(); for(int j=totalorders-1;j>=0;j--) // analizza tutti gli ordini e posizioni... { OrderSelect(j, SELECT_BY_POS); if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) )  // guarda solo se mygrid e symbol...
         { int type = OrderType(); bool result = false; //if (type > 1) Print(type," ",theEMAValue," ",OrderOpenPrice()); if ( type == OP_BUYLIMIT && OrderOpenPrice() <= theEMAValue ) result = OrderDelete( OrderTicket() ); if ( type == OP_BUYSTOP && OrderOpenPrice() <= theEMAValue ) result = OrderDelete( OrderTicket() ); if ( type == OP_SELLLIMIT && OrderOpenPrice() >= theEMAValue ) result = OrderDelete( OrderTicket() ); if ( type == OP_SELLSTOP && OrderOpenPrice() >= theEMAValue ) result = OrderDelete( OrderTicket() ); } } 
   return; } //+------------------------------------------------------------------+ //| funzione inizio programma script | //+------------------------------------------------------------------+ int start() { //---- int i, j,k, ticket, entermode, totalorders; bool doit; double point, startrate, traderate; //---- parametri di setup if ( TakeProfit <= 0 ) // { TakeProfit = GridSize; } bool myWantLongs = wantLongs;
 bool myWantShorts = wantShorts; //---- if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) // aggiorniamo la prima volta che viene chiamato e ogni minuto di UpdateInterval { LastUpdate = CurTime();
   point = MarketInfo(Symbol(),MODE_POINT); startrate = ( Ask + point*GridSize/2 ) / point / GridSize; // arrotonda a un numero di tick divisibile per GridSize k = startrate ; k = k * GridSize ; startrate = k * point - GridSize*GridSteps/2*point ;          // calcolare il punto di entrata più basso double myEMA=iMA(NULL,0,EMAperiod,0,MODE_EMA,PRICE_CLOSE,0); if (limitEMA) { if (doHouseKeeping) CloseOrdersfromEMA(myEMA); } if ( UseMACD ) { double Macd0=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
      double Macd1=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); double Macd2=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,2); if( Macd0>0 && Macd1>0 && Macd2<0) // cross up { CloseAllPendingOrders(); if ( CloseOpenPositions == true ) { CloseOpenOrders(); } } } if( Macd0<0 && Macd1<0 && Macd2>0) // cross down { CloseAllPendingOrders();
         if ( CloseOpenPositions == true ) { CloseOpenOrders(); } } } myWantLongs = false; myWantShorts = false; if( Macd0>0 && Macd1>0 && Macd2>0 && wantLongs )     // è ben al di sopra dello zero { myWantLongs = true; } if( Macd0<0 && Macd1<0 && Macd2<0 && wantShorts )     // è ben al di sotto dello zero { myWantShorts = true; } } for( i=0;i<GridSteps;i++) { traderate = startrate + i*point*GridSize; if ( myWantLongs && (!limitEMA || traderate > myEMA)) { if ( IsPosition(traderate,point*GridSize,true) == false )           // testate se non ho ordini aperti vicino al mio prezzo: se sì, mettetene uno { double myStopLoss = 0; if ( StopLoss > 0 ) { myStopLoss = traderate-point*StopLoss ; } if ( traderate > Ask ) { entermode = OP_BUYSTOP; } 
              else { entermode = OP_BUYLIMIT ; } 
              if ( ((traderate > Ask ) && (wantBreakout)) || ((traderate <= Ask ) && (wantCounter)) ) 
              { // modificato da cori. Usando OrderMagicNumber per identificare le operazioni della griglia ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate+point*TakeProfit,GridName,uniqueGridMagic,0,Green); } } } if ( myWantShorts && (!limitEMA || traderate < myEMA)) { if (IsPosition(traderate,point*GridSize,false)== false )           // testate se non ho ordini aperti vicino al mio prezzo: se sì, mettetene uno { myStopLoss = 0; if ( StopLoss > 0 ) { myStopLoss = traderate+point*StopLoss ; } if ( traderate > Bid ) { entermode = OP_SELLLIMIT; } 
              else { entermode = OP_SELLSTOP ; } 
              
              if ( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) ) 
                { // modificato da cori. Usando OrderMagicNumber per identificare le operazioni della griglia ticket=OrderSend(Symbol(),entermode,Lots,traderate,0,myStopLoss,traderate-point*TakeProfit,GridName,uniqueGridMagic,0,Red); } } } } return(0); } //+------------------------------------------------------------------+