HistoryDownloader

Download script
Author: � xp3rienced
HistoryDownloader

This script is designed to automatically fetch and load historical price data (quotes) into your trading chart. Instead of requiring the user to manually scroll back through months or years of data, it automates this process until a specific date in the past is reached.

Core Functionality

The tool works by simulating keyboard inputs. It sends a "HOME" key command to the trading platform, which usually forces the chart to jump to its earliest available data point. The script then repeats this action systematically, pulling in new batches of history until it reaches the target date you have specified in the settings.

How It Works Internally

  • Targeting: You define a "Limit Date" (e.g., 01.01.2009). The script will keep downloading data until the chart history covers that specific point in time.
  • Monitoring: It constantly monitors the chart to see if new bars (price candles) have actually appeared. If it detects that the chart has updated, it resets its internal error counter and continues.
  • Safety Mechanisms:
    • Timeout: If the platform takes too long to load the next set of data, the script recognizes this as a delay and waits.
    • Failure Limit: To prevent the script from getting stuck in an infinite loop (for example, if there is no more data available or the connection is lost), it includes a "Max Fails" setting. If it fails to load new data multiple times in a row, it will stop automatically.
  • Visual Feedback: While the process is running, the script provides a real-time status update on your chart screen. This shows you exactly how many bars have been loaded so far, the current date being reached, and the time elapsed during the operation.

Key Requirements for Use

For this script to function correctly, certain environment conditions must be met:

  1. Auto-Scroll: The "Auto-Scroll" feature of your trading platform must be turned off.
  2. Chart Limits: Your platform's global settings must be configured to allow a high enough maximum number of bars in the history window.
  3. Helper Indicator: A specific companion indicator (HistoryDownloaderI) must be active on the chart. This is necessary because the script relies on shared data (global variables) from that indicator to "see" the total count of bars and the exact time of the first visible candle.

Summary of User Experience

Once you attach the script and set your desired date, it handles the tedious work of "scrolling" for you. It will alert you once the download is complete, informing you of the total number of bars successfully loaded and the total time taken to perform the task.

Miscellaneous
It issuies visual alerts to the screen
7 Views
0 Downloads
0 Favorites
HistoryDownloader
// +——————————————————————————————————————————————————————————————————————————————————————————————+
// ¦     History Downloader Expert                                          HistoryDownloader.mq4 ¦
// ¦  Ñîâåòíèê äëÿ çàãðóçêè â òåêóùèé ÷àðò èñòîðèè êîòèðîâîê.                                     ¦
// ¦  Èäåÿ ïîçàèìñòâîâàíà èç ñêðèïòà s-Downloader (http://codebase.mql4.com/ru/5875) óâàæàåìîãî   ¦
// ¦ Talex.                                                                                       ¦
// ¦  Ãëàâíîå îòëè÷èå îò s-Downloader: çàãðóçêà ïðîèçâîäèòñÿ ÒÎËÜÊÎ áàðîâ òåêóùåãî òàéìôðåéìà, è  ¦
// ¦ òîëüêî äî óêàçàííîãî âðåìåíè.                                                                ¦
// ¦  Äî ïðèñîåäèíåíèÿ ñîâåòíèêà íåîáõîäèìî:                                                      ¦
// ¦     •îòêëþ÷èòü Àâòî Ïðîêðóòêó;                                                               ¦
// ¦     •ïðîâåðèòü â Îïöèÿõ çíà÷åíèÿ ìàêñ. êîëè÷åñòâà áàðîâ;                                     ¦
// ¦     •ïðèñîåäèíèòü ê ÷àðòó èíäèêàòîð HistoryDownloaderI.                                      ¦
// ¦  Ïðèëàãàåìûé èíäèêàòîð íåîáõîäèì äëÿ ïîëó÷åíèÿ ïåðåìåííîé Bars, è òàéì-ñåðèè Time[]. Äåëî â  ¦
// ¦ òîì, ÷òî ñîâåòíèê âûïîëíÿåò âñþ ñâîþ ðàáîòó íà îäíîé èòåðàöèè start(), à ñëåäîâàòåëüíî, íå   ¦
// ¦ ïîëó÷àåò îáíîâëåííûõ äàííûõ èç ïðåäîïðåäåëåííûõ ïåðåìåííûõ ÷àðòà. Èíäèêàòîð ñîçäàåò, è       ¦
// ¦ îáíîâëÿåò ãëîáàëüíûå ïåðåìåííûå íóæíûìè ñîâåòíèêó äàííûìè. Ýòèì ýòî ôóíêöèè îãðàíè÷èâàþòñÿ.  ¦
// ¦----------------------------------------------------------------------------------------------¦
// ¦     [release 1] 23.08.2009                                                                   ¦
// ¦ •Ïåðâûé ðåëèç. Áàãðåïîðòû è ïðåäëîæåíèÿ ïî îïòèìèçàöèè ïðèâåòñòâóþòñÿ ;)                     ¦
// ¦                                                            | © xp3rienced, Ekaterinburg 2009 ¦
// +——————————————————————————————————————————————————————————————————————————————————————————————+
#property copyright "© xp3rienced"
#property link      "no4ta[at]inbox.ru"

