etl.t:
Привет. Вот что произошло. Робот Ilan_mql5.mq5 нормально до 13 мая 2016. Потом начал совершать сделки без учета выставленных колен, одну за другой. Хорошо, что комп был перед глазами был и я вовремя все остановил. Проверил робота на дэмо- все работает, в реале - глючит. Помогите. Вот он
Нет там явно проверки на такую дату.
Код оформите, а то модератор заругает - в редакторе есть кнопка SRC.
Copyright © 2011, Tarakan Software Corp.
Проблема скорее всего была при позиции селл. Да. При работе с историей, при поиске цены последнего входа не выполняется проверка на успешность выполнения функций.
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Привет. Вот что произошло. Робот Ilan_mql5.mq5 нормально до 13 мая 2016. Потом начал совершать сделки без учета выставленных колен, одну за другой. Хорошо, что комп был перед глазами был и я вовремя все остановил. Проверил робота на дэмо- все работает, в реале - глючит. Помогите. Вот он
//+------------------------------------------------------------------+
//| Ilan_mql5.mq5 |
//| Copyright © 2011, Tarakan Software Corp. |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, Tarakan Software Corp."
#property version "1.00"
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
//---
input double TakeProfit = 10; // TakeProfit в пунктах
input double PipStep = 30; // Размер шага открытия колен
input double Lots = 0.10; // Начальный объем лота
input int LotDecimal = 2; // Количество знаков после запятой в объеме лота
input double LotExponent = 1.40; // Экспонента увеличения объема лота
input int MagicNumber = 70707; // Магический номер советника
input int MaxTrades = 8; // Максимальное количество открытых колен
input int Slip = 3; // Проскальзывание
/*input*/ bool UseTrailingStop = false; // Использовать TrailingStop
/*input*/ int TrailStart = 10; // Прибыль в пунктах, необходимая для старта трала
/*input*/ int TrailStop = 10; // StopLoss в пунктах, выставляемый при трале
/*input*/ bool UseEquityStop = false; // Использовать ограничение на убыток
/*input*/ double TotalEquityRisk = 50.0; // Максимальный убыток в процентах от депозита
/*input*/ bool UseTimeOut = false; // Использовать ограничение на время жизни позиции
/*input*/ double MaxTradeOpenHours = 48; // Максимальное время жизни позиции в часах
//+------------------------------------------------------------------+
//double Spread;
datetime Expiration;
double LotSize;
int TotalOrders;
bool TradeNow = false, LongTrade = false, ShortTrade = false;
bool NewOrdersPlaced = false;
double LastBuyPrice, LastSellPrice;
double iTakeProfit, iPipStep;
int iTrailStart, iTrailStop;
bool Position = false; // true - есть открытая позиция, false - нет
long PositionID = 0; // идентификатор открытой позиции
ulong LastDealTicket = 0; // тикет сделки, который мы будем ловить в OnTrade()
bool CanTrade = true; // запрет торговли до полного исполнения ордера
CTrade Trade; // класс для совершения торговых операций
CSymbolInfo SymbolInfo;
CPositionInfo PositionInfo;
//+------------------------------------------------------------------+
int OnInit()
{
Trade.SetExpertMagicNumber(MagicNumber);
Trade.SetDeviationInPoints(Slip);
SymbolInfo.Name(_Symbol);
iTakeProfit = TakeProfit;
iPipStep = PipStep;
iTrailStart = TrailStart;
iTrailStop = TrailStop;
// если после запятой пять знаков - коррекция уровней
if (_Digits == 5 || _Digits == 3)
{
iTakeProfit = TakeProfit * 10;
iPipStep = PipStep * 10;
iTrailStart = TrailStart * 10;
iTrailStop = TrailStop * 10;
}
return(0);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
return;
}
//+------------------------------------------------------------------+
void OnTick()
{
if (!CanTrade) return;
//---------------------------------
// Spread = NormalizeDouble(SymbolInfo.Ask() - SymbolInfo.Bid(), _Digits);
//---------------------------------
// если включен TrailingStop
if (UseTrailingStop)
TrailPosition(iTrailStart, iTrailStop);
//---------------------------------
// если стоит ограничение на время жизни позиции
if (UseTimeOut && TimeCurrent() >= Expiration)
{
Print("Время жизни позиции истекло, принудительное закрытие");
ClosePosition(); // закрываем позицию
}
//---------------------------------
// советник работает только по открытиям новых баров
// если это первый тик на текущем баре значит бар только что открылся
long TickVolume[1]; // массив для тикового объема последнего бара
// получим количество тиков на последнем баре
if (CopyTickVolume(_Symbol, _Period, 0, 1, TickVolume) != 1)
{
Print("Не удалось получить количество тиков на текущем баре");
return;
}
// если на текущем баре больше одного тика - выход
if (TickVolume[0] > 1) return;
//---------------------------------
// если включено ограничение на убыток
if (UseEquityStop)
{
// если потеряно TotalEquityRisk (или больше) процентов депозита - закрываем позицию
double AccountEquity = AccountInfoDouble(ACCOUNT_EQUITY);
double AccountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
if (AccountEquity <= AccountBalance * (1 - TotalEquityRisk / 100))
{
Print("Потеряно ", TotalEquityRisk, "% депозита, принудительное закрытие позиции");
ClosePosition();
}
}
//---------------------------------
// найдем открытую позицию по текущему финансовому инструменту
if (PositionInfo.Select(_Symbol))
{
Position = true;
PositionID = PositionInfo.Identifier();
}
else
{
Position = false;
PositionID = 0;
}
//---------------------------------
// узнаем направление открытой позиции
if (Position) // если есть открытая позиция
{
if (PositionInfo.PositionType() == POSITION_TYPE_BUY)
{
LongTrade = true;
ShortTrade = false;
}
if (PositionInfo.PositionType() == POSITION_TYPE_SELL)
{
LongTrade = false;
ShortTrade = true;
}
}
//---------------------------------------
// узнаем количество ордеров в нашей позиции
if (Position) TotalOrders = CountTrades(PositionID);
else TotalOrders = 0;
//---------------------------------------
// если цена прошла PipStep пунктов против нас - открываем новый ордер
SymbolInfo.RefreshRates();
if (Position && (TotalOrders > 0 && TotalOrders <= MaxTrades))
{
// найдем цены открытия последнего ордера Buy и последнего ордера Sell
LastBuyPrice = FindLastBuyPrice(PositionID);
LastSellPrice = FindLastSellPrice(PositionID);
if (LongTrade && LastBuyPrice - SymbolInfo.Ask() >= iPipStep * _Point) // цена ушла вниз
TradeNow = true;
if (ShortTrade && SymbolInfo.Bid() - LastSellPrice >= iPipStep * _Point) // цена ушла вверх
TradeNow = true;
} // if (Total > 0 && Total <= MaxTrades)
//---------------------------------------
// если нет открытой позиции - начинаем новую серию
if (!Position)
{
ShortTrade = false;
LongTrade = false;
TradeNow = true;
}
//-----------------------------------
// если продолжаем торговую серию
if (Position && TradeNow)
{
// размер лота очередного ордера
LotSize = NormalizeDouble(Lots * MathPow(LotExponent, TotalOrders), LotDecimal);
if (ShortTrade) // Sell - серия
{
if (!Sell(LotSize, SymbolInfo.Bid())) return; // продаем
TradeNow = false;
NewOrdersPlaced = true; // новый ордер открыт
}
else if (LongTrade) // Buy - серия
{
if (!Buy(LotSize, SymbolInfo.Ask())) return; // покупаем
TradeNow = false;
NewOrdersPlaced = true; // новый ордер открыт
}
} // if (Position && TradeNow)
//-------------------------------
// если начинаем новую торговую серию
if (!Position && TradeNow) // если нет открытой позиции
{
// массив структур для получения информации о ценах последней свечи
// цвет последней свечи нужен для определения направления открытия первого ордера серии
MqlRates Rates[1];
// получим цены последней свечи (свечи с индексом 1)
if (CopyRates(_Symbol, _Period, 1, 1, Rates) != 1)
{
Print("Не удалось получить ценовые данные для предпоследней свечи");
return;
}
if (!ShortTrade && !LongTrade)
{
// размер лота очередного ордера
LotSize = NormalizeDouble(Lots * MathPow(LotExponent, TotalOrders), LotDecimal);
if (Rates[0].open > Rates[0].close) // если последняя свеча черная - продаем
{
if (!Sell(LotSize, SymbolInfo.Bid())) return;
NewOrdersPlaced = true; // новый ордер открыт
}
else // последняя свеча белая - покупаем
{
if (!Buy(LotSize, SymbolInfo.Ask())) return;
NewOrdersPlaced = true; // новый ордер открыт
}
} // if (!ShortTrade && !LongTrade)
if (NewOrdersPlaced)
Expiration = (datetime)(TimeCurrent() + PeriodSeconds(PERIOD_H1) * MaxTradeOpenHours);
TradeNow = false;
} // if (!Position && TradeNow)
//----------------------------
// установим TakeProfit для нашей позиции
if (NewOrdersPlaced)
{
// найдем нашу позицию
if (!PositionInfo.Select(_Symbol)) return;
double NewTakeProfit = 0;
if (PositionInfo.PositionType() == POSITION_TYPE_BUY)
{
if (iTakeProfit > SymbolInfo.StopsLevel())
NewTakeProfit = PositionInfo.PriceOpen() + iTakeProfit * _Point;
else
NewTakeProfit = PositionInfo.PriceOpen() + SymbolInfo.StopsLevel() * _Point;
}
else
{
if (iTakeProfit > SymbolInfo.StopsLevel())
NewTakeProfit = PositionInfo.PriceOpen() - iTakeProfit * _Point;
else
NewTakeProfit = PositionInfo.PriceOpen() - SymbolInfo.StopsLevel() * _Point;
}
if (!CompareDouble(PositionInfo.TakeProfit(), NewTakeProfit))
if (!Modify(0, NewTakeProfit)) return;
NewOrdersPlaced = false;
} // if (NewOrdersPlaced)
return;
} // --- Exit OnTick() function ---
//+------------------------------------------------------------------+
// с момента отправки приказа на открытие и до полного совершения сделки торговля запрещена
// здесь мы ловим момент когда сделка состоялась после чего вновь разрешаем советнику торговать
void OnTrade()
{
if (LastDealTicket == 0) return; // небыло приказа на совершение сделки
// получим историю ордеров и сделок за последний час
datetime EndDate = TimeCurrent();
datetime StartDate = EndDate - PeriodSeconds(PERIOD_H1);
HistorySelect(StartDate, EndDate);
int Total = HistoryDealsTotal();
ulong Ticket = HistoryDealGetTicket(Total - 1); // тикет последней сделки
if (Ticket == LastDealTicket) // если это наш ордер, значит сделка состоялась
{
LastDealTicket = 0;
CanTrade = true; // разрешаем торговлю
}
}
//+------------------------------------------------------------------+
// возвращает количество сделок позиции, заданной идентификатором id
int CountTrades(long id)
{
int Total; // количество сделок текущей позиции
ulong Ticket; // тикет выбранной сделки из истории
int Count = 0; // количество найденных ордеров
// создадим список ордеров и сделок текущей позиции
HistorySelectByPosition(id);
// переберем все сделки открытой позиции
Total = HistoryDealsTotal(); // количество сделок в истории
for (int i = 0; i < Total; i++)
{
Ticket = HistoryDealGetTicket(i); // получим тикет очередной сделки
if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_IN) // считаем только вход в рынок
{
if (HistoryDealGetInteger(Ticket, DEAL_MAGIC) == MagicNumber) Count++;
}
}
return(Count);
}
//+------------------------------------------------------------------+
// возвращает суммарный объем ордеров, открытых советником
double CalculateVolume(long id)
{
int Total; // количество сделок текущей позиции
ulong Ticket; // тикет выбранной сделки из истории
double Volume = 0; // суммарный объем ордеров советника
// создадим список ордеров и сделок текущей позиции
HistorySelectByPosition(id);
// переберем все сделки открытой позиции
Total = HistoryDealsTotal(); // количество сделок в истории
for (int i = 0; i < Total; i++)
{
Ticket = HistoryDealGetTicket(i); // получим тикет очередной сделки
if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_IN) // считаем только вход в рынок
{
if (HistoryDealGetInteger(Ticket, DEAL_MAGIC) == MagicNumber)
Volume = Volume + HistoryDealGetDouble(Ticket, DEAL_VOLUME);
}
}
return(Volume);
}
//+------------------------------------------------------------------+
// закрывает все ордеры, открытые советником
bool ClosePosition()
{
if (!PositionInfo.Select(_Symbol)) return(false); // нет открытой позиции
SymbolInfo.RefreshRates();
double Volume = NormalizeDouble(CalculateVolume(PositionInfo.Identifier()), LotDecimal);
ENUM_POSITION_TYPE Type = PositionInfo.PositionType();
if (Type == POSITION_TYPE_BUY)
{
if (Trade.Sell(Volume, _Symbol, SymbolInfo.Bid()))
{
if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
{
CanTrade = false; // запрещаем торговлю (разрешаем вновь в OnTrade)
LastDealTicket = Trade.ResultDeal();
return(true);
}
}
Print("Позиция не закрыта, ошибка ", Trade.ResultRetcodeDescription());
return(false);
}
else if (Type == POSITION_TYPE_SELL)
{
if (Trade.Buy(Volume, _Symbol, SymbolInfo.Ask()))
{
if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
{
CanTrade = false; // запрещаем торговлю (разрешаем вновь в OnTrade)
LastDealTicket = Trade.ResultDeal();
return(true);
}
}
Print("Позиция не закрыта, ошибка ", Trade.ResultRetcodeDescription());
return(false);
}
return(false);
}
//+------------------------------------------------------------------+
// возвращает цену открытия последнего ордера Buy
// для позиции с идентификатором id
double FindLastBuyPrice(long id)
{
int Total; // количество сделок в истории
ulong Ticket; // тикет выбранной сделки из истории
long Entry; // направление сделки (IN или OUT)
long Magic; // магический номер сделки
long Type; // тип сделки (BUY или SELL)
double Price = 0; // цена сделки
double LastPrice = 1000000; // цена сделки, найденн на предыдущей итерации цикла
// создадим список ордеров и сделок текущей позиции
HistorySelectByPosition(id);
Total = HistoryDealsTotal(); // количество сделок в истории
for (int i = 0; i < Total; i++)
{
Ticket = HistoryDealGetTicket(i); // получим тикет очередной сделки
Entry = HistoryDealGetInteger(Ticket, DEAL_ENTRY);
Magic = HistoryDealGetInteger(Ticket, DEAL_MAGIC);
Type = HistoryDealGetInteger(Ticket, DEAL_TYPE);
Price = HistoryDealGetDouble(Ticket, DEAL_PRICE);
if (Entry == DEAL_ENTRY_IN && Magic == MagicNumber && Type == DEAL_TYPE_BUY)
{
if (Price < LastPrice) LastPrice = Price;
}
}
return(LastPrice);
}
//+------------------------------------------------------------------+
// возвращает цену открытия последнего ордера Sell
// для позиции с идентификатором id
double FindLastSellPrice(long id)
{
int Total; // количество сделок в истории
ulong Ticket; // тикет выбранной сделки из истории
long Entry; // направление сделки (IN или OUT)
long Magic; // магический номер сделки
long Type; // тип сделки (BUY или SELL)
double Price = 0; // цена сделки
double LastPrice = 0; // цена сделки, найденн на предыдущей итерации цикла
// создадим список ордеров и сделок текущей позиции
HistorySelectByPosition(id);
Total = HistoryDealsTotal(); // количество сделок в истории
for (int i = 0; i < Total; i++)
{
Ticket = HistoryDealGetTicket(i); // получим тикет очередной сделки
Entry = HistoryDealGetInteger(Ticket, DEAL_ENTRY);
Magic = HistoryDealGetInteger(Ticket, DEAL_MAGIC);
Type = HistoryDealGetInteger(Ticket, DEAL_TYPE);
Price = HistoryDealGetDouble(Ticket, DEAL_PRICE);
if (Entry == DEAL_ENTRY_IN && Magic == MagicNumber && Type == DEAL_TYPE_SELL)
{
if (Price > LastPrice) LastPrice = Price;
}
}
return(LastPrice);
}
//+------------------------------------------------------------------+
// тралит открытую позицию
// трал включается если прибыль по позиции составляет не меньше trStart пунктов
// StopLoss выставляется на trStop пунктов от текущей цены
void TrailPosition(int trStart, int trStop)
{
int CurrentPipsProfit; // текущая прибыль позиции в пунктах
double OldStopLoss; // старый уровень StopLoss
double NewStopLoss; // новый уровень StopLoss
if (!PositionInfo.Select(_Symbol)) return; // нет открытой позиции
double PositionOpenPrice = PositionInfo.PriceOpen(); // цена открытия позиции
double PositionTakeProfit = PositionInfo.TakeProfit(); // уровень TakeProfit позиции
SymbolInfo.RefreshRates();
if (PositionInfo.PositionType() == POSITION_TYPE_BUY) // позиция Buy
{
// вычислим прибыль позиции в пунктах
CurrentPipsProfit = (int)((SymbolInfo.Bid() - PositionOpenPrice) / _Point);
if (CurrentPipsProfit < trStart) return;
OldStopLoss = PositionInfo.StopLoss(); // текущий StopLoss позиции
NewStopLoss = SymbolInfo.Bid() - trStop * _Point; // новый StopLoss позиции
// установим новый уровень StopLoss
if (OldStopLoss == 0 || (OldStopLoss != 0 && NewStopLoss > OldStopLoss))
{
if (!Modify(NewStopLoss, 0)) return;
}
}
if (PositionInfo.PositionType() == POSITION_TYPE_SELL) // позиция Sell
{
// прибыль позиции в пунктах
CurrentPipsProfit = (int)((PositionOpenPrice - SymbolInfo.Ask()) / _Point);
if (CurrentPipsProfit < trStart) return;
OldStopLoss = PositionInfo.StopLoss(); // текущий StopLoss позиции
NewStopLoss = SymbolInfo.Ask() + trStop * _Point; // новый StopLoss позиции
// установим новый уровень StopLoss
if (OldStopLoss == 0 || (OldStopLoss != 0 && NewStopLoss < OldStopLoss))
{
if (!Modify(NewStopLoss, 0)) return;
}
}
}
//+------------------------------------------------------------------+
// возвращает нормализованное значение цены
double ND(double price)
{
return(NormalizeDouble(price, _Digits));
}
//-------------------------------------------------------------------+
// открывает ордер Buy
bool Buy(double OrderLotSize, double OrderPrice)
{
if (Trade.Buy(OrderLotSize, _Symbol, OrderPrice))
{
if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
{
CanTrade = false; // запрещаем торговлю (разрешаем вновь в OnTrade)
LastDealTicket = Trade.ResultDeal();
return(true);
}
}
Print("Ордер Buy не открыт, ошибка ", Trade.ResultRetcodeDescription());
return(false);
}
//+------------------------------------------------------------------+
// открывает ордер Sell
bool Sell(double OrderLotSize, double OrderPrice)
{
if (Trade.Sell(OrderLotSize, _Symbol, OrderPrice))
{
if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
{
CanTrade = false; // запрещаем торговлю (разрешаем вновь в OnTrade)
LastDealTicket = Trade.ResultDeal();
return(true);
}
}
Print("Ордер Sell не открыт, ошибка ", Trade.ResultRetcodeDescription());
return(false);
}
//+------------------------------------------------------------------+
// устанавливает уровень TakeProfit
bool Modify(double NewStopLoss, double NewTakeProfit)
{
if (CompareDouble(NewStopLoss, 0.0)) NewStopLoss = PositionInfo.StopLoss();
if (CompareDouble(NewTakeProfit, 0.0)) NewTakeProfit = PositionInfo.TakeProfit();
if (Trade.PositionModify(_Symbol, NewStopLoss, NewTakeProfit))
{
if (Trade.ResultRetcode() == TRADE_RETCODE_DONE)
{
// CanTrade = false;
return(true);
}
}
Print("TakeProfit не установлен, ошибка ", Trade.ResultRetcodeDescription());
return(false);
}
//+------------------------------------------------------------------+
// сравнивает два вещественных числа
// возвращает true если числа равны, false если числа не равны
bool CompareDouble(double a, double b)
{
if (NormalizeDouble(a - b, 8) == 0) return(true);
else return(false);
}
//+------------------------------------------------------------------+