//+------------------------------------------------------------------+ //| OpenSellStopOrder.mq5 | //| Copyright © 2017, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2017, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- номер версии скрипта #property version "1.00" //---- показывать входные параметры #property script_show_inputs //+----------------------------------------------+ //| ВХОДНЫЕ ПАРАМЕТРЫ СКРИПТА | //+----------------------------------------------+ input double MM=0.1; // Money Management input int DEVIATION=10; // Отклонение цены input uint LEVEL=100; // Расстояние до ордера в пунктах input uint STOPLOSS=300; // Стоплосс в пунктах от текущей цены input uint TAKEPROFIT=800; // Тейкпрофит в пунктах от текущей цены input uint RTOTAL=4; // Число повторов при неудачных попытках размещения ордера input uint SLEEPTIME=1; // Время паузы между повторами в секундах //+------------------------------------------------------------------+ //| start function | //+------------------------------------------------------------------+ void OnStart() { //---- for(uint count=0; count<=RTOTAL && !IsStopped(); count++) { uint result=SellLimitOrderOpen(Symbol(),MM,DEVIATION,LEVEL,STOPLOSS,TAKEPROFIT); if(ResultRetcodeCheck(result)) break; else Sleep(SLEEPTIME*1000); } //---- } //+------------------------------------------------------------------+ //| Открываем Sell ордер. | //+------------------------------------------------------------------+ uint SellLimitOrderOpen ( const string symbol, double Money_Management, uint deviation, uint level, uint StopLoss, uint Takeprofit ) //SellPositionOpen(symbol, Money_Management, deviation, StopLoss, Takeprofit); //+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ { //---- double volume=SellLotCount(symbol,Money_Management); if(volume<=0) { Print(__FUNCTION__,"(): Неверный объём для структуры торгового запроса"); return(TRADE_RETCODE_INVALID_VOLUME); } //---- Объявление структур торгового запроса и результата торгового запроса MqlTradeRequest request; MqlTradeCheckResult check; MqlTradeResult result; //---- обнуление структур ZeroMemory(request); ZeroMemory(result); ZeroMemory(check); //---- int digit=int(SymbolInfoInteger(symbol,SYMBOL_DIGITS)); double point=SymbolInfoDouble(symbol,SYMBOL_POINT); double price=SymbolInfoDouble(symbol, SYMBOL_BID); if(!digit || !point || !price) return(TRADE_RETCODE_ERROR); price-=level*point; //---- Инициализация структуры торгового запроса MqlTradeRequest для открывания SELL ордера request.type = ORDER_TYPE_SELL_STOP; request.price = price; request.action = TRADE_ACTION_PENDING; request.symbol = symbol; request.volume = volume; //---- if(StopLoss) { //---- Определение расстояния до стоплосса в единицах ценового графика if(!StopCorrect(symbol,StopLoss)) return(TRADE_RETCODE_ERROR); double dStopLoss=StopLoss*point; request.sl=NormalizeDouble(request.price+dStopLoss,digit); } else request.sl=0.0; if(Takeprofit) { //---- Определение расстояния до тейкпрофита единицах ценового графика if(!StopCorrect(symbol,Takeprofit)) return(TRADE_RETCODE_ERROR); double dTakeprofit=Takeprofit*point; request.tp=NormalizeDouble(request.price-dTakeprofit,digit); } else request.tp=0.0; //---- request.deviation=deviation; request.type_filling=ORDER_FILLING_FOK; //---- Проверка торгового запроса на корректность if(!OrderCheck(request,check)) { Print(__FUNCTION__,"(): OrderCheck(): ",ResultRetcodeDescription(check.retcode)); return(TRADE_RETCODE_INVALID); } string word=""; StringConcatenate(word,__FUNCTION__,"(): <<< Выставляем Sell Stop ордер по ",symbol,"! >>>"); Print(word); word=__FUNCTION__+"(): OrderSend(): "; //---- Открываем SELL ордер и делаем проверку результата торгового запроса if(!OrderSend(request,result) || result.retcode!=TRADE_RETCODE_DONE) { Print(word,"<<< Не удалось выставить Sell Stop ордер по ",symbol,"!!! >>>"); Print(word,ResultRetcodeDescription(result.retcode)); PlaySound("timeout.wav"); return(result.retcode); } else if(result.retcode==TRADE_RETCODE_DONE) { Print(word,"<<< Sell Stop ордер по ",symbol," выставлен! >>>"); PlaySound("ok.wav"); } else { Print(word,"<<< Не удалось выставить Sell Stop ордер по ",symbol,"!!! >>>"); PlaySound("timeout.wav"); return(TRADE_RETCODE_ERROR); } //---- return(TRADE_RETCODE_DONE); } //+------------------------------------------------------------------+ //| Расчёт размера лота для открывания лонга | //+------------------------------------------------------------------+ double SellLotCount ( string symbol, double Money_Management ) // (string symbol, double Money_Management) //+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ { //---- double margin,Lot; //---- Расчёт лота от баланса средств на счёте margin=AccountInfoDouble(ACCOUNT_BALANCE)*Money_Management; if(!margin) return(-1); Lot=GetLotForOpeningPos(symbol,POSITION_TYPE_SELL,margin); //---- нормирование величины лота до ближайшего стандартного значения if(!LotCorrect(symbol,Lot,POSITION_TYPE_SELL)) return(-1); //---- return(Lot); } //+------------------------------------------------------------------+ //| коррекция размера отложенного ордера до допустимого значения | //+------------------------------------------------------------------+ bool StopCorrect(string symbol,int &Stop) { //---- long Extrem_Stop; if(!SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL,Extrem_Stop)) return(false); if(StopMaxLot) Lot=MaxLot; //---- проверка средств на достаточность if(!LotFreeMarginCorrect(symbol,Lot,trade_operation))return(false); //---- return(true); } //+------------------------------------------------------------------+ //| LotFreeMarginCorrect() function | //+------------------------------------------------------------------+ bool LotFreeMarginCorrect ( string symbol, double &Lot, ENUM_POSITION_TYPE trade_operation ) //(string symbol, double& Lot, ENUM_POSITION_TYPE trade_operation) //+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ { //---- //---- проверка средств на достаточность double freemargin=AccountInfoDouble(ACCOUNT_FREEMARGIN); if(freemargin<=0) return(false); double LOTSTEP=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP); double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN); if(!LOTSTEP || !MinLot) return(0); double maxLot=GetLotForOpeningPos(symbol,trade_operation,freemargin); //---- нормирование величины лота до ближайшего стандартного значения maxLot=LOTSTEP*MathFloor(maxLot/LOTSTEP); if(maxLotmaxLot) Lot=maxLot; //---- return(true); } //+------------------------------------------------------------------+ //| расчёт размер лота для открывания ордера с маржой lot_margin | //+------------------------------------------------------------------+ double GetLotForOpeningPos(string symbol,ENUM_POSITION_TYPE direction,double lot_margin) { //---- double price=0.0,n_margin; if(direction==POSITION_TYPE_SELL) price=SymbolInfoDouble(symbol,SYMBOL_ASK); if(direction==POSITION_TYPE_SELL) price=SymbolInfoDouble(symbol,SYMBOL_BID); if(!price) return(NULL); if(!OrderCalcMargin(ENUM_ORDER_TYPE(direction),symbol,1,price,n_margin) || !n_margin) return(0); double lot=lot_margin/n_margin; //---- получение торговых констант double LOTSTEP=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP); double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX); double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN); if(!LOTSTEP || !MaxLot || !MinLot) return(0); //---- нормирование величины лота до ближайшего стандартного значения lot=LOTSTEP*MathFloor(lot/LOTSTEP); //---- проверка лота на минимальное допустимое значение if(lotMaxLot) lot=MaxLot; //---- return(lot); } //+------------------------------------------------------------------+ //| возврат стрингового результата торговой операции по его коду | //+------------------------------------------------------------------+ string ResultRetcodeDescription(int retcode) { string str; //---- switch(retcode) { case TRADE_RETCODE_REQUOTE: str="Реквота"; break; case TRADE_RETCODE_REJECT: str="Запрос отвергнут"; break; case TRADE_RETCODE_CANCEL: str="Запрос отменен трейдером"; break; case TRADE_RETCODE_PLACED: str="Ордер размещен"; break; case TRADE_RETCODE_DONE: str="Заявка выполнена"; break; case TRADE_RETCODE_DONE_PARTIAL: str="Заявка выполнена частично"; break; case TRADE_RETCODE_ERROR: str="Ошибка обработки запроса"; break; case TRADE_RETCODE_TIMEOUT: str="Запрос отменен по истечению времени";break; case TRADE_RETCODE_INVALID: str="Неправильный запрос"; break; case TRADE_RETCODE_INVALID_VOLUME: str="Неправильный объем в запросе"; break; case TRADE_RETCODE_INVALID_PRICE: str="Неправильная цена в запросе"; break; case TRADE_RETCODE_INVALID_STOPS: str="Неправильные стопы в запросе"; break; case TRADE_RETCODE_TRADE_DISABLED: str="Торговля запрещена"; break; case TRADE_RETCODE_MARKET_CLOSED: str="Рынок закрыт"; break; case TRADE_RETCODE_NO_MONEY: str="Нет достаточных денежных средств для выполнения запроса"; break; case TRADE_RETCODE_PRICE_CHANGED: str="Цены изменились"; break; case TRADE_RETCODE_PRICE_OFF: str="Отсутствуют котировки для обработки запроса"; break; case TRADE_RETCODE_INVALID_EXPIRATION: str="Неверная дата истечения ордера в запросе"; break; case TRADE_RETCODE_ORDER_CHANGED: str="Состояние ордера изменилось"; break; case TRADE_RETCODE_TOO_MANY_REQUESTS: str="Слишком частые запросы"; break; case TRADE_RETCODE_NO_CHANGES: str="В запросе нет изменений"; break; case TRADE_RETCODE_SERVER_DISABLES_AT: str="Автотрейдинг запрещен сервером"; break; case TRADE_RETCODE_CLIENT_DISABLES_AT: str="Автотрейдинг запрещен клиентским терминалом"; break; case TRADE_RETCODE_LOCKED: str="Запрос заблокирован для обработки"; break; case TRADE_RETCODE_FROZEN: str="Ордер или позиция заморожены"; break; case TRADE_RETCODE_INVALID_FILL: str="Указан неподдерживаемый тип исполнения ордера по остатку "; break; case TRADE_RETCODE_CONNECTION: str="Нет соединения с торговым сервером"; break; case TRADE_RETCODE_ONLY_REAL: str="Операция разрешена только для реальных счетов"; break; case TRADE_RETCODE_LIMIT_ORDERS: str="Достигнут лимит на количество отложенных ордеров"; break; case TRADE_RETCODE_LIMIT_VOLUME: str="Достигнут лимит на объем ордеров и позиций для данного символа"; break; default: str="Неизвестный результат"; } //---- return(str); } //+------------------------------------------------------------------+ //| возврат результата торговой операции для повтора сделки | //+------------------------------------------------------------------+ bool ResultRetcodeCheck(int retcode) { string str; //---- switch(retcode) { case TRADE_RETCODE_REQUOTE: /*Реквота*/ return(false); break; case TRADE_RETCODE_REJECT: /*Запрос отвергнут*/ return(false); break; case TRADE_RETCODE_CANCEL: /*Запрос отменен трейдером*/ return(true); break; case TRADE_RETCODE_PLACED: /*Ордер размещен*/ return(true); break; case TRADE_RETCODE_DONE: /*Заявка выполнена*/ return(true); break; case TRADE_RETCODE_DONE_PARTIAL: /*Заявка выполнена частично*/ return(true); break; case TRADE_RETCODE_ERROR: /*Ошибка обработки запроса*/ return(false); break; case TRADE_RETCODE_TIMEOUT: /*Запрос отменен по истечению времени*/ return(false); break; case TRADE_RETCODE_INVALID: /*Неправильный запрос*/ return(true); break; case TRADE_RETCODE_INVALID_VOLUME: /*Неправильный объем в запросе*/ return(true); break; case TRADE_RETCODE_INVALID_PRICE: /*Неправильная цена в запросе*/ return(true); break; case TRADE_RETCODE_INVALID_STOPS: /*Неправильные стопы в запросе*/ return(true); break; case TRADE_RETCODE_TRADE_DISABLED: /*Торговля запрещена*/ return(true); break; case TRADE_RETCODE_MARKET_CLOSED: /*Рынок закрыт*/ return(true); break; case TRADE_RETCODE_NO_MONEY: /*Нет достаточных денежных средств для выполнения запроса*/ return(true); break; case TRADE_RETCODE_PRICE_CHANGED: /*Цены изменились*/ return(false); break; case TRADE_RETCODE_PRICE_OFF: /*Отсутствуют котировки для обработки запроса*/ return(false); break; case TRADE_RETCODE_INVALID_EXPIRATION: /*Неверная дата истечения ордера в запросе*/ return(true); break; case TRADE_RETCODE_ORDER_CHANGED: /*Состояние ордера изменилось*/ return(true); break; case TRADE_RETCODE_TOO_MANY_REQUESTS: /*Слишком частые запросы*/ return(false); break; case TRADE_RETCODE_NO_CHANGES: /*В запросе нет изменений*/ return(false); break; case TRADE_RETCODE_SERVER_DISABLES_AT: /*Автотрейдинг запрещен сервером*/ return(true); break; case TRADE_RETCODE_CLIENT_DISABLES_AT: /*Автотрейдинг запрещен клиентским терминалом*/ return(true); break; case TRADE_RETCODE_LOCKED: /*Запрос заблокирован для обработки*/ return(true); break; case TRADE_RETCODE_FROZEN: /*Ордер или позиция заморожены*/ return(false); break; case TRADE_RETCODE_INVALID_FILL: /*Указан неподдерживаемый тип исполнения ордера по остатку */ return(true); break; case TRADE_RETCODE_CONNECTION: /*Нет соединения с торговым сервером*/ break; case TRADE_RETCODE_ONLY_REAL: /*Операция разрешена только для реальных счетов*/ return(true); break; case TRADE_RETCODE_LIMIT_ORDERS: /*Достигнут лимит на количество отложенных ордеров*/ return(true); break; case TRADE_RETCODE_LIMIT_VOLUME: /*Достигнут лимит на объем ордеров и позиций для данного символа*/ return(true); break; default: /*Неизвестный результат*/ return(false); } //---- return(true); } //+------------------------------------------------------------------+