#import "user32.dll"
  int PostMessageA (int hWnd, int Msg, int wParam, int lParam);
#import

#define PAUSE_ON_UPDWAIT 0
#define KEYPRESS_REPEATS 2
#define WM_KEYDOWN 0x0100
#define WM_KEYUP 0x0101
#define VK_HOME 0x24
#define GVNAME_BAR_COUNT "BarOnChartCount"
#define GVNAME_FIRST_BAR_TIME "FirstBarDateTime"
#define DELIMITER_STR "————————————————————————————\n"
#define ERRSTR_CANT_RECV_HWND "Íå óäàëîñü ïîëó÷èòü îïèñàòåëü îêíà (HWND) ÷àðòà.\nÑîâåòíèê îñòàíîâëåí"
#define ERRSTR_CANT_FIND_GV "Íå íàéäåíû ãëîáàëüíûå ïåðåìåííûå. Óáåäèòåñü, ÷òî èíäèêàòîð ïîäêëþ÷åí ê ÷àðòó.\nÑîâåòíèê îñòàíîâëåí"
#define ERRSTR_SUCCESS "Çàãðóçêà êîòèðîâîê çàâåðøåíà óñïåøíî.\nÎòêëþ÷èòå ñîâåòíèêà, è çàêðîéòå òåðìèíàë, îñòàâèâ îêíî ÷àðòà, äëÿ çàïèñè èñòîðèè íà äèñê\n(íå îáÿçàòåëüíî, íî ó àâòîðà, çàïèñü íà äèñê ïðîèñõîäèëà òîëüêî ïîñëå äàííûõ ìàíèïóëÿöèé)\n"
#define ERRSTR_FAIL "Íå óäàëîñü çàãðóçèòü êîòèðîâêè.\nÓáåäèòåñü, ÷òî Àâòî Ïðîêðóòêà îòêëþ÷åíà, è â Îïöèÿõ óñòàíîâëåíî äîñòàòî÷íîå êîëè÷åñòâî\náàðîâ â îêíå, äëÿ âìåùåíèÿ áàðîâ êîòèðîâîê äî óêàçàííîé äàòû\n"

//====[ ïàðàìåòðû ñîâåòíèêà ]====
extern string d1 = "Ëèìèò çàãðóçêè. Ò.å. äî êàêîé äàòû çàãðóæàòü èñòîðèþ";
extern datetime ToDate = D'01.01.2009';
extern string d2 = "Òàéìàóò çàïðîñà (ìñ). Åñëè çà óêàçàííîå âðåìÿ, â ÷àðòå íå äîáàâèòñÿ áàðîâ, ïîïûòêà çàãðóçèòü áàðû áóäåò ïðèçíàíà íåóäà÷íîé";
extern int Timeout = 1000;
extern string d3 = "Ìàêñèìàëüíî äîïóñòèìîå êîëè÷åñòâî íåóäà÷íûõ ïîïûòîê ïîäðÿä. Ïðè äîñòèæåíèè óêàçàííîãî ÷èñëà íåóäà÷íûõ ïîïûòîê, ñîâåòíèê îñòàíîâèò âûïîëíåíèå";
extern int MaxFailsInARow = 10;

