В качестве основы советника возьмем следующий код:
input double Lot=1;
input int EA_Magic=1000;
input double spreadLevel=5.0;
input double StopLoss=0.01;
input double Profit=0.01;
bool flagStopLoss=false;
int OnCheckTradeInit () {
//Проверка запуска эксперта на реальном счете
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);
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert initialization function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
int OnInit ()
{
return (OnCheckTradeInit ());
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert deinitialization function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
void OnDeinit (const int reason)
{
}
int OnCheckTradeTick () {
//Проверка отсутствия соединения к серверу
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> spreadLevel) {
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);
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert tick function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
void OnTick ()
{
if (!OnCheckTradeTick ()) {
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;
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
//Проверка наличия открытой позиции, чтобы не пытаться открыть ее заново
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;
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
//Для вычисления сигналов торговой системы требуются исторические данные символа
MqlRates mrate [];
ResetLastError ();
if (CopyRates (Symbol (),Period (),0,3,mrate) <0)
{
Print (GetLastError ());
return;
}
ArraySetAsSeries (mrate, true);
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
bool TradeSignalBuy=false;
bool TradeSignalSell=false;
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
MqlTradeRequest mrequest;
MqlTradeCheckResult check_result;
MqlTradeResult mresult;
MqlTick latest_price;
if (!SymbolInfoTick (_Symbol, latest_price))
{
Alert («Ошибка получения последних котировок – ошибка:», GetLastError (),»!!»);
return;
}
if (TradeSignalBuy==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 (TradeSignalSell==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);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| 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;
}
}
}
}
Здесь общие проверки функции OnInit выделены в отдельную функцию OnCheckTradeInit, а общие проверки функции OnTick выделены в отдельную функцию OnCheckTradeTick.
Советник будет отправлять ордера на покупку и продажу при установке флагов TradeSignalBuy и TradeSignalSell в значение true.
Установку значений флагов TradeSignalBuy и TradeSignalSell должна осуществлять торговая система.
В качестве торговой системы возьмем «Метод Сидуса»:
Валютные пары: EUR/GBP и EUR/USD.
Временной интервал – Н1;
Экспоненциальные скользящие средние (Exponential Moving Average): 18 ЕМА и 28 ЕМА;
Weighted Moving Average – 5WMA и 8 WMA.
Торговые сигналы на вход в рынок по Методу Сидуса:
Открытие позиции на покупку: 5WMA и 8 WMA скользящие средние пересекают туннель из 18 ЕМА и 28 ЕМА снизу вверх.
Открытие позиции на продажу: 5WMA и 8 WMA скользящие средние пересекают туннель из 18 ЕМА и 28 ЕМА сверху вниз.
Торговые сигналы на выход из рынка по Методу Сидуса:
На покупку: цена на графике достигла вершины и 5 WMA как бы «ныряет» под 8 WMA скользящую среднюю. Следует закрыть открытую торговую позицию.
На продажу: цена на графике достигла дна и скользящая средняя 5 WMA как бы «прыгает» над 8WMA. Следует закрыть торговую позицию.
Код советника, реализующий Метод Сидуса:
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=5;
input int numberBarStopPosition=5;
bool flagStopLoss=false;
int handleIMA18;
double MA18Buffer [];
int handleIMA28;
double MA28Buffer [];
int handleIWMA5;
double WMA5Buffer [];
int handleIWMA8;
double WMA8Buffer [];
int OnCheckTradeInit () {
//Проверка запуска эксперта на реальном счете
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);
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert initialization function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
int OnInit ()
{
handleIMA18=iMA (_Symbol, PERIOD_H1,18,0,MODE_EMA, PRICE_CLOSE);
handleIMA28=iMA (_Symbol, PERIOD_H1,28,0,MODE_EMA, PRICE_CLOSE);
handleIWMA5=iMA (_Symbol, PERIOD_H1,5,0,MODE_LWMA, PRICE_CLOSE);
handleIWMA8=iMA (_Symbol, PERIOD_H1,8,0,MODE_LWMA, PRICE_CLOSE);
return (OnCheckTradeInit ());
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert deinitialization function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
void OnDeinit (const int reason)
{
}
int OnCheckTradeTick () {
//Проверка отсутствия соединения к серверу
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> spreadLevel) {
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);
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| Expert tick function |
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
void OnTick ()
{
if (!OnCheckTradeTick ()) {
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;
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
//Проверка наличия открытой позиции, чтобы не пытаться открыть ее заново
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;
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
//Для вычисления сигналов торговой системы требуются исторические данные символа
MqlRates mrate [];
ResetLastError ();
if (CopyRates (Symbol (),Period (),0,numberBarStopPosition, mrate) <0)
{
Print (GetLastError ());
return;
}
ArraySetAsSeries (mrate, true);
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
bool TradeSignalBuy=false;
bool TradeSignalSell=false;
TradeSignalBuy=OnTradeSignalBuy ();
TradeSignalSell=OnTradeSignalSell ();
bool TradeSignalBuyStop=false;
bool TradeSignalSellStop=false;
TradeSignalBuyStop=OnTradeSignalBuyStop (mrate);
TradeSignalSellStop=OnTradeSignalSellStop (mrate);
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
MqlTradeRequest mrequest;
MqlTradeCheckResult check_result;
MqlTradeResult mresult;
MqlTick latest_price;
if (!SymbolInfoTick (_Symbol, latest_price))
{
Alert («Ошибка получения последних котировок – ошибка:», GetLastError (),»!!»);
return;
}
if (TradeSignalBuy==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 (TradeSignalSellStop==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 (TradeSignalSell==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 (TradeSignalBuyStop==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);
}
}
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — —
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
}
//+ – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – +
//| 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;
}
}
}
}
bool 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);
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;
}
}
flagBuy=flagCross;
return flagBuy;
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – —
bool 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 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;
}
}
flagSell=flagCross;
return flagSell;
}
// – — – — – — – — – — – — – — – — – — – — – — – — – — —
bool 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;
}
Здесь перед функциями обратного вызова, объявляются входные параметры numberBarOpenPosition – количество баров, на которых будет проверяться пересечение 5WMA и 8 WMA туннеля из 18 ЕМА и 28 ЕМА, и numberBarStopPosition – количество баров, на которых будет проверяться пересечение 5WMA и 8 WMA и достижения ценой вершины или дна.
Далее объявляются хэндлы индикаторов и динамические массивы значений индикаторов.
В методе OnInit с помощью стандартных функций возвращаются хэндлы индикаторов.
В методе OnTick для получения сигналов на продажу или покупку вызываются функции OnTradeSignalBuy, OnTradeSignalSell, OnTradeSignalBuyStop, OnTradeSignalSellStop.
В функции OnTradeSignalBuy и функции OnTradeSignalSell с помощью хэндлов индикаторов заполняются динамические массивы значений индикаторов и на количестве баров numberBarOpenPosition проверяется пресечение 5WMA и 8 WMA туннеля из 18 ЕМА и 28 ЕМА.
В функции OnTradeSignalBuyStop и функции OnTradeSignalSellStop с помощью хэндлов индикаторов заполняются динамические массивы значений индикаторов и на количестве баров numberBarStopPosition проверяется пресечение 5WMA и 8 WMA и достижения ценой вершины или дна.
После компиляции советника в клиентском терминале нажмем правой кнопкой мышки на советнике и выберем Тестировать.
Попробуем оптимизировать параметры numberBarOpenPosition и numberBarStopPosition.
В результате оптимизации получим профит при значении numberBarOpenPosition = 3, независимо от значений numberBarStopPosition.
Так получилось, потому что только два раза на трех барах произошло пересечение 5WMA и 8 WMA туннеля из 18 ЕМА и 28 ЕМА и оба раза сделки были прибыльными.
Если взять больший период, картина будет не такая радужная, хотя профит сохранится при значении numberBarOpenPosition = 3, независимо от значений numberBarStopPosition.
При изменении параметра цены индикаторов на PRICE_WEIGHTED показатель прибыли улучшается.
Условие достижения рынком дна или вершины можно заменить на горизонтальность линии EMA.
MathAbs (WMA5Buffer [1] -WMA5Buffer [numberBarStopPosition-1]) <0.001
Можно убрать действие сигналов TradeSignalBuyStop и TradeSignalSellStop и работать только на достижение Take Profit или Stop Loss.