#include <Работа с файлами.mqh> int init() { ВыполнитьВыгрузку(); //бесконечная процедура, прерываемая удалением эксперта из окна графика } int start() { ВыполнитьВыгрузку(); //если мы здесь, значит по какой-то причине работа эксперта прервалась - чего быть не должно } void ВыполнитьВыгрузку() { // ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ //служебные общие bool ДанныеОбновлены; bool РезультатОбработки; int ПозицияПоиска; int ПозицияПоискаРазделителя; string Текст; int Счетчик; int Результат; int ВремяПоследнейКотировки; string ВремяОбновления; int СчетчикЗацикливания; int ТекЧас,ТекМинута; int ВремяСна,НачалоСна,ОкончаниеСна; //ключевые int РезультатИнициализации; string ИмяФайла; int КоличествоПериодов; string КодИнструмента; string КодПериодичности; string СтрокаКотировок; // ОСНОВНАЯ ПРОГРАММА while (true) // в этом цикле ожидаем обновление котировок { ТекЧас = Hour(); ТекМинута = Minute(); // проверим, а не пора ли спать? проверять файл нужно каждый раз, ибо файл теоретически может измениться в любой момент ВремяСна = 0; НачалоСна = 0; ОкончаниеСна = 0; Текст = ПрочитатьЗначение("Обмен/! Сон.csv",1); if (Текст != "-1" // удалось прочитать файл && Текст != "") // и в строке есть некая запись { НачалоСна = StrToInteger(Текст)*60+StrToInteger(ПрочитатьЗначение("Обмен/! Сон.csv",2)); // в минутах от 00:00 } Текст = ПрочитатьЗначение("Обмен/! Сон.csv",3); if (Текст != "-1" // удалось прочитать файл && Текст != "") // и в строке есть некая запись { ОкончаниеСна = StrToInteger(Текст)*60+StrToInteger(ПрочитатьЗначение("Обмен/! Сон.csv",4)); // в минутах от 00:00 } if (НачалоСна != 0 && ОкончаниеСна != 0) //время сна задано, надо сравнить интервалы { if (ТекЧас*60+ТекМинута >= НачалоСна) //возможно пора спать { if (НачалоСна < ОкончаниеСна && ТекЧас*60+ТекМинута < ОкончаниеСна) ВремяСна = ОкончаниеСна - (ТекЧас*60+ТекМинута); if (НачалоСна > ОкончаниеСна) ВремяСна = ОкончаниеСна + (24-ТекЧас-1)*60 + (60-ТекМинута); } else //ТекЧас*60+ТекМинута < НачалоСна //возможно рано проснулись { if (НачалоСна > ОкончаниеСна && ТекЧас*60+ТекМинута < ОкончаниеСна) ВремяСна = ОкончаниеСна - (ТекЧас*60+ТекМинута); } } if (ВремяСна != 0) { ВремяСна = (ВремяСна - 1)*60 + (60-Seconds()); // теперь в секундах Comment("Спим с "+ПрочитатьЗначение("Обмен/! Сон.csv",1)+":"+ПрочитатьЗначение("Обмен/! Сон.csv",2)+" до "+ПрочитатьЗначение("Обмен/! Сон.csv",3)+":"+ПрочитатьЗначение("Обмен/! Сон.csv",4)); Sleep(ВремяСна*1000); } // проверили, не нужно ли спать Comment("Ожидание обновления..."); ДанныеОбновлены = RefreshRates(); if (!ДанныеОбновлены) continue; // котировки не обновились ВремяОбновления = TimeToStr(TimeCurrent(),TIME_DATE|TIME_SECONDS); // Обработка файла инициализации Comment("Инициализация"); while (true) //будем пытаться открыть файл бесконечно, пока он не откроется { РезультатИнициализации = FileOpen("Обмен\! Выгрузка.csv", FILE_CSV|FILE_READ); if (РезультатИнициализации == 1) break; } while (true) { if (FileIsEnding(РезультатИнициализации)) break; //это последняя строка ИмяФайла = FileReadString(РезультатИнициализации); //читает до разделителя ; if (StringLen(ИмяФайла) == 0) continue; // пустая строка // Количество периодов для выгрузки КоличествоПериодов = 0; Comment("Чтение \"Обмен/"+ИмяФайла+".csv\""); Текст = ПрочитатьЗначение("Обмен/"+ИмяФайла+".csv",1); if (Текст != "-1" // удалось прочитать файл && Текст != "" // и в первой строке есть некая запись && StringSubstr(Текст,0,21) == "Количество периодов: ") // и эта запись - идентификатор запроса периодов { Текст = StringSubstr(Текст,21); if (Текст == "Все") {КоличествоПериодов = 16383;} //максимально возможное количество else { КоличествоПериодов = StrToInteger(Текст); if (КоличествоПериодов > 16383) КоличествоПериодов = 16383; //максимальное возможное количество } //количество периодов для выгрузки FileDelete("Обмен/"+ИмяФайла+".csv"); //файл будем перезаписывать, иначе каждый раз будут выгружаться ненужные периоды } // Преобразуем имя файла в код инструмента и ТФ ПозицияПоиска = StringFind(ИмяФайла,","); ПозицияПоискаРазделителя = StringFind(ИмяФайла,";"); if (ПозицияПоиска == 0) continue; //это какой-то некорректный идентификатор КодИнструмента = StringSubstr(ИмяФайла,0,ПозицияПоиска); КодПериодичности = StringSubstr(ИмяФайла,ПозицияПоиска+1,ПозицияПоискаРазделителя); Comment("Проверка факта обновления \""+КодИнструмента+"\""); ВремяПоследнейКотировки = MarketInfo(КодИнструмента,MODE_TIME); if (ВремяПоследнейКотировки == 0) continue; // обновилась другая котировка, или инструмент отсутствует в окне "Обзор рынка". if (ВремяОбновления != TimeToStr(ВремяПоследнейКотировки,TIME_DATE|TIME_SECONDS)) continue; //обновилась какая-то другая котировка // Выгружаем Comment("Запись "+КодИнструмента+":"+КодПериодичности); for (Счетчик=КоличествоПериодов; Счетчик >= 0; Счетчик--) { СтрокаКотировок = ВремяОбновления + ";"; if (КодПериодичности == "M1") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_M1, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_M1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_M1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_M1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_M1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_M1, Счетчик) + ";"; } if (КодПериодичности == "M5") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_M5, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_M5, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_M5, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_M5, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_M5, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_M5, Счетчик) + ";"; } if (КодПериодичности == "M15") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_M15, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_M15, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_M15, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_M15, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_M15, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_M15, Счетчик) + ";"; } if (КодПериодичности == "M30") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_M30, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_M30, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_M30, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_M30, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_M30, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_M30, Счетчик) + ";"; } if (КодПериодичности == "H1") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_H1, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_H1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_H1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_H1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_H1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_H1, Счетчик) + ";"; } if (КодПериодичности == "H4") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_H4, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_H4, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_H4, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_H4, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_H4, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_H4, Счетчик) + ";"; } if (КодПериодичности == "D1") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_D1, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_D1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_D1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_D1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_D1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_D1, Счетчик) + ";"; } if (КодПериодичности == "W1") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_W1, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_W1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_W1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_W1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_W1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_W1, Счетчик) + ";"; } if (КодПериодичности == "MN1") { СтрокаКотировок = СтрокаКотировок + TimeToStr(iTime(КодИнструмента, PERIOD_MN1, Счетчик),TIME_DATE|TIME_SECONDS) + ";"; СтрокаКотировок = СтрокаКотировок + iOpen(КодИнструмента, PERIOD_MN1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iHigh(КодИнструмента, PERIOD_MN1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iLow(КодИнструмента, PERIOD_MN1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iClose(КодИнструмента, PERIOD_MN1, Счетчик) + ";"; СтрокаКотировок = СтрокаКотировок + iVolume(КодИнструмента, PERIOD_MN1, Счетчик) + ";"; } if (StringLen(СтрокаКотировок) <= 20) continue; //строка содержит только текущее время = котировки не заполнены / такая периодичность не используется Результат = GetLastError(); if (Результат != 0) ОбработкаРезультата("Формирование котировок "+КодИнструмента); СчетчикЗацикливания = 0; while (true) { СчетчикЗацикливания++; if (СчетчикЗацикливания == 1000000) break; //от зацикливания РезультатОбработки = ЗаписатьСтроку("Обмен/"+ИмяФайла+".csv", СтрокаКотировок); if (РезультатОбработки) break; } Comment("Успешно записан \"Обмен/"+ИмяФайла+".csv\""); } } //обработка файла инициализации FileClose(РезультатИнициализации); } //обработали изменение котировок } void ОбработкаРезультата(string Операция) { string ТекстОшибки = GetLastError(); ЗаписатьОшибку(ТекстОшибки+";"+Операция); } void ЗаписатьОшибку(string ТекстОшибки) { bool РезультатОбработки; int СчетчикЗацикливания = 0; while (true) { СчетчикЗацикливания++; if (СчетчикЗацикливания == 1000000) break; //от зацикливания РезультатОбработки = ЗаписатьСтроку("Обмен/! Ошибки.csv", TimeToStr(TimeCurrent(),TIME_DATE|TIME_MINUTES) + ";" + ТекстОшибки); if (РезультатОбработки) break; //ошибку записали успешно } }