//====[ ãëîáàëüíûå ïåðåìåííûå ]====
string CurrSymbol;                      // Èíñòðóìåíò òåêóùåãî ÷àðòà
int CurrPeriod;                         // Ïåðèîä òåêóùåãî ÒÔ
int ChartHWND;                          // Îïèñàòåëü îêíà ãðàôèêà
int BarsAtStart;                        // Êîëè÷åñòâî áàðîâ íà ÷àðòå, äî çàïóñêà
int ExecStartTime;                      // Âðåìÿ íà÷àëà âûïîëíåíèÿ ñîâåòíèêà
int LastLatency;                        // Ïîñëåäíÿÿ çàäåðæêà îáíîâëåíèÿ ãðàôèêà
string ErrorString;

//+------------------------------------------------------------------+
//|                  Ôóíêöèÿ èíèöèàëèçàöèè ýêñïåðòà                  |
//+------------------------------------------------------------------+
int init()
{
//----
  CurrSymbol = Symbol();
  CurrPeriod = Period();
  ErrorString = "";
  GetLastError();           // Îáíóëÿåì çíà÷åíèå last_error
  ChartHWND = WindowHandle(CurrSymbol, CurrPeriod);
  if(ChartHWND == 0)
    ErrorString = StringConcatenate(ERRSTR_CANT_RECV_HWND, "\nÊîä îøèáêè: ", GetLastError(), "\n");
  if(!GlobalVariableCheck(GVNAME_BAR_COUNT) || !GlobalVariableCheck(GVNAME_FIRST_BAR_TIME))
    ErrorString = StringConcatenate(ErrorString, ERRSTR_CANT_FIND_GV);
  if(ErrorString != "")
  {
    Alert(ErrorString);
    return(0);
  }
  BarsAtStart = Bars;
  ExecStartTime = GetTickCount();
  start();                  // Çíàþ, íåëüçÿ òàê äåëàòü :) ýòî íà ñëó÷àé îòñóòñòâèÿ ïðèõîäÿùèõ òèêîâ
//----
  return(0);
}

//+------------------------------------------------------------------+
//|                 Ôóíêöèÿ äåèíèöèàëèçàöèè ýêñïåðòà                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
  UnpressHOME();            // (?) ïî êàêèì-òî ïðè÷èíàì, íå âñåãäà ñðàáàòûâàåò
//----
  return(0);
}

//+------------------------------------------------------------------+
//|                    Ôóíêöèÿ èòåðàöèè ýêñïåðòà                     |
//+------------------------------------------------------------------+
int start()
{
  if(ErrorString != "") return(0);
//----
  bool success = DownloadHistory(ToDate);
  string s = StringConcatenate(DELIMITER_STR,
    "Áàðîâ çàãðóæåíî: ", WindowFirstVisibleBar() - BarsAtStart + 1,
    "\nÇàòðà÷åíî âðåìåíè: ", FormatTime(GetTickCount() - ExecStartTime)
  );
  if(success) s = StringConcatenate(ERRSTR_SUCCESS, s);
  else s = StringConcatenate(ERRSTR_FAIL, s);
  Alert(s);
//----
  return(0);
}
//+----------------- Äàëåå ïîëüçîâàòåëüñêèå ôóíêöèè -----------------+

//+------------------------------------------------------------------+
//|                 Ôóíêöèÿ çàêà÷êè èñòîðèè êîòèðîâîê                |
//| Çàêà÷êà îñóùåñòâëÿåòñÿ ýìóëÿöèåé íàæàòèÿ êëàâèøè HOME â îêíî     |
//| ÷àðòà, ê êîòîðîìó ïðèêðåïëåí ñîâåòíèê. Çàêà÷èâàþòñÿ òîëüêî       |
//| áàðû òåêóùåãî òàéìôðåéìà, äî âðåìåíè, óêàçàííîãî â ïàðàìåòðå     |
//+------------------------------------------------------------------+
bool DownloadHistory(datetime EndTime)
{
  int FailCount = 0;                                          // Ñ÷åò÷èê íåóäà÷íûõ ñ÷èòûâàíèé, èäóùèõ ïîäðÿä
  datetime FirstBarTime;
  while(!IsStopped())
  {
    PressHOME();                                              // Ýìóëèðóåì çàæàòèå êëàâèøè HOME
    if(WaitForChartUpdate())                                  // Æäåì îáíîâëåíèÿ ÷àðòà
      FailCount = 0;                                          // Åñëè ïîëó÷èëè êîòèðîâêè - îáíóëÿåì ñ÷åò÷èê îøèáîê
    else FailCount++;                                         // Íåóäà÷íî, óâåëè÷èì ñ÷åò÷èê îøèáîê
    UnpressHOME();                                            // Îòæèìàåì HOME
    FirstBarTime = GlobalVariableGet(GVNAME_FIRST_BAR_TIME);
    Comment(StringConcatenate("Èäåò çàãðóçêà èñòîðèè äî ", TimeToStr(EndTime), "\nÒåêóùàÿ ïîçèöèÿ ÷àðòà: ",
      TimeToStr(FirstBarTime), "\nÁàðîâ íà ÷àðòå: ", GlobalVariableGet(GVNAME_BAR_COUNT),
      "\nÏîñëåäíÿÿ çàäåðæêà îáíîâëåíèÿ ÷àðòà: ", LastLatency, "ìñ\nÑ ìîìåíòà çàïóñêà ïðîøëî: ",
      FormatTime(GetTickCount() - ExecStartTime)));
    if(FirstBarTime <= EndTime) return(true);
    if(FailCount >= MaxFailsInARow) return(false);
  }
}

