I have been working on this simple expert for days, but it does not open any pending orders when you reach the preset levels BestLongPrice or BestShortPrice. Yet the logic is very simple. these values are set, you set whether the direction is long or short and set the entry and exit levels. the end. Is anyone kind enough to help me?
//+------------------------------------------------------------------+//| Ulcer-Index.mq4 |//| Copyright 2024, Michele Guidoni |//| https://www.opinioniprodotto.it |//+------------------------------------------------------------------+#property strict//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+// Definizioni Variabiliinputbool IsLong = true; // Direzione: true per Long, false per Shortinputdouble BestLongPrice; // Livello prezzo migliore per Longinputdouble LongEntryLevel; // Livello di ingresso Longinputdouble LongTarget; // Target Longinputdouble BestShortPrice; // Livello prezzo migliore per Shortinputdouble ShortEntryLevel; // Livello di ingresso Shortinputdouble ShortTarget; // Target Shortinputint CloseAllOrdersHour = 19; // Ora chiusura tutti gli ordiniinputint CancelAllOrdersHour = 19; // Ora cancellazione ordini non apertiinputdouble CapitalManagementPercentage = 5.0; // Gestione capitale in percentualeinputint AdjustTPHour = 19; // Ora del giorno per regolare il TPinputdouble ProfitAdjustmentPercentage = 10.0; // Percentuale di profitto aggiuntivo da aggiungere al pareggioinputint MagicNumber = 12345; // Numero magicoinputint Slippage = 2;
bool longConditionMetAfterEight = false;
bool shortConditionMetAfterEight = false;
int lastDayChecked = 0;
int LongLineHandle, ShortLineHandle;
double currentAskPrice;
double currentBidPrice;
bool bestLongPriceTouched = false;
bool bestShortPriceTouched = false;
intOnInit() {
// Qui va il codice per l'inizializzazione dell'EA
LongLineHandle = -1;
ShortLineHandle = -1;
Print("Ulcer Index è pronto per farti fare un monte di soldi! Tieniti forte!");
return(INIT_SUCCEEDED);
}
voidOnDeinit(constint reason) {
ObjectsDeleteAll(0, OBJ_HLINE);
ObjectsDeleteAll(0, OBJ_TEXT);
ObjectsDeleteAll(0, OBJ_ARROW_UP);
ObjectsDeleteAll(0, OBJ_ARROW_DOWN);
}
voidOnTick() {
datetime now = TimeCurrent();
int currentHour = TimeHour(now);
MqlDateTime str;
TimeToStruct(now, str);
if (str.day != lastDayChecked) {
longConditionMetAfterEight = false;
shortConditionMetAfterEight = false;
lastDayChecked = str.day;
}
if (currentHour < 8) return;
CheckMarketConditions();
if(AreThereOpenOrPendingOrders(_Symbol, IsLong)) {
return;
}
if (IsLong && longConditionMetAfterEight) {
PlaceLongOrder(CalculateLotSize(), LongEntryLevel); // Aggiungi LongEntryLevel come prezzo limite
longConditionMetAfterEight = false;
} elseif (!IsLong && shortConditionMetAfterEight) {
PlaceShortOrder(CalculateLotSize(), ShortEntryLevel); // Aggiungi ShortEntryLevel come prezzo limite
shortConditionMetAfterEight = false;
}
if(currentHour == AdjustTPHour) {
AdjustTakeProfitToBreakEvenPlus();
}
if(currentHour == CancelAllOrdersHour) {
CancelPendingOrders();
}
if(currentHour == CloseAllOrdersHour) {
CloseMarketOrders();
}
}
void CheckMarketConditions() {
CheckHistoricalPriceTouch(); // Verifica se i livelli sono stati toccati dopo le 8 di mattina// Aggiornamento delle variabili globali per riflettere i prezzi correnti di ask e bid
currentBidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); // Aggiornato: Prezzo di offerta per operazioni Short
currentAskPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // Aggiornato: Prezzo di domanda per operazioni Longdatetime now = TimeCurrent();
MqlDateTime str;
TimeToStruct(now, str);
if (str.day != lastDayChecked) {
// Se è un nuovo giorno, resettiamo le condizioni e verifichiamo se i livelli sono stati toccati
longConditionMetAfterEight = false;
shortConditionMetAfterEight = false;
lastDayChecked = str.day;
// Reset dei controlli sui livelli di prezzo raggiunti durante la giornata
bestLongPriceTouched = false;
bestShortPriceTouched = false;
}
int currentHour = TimeHour(now);
if (currentHour >= 8) {
// Aggiorna i flag se i livelli di prezzo sono stati toccati dopo le 8if (!bestLongPriceTouched && currentAskPrice <= BestLongPrice) {
bestLongPriceTouched = true;
Print("BestLongPrice toccato alle ore ", TimeToString(now, TIME_MINUTES));
Alert("BestLongPrice toccato alle ore ", TimeToString(now, TIME_MINUTES));
}
if (!bestShortPriceTouched && currentBidPrice >= BestShortPrice) {
bestShortPriceTouched = true;
Print("BestShortPrice toccato alle ore ", TimeToString(now, TIME_MINUTES));
Alert("BestShortPrice toccato alle ore ", TimeToString(now, TIME_MINUTES));
}
} else {
// Se l'ora corrente è prima delle 8, non eseguiamo alcuna azione relativa ai prezzireturn;
}
// Verifica delle condizioni di mercato senza piazzare ordini direttamente quiif (!AreThereOpenOrPendingOrders(_Symbol, IsLong)) {
if (IsLong && currentAskPrice <= BestLongPrice && currentAskPrice >= LongEntryLevel) {
// Se le condizioni per un ordine Long sono soddisfatte
longConditionMetAfterEight = true;
} elseif (!IsLong && currentBidPrice >= BestShortPrice && currentBidPrice <= ShortEntryLevel) {
// Se le condizioni per un ordine Short sono soddisfatte
shortConditionMetAfterEight = true;
}
}
// Azione basata sulle condizioni verificate in precedenzaif (longConditionMetAfterEight) {
// Se è stata soddisfatta la condizione per un ordine Long dopo le 8
PlaceLongOrder(CalculateLotSize(), LongEntryLevel);
longConditionMetAfterEight = false; // Reset della condizione
} elseif (shortConditionMetAfterEight) {
// Se è stata soddisfatta la condizione per un ordine Short dopo le 8
PlaceShortOrder(CalculateLotSize(), ShortEntryLevel);
shortConditionMetAfterEight = false; // Reset della condizione
}
// Operazioni di routine eseguite a orari specificiif (currentHour == AdjustTPHour) {
AdjustTakeProfitToBreakEvenPlus();
}
if (currentHour == CancelAllOrdersHour) {
CancelPendingOrders();
}
if (currentHour == CloseAllOrdersHour) {
CloseMarketOrders();
}
}
void CheckHistoricalPriceTouch() {
MqlDateTime str;
TimeToStruct(TimeCurrent(), str);
// Assicurati che la verifica venga eseguita solo una volta al giornoif(lastDayChecked == str.day) return; // Se abbiamo già controllato oggi, non eseguire nuovamente
lastDayChecked = str.day; // Aggiorna l'ultimo giorno controllatodatetime todayStart = D'1970.01.01 00:00' + (TimeCurrent() - TimeDay(TimeCurrent())); // Mezzanotte del giorno correntedatetime eightAMToday = todayStart + 8 * 3600; // Calcola le 8 di mattina del giorno corrente// Ottieni l'indice del primo tick dopo le 8 di mattinaint startBar = iBarShift(_Symbol, PERIOD_M1, eightAMToday, true);
// Controlla se il livello BestLongPrice è stato toccato dopo le 8 di mattinafor(int i = startBar; i >= 0; i--) {
double highPrice = iHigh(_Symbol, PERIOD_M1, i);
if(highPrice >= BestLongPrice) {
bestLongPriceTouched = true;
Print("BestLongPrice è stato toccato dopo le 8 di mattina.");
Alert("BestLongPrice è stato toccato dopo le 8 di mattina.");
break; // Interrompi il ciclo una volta trovato
}
}
// Controlla se il livello BestShortPrice è stato toccato dopo le 8 di mattinafor(int i = startBar; i >= 0; i--) {
double lowPrice = iLow(_Symbol, PERIOD_M1, i);
if(lowPrice <= BestShortPrice) {
bestShortPriceTouched = true;
Print("BestShortPrice è stato toccato dopo le 8 di mattina.");
Alert("BestShortPrice è stato toccato dopo le 8 di mattina.");
break; // Interrompi il ciclo una volta trovato
}
}
}
bool AreThereOpenOrPendingOrders(string symbol, bool isLong) {
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == symbol && OrderMagicNumber() == MagicNumber) {
// Verifica per gli ordini pendentiif(isLong && (OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP)) returntrue;
if(!isLong && (OrderType() == OP_SELLLIMIT || OrderType() == OP_SELLSTOP)) returntrue;
// Aggiunto: Verifica per gli ordini a mercato apertiif(isLong && OrderType() == OP_BUY) returntrue;
if(!isLong && OrderType() == OP_SELL) returntrue;
}
}
returnfalse; // Nessun ordine che corrisponde ai criteri trovato
}
void PlaceLongOrder(double lotSize, double price) {
// Eliminiamo il controllo della direzione qui, poiché è già stato verificato prima di chiamare questa funzione// Prepariamo il palcoscenico per l'ordine Longdouble stopLoss = BestLongPrice - (2 * _Point); // Calcoliamo lo stop lossdouble takeProfit = LongTarget; // Definiamo il take profit// Invio dell'ordine BUYLIMIT con le coordinate preciseint ticket = OrderSend(_Symbol, OP_BUYLIMIT, lotSize, price, Slippage, stopLoss, takeProfit, "Long Order", MagicNumber, 0, clrGreen);
if (ticket < 0) {
Print("Errore nell'invio ordine Long: ", GetLastError());
} else {
Print("Ordine Long pendente piazzato con successo.");
}
}
void PlaceShortOrder(double lotSize, double price) {
// Anche qui, il controllo di direzione viene rimosso, assumendo che la decisione sia già stata presa// Luci sulla scena per l'ordine Shortdouble stopLoss = BestShortPrice + (2 * _Point); // Calcolo dello stop lossdouble takeProfit = ShortTarget; // Impostazione del take profit// Invio dell'ordine SELLLIMIT con precisione millimetricaint ticket = OrderSend(_Symbol, OP_SELLLIMIT, lotSize, price, Slippage, stopLoss, takeProfit, "Short Order", MagicNumber, 0, clrRed);
if (ticket < 0) {
Print("Errore nell'invio ordine Short: ", GetLastError());
} else {
Print("Ordine Short pendente piazzato con successo.");
}
}
double CalculateLotSize() {
double accountBalance = AccountBalance(); // Il saldo attuale del contodouble riskPerTrade = accountBalance * (CapitalManagementPercentage / 100.0); // Il rischio per trade in termini monetari// Determiniamo la distanza dello stop loss in pips per un calcolo accurato del rischiodouble stopLossDistance;
if (IsLong) {
stopLossDistance = MathAbs(LongEntryLevel - (BestLongPrice - (2 * _Point))); // Per Long
} else {
stopLossDistance = MathAbs((BestShortPrice + (2 * _Point)) - ShortEntryLevel); // Per Short
}
// Calcoliamo il valore del pip per lotti standard per questo simbolodouble pipValuePerLot = MarketInfo(_Symbol, MODE_TICKVALUE) / MarketInfo(_Symbol, MODE_TICKSIZE);
// Ora, determiniamo la dimensione del lotto basata sul rischio fisso per trade e sulla distanza dello stop lossdouble lotSize = riskPerTrade / (stopLossDistance * pipValuePerLot);
// Assicuriamoci che la dimensione del lotto sia nei limiti consentiti dal brokerdouble minLot = MarketInfo(_Symbol, MODE_MINLOT);
double maxLot = MarketInfo(_Symbol, MODE_MAXLOT);
double lotStep = MarketInfo(_Symbol, MODE_LOTSTEP);
lotSize = MathMax(minLot, MathMin(lotSize, maxLot)); // Confiniamo la dimensione del lotto entro i limiti
lotSize = MathRound(lotSize / lotStep) * lotStep; // Arrotondiamo alla dimensione del lotto permessa più vicinareturn lotSize; // E così, con un grido di sfida, il nostro lotto prende forma
}
void AdjustTakeProfitToBreakEvenPlus() {
datetime now = TimeCurrent();
if(TimeHour(now) != AdjustTPHour) return; // Esegue solo all'ora specificatafor(int i = OrdersTotal()-1; i >= 0; i--) {
if(OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol()) {
if(OrderType() == OP_BUY || OrderType() == OP_SELL) {
double currentProfit = OrderProfit();
double breakEvenPrice = OrderOpenPrice();
double adjustedTP = 0.0;
// Calcolo del nuovo Take Profit basato sulla direzione dell'ordineif(currentProfit > 0) { // Se l'ordine è in profittoif(OrderType() == OP_BUY) {
adjustedTP = breakEvenPrice + (Point * SymbolInfoInteger(Symbol(), SYMBOL_DIGITS) * ProfitAdjustmentPercentage / 100);
} elseif(OrderType() == OP_SELL) {
adjustedTP = breakEvenPrice - (Point * SymbolInfoInteger(Symbol(), SYMBOL_DIGITS) * ProfitAdjustmentPercentage / 100);
}
// Aggiorna il Take Profit solo se il nuovo TP è migliore di quello esistenteif((OrderType() == OP_BUY && adjustedTP > OrderTakeProfit()) || (OrderType() == OP_SELL && adjustedTP < OrderTakeProfit())) {
bool result = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), adjustedTP, 0, clrNONE);
if(!result) {
Print("Errore nella modifica dell'ordine ", OrderTicket(), ": ", GetLastError());
} else {
Print("Take Profit aggiustato per l'ordine ", OrderTicket(), " al prezzo ", adjustedTP);
}
}
}
}
}
}
}
// funzione che cancella tutti gli oridini pendenti ad una precisa ora del giorno, se non siamo entrati a mercatovoid CancelPendingOrders() {
// Ciclo attraverso tutti gli ordinifor(int i = OrdersTotal() - 1; i >= 0; i--) {
if(OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber() == MagicNumber) {
// Verifichiamo che l'ordine sia pendente e corrisponda al nostro numero magicoif(OrderType() == OP_BUYSTOP || OrderType() == OP_SELLSTOP || OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT) {
// Cancella l'ordine pendentebool result = OrderDelete(OrderTicket(), clrRed);
if(!result) {
Print("Errore nella cancellazione dell'ordine pendente ", OrderTicket(), ": ", GetLastError());
} else {
Print("Ordine pendente ", OrderTicket(), " cancellato con successo.");
}
}
}
}
}
// funzione che cancella tutti gli oridini a mercato e pendenti ad una precisa ora del giorno, se siamo entrati a mercatovoid CloseMarketOrders() {
// Ciclo attraverso tutti gli ordini apertifor(int i = OrdersTotal() - 1; i >= 0; i--) {
if(OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber() == MagicNumber) {
// Controlla se l'ordine appartiene al nostro EA tramite il Magic Numberif(OrderType() <= OP_SELL) { // Se l'ordine è a mercato (BUY o SELL)bool closeResult = false; // Variabile per controllare il risultato dell'azione di chiusura// Prova a chiudere l'ordine a mercatoif(OrderType() == OP_BUY) {
closeResult = OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrRed);
} elseif(OrderType() == OP_SELL) {
closeResult = OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrRed);
}
// Controlla il risultato della chiusura e agisci di conseguenzaif(!closeResult) {
Print("Errore nella chiusura dell'ordine ", OrderTicket(), ": ", GetLastError());
}
} else { // Se l'ordine è pendente (BUY LIMIT, SELL LIMIT, BUY STOP, SELL STOP)// Cancella l'ordine pendente e controlla il risultatobool deleteResult = OrderDelete(OrderTicket());
if(!deleteResult) {
Print("Errore nella cancellazione dell'ordine pendente ", OrderTicket(), ": ", GetLastError());
}
}
}
}
}
// Verifica se ci sono ordini aperti per la direzione specificatabool ExistOpenOrders(string symbol, bool isLong) {
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == symbol && OrderMagicNumber() == MagicNumber) {
if((isLong && OrderType() == OP_BUY) || (!isLong && OrderType() == OP_SELL)) {
returntrue; // Trovato un ordine aperto che corrisponde ai criteri
}
}
}
returnfalse; // Nessun ordine aperto che corrisponde ai criteri trovato
}
bool ExistPendingOrders(string symbol, bool isLong) {
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == symbol && OrderMagicNumber() == MagicNumber) {
if(isLong && (OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP)) returntrue;
if(!isLong && (OrderType() == OP_SELLLIMIT || OrderType() == OP_SELLSTOP)) returntrue;
}
}
returnfalse; // Nessun ordine pendente che corrisponde ai criteri trovato
}
Allow the use of cookies to log in to the MQL5.com website.
Please enable the necessary setting in your browser, otherwise you will not be able to log in.
You are signed in. Two-factor authentication has been disabled. Set it up again and scan a new QR code, or continue with two-factor authentication disabled.
I have been working on this simple expert for days, but it does not open any pending orders when you reach the preset levels BestLongPrice or BestShortPrice. Yet the logic is very simple. these values are set, you set whether the direction is long or short and set the entry and exit levels. the end. Is anyone kind enough to help me?