//+------------------------------------------------------------------+ //| ZZ_Vol.mq4 | //+------------------------------------------------------------------+ #property copyright "Oleg Snegov" #property link "mailto:olegsng@gmail.com" #property version "1.00" #property strict #property script_show_inputs enum YesNo { YES = 1, //Учитывать NO = 0 //Не учитывать }; //-- Входные параметры extern string str1 = "-- Период расчета "; input datetime FromDate = D'2016.06.30 00:00'; // Расчет c даты input datetime ToDate = D'2018.05.01 00:00'; // Расчет по дату (включая дату) //-- Фильтр дней недели extern string str2 = "-- Фильтр дней недели "; input YesNo DoW0 = NO; // Расчет в воскресенье input YesNo DoW1 = YES; // Расчет в понедельник input YesNo DoW2 = YES; // Расчет во вторник input YesNo DoW3 = YES; // Расчет в среду input YesNo DoW4 = YES; // Расчет в четверг input YesNo DoW5 = YES; // Расчет в пятницу //--- Фильтр времени расчета внутри дня extern string str3 = "-- Внутридневной Фильтр "; input int StartHour = 0; // Первый час расчета внутри дня, с начала часа input int EndHour = 23; // Последний час расчета внутри дня, до конца часа //--- Параметры ZigZag extern string str4 = "-- Параметры ZigZag "; input int ZZ_Dept = 12; input int ZZ_Deviation = 5; input int ZZ_BackStep = 3; input int ZZ_TFrame = 5; //Таймфрейм ZZ; //--- Время //input datetime StartTime = D'2018.05.01 00:00'; //input datetime EndTime = D'2018.05.09 00:00'; //--- Глобальные переменные bool DaysWeek[]; int MainTF = PERIOD_D1; // жесткая привязка к D1 int HourTF = PERIOD_H1; // жесткая привязка к D1 //--- Расходники bool RightDayByFilter(int NumberOfDayBar, int &CurrentDayOfWeek) // Функция проверяет по фильтру - нужен ли расчет для этго бара { bool Result = false; MqlDateTime MqlTimeOfDayBar; //TimeOfDayBar = iTime(NULL, MainTF, NumberOfDayBar); TimeToStruct(iTime(NULL, MainTF, NumberOfDayBar), MqlTimeOfDayBar); CurrentDayOfWeek = MqlTimeOfDayBar.day_of_week; Result = DaysWeek[CurrentDayOfWeek]; //if (Result) CurrentDayOfWeek = MqlTimeOfDayBar.day_of_week; return(Result); } double ZZPeriodMotion(int FromHourBarNumber, int ToHourBarNumber) // bool ZZPeriodMotion(int FromHourBarNumber, int ToHourBarNumber, double &ZZMotion) // Функция расчета пробега зигзага за период FromHourBar - ToHourBar часовых баров { double ZZMotion = 0; datetime FromHourBarTime = iTime(NULL, HourTF, FromHourBarNumber); datetime ToHourBarTime = iTime(NULL, HourTF, ToHourBarNumber); int ZZToBarNumber = iBarShift(NULL, ZZ_TFrame, ToHourBarTime, false); int ZZFromBarNumber = iBarShift(NULL, ZZ_TFrame, FromHourBarTime, false); if (ZZToBarNumber == ZZFromBarNumber) { // попали на субботу-понедельник !!! 12.06.2018 return(ZZMotion); }; //if (ZZToBarNumber == ZZFromBarNumber) { // попали на субботу-понедельник datetime ZZTime = 0; //--- Ищем первый зигзаг int CurrentZZBar = ZZToBarNumber; // находим относительно последнего разрешенного часа в течении дня double FirstZigZag = 0; do { ZZTime = iTime(NULL, ZZ_TFrame/*HourTF*/, CurrentZZBar); FirstZigZag = iCustom(NULL, ZZ_TFrame, "ZigZag", ZZ_Dept, ZZ_Deviation, ZZ_BackStep, 0, CurrentZZBar); CurrentZZBar++; } while(!IsStopped() && FirstZigZag < 0.0001 && CurrentZZBar <= ZZFromBarNumber); //--- проверка на наличие, если нет - сорри, выход if (FirstZigZag < 0.00001) { // сказать MessageBox("Зигзаг не найден :\t\t" + TimeToStr(ZZTime, TIME_DATE|TIME_MINUTES)+ "\n", "Информация", MB_OK); ZZTime = 0; return(ZZMotion); }; double ToBarClosePrice = iOpen(NULL, HourTF, ToHourBarNumber); // Граничная цена - цена закрытия последнего разрешенного часа в течении дняона же цена открытия след часа // т.к. 24 считаем относ к тек дню, а МТ считает 00:00 след дня ZZMotion = MathAbs(FirstZigZag - ToBarClosePrice); //--- Ищем последний зигзаг CurrentZZBar = ZZFromBarNumber; // находим относительно первого разрешенного часа в течении дня, у АМ нет свечи М5 00:00, после 23:55 идет 00:05, у Робо свеча М5 00:00 есть double LastZigZag = 0; do { ZZTime = iTime(NULL, ZZ_TFrame/*HourTF*/, CurrentZZBar); LastZigZag = iCustom(NULL, ZZ_TFrame, "ZigZag", ZZ_Dept, ZZ_Deviation, ZZ_BackStep, 0, CurrentZZBar); CurrentZZBar--; } while(!IsStopped() && LastZigZag < 0.0001 && CurrentZZBar >= ZZToBarNumber); double FromBarOpenPrice = iOpen(NULL, HourTF, FromHourBarNumber); // Граничная цена - цена закрытия открытия первого разрешенного часа в течении дня ZZMotion = ZZMotion + MathAbs(LastZigZag - FromBarOpenPrice); //--- И проход по всем зигзагам double NextZigZag = 0; do { ZZTime = iTime(NULL, ZZ_TFrame, CurrentZZBar); NextZigZag = iCustom(NULL, ZZ_TFrame, "ZigZag", ZZ_Dept, ZZ_Deviation, ZZ_BackStep, 0, CurrentZZBar); if (NextZigZag > 0.0001) { ZZMotion = ZZMotion + MathAbs(LastZigZag - NextZigZag); LastZigZag = NextZigZag; } // if (NextZigZag > 0.0001) { CurrentZZBar--; } while(!IsStopped() && CurrentZZBar >= ZZToBarNumber); return(ZZMotion); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { int FirstHistoryBar = iBars(Symbol(), ZZ_TFrame); datetime FirstHistoryDate = iTime(Symbol(), ZZ_TFrame, FirstHistoryBar-1); // Если FromDate if (FromDate < FirstHistoryDate) { MessageBox("Первая известная котировка\t" + (string)FirstHistoryDate + "\n" + "меньше начальной даты\t\t" + (string)FromDate + ".\n\n" + "Загрузите котировки !!!", "Информация", MB_OK ); return; } //--- Рассчитываем множитель int Mult = 100; if((Digits==3) || (Digits==5) || (StringFind(Symbol(),"XAU") > -1) || (StringFind(Symbol(),"GOLD") > -1)) { Mult *= 10; }; ArrayResize(DaysWeek, 6); ArrayFill(DaysWeek, 0, 6, true); // Первично - все дни в расчете if (DoW0 == NO) {DaysWeek[0] = false;} if (DoW1 == NO) {DaysWeek[1] = false;} if (DoW2 == NO) {DaysWeek[2] = false;} if (DoW3 == NO) {DaysWeek[3] = false;} if (DoW4 == NO) {DaysWeek[4] = false;} if (DoW5 == NO) {DaysWeek[5] = false;} int FromDayBar = iBarShift(NULL, MainTF, FromDate, false); // жесткая привязка к D1 int ToDayBar = iBarShift(NULL, MainTF, ToDate, false); // проверка на наличие баров на ZZ_TFrame для диапазона FromDayBar - ToDayBar //iBars int CurrentD1Bar; datetime TimeD1Bar; int FromHourBar; int ToHourBar; double DayHi = 0; double DayLo = 0; int DayWeek = 0; double ZZMotion = 0; int ptZZMotion = 0; double ADR = 0; int ptAdr = 0; //double SSS = 0; string CsvFileName = Symbol() + "_ZZ_" + TimeToStr(FromDate,TIME_DATE) + "_" + TimeToStr(ToDate,TIME_DATE) +".csv"; if (FileIsExist(CsvFileName)) FileDelete(CsvFileName); int CsvHandle = FileOpen(CsvFileName, FILE_READ|FILE_WRITE|FILE_CSV); /* ((C) Star ) Структура записи файла в первом приближении может быть такой: 1) символ 2) дата ГГГГММДД с или без разделяющих точек или тире 3) первый час внутридневного диапазона. Дефолтно 00 - с открытия суток 4) последний час внутридневного диапазона. Дефолтно 23 - до последней минуты суток включительно. 5) день недели - 1, 2, 3, 4, 5 6) ДТД целочисленное (пипсы) - всегда абсолютное значение (хай-лоу) дня 7) ДВП целочисленное (пипсы) - сумма за весь день или выбранный интервал времени внутри дня 8) КДВ с округлением до 3-х знаков после запятой. */ if (CsvHandle != INVALID_HANDLE) { FileSeek(CsvHandle, 0, SEEK_END); FileWrite(CsvHandle, "Символ", "Дата", "Первый час","Последний час", "День недели", "ДТД", "ДВП", "КДВ", "DayHi", "DayLo"); } else { string ErrorStr = "Ошибка открытия файла " + CsvFileName + " №: " + (string)GetLastError(); Print(ErrorStr); // if (CsvHandle != INVALID_HANDLE) MessageBox(ErrorStr, "Информация", MB_OK); return; }; // if else (CsvHandle != INVALID_HANDLE) for (CurrentD1Bar = FromDayBar; CurrentD1Bar > ToDayBar - 1; CurrentD1Bar--) { TimeD1Bar = iTime(NULL, MainTF, CurrentD1Bar); if (RightDayByFilter(CurrentD1Bar, DayWeek)) { // день подходит // определение периода внутри дня, может быть только один период FromHourBar = iBarShift(NULL, HourTF, TimeD1Bar, false); //ToHourBar = FromHourBar - EndHour; // в связи с указанием граничного времени до 23:00 в понимании 23:59 (до 00:00) ToHourBar = FromHourBar - (EndHour + 1); FromHourBar = FromHourBar + StartHour; ZZMotion = ZZPeriodMotion(FromHourBar, ToHourBar); if (ZZMotion > 0.00) { DayHi = iHigh(NULL, MainTF, CurrentD1Bar); DayLo = iLow(NULL, MainTF, CurrentD1Bar); ADR = DayHi - DayLo; //Вывод в файл if (CsvHandle != INVALID_HANDLE) { FileSeek(CsvHandle, 0, SEEK_END); FileWrite(CsvHandle, Symbol(), TimeToStr(TimeD1Bar,TIME_DATE), IntegerToString(StartHour, 2),IntegerToString(EndHour, 2), IntegerToString(DayWeek, 1), IntegerToString(MathRound(ADR * Mult), 5), //"ДТД" IntegerToString(MathRound(ZZMotion * Mult), 5), //"ДВП" DoubleToStr(ZZMotion / ADR, 3), //"КДВ" DoubleToStr(DayHi, 5), //DayHi DoubleToStr(DayLo, 5)); //DayLo }; // if (CsvHandle != INVALID_HANDLE) { }; // if (ZZMotion > 0.00) { }; // if (RightDayByFilter(CurrentD1Bar, DayWeek)) { // день подходит } // for (int CurrentBar = ToBar; CurrentBar < FromBar; CurrentBar) { if (CsvHandle != INVALID_HANDLE) FileClose(CsvHandle); MessageBox("Расчет окончен", "Информация", MB_OK); return; }