//+------------------------------------------------------------------+
//|                 Ôóíêöèÿ îæèäàíèÿ îáíîâëåíèÿ ÷àðòà                |
//| Îáíîâëåíèå ÷àðòà ïðîâåðÿåòñÿ ïî èíäåêñó ïåðâîãî âèäèìîãî áàðà.   |
//| Âîçâðàùàåìûå çíà÷åíèÿ: true - ÷àðò îáíîâèëñÿ (áàðû ïîäãðóæåíû);  |
//| false - èñòåêëî âðåìÿ òàéìàóòà, îáíîâëåíèÿ íå ïðîèçîøëî.         |
//| Åñëè, ïî êàêèì-òî ïðè÷èíàì, ïîòîê ñîâåòíèêà òîðìîçèò ñèñòåìó(?)  |
//| èçìåíèòå êîíñòàíòó PAUSE_ON_UPD_WAIT, óñòàíîâèâ âðåìÿ ïàóçû      |
//| ìåæäó èòåðàöèÿìè öèêëà ôóíêöèè                                   |
//+------------------------------------------------------------------+
bool WaitForChartUpdate()
{
  int FirstVisBar = WindowFirstVisibleBar();
  int Start = GetTickCount();
  while(true)
  {
    if(WindowFirstVisibleBar() > FirstVisBar) return(true);
    LastLatency = GetTickCount() - Start;                     // Ïîñëåäíåå çíà÷åíèå çàäåðæêè îáíîâëåíèÿ ÷àðòà
    if(LastLatency >= Timeout) return(false);
    Sleep(PAUSE_ON_UPDWAIT);
  }
}

//+------------------------------------------------------------------+
//|              Ôóíêöèÿ ýìóëÿöèè íàæàòèÿ êëàâèøè HOME               |
//| Ýìóëÿöèÿ îñóùåñòâëÿåòñÿ îòïðàâêîé WM-ñîîáùåíèÿ îêíó ÷àðòà.       |
//| Êîíñòàíòîé KEYPRESS_REPEATS îïðåäåëÿåòñÿ êîëè÷åñòâî ïîâòîðîâ     |
//| íàæàòèÿ êëàâèøè. Äèàïàçîí çíà÷åíèé: 0..255                       |
//+------------------------------------------------------------------+
void PressHOME()
{
  PostMessageA(ChartHWND, WM_KEYDOWN, VK_HOME, KEYPRESS_REPEATS);
}

//+------------------------------------------------------------------+
//|              Ôóíêöèÿ ýìóëÿöèè îòæàòèÿ êëàâèøè HOME               |
//| Ýìóëÿöèÿ îñóùåñòâëÿåòñÿ îòïðàâêîé WM-ñîîáùåíèÿ îêíó ÷àðòà.       |
//+------------------------------------------------------------------+
void UnpressHOME()
{
  PostMessageA(ChartHWND, WM_KEYUP, VK_HOME, 1);
}

//+------------------------------------------------------------------+
//|   Ôóíêöèÿ ôîðìàòèðîâàíèÿ ìèëëèñèêóíä âî âðåìåííÎå ïðåäñòàâëåíèå  |
//+------------------------------------------------------------------+
string FormatTime(int milliseconds)
{
  int seconds = milliseconds / 1000;
  return(StringConcatenate(TimeHour(seconds), "÷ ", TimeMinute(seconds), "ì ", TimeSeconds(seconds), "ñ"));
}
//+------------------------------------------------------------------+

Comments