//+------------------------------------------------------------------+ //| Visual_Handle_Tranning.mq4 | //+------------------------------------------------------------------+ //| b - открыть позицию Buy; | //| s - открыть позицию Sell; | //| "стрелка вверх" - закрыть все BUY; | //| "стрелка вниз" - закрыть все SELL; | //| t - включает трейлинг стоп общий; | //| r - выключает трейлинг стоп; | //| d - удаление всех отложенных ордеров. | //| Для выставления отложенного ордера мышкой выбираем из меню | //| значков "Стрелочку вверх" для Buy-ев и щелкаем в том месте, | //| где планируем поставить ордер. Если щелкнуть выше цены, то | //| будет BuyStop, если ниже - будет BuyLimit. | //| для Sell-ов, соответственно, значек "стрелочка вниз". | //| Модификация отдельных ордеров: | //| Двойным щелчком мыши выделяем нужный нам значек-ордер | //| далее, щелкаем по нему правой клавишей мыши | //| и выбираем свойства Arrow. | //| Далее, меняем в поле "Описание" нужные параметры отдельного | //| ордера. | //| Можно менять SL, TP, а также закрыть рыночный ордер | //| или удалить отложенный Вместо EMPTY пишем close или del | //| ВАЖНО сохранить пробелы - это разделители !!! | //| Формат поля "Описание", разделитель-"ПРОБЕЛ!!!": | //| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | | //| Price= 1.2565 SL= 1.2765 TP= 1.2265 Команда= close | //| | | | | | | | | | | //| Команда на закрытие рыночного ордера - close | //| Удаление отложенного - del | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, klot" #property link "klot@mail.ru" #define MAGICEXP 00000001 //---- #include #include //---- #import "IdleLib.dll" int GetLastKeyWP(); int GetLastMouseWP(); int IdleLibInit(); int IdleLibUnInit(); string GetActiveWndName(); #import //---- extern double Lots = 0.1; extern double TrailingStop = 15.0; //---- static datetime lastsd; static int tral = 0; //color clModifyBuy = Aqua; //color clModifySell = Magenta; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { // инициализируем Dll для перехвата событий IdleLibInit(); //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { // деинициализируем Dll для перехвата событий IdleLibUnInit(); //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { if(IsDllsAllowed() == false) { Print("Вызов DLL-функций из библиотек невозможен. Эксперт не может выполняться."); return(0); } if(IsLibrariesAllowed() == false) { Print("Библиотечные вызовы запрещены. Эксперт не может выполняться."); return(0); } if(!IsTesting()) { Print("Эксперт запущен не в режиме тестирования"); return(0); } if(IsOptimization()) { Print("Эксперт запущен в режиме оптимизации"); return(0); } // устранение дребезга клавиш static int trigger = 0; // Опрашиваем код последней нажатой клавиши int lastkey = GetLastKeyWP(); // Имя окна Metatrader, где произошло событие string lastwnd = GetActiveWndName(); //---- if((lastkey != 0) && (lastwnd != "")) { //устранение дребезга клавиш if(trigger != lastkey) trigger = lastkey; else { lastkey = 0; trigger = 0; } //--- switch(lastkey) { case 66: buy_open(0, 0); break; case 83: sell_open(0, 0); break; case 38: close_order(1); break; case 40: close_order(-1); break; case 84: if(tral == 0) tral = 1; Comment("Tralling включен = ", TrailingStop); break; case 82: if(tral == 1 ) tral = 0; Comment("Tralling выключен"); break; case 68: delete_pending_all(); break; //case ..: можно придумать любую собственню фичу default : break; } } send_pending(); managers_market_orders(); //---- if(lastkey != 0) Print(" "+lastkey); //---- return(0); } //+------------------------------------------------------------------+ //| Управление рыночными ордерами (изменение SL,TP,price) | //| Все писать в Свойствах Arrow, в поле "Описание" | //| Формат поля "Описание", разделитель-"ПРОБЕЛ!!!": | //| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | | //| Price= 1.2565 SL= 1.2765 TP= 1.2265 Команда= close | //| | | | | | | | | | | //| Команда на закрытие рыночного ордера - close | //| Удаление отложенного - del | //| //+------------------------------------------------------------------+ void managers_market_orders() { string desc, name, exec, _EMPTY = "EMPTY"; string array_param[]; int count, arrow_code, ticket, pos, nGetLastError; double price, sl, tp; int TrailingStep = 5; int obj_total = ObjectsTotal(); //---- if(obj_total == 0) return; //---- for(int i = obj_total - 1; i >= 0; i--) { name = ObjectName(i); //---- if(ObjectType(name) != OBJ_ARROW) continue; arrow_code = ObjectGet(name, OBJPROP_ARROWCODE); if(arrow_code != 1 && arrow_code != 2) continue; else { //Вычисляем тикет ордера по значку Arrow pos = StringFind(name, " ", 0); ticket = StrToInteger(StringSubstr(name, 1, pos)); //Print("ticket= ",ticket); //--- if(OrderSelect(ticket, SELECT_BY_TICKET) == true) { if(OrderCloseTime()!=0) continue; //Читаем поле Описание в свойствах Arrow desc = ObjectDescription(name); // Если строчка пустая заполним начальными значениями if(StringLen(desc) == 0) { desc = StringConcatenate("Price= ", OrderOpenPrice(), " SL= ", OrderStopLoss(), " TP= ", OrderTakeProfit(), " Команда= ",_EMPTY); ObjectSetText(name, desc); } // заполнение массива параметров ордера count = StrSplit(desc, array_param, " "); if(count != 8) { desc = StringConcatenate("Price= ", OrderOpenPrice(), " SL= ", OrderStopLoss(), " TP= ", OrderTakeProfit(), " Команда= ",_EMPTY); ObjectSetText(name, desc); Print(" Ошибка в формате поля Оисание. Поле востановлено!!!"); } else { price = StrToDouble(array_param[1]); sl = StrToDouble(array_param[3]); tp = StrToDouble(array_param[5]); exec = array_param[7]; } //--- if(OrderType()==OP_BUY) { if(TrailingStop > MarketInfo(Symbol(), MODE_STOPLEVEL) && tral == 1) { if(Bid - OrderOpenPrice() > TrailingStop*Point) { if(OrderStopLoss() < Bid - (TrailingStop + TrailingStep - 1)*Point) { sl = Bid - TrailingStop*Point; desc = StringConcatenate("Price= ", OrderOpenPrice(), " SL= ", sl, " TP= ", OrderTakeProfit(), " Команда= ", _EMPTY); ObjectSetText(name, desc); } } } //--- if(sl != 0 && sl != OrderStopLoss()) ModifyStopLoss(sl); if(tp != 0 && tp != OrderTakeProfit()) ModifyTakeProfit(tp); //--- if(exec == "close") { RefreshRates(); OrderClose(OrderTicket(), OrderLots(), Bid, 3, Aqua); nGetLastError = GetLastError(); if(nGetLastError != 0) Print("Error closing BUY order : ", ErrorDescription(nGetLastError)); } } if(OrderType() == OP_SELL) { if(TrailingStop > MarketInfo(Symbol(), MODE_STOPLEVEL) && tral == 1) { if(OrderOpenPrice() - Ask > TrailingStop*Point) { if(OrderStopLoss() > Ask + (TrailingStop + TrailingStep - 1)*Point || OrderStopLoss() == 0) { sl = Ask + TrailingStop*Point; desc = StringConcatenate("Price= ", OrderOpenPrice(), " SL= ", sl, " TP= ", OrderTakeProfit(), " Команда= ",_EMPTY); ObjectSetText(name, desc); } } } //--- if(sl != 0 && sl != OrderStopLoss()) ModifyStopLoss(sl); if(tp != 0 && tp != OrderTakeProfit()) ModifyTakeProfit(tp); //--- if(exec=="close") { RefreshRates(); OrderClose(OrderTicket(), OrderLots(), Ask, 3, Yellow); nGetLastError = GetLastError(); if(nGetLastError != 0) Print("Error closing SELL order : ", ErrorDescription(nGetLastError)); } } if(OrderType() == OP_SELLLIMIT || OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP || OrderType() == OP_SELLSTOP) { // если мышкой переместили ордер if(NormalizeDouble(ObjectGet(name, OBJPROP_PRICE1), Digits) != price) { price = NormalizeDouble(ObjectGet(name, OBJPROP_PRICE1), Digits); desc = StringConcatenate("Price= ", price, " SL= ", OrderStopLoss(), " TP= ", OrderTakeProfit(), " Команда= ", _EMPTY); ObjectSetText(name, desc); } //--- if(price != OrderOpenPrice() && MathAbs(price - Ask) > (MarketInfo(Symbol(), MODE_STOPLEVEL)*Point) ) { OrderModify(OrderTicket(), price, OrderStopLoss(), OrderTakeProfit(), OrderExpiration(),CLR_NONE); nGetLastError = GetLastError(); if(nGetLastError != 0) Print("Error closing SELL order : ", ErrorDescription(nGetLastError)); else ObjectDelete(name); } //---- if(sl != 0 && sl != OrderStopLoss()) ModifyStopLoss(sl); if(tp != 0 && tp != OrderTakeProfit()) ModifyTakeProfit(tp); //---- if(exec == "del") { OrderDelete(OrderTicket()); nGetLastError = GetLastError(); if(nGetLastError != 0) Print("Error closing SELL order : ", ErrorDescription(nGetLastError)); } } } else Print("OrderSelect() вернул ошибку - ", GetLastError()); } } } //+------------------------------------------------------------------+ //| Установка отложенных ордеров | //| просто перетаскиваем значек "стрелочка вверх" на место, куда | //| хотим поставить отложенный ордер. Если выше цены будет ByuStop | //| если ниже цены - будет BuyLimit. Для Sel-ов - соответственно | //| значек "стрелочка вниз" | //+------------------------------------------------------------------+ void send_pending() { int arrow_code; string name; double price; int obj_total = ObjectsTotal(); //---- for(int i = 0; i < obj_total; i++) { name = ObjectName(i); if(ObjectType(name) != OBJ_ARROW) continue; arrow_code = ObjectGet(name, OBJPROP_ARROWCODE); if(arrow_code != 242 && arrow_code != 241) continue; //--- if(arrow_code == 242) { price = NormalizeDouble(ObjectGet(name, OBJPROP_PRICE1), Digits); if(price < Bid - (MarketInfo(Symbol(), MODE_STOPLEVEL)*Point)) { sellstop_open(price, 0, 0); ObjectDelete(name); } if(price > Ask + (MarketInfo(Symbol(), MODE_STOPLEVEL)*Point)) { selllimit_open(price, 0, 0); ObjectDelete(name); } } //--- if(arrow_code == 241) { price = NormalizeDouble(ObjectGet(name, OBJPROP_PRICE1), Digits); //---- if(price > Ask + (MarketInfo(Symbol(), MODE_STOPLEVEL)*Point)) { buystop_open(price, 0, 0); ObjectDelete(name); } if(price < Bid - (MarketInfo(Symbol(), MODE_STOPLEVEL)*Point)) { buylimit_open(price, 0, 0); ObjectDelete(name); } } } //---- return; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void delete_pending_all() { bool result; int cmd, total; total = OrdersTotal(); //---- if(total == 0) return; //---- for(int i = total - 1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { cmd = OrderType(); //---- pending orders only are considered if(cmd != OP_BUY && cmd != OP_SELL) { //---- print selected order OrderPrint(); //---- delete first pending order result = OrderDelete(OrderTicket()); //---- if(result != TRUE) { Print("LastError = ", GetLastError()); break; } } } else { Print( "Error when order select ", GetLastError()); break; } } //---- return; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void selllimit_open( double price, double SL=0, double TP=0 ) { int ticket, expiration; //---- expiration = CurTime() + PERIOD_D1*60; //---- ticket = OrderSend(Symbol(), OP_SELLLIMIT, Lots, price, 0, SL, TP, "", MAGICEXP, expiration, Green); if(ticket <= 0) Print("Error = ", GetLastError()); else { Print("ticket = ", ticket); lastsd = CurTime(); } //---- return(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void sellstop_open( double price, double SL=0, double TP=0 ) { int ticket, expiration; //---- expiration = CurTime() + PERIOD_D1*60; //---- ticket = OrderSend(Symbol(), OP_SELLSTOP, Lots,price, 0, SL, TP, "", MAGICEXP, expiration, Green); if(ticket <= 0) Print("Error = ", GetLastError()); else { Print("ticket = ", ticket); lastsd = CurTime(); } //---- return(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void buylimit_open(double price, double SL = 0, double TP = 0) { int ticket,expiration; //---- expiration = CurTime() + PERIOD_D1*60; //---- ticket = OrderSend(Symbol(), OP_BUYLIMIT, Lots, price, 0, SL, TP, "", MAGICEXP, expiration, Green); if(ticket <= 0) Print("Error = ", GetLastError()); else { Print("ticket = ", ticket); lastsd = CurTime(); } //---- return(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void buystop_open(double price, double SL = 0, double TP = 0) { int ticket, expiration; //---- expiration = CurTime() + PERIOD_D1*60; //---- RefreshRates(); ticket = OrderSend(Symbol(), OP_BUYSTOP, Lots, price, 0, SL, TP, "", MAGICEXP, expiration,Green); if(ticket <= 0) Print("Error = ", GetLastError()); else { Print("ticket = ", ticket); lastsd = CurTime(); } //---- return(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void buy_open(double SL, double TP) { int ticket, lasterror; RefreshRates(); ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 5, SL, TP, 0, MAGICEXP, 0, Aqua); if(ticket > 0) { if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) Print("BUY order opened : ", OrderOpenPrice()); lastsd = CurTime(); } else Print("Error opening BUY order : ", ErrorDescription(GetLastError())); return; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void sell_open(double SL, double TP) { int ticket, lasterror; RefreshRates(); ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 5, SL, TP, 0, MAGICEXP, 0, Red); if(ticket > 0) { if(OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) Print("Sell order opened : ", OrderOpenPrice()); lastsd=CurTime(); } else Print("Error opening Sell order : ", ErrorDescription(GetLastError())); return; } //+------------------------------------------------------------------+ //| Закрытие ордеров n=1 - закрыть Buy, n=-1 - закрыть Sell | //+------------------------------------------------------------------+ void close_order(int n = 0) { int nGetLastError; int nOrdersTotal = OrdersTotal(); //---- for(int i = nOrdersTotal - 1; i >= 0; i--) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); nGetLastError = GetLastError(); //---- if(nGetLastError != 0) { Print("Error selecting order : ", ErrorDescription(nGetLastError)); continue; } //---- if(OrderMagicNumber() != MAGICEXP || OrderSymbol() != Symbol()) continue; //---- check order type if(OrderType() == OP_BUY && n == 1) { RefreshRates(); OrderClose(OrderTicket(), OrderLots(), Bid, 3, Aqua); nGetLastError = GetLastError(); if(nGetLastError != 0) Print("Error closing BUY order : ", ErrorDescription(nGetLastError)); } //---- if(OrderType() == OP_SELL && n==-1) { RefreshRates(); OrderClose(OrderTicket(), OrderLots(), Ask, 3, Yellow); nGetLastError = GetLastError(); if(nGetLastError != 0) Print("Error closing SELL order : ", ErrorDescription(nGetLastError)); } } } //+------------------------------------------------------------------+ //| Перенос уровня StopLoss "Copyright" © KimIV | //| Параметры: | //| ldStopLoss - уровень StopLoss | //| clModify - цвет модификации | //+------------------------------------------------------------------+ void ModifyStopLoss(double ldStop, color clModify = Magenta ) { bool fm; double ldOpen = OrderOpenPrice(); double ldTake = OrderTakeProfit(); int err; //---- if(IsTradeAllowed()) { fm = OrderModify(OrderTicket(), ldOpen, ldStop, ldTake, 0, clModify); if(!fm) { err = GetLastError(); Print("Error(",err,") modifying SL: ", ErrorDescription(err)); } } } //+------------------------------------------------------------------+ //| Перенос уровня TakeProfit | //| Параметры: | //| ldTake - уровень TakeProfit | //| clModify - цвет модификации | //+------------------------------------------------------------------+ void ModifyTakeProfit(double ldTake, color clModify = Magenta ) { bool fm; double ldOpen = OrderOpenPrice(); double ldStop = OrderStopLoss(); int err; //---- if(IsTradeAllowed()) { fm = OrderModify(OrderTicket(), ldOpen, ldStop, ldTake, 0, clModify); if(!fm) { err = GetLastError(); Print("Error(",err,") modifying SL: ", ErrorDescription(err)); } } } //+------------------------------------------------------------------+ //| Разбиение строки на массив элементов | //| Возврат: | //| Количество элементов в массиве | //| Параметры: | //| source - текстовая строка | //| dest - выходной массив | //| delimeter - разделитель | //+------------------------------------------------------------------+ int StrSplit(string source, string& dest[], string delimeter = ";") { int cnt = 0; int last_pos = 0; int pos = StringFind(source, delimeter, last_pos); //---- while(pos != -1) { ArrayResize(dest, cnt + 1); dest[cnt] = StringSubstr(source, last_pos, pos - last_pos); cnt++; last_pos = pos + 1; pos = StringFind(source, delimeter, last_pos); } if(last_pos != 0 && last_pos < StringLen(source)) { ArrayResize(dest, cnt + 1); dest[cnt] = StringSubstr(source, last_pos, StringLen(source) - last_pos); cnt++; } return (cnt); } //+------------------------------------------------------------------+