//+------------------------------------------------------------------+ //| CurrencyIndex.mqh | //| Copyright 2000-2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2000-2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #define SECONDS_IN_DAY (24*60*60) // количество секунд в сутках #define SECONDS_IN_MINUTE 60 // количество секунд в минуте #define MSECS_IN_MINIUTE (60*1000) // количество миллисекунд в минуте //--- структура символа корзины struct SymbolWeight { string symbol; // символ double weight; // вес }; //--- структура исторических данных struct str_rates { int index; // индекс данных MqlRates rates[]; // массив исторических данных }; //--- структура тиковых данных struct str_ticks { int index; // индекс данных MqlTick ticks[]; // массив тиков }; //--- перечисление типов цен enum ENUM_RATES_VALUES { VALUE_OPEN, // цена Open VALUE_HIGH, // цена High VALUE_LOW, // цена Low VALUE_CLOSE // цена Close }; int ExtDigits=5; // точность измерения цены символа //+------------------------------------------------------------------+ //| Обработка тиков | //+------------------------------------------------------------------+ void ProcessTick(const string custom_symbol) { static long last_time_msc=0; // время в миллисекундах последнего тика static MqlTick synth_tick[1]; // структура последнего тика синтетического инструмента static MqlTick ticks[BASKET_SIZE]; // массив данных последних тиков корзины символов static MqlTick tick; // вспомогательная переменная для получения данных и поиска времени int success_cnt=0; int change_cnt=0; //--- инициализируем время тика синтетического символа synth_tick[0].time=0; //--- в цикле по количеству символов в корзине инструментов for(int i=0; i=0) { //--- если график открыт - сообщаем об этом в журнал, ставим флаг найденного графика и выходим из цикла поиска if(ChartSymbol(chart_id)==symbol) { found=true; Print(symbol," chart found"); break; } //--- на основании текущего выбранного графика получаем идентификатор следующего для очередной итерации поиска в цикле chart_id=ChartNext(chart_id); } //--- если график символа не найден среди открытых графиков if(!found) { //--- сообщаем об открытии графика M1 пользовательского символа, //--- получаем идентификатор открываемого графика и переходим на него Print("open chart ",symbol,",M1"); chart_id=ChartOpen(symbol,PERIOD_M1); ChartSetInteger(chart_id,CHART_BRING_TO_TOP,true); } } //--- пользовательский символ инициализирован return(is_custom); } //+------------------------------------------------------------------+ //| Подготовка исторических данных | //+------------------------------------------------------------------+ bool PrepareRates(const string custom_symbol) { str_rates symbols_rates[BASKET_SIZE]; int i,reserve=0; MqlRates usdx_rates[]; // массив-таймсерия синтетического инструмента MqlRates rate; // данные одного бара синтетического инструмента datetime stop=(TimeCurrent()/SECONDS_IN_MINUTE)*SECONDS_IN_MINUTE; // время бара M1 конечной даты datetime start=stop-31*SECONDS_IN_DAY; // время бара M1 начальной даты datetime start_date=0; //--- копируем исторические данные M1 за месяц для всех символов корзины инструментов start/=SECONDS_IN_DAY; start*=SECONDS_IN_DAY; // время бара D1 начальной даты for(i=0; i0 && j0) { if(!IsStopped()) { int cnt=CustomRatesReplace(custom_symbol,usdx_rates[0].time,usdx_rates[ArraySize(usdx_rates)-1].time+1,usdx_rates); Print(cnt," ",custom_symbol,",M1 rates from ",usdx_rates[0].time," to ",usdx_rates[ArraySize(usdx_rates)-1].time," added"); } } //--- успешно return(true); } //+------------------------------------------------------------------+ //| Подготовка последних тиков | //+------------------------------------------------------------------+ void PrepareLastTicks(const string custom_symbol) { str_ticks symbols_ticks[BASKET_SIZE]; int i,j,cnt,reserve=0; MqlTick usdx_ticks[]; // массив тиков синтетического инструмента MqlTick tick={0}; // данные одного тика синтетического инструмента long time_to=TimeCurrent()*1000; // время конца тиковых данных в миллисекундах long start_date=(time_to/MSECS_IN_MINIUTE)*MSECS_IN_MINIUTE; // время открытия бара в миллисекундах со временем TimeCurrent() long time_from=start_date-MSECS_IN_MINIUTE; // время начала копирования тиковых данных в миллисекундах //--- если были тики за последнюю минуту if(SymbolInfoTick(custom_symbol,tick) && tick.time_msc>=start_date) { Print(custom_symbol," last tick at ",datetime(tick.time_msc/1000),":",IntegerToString(tick.time_msc%1000,3,'0')); str_rates symbols_rates[BASKET_SIZE]; bool copy_error=false; //--- в цикле по количеству символов в корзине инструментов for(i=0; i=ArraySize(symbols_ticks[0].ticks)) { Print("no ticks at ",datetime(start_date/1000),":",IntegerToString(start_date%1000,3,'0')," (",start_date/1000,")" ); return; } symbols_ticks[0].index=j; long time_msc=symbols_ticks[0].ticks[j].time_msc; for(i=1; i0 && j0) { Print(array_size," ticks from ",usdx_ticks[0].time,":",IntegerToString(usdx_ticks[0].time_msc%1000,3,'0')," prepared"); cnt=CustomTicksAdd(custom_symbol,usdx_ticks); if(cnt>0) Print(cnt," ticks applied"); else Print("no ticks applied"); } } //+------------------------------------------------------------------+ //| Расчёт цен и объёмов синтетического инструмента | //+------------------------------------------------------------------+ bool CalculateRate(MqlRates& rate,str_rates& symbols_rates[]) { double values[BASKET_SIZE]={0}; long tick_volume=0; int i; //--- получаем цены Open всех символов корзины инструментов в массив values[] for(i=0; irate.open) rate.low=rate.open; if(rate.highrate.close) rate.low=rate.close; //--- всё успешно return(true); } //+------------------------------------------------------------------+ //| Возвращает значение тика | //+------------------------------------------------------------------+ double GetTickValue(str_ticks &symbol_ticks,long time_msc) { double value=0; //--- если индекс данных, записанный в структуре symbol_ticks, находится в пределах массива тиков структуры if(symbol_ticks.index