//+------------------------------------------------------------------+ //| mts.mq5 | //| Copyright 2010, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "denkir@gmail.com" #property version "1.00" //--- входные параметры input int K=3; // бар открытия позиции после креста 21/55: объект данных "K" в подсистеме Position handling и блоке K-Delay input int TakeProfit = 295; // Take Profit: блок Take Profit в подсистеме FromWorkspace input int StopLoss = 65; // Stop Loss: блок Stop Loss в подсистеме FromWorkspace input int MA1_Period = 21; // Период Moving Average 1 input int MA2_Period= 55; // Период Moving Average 2 input int Magic=76767; // Magic Number советника //--- глобальные переменные double Lot=1; // Количество лотов для торговли: объект данных "Lots" в подсистеме Position handling int ma1Handle; // хэндл индикатора Moving Average 1: блок "ema21 signal" int ma2Handle; // хэндл индикатора Moving Average 2: блок "ema55 signal" double ma1Val[]; // динамический массив для хранения значений индикатора Moving Average 1 для каждого бара: блок "ema21 signal" double ma2Val[]; // динамический массив для хранения значений индикатора Moving Average 2 для каждого бара: блок "ema55 signal" int sl,tp; // будут использованы для значений Stop Loss и Take Profit //+------------------------------------------------------------------+ //| Функция проверки открытой позиции | //+------------------------------------------------------------------+ bool IsTraded(bool IsBought,bool IsSold) { if(IsSold || IsBought) { Alert("Уже совершили сделку"); return(true); } else return(false); } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Необходимый минимум баров if(Bars(_Symbol,_Period)<56) // 1-ый переход подсистемы «Position handling»: условие [Input.num>=56] { Alert("Недостаточно баров!"); return(-1); } ma1Handle=iMA(_Symbol,_Period,MA1_Period,0,MODE_EMA,PRICE_CLOSE);//хэндл индикатора Moving Average 1: блок "ema21 signal" ma2Handle=iMA(_Symbol,_Period,MA2_Period,0,MODE_EMA,PRICE_CLOSE);//хэндл индикатора Moving Average 2: блок "ema55 signal" //--- Проверка на Invalid Handle if(ma1Handle<0 || ma2Handle<0) { Alert("Ошибка при создании индикаторов - номер ошибки: ",GetLastError(),"!!"); return(-1); } //--- Для работы с брокерами, использующими 5-ти значные котировки, //--- умножаем на 10 значения SL и TP sl = StopLoss; tp = TakeProfit; if(_Digits==5) { sl = sl*10; tp = tp*10; } return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Освобождаем хэндлы индикаторов IndicatorRelease(ma1Handle); IndicatorRelease(ma2Handle); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //Проверка на появление нового бара static datetime Old_Time; //static datetime Open_Time; //время открытия бара, на котором произошла предыдущая сделка datetime New_Time[1]; bool IsNewBar=false; int copied=CopyTime(_Symbol,_Period,0,1,New_Time); if(copied>0) { if(Old_Time!=New_Time[0]) { IsNewBar=true; Old_Time=New_Time[0]; } } else { Alert("Error =",GetLastError()); ResetLastError(); return; } if(IsNewBar==false) { return; } //--- Объявляем структуры, которые будут использоваться для торговли MqlTick latest_price; // Будет использоваться для текущих котировок MqlTradeRequest mrequest; // Будет использоваться для отсылки торговых запросов MqlTradeResult mresult; // Будет использоваться для получения результатов выполнения торговых запросов MqlRates mrate[]; // Будет содержать цены, объемы и спред для каждого бара /* Установим индексацию в массивах котировок и индикаторов как в таймсериях */ ArraySetAsSeries(mrate,true); // массив котировок ArraySetAsSeries(ma1Val,true);// массив значений индикатора MA 1: блок "ema21 signal" ArraySetAsSeries(ma2Val,true);// массив значений индикатора MA 2: блок "ema55 signal" //--- Получить текущее значение котировки в структуру типа MqlTick if(!SymbolInfoTick(_Symbol,latest_price)) { Alert("Ошибка получения последних котировок - ошибка:",GetLastError(),"!!"); return; } //--- Получить исторические данные последних 2+K-х баров if(CopyRates(_Symbol,_Period,0,2+K,mrate)<0) { Alert("Ошибка копирования исторических данных - ошибка:",GetLastError(),"!!"); return; } //--- Copy the new values of our indicators to buffers (arrays) using the handle if(CopyBuffer(ma1Handle,0,0,2+K,ma1Val)<0) { Alert("Ошибка копирования буферов индикатора Moving Average 1 - номер ошибки:",GetLastError()); return; } if(CopyBuffer(ma2Handle,0,0,2+K,ma2Val)<0) { Alert("Ошибка копирования буферов индикатора Moving Average 2 - номер ошибки:",GetLastError()); return; } //--- 1-ый переход подсистемы «Position handling»: условие [Input.num>Output.barClose] bool IsBought=false; // купили bool IsSold=false; // продали if(PositionSelect(_Symbol)==true) { if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) { IsBought=true; //long } else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) { IsSold=true; // short } } /* Проверка условий для покупки : EMA 21 на 1+K-м баре меньше EMA 55, EMA 21 на K-м баре больше EMA 55 */ /* проверка условий для покупки: блок "emas differential"; задержка массивов средних на K баров: блок "K Delay" создание события Buy (активизация отрицательным фронтом) */ bool Buy=((ma2Val[1+K]-ma1Val[1+K])>=0 && (ma2Val[K]-ma1Val[K])<0) || ((ma2Val[1+K]-ma1Val[1+K])>0 && (ma2Val[K]-ma1Val[K])==0); //создание события OpenBuy: подсистема "Position opening" //обработка события OpenBuy: подсистема "Position handling", её условия и процедуры if(Buy) { if(IsTraded(IsBought,IsSold)){ return;} // проверка на открытые позиции //процедуры 4-го перехода подсистемы «Position handling»: открытие длинной позиции mrequest.action = TRADE_ACTION_DEAL; // покупаем по рынку mrequest.price = NormalizeDouble(latest_price.ask,_Digits); // последняя цена ask mrequest.sl = NormalizeDouble(latest_price.bid - sl*_Point,_Digits); // ставим Stop Loss mrequest.tp = NormalizeDouble(latest_price.bid + tp*_Point,_Digits); // ставим Take Profit mrequest.symbol = _Symbol; // инструмент mrequest.volume = Lot; // всего лотов mrequest.magic=Magic; // Magic Number mrequest.type = ORDER_TYPE_BUY; // ордер на покупку mrequest.type_filling = ORDER_FILLING_AON; // в указанном объеме и по цене равной или лучше указанной в ордере mrequest.deviation=100; // величина проскальзывания OrderSend(mrequest,mresult); if(mresult.retcode==10009 || mresult.retcode==10008) // заявка выполнена или ордер размещен { //Open_Time=New_Time[0]; Alert("Ордер на покупку размещен, тикет #:",mresult.order); } else { Alert("Ордер на покупку не размещен; ошибка:",GetLastError()); return; } } /* Проверка условий для продажи : EMA 21 на 1+K-м баре больше EMA 55, EMA 21 на K-м баре меньше EMA 55 */ /* проверка условий для покупки: блок "emas differential"; задержка массивов средних на K баров: блок "K Delay" создание события Sell (активизация положительным фронтом) */ bool Sell=((ma2Val[1+K]-ma1Val[1+K])<=0 && (ma2Val[K]-ma1Val[K])>0) || ((ma2Val[1+K]-ma1Val[1+K])<0 && (ma2Val[K]-ma1Val[K])==0); //создание события OpenSell: подсистема "Position opening" //обработка события OpenSell: подсистема "Position handling", её условия и процедуры if(Sell) { if(IsTraded(IsBought,IsSold)){ return;} // проверка на открытые позиции //процедуры 5-го перехода подсистемы «Position handling»: открытие короткой позиции mrequest.action = TRADE_ACTION_DEAL; // продаём по рынку mrequest.price = NormalizeDouble(latest_price.bid,_Digits); // последняя цена bid mrequest.sl=NormalizeDouble(latest_price.ask+sl*_Point,_Digits); // ставим Stop Loss mrequest.tp=NormalizeDouble(latest_price.ask-tp*_Point,_Digits); // ставим Take Profit mrequest.symbol = _Symbol; // инструмент mrequest.volume = Lot; // всего лотов mrequest.magic=Magic; // Magic Number mrequest.type= ORDER_TYPE_SELL; // ордер на продажу mrequest.type_filling = ORDER_FILLING_AON; // в указанном объеме и по цене равной или лучше указанной в ордере mrequest.deviation=100; // величина проскальзывания OrderSend(mrequest,mresult); if(mresult.retcode==10009 || mresult.retcode==10008) // заявка выполнена или ордер размещен { Alert("Ордер на продажу размещен, тикет #:",mresult.order); } else { //Open_Time=New_Time[0]; Alert("Ордер на продажу не размещен; ошибка:",GetLastError()); return; } } return; //+------------------------------------------------------------------+ } //+------------------------------------------------------------------+