//+------------------------------------------------------------------+ //| ISHIMOKU.mq4 | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property copyright "more" #property link "mailto:tradertobe@gmail.com" #include #include #include //+------------------------------------------------------------------+ //ВСЕ ОЧЕНЬ ПРОСТО: ОТКРЫТИЕ/ЗАКРЫТИЕ ПОЗИЦИЙ ПРОИСХОДИТ ПРИ ПЕРЕСЕЧЕНИЕ ЛИНИЙ ИНДИКАТОРА ИШИМОКУ tenkan_sen И kijun_sen. // TakeProfit, StopLoss и Stop_0 заданы для 4-х разрядных котировок, если котировки 5-ти разрядные, то программа сама это обнаруживает // и умножает заданные величины на 10. //+------------------------------------------------------------------+ // Bar0Mode - режим нулевого бара: extern bool Bar0Mode = true; // если Bar0Mode = true, то перечечение tenkan_sen И kijun_sen будет фиксироваться по нулевому бару, // иначе пересечение будет фиксироваться по первому бару. extern int MagicNumber = 999; extern bool TradeAllowed = true; // разрешение на торговлю, если TradeAllowed = false, но есть открытая позиция, // то она будет закрыта обычным манером - при возникновения сигнала на закрытие, // однако, новая позиция открываться не будет. // Поэтому задав TradeAllowed = false, можно идти отдыхать, надеясь что все будет хорошо. extern double Lot = 0.1; // эти лотом мы будем торговать // TakeProfit,StopLoss и Stop_0 заданы для 4-х разрядных котировок, если котировки 5-ти разрядные, то программа сама это обнаруживает // и умножает заданные величины на 10. extern int TakeProfit = 30; // 4-х разрядная котировка extern int StopLoss = 30; // 4-х разрядная котировка extern int Stop_0 = 10; // 4-х разрядная котировка, при достижение такого профита StopLoss переносится в безубыток. // Если Stoplevel не позволяет этого сделать, выдается сообщение и звуковой сигнал тревоги. int Stoplevel; // здесь будет храниться текущий Stoplevel = MarketInfo(Symbol(),MODE_STOPLEVE) string Indicator_Name = "ISHIMOKU_IND"; static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop; static datetime LastBar; int bar2, bar1, bar0; int _ExpertOrdersTotal; //общее количество ордеров, принадлежащих эксперту int _ExpertOrdersBuy; int _ExpertOrdersSell; int _ExpertOrdersBuyStop; int _ExpertOrdersSellStop; int _ExpertOrdersBuyLimit; int _ExpertOrdersSellLimit; // массивы, в которых будут хранитсья характеристики ордеров при входе по текущему тику: int _OrderTicket[], _OrderType[]; double _OrderLots[], _OrderOpenPrice[], _OrderStopLoss[], _OrderTakeProfit[]; double _OrderProfit[], _OrderSwap[], _OrderCommission[]; datetime _OrderOpenTime[], _OrderExpiration[]; string _OrderComment[]; int _OrderMagicNumber[]; color Order_Clr; #define ORDER_BUY_CLR Blue #define ORDER_SELL_CLR Red string OrderOpenSetOkMes = " - Открыт/установлен успешно"; string OrderOpenSetErrorMes = " - Ошибка открытия/установки"; string OrderOpenStoplevel_ErrorMes = " - Ошибка открытия: StopLoss/TakeProfit меньше текущего Stoplevel="; string OrderModifyOkMes = " - Модифицирован успешно"; string OrderModifyErrorMes = " - Ошибка при модификации"; string OrderModifyStop_0_ErrorMes = " - Ошибка при модификации: Stop_0 меньше текущего Stoplevel="; string OrderDeleteOkMes = " - Удален успешно"; string OrderDeleteErrorMes = " - Ошибка при удалении"; string OrderCloseOkMes = " - Закрыт успешно"; string OrderCloseErrorMes = " - Ошибка при закрытии"; int TradeDirection; int LastError; int i; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- if (Digits == 5 ||Digits == 3 ) { TakeProfit *=10; StopLoss *=10; Stop_0 *=10; } //---- LastBar = iTime(NULL,0,0); return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //---- AllOrdersInit(MagicNumber); SetSignales(BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop, LastBar, bar2, bar1, bar0 ); if (OrdersOpenSet(BUY_Sign, SELL_Sign)) return(0); AllOrdersInit(MagicNumber); if (OrdersClose(BUY_Stop, SELL_Stop ) ) return(0); AllOrdersInit(MagicNumber); if (OrdersModify()) return(0); //---- return(0); // возвращаем управление терминалу } // end of int start() void SetSignales(bool& BUY_Sign, bool& BUY_Stop, bool& SELL_Sign, bool& SELL_Stop, datetime& LastBar, int& bar2, int& bar1,int& bar0 ) { if (Bar0Mode) { //--- BUY_Sign = false; BUY_Stop = false; SELL_Sign = false; SELL_Stop = false; //--- bar0 = iCustom(NULL,0,Indicator_Name,0,0); //--- bar1 = iCustom(NULL,0,Indicator_Name,0,1); //--- bar2 = iCustom(NULL,0,Indicator_Name,0,2); //--- if (bar0 > 0 && bar1 <= 0) BUY_Sign = true; if (bar0 < 0 && bar1 >= 0) BUY_Stop = true; if (bar0 < 0 && bar1 >= 0) SELL_Sign = true; if (bar0 > 0 && bar1 <= 0) SELL_Stop = true; //--- return; } // end of if (Bar0Mode) //--- datetime IBARS = iTime(NULL,0,0); //--- if (LastBar == IBARS) return; LastBar = IBARS; //--- BUY_Sign = false; BUY_Stop = false; SELL_Sign = false; SELL_Stop = false; //--- //--- bar0 = iCustom(NULL,0,Indicator_Name,0,0); //--- bar1 = iCustom(NULL,0,Indicator_Name,0,1); //--- bar2 = iCustom(NULL,0,Indicator_Name,0,2); //--- //--- if (bar1 > 0 && bar2 <= 0) BUY_Sign = true; if (bar1 < 0 && bar2 >= 0) BUY_Stop = true; if (bar1 < 0 && bar2 >= 0) SELL_Sign = true; if (bar1 > 0 && bar2 <= 0) SELL_Stop = true; //--- return; } // end of void SetSignales () //************************************************************ //+---------------------------------------------------------------------------------------------------------------+ //| функция открывает ордера и устанавливает лимитные ордера исходя из результатов анализа текущей ситуацию | //+---------------------------------------------------------------------------------------------------------------+ bool OrdersOpenSet(bool& BUY_Sign, bool& SELL_Sign) // return(true) -функция выполнила все что могла и управление следует передать терминалу { // return(false)-в вызове функции не было необходимости, управление следует передать далее по телу функции start() //---- if (_ExpertOrdersTotal == 0 && TradeAllowed) { Stoplevel = MarketInfo(Symbol(),MODE_STOPLEVEL); if ( (StopLoss != 0 && StopLoss < Stoplevel) || (TakeProfit != 0 && TakeProfit < Stoplevel) ) { PlaySound("alert.wav"); Print(OrderOpenStoplevel_ErrorMes+Stoplevel); return(false); } i = 0; // ради удобства TradeDirection = iif(BUY_Sign,+1,-1); _OrderType [i] = iif(TradeDirection < 0,OP_SELL,OP_BUY); _OrderLots [i] = Lot; _OrderOpenPrice [i] = iif(_OrderType[i]==OP_BUY,Ask,Bid); _OrderStopLoss [i] = iif(_OrderType[i]==OP_BUY,_OrderOpenPrice[i] - StopLoss * Point,_OrderOpenPrice[i] + StopLoss * Point); _OrderStopLoss [i] = iif( _OrderStopLoss[i]==_OrderOpenPrice[i],0,_OrderStopLoss[i]); _OrderTakeProfit[i] = iif(_OrderType[i]==OP_BUY,_OrderOpenPrice[i] + TakeProfit*Point,_OrderOpenPrice[i] - TakeProfit*Point); _OrderTakeProfit[i] = iif(_OrderTakeProfit[i] == _OrderOpenPrice[i],0,_OrderTakeProfit[i]); _OrderMagicNumber[i] = MagicNumber; _OrderComment [i] = " "; Order_Clr = iif(TradeDirection > 0,ORDER_BUY_CLR,ORDER_SELL_CLR); if (_OrderSend()) { BUY_Sign = iif(TradeDirection == +1,false,BUY_Sign ); SELL_Sign = iif(TradeDirection == -1,false,SELL_Sign); } return(true); } // end of if (_ExpertOrdersTotal == 0 && TradeAllowed) //---- return(false); // вызов функции не был необходим, управление следует передать далее по телу функции start() } // end of bool OrdersOpenSet(BUY_Sign, SELL_Sign) //+------------------------------------------------------------------+ //| функция посылает на ТОРГОВЫЙ СЕРВЕР команды на немедленное | //| открытие ордера или на установку лимитного ордера | //+------------------------------------------------------------------+ bool _OrderSend() { if (IsTradeContextBusy()) { PlaySound("alert.wav"); return(false);} // торговый поток занят, подождем следующего тика _OrderTicket[i]= OrderSend(Symbol(),_OrderType [i] ,_OrderLots [i] ,_OrderOpenPrice [i] ,3 ,_OrderStopLoss [i] ,_OrderTakeProfit [i] ,_OrderComment [i] ,_OrderMagicNumber[i],0,Order_Clr); if (_OrderTicket[i] < 0) { LastError = GetLastError(); Print("("+_OrderMagicNumber[i]+")"+_OrderComment[i]+OrderOpenSetErrorMes+" : "+ LastError+" - "+ErrorDescription(LastError)); PlaySound("alert.wav"); return(false); } Print("("+_OrderMagicNumber[i]+")"+_OrderComment[i]+"("+_OrderTicket[i]+")"+OrderOpenSetOkMes); PlaySound("ok.wav"); return(true); } // end of bool _OrderSend() //+---------------------------------------------------------------------------------------+ //| функция производит модификацию ордеров исходя из результатов анализа текущей ситуации | //+---------------------------------------------------------------------------------------+ bool OrdersModify() // return(true) -функция выполнила все что могла и управление следует передать терминалу { // return(false)-в вызове функции не было необходимости, управление следует передать далее по телу функции start() if (_ExpertOrdersTotal == 0) return(false); i = 0; // ради удобства TradeDirection = iif(_OrderType[i] == OP_BUY,+1,-1); double CurrentPrice = iif(TradeDirection == +1,Bid,Ask); int Profit = iif(TradeDirection == +1,(CurrentPrice - _OrderOpenPrice[i])/Point,(_OrderOpenPrice[i] - CurrentPrice)/Point); if (Profit < Stop_0) return(false); Stoplevel = MarketInfo(Symbol(),MODE_STOPLEVEL); if (Stop_0 <= Stoplevel) { PlaySound("alert.wav"); Print("("+MagicNumber+")"+_OrderComment[i]+"("+_OrderTicket[i]+")"+OrderModifyStop_0_ErrorMes+Stoplevel); return(false); } if (_OrderStopLoss [i] >= _OrderOpenPrice [i]) return(false); _OrderStopLoss [i] = _OrderOpenPrice [i]; _OrderModify(); return(true); } // end of bool OrdersModify() //+--------------------------------------------------------------------+ //| функция посылает на ТОРГОВЫЙ СЕРВЕР команду на немедленную | //| модификацию открытого или лимитного ордера | //+--------------------------------------------------------------------+ bool _OrderModify() { if (IsTradeContextBusy()) { PlaySound("alert.wav"); return(false);} // торговый поток занят, подождем следующего тика if (OrderModify(_OrderTicket [i] ,_OrderOpenPrice [i] ,_OrderStopLoss [i] ,_OrderTakeProfit[i] ,0 ,CLR_NONE)) { Print("("+MagicNumber+")"+_OrderComment[i]+"("+_OrderTicket[i]+")"+OrderModifyOkMes); PlaySound("ok.wav"); return(true); } LastError = GetLastError(); if (LastError == ERR_NO_RESULT) return(true); Print("("+MagicNumber+")"+_OrderComment[i]+"("+_OrderTicket[i]+")"+OrderModifyErrorMes+" : "+ LastError+" - "+ErrorDescription(LastError)); PlaySound("alert.wav"); return(false); } // end of bool _OrderModify() //+---------------------------------------------------------------------------------------+ //| функция производит удаление стоповых ордеров, когда открытых ордеров уже не осталось | //+---------------------------------------------------------------------------------------+ /* bool OrdersDelete() // return(true) -функция выполнила все что могла и управление следует передать терминалу { // return(false)-в вызове функции не было необходимости, управление следует передать далее по телу функции start() //---- if (TradeCycleClose) { if ( (_ExpertOrdersSell + _ExpertOrdersBuy) != 0) return(false); if (_ExpertOrdersTotal == 0) { TradeCycleClose = false; return(false); } for (i = 0; i < _ExpertOrdersTotal; i++) { switch(_OrderType [i]) { case OP_BUYSTOP : _OrderDelete(); break; case OP_SELLSTOP : _OrderDelete(); break; } } } //---- return(true); } //+--------------------------------------------------------------------+ //| функция посылает на ТОРГОВЫЙ СЕРВЕР команду на немедленное | //| удаление лимитного ордера | //+--------------------------------------------------------------------+ bool _OrderDelete() { if (IsTradeContextBusy()) { PlaySound("alert.wav"); return(false);} // торговый поток занят, подождем следующего тика if (OrderDelete(_OrderTicket[i] ,CLR_NONE)) { Print("("+_OrderMagicNumber[i]+")"+_OrderComment[i]+"("+_OrderTicket[i]+")"+OrderDeleteOkMes); PlaySound("ok.wav"); return(true); } LastError = GetLastError(); Print("("+_OrderMagicNumber[i]+")"+_OrderComment[i]+"("+_OrderTicket[i]+")"+OrderDeleteErrorMes+" : "+ LastError+" - "+ErrorDescription(LastError)); PlaySound("alert.wav"); return(false); } */ //+----------------------------------------------------------------------------------------------------------------------+ //| функция производит закрытие всех открытых ордеров, в случае если обнаружит смену тренда по простому признаку Ишимоку | //+----------------------------------------------------------------------------------------------------------------------+ bool OrdersClose(bool& BUY_Stop, bool& SELL_Stop ) // return(true) -функция выполнила все что могла и управление следует передать терминалу { // return(false)-в вызове функции не было необходимости, управление следует передать далее по телу функции start() if ( (BUY_Stop && _ExpertOrdersBuy != 0) || (SELL_Stop && _ExpertOrdersSell != 0)) { i = 0; TradeDirection = iif(BUY_Stop,+1,-1); _OrderOpenPrice [i] = iif(TradeDirection == +1,Bid,Ask); Order_Clr = iif(TradeDirection > 0,ORDER_BUY_CLR,ORDER_SELL_CLR); if (_OrderClose()) { BUY_Stop = iif(TradeDirection == +1,false,BUY_Stop ); SELL_Stop = iif(TradeDirection == -1,false,SELL_Stop); } return(true); } // end of if ( (BUY_Stop && _ExpertOrdersOP_BUY != 0) || (SELL_Stop && _ExpertOrdersOP_SELL != 0)) return(false); } // end of if ( (BUY_Stop && _ExpertOrdersBuy != 0) || (SELL_Stop && _ExpertOrdersSell != 0)) //+--------------------------------------------------------------------+ //| функция посылает на ТОРГОВЫЙ СЕРВЕР команду на немедленное | //| закрытие открытогоо ордера | //+--------------------------------------------------------------------+ bool _OrderClose() { if (IsTradeContextBusy()) { PlaySound("alert.wav"); return(false);} // торговый поток занят, подождем следующего тика if (OrderClose(_OrderTicket [i] ,_OrderLots [i] ,_OrderOpenPrice[i],3 ,Order_Clr)) { Print("("+_OrderMagicNumber[i]+")"+_OrderComment[i]+"("+_OrderTicket[i]+")"+OrderCloseOkMes); PlaySound("ok.wav"); return(true); } LastError = GetLastError(); Print("("+_OrderMagicNumber[i]+")"+_OrderComment[i]+"("+_OrderTicket[i]+")"+OrderCloseErrorMes+" : "+ LastError+" - "+ErrorDescription(LastError)); PlaySound("alert.wav"); return(false); } // end of bool _OrderClose() //+-----------------------------------------------------------------------------------------------------+ //| функция производит формирование массивов, каждый из которых представляет одно | //| поле ордера, принадлежащего эксперту. таким образом, множество элементов массивов с | //| одним значение индекса представляет ордер. массивы отсортированы в порядке возрастания тикета | //| размерность массивов = _ExpertOrdersTotal + 1 | //| последние элементы массивов будут использоваться нами для формирования данных при открытии/установки| //| нового ордера | //+----------------------------------------------------------------------------------------------------+ //"mailto:komposterius@mail.ru" - Андрей Хатимлянский - автор этой функции //http://www.mql4.com/ru/users/komposter Андрей Хатимлянский void AllOrdersInit( int magic ) { int _GetLastError = 0, _OrdersTotal = OrdersTotal(); _ExpertOrdersTotal = 0; //общее количество ордеров, принадлежащих эксперту _ExpertOrdersBuy = 0; // _ExpertOrdersSell = 0; // _ExpertOrdersBuyStop = 0; // _ExpertOrdersSellStop = 0; // _ExpertOrdersBuyLimit = 0; // _ExpertOrdersSellLimit = 0; // // изменяем размеры массивов под текущее кол-во позиций // (если _OrdersTotal = 0, меняем размер массивов на 1) int temp_value = MathMax( _OrdersTotal+1, 1 ); ArrayResize( _OrderTicket, temp_value ); ArrayResize( _OrderType, temp_value ); ArrayResize( _OrderLots, temp_value ); ArrayResize( _OrderOpenPrice, temp_value ); ArrayResize( _OrderStopLoss, temp_value ); ArrayResize( _OrderTakeProfit, temp_value ); ArrayResize( _OrderOpenTime, temp_value ); ArrayResize( _OrderProfit, temp_value ); ArrayResize( _OrderSwap, temp_value ); ArrayResize( _OrderCommission, temp_value ); ArrayResize( _OrderComment, temp_value ); ArrayResize( _OrderExpiration, temp_value ); ArrayResize( _OrderMagicNumber, temp_value ); // обнуляем массивы ArrayInitialize( _OrderTicket, 0 ); ArrayInitialize( _OrderType, 0 ); ArrayInitialize( _OrderLots, 0 ); ArrayInitialize( _OrderOpenPrice, 0 ); ArrayInitialize( _OrderStopLoss, 0 ); ArrayInitialize( _OrderTakeProfit, 0 ); ArrayInitialize( _OrderOpenTime, 0 ); ArrayInitialize( _OrderProfit, 0 ); ArrayInitialize( _OrderSwap, 0 ); ArrayInitialize( _OrderCommission, 0 ); ArrayInitialize( _OrderExpiration, 0 ); ArrayInitialize( _OrderMagicNumber, 0 ); for ( int z = 0; z < _OrdersTotal; z ++ ) { if ( !OrderSelect( z, SELECT_BY_POS ) ) { _GetLastError = GetLastError(); Print("OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", _GetLastError ); continue; } if (OrderMagicNumber() == magic && OrderSymbol() == Symbol() ) { // заполняем массив тикетов ордеров, принадлежащих експерту _OrderTicket [_ExpertOrdersTotal] = OrderTicket(); _ExpertOrdersTotal ++; switch(OrderType()) { case OP_BUY : _ExpertOrdersBuy++ ; break; case OP_SELL : _ExpertOrdersSell++ ; break; case OP_BUYSTOP : _ExpertOrdersBuyStop++ ; break; case OP_SELLSTOP : _ExpertOrdersSellStop++ ; break; case OP_BUYLIMIT : _ExpertOrdersBuyLimit++ ; break; case OP_SELLLIMIT : _ExpertOrdersSellLimit++ ; break; } } } // изменяем размеры массивов под кол-во позиций, принадлежащих эксперту + одна // (если _ExpertOrdersTotal = 0, меняем размер массивов на 1) temp_value = MathMax( _ExpertOrdersTotal+1, 1 ); ArrayResize( _OrderTicket, temp_value ); ArrayResize( _OrderType, temp_value ); ArrayResize( _OrderLots, temp_value ); ArrayResize( _OrderOpenPrice, temp_value ); ArrayResize( _OrderStopLoss, temp_value ); ArrayResize( _OrderTakeProfit, temp_value ); ArrayResize( _OrderOpenTime, temp_value ); ArrayResize( _OrderProfit, temp_value ); ArrayResize( _OrderSwap, temp_value ); ArrayResize( _OrderCommission, temp_value ); ArrayResize( _OrderComment, temp_value ); ArrayResize( _OrderExpiration, temp_value ); _OrderTicket[_ExpertOrdersTotal] = 99999999;// при сортировке этот пустой элемент будет последним ArraySort(_OrderTicket); // получим хронологический порядок... //------------------------------------------------------------------------------------------------------------------------ for ( z = 0; z < _ExpertOrdersTotal; z ++ ) { if ( !OrderSelect( _OrderTicket[z], SELECT_BY_TICKET ) ) { _GetLastError = GetLastError(); Print("OrderSelect( ", _OrderTicket[z], ", SELECT_BY_TICKET ) - Error #", _GetLastError ); continue; } // заполняем остальные массивы _OrderType [z] = OrderType(); _OrderLots [z] = NormalizeDouble( OrderLots(), 2 ); _OrderOpenPrice [z] = NormalizeDouble( OrderOpenPrice(), Digits ); _OrderStopLoss [z] = NormalizeDouble( OrderStopLoss(), Digits ); _OrderTakeProfit [z] = NormalizeDouble( OrderTakeProfit(), Digits ); _OrderOpenTime [z] = OrderOpenTime(); _OrderProfit [z] = NormalizeDouble( OrderProfit(), 2 ); _OrderSwap [z] = NormalizeDouble( OrderSwap(), 2 ); _OrderCommission [z] = NormalizeDouble( OrderCommission(), 2 ); _OrderComment [z] = OrderComment(); _OrderExpiration [z] = OrderExpiration(); _OrderMagicNumber [z] = OrderMagicNumber(); } //------------------------------------------------------------------------------------------------------------------------ return; } //------------------------------------------------------------------------------------------------------------------------ //http://www.mql4.com/ru/users/bstone -Крамарь Роман - автор четырех, следующих ниже функций //+------------------------------------------------------------------+ //| helper functions - Крамарь Роман //+------------------------------------------------------------------+ int sign( double v ) { if( v < 0 ) return( -1 ); return( 1 ); } //+------------------------------------------------------------------+ double iif( bool condition, double ifTrue, double ifFalse ) { if( condition ) return( ifTrue ); return( ifFalse ); } //+------------------------------------------------------------------+ string iifStr( bool condition, string ifTrue, string ifFalse ) { if( condition ) return( ifTrue ); return( ifFalse ); } //+------------------------------------------------------------------+ int orderDirection() { return( 1 - 2 * ( OrderType() % 2 ) ); } //------------------------------------------------------------------------------------------------------------------------