//+------------------------------------------------------------------+
//| Советник выводит окно MessageBox с запросом о дальнейшей работе |
//| при достижении указанного количества серии убыточных сделок |
//| Ожидает заданное количество баров и выводит окно MessageBox |
//| с запросом о продолжении работы. |
//| Для проверки достаточно вручную открыть и закрыть с убытком |
//| несколько позиций, так как для упрощения советник не контролирует|
//| "свои" позиции по магику. |
//+------------------------------------------------------------------+
//--- input parameters
input uint InpMaxLossDeals = 3; // Max Loss deals
input uint InpInactivityNumBars = 5; // Number of bars of advisor inactivity
//--- global variables
bool ExtFirstStart=true; // Флаг первого запуска
bool ExtFlag=true; // Флаг разрешения работы советника
uint ExtNumLoss; // Количество убыточных сделок подряд
datetime ExtTimeLastLoss; // Время последней сделки закрытия убыточной позиции
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- получаем количество убыточных сделок подряд и время последней сделки закрытия позиции
ExtNumLoss=GetNumLosingTradesInRow(ExtTimeLastLoss);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- определяем, сколько прошло баров после последней закрытой убыточной позиции в серии
int bars_remaining=iBarShift(Symbol(),PERIOD_CURRENT,ExtTimeLastLoss);
//--- если это первый запуск
if(ExtFirstStart)
{
//--- Если уже прошло заданное количество баров после серии убыточных позиций - устанавливаем флаг работы советника
if(bars_remaining>(int)InpInactivityNumBars)
ExtFlag=true;
ExtFirstStart=false;
}
//--- если флаг работы советника снят
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)));
//--- если прошло заданное количество баров после серии убыточных позиций
if(bars_remaining>(int)InpInactivityNumBars)
{
//--- выводим окно MessageBox с заданным текстом и заголовком окна
//--- окно запроса имеет две кнопки Yes/No и иконку со знаком вопроса.
//--- кнопка Yes выбрана по умолчанию.
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);
//--- если код возврата от MessageBox - нажатая кнопка Yes - устанавливаем флаг работы советника
if(mb_id==IDYES)
{
ExtFlag=true;
return;
}
}
//--- флаг работы советника снят - выходим из OnTick()
return;
}
//--- флаг работы советника установлен - работает советник, как предусмотрено кодом, следующим ниже
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)
{
//--- если тип транзакции - добавление сделки в историю
if(trans.type==TRADE_TRANSACTION_DEAL_ADD)
{
//--- Получаем тикет сделки и выбираем сделку из списка по тикету
ulong deal_ticket=trans.deal;
if(HistoryDealSelect(deal_ticket))
{
//--- если это сделка на выход из рынка - получаем количество убыточных сделок подряд и время последней сделки
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);
}
}
//--- если количество убыточных сделок, идущих подряд, больше заданного значения и установлен флаг работы советника
if(ExtNumLoss>=InpMaxLossDeals && ExtFlag)
{
//--- выводим окно MessageBox с заданным текстом и заголовком окна
//--- окно запроса имеет две кнопки Yes/No и иконку с восклицательным знаком.
//--- кнопка No выбрана по умолчанию.
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);
//--- если код возврата от MessageBox - нажатая кнопка No - снимаем флаг работы советника
if(mb_id==IDNO)
ExtFlag=false;
}
}
//+------------------------------------------------------------------+
//| Возвращает количество убыточных сделок подряд |
//| и время последней сделки закрытия убыточной позиции |
//+------------------------------------------------------------------+
uint GetNumLosingTradesInRow(datetime &time_last_deal)
{
//--- Выбираем всю историю
if(!HistorySelect(0,TimeCurrent()))
return(0);
//--- в цикле по списку исторических сделок получаем тикет очередной сделки
uint res=0;
uint total=HistoryDealsTotal();
for(int i=(int)total-1; i>=0; i--)
{
ulong deal_ticket=HistoryDealGetTicket(i);
if(deal_ticket>0)
{
//--- если сделка не на выход из позиции - идём к следующей
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;
//--- если результат закрытия позиции имеет положительный профит - прерываем цикл
if(!IsClosePositionWithLoss(deal_ticket))
break;
//--- увеличиваем счётчик идущих подряд сделок с отрицательной прибылью
res++;
//--- записываем в переменную максимальное время сделки (ищем последнюю)
datetime deal_time=(datetime)HistoryDealGetInteger(deal_ticket,DEAL_TIME);
if(deal_time>time_last_deal)
time_last_deal=deal_time;
}
}
//--- Возвращаем количество идущих подряд убытков
return(res);
}
//+------------------------------------------------------------------+
//| Возвращает флаг закрытия позиции с убытком |
//+------------------------------------------------------------------+
bool IsClosePositionWithLoss(const ulong deal_ticket)
{
//--- получаем из сделки значения свойств, влияющих на прибыль
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);
//--- возвращаем флаг того, что суммарное значение полученных свойств отрицательно
return(profit+comission+swap+fee<0);
}
|