В предыдущем примере советника выделим функции OnCheckTradeInit, OnCheckTradeTick, OnTradeSignalBuy, OnTradeSignalBuyStop, OnTradeSignalSell, OnTradeSignalSellStop, а также код открытия и закрытия позиции в отдельные классы.
Проверочные функции OnCheckTradeInit и OnCheckTradeTick выделим в класс CheckTrade.
class CheckTrade
{
private:
public:
CheckTrade ();
~CheckTrade ();
int OnCheckTradeInit (double lot);
int OnCheckTradeTick (double lot, double spread);
};
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
CheckTrade::CheckTrade ()
{
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
CheckTrade::~CheckTrade ()
{
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
int CheckTrade::OnCheckTradeInit (double lot) {
//Проверка запуска эксперта на реальном счете
if ((ENUM_ACCOUNT_TRADE_MODE) AccountInfoInteger (ACCOUNT_TRADE_MODE) ==ACCOUNT_TRADE_MODE_REAL) {
int mb=MessageBox («Запустить советник на реальном счете?», «Message Box», MB_YESNO|MB_ICONQUESTION);
if (mb==IDNO) return (0);
}
// – — – — – — – — – — – — – — – — – — – — – — – — —
//Проверки: запрещена торговля в случае подключения к счету в режиме инвестора,
//отсутствия соединения к серверу, запрета торговли на стороне сервера, если счет отправлен в архив
//брокер запрещает автоматическую торговлю
if (!TerminalInfoInteger (TERMINAL_CONNECTED)) {
Alert («No connection to the trade server»);
return (0);
} else {
if (!AccountInfoInteger (ACCOUNT_TRADE_ALLOWED)) {
Alert («Trade for this account is prohibited»);
return (0);
}
}
if (!AccountInfoInteger (ACCOUNT_TRADE_EXPERT)) {
Alert («Trade with the help of experts for the account is prohibited»);
return (0);
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
//Проверить корректность объема, с которым мы собираемся выйти на рынок
if (lot <SymbolInfoDouble (Symbol (),SYMBOL_VOLUME_MIN) ||lot> SymbolInfoDouble (Symbol (),SYMBOL_VOLUME_MAX)) {
Alert («Lot is not correct!!!»);
return (0);
}
return (INIT_SUCCEEDED);
}
int CheckTrade::OnCheckTradeTick (double lot, double spread) {
//Проверка отсутствия соединения к серверу
if (!TerminalInfoInteger (TERMINAL_CONNECTED)) {
Alert («No connection to the trade server»);
return (0);
}
//Включена ли кнопка авто-торговли в клиентском терминале
if (!TerminalInfoInteger (TERMINAL_TRADE_ALLOWED)) {
Alert («Разрешение на автоматическую торговлю выключено!»);
return (0);
}
//Разрешение на торговлю с помощью эксперта отключено в общих свойствах самого эксперта
if (!MQLInfoInteger (MQL_TRADE_ALLOWED)) {
Alert («Автоматическая торговля запрещена в свойствах эксперта», __FILE__);
return (0);
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
//Уровень залоговых средств, при котором требуется пополнение счета
if ((ENUM_ACCOUNT_STOPOUT_MODE) AccountInfoInteger (ACCOUNT_MARGIN_SO_MODE) ==ACCOUNT_STOPOUT_MODE_PERCENT) {
if (AccountInfoDouble (ACCOUNT_MARGIN_LEVEL)!=0&&AccountInfoDouble (ACCOUNT_MARGIN_LEVEL) <=AccountInfoDouble (ACCOUNT_MARGIN_SO_CALL)) {
Alert («Margin Call!!!»);
return (0);
}}
if ((ENUM_ACCOUNT_STOPOUT_MODE) AccountInfoInteger (ACCOUNT_MARGIN_SO_MODE) ==ACCOUNT_STOPOUT_MODE_MONEY) {
if (AccountInfoDouble (ACCOUNT_EQUITY) <=AccountInfoDouble (ACCOUNT_MARGIN_SO_CALL)) {
Alert («Margin Call!!!»);
return (0);
}}
//Уровень залоговых средств, при достижении которого происходит принудительное закрытие самой убыточной позиции
if ((ENUM_ACCOUNT_STOPOUT_MODE) AccountInfoInteger (ACCOUNT_MARGIN_SO_MODE) ==ACCOUNT_STOPOUT_MODE_PERCENT) {
if (AccountInfoDouble (ACCOUNT_MARGIN_LEVEL)!=0&&AccountInfoDouble (ACCOUNT_MARGIN_LEVEL) <=AccountInfoDouble (ACCOUNT_MARGIN_SO_SO)) {
Alert («Stop Out!!!»);
return (0);
}}
if ((ENUM_ACCOUNT_STOPOUT_MODE) AccountInfoInteger (ACCOUNT_MARGIN_SO_MODE) ==ACCOUNT_STOPOUT_MODE_MONEY) {
if (AccountInfoDouble (ACCOUNT_EQUITY) <=AccountInfoDouble (ACCOUNT_MARGIN_SO_SO)) {
Alert («Stop Out!!!»);
return (0);
}}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
//Проверка размера свободных средств на счете, доступных для открытия позиции
double margin;
MqlTick last_tick;
ResetLastError ();
if (SymbolInfoTick (Symbol (),last_tick))
{
if(OrderCalcMargin(ORDER_TYPE_BUY,Symbol(),lot,last_tick.ask, margin))
{
if (margin> AccountInfoDouble (ACCOUNT_MARGIN_FREE)) {
Alert («Not enough money in the account!»);
return (0);
}
}
}
else
{
Print (GetLastError ());
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
//Контроль над спредом брокера
double _spread=SymbolInfoInteger (Symbol (),SYMBOL_SPREAD) *MathPow (10, -SymbolInfoInteger (Symbol (),SYMBOL_DIGITS)) /MathPow (10, -4);
if (_spread> spread) {
Alert («Слишком большой спред!»);
return (0);
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
//Проверка ограничений на торговые операции по символу, установленные брокером
if ((ENUM_SYMBOL_TRADE_MODE) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_MODE)!=SYMBOL_TRADE_MODE_FULL) {
Alert («Установлены ограничения на торговые операции»);
return (0);
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
//Достаточно ли баров в истории для расчета советника
if (Bars (Symbol (), 0) <100)
{
Alert («In the chart little bars, Expert will not work!!»);
return (0);
}
return (1);
}
Код открытия и закрытия позиции выделим в класс Trade.
class Trade
{
private:
double StopLoss;
double Profit;
double Lot;
public:
Trade (double stopLoss, double profit, double lot);
~Trade ();
void Order (bool Buy, bool StopBuy, bool Sell, bool StopSell);
};
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
Trade::Trade (double stopLoss, double profit, double lot)
{
StopLoss=stopLoss;
Profit=profit;
Lot=lot;
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
Trade::~Trade ()
{
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
Trade::Order (bool Buy, bool BuyStop, bool Sell, bool SellStop) {
//Проверка наличия открытой позиции, чтобы не пытаться открыть ее заново
bool BuyOpened=false;
bool SellOpened=false;
if (PositionSelect (_Symbol) ==true)
{
if (PositionGetInteger (POSITION_TYPE) ==POSITION_TYPE_BUY)
{
BuyOpened=true;
}
else if (PositionGetInteger (POSITION_TYPE) ==POSITION_TYPE_SELL)
{
SellOpened=true;
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
MqlTradeRequest mrequest;
MqlTradeCheckResult check_result;
MqlTradeResult mresult;
MqlTick latest_price;
if (!SymbolInfoTick (_Symbol, latest_price))
{
Alert («Ошибка получения последних котировок – ошибка:», GetLastError (),»!!»);
return;
}
if (Buy==true&&BuyOpened==false) {
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
if (((ENUM_SYMBOL_TRADE_EXECUTION) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_EXEMODE)) ==SYMBOL_TRADE_EXECUTION_INSTANT) {
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_DEAL;
mrequest.symbol = _Symbol;
mrequest. volume = Lot;
mrequest.price = NormalizeDouble(latest_price.ask,_Digits);
mrequest.sl = NormalizeDouble(latest_price.bid – StopLoss,_Digits);
mrequest.tp = NormalizeDouble(latest_price.ask + Profit,_Digits);
mrequest.deviation=10;
mrequest. type = ORDER_TYPE_BUY;
mrequest. type_filling = ORDER_FILLING_FOK;
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10014) Alert («Неправильный объем в запросе»);
if(check_result.retcode==10015) Alert («Неправильная цена в запросе»);
if(check_result.retcode==10016) Alert («Неправильные стопы в запросе»);
if(check_result.retcode==10019) Alert («Нет достаточных денежных средств для выполнения запроса»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
Print («Price», mresult.price);
}
else
{
if(mresult.retcode==10004) //Реквота
{
Print («Requote bid ",mresult.bid);
Print («Requote ask ",mresult.ask);
} else {
Print («Retcode ",mresult.retcode);
}
}
} else {
Print («Retcode ",mresult.retcode);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
if (((ENUM_SYMBOL_TRADE_EXECUTION) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_EXEMODE)) ==SYMBOL_TRADE_EXECUTION_EXCHANGE) {
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_DEAL;
mrequest.symbol = _Symbol;
mrequest. volume = Lot;
mrequest. type = ORDER_TYPE_BUY;
mrequest. type_filling = ORDER_FILLING_FOK;
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10014) Alert («Неправильный объем в запросе»);
if(check_result.retcode==10019) Alert («Нет достаточных денежных средств для выполнения запроса»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
// – — – — – — – — – — – —
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_SLTP;
mrequest.symbol = _Symbol;
mrequest.sl = NormalizeDouble(mresult.price – StopLoss,_Digits);
mrequest.tp = NormalizeDouble(mresult.price + Profit,_Digits);
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10015) Alert («Неправильная цена в запросе»);
if(check_result.retcode==10016) Alert («Неправильные стопы в запросе»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
Print («SL», mrequest.sl, «TP ",mrequest.tp);
}
else
{
Print («Retcode ",mresult.retcode);
}
} else {
Print («Retcode ",mresult.retcode);
}
}
// – — – — – — – — – — – — – — – — – — – — —
}
else
{
Print («Retcode ",mresult.retcode);
}
} else {
Print («Retcode ",mresult.retcode);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
if (SellStop==true&&SellOpened==true) {
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
if (((ENUM_SYMBOL_TRADE_EXECUTION) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_EXEMODE)) ==SYMBOL_TRADE_EXECUTION_INSTANT) {
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_DEAL;
mrequest.symbol = _Symbol;
mrequest. volume = Lot;
mrequest.price = NormalizeDouble(latest_price.ask,_Digits);
mrequest.sl = NormalizeDouble (0.0,_Digits);
mrequest.tp = NormalizeDouble (0.0,_Digits);
mrequest.deviation=10;
mrequest. type = ORDER_TYPE_BUY;
mrequest. type_filling = ORDER_FILLING_FOK;
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10014) Alert («Неправильный объем в запросе»);
if(check_result.retcode==10015) Alert («Неправильная цена в запросе»);
if(check_result.retcode==10016) Alert («Неправильные стопы в запросе»);
if(check_result.retcode==10019) Alert («Нет достаточных денежных средств для выполнения запроса»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
Print («Price», mresult.price);
}
else
{
if(mresult.retcode==10004) //Реквота
{
Print («Requote bid ",mresult.bid);
Print («Requote ask ",mresult.ask);
} else {
Print («Retcode ",mresult.retcode);
}
}
} else {
Print («Retcode ",mresult.retcode);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
if (((ENUM_SYMBOL_TRADE_EXECUTION) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_EXEMODE)) ==SYMBOL_TRADE_EXECUTION_EXCHANGE) {
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_DEAL;
mrequest.symbol = _Symbol;
mrequest. volume = Lot;
mrequest. type = ORDER_TYPE_BUY;
mrequest. type_filling = ORDER_FILLING_FOK;
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10014) Alert («Неправильный объем в запросе»);
if(check_result.retcode==10019) Alert («Нет достаточных денежных средств для выполнения запроса»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
Print («Price», mresult.price);
}
else
{
Print («Retcode ",mresult.retcode);
}
} else {
Print («Retcode ",mresult.retcode);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
if (Sell==true&&SellOpened==false) {
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
if (((ENUM_SYMBOL_TRADE_EXECUTION) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_EXEMODE)) ==SYMBOL_TRADE_EXECUTION_INSTANT) {
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_DEAL;
mrequest.symbol = _Symbol;
mrequest. volume = Lot;
mrequest.price = NormalizeDouble(latest_price.bid,_Digits);
mrequest.sl = NormalizeDouble(latest_price.ask + StopLoss,_Digits);
mrequest.tp = NormalizeDouble(latest_price.bid – Profit,_Digits);
mrequest.deviation=10;
mrequest. type = ORDER_TYPE_SELL;
mrequest. type_filling = ORDER_FILLING_FOK;
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10014) Alert («Неправильный объем в запросе»);
if(check_result.retcode==10015) Alert («Неправильная цена в запросе»);
if(check_result.retcode==10016) Alert («Неправильные стопы в запросе»);
if(check_result.retcode==10019) Alert («Нет достаточных денежных средств для выполнения запроса»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
Print («Price», mresult.price);
}
else
{
if(mresult.retcode==10004) //Реквота
{
Print («Requote bid ",mresult.bid);
Print («Requote ask ",mresult.ask);
} else {
Print («Retcode ",mresult.retcode);
}
}
} else {
Print («Retcode ",mresult.retcode);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
if (((ENUM_SYMBOL_TRADE_EXECUTION) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_EXEMODE)) ==SYMBOL_TRADE_EXECUTION_EXCHANGE) {
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_DEAL;
mrequest.symbol = _Symbol;
mrequest. volume = Lot;
mrequest. type = ORDER_TYPE_SELL;
mrequest. type_filling = ORDER_FILLING_FOK;
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10014) Alert («Неправильный объем в запросе»);
if(check_result.retcode==10019) Alert («Нет достаточных денежных средств для выполнения запроса»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
// – — – — – — – — – — – —
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_SLTP;
mrequest.symbol = _Symbol;
mrequest.tp = NormalizeDouble(mresult.price – Profit,_Digits);
mrequest.sl = NormalizeDouble(mresult.price + StopLoss,_Digits);
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10015) Alert («Неправильная цена в запросе»);
if(check_result.retcode==10016) Alert («Неправильные стопы в запросе»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
Print («SL», mrequest.sl, «TP ",mrequest.tp);
}
else
{
Print («Retcode ",mresult.retcode);
}
} else {
Print («Retcode ",mresult.retcode);
}
}
// – — – — – — – — – — – — – — – — – — – — —
}
else
{
Print («Retcode ",mresult.retcode);
}
} else {
Print («Retcode ",mresult.retcode);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
if (BuyStop==true&&BuyOpened==true) {
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
if (((ENUM_SYMBOL_TRADE_EXECUTION) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_EXEMODE)) ==SYMBOL_TRADE_EXECUTION_INSTANT) {
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_DEAL;
mrequest.symbol = _Symbol;
mrequest. volume = Lot;
mrequest.price = NormalizeDouble(latest_price.bid,_Digits);
mrequest.sl = NormalizeDouble (0.0,_Digits);
mrequest.tp = NormalizeDouble (0.0,_Digits);
mrequest.deviation=10;
mrequest. type = ORDER_TYPE_SELL;
mrequest. type_filling = ORDER_FILLING_FOK;
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10014) Alert («Неправильный объем в запросе»);
if(check_result.retcode==10015) Alert («Неправильная цена в запросе»);
if(check_result.retcode==10016) Alert («Неправильные стопы в запросе»);
if(check_result.retcode==10019) Alert («Нет достаточных денежных средств для выполнения запроса»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
Print («Price», mresult.price);
}
else
{
if(mresult.retcode==10004) //Реквота
{
Print («Requote bid ",mresult.bid);
Print («Requote ask ",mresult.ask);
} else {
Print («Retcode ",mresult.retcode);
}
}
} else {
Print («Retcode ",mresult.retcode);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
if (((ENUM_SYMBOL_TRADE_EXECUTION) SymbolInfoInteger (Symbol (),SYMBOL_TRADE_EXEMODE)) ==SYMBOL_TRADE_EXECUTION_EXCHANGE) {
ZeroMemory (mrequest);
mrequest.action = TRADE_ACTION_DEAL;
mrequest.symbol = _Symbol;
mrequest. volume = Lot;
mrequest. type = ORDER_TYPE_SELL;
mrequest. type_filling = ORDER_FILLING_FOK;
ZeroMemory (check_result);
ZeroMemory (mresult);
if (!OrderCheck (mrequest, check_result))
{
if(check_result.retcode==10014) Alert («Неправильный объем в запросе»);
if(check_result.retcode==10019) Alert («Нет достаточных денежных средств для выполнения запроса»);
return;
} else {
if (OrderSend (mrequest, mresult)) {
if(mresult.retcode==10009 || mresult.retcode==10008) //запрос выполнен или ордер успешно помещен
{
Print («Price», mresult.price);
}
else
{
Print («Retcode ",mresult.retcode);
}
} else {
Print («Retcode ",mresult.retcode);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
}
Функции сигналов торговой системы выделим в класс Sidus.
class Sidus
{
private:
int numberBarOpenPosition;
int numberBarStopPosition;
int handleIMA18;
double MA18Buffer [];
int handleIMA28;
double MA28Buffer [];
int handleIWMA5;
double WMA5Buffer [];
int handleIWMA8;
double WMA8Buffer [];
public:
Sidus (int BarOpenPosition, int BarStopPosition);
~Sidus ();
bool OnTradeSignalBuy ();
bool OnTradeSignalBuyStop (MqlRates& mrate []);
bool OnTradeSignalSell ();
bool OnTradeSignalSellStop (MqlRates& mrate []);
};
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
Sidus::Sidus (int BarOpenPosition, int BarStopPosition)
{
numberBarOpenPosition=BarOpenPosition;
numberBarStopPosition=BarStopPosition;
handleIMA18=iMA (_Symbol, PERIOD_H1,18,0,MODE_EMA, PRICE_WEIGHTED);
handleIMA28=iMA (_Symbol, PERIOD_H1,28,0,MODE_EMA, PRICE_WEIGHTED);
handleIWMA5=iMA (_Symbol, PERIOD_H1,5,0,MODE_LWMA, PRICE_WEIGHTED);
handleIWMA8=iMA (_Symbol, PERIOD_H1,8,0,MODE_LWMA, PRICE_WEIGHTED);
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
Sidus::~Sidus ()
{
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
bool Sidus::OnTradeSignalBuy () {
bool flagBuy=false;
if (CopyBuffer (handleIMA18,0,0,numberBarOpenPosition, MA18Buffer) <0)
{
return false;
}
if (CopyBuffer (handleIMA28,0,0,numberBarOpenPosition, MA28Buffer) <0)
{
return false;
}
if (CopyBuffer (handleIWMA5,0,0,numberBarOpenPosition, WMA5Buffer) <0)
{
return false;
}
if (CopyBuffer (handleIWMA8,0,0,numberBarOpenPosition, WMA8Buffer) <0)
{
return false;
}
ArraySetAsSeries (MA18Buffer, true);
ArraySetAsSeries (MA28Buffer, true);
ArraySetAsSeries (WMA5Buffer, true);
bool flagCross1=false;
bool flagCross2=false;
bool flagCross=false;
if (WMA5Buffer [1]> MA18Buffer [1] &&WMA5Buffer [1]> MA28Buffer [1] &&WMA8Buffer [1]> MA18Buffer [1] &&WMA8Buffer [1]> MA28Buffer [1]) {
for (int i=2;i <numberBarOpenPosition; i++) {
if (WMA5Buffer [i] <MA18Buffer [i] &&WMA5Buffer [i] <MA28Buffer [i]) {
flagCross1=true;
}
if (WMA8Buffer [i] <MA18Buffer [i] &&WMA8Buffer [i] <MA28Buffer [i]) {
flagCross2=true;
}
}
if (flagCross1==true&&flagCross2==true) {
flagCross=true;
}
}
if (flagCross==true) {
flagBuy=true;
}
return flagBuy;
}
bool Sidus::OnTradeSignalBuyStop (MqlRates& mrate []) {
bool flagBuyStop=false;
if (CopyBuffer (handleIWMA5,0,0,numberBarStopPosition, WMA5Buffer) <0)
{
return false;
}
if (CopyBuffer (handleIWMA8,0,0,numberBarStopPosition, WMA8Buffer) <0)
{
return false;
}
ArraySetAsSeries (WMA5Buffer, true);
ArraySetAsSeries (WMA8Buffer, true);
bool flagCross=false;
if (WMA5Buffer [1] <WMA8Buffer [1]) {
for (int i=2;i <numberBarStopPosition; i++) {
if (WMA5Buffer [i]> WMA8Buffer [i]) {
flagCross=true;
}
}
}
double max=mrate [1].high;
for (int i=1;i <numberBarStopPosition; i++) {
if (mrate [i].high> max) max=mrate [i].high;
}
if (flagCross==true&&mrate [1].high <=max&&mrate [numberBarStopPosition-1].high <=max) {
flagBuyStop=true;
}
return flagBuyStop;
}
bool Sidus::OnTradeSignalSell () {
bool flagSell=false;
if (CopyBuffer (handleIMA18,0,0,numberBarOpenPosition, MA18Buffer) <0)
{
return false;
}
if (CopyBuffer (handleIMA28,0,0,numberBarOpenPosition, MA28Buffer) <0)
{
return false;
}
if (CopyBuffer (handleIWMA5,0,0,numberBarOpenPosition, WMA5Buffer) <0)
{
return false;
}
if (CopyBuffer (handleIWMA8,0,0,numberBarOpenPosition, WMA8Buffer) <0)
{
return false;
}
ArraySetAsSeries (MA18Buffer, true);
ArraySetAsSeries (MA28Buffer, true);
ArraySetAsSeries (WMA5Buffer, true);
ArraySetAsSeries (WMA8Buffer, true);
bool flagCross1=false;
bool flagCross2=false;
bool flagCross=false;
if (WMA5Buffer [1] <MA18Buffer [1] &&WMA5Buffer [1] <MA28Buffer [1] &&WMA8Buffer [1] <MA18Buffer [1] &&WMA8Buffer [1] <MA28Buffer [1]) {
for (int i=2;i <numberBarOpenPosition; i++) {
if (WMA5Buffer [i]> MA18Buffer [i] &&WMA5Buffer [i]> MA28Buffer [i]) {
flagCross1=true;
}
if (WMA8Buffer [i]> MA18Buffer [i] &&WMA8Buffer [i]> MA28Buffer [i]) {
flagCross2=true;
}
}
if (flagCross1==true&&flagCross2==true) {
flagCross=true;
}
}
if (flagCross==true) {
flagSell=true;
}
return flagSell;
}
bool Sidus::OnTradeSignalSellStop (MqlRates& mrate []) {
bool flagSellStop=false;
if (CopyBuffer (handleIWMA5,0,0,numberBarStopPosition, WMA5Buffer) <0)
{
return false;
}
if (CopyBuffer (handleIWMA8,0,0,numberBarStopPosition, WMA8Buffer) <0)
{
return false;
}
ArraySetAsSeries (WMA5Buffer, true);
ArraySetAsSeries (WMA8Buffer, true);
bool flagCross=false;
if (WMA5Buffer [1]> WMA8Buffer [1]) {
for (int i=2;i <numberBarStopPosition; i++) {
if (WMA5Buffer [i] <WMA8Buffer [i]) {
flagCross=true;
}
}
}
double min=mrate [1].low;
for (int i=1;i <numberBarStopPosition; i++) {
if (mrate [i].low <min) min=mrate [i].low;
}
if (flagCross==true&&mrate [1].low> =min&&mrate [numberBarStopPosition-1].low> =min) {
flagSellStop=true;
}
return flagSellStop;
}
В результате выделения функций в отдельные классы код советника существенно сократится.
#include "CheckTrade.mqh»
#include "Trade.mqh»
#include "Sidus.mqh»
input double Lot=1;
input int EA_Magic=1000;
input double spreadLevel=5.0;
input double StopLoss=0.01;
input double Profit=0.01;
input int numberBarOpenPosition=3;
input int numberBarStopPosition=5;
CheckTrade checkTrade;
Trade trade (StopLoss, Profit, Lot);
Sidus sidus (numberBarOpenPosition, numberBarStopPosition);
bool flagStopLoss=false;
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert initialization function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
int OnInit ()
{
return (checkTrade. OnCheckTradeInit (Lot));
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert deinitialization function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
void OnDeinit (const int reason)
{
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert tick function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
void OnTick ()
{
if (!checkTrade. OnCheckTradeTick (Lot, spreadLevel)) {
return;
}
//Ограничить вычисления советника по появлению нового бара на графике
static datetime last_time;
datetime last_bar_time= (datetime) SeriesInfoInteger (Symbol (),Period (),SERIES_LASTBAR_DATE);
if (last_time!=last_bar_time)
{
last_time=last_bar_time;
} else {
return;
}
//Ограничить вычисления советника по flagStopLoss
static datetime last_time_daily;
datetime last_bar_time_daily= (datetime) SeriesInfoInteger (Symbol (),PERIOD_D1,SERIES_LASTBAR_DATE);
if (last_time_daily!=last_bar_time_daily)
{
last_time_daily=last_bar_time_daily;
flagStopLoss=false;
}
if (flagStopLoss==true) return;
//Для вычисления сигналов торговой системы требуются исторические данные символа
MqlRates mrate [];
ResetLastError ();
if (CopyRates (Symbol (),Period (),0,numberBarStopPosition, mrate) <0)
{
Print (GetLastError ());
return;
}
ArraySetAsSeries (mrate, true);
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
bool TradeSignalBuy=false;
bool TradeSignalSell=false;
TradeSignalBuy=sidus. OnTradeSignalBuy ();
TradeSignalSell=sidus. OnTradeSignalSell ();
bool TradeSignalBuyStop=false;
bool TradeSignalSellStop=false;
TradeSignalBuyStop=sidus. OnTradeSignalBuyStop (mrate);
TradeSignalSellStop=sidus. OnTradeSignalSellStop (mrate);
trade. Order (TradeSignalBuy, TradeSignalBuyStop, TradeSignalSell, TradeSignalSellStop);
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Trade function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
void OnTrade ()
{
static int _deals;
ulong _ticket=0;
if (HistorySelect (0,TimeCurrent ()))
{
int i=HistoryDealsTotal () -1;
if (_deals!=i) {
_deals=i;
} else {return;}
if ((_ticket=HistoryDealGetTicket (i))> 0)
{
string _comment=HistoryDealGetString (_ticket, DEAL_COMMENT);
if (StringFind (_comment,«sl», 0)!=-1) {
flagStopLoss=true;
}
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — —