//+--------------------------------------------------------------------------------------------------------------+
//| L'EA visualizza la finestra MessageBox con una richiesta di ulteriori lavori |
//| al raggiungimento di un determinato numero di serie di operazioni non redditizie |
//| Attende per il numero specificato di barre e visualizza MessageBox |
//| con la richiesta di proseguire il lavoro. |
//| Per controllare, dobbiamo aprire e chiudere manualmente diverse posizioni |
//| con una perdita, poiché l'EA non controlla |
//| le proprie "posizioni" per numero magico per semplicità. |
//+--------------------------------------------------------------------------------------------------------------+
//-- parametri di input
input uint InpMaxLossDeals = 3; // Numero massimo di operazioni in perdita
input uint InpInactivityNumBars = 5; // Numero di barre di inattività dell'advisor
//---variabili globali
bool ExtFirstStart=true; // Flag del primo avvio
bool ExtFlag=true; // Flag per consentire all'EA di funzionare
uint ExtNumLoss; // Numero di trade non profittevoli consecutivi
datetime ExtTimeLastLoss; // Ora dell'ultimo trade per la chiusura di una posizione perdente
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//-- ottenere il numero di trade perdenti consecutivi e il tempo dell'ultimo trade per chiudere la posizione
ExtNumLoss=GetNumLosingTradesInRow(ExtTimeLastLoss);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//-- determinare quante barre sono passate dall'ultima posizione in perdita chiusa della serie
int bars_remaining=iBarShift(Symbol(),PERIOD_CURRENT,ExtTimeLastLoss);
//-- se questo è il primo avvio
if(ExtFirstStart)
{
//--- Se un numero specificato di barre sono già passate dopo una serie di posizioni non profittevoli, impostare il flag di funzionamento dell' EA
if(bars_remaining>(int)InpInactivityNumBars)
ExtFlag=true;
ExtFirstStart=false;
}
//-- se il flag del funzionamento dell' EA è disattivato
if(!ExtFlag)
{
Comment(StringFormat("The advisor is stopped for %d bars. Num Loss positions: %u, Time last loss: %s",
(InpInactivityNumBars-bars_remaining),ExtNumLoss,TimeToString(ExtTimeLastLoss,TIME_DATE|TIME_MINUTES|TIME_SECONDS)));
//-- se un numero specificato di barre è passato dopo una serie di posizioni non profittevoli
if(bars_remaining>(int)InpInactivityNumBars)
{
//-- mostra la finestra MessageBox con il testo specificato e il titolo della finestra
//-- la finestra di richiesta ha due pulsanti Sì/No e un'icona con un punto interrogativo.
//-- il pulsante Sì è selezionato per impostazione predefinita.
string mb_text="The specified number of bars of EA inactivity have passed.\n Continue its work?";
string mb_caption="Please note";
int mb_id=MessageBox(mb_text,mb_caption,MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1);
//-- se il codice restituito da MessageBox è la pressione del pulsante Sì, impostare il flag di funzionamento dell' EA
if(mb_id==IDYES)
{
ExtFlag=true;
return;
}
}
//-- il flag di funzionamento dell' EA è disabilitato, uscire da OnTick()
return;
}
//--- viene impostato il flag di funzionamento dell' EA - l'EA funziona come previsto dal codice seguente
Comment(StringFormat("The advisor is working. Num Loss positions: %u, Time last loss: %s, Elapsed Bars: %d",
ExtNumLoss,TimeToString(ExtTimeLastLoss,TIME_DATE|TIME_MINUTES|TIME_SECONDS),bars_remaining));
}
//+------------------------------------------------------------------+
//| TradeTransaction function |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
const MqlTradeRequest& request,
const MqlTradeResult& result)
{
//-- se il tipo di transazione aggiunge una transazione alla cronologia
if(trans.type==TRADE_TRANSACTION_DEAL_ADD)
{
//-- ottenere un ticket dell'operazione e selezionarla dalla lista tramite ticket
ulong deal_ticket=trans.deal;
if(HistoryDealSelect(deal_ticket))
{
//-- se si tratta di un trade di uscita dal mercato, ottenere il numero di trade perdenti consecutivi e l'ora dell'ultimo trade
ENUM_DEAL_ENTRY entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
if(entry==DEAL_ENTRY_OUT || entry==DEAL_ENTRY_INOUT || entry==DEAL_ENTRY_OUT_BY)
ExtNumLoss=GetNumLosingTradesInRow(ExtTimeLastLoss);
}
}
//-- se il numero di operazioni perse di fila è maggiore del valore specificato e il flag di funzionamento dell'EA è abilitato
if(ExtNumLoss>=InpMaxLossDeals && ExtFlag)
{
//-- mostrare la finestra MessageBox con il testo specificato e il titolo della finestra
//-- la finestra di richiesta ha due pulsanti Sì/No e un'icona con un punto esclamativo.
//-- il pulsante No è selezionato per impostazione predefinita.
string mb_text="The number of losing trades has reached the specified maximum. The advisor is stopped.\n Continue its work?";
string mb_caption="Attention!";
int mb_id=MessageBox(mb_text,mb_caption,MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2);
//-- se il codice restituito da MessageBox è la pressione del pulsante No, disabilitare il flag di funzionamento dell'EA
if(mb_id==IDNO)
ExtFlag=false;
}
}
//+-------------------------------------------------------------------------------------+
//| Restituisce il numero di operazioni consecutive non redditizie |
//| e l'ora dell'ultima operazione chiusa di una posizione perdente |
//+-------------------------------------------------------------------------------------+
uint GetNumLosingTradesInRow(datetime &time_last_deal)
{
//-- seleziona l'intera cronologia
if(!HistorySelect(0,TimeCurrent()))
return(0);
//-- ottenere il ticket del trade successivo dalla lista delle operazioni storiche in un ciclo
uint res=0;
uint total=HistoryDealsTotal();
for(int i=(int)total-1; i>=0; i--)
{
ulong deal_ticket=HistoryDealGetTicket(i);
if(deal_ticket>0)
{
//-- se l'operazione non è di uscita dalla posizione, passare a quella successiva
ENUM_DEAL_ENTRY entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
if(entry!=DEAL_ENTRY_OUT && entry!=DEAL_ENTRY_OUT_BY && entry!=DEAL_ENTRY_INOUT)
continue;
//-- se il risultato della chiusura di una posizione ha un profitto, interrompere il ciclo
if(!IsClosePositionWithLoss(deal_ticket))
break;
//-- aumentare il contatore di operazioni consecutive in perdita
res++;
//-- scrivere l'ora di trade maggiore in una variabile (cercando l'ultima)
datetime deal_time=(datetime)HistoryDealGetInteger(deal_ticket,DEAL_TIME);
if(deal_time>time_last_deal)
time_last_deal=deal_time;
}
}
//-- restituire il numero di perdite consecutive
return(res);
}
//+-------------------------------------------------------------------------------------+
//| Restituisce il flag di chiusura di una posizione con una perdita |
//+-------------------------------------------------------------------------------------+
bool IsClosePositionWithLoss(const ulong deal_ticket)
{
//-- ottenere i valori delle proprietà che sono interessate dal profitto dal trade
double profit=HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
double comission=HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);
double swap=HistoryDealGetDouble(deal_ticket,DEAL_SWAP);
double fee=HistoryDealGetDouble(deal_ticket,DEAL_FEE);
//-- restituire il flag indicando che il valore totale delle proprietà ricevute è negativo
return(profit+comission+swap+fee<0);
}
|