//+------------------------------------------------------------------+ //| Объединённый скрипт (H1 + H4) | //| | //| Этот скрипт реализует калькулятор на графике H1 для расчёта риска/лота| //| и "прошив D1", а также панель выбора уровня на графике H4. | //| | //| Для H1 панель создаётся и удаляется (с сохранением в глобальных | //| переменных), а для H4 объект поля ввода создаётся только на графике H4.| //| Если таймфрейм не H4, объект не создаётся – значение сохраняется в | //| глобальной переменной и в файле, и при переключении на H4 поле создаётся| //| с этим значением. Для перекрашивания линий используется поиск всех | //| горизонтальных линий, содержащих "Horizontal" в названии, при этом | //| линии с цветом DodgerBlue остаются неизменными. | //+------------------------------------------------------------------+ #include #property strict #property version "10.3" #ifndef OBJPROP_VISIBLE #define OBJPROP_VISIBLE 20 #endif //------------------------------------------ // Константы для панели H1 #define LOT_DECIMALS 2 #define GLOB_STOP_SIZE "MyLotCalc_StopSize" #define GLOB_STOP_PRICE "MyLotCalc_StopPrice" #define GLOB_RISK_PERCENT "MyLotCalc_RiskPercent" #define GLOB_LOT "MyLotCalc_Lot" #define OBJ_LABEL_PROSHIVD1_UPPER "label_ProshivD1_upper" #define OBJ_VALUE_PROSHIVD1_UPPER "value_ProshivD1_upper" #define OBJ_LABEL_PROSHIVD1_LOWER "label_ProshivD1_lower" #define OBJ_VALUE_PROSHIVD1_LOWER "value_ProshivD1_lower" #define OBJ_LABEL_RANGE_D1 "label_RangeD1" #define OBJ_VALUE_RANGE_D1 "value_RangeD1" #define OBJ_NAME_STOP_SIZE "edit_StopSize" #define OBJ_NAME_STOP_PRICE "edit_StopPrice" #define OBJ_NAME_RISK_PERCENT "edit_RiskPercent" #define OBJ_NAME_LOT "edit_Lot" #define OBJ_LABEL_STOP_SIZE "label_StopSize" #define OBJ_LABEL_STOP_PRICE "label_StopPrice" #define OBJ_LABEL_RISK_PERCENT "label_RiskPercent" #define OBJ_LABEL_LOT_NAME "label_LotName" #define OBJ_LABEL_ATR "label_ATR" #define OBJ_VALUE_ATR "value_ATR" #define OBJ_LABEL_PROSHIVD1_4C_UPPER "label_ProshivD1_4cand_upper" #define OBJ_VALUE_PROSHIVD1_4C_UPPER "value_ProshivD1_4cand_upper" #define OBJ_LABEL_PROSHIVD1_4C_LOWER "label_ProshivD1_4cand_lower" #define OBJ_VALUE_PROSHIVD1_4C_LOWER "value_ProshivD1_4cand_lower" //------------------------------------------ // Фиксированные Y-координаты для объектов панели H1 #define Y_RANGE_D1 17 #define Y_PROSHIV_UPPER 32 #define Y_PROSHIV_LOWER 47 #define Y_PROSHIV_4C_UPPER 62 #define Y_PROSHIV_4C_LOWER 77 #define Y_ATR 107 #define Y_STOP_SIZE 122 #define Y_STOP_PRICE 137 #define Y_RISK_PERCENT 152 #define Y_LOT 167 //------------------------------------------ // Параметры расположения объектов (по оси X) #define X_LABEL 10 #define X_VALUE 160 //------------------------------------------ // Глобальные переменные color TextColor = clrLightSlateGray; string lastChanged = ""; bool updating = false; input int ATRPeriod = 7; //------------------------------------------ // Для панели H4: имя объекта и имена для сохранения выбранного уровня string objNameSelectedLevel = "SelectedLevelInput"; string gvNameSelectedLevel = "SelectedLevel_H4"; color selectedColor = clrGreen; color unselectedColor = clrOrange; color excludeColor = clrDodgerBlue; //------------------------------------------ // Структура спецификации и массив struct InstrumentSpec { string symbol; string description; double tradeContractSize; double tradeTickSize; double pointSize; int digits; double volumeStep; double volumeMin; double volumeMax; string currencyProfit; double spreadFloat; }; InstrumentSpec Specs[]; //------------------------------------------ // Утилитарные функции string trimQuotes(string str) { StringReplace(str, "\"", ""); return str; } string trimAllSpaces(string s) { StringTrimLeft(s); StringTrimRight(s); return s; } long ToPips(double price) { int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); return (long)(price * MathPow(10, digits)); } //------------------------------------------ // Функции работы со спецификациями (CSV) bool loadInstrumentSpecs() { int fileHandle = FileOpen("SymbolSpecifications.csv", FILE_READ|FILE_CSV|FILE_ANSI); if(fileHandle == INVALID_HANDLE) { Print("Не удалось открыть файл SymbolSpecifications.csv."); return false; } string header = FileReadString(fileHandle); ArrayResize(Specs, 0); while(!FileIsEnding(fileHandle)) { string line = FileReadString(fileHandle); if(StringLen(line)==0) continue; string fields[]; int count = (int)StringSplit(line, ';', fields); if(count < 11) continue; InstrumentSpec spec; spec.symbol = trimAllSpaces(trimQuotes(fields[0])); spec.description = trimAllSpaces(trimQuotes(fields[1])); spec.tradeContractSize = StringToDouble(trimAllSpaces(trimQuotes(fields[2]))); spec.tradeTickSize = StringToDouble(trimAllSpaces(trimQuotes(fields[3]))); spec.pointSize = StringToDouble(trimAllSpaces(trimQuotes(fields[4]))); spec.digits = (int)StringToDouble(trimAllSpaces(trimQuotes(fields[5]))); spec.volumeStep = StringToDouble(trimAllSpaces(trimQuotes(fields[6]))); spec.volumeMin = StringToDouble(trimAllSpaces(trimQuotes(fields[7]))); spec.volumeMax = StringToDouble(trimAllSpaces(trimQuotes(fields[8]))); spec.currencyProfit = trimAllSpaces(trimQuotes(fields[9])); spec.spreadFloat = StringToDouble(trimAllSpaces(trimQuotes(fields[10]))); int size = (int)ArraySize(Specs); ArrayResize(Specs, size+1); Specs[size] = spec; } FileClose(fileHandle); Print("Загружено спецификаций инструментов: ", IntegerToString(ArraySize(Specs))); return true; } bool getInstrumentSpec(string symbol, InstrumentSpec &spec) { int sz = (int)ArraySize(Specs); for(int i = 0; i < sz; i++) if(Specs[i].symbol == symbol) { spec = Specs[i]; return true; } Print("ERROR: Не найдена спецификация для символа ", symbol); return false; } double trySymbolRate(string baseSymbol) { if(SymbolSelect(baseSymbol, true)) { double r = SymbolInfoDouble(baseSymbol, SYMBOL_BID); if(r > 0.0) return r; } string possibleSuffixes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; int len = (int)StringLen(possibleSuffixes); for(int i = 0; i < len; i++) { string suffix = StringSubstr(possibleSuffixes, i, 1); string symbolWithSuffix = baseSymbol + suffix; if(SymbolSelect(symbolWithSuffix, true)) { double r = SymbolInfoDouble(symbolWithSuffix, SYMBOL_BID); if(r > 0.0) return r; } } return 0.0; } double convertToUSD(double amount, string fromCurrency) { if(fromCurrency=="USD" || fromCurrency=="") return amount; string directSymbol = "USD" + fromCurrency; double rate = trySymbolRate(directSymbol); if(rate > 0.0) return amount / rate; string altSymbol = fromCurrency + "USD"; rate = trySymbolRate(altSymbol); if(rate > 0.0) return amount * rate; if(fromCurrency=="GBP") { rate = trySymbolRate("EURGBP"); if(rate > 0.0) { double eurUsd = convertToUSD(amount, "EUR"); return eurUsd / rate; } } Print("WARNING: не удалось найти кросс для ", fromCurrency, " -> USD. Возвращаем ", DoubleToString(amount,2)); return amount; } double getInstrumentPipValue(string symbol) { InstrumentSpec spec; if(!getInstrumentSpec(symbol, spec)) return 0.0; if(spec.tradeContractSize <= 0 || spec.pointSize <= 0) { Print("ERROR: Некорректные значения для ", symbol); return 0.0; } double pipValue = spec.tradeContractSize * spec.pointSize; if(spec.currencyProfit!="USD") pipValue = convertToUSD(pipValue, spec.currencyProfit); if(pipValue <= 0.0) { Print("ERROR: PipValue <= 0 для ", symbol); return 0.0; } return pipValue; } //------------------------------------------ // Функции расчёта ATR и пересчёта значений double getATR20Percent(int atrPeriod) { int handle = iATR(_Symbol, PERIOD_D1, atrPeriod); if(handle == INVALID_HANDLE) return 0.0; double buffer[]; int copied = CopyBuffer(handle, 0, 0, 1, buffer); IndicatorRelease(handle); if(copied > 0) return buffer[0] * 0.2 / _Point; return 0.0; } void recalculateValues(double stopSize, double stopPrice, double pipValue, double &newRisk, double &newLot) { double balance = AccountInfoDouble(ACCOUNT_BALANCE); newRisk = (balance > 0.0) ? (stopPrice / balance) * 100.0 : 0.0; newLot = (stopSize > 0 && pipValue > 0) ? stopPrice / (stopSize * pipValue) : 0.0; } //------------------------------------------ // Сохранение/загрузка глобальных переменных для H1 void saveValues(double stopSize, double stopPrice, double riskPercent, double lot) { GlobalVariableSet(StringFormat("%s_%s", GLOB_STOP_SIZE, _Symbol), stopSize); GlobalVariableSet(StringFormat("%s_%s", GLOB_STOP_PRICE, _Symbol), stopPrice); GlobalVariableSet(StringFormat("%s_%s", GLOB_RISK_PERCENT, _Symbol), riskPercent); GlobalVariableSet(StringFormat("%s_%s", GLOB_LOT, _Symbol), lot); } void loadValues(double &stopSize, double &stopPrice, double &riskPercent, double &lot) { string sStop = StringFormat("%s_%s", GLOB_STOP_SIZE, _Symbol); string sPrice = StringFormat("%s_%s", GLOB_STOP_PRICE, _Symbol); string sRisk = StringFormat("%s_%s", GLOB_RISK_PERCENT, _Symbol); string sLot = StringFormat("%s_%s", GLOB_LOT, _Symbol); stopSize = GlobalVariableCheck(sStop) ? GlobalVariableGet(sStop) : 0.0; stopPrice = GlobalVariableCheck(sPrice) ? GlobalVariableGet(sPrice) : 0.0; riskPercent = GlobalVariableCheck(sRisk) ? GlobalVariableGet(sRisk) : 0.0; lot = GlobalVariableCheck(sLot) ? GlobalVariableGet(sLot) : 0.0; } //------------------------------------------ // Дополнительный метод сохранения уровня для H4 через файл bool SaveLevelToFile(int level) { int handle = FileOpen("level_h4.txt", FILE_WRITE|FILE_TXT|FILE_COMMON); if(handle == INVALID_HANDLE) { Print("Ошибка открытия файла для сохранения уровня."); return false; } FileWrite(handle, IntegerToString(level)); FileClose(handle); return true; } int LoadLevelFromFile() { int level = 1; int handle = FileOpen("level_h4.txt", FILE_READ|FILE_TXT|FILE_COMMON); if(handle != INVALID_HANDLE) { string s = FileReadString(handle); FileClose(handle); level = StringToInteger(s); } return level; } //------------------------------------------ // Функция для определения количества линий DodgerBlue int GetDodgerBlueLevelsCount() { int count = 0; int total = (int)ObjectsTotal(0); for(int i = 0; i < total; i++) { string objName = ObjectName(0, i); int type = (int)ObjectGetInteger(0, objName, OBJPROP_TYPE); if(type == OBJ_HLINE && (StringFind(objName, "Horizontal") >= 0) && ((int)ObjectGetInteger(0, objName, OBJPROP_COLOR)) == (int)clrDodgerBlue) count++; } return count; } //------------------------------------------ // Панель калькулятора H1 (с отдельными координатами) void createPanel() { if(ChartPeriod() != PERIOD_H1) return; // Диапазон D1 ObjectCreate(0, OBJ_LABEL_RANGE_D1, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_RANGE_D1); ObjectSetInteger(0, OBJ_LABEL_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, OBJ_LABEL_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectSetString(0, OBJ_LABEL_RANGE_D1, OBJPROP_TEXT, "Диапазон D1:"); ObjectCreate(0, OBJ_VALUE_RANGE_D1, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_VALUE_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_VALUE_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_VALUE_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_RANGE_D1); ObjectSetString(0, OBJ_VALUE_RANGE_D1, OBJPROP_TEXT, "-"); ObjectSetInteger(0, OBJ_VALUE_RANGE_D1, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); // Прошив D1 верх общий ObjectCreate(0, OBJ_LABEL_PROSHIVD1_UPPER, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_PROSHIV_UPPER); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectSetString(0, OBJ_LABEL_PROSHIVD1_UPPER, OBJPROP_TEXT, "Прошив D1 верх общий:"); ObjectCreate(0, OBJ_VALUE_PROSHIVD1_UPPER, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_PROSHIV_UPPER); ObjectSetString(0, OBJ_VALUE_PROSHIVD1_UPPER, OBJPROP_TEXT, "-"); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); // Прошив D1 низ общий ObjectCreate(0, OBJ_LABEL_PROSHIVD1_LOWER, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_PROSHIV_LOWER); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectSetString(0, OBJ_LABEL_PROSHIVD1_LOWER, OBJPROP_TEXT, "Прошив D1 низ общий:"); ObjectCreate(0, OBJ_VALUE_PROSHIVD1_LOWER, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_PROSHIV_LOWER); ObjectSetString(0, OBJ_VALUE_PROSHIVD1_LOWER, OBJPROP_TEXT, "-"); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); // Прошив D1 верх 4свч ObjectCreate(0, OBJ_LABEL_PROSHIVD1_4C_UPPER, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_PROSHIV_4C_UPPER); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectSetString(0, OBJ_LABEL_PROSHIVD1_4C_UPPER, OBJPROP_TEXT, "Прошив D1 верх 4свч:"); ObjectCreate(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_PROSHIV_4C_UPPER); ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, OBJPROP_TEXT, "-"); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); // Прошив D1 низ 4свч ObjectCreate(0, OBJ_LABEL_PROSHIVD1_4C_LOWER, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_PROSHIV_4C_LOWER); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, OBJ_LABEL_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectSetString(0, OBJ_LABEL_PROSHIVD1_4C_LOWER, OBJPROP_TEXT, "Прошив D1 низ 4свч:"); ObjectCreate(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_PROSHIV_4C_LOWER); ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, OBJPROP_TEXT, "-"); ObjectSetInteger(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); // ATR(7) 20% ObjectCreate(0, OBJ_LABEL_ATR, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_ATR); ObjectSetInteger(0, OBJ_LABEL_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, OBJ_LABEL_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectSetString(0, OBJ_LABEL_ATR, OBJPROP_TEXT, "ATR(7) 20%:"); ObjectCreate(0, OBJ_VALUE_ATR, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_VALUE_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_VALUE_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_VALUE_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_ATR); ObjectSetInteger(0, OBJ_VALUE_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, OBJ_VALUE_ATR, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); ObjectSetString(0, OBJ_VALUE_ATR, OBJPROP_TEXT, DoubleToString(getATR20Percent(ATRPeriod), 1)); // Размер стопа ObjectCreate(0, OBJ_LABEL_STOP_SIZE, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_STOP_SIZE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_STOP_SIZE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_STOP_SIZE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_STOP_SIZE); ObjectSetString(0, OBJ_LABEL_STOP_SIZE, OBJPROP_TEXT, "Размер стопа:"); ObjectSetInteger(0, OBJ_LABEL_STOP_SIZE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectCreate(0, OBJ_NAME_STOP_SIZE, OBJ_EDIT, 0, 0, 0); ObjectSetInteger(0, OBJ_NAME_STOP_SIZE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_NAME_STOP_SIZE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_NAME_STOP_SIZE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_STOP_SIZE); ObjectSetString(0, OBJ_NAME_STOP_SIZE, OBJPROP_TEXT, "0"); ObjectSetInteger(0, OBJ_NAME_STOP_SIZE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); // Цена стопа ObjectCreate(0, OBJ_LABEL_STOP_PRICE, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_STOP_PRICE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_STOP_PRICE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_STOP_PRICE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_STOP_PRICE); ObjectSetString(0, OBJ_LABEL_STOP_PRICE, OBJPROP_TEXT, "Цена стопа:"); ObjectSetInteger(0, OBJ_LABEL_STOP_PRICE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectCreate(0, OBJ_NAME_STOP_PRICE, OBJ_EDIT, 0, 0, 0); ObjectSetInteger(0, OBJ_NAME_STOP_PRICE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_NAME_STOP_PRICE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_NAME_STOP_PRICE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_STOP_PRICE); ObjectSetString(0, OBJ_NAME_STOP_PRICE, OBJPROP_TEXT, "0.00"); ObjectSetInteger(0, OBJ_NAME_STOP_PRICE, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); // Риск (%) ObjectCreate(0, OBJ_LABEL_RISK_PERCENT, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_RISK_PERCENT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_RISK_PERCENT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_RISK_PERCENT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_RISK_PERCENT); ObjectSetString(0, OBJ_LABEL_RISK_PERCENT, OBJPROP_TEXT, "Риск (%):"); ObjectSetInteger(0, OBJ_LABEL_RISK_PERCENT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectCreate(0, OBJ_NAME_RISK_PERCENT, OBJ_EDIT, 0, 0, 0); ObjectSetInteger(0, OBJ_NAME_RISK_PERCENT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_NAME_RISK_PERCENT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_NAME_RISK_PERCENT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_RISK_PERCENT); ObjectSetString(0, OBJ_NAME_RISK_PERCENT, OBJPROP_TEXT, "0"); ObjectSetInteger(0, OBJ_NAME_RISK_PERCENT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); // Лот ObjectCreate(0, OBJ_LABEL_LOT_NAME, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, OBJ_LABEL_LOT_NAME, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_LABEL_LOT_NAME, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_LABEL); ObjectSetInteger(0, OBJ_LABEL_LOT_NAME, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_LOT); ObjectSetString(0, OBJ_LABEL_LOT_NAME, OBJPROP_TEXT, "Лот:"); ObjectSetInteger(0, OBJ_LABEL_LOT_NAME, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)clrLightSlateGray); ObjectCreate(0, OBJ_NAME_LOT, OBJ_EDIT, 0, 0, 0); ObjectSetInteger(0, OBJ_NAME_LOT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, OBJ_NAME_LOT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)X_VALUE); ObjectSetInteger(0, OBJ_NAME_LOT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, Y_LOT); ObjectSetString(0, OBJ_NAME_LOT, OBJPROP_TEXT, "0"); ObjectSetInteger(0, OBJ_NAME_LOT, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); } //------------------------------------------ // Удаление панели H1 void deletePanel() { ObjectDelete(0, OBJ_LABEL_ATR); ObjectDelete(0, OBJ_VALUE_ATR); ObjectDelete(0, OBJ_LABEL_RANGE_D1); ObjectDelete(0, OBJ_VALUE_RANGE_D1); ObjectDelete(0, OBJ_LABEL_PROSHIVD1_UPPER); ObjectDelete(0, OBJ_VALUE_PROSHIVD1_UPPER); ObjectDelete(0, OBJ_LABEL_PROSHIVD1_4C_UPPER); ObjectDelete(0, OBJ_VALUE_PROSHIVD1_4C_UPPER); ObjectDelete(0, OBJ_LABEL_PROSHIVD1_LOWER); ObjectDelete(0, OBJ_VALUE_PROSHIVD1_LOWER); ObjectDelete(0, OBJ_LABEL_PROSHIVD1_4C_LOWER); ObjectDelete(0, OBJ_VALUE_PROSHIVD1_4C_LOWER); ObjectDelete(0, OBJ_LABEL_STOP_SIZE); ObjectDelete(0, OBJ_NAME_STOP_SIZE); ObjectDelete(0, OBJ_LABEL_STOP_PRICE); ObjectDelete(0, OBJ_NAME_STOP_PRICE); ObjectDelete(0, OBJ_LABEL_RISK_PERCENT); ObjectDelete(0, OBJ_NAME_RISK_PERCENT); ObjectDelete(0, OBJ_LABEL_LOT_NAME); ObjectDelete(0, OBJ_NAME_LOT); } //------------------------------------------ // Получение H1 уровней (ищем горизонтальные линии с "Horizontal" и цветом clrDodgerBlue) void GetH1Levels(double &upper, double &lower) { upper = 0.0; lower = 0.0; int count = 0; int total = (int)ObjectsTotal(0); for(int i = 0; i < total; i++) { string objName = ObjectName(0, i); int type = (int)ObjectGetInteger(0, objName, OBJPROP_TYPE); if(type == OBJ_HLINE && (StringFind(objName, "Horizontal") >= 0) && ((int)ObjectGetInteger(0, objName, OBJPROP_COLOR)) == (int)clrDodgerBlue) { double price = ObjectGetDouble(0, objName, OBJPROP_PRICE); Print("Найдена линия: ", objName, " Цена = ", DoubleToString(price, (int)Digits())); if(count == 0) { upper = price; lower = price; } else { if(price > upper) upper = price; if(price < lower) lower = price; } count++; } } Print("Обнаружено линий: ", count, " | Upper = ", DoubleToString(upper, (int)Digits()), " | Lower = ", DoubleToString(lower, (int)Digits())); } //------------------------------------------ // Поиск оптимального блока свечей на D1 bool GetMaxNestedRange(int startCandidate, int minCandles, int maxLookBack, double &bestHigh, double &bestLow, int &bestCount) { bestCount = 0; bool found = false; for(int i = startCandidate; i < maxLookBack; i++) { if(iTime(_Symbol, PERIOD_D1, i) == (datetime)0) break; double candidateHigh = iHigh(_Symbol, PERIOD_D1, i); double candidateLow = iLow(_Symbol, PERIOD_D1, i); bool valid = true; for(int j = 1; j <= i; j++) { if(iTime(_Symbol, PERIOD_D1, j) == (datetime)0) { valid = false; break; } double op = iOpen(_Symbol, PERIOD_D1, j); double cl = iClose(_Symbol, PERIOD_D1, j); if(op < candidateLow || op > candidateHigh || cl < candidateLow || cl > candidateHigh) { valid = false; break; } } if(valid) { int currentCount = i; for(int j = i+1; j < maxLookBack; j++) { if(iTime(_Symbol, PERIOD_D1, j) == (datetime)0) break; double op = iOpen(_Symbol, PERIOD_D1, j); double cl = iClose(_Symbol, PERIOD_D1, j); if(op < candidateLow || op > candidateHigh || cl < candidateLow || cl > candidateHigh) break; currentCount = j; } if(currentCount >= minCandles && currentCount > bestCount) { bestCount = currentCount; bestHigh = candidateHigh; bestLow = candidateLow; found = true; Print("GetMaxNestedRange: кандидат i=", i, " блок расширен до ", currentCount, " candidateHigh=", DoubleToString(bestHigh,5), " candidateLow=", DoubleToString(bestLow,5)); } } } return found; } //------------------------------------------ // Функция "Прошив D1 общий" – выбираем самую большую свечу из блока double calculateProshivD1ForLevel(double targetLevel) { if(iTime(_Symbol, PERIOD_D1, 3) == (datetime)0) return -1; double blockHigh, blockLow; int cnt; if(!GetMaxNestedRange(2, 4, 50, blockHigh, blockLow, cnt)) { Print("Не найден оптимальный блок свечей для расчёта прошива."); return -1; } Print("Оптимальный блок: ", cnt, " свечей | BlockHigh = ", DoubleToString(blockHigh,5), " | BlockLow = ", DoubleToString(blockLow,5)); double maxRange = -1, candHigh = 0, candLow = 0; for(int i = 1; i <= cnt; i++) { if(iTime(_Symbol, PERIOD_D1, i) == (datetime)0) break; double h = iHigh(_Symbol, PERIOD_D1, i); double l = iLow(_Symbol, PERIOD_D1, i); double range = h - l; if(range > maxRange) { maxRange = range; candHigh = h; candLow = l; } } long diff = ToPips(candHigh) - ToPips(candLow); Print("Максимальная свеча блока: candHigh = ", DoubleToString(candHigh,5), " | candLow = ", DoubleToString(candLow,5), " | diff = ", diff); if(diff == 0) return 0; long targetPips = ToPips(targetLevel); double percent = ((double)(targetPips - ToPips(candLow)) / (double)diff) * 100.0; if(percent < 0) percent = 0; if(percent > 100) percent = 100; Print("TargetLevel = ", DoubleToString(targetLevel, (int)Digits()), " | TargetPips = ", targetPips, " | Прошив = ", percent, "%"); return percent; } //------------------------------------------ // Функция "Прошив D1 по 4 свечам" – выбираем из последних 4 свечей самую большую свечу double calculateProshivD1For4CandlesForLevel(double targetLevel) { int numCandles = 4; double maxRange = -1, candHigh = 0, candLow = 0; for(int i = 1; i <= numCandles; i++) { if(iTime(_Symbol, PERIOD_D1, i) == (datetime)0) return -1; double h = iHigh(_Symbol, PERIOD_D1, i); double l = iLow(_Symbol, PERIOD_D1, i); double range = h - l; if(range > maxRange) { maxRange = range; candHigh = h; candLow = l; } } if(maxRange <= 0) return -1; long diff = ToPips(candHigh) - ToPips(candLow); if(diff <= 0) return 0; long targetPips = ToPips(targetLevel); double percent = ((double)(targetPips - ToPips(candLow)) / (double)diff) * 100.0; if(percent < 0) percent = 0; if(percent > 100) percent = 100; Print("Прошив 4 свеч: TargetLevel = ", DoubleToString(targetLevel, (int)Digits()), " | candLow = ", DoubleToString(candLow, (int)Digits()), " | candHigh = ", DoubleToString(candHigh, (int)Digits()), " | Прошив = ", percent, "%"); return percent; } //------------------------------------------ // Обновление ATR (без " pips") void updateATRTextImmediate(int atrPeriod) { double atr20 = getATR20Percent(atrPeriod); string text = DoubleToString(atr20, 1); ObjectSetString(0, OBJ_VALUE_ATR, OBJPROP_TEXT, text); } void updateATRTextOnM5Bar(int atrPeriod) { if(ChartPeriod() != PERIOD_H1) return; static datetime lastM5BarTime = 0; datetime currentBarTime = iTime(_Symbol, PERIOD_M5, 0); if(currentBarTime != lastM5BarTime) { lastM5BarTime = currentBarTime; updateATRTextImmediate(atrPeriod); } } //------------------------------------------ // Пересчёт панели H1 void recalculatePanel() { if(updating) return; updating = true; double stopSize = StringToDouble(ObjectGetString(0, OBJ_NAME_STOP_SIZE, OBJPROP_TEXT)); double stopPrice = StringToDouble(ObjectGetString(0, OBJ_NAME_STOP_PRICE, OBJPROP_TEXT)); double riskPercent = StringToDouble(ObjectGetString(0, OBJ_NAME_RISK_PERCENT, OBJPROP_TEXT)); double lot = StringToDouble(ObjectGetString(0, OBJ_NAME_LOT, OBJPROP_TEXT)); double pipValue = getInstrumentPipValue(_Symbol); double newRisk = riskPercent, newLot = lot; if(lastChanged == OBJ_NAME_STOP_PRICE) { double balance = AccountInfoDouble(ACCOUNT_BALANCE); if(balance > 0.0) { newRisk = (stopPrice / balance) * 100.0; ObjectSetString(0, OBJ_NAME_RISK_PERCENT, OBJPROP_TEXT, DoubleToString(newRisk, 2)); } recalculateValues(stopSize, stopPrice, pipValue, newRisk, newLot); ObjectSetString(0, OBJ_NAME_LOT, OBJPROP_TEXT, DoubleToString(newLot, LOT_DECIMALS)); } else if(lastChanged == OBJ_NAME_RISK_PERCENT) { double balance = AccountInfoDouble(ACCOUNT_BALANCE); if(balance > 0.0) { stopPrice = (riskPercent / 100.0) * balance; ObjectSetString(0, OBJ_NAME_STOP_PRICE, OBJPROP_TEXT, DoubleToString(stopPrice, 2)); } recalculateValues(stopSize, stopPrice, pipValue, newRisk, newLot); ObjectSetString(0, OBJ_NAME_LOT, OBJPROP_TEXT, DoubleToString(newLot, LOT_DECIMALS)); } else if(lastChanged == OBJ_NAME_LOT) { stopPrice = lot * stopSize * pipValue; ObjectSetString(0, OBJ_NAME_STOP_PRICE, OBJPROP_TEXT, DoubleToString(stopPrice, 2)); double balance = AccountInfoDouble(ACCOUNT_BALANCE); if(balance > 0.0) { newRisk = (stopPrice / balance) * 100.0; ObjectSetString(0, OBJ_NAME_RISK_PERCENT, OBJPROP_TEXT, DoubleToString(newRisk, 2)); } } else if(lastChanged == OBJ_NAME_STOP_SIZE) { recalculateValues(stopSize, stopPrice, pipValue, newRisk, newLot); ObjectSetString(0, OBJ_NAME_LOT, OBJPROP_TEXT, DoubleToString(newLot, LOT_DECIMALS)); } if(lastChanged != OBJ_NAME_LOT && lastChanged != OBJ_NAME_STOP_SIZE) { if(stopSize > 0 && pipValue > 0) { recalculateValues(stopSize, stopPrice, pipValue, newRisk, newLot); ObjectSetString(0, OBJ_NAME_LOT, OBJPROP_TEXT, DoubleToString(newLot, LOT_DECIMALS)); } } double upperLevel, lowerLevel; GetH1Levels(upperLevel, lowerLevel); Print("Рассчитаны уровни: UpperLevel = ", DoubleToString(upperLevel, (int)Digits()), " | LowerLevel = ", DoubleToString(lowerLevel, (int)Digits())); double proshivUpper = calculateProshivD1ForLevel(upperLevel); double proshivLower = calculateProshivD1ForLevel(lowerLevel); double proshivUpper4 = calculateProshivD1For4CandlesForLevel(upperLevel); double proshivLower4 = calculateProshivD1For4CandlesForLevel(lowerLevel); int dodgerCount = GetDodgerBlueLevelsCount(); if(ChartPeriod() == PERIOD_H1) { // Если только одна DodgerBlue-линия: if(dodgerCount == 1) { if(proshivUpper < 0) ObjectSetString(0, OBJ_VALUE_PROSHIVD1_UPPER, OBJPROP_TEXT, "-"); else ObjectSetString(0, OBJ_VALUE_PROSHIVD1_UPPER, OBJPROP_TEXT, DoubleToString(proshivUpper, 2) + "%"); ObjectSetString(0, OBJ_VALUE_PROSHIVD1_LOWER, OBJPROP_TEXT, "-"); // Для 4-свечного прошива всегда прочерк ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, OBJPROP_TEXT, "-"); ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, OBJPROP_TEXT, "-"); } else { // Для общего прошива: if(proshivUpper < 0) ObjectSetString(0, OBJ_VALUE_PROSHIVD1_UPPER, OBJPROP_TEXT, "-"); else ObjectSetString(0, OBJ_VALUE_PROSHIVD1_UPPER, OBJPROP_TEXT, DoubleToString(proshivUpper, 2) + "%"); if(proshivLower < 0) ObjectSetString(0, OBJ_VALUE_PROSHIVD1_LOWER, OBJPROP_TEXT, "-"); else ObjectSetString(0, OBJ_VALUE_PROSHIVD1_LOWER, OBJPROP_TEXT, DoubleToString(proshivLower, 2) + "%"); // Для 4-свечного прошива: если значение общего больше или равно, оставляем прочерк if(proshivUpper >= proshivUpper4) ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, OBJPROP_TEXT, "-"); else if(proshivUpper4 < 0) ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, OBJPROP_TEXT, "-"); else ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, OBJPROP_TEXT, DoubleToString(proshivUpper4, 2) + "%"); if(proshivLower >= proshivLower4) ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, OBJPROP_TEXT, "-"); else if(proshivLower4 < 0) ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, OBJPROP_TEXT, "-"); else ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, OBJPROP_TEXT, DoubleToString(proshivLower4, 2) + "%"); } } double blockHigh, blockLow; int blockCount; double overallRange = -1; if(GetMaxNestedRange(2, 4, 50, blockHigh, blockLow, blockCount)) overallRange = (double)ToPips(blockHigh) - (double)ToPips(blockLow); int numCandles = 4; double maxRange4 = -1; for(int i = 1; i <= numCandles; i++) { if(iTime(_Symbol, PERIOD_D1, i) == (datetime)0) { maxRange4 = -1; break; } double r = iHigh(_Symbol, PERIOD_D1, i) - iLow(_Symbol, PERIOD_D1, i); if(r > maxRange4) maxRange4 = r; } if(overallRange > (double)ToPips(maxRange4)) { ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_UPPER, OBJPROP_TEXT, "-"); ObjectSetString(0, OBJ_VALUE_PROSHIVD1_4C_LOWER, OBJPROP_TEXT, "-"); } double overallBlockHigh, overallBlockLow; int overallBlockCount; double overallBlockRange = -1; if(GetMaxNestedRange(2, 4, 50, overallBlockHigh, overallBlockLow, overallBlockCount)) overallBlockRange = (double)ToPips(overallBlockHigh) - (double)ToPips(overallBlockLow); if(overallBlockRange > 0) ObjectSetString(0, OBJ_VALUE_RANGE_D1, OBJPROP_TEXT, "есть"); else ObjectSetString(0, OBJ_VALUE_RANGE_D1, OBJPROP_TEXT, "нет"); saveValues(stopSize, stopPrice, newRisk, newLot); updating = false; } //------------------------------------------ // Функциональность для H4: панель выбора уровня void SaveSelectedLevel(int level) { GlobalVariableSet(gvNameSelectedLevel, level); SaveLevelToFile(level); // резервное сохранение в файл } int LoadSelectedLevel() { int level = LoadLevelFromFile(); if(level < 1) level = GlobalVariableCheck(gvNameSelectedLevel) ? (int)GlobalVariableGet(gvNameSelectedLevel) : 1; return level; } void CreateLevelSelectionInput() { if(ChartPeriod() != PERIOD_H4) return; if((int)ObjectFind(0, objNameSelectedLevel) >= 0) return; int savedLevel = LoadSelectedLevel(); ObjectCreate(0, objNameSelectedLevel, OBJ_EDIT, 0, iTime(_Symbol, PERIOD_H4, 0), SymbolInfoDouble(_Symbol, SYMBOL_BID)); ObjectSetInteger(0, objNameSelectedLevel, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_CORNER, (int)CORNER_LEFT_UPPER); ObjectSetInteger(0, objNameSelectedLevel, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_XDISTANCE, (int)10); ObjectSetInteger(0, objNameSelectedLevel, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_YDISTANCE, (int)10); ObjectSetString(0, objNameSelectedLevel, OBJPROP_TEXT, IntegerToString(savedLevel)); ObjectSetInteger(0, objNameSelectedLevel, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)TextColor); ObjectSetInteger(0, objNameSelectedLevel, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_FONTSIZE, (int)10); } void UpdateH4LevelColors() { if(ChartPeriod() != PERIOD_H4) return; string inputText = ((int)ObjectFind(0, objNameSelectedLevel) >= 0 ? ObjectGetString(0, objNameSelectedLevel, OBJPROP_TEXT) : "1"); int selected = (int)StringToInteger(inputText); if(selected < 1) selected = 1; if(selected > 10) selected = 10; SaveSelectedLevel(selected); string levels[]; int total = (int)ObjectsTotal(0); for (int i = 0; i < total; i++) { string name = ObjectName(0, i); if((int)ObjectGetInteger(0, name, OBJPROP_TYPE) == OBJ_HLINE && (StringFind(name, "Horizontal") >= 0)) { if((int)ObjectGetInteger(0, name, OBJPROP_COLOR) == (int)clrDodgerBlue) continue; int size = ArraySize(levels); ArrayResize(levels, size + 1); levels[size] = name; } } if(ArraySize(levels) == 0) return; int count = (int)ArraySize(levels); for (int i = 0; i < count - 1; i++) for (int j = i + 1; j < count; j++) if(ObjectGetDouble(0, levels[j], OBJPROP_PRICE) > ObjectGetDouble(0, levels[i], OBJPROP_PRICE)) { string tmp = levels[i]; levels[i] = levels[j]; levels[j] = tmp; } for (int i = 0; i < count; i++) { if(i == selected - 1) ObjectSetInteger(0, levels[i], (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)selectedColor); else ObjectSetInteger(0, levels[i], (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_COLOR, (int)unselectedColor); } } //------------------------------------------ // Обработчики событий int OnInit() { if(ChartPeriod() == PERIOD_H1) { loadInstrumentSpecs(); double sStop = 0, sPrice = 0, sRisk = 0, sLot = 0; loadValues(sStop, sPrice, sRisk, sLot); createPanel(); ObjectSetString(0, OBJ_NAME_STOP_SIZE, OBJPROP_TEXT, DoubleToString(sStop, 2)); ObjectSetString(0, OBJ_NAME_STOP_PRICE, OBJPROP_TEXT, DoubleToString(sPrice, 2)); ObjectSetString(0, OBJ_NAME_RISK_PERCENT, OBJPROP_TEXT, DoubleToString(sRisk, 2)); ObjectSetString(0, OBJ_NAME_LOT, OBJPROP_TEXT, DoubleToString(sLot, LOT_DECIMALS)); updateATRTextImmediate(ATRPeriod); recalculatePanel(); if((int)ObjectFind(0, objNameSelectedLevel) >= 0) ObjectDelete(0, objNameSelectedLevel); } if(ChartPeriod() == PERIOD_H4) { int savedLevel = LoadSelectedLevel(); SaveSelectedLevel(savedLevel); CreateLevelSelectionInput(); UpdateH4LevelColors(); ObjectSetInteger(0, objNameSelectedLevel, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_VISIBLE, (int)1); // Устанавливаем таймер для H4 EventSetTimer(1); } return INIT_SUCCEEDED; } void OnDeinit(const int reason) { if(ChartPeriod() == PERIOD_H1) deletePanel(); if(ChartPeriod() == PERIOD_H4 && (int)ObjectFind(0, objNameSelectedLevel) >= 0) { string sel = ObjectGetString(0, objNameSelectedLevel, OBJPROP_TEXT); SaveSelectedLevel(StringToInteger(sel)); ObjectDelete(0, objNameSelectedLevel); } // Останавливаем таймер для H4 EventKillTimer(); } void OnTick() { if(ChartPeriod() != PERIOD_H4) { if((int)ObjectFind(0, objNameSelectedLevel) >= 0) ObjectDelete(0, objNameSelectedLevel); } if(ChartPeriod() == PERIOD_H1) { if(ArraySize(Specs) == 0) if(!loadInstrumentSpecs()) { Print("ERROR: Спецификации не загружены."); return; } if((int)ObjectFind(0, OBJ_LABEL_STOP_SIZE) < 0) { double sStop = 0, sPrice = 0, sRisk = 0, sLot = 0; loadValues(sStop, sPrice, sRisk, sLot); createPanel(); ObjectSetString(0, OBJ_NAME_STOP_SIZE, OBJPROP_TEXT, DoubleToString(sStop, 2)); ObjectSetString(0, OBJ_NAME_STOP_PRICE, OBJPROP_TEXT, DoubleToString(sPrice, 2)); ObjectSetString(0, OBJ_NAME_RISK_PERCENT, OBJPROP_TEXT, DoubleToString(sRisk, 2)); ObjectSetString(0, OBJ_NAME_LOT, OBJPROP_TEXT, DoubleToString(sLot, LOT_DECIMALS)); updateATRTextImmediate(ATRPeriod); } updateATRTextOnM5Bar(ATRPeriod); recalculatePanel(); } else if(ChartPeriod() == PERIOD_H4) { if((int)ObjectFind(0, objNameSelectedLevel) >= 0) { string sel = ObjectGetString(0, objNameSelectedLevel, OBJPROP_TEXT); SaveSelectedLevel(StringToInteger(sel)); } UpdateH4LevelColors(); if((int)ObjectFind(0, objNameSelectedLevel) == -1) CreateLevelSelectionInput(); ObjectSetInteger(0, objNameSelectedLevel, (ENUM_OBJECT_PROPERTY_INTEGER)OBJPROP_VISIBLE, (int)1); } else { if((int)ObjectFind(0, objNameSelectedLevel) >= 0) ObjectDelete(0, objNameSelectedLevel); } } //------------------------------------------ // Таймер для H4 – проверяем и сохраняем значение выбранного уровня void OnTimer() { if(ChartPeriod() == PERIOD_H4) { if((int)ObjectFind(0, objNameSelectedLevel) >= 0) { string sel = ObjectGetString(0, objNameSelectedLevel, OBJPROP_TEXT); SaveSelectedLevel(StringToInteger(sel)); } } } //------------------------------------------ // Обработчики событий void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(ChartPeriod() == PERIOD_H1) { if(id == CHARTEVENT_OBJECT_ENDEDIT && (sparam == OBJ_NAME_STOP_SIZE || sparam == OBJ_NAME_STOP_PRICE || sparam == OBJ_NAME_RISK_PERCENT || sparam == OBJ_NAME_LOT)) { lastChanged = sparam; updateATRTextImmediate(ATRPeriod); recalculatePanel(); } } if(ChartPeriod() == PERIOD_H4) { if(id == CHARTEVENT_OBJECT_ENDEDIT && sparam == objNameSelectedLevel) { string inputText = ObjectGetString(0, objNameSelectedLevel, OBJPROP_TEXT); int selected = (int)StringToInteger(inputText); if(selected < 1) selected = 1; if(selected > 10) selected = 10; SaveSelectedLevel(selected); UpdateH4LevelColors(); } } }