Смотри, как бесплатно скачать роботов
Ищи нас в Telegram!
Ставь лайки и следи за новостями
Интересный скрипт?
Поставь на него ссылку - пусть другие тоже оценят
Понравился скрипт?
Оцени его работу в терминале MetaTrader 5
Советники

Download all ticks of a symbol's history - эксперт для MetaTrader 5

Просмотров:
98
Рейтинг:
(4)
Опубликован:
2025.06.18 12:06
MQL5 Фриланс Нужен робот или индикатор на основе этого кода? Закажите его на бирже фрилансеров Перейти на биржу

Код этого эксперта просканирует рыночные часы брокера пользователя и извлечет символы, для которых загрузит все доступные тики или тики до определенной даты.

Это может помочь вам загрузить всю историю символов для бэктеста или создать пользовательский график на основе этих тиков.

Терминалы будут кэшировать тики в папке с данными, поэтому убедитесь, что у вас достаточно места на жестком диске.

Чтобы облегчить загрузку символов, нам понадобится менеджер загрузки.

Структура CDownloadManager содержит всю информацию, которую нам нужно сохранить.

struct CDownloadManager
  {
   bool              m_started,m_finished;
   string            m_symbols[],m_current;
   int               m_index;

  • состояние загрузки (начата/закончена)
  • список символов для сканирования
  • текущий символ
  • и индекс сканируемого символа.

Нам также понадобится читать и записывать данные на жесткий диск, и поскольку мы работаем с символами, мы создадим 2 быстрые функции для записи и чтения строк из бинарных файлов.

Функция сохранения строки в файл:

void writeStringToFile(int f,string thestring)
  {
//сохраните строку символов
   char sysave[];
   int charstotal=StringToCharArray(thestring,sysave,0,StringLen(thestring),CP_ACP);
   FileWriteInteger(f,charstotal,INT_VALUE);
   for(int i=0;i<charstotal;i++)
     {
      FileWriteInteger(f,sysave[i],CHAR_VALUE);
     }
  }

Она получает :

  • хэндл файла f, открытого для записи, и бинарные флаги FILE_WRITE|FILE_BIN
  • строку для записи в файл.

Она записывает целое число длины, показывающее, сколько символов в строке, а затем сохраняет каждый символ в строке.

Функция загрузки строки из файла:

string readStringFromFile(int f)
  {
   string result="";
// загрузите строку символов
   char syload[];
   int charstotal=(int)FileReadInteger(f,INT_VALUE);
   if(charstotal>0)
     {
      ArrayResize(syload,charstotal,0);
      for(int i=0;i<charstotal;i++)
        {
         syload[i]=(char)FileReadInteger(f,CHAR_VALUE);
        }
      result=CharArrayToString(syload,0,charstotal,CP_ACP);
     }
   return(result);
  }

Получает:

  • хэндл файла f файла, открытого для чтения в двоичном виде , флаги FILE_READ|FILE_BIN

Считывается целое число длины, указывающее, сколько символов ожидается в данной точке файла. Далее происходит считывание каждого символа в массив char и создание строки из этого массива char, которая возвращается как результат загрузки в виде строки.

Вернемся к структуре CDownloadManager. Нам нужен способ инициализации менеджера и его наполнения из маркет-чата:

   //+------------------------------------------------------------------+
   //| Захватывайте символы с рынка.|
   //+------------------------------------------------------------------+
   void              grab_symbols()
     {
      //! только с mw!
      int s=SymbolsTotal(true);
      ArrayResize(m_symbols,s,0);
      for(int i=0;i<ArraySize(m_symbols);i++)
        {
         m_symbols[i]=SymbolName(i,true);
        }
     }

Довольно просто:

  • запрашиваем, сколько символов находится в списке (активных)
  • изменить размер нашего массива m_symbols, чтобы получить их
  • зацикливаемся на общем количестве символов и запрашиваем название символа

Мы также отвечаем за управление загрузкой данных о символах, поэтому нам понадобится функция, которая, по сути, является менеджером:

   //+------------------------------------------------------------------+
   //| Управление процессом загрузки символов|
   //+------------------------------------------------------------------+
   void              manage(string folder,string filename)
     {
      //по сути, это запуск или переход к следующему символу
      //если установлен
      if(ArraySize(m_symbols)>0)
        {
         //если не запущен
         if(!m_started)
           {
            m_started=true;
            //переход к первому символу
            m_current=m_symbols[0];
            m_index=1;
            save(folder,filename);
            if(_Symbol!=m_current)
              {
               ChartSetSymbolPeriod(ChartID(),m_current,_Period);
              }
            else
              {
               ENUM_TIMEFRAMES new_period=PERIOD_M1;
               for(int p=0;p<ArraySize(TFS);p++)
                 {
                  if(_Period!=TFS[p])
                    {
                     new_period=TFS[p];
                     break;
                    }
                 }
               ChartSetSymbolPeriod(ChartID(),m_current,new_period);
              }
            return;
           }
         //если начато
         else
           {
            m_index++;
            if(m_index<=ArraySize(m_symbols))
              {
               m_current=m_symbols[m_index-1];
               save(folder,filename);
               if(_Symbol!=m_current)
                 {
                  ChartSetSymbolPeriod(ChartID(),m_current,_Period);
                 }
               return;
              }
            else
              {
               m_finished=true;
               FileDelete(folder+"\\"+filename);
               Print("Finished");
               ExpertRemove();
               return;
              }
           }
        }
      else
        {
         Print("Please grab symbols first");
        }
      //если набор заканчивается здесь
     }

Как работает система:

  • Открывается график, нам нужен 1 график, устанавливается таймер.
  • Таймер выполняется, мы отменяем таймер.
  • Мы проверяем, является ли это новая загрузка или продолжающаяся загрузка.
  • Если это новая загрузка, мы устанавливаем ее, захватывая все символы.
  • Если это продолжающаяся загрузка, мы загружаем данные для текущего символа.

Это часть кода, выполняющая загрузку по таймеру:

//+------------------------------------------------------------------+
//|Таймер|
//+------------------------------------------------------------------+
void OnTimer()
  {
//--- если синхронизированы
   if(SymbolIsSynchronized(_Symbol)&&TerminalInfoInteger(TERMINAL_CONNECTED)==1)
     {
      EventKillTimer();
      //--- загрузите систему здесь
      if(MANAGER.load(MANAGER_FOLDER,MANAGER_STATUS_FILE))
        {
         //--- система загружена, поэтому мы сканируем символ здесь
         Comment("System loaded and we are processing "+MANAGER.m_current);
         //--- загрузка тика

         //--- сначала найдите самый старый тик, доступный в брокере
         int attempts=0;
         int ping=-1;
         datetime cursor=flatten(TimeTradeServer());
         long cursorMSC=((long)cursor)*1000;
         long jump=2592000000;//60*60*24*30*1000;

         MqlTick receiver[];
         long oldest=LONG_MAX;
         Comment("PleaseWait");
         while(attempts<5)
           {
            ping=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,cursorMSC,1);
            if(ping==1)
              {
               if(receiver[0].time_msc==oldest)
                 {
                  attempts++;
                 }
               else
                 {
                  attempts=0;
                 }
               if(receiver[0].time_msc<oldest)
                 {
                  oldest=receiver[0].time_msc;
                 }
               cursorMSC-=jump;
               if(limitDate&&receiver[0].time<=oldestLimit)
                 {
                  break;
                 }
              }
            else
              {
               attempts++;
              }

            Sleep(44);
            Comment("Oldest Tick : "+TimeToString((datetime)(oldest/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+"\nCursor("+TimeToString((datetime)(cursorMSC/1000),TIME_DATE|TIME_MINUTES|TIME_SECONDS)+")\nAttempts("+IntegerToString(attempts)+")\nPlease wait for response...");
           }
         //--- в этот момент у нас есть самый старый тик
         //--- начните запрашивать тики от самого старого к самому новому
         if(oldest!=LONG_MAX)
           {
            ArrayFree(receiver);
            datetime newest_tick=0;
            //--- получаем время последнего тика для этого символа, хранящееся в symbol_time
            datetime most_recent_candle=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
            while(newest_tick<most_recent_candle)
              {
               //--- запросите новую партию, начиная с самого старого времени с указанным лимитом тиков
               int pulled=CopyTicks(_Symbol,receiver,COPY_TICKS_ALL,oldest,tick_packets);
               if(pulled>0)
                 {
                  //--- если мы получим новую партию, обновите время загрузки.
                  newest_tick=receiver[pulled-1].time;
                  oldest=receiver[pulled-1].time_msc;
                  ArrayFree(receiver);
                 }
               //--- таймаут запросов к серверу, измените его, если хотите
               Sleep(44);
               Comment("Pulled up to "+TimeToString(newest_tick,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" so far");
              }
           }
         else
           {
            Alert("Please close the terminal \n head over to the ticks folder \n and delete the empty folders");
            ExpertRemove();
           }
         //--- обновите менеджера и двигайтесь дальше
         MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE);
        }
      else
        {
         //--- захватите символы наблюдения за рынком, чтобы начать загрузку
         Comment("Grabbing MW and starting");
         MANAGER.grab_symbols();
         MANAGER.manage(MANAGER_FOLDER,MANAGER_STATUS_FILE);
        }
     }
  }


Перевод с английского произведен MetaQuotes Ltd.
Оригинальная публикация: https://www.mql5.com/en/code/56324

Цветная гистограмма MACD Цветная гистограмма MACD

Цветная гистограмма MACD - это усовершенствованная версия классического индикатора MACD (Moving Average Convergence Divergence), разработанная для более четкого и интуитивно понятного визуального анализа рыночного импульса. Этот индикатор сочетает в себе традиционные функции MACD с динамической гистограммой, которая меняет цвет в зависимости от соотношения между линией MACD и сигнальной линией, позволяя трейдерам быстро определять тренды, точки разворота и моменты нерешительности на рынке.

Multiple EA Tracking with a Magic Number Based Profit and Loss Live Dashboard in MQL5 Multiple EA Tracking with a Magic Number Based Profit and Loss Live Dashboard in MQL5

Независимо от того, работаете ли вы с несколькими торговыми роботами одновременно или только с одной сложной стратегией, отслеживание работы каждого советника может занять немало времени. MetaTrader 5 (MT5) удобно отображает ордера и позиции в "Инструментарии", но когда на одном счете работает несколько роботов, становится сложнее понять, какой советник приносит вам прибыль или убытки. На одном счете могут быть десятки или сотни сделок, каждая из которых открыта разными советниками, поэтому трудно отделить результаты работы одного робота от другого.

Useful #define statements Useful #define statements

Это несколько операторов #define, которые полезны для выполнения операций в вашем советнике. Вам нужно только присвоить имя переменным в начале файла, а затем позволить другим операторам #define выполнять свою работу. Чтобы использовать этот файл, добавьте #include <DEFINE_statements.mqh> в первую строку вашего EA-файла.

Self Optimized SMA Self Optimized SMA

Индикатор строит две линии. Нижняя линия рассчитывается на основе последнего периода SMA, который вызвал отскок вверх. Верхняя линия рассчитывается по последнему периоду SMA, который вызвал отскок вниз.