Код:
#property copyright "Copyright © HELLTEAM^Pirat" #property link "http://www.fxmania.ru" //+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ //+ //| 03/07/2011 ver. 3.8.5 Добавлено ограничение на открытие только одного ордера внутри свечи (в данном случае раз в 15 минут), см. функцию OneOrderInBar и параметр OneOrderInBarMode. //| Профиксен баг с постоянно выскакивающими сообщениями о превышении спреда, теперь сообщение будет появляться, только если при попытке открытия спред превышен. //| Добавлена правило, при котором может происходить открытие противоположных ордеров (например на парах USDCAD и USDCHF может открываться). Раньше можно было открывать только 1 //| ордер, либо длинный, либо короткий. Теперь при желании можно открываться в обе стороны. См. параметр No_Hedge_Trades. //| Добавлена дополнительная функция модификации (см. функцию ModifyOrder). //| //| 06/06/2011 ver. 3.8.4 Добавлено рыночное исполнение (см. параметр IsMarketExecution), то есть ордер открывается без sl и tp, а далее происходит модификация. //| Необходимо для NDD счетов. Также изменена функция открытия и закрытия ордеров, теперь при реквотах советник повторяет попытки открытия. Число попыток можно задать в //| параметре RequoteAttempts. //+ //+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ //| WallStreet Forex Robot ver. 3.8.5 FINAL (Pirate Edition) //| //| Рабочие пары EURUSD, GBPUSD, USDCHF, USDJPY, USDCAD. Таймфрейм M15. Для каждой пары необходимы свои настройки. //| По умолчанию эксперт настроен под торговлю на паре EURUSD M15. Для остальных пар подгружайте файлы настроек //| .set из папки sets. //| //| Для оптимизации используйте файл for_optimisation_wsfr_3.8.5_final.set. Оптимизацию можно проводить по //| контрольным точкам. Желательно оптимизировать на тиковых котировках (99% моделирование) по всем тикам. //| Среднее время оптимизации по всем тикам занимает 10 дней. По контрольным точкам 1 сутки. //| Рекомендуемый период оптимизации 1,5 года + 6 месяцев форвард. Оптимизацию необходимо проводить раз в квартал. //| Также можно смело торговать на паре EURUSD m15 на стандартных "заводских" настройках. //| //| Данные для связи: //| //| e-mail: fxmania.ru@gmail.com //| icq: 8-345-89-91 //| skype: fxmania.ru //+--------------------------------------------------------------------------------------------------------------+ //+--------------------------------------------------------------------------------------------------------------+ //| Основные входные параметры. Тейк-профит, стоп-лосс, вывод в безубыток и размер лота. //+--------------------------------------------------------------------------------------------------------------+ extern string Name = "WallStreet Forex Robot ver. 3.8.5 FINAL (Pirate Edition)"; extern string Copy = "Copyright © HELLTEAM^Pirat"; extern string Op2 = "Оптимизация для пары"; extern string Symbol_Op = "EURUSD m15"; extern string Op = "Дата оптимизации"; extern datetime Date = D'23.11.2011'; //--- Сделал чисто для себя, чтобы видеть от какой даты оптимизация (дата забивается вручную) extern string _TP = "Основные входные параметры"; //--- extern int TakeProfit = 26; //--- (10 2 60) extern int StopLoss = 120; //--- (100 10 200) extern bool UseStopLevels = TRUE; //--- Включение стоповых ордеров. Если выключена, то работают только виртуальные тейки и лоссы. extern bool IsMarketExecution = FALSE; //--- Включение рыночного исполнения открытия ордеров (сначало открывает, затем модифицирует) //--- extern int SecureProfit = 1; //--- (0 1 5) Вывод в безубыток extern int SecureProfitTriger = 10; //--- (10 2 30) extern int MaxLossPoints = -65; //--- (-200 5 -20) Максимальная просадка для закрытия ордеров Buy и Sell при изменении сигнала (При просадке равной от - MaxLossPoints или меньше (например прибыль 0), ордер закроется) extern string _MM = "Настройка MM"; //--- extern bool RecoveryMode = FALSE; //--- Включение режима восстановления депозита (увеличение лота если случился стоп-лосс) extern double FixedLot = 0.1; //--- Фиксированный объём лота extern double AutoMM = 0.0; //--- ММ включается если AutoMM > 0. Процент риска. При RecoveryMode = FALSE, менять нужно только это значение. //--- При AutoMM = 20 и депозите в 1000$, лот будет равен 0,2. Далее лот будет увеличиваться исходя из свободных средств, то есть уже при депозите в 2000$ лот будет равен 0,4. extern double AutoMM_Max = 20.0; //--- Максимальный риск extern int MaxAnalizCount = 50; //--- Число закрытых ранее ордеров для анализа(Используется при RecoveryMode = True) extern double Risk = 25.0; //--- Риск от депозита (Используется при RecoveryMode = True) extern double MultiLotPercent = 1.1; //--- Коэффициент умножение лота (Используется при RecoveryMode = True) //+--------------------------------------------------------------------------------------------------------------+ //| Периоды индикаторов. Кол-во баров для каждого индикатора. //+--------------------------------------------------------------------------------------------------------------+ extern string _Periods = "Периоды индикаторов"; //--- Периоды индикаторов (Тоже можно будет заоптить, так как для каждой пары свои) extern int iMA_Period = 75; //--- (60 5 100) extern int iCCI_Period = 18; //--- (10 2 30) extern int iATR_Period = 14; //--- (10 2 30) (!) Можно не оптить extern int iWPR_Period = 11; //--- (10 1 20) //+--------------------------------------------------------------------------------------------------------------+ //| Настройки из DLL //+--------------------------------------------------------------------------------------------------------------+ //| EURUSD | GBPUSD | USDCHF | USDJPY | USDCAD | //+---------------------------------------------------------------- //| TP=26; | TP=50; | TP=17; | TP=27; | TP=14; | //| SL=120; | SL=120; | SL=120; | SL=130; | SL=150; | //| SP=1; | SP=2; | SP=0; | SP=2; | SP=2; | //| SPT=10; | SPT=24; | SPT=15; | SPT=14; | SPT=10; | //| MLP=-65; | MLP=-200; | MLP=-40; | MLP=-80; | MLP=-30; | //+---------------------------------------------------------------- //| MA=75; | MA=75; | MA=70; | MA=85; | MA=65; | //| CCI=18; | CCI=12; | CCI=14; | CCI=12; | CCI=12; | //| ATR=14; | ATR=14; | ATR=14; | ATR=14; | ATR=14; | //| WPR=11; | WPR=12; | WPR=12; | WPR=12; | WPR=16; | //+---------------------------------------------------------------- //| FATR=6; | FATR=6; | FATR=3; | FATR=0; | FATR=4; | //| FCCI=150; | FCCI=290; | FCCI=170; | FCCI=2000; | FCCI=130; | //+---------------------------------------------------------------- //| MAFOA=15; | MAFOA=12; | MAFOA=8; | MAFOA=5; | MAFOA=5; | //| MAFOB=39; | MAFOB=33; | MAFOB=25; | MAFOB=21; | MAFOB=15; | //| WPRFOA=-99;| WPRFOA=-99;| WPRFOA=-95;| WPRFOA=-99;| WPRFOA=-99;| //| WPRFOB=-95;| WPRFOB=-94;| WPRFOB=-92;| WPRFOB=-95;| WPRFOB=-89;| //+---------------------------------------------------------------- //| MAFC=14; | MAFC=18; | MAFC=11; | MAFC=14; | MAFC=14; | //| WPRFC=-19; | WPRFC=-19; | WPRFC=-22; | WPRFC=-27; | WPRFC=-6; | //+--------------------------------------------------------------------------------------------------------------+ //+--------------------------------------------------------------------------------------------------------------+ //| Параметры оптимизации для правил открытия и закрытия позиции. //+--------------------------------------------------------------------------------------------------------------+ extern string _Add_Op = "Расширенные параметры оптимизации"; //--- extern string _AddOpenFilters = "---"; //--- extern int FilterATR = 6; //--- (0 1 10) Проверка на вход по ATR для Buy и Sell (if (iATR_Signal <= FilterATR * pp) return (0);) (!) Можно не оптить extern double iCCI_OpenFilter = 150; //--- (100 10 400) Фильтр по iCCI для Buy и Sell. При оптимизации под JPY рекомендуемо оптить по правилу (100 50 4000) //--- extern string _OpenOrderFilters = "---"; //--- extern int iMA_Filter_Open_a = 15; //--- (4 2 20) Фильтр МА для открытия Buy и Sell (Пунты) extern int iMA_Filter_Open_b = 39; //--- (14 2 50) Фильтр МА для открытия Buy и Sell (Пунты) extern int iWPR_Filter_Open_a = -99; //--- (-100 1 0) Фильтр WPR для открытия Buy и Sell extern int iWPR_Filter_Open_b = -95; //--- (-100 1 0) Фильтр WPR для открытия Buy и Sell //--- extern string _CloseOrderFilters = "---"; //--- extern int Price_Filter_Close = 14; //--- (10 2 20) Фильтр цены открытия для закрытия Buy и Sell (Пунты) extern int iWPR_Filter_Close = -19; //--- (0 1 -100) Фильтр WPR для закрытия Buy и Sell //+--------------------------------------------------------------------------------------------------------------+ //| Расширенные настройки //+--------------------------------------------------------------------------------------------------------------+ extern string _Add = "Расширенные настройки"; extern bool LongTrade = TRUE; //--- Выключатель длинных позиций extern bool ShortTrade = TRUE; //--- Выключатель коротких позиций extern bool No_Hedge_Trades = TRUE; //--- Одновременное открытие одного Buy и одного Sell ордера. При True не хеджирует. extern bool OneOrderInBarMode = TRUE; //--- При True советник будет открывать только 1 ордер в 1 свече. (В данном случае не более чем 1 раз в 15 минут). В тестере не работает, так как замедляет его в 10 раз. extern int MagicNumber = 2011; extern double MaxSpread = 5.0; extern double OpenSlippage = 2; //--- Проскальзывание для открытия ордера extern double CloseSlippage = 3; //--- Проскальзывание для закрытия ордера extern int RequoteAttempts = 3; //--- Максимальное число повторений при открытии/закрытии ордера при реквотах и других ошибках extern bool WriteLog = TRUE; //--- //--- Включение всплывающих окон в терминале. extern bool WriteDebugLog = TRUE; //--- Включение всплывающих окон об ошибках в терминале. extern bool PrintLogOnChart = TRUE; //--- Включение комментариев на графике (при тестировании выключается автоматически) //+--------------------------------------------------------------------------------------------------------------+ //| Блок дополнительных переменных //+--------------------------------------------------------------------------------------------------------------+ double pp; int pd; double cf; string EASymbol; //--- Текущий символ int SP; int CloseSP; int MaximumTrades = 1; double NDMaxSpread; //--- Максимальный спред ввиде пунктов bool CheckSpreadRuleBuy; //--- Правило для проверки спреда перед открытием (Останавливает зацикливание сообщений о превышенном спреде) bool CheckSpreadRuleSell; string OpenOrderComment = "WSFR v3.8.5 FINAL"; int RandomOpenTimePercent = 0; //--- Используется при занятом потоке комманд терминала, своебразная рендомная пауза. Выражается в секундах. //--- //--- Параметры для автолота double MinLot = 0.01; double MaxLot = 0.01; double LotStep = 0.01; int LotValue = 100000; double FreeMargin = 1000.0; double LotPrice = 1; double LotSize; //--- Параметры на открытие int iWPR_Filter_OpenLong_a; int iWPR_Filter_OpenLong_b; int iWPR_Filter_OpenShort_a; int iWPR_Filter_OpenShort_b; //--- Параметры на закрытие int iWPR_Filter_CloseLong; int iWPR_Filter_CloseShort; //--- color OpenBuyColor = Blue; color OpenSellColor = Red; color CloseBuyColor = DodgerBlue; color CloseSellColor = DeepPink; //+--------------------------------------------------------------------------------------------------------------+ //| INIT. Инициализация некоторых переменных, удаление объектов на графике. //+--------------------------------------------------------------------------------------------------------------+ void init() { //+--------------------------------------------------------------------------------------------------------------+ //--- if (IsTesting() && !IsVisualMode()) {PrintLogOnChart = FALSE; OneOrderInBarMode = FALSE;} //--- Если тестируем, то отключаются комментарии на графике и функция OneOrderInBarMode if (!PrintLogOnChart) Comment(""); //--- EASymbol = Symbol(); //--- Инициализация текущено символа //--- if (Digits < 4) { pp = 0.01; pd = 2; cf = 0.009; } else { pp = 0.0001; pd = 4; cf = 0.00009; } //--- SP = OpenSlippage * MathPow(10, Digits - pd); //--- Расчет проскальзывания цены для пятизнака CloseSP = CloseSlippage * MathPow(10, Digits - pd); NDMaxSpread = NormalizeDouble(MaxSpread * pp, pd + 1); //--- Преобразование значения MaxSpread в пункты //--- if (ObjectFind("BKGR") >= 0) ObjectDelete("BKGR"); if (ObjectFind("BKGR2") >= 0) ObjectDelete("BKGR2"); if (ObjectFind("BKGR3") >= 0) ObjectDelete("BKGR3"); if (ObjectFind("BKGR4") >= 0) ObjectDelete("BKGR4"); if (ObjectFind("LV") >= 0) ObjectDelete("LV"); //--- //--- Инициализация параметров для MM MinLot = MarketInfo(Symbol(), MODE_MINLOT); MaxLot = MarketInfo(Symbol(), MODE_MAXLOT); LotValue = MarketInfo(Symbol(), MODE_LOTSIZE); LotStep = MarketInfo(Symbol(), MODE_LOTSTEP); FreeMargin = MarketInfo(Symbol(), MODE_MARGINREQUIRED); //--- Получение значения стоимости лота конкретного символа исходя из парамтеров вашего брокера. double SymbolBid = 0; if (StringSubstr(AccountCurrency(), 0, 3) == "JPY") { SymbolBid = MarketInfo("USDJPY" + StringSubstr(Symbol(), 6), MODE_BID); if (SymbolBid > 0.1) LotPrice = SymbolBid; else LotPrice = 84; } //--- if (StringSubstr(AccountCurrency(), 0, 3) == "GBP") { SymbolBid = MarketInfo("GBPUSD" + StringSubstr(Symbol(), 6), MODE_BID); if (SymbolBid > 0.1) LotPrice = 1 / SymbolBid; else LotPrice = 0.6211180124; } //--- if (StringSubstr(AccountCurrency(), 0, 3) == "EUR") { SymbolBid = MarketInfo("EURUSD" + StringSubstr(Symbol(), 6), MODE_BID); if (SymbolBid > 0.1) LotPrice = 1 / SymbolBid; else LotPrice = 0.7042253521; } //--- Параметры на открытие iWPR_Filter_OpenLong_a = iWPR_Filter_Open_a; iWPR_Filter_OpenLong_b = iWPR_Filter_Open_b; iWPR_Filter_OpenShort_a = -100 - iWPR_Filter_Open_a; iWPR_Filter_OpenShort_b = -100 - iWPR_Filter_Open_b; //--- Параметры на закрытие iWPR_Filter_CloseLong = iWPR_Filter_Close; iWPR_Filter_CloseShort = -100 - iWPR_Filter_Close; //--- return (0); } //+--------------------------------------------------------------------------------------------------------------+ //| DEINIT. Удаление объектов на графике. //+--------------------------------------------------------------------------------------------------------------+ int deinit() { //+--------------------------------------------------------------------------------------------------------------+ if (ObjectFind("BKGR") >= 0) ObjectDelete("BKGR"); if (ObjectFind("BKGR2") >= 0) ObjectDelete("BKGR2"); if (ObjectFind("BKGR3") >= 0) ObjectDelete("BKGR3"); if (ObjectFind("BKGR4") >= 0) ObjectDelete("BKGR4"); if (ObjectFind("LV") >= 0) ObjectDelete("LV"); //--- return (0); } //+--------------------------------------------------------------------------------------------------------------+ //| START. Проверка на ошибки, а также старт функции Scalper. //+--------------------------------------------------------------------------------------------------------------+ int start() { //+--------------------------------------------------------------------------------------------------------------+ if (PrintLogOnChart) ShowComments (); //--- Включение комментариев на графике //--- CloseOrders(); //--- Сопровождение ордеров ModifyOrders(); //--- Вывод в безубыток //--- Инициализация объёма сдеки //if (AutoMM > 0.0 && (!RecoveryMode)) LotSize = MathMax(MinLot, MathMin(MaxLot, MathCeil(MathMin(AutoMM_Max, AutoMM) / LotPrice / 100.0 * AccountFreeMargin() / LotStep / (LotValue / 100)) * LotStep)); //*** if (AutoMM > 0.0 && (!RecoveryMode)) LotSize = NormalizeDouble(MathFloor( AccountFreeMargin() * (AutoMM * (100.0 / AccountLeverage())) / 100.0 ) * LotStep, Digits); if (LotSize < MinLot) LotSize = MinLot; if (LotSize > MaxLot) LotSize = MaxLot; //*** if (AutoMM > 0.0 && RecoveryMode) LotSize = CalcLots(); //--- Если включен RecoveryMode используем CalcLots if (AutoMM == 0.0) LotSize = FixedLot; //--- Проверка наличия исторических данных для таймфрейма M15 if(iBars(Symbol(), PERIOD_M15) < iMA_Period || iBars(Symbol(), PERIOD_M15) < iWPR_Period || iBars(Symbol(), PERIOD_M15) < iATR_Period || iBars(Symbol(), PERIOD_M15) < iCCI_Period) { Print("Недостаточно исторических данных для торговли"); return; } //--- if (DayOfWeek() == 1 && iVolume(NULL, PERIOD_D1, 0) < 5.0) return (0); if (StringLen(EASymbol) < 6) return (0); //--- if ((!IsTesting()) && IsStopped()) return (0); if ((!IsTesting()) && !IsTradeAllowed()) return (0); if ((!IsTesting()) && IsTradeContextBusy()) return (0); //--- HideTestIndicators(TRUE); //--- Scalper(); //--- return (0); } //+--------------------------------------------------------------------------------------------------------------+ //| Scalper. Основная функция. Сначало производится проверка спреда, далее проверка сигналов на вход. //+--------------------------------------------------------------------------------------------------------------+ void Scalper() { //+--------------------------------------------------------------------------------------------------------------+ bool OpenBuyRule = TRUE; bool OpenSellRule = TRUE; //--- Правило для открытия противоположных ордеров. if (No_Hedge_Trades == TRUE && CheckOpenTrade(OP_SELL)) OpenBuyRule = FALSE; if (No_Hedge_Trades == TRUE && CheckOpenTrade(OP_BUY)) OpenSellRule = FALSE; //--- Проверка на открытие длинного ордера if (OpenLongSignal() && !CheckOpenTrade(OP_BUY) && OpenBuyRule && OneOrderInBar(OP_BUY) && LongTrade) { //--- Сообщение о превышенном спреде if (MaxSpreadFilter()) { if (!CheckSpreadRuleBuy && WriteDebugLog) { //--- Print("Торговый сигнал на покупку пропущен из-за большого спреда."); Print("Текущий спред = ", DoubleToStr((Ask - Bid) / pp, 1), ", MaxSpread = ", DoubleToStr(MaxSpread, 1)); Print("Эксперт WSFR 3.8.5 будет пробовать позже, когда спред станет допустимым."); } //--- CheckSpreadRuleBuy = TRUE; //--- } else { //--- CheckSpreadRuleBuy = FALSE; OpenPosition(OP_BUY);} }//--- Закрытие if (OpenLongSignal() //--- Проверка на открытие короткого ордера if (OpenShortSignal() && !CheckOpenTrade(OP_SELL) && OpenSellRule && OneOrderInBar(OP_SELL) && ShortTrade) { //--- Сообщение о превышенном спреде if (MaxSpreadFilter()) { if (!CheckSpreadRuleSell && WriteDebugLog) { //--- Print("Торговый сигнал на продажу пропущен из-за большого спреда."); Print("Текущий спред = ", DoubleToStr((Ask - Bid) / pp, 1), ", MaxSpread = ", DoubleToStr(MaxSpread, 1)); Print("Эксперт WSFR 3.8.5 будет пробовать позже, когда спред станет допустимым."); } //--- CheckSpreadRuleSell = TRUE; //--- } else { //--- CheckSpreadRuleSell = FALSE; OpenPosition(OP_SELL);} } //--- Закрытие if (OpenShortSignal() } //+--------------------------------------------------------------------------------------------------------------+ //| OpenPosition. Функция открытия позиции. //+--------------------------------------------------------------------------------------------------------------+ int OpenPosition(int OpType) { //+--------------------------------------------------------------------------------------------------------------+ int RandomOpenTime; //--- Задержка по времени на открытие color OpenColor; //--- Цвет открытия позиции. Если Buy то голубая, если Sell то красная int OpenOrder = 0; //--- Открытие позиции int OpenOrderError; //--- Ошибка открытия string OpTypeString; //--- Преобразования вида позиции в текстовое значение double OpenPrice; //--- Цена открытия int maxtry = RequoteAttempts; int lasterror = 0; double price = 0; //--- double TP, SL; double OrderTP = NormalizeDouble (TakeProfit * pp , pd); //--- Преобразуем тейк-профит в вид Points double OrderSL = NormalizeDouble (StopLoss * pp , pd); //--- Преобразуем стоп-лосс в вид Points //--- Задержка в секундах между открытиями if (RandomOpenTimePercent > 0) { MathSrand(TimeLocal()); RandomOpenTime = MathRand() % RandomOpenTimePercent; if (WriteLog) { Print("DelayRandomiser: задержка ", RandomOpenTime, " секунд."); } Sleep(1000 * RandomOpenTime); } //--- Закрытие if (RandomOpenTimePerc double OpenLotSize = LotSize; //--- Расчет объёма позиции //--- Если не хватет средств, возвращаем ошибку if (AccountFreeMarginCheck(EASymbol, OpType, OpenLotSize) <= 0.0 || GetLastError() == 134/* NOT_ENOUGH_MONEY */) { //--- if (WriteDebugLog) { //--- Print("Для открытия ордера недостаточно свободной маржи."); Comment("Для открытия ордера недостаточно свободной маржи."); //--- } return (-1); } //--- Закрытие if (AccountFreeMarginCheck RefreshRates(); //--- Если длинная позиция, то if (OpType == OP_BUY) { OpenPrice = NormalizeDouble(Ask, Digits); OpenColor = OpenBuyColor; //--- if (UseStopLevels) { //--- Если включены стоп-уровни (стоп-лосс и тейк-профит) TP = NormalizeDouble(OpenPrice + OrderTP, Digits); //--- То расчитывает тейк-профит SL = NormalizeDouble(OpenPrice - OrderSL, Digits); //--- и стоп-лосс //--- } else {TP = 0; SL = 0;} //--- Если короткая позиция, то } else { OpenPrice = NormalizeDouble(Bid, Digits); OpenColor = OpenSellColor; //--- if (UseStopLevels) { TP = NormalizeDouble(OpenPrice - OrderTP, Digits); SL = NormalizeDouble(OpenPrice + OrderSL, Digits); } //--- else {TP = 0; SL = 0;} } //--- Если тип исполнения Market Execution (рыночное исполнение), то сначало открываем ордер без sl и tp, а после модифицируем его if (IsMarketExecution && UseStopLevels) { OpenOrder = OrderSend(EASymbol, OpType, OpenLotSize, OpenPrice, SP, 0, 0, OpenOrderComment, MagicNumber, 0, OpenColor); if (OpenOrder > 0) { ModifyOrder(EASymbol, OpenOrder, OrderOpenPrice(), SL, TP, 0); return(OpenOrder); } } //--- Если же нет, то сразу открываем с sl и tp else { OpenOrder = OrderSend(EASymbol, OpType, OpenLotSize, OpenPrice, SP, SL, TP, OpenOrderComment, MagicNumber, 0, OpenColor); if (OpenOrder > 0) return(OpenOrder); } //--- Если тип ордера не верен, то повторяем операцию. if ((OpType != OP_BUY) && (OpType != OP_SELL)) return(OpenOrder); //--- Если ордер открылся успешно, то отправляем сообщение на e-mail (если включена отправка) if (OpenOrder < 0) { //--- Если ордер не открылся, то OpenOrderError = GetLastError(); //--- Возвращаем ошибку //--- if (WriteDebugLog) { if (OpType == OP_BUY) OpTypeString = "OP_BUY"; else OpTypeString = "OP_SELL"; Print("Открытие: OrderSend(", OpTypeString, ") ошибка = ", ErrorDescription(OpenOrderError)); //--- Код ошибки на Русском } //--- Закрытие if (WriteDebugLog) } //--- При реквотах повторяем операцию. lasterror = GetLastError(); if ((OpenOrder < 0) && ((lasterror == 135) || (lasterror == 138) || (lasterror == 146))) { Print("Requote. Error" + lasterror + ". Ticket: " + OpenOrder); } else { return(OpenOrder); } //--- Цикл открытия ордера при возникновении ошибок (Максимальное число попыток открытия при возникновении ошибок равно значению RequoteAttempts) price = OpenPrice; for (int attempt = 1; attempt <= maxtry; attempt++) { RefreshRates(); if (OpType == OP_BUY) { if (Ask <= price) { if (IsMarketExecution && UseStopLevels) { OpenOrder = OrderSend(EASymbol, OpType, OpenLotSize, NormalizeDouble(Ask,Digits), SP, 0, 0, OpenOrderComment, MagicNumber, 0, OpenColor); if (OpenOrder > 0) { ModifyOrder(EASymbol, OpenOrder, OrderOpenPrice(), SL, TP, 0); return(OpenOrder); } } else { OpenOrder = OrderSend(EASymbol, OpType, OpenLotSize, NormalizeDouble(Ask,Digits), SP, SL, TP, OpenOrderComment, MagicNumber, 0, OpenColor); if (OpenOrder > 0) return(OpenOrder); } if ((GetLastError() != 135) && (GetLastError() != 138) && (GetLastError() != 146)) return(OpenOrder); Print("Requote. " + "Attempt " + (attempt + 1)); continue; } } if (OpType == OP_SELL) { if (Bid >= price) { if (IsMarketExecution && UseStopLevels) { OpenOrder = OrderSend(EASymbol, OpType, OpenLotSize, NormalizeDouble(Bid,Digits), SP, 0, 0, OpenOrderComment, MagicNumber, 0, OpenColor); if (OpenOrder > 0) { ModifyOrder(EASymbol, OpenOrder, OrderOpenPrice(), SL, TP, 0); return(OpenOrder); } } else { OpenOrder = OrderSend(EASymbol, OpType, OpenLotSize, NormalizeDouble(Bid,Digits), SP, SL, TP, OpenOrderComment, MagicNumber, 0, OpenColor); if (OpenOrder > 0) return(OpenOrder); } if ((GetLastError() != 135) && (GetLastError() != 138) && (GetLastError() != 146)) return(OpenOrder); Print("Requote. " + "Attempt " + (OpenOrder + 1)); } } } //--- return(-1); } //+--------------------------------------------------------------------------------------------------------------+ //| ModifyOrders. Модификация ордеров в безубыток. //+--------------------------------------------------------------------------------------------------------------+ void ModifyOrders() { //+--------------------------------------------------------------------------------------------------------------+ int total = OrdersTotal() - 1; int ModifyError = GetLastError(); //--- for (int i = total; i >= 0; i--) { //--- Счетчик открытых ордеров if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if (WriteDebugLog) Print("Произошла ошибка во время выборки ордера. Причина: ", ErrorDescription(ModifyError)); } else { //--- Модификация ордера на покупку if (OrderType() == OP_BUY) { if (OrderMagicNumber() == MagicNumber && OrderSymbol() == EASymbol) { if (Bid - OrderOpenPrice() > SecureProfitTriger * pp && MathAbs(OrderOpenPrice() + SecureProfit * pp - OrderStopLoss()) >= Point) { //--- Модифицируем ордер ModifyOrder(EASymbol, OrderTicket(), OrderOpenPrice(), NormalizeDouble(OrderOpenPrice() + SecureProfit * pp, Digits), OrderTakeProfit(), Blue); } } } //--- Закрытие if (OrderType() == OP_BUY) //--- Модификация ордера на продажу if (OrderType() == OP_SELL) { if (OrderMagicNumber() == MagicNumber && OrderSymbol() == EASymbol) { if (OrderOpenPrice() - Ask > SecureProfitTriger * pp && MathAbs(OrderOpenPrice() - SecureProfit * pp - OrderStopLoss()) >= Point) { //--- Модифицируем ордер ModifyOrder(EASymbol, OrderTicket(), OrderOpenPrice(), NormalizeDouble(OrderOpenPrice() - SecureProfit * pp, Digits), OrderTakeProfit(), Red); } } } //--- Закрытие if (OrderType() == OP_SELL) } } //--- Закрытие for (int i = total - 1; i >= 0; i--) } //+--------------------------------------------------------------------------------------------------------------+ //| ModifyOrder. Модификация предварительно выбранного ордера. //| //| Параметры: //| sy - наименование инструмента ("" - текущий символ) //| ticket - заранее выбранный ордер //| pp - цена открытия позиции, установки ордера //| sl - ценовой уровень стопа //| tp - ценовой уровень тейка //| cl - цвет //+--------------------------------------------------------------------------------------------------------------+ void ModifyOrder(string sy="", int ticket=0, double pp=-1, double sl=0, double tp=0, color cl=CLR_NONE) { //+--------------------------------------------------------------------------------------------------------------+ int ModifyTicketID = OrderTicket(); if (sy=="") sy=Symbol(); bool fm; //--- Модификация ордера int dg, err, it; int PauseAfterError = 5; //--- Пауза в секундах между попытками модификаций int NumberOfTry = 10; //--- Кол-во попыток модификаций при возникновении ошибок //--- Проверка на ошибки переменных if (pp<=0) pp=OrderOpenPrice(); if (sl<0) sl=OrderStopLoss(); if (tp<0) tp=OrderTakeProfit(); //--- Инициализация параметров dg=MarketInfo(sy, MODE_DIGITS); pp=NormalizeDouble(pp, dg); sl=NormalizeDouble(sl, dg); tp=NormalizeDouble(tp, dg); //--- Дополнительная проверка на ошибки переменных, после которой if (pp!=OrderOpenPrice() || sl!=OrderStopLoss() || tp!=OrderTakeProfit()) { //--- Начинаем цикл попыток модификаций for (it=1; it<=NumberOfTry; it++) { if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) break; while (!IsTradeAllowed()) Sleep(5000); RefreshRates(); //--- Модифицируем ордер fm = OrderModify(ticket, pp, sl, tp, 0, cl); if (fm==1) return(1); //--- Если произошла ошибка, то else { err=GetLastError(); //--- Выдаём ошибку, если включено отображение ошибок if (WriteDebugLog) Print("Произошла ошибка во время модификации ордера (", GetNameOP(OrderType()), ",", ModifyTicketID, "). Причина: ", ErrorDescription(err),". Попытка №",it); //--- Ждём PauseAfterError секунд, после чего повторяем попытку модификаций Sleep(1000*PauseAfterError); } //--- Закрытие if (!fm) { } } } //+--------------------------------------------------------------------------------------------------------------+ //| CloseTrades. Виртуальный тейк-профит и стоп-лосс. //| Если включена функция UseStopLevels, то используется как функция резервного закрытия. //+--------------------------------------------------------------------------------------------------------------+ void CloseOrders() { //+--------------------------------------------------------------------------------------------------------------+ int total = OrdersTotal() - 1; int SelectCloseError = GetLastError(); //--- for (int i = total; i >= 0; i--) { //--- Счетчик открытых ордеров if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if (WriteDebugLog) Print("Произошла ошибка во время выборки ордера. Причина: ", ErrorDescription(SelectCloseError)); } else { //--- Закрытие по профиту или лоссу ордеров на покупку if (OrderType() == OP_BUY) { if (OrderMagicNumber() == MagicNumber && OrderSymbol() == EASymbol) { if (Bid >= OrderOpenPrice() + TakeProfit * pp || Bid <= OrderOpenPrice() - StopLoss * pp || CloseLongSignal(OrderOpenPrice(), ExistPosition())) { //--- CloseOrder(OrderTicket(),Bid); //--- } } } //--- Закрытие if (OrderType() == OP_BUY) //--- Закрытие по профиту или лоссу ордеров на продажу if (OrderType() == OP_SELL) { if (OrderMagicNumber() == MagicNumber && OrderSymbol() == EASymbol) { if (Ask <= OrderOpenPrice() - TakeProfit * pp || Ask >= OrderOpenPrice() + StopLoss * pp || CloseShortSignal(OrderOpenPrice(), ExistPosition())) { //--- CloseOrder(OrderTicket(),Ask); //--- } } } //--- Закрытие if (OrderType() == OP_SELL) } } //--- Закрытие for (int i = total - 1; i >= 0; i--) { } //+--------------------------------------------------------------------------------------------------------------+ //| CloseOrder. Функция закрытия ордера. //+--------------------------------------------------------------------------------------------------------------+ int CloseOrder(int ticket, double prce) { //+--------------------------------------------------------------------------------------------------------------+ //--- Инициализация переменных необходимых для повтора открытия при реквотах или простых ошибках. double price; int slippage; double p = prce; int maxtry = RequoteAttempts; color CloseColor; OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES); int ordtype = OrderType(); if (ordtype == OP_BUY) {price = NormalizeDouble(Bid,Digits); CloseColor = CloseBuyColor;} if (ordtype == OP_SELL) {price = NormalizeDouble(Ask,Digits); CloseColor = CloseSellColor;} if (MathAbs(OrderTakeProfit() - price) <= MarketInfo(Symbol(),MODE_FREEZELEVEL) * Point) return(0); //--- Проверка уровней заморозки тейк-профита if (MathAbs(OrderStopLoss() - price) <= MarketInfo(Symbol(),MODE_FREEZELEVEL) * Point) return(0); //--- Проверка уровней заморозки стоп-лосса if (OrderClose(ticket,OrderLots(),price,CloseSlippage,CloseColor)) return(1); //--- Если ордер открыт успешно, то возвращаем 1) if ((GetLastError() != 135) && (GetLastError() != 138) && (GetLastError() != 146)) return(0); //--- Если нет то 0 Print("Requote"); //--- Цикл закрытия ордера при возникновении ошибок (Максимальное число попыток открытия при возникновении ошибок равно значению RequoteAttempts) for (int attempt = 1; attempt <= maxtry; attempt++) { RefreshRates(); if (ordtype == OP_BUY) { slippage = MathRound((Bid - p) / pp); if (Bid >= p) { Print("Closing order. Attempt " + (attempt + 1)); if (OrderClose(ticket,OrderLots(),NormalizeDouble(Bid,Digits),slippage,CloseColor)) return(1); if (!((GetLastError() != 135) && (GetLastError() != 138) && (GetLastError() != 146))) continue; return(0); } } if (ordtype == OP_SELL) { slippage = MathRound((p - Ask) / pp); if (p >= Ask) { Print("Closing order. Attempt " + (attempt + 1)); if (OrderClose(ticket,OrderLots(),NormalizeDouble(Ask,Digits),slippage,CloseColor)) return(1); if ((GetLastError() != 135) && (GetLastError() != 138) && (GetLastError() != 146)) return(0); } } } } //+--------------------------------------------------------------------------------------------------------------+ //| OpenLongSignal. Сигнал на открытие длинной позиции. //+--------------------------------------------------------------------------------------------------------------+ bool OpenLongSignal() { //+--------------------------------------------------------------------------------------------------------------+ bool result = false; bool result1 = false; bool result2 = false; bool result3 = false; //--- Расчет основных сигналов на вход double iClose_Signal = iClose(NULL, PERIOD_M15, 1); double iMA_Signal = iMA(NULL, PERIOD_M15, iMA_Period, 0, MODE_SMMA, PRICE_CLOSE, 1); double iWPR_Signal = iWPR(NULL, PERIOD_M15, iWPR_Period, 1); double iATR_Signal = iATR(NULL, PERIOD_M15, iATR_Period, 1); double iCCI_Signal = iCCI(NULL, PERIOD_M15, iCCI_Period, PRICE_TYPICAL, 1); //--- double iMA_Filter_a = NormalizeDouble(iMA_Filter_Open_a*pp,pd); double iMA_Filter_b = NormalizeDouble(iMA_Filter_Open_b*pp,pd); double BidPrice = Bid; //--- (iClose_Signal >= BidPrice) Сравнение идёт именно с Bid (а не с Ask, как должно быть), так как цена закрытия свечи iClose_Signal формируется на основании значения Bid //--- //--- Сверяем сигнал по АТР с его фильтром if (iATR_Signal <= FilterATR * pp) return (0); //--- if (iClose_Signal - iMA_Signal > iMA_Filter_a && iClose_Signal - BidPrice >= - cf && iWPR_Filter_OpenLong_a > iWPR_Signal) result1 = true; else result1 = false; //--- if (iClose_Signal - iMA_Signal > iMA_Filter_b && iClose_Signal - BidPrice >= - cf && - iCCI_OpenFilter > iCCI_Signal) result2 = true; else result2 = false; //--- if (iClose_Signal - iMA_Signal > iMA_Filter_b && iClose_Signal - BidPrice >= - cf && iWPR_Filter_OpenLong_b > iWPR_Signal) result3 = true; else result3 = false; //--- if (result1 == true || result2 == true || result3 == true) result = true; else result = false; //--- return (result); } //+--------------------------------------------------------------------------------------------------------------+ //| OpenShortSignal. Сигнал на открытие короткой позиции. //+--------------------------------------------------------------------------------------------------------------+ bool OpenShortSignal() { //+--------------------------------------------------------------------------------------------------------------+ bool result = false; bool result1 = false; bool result2 = false; bool result3 = false; //--- Расчет основных сигналов на вход double iClose_Signal = iClose(NULL, PERIOD_M15, 1); double iMA_Signal = iMA(NULL, PERIOD_M15, iMA_Period, 0, MODE_SMMA, PRICE_CLOSE, 1); double iWPR_Signal = iWPR(NULL, PERIOD_M15, iWPR_Period, 1); double iATR_Signal = iATR(NULL, PERIOD_M15, iATR_Period, 1); double iCCI_Signal = iCCI(NULL, PERIOD_M15, iCCI_Period, PRICE_TYPICAL, 1); //--- double iMA_Filter_a = NormalizeDouble(iMA_Filter_Open_a*pp,pd); double iMA_Filter_b = NormalizeDouble(iMA_Filter_Open_b*pp,pd); double BidPrice = Bid; //--- //--- Сверяем сигнал по АТР с его фильтром if (iATR_Signal <= FilterATR * pp) return (0); //--- if (iMA_Signal - iClose_Signal > iMA_Filter_a && iClose_Signal - BidPrice <= cf && iWPR_Signal > iWPR_Filter_OpenShort_a) result1 = true; else result1 = false; //--- if (iMA_Signal - iClose_Signal > iMA_Filter_b && iClose_Signal - BidPrice <= cf && iCCI_Signal > iCCI_OpenFilter) result2 = true; else result2 = false; //--- if (iMA_Signal - iClose_Signal > iMA_Filter_b && iClose_Signal - BidPrice <= cf && iWPR_Signal > iWPR_Filter_OpenShort_b) result3 = true; else result3 = false; //--- if (result1 == true || result2 == true || result3 == true) result = true; else result = false; //--- return (result); } //+--------------------------------------------------------------------------------------------------------------+ //| CloseLongSignal. Сигнал на закрытие длинной позиции. //+--------------------------------------------------------------------------------------------------------------+ bool CloseLongSignal(double OrderPrice, int CheckOrders) { //+--------------------------------------------------------------------------------------------------------------+ bool result = false; bool result1 = false; bool result2 = false; //--- double iWPR_Signal = iWPR(NULL, PERIOD_M15, iWPR_Period, 1); double iClose_Signal = iClose(NULL, PERIOD_M15, 1); double iOpen_CloseSignal = iOpen(NULL, PERIOD_M1, 1); double iClose_CloseSignal = iClose(NULL, PERIOD_M1, 1); //--- double MaxLoss = NormalizeDouble(-MaxLossPoints * pp,pd); //--- double Price_Filter = NormalizeDouble(Price_Filter_Close*pp,pd); double BidPrice = Bid; //--- //--- if (OrderPrice - BidPrice <= MaxLoss && iClose_Signal - BidPrice <= cf && iWPR_Signal > iWPR_Filter_CloseLong && CheckOrders == 1) result1 = true; else result1 = false; //--- if (iOpen_CloseSignal > iClose_CloseSignal && BidPrice - OrderPrice >= Price_Filter && CheckOrders == 1) result2 = true; else result2 = false; //--- if (result1 == true || result2 == true) result = true; else result = false; //--- return (result); } //+--------------------------------------------------------------------------------------------------------------+ //| CloseShortSignal. Сигнал на закрытие короткой позиции. //+--------------------------------------------------------------------------------------------------------------+ bool CloseShortSignal(double OrderPrice, int CheckOrders) { //+--------------------------------------------------------------------------------------------------------------+ bool result = false; bool result1 = false; bool result2 = false; //--- double iWPR_Signal = iWPR(NULL, PERIOD_M15, iWPR_Period, 1); double iClose_Signal = iClose(NULL, PERIOD_M15, 1); double iOpen_CloseSignal = iOpen(NULL, PERIOD_M1, 1); double iClose_CloseSignal = iClose(NULL, PERIOD_M1, 1); //--- double MaxLoss = NormalizeDouble(-MaxLossPoints*pp,pd); //--- double Price_Filter = NormalizeDouble(Price_Filter_Close*pp,pd); double BidPrice = Bid; double AskPrice = Ask; //--- //--- if (AskPrice - OrderPrice <= MaxLoss && iClose_Signal - BidPrice >= - cf && iWPR_Signal < iWPR_Filter_CloseShort && CheckOrders == 1) result1 = true; else result1 = false; //--- if (iOpen_CloseSignal < iClose_CloseSignal && OrderPrice - AskPrice >= Price_Filter && CheckOrders == 1) result2 = true; else result2 = false; //--- if (result1 == true || result2 == true) result = true; else result = false; //--- return (result); } //+--------------------------------------------------------------------------------------------------------------+ //| CalcLots. Функция расчета обьема лота. //| При AutoMM > 0.0 && RecoveryMode функция CalcLots расчитывает объём лота относительно свободных средств. //| //| Также расчет лота производиться исходя из числа открытых в прошлом ордеров. То есть увеличение лота теперь //| зависит не только от свободных средств, но и от числа открытых в прошлом советником ордеров. //| //| Помимо простого ММ, функция рассчитывает лот исходя из произошедших ранее стоп-лоссов при включенном //| параметре RecoveryMode, то есть, при желании можно включить режим восстановления депозита. //+--------------------------------------------------------------------------------------------------------------+ double CalcLots() { //+--------------------------------------------------------------------------------------------------------------+ double SumProfit; //--- Суммарный профит int OldOrdersCount; //--- Текущее кол-во закрытых советником ордеров double loss; //--- Просадка int LossOrdersCount; //--- Число лосей в прошлом double pr; //--- Профит int ProfitOrdersCount; //--- Кол-во прибыльных ордеров ы прошлом double LastPr; //--- Предыдущее значение профит int LastCount; //--- Предыдущее значение счетчика ордеров double MultiLot = 1; //--- Обнуление значения умножения лота //--- //--- Если ММ включен, то if (MultiLotPercent > 0.0 && AutoMM > 0.0) { //--- Обнуляем значения SumProfit = 0; OldOrdersCount = 0; loss = 0; LossOrdersCount = 0; pr = 0; ProfitOrdersCount = 0; //--- //--- Выбираем закрытие ранее ордера for (int i = OrdersHistoryTotal() - 1; i >= 0; i--) { if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { OldOrdersCount++; //--- Считаем ордера SumProfit += OrderProfit(); //--- и суммарный профит //--- Если суммарный профит больше pr (для начала больше 0) if (SumProfit > pr) { //--- Инициализируем профит и счетчик прибыльных ордеров pr = SumProfit; ProfitOrdersCount = OldOrdersCount; } //--- Если суммарный профит меньше loss (для начала больше 0) if (SumProfit < loss) { //--- Инициализируем просадку и счетчик убыточных ордеров loss = SumProfit; LossOrdersCount = OldOrdersCount; } //--- Если текущее кол-во подсчитанных ордеров больше или равно MaxAnalizCount (50), то в будущем считаем только свеженькие ордера а старые вычитаем. if (OldOrdersCount >= MaxAnalizCount) break; } } } //--- Закрытие for (int i = OrdersHistoryTotal() - 1; i >= 0; i--) { //--- Если число прибыльных ордеров меньше или равно числу лосей, то расчитываем значение умножения лота MultiLot if (ProfitOrdersCount <= LossOrdersCount) MultiLot = MathPow(MultiLotPercent, LossOrdersCount); //--- Если нет, то else { //--- Инициализируем параметры по профиту SumProfit = pr; OldOrdersCount = ProfitOrdersCount; LastPr = pr; LastCount = ProfitOrdersCount; //--- Выбираем закрытие ранее ордера (минус число прибыльных ордеров) for (i = OrdersHistoryTotal() - ProfitOrdersCount - 1; i >= 0; i--) { if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { //--- Если выбрано более 50 ордеров прекразщаем выбирать if (OldOrdersCount >= MaxAnalizCount) break; //--- OldOrdersCount++; //--- Считаем кол-во ордеров SumProfit += OrderProfit(); //--- и профит //--- Если новый профит меньше предыдущего (LastPr), то if (SumProfit < LastPr) { //--- Переинициализируем значения профита и кол-во ордеров LastPr = SumProfit; LastCount = OldOrdersCount; } } } } //--- Закрытие for (i = OrdersHistoryTotal() - ProfitOrdersCount - 1; i >= 0; i--) { //--- Если значение счетчика LastCount равно счетчику прибыльных ордеров или прошлый профит равен текщему, то if (LastCount == ProfitOrdersCount || LastPr == pr) MultiLot = MathPow(MultiLotPercent, LossOrdersCount); //--- расчитываем значение умножения лота MultiLot //--- Если нет, то else { //--- Делим положительный (loss - pr) на положительный (LastPr - pr) и сравниваем с риском, после расчитываем умножение лота MultiLot if (MathAbs(loss - pr) / MathAbs(LastPr - pr) >= (Risk + 100.0) / 100.0) MultiLot = MathPow(MultiLotPercent, LossOrdersCount); else MultiLot = MathPow(MultiLotPercent, LastCount); } } } //--- Закрытие if (MultiLotPercent > 0.0 && AutoMM > 0.0) { //--- Получаем финальный объём лота, исходя из выполненных выше действий for (double OpLot = MathMax(MinLot, MathMin(MaxLot, MathCeil(MathMin(AutoMM_Max, MultiLot * AutoMM) / 100.0 * AccountFreeMargin() / LotStep / (LotValue / 100)) * LotStep)); OpLot >= 2.0 * MinLot && 1.05 * (OpLot * FreeMargin) >= AccountFreeMargin(); OpLot -= MinLot) { } return (OpLot); } //+--------------------------------------------------------------------------------------------------------------+ //| MaxSpreadFilter. Функция для расчета размера спреда и сравнения его со значением MaxSpread. //| Если текущий спред превышен, то возвращаем TRUE. //+--------------------------------------------------------------------------------------------------------------+ bool MaxSpreadFilter() { //+--------------------------------------------------------------------------------------------------------------+ RefreshRates(); if (NormalizeDouble(Ask - Bid, Digits) > NDMaxSpread) return (TRUE); //--- else return (FALSE); } //+--------------------------------------------------------------------------------------------------------------+ //| ExistPosition. Функция проверки открытых ордеров. //| Если открыт ордер возвращает True, если нет, дает разрешение (False, 0) на открытие. //+--------------------------------------------------------------------------------------------------------------+ int ExistPosition() { //+--------------------------------------------------------------------------------------------------------------+ int trade = OrdersTotal() - 1; for (int i = trade; i >= 0; i--) { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if (OrderMagicNumber() == MagicNumber) { if (OrderSymbol() == EASymbol) if (OrderType() <= OP_SELL) return (1); } } } //--- return (0); } //+--------------------------------------------------------------------------------------------------------------+ //| OneOrderInBar. Функция проверяет, открывался ли ордер внутри нулевой свечи. //+--------------------------------------------------------------------------------------------------------------+ bool OneOrderInBar(int OpType = -1){ //+--------------------------------------------------------------------------------------------------------------+ //--- Если отключена функция, то ничего не расчитываем. if (OneOrderInBarMode == FALSE) return(True); int Bar = Period(); //--- Свеча //--- Делаем выборку по закрытым ордерам for(int i = OrdersHistoryTotal(); i>=0; i--){ //--- if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)){ //--- if(OrderSymbol() == EASymbol && OrderType() == OpType && OrderMagicNumber() == MagicNumber) { //--- Если время закрытия ордера больше времени открытия нулевого бара, то запрещаем открытие нового ордера. if(OrderCloseTime()>iTime(EASymbol,Bar,0)) return(False); } } } //--- return(True); } //+--------------------------------------------------------------------------------------------------------------+ //| CheckOpenTrade. Функция для проверки открытого ордера. Проверяет был ли открыт ордер по OrderType. //| Если был открыт, то возвращает TRUE, если нет, то FALSE. //+--------------------------------------------------------------------------------------------------------------+ bool CheckOpenTrade(int OpType) { //+--------------------------------------------------------------------------------------------------------------+ int total = OrdersTotal(); for (int i = total - 1; i >= 0; i--) { if (OrderSelect(i, SELECT_BY_POS) == TRUE) if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OpType) return (TRUE); } //--- return (FALSE); } //+--------------------------------------------------------------------------------------------------------------+ //| ShowComments. Функция для отображения комментариев на графике. //+--------------------------------------------------------------------------------------------------------------+ void ShowComments() { //+--------------------------------------------------------------------------------------------------------------+ string ComSpacer = ""; //--- "/n" datetime MyOpDate = TIME_DATE; //--- Вывод в комментарий даты оптимизации (формат) //--- ComSpacer = ComSpacer + "\n " + "\n " + "\n Version 3.8.5 (FINAL)" + "\n Copyright © HELLTEAM^Pirat" + "\n http://www.fxmania.ru" + "\n -----------------------------------------------" + "\n Sets for: " + Symbol_Op + "\n Optimization date: " + TimeToStr (Date, MyOpDate) + "\n -----------------------------------------------" + "\n SL = " + StopLoss + " pips / TP = " + TakeProfit + " pips" + "\n Spread = " + DoubleToStr((Ask - Bid) / pp, 1) + " pips"; if (NormalizeDouble(Ask - Bid, Digits) > NDMaxSpread) ComSpacer = ComSpacer + " - TOO HIGH"; else ComSpacer = ComSpacer + " - NORMAL"; ComSpacer = ComSpacer + "\n -----------------------------------------------"; if (AutoMM > 0.0) { ComSpacer = ComSpacer + "\n AutoMM - ENABLED" + "\n Risk = " + DoubleToStr(AutoMM, 1) + "%"; } ComSpacer = ComSpacer + "\n Trading Lots = " + DoubleToStr(LotSize, 2); ComSpacer = ComSpacer + "\n -----------------------------------------------"; if (UseStopLevels) { ComSpacer = ComSpacer + "\n Stop Levels - ENABLED"; } else { ComSpacer = ComSpacer + "\n Stop Levels - DISABLED"; } if (RecoveryMode) { ComSpacer = ComSpacer + "\n Recovery Mode - ENABLED"; } else { ComSpacer = ComSpacer + "\n Recovery Mode - DISABLED"; } ComSpacer = ComSpacer + "\n -----------------------------------------------"; Comment(ComSpacer); if (ObjectFind("LV") < 0) { ObjectCreate("LV", OBJ_LABEL, 0, 0, 0); ObjectSetText("LV", "WALL STREET ROBOT", 9, "Tahoma Bold", White); ObjectSet("LV", OBJPROP_CORNER, 0); ObjectSet("LV", OBJPROP_BACK, FALSE); ObjectSet("LV", OBJPROP_XDISTANCE, 13); ObjectSet("LV", OBJPROP_YDISTANCE, 23); } if (ObjectFind("BKGR") < 0) { ObjectCreate("BKGR", OBJ_LABEL, 0, 0, 0); ObjectSetText("BKGR", "g", 110, "Webdings", DarkViolet ); ObjectSet("BKGR", OBJPROP_CORNER, 0); ObjectSet("BKGR", OBJPROP_BACK, TRUE); ObjectSet("BKGR", OBJPROP_XDISTANCE, 5); ObjectSet("BKGR", OBJPROP_YDISTANCE, 15); } if (ObjectFind("BKGR2") < 0) { ObjectCreate("BKGR2", OBJ_LABEL, 0, 0, 0); ObjectSetText("BKGR2", "g", 110, "Webdings", MidnightBlue); ObjectSet("BKGR2", OBJPROP_BACK, TRUE); ObjectSet("BKGR2", OBJPROP_XDISTANCE, 5); ObjectSet("BKGR2", OBJPROP_YDISTANCE, 60); } if (ObjectFind("BKGR3") < 0) { ObjectCreate("BKGR3", OBJ_LABEL, 0, 0, 0); ObjectSetText("BKGR3", "g", 110, "Webdings", MidnightBlue); ObjectSet("BKGR3", OBJPROP_CORNER, 0); ObjectSet("BKGR3", OBJPROP_BACK, TRUE); ObjectSet("BKGR3", OBJPROP_XDISTANCE, 5); ObjectSet("BKGR3", OBJPROP_YDISTANCE, 45); } if (ObjectFind("BKGR4") < 0) { ObjectCreate("BKGR4", OBJ_LABEL, 0, 0, 0); ObjectSetText("BKGR4", "g", 110, "Webdings", MidnightBlue); ObjectSet("BKGR4", OBJPROP_CORNER, 0); ObjectSet("BKGR4", OBJPROP_BACK, TRUE); ObjectSet("BKGR4", OBJPROP_XDISTANCE, 5); ObjectSet("BKGR4", OBJPROP_YDISTANCE, 84); } } //+--------------------------------------------------------------------------------------------------------------+ //| GetNameOP. Функций возвращает наименование торговой операции //| Параметры: //| op - идентификатор торговой операции //+--------------------------------------------------------------------------------------------------------------+ string GetNameOP(int op) { //+--------------------------------------------------------------------------------------------------------------+ switch (op) { case OP_BUY : return("Buy"); case OP_SELL : return("Sell"); case OP_BUYLIMIT : return("Buy Limit"); case OP_SELLLIMIT: return("Sell Limit"); case OP_BUYSTOP : return("Buy Stop"); case OP_SELLSTOP : return("Sell Stop"); default : return("Unknown Operation"); } } //+--------------------------------------------------------------------------------------------------------------+ //| ErrorDescription. Возвращает описание ошибки по её номеру. //+--------------------------------------------------------------------------------------------------------------+ string ErrorDescription(int error) { //+--------------------------------------------------------------------------------------------------------------+ string ErrorNumber; //--- switch (error) { case 0: case 1: ErrorNumber = "Нет ошибки, но результат неизвестен"; break; case 2: ErrorNumber = "Общая ошибка"; break; case 3: ErrorNumber = "Неправильные параметры"; break; case 4: ErrorNumber = "Торговый сервер занят"; break; case 5: ErrorNumber = "Старая версия клиентского терминала"; break; case 6: ErrorNumber = "Нет связи с торговым сервером"; break; case 7: ErrorNumber = "Недостаточно прав"; break; case 8: ErrorNumber = "Слишком частые запросы"; break; case 9: ErrorNumber = "Недопустимая операция нарушающая функционирование сервера"; break; case 64: ErrorNumber = "Счет заблокирован"; break; case 65: ErrorNumber = "Неправильный номер счета"; break; case 128: ErrorNumber = "Истек срок ожидания совершения сделки"; break; case 129: ErrorNumber = "Неправильная цена"; break; case 130: ErrorNumber = "Неправильные стопы"; break; case 131: ErrorNumber = "Неправильный объем"; break; case 132: ErrorNumber = "Рынок закрыт"; break; case 133: ErrorNumber = "Торговля запрещена"; break; case 134: ErrorNumber = "Недостаточно денег для совершения операции"; break; case 135: ErrorNumber = "Цена изменилась"; break; case 136: ErrorNumber = "Нет цен"; break; case 137: ErrorNumber = "Брокер занят"; break; case 138: ErrorNumber = "Новые цены - Реквот"; break; case 139: ErrorNumber = "Ордер заблокирован и уже обрабатывается"; break; case 140: ErrorNumber = "Разрешена только покупка"; break; case 141: ErrorNumber = "Слишком много запросов"; break; case 145: ErrorNumber = "Модификация запрещена, так как ордер слишком близок к рынку";break; case 146: ErrorNumber = "Подсистема торговли занята"; break; case 147: ErrorNumber = "Использование даты истечения ордера запрещено брокером"; break; case 148: ErrorNumber = "Количество открытых и отложенных ордеров достигло предела "; break; //---- case 4000: ErrorNumber = "Нет ошибки"; break; case 4001: ErrorNumber = "Неправильный указатель функции"; break; case 4002: ErrorNumber = "Индекс массива - вне диапазона"; break; case 4003: ErrorNumber = "Нет памяти для стека функций"; break; case 4004: ErrorNumber = "Переполнение стека после рекурсивного вызова"; break; case 4005: ErrorNumber = "На стеке нет памяти для передачи параметров"; break; case 4006: ErrorNumber = "Нет памяти для строкового параметра"; break; case 4007: ErrorNumber = "Нет памяти для временной строки"; break; case 4008: ErrorNumber = "Неинициализированная строка"; break; case 4009: ErrorNumber = "Неинициализированная строка в массиве"; break; case 4010: ErrorNumber = "Нет памяти для строкового массива"; break; case 4011: ErrorNumber = "Слишком длинная строка"; break; case 4012: ErrorNumber = "Остаток от деления на ноль"; break; case 4013: ErrorNumber = "Деление на ноль"; break; case 4014: ErrorNumber = "Неизвестная команда"; break; case 4015: ErrorNumber = "Неправильный переход"; break; case 4016: ErrorNumber = "Неинициализированный массив"; break; case 4017: ErrorNumber = "Вызовы DLL не разрешены"; break; case 4018: ErrorNumber = "Невозможно загрузить библиотеку"; break; case 4019: ErrorNumber = "Невозможно вызвать функцию"; break; case 4020: ErrorNumber = "Вызовы внешних библиотечных функций не разрешены"; break; case 4021: ErrorNumber = "Недостаточно памяти для строки, возвращаемой из функции"; break; case 4022: ErrorNumber = "Система занята"; break; case 4050: ErrorNumber = "Неправильное количество параметров функции"; break; case 4051: ErrorNumber = "Недопустимое значение параметра функции"; break; case 4052: ErrorNumber = "Внутренняя ошибка строковой функции"; break; case 4053: ErrorNumber = "Ошибка массива"; break; case 4054: ErrorNumber = "Неправильное использование массива-таймсерии"; break; case 4055: ErrorNumber = "Ошибка пользовательского индикатора"; break; case 4056: ErrorNumber = "Массивы несовместимы"; break; case 4057: ErrorNumber = "Ошибка обработки глобальныех переменных"; break; case 4058: ErrorNumber = "Глобальная переменная не обнаружена"; break; case 4059: ErrorNumber = "Функция не разрешена в тестовом режиме"; break; case 4060: ErrorNumber = "Функция не подтверждена"; break; case 4061: ErrorNumber = "Ошибка отправки почты"; break; case 4062: ErrorNumber = "Ожидается параметр типа string"; break; case 4063: ErrorNumber = "Ожидается параметр типа integer"; break; case 4064: ErrorNumber = "Ожидается параметр типа double"; break; case 4065: ErrorNumber = "В качестве параметра ожидается массив"; break; case 4066: ErrorNumber = "Запрошенные исторические данные в состоянии обновления"; break; case 4067: ErrorNumber = "Ошибка при выполнении торговой операции"; break; case 4099: ErrorNumber = "Конец файла"; break; case 4100: ErrorNumber = "Ошибка при работе с файлом"; break; case 4101: ErrorNumber = "Неправильное имя файла"; break; case 4102: ErrorNumber = "Слишком много открытых файлов"; break; case 4103: ErrorNumber = "Невозможно открыть файл"; break; case 4104: ErrorNumber = "Несовместимый режим доступа к файлу"; break; case 4105: ErrorNumber = "Ни один ордер не выбран"; break; case 4106: ErrorNumber = "Неизвестный символ"; break; case 4107: ErrorNumber = "Неправильный параметр цены для торговой функции"; break; case 4108: ErrorNumber = "Неверный номер тикета"; break; case 4109: ErrorNumber = "Торговля не разрешена"; break; case 4110: ErrorNumber = "Длинные позиции не разрешены"; break; case 4111: ErrorNumber = "Короткие позиции не разрешены"; break; case 4200: ErrorNumber = "Объект уже существует"; break; case 4201: ErrorNumber = "Запрошено неизвестное свойство объекта"; break; case 4202: ErrorNumber = "Объект не существует"; break; case 4203: ErrorNumber = "Неизвестный тип объекта"; break; case 4204: ErrorNumber = "Нет имени объекта"; break; case 4205: ErrorNumber = "Ошибка координат объекта"; break; case 4206: ErrorNumber = "Не найдено указанное подокно"; break; case 4207: ErrorNumber = "Ошибка при работе с объектом"; break; default: ErrorNumber = "Неизвестная ошибка"; } //--- return (ErrorNumber); }