Вывод котировок MQL5 в Exel - страница 2

 
sig volt:
Разобрался как в ексель автоматически закидывать котировки из csv формата. Помогите кто знает как автоматом выгружать котировки из метатрейдера 4 или 5 в формат csv?

Такое подходит: https://www.mql5.com/ru/code/1252  ?

sHistoryExport
sHistoryExport
  • www.mql5.com
Экспорт всех необходимых инструментов и таймфреймов одним кликом с загрузкой и проверкой истории.
 

https://habr.com/ru/post/346058/

 
Yevhenii Levchenko:

Такое подходит: https://www.mql5.com/ru/code/1252  ?

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

 
sig volt:

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

Закажите автору модернизацию
 

Вот решил помочь и написал эксперта, который сохраняет котировки в csv-файл

Особенности:

  • При выборе периода, укажите конкретный. Для текущего периода, имя файла будет EURUSD_CURRENT.csv
  • Для текущего бара (только, что открывшегося) tick_volume = 1. Поэтому котировки сохраняются с запаздыванием на один период

Пока отлаживал эксперта, нашел у себя "страшный" баг (когда уверен, что понимаешь как работает функция, но она работает не так). Речь идет о записи в конец файла

int file = FileOpen(path, FILE_READ|FILE_WRITE|FILE_UNICODE);
if(file != INVALID_HANDLE && FileSeek(file, 0, SEEK_END)) {
    FileWriteString(file, text);
    FileClose(file);
}

Без флага FILE_READ запись будет сначала файла. Я думал, что FileSeek достаточно, оказалось совсем нет. Ладно, спишем на фишки MQL ;-)

Вот сам эксперт UploadQuotes. Почему именно эксперт? Потому, что у него есть обработчик OnTick()

#define tframe ENUM_TIMEFRAMES

input   tframe gPeriodView = PERIOD_CURRENT; // Период наблюдения
input   datetime gTimeBegin = 0; // Начальная дата котировок (0 - с тек.времени)

string  gNameTime0Bar; // имя глобальной переменной с временем 0-го бара
string  gPathCsv; // путь к csv-файлу котировок

// --------------------------------------------------------------------------------------
// Инициализация эксперта
// --------------------------------------------------------------------------------------
int OnInit() {
    
    gNameTime0Bar = StringFormat("time0Bar_%s", IntegerToString(ChartID()));
    gPathCsv = StringFormat("%s_%s.csv", Symbol(), StringSubstr(EnumToString(gPeriodView), 7));

    if (gTimeBegin > 0) {
        datetime dtime = TimeCurrent() - 2 * PeriodSeconds(gPeriodView);
        UploadQuotes(gPeriodView, gTimeBegin, dtime);
        GlobalVariableSet(gNameTime0Bar, dtime);
    }
    
    return(INIT_SUCCEEDED);
}

// --------------------------------------------------------------------------------------
// Деинициализация эксперта
// --------------------------------------------------------------------------------------
void OnDeinit(const int reason) {
}

// --------------------------------------------------------------------------------------
// Обработчик тиков
// --------------------------------------------------------------------------------------
void OnTick() {
    if (IsNewBar(gPeriodView)) {
        datetime dtime = (datetime)GlobalVariableGet(gNameTime0Bar);
        dtime = dtime - PeriodSeconds(gPeriodView);
        UploadQuotes(gPeriodView, dtime, dtime);
    }
}

// --------------------------------------------------------------------------------------
// Проверить появление нового бара на заданном периоде
// --------------------------------------------------------------------------------------
bool IsNewBar(tframe period) {
    datetime dtime = TrimTime(TimeCurrent(), gPeriodView);
    if (dtime != GlobalVariableGet(gNameTime0Bar)) {
        GlobalVariableSet(gNameTime0Bar, dtime);
        return true;
    }
    return false;
}

// --------------------------------------------------------------------------------------
// Подравнять время до периода (13:25, H1 => 13:00 )
// --------------------------------------------------------------------------------------
datetime TrimTime(datetime dtime, tframe period) {
    int persec = PeriodSeconds(period);
    return((datetime)(persec * MathFloor(dtime/persec)));
}

// --------------------------------------------------------------------------------------
// Выгрузить котировки в csv-файл за заданные таймфрейм и период времени
// --------------------------------------------------------------------------------------
void UploadQuotes(tframe period, datetime dt1, datetime dt2) {
    MqlRates rates[];
    ResetLastError();
    
    // считываем котировки за период [dt1, dt2]
    int numBars = CopyRates(_Symbol, period, dt1, dt2, rates);
    if (numBars < 0) {
        PrintFormat("%s ERROR: %i", __FUNCTION__, GetLastError());
        return;
    }
    
    // формируем csv-текст
    string text = "";
    for (int j = 0; j < numBars; j++) {
        text += StringFormat("%s;%s;%s;%s;%s;%i\n", 
            TimeToString(rates[j].time),
            DoubleToString(rates[j].open, _Digits),
            DoubleToString(rates[j].high, _Digits),
            DoubleToString(rates[j].low, _Digits),
            DoubleToString(rates[j].close, _Digits),
            rates[j].tick_volume);
    }
    
    // сохраняем csv-текст
    if (SaveText(text, gPathCsv))
        PrintFormat("%s / %s / %s", __FUNCTION__, TimeToString(dt1), TimeToString(dt2));
}

// --------------------------------------------------------------------------------------
// Сохранить текст
// --------------------------------------------------------------------------------------
bool SaveText(string text, string path) {
   
    // сохраняем текст в конец файла
    ResetLastError();
    int file = FileOpen(path, FILE_READ|FILE_WRITE|FILE_UNICODE);
    if(file != INVALID_HANDLE && FileSeek(file, 0, SEEK_END)) {
        FileWriteString(file, text);
        FileClose(file);
    }

    // проверяем код ошибки
    int rcode = GetLastError();
    if (rcode != ERR_SUCCESS) {
        PrintFormat("%s / ERROR: %i / %s", __FUNCTION__, rcode, path);
        return false;
    }
    return true;
}
 
Malik Arykov:

Вот решил помочь и написал эксперта, который сохраняет котировки в csv-файл

Особенности:

  • При выборе периода, укажите конкретный. Для текущего периода, имя файла будет EURUSD_CURRENT.csv
  • Для текущего бара (только, что открывшегося) tick_volume = 1. Поэтому котировки сохраняются с запаздыванием на один период

Пока отлаживал эксперта, нашел у себя "страшный" баг (когда уверен, что понимаешь как работает функция, но она работает не так). Речь идет о записи в конец файла

Без флага FILE_READ запись будет сначала файла. Я думал, что FileSeek достаточно, оказалось совсем нет. Ладно, спишем на фишки MQL ;-)

Вот сам эксперт UploadQuotes. Почему именно эксперт? Потому, что у него есть обработчик OnTick

Спасибо

 
Malik Arykov:

Вот решил помочь и написал эксперта, который сохраняет котировки в csv-файл

Скриптом не лучше ???

//+------------------------------------------------------------------+
//|                                                 Malik Arykov.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property script_show_inputs
//---
#define tframe ENUM_TIMEFRAMES
//---
input   tframe   gPeriodView = PERIOD_CURRENT; // Период наблюдения
input   datetime gTimeBegin  = D'2021.04.12';  // Начальная дата котировок (0 - с тек.времени)
//---
string  gNameTime0Bar; // имя глобальной переменной с временем 0-го бара
string  gPathCsv;      // путь к csv-файлу котировок
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   gNameTime0Bar = StringFormat("time0Bar_%s", IntegerToString(ChartID()));
   gPathCsv = StringFormat("%s_%s.csv", Symbol(), StringSubstr(EnumToString(gPeriodView), 7));
   if(gTimeBegin > 0)
     {
      datetime dtime = TimeCurrent() - 2 * PeriodSeconds(gPeriodView);
      UploadQuotes(gPeriodView, gTimeBegin, dtime);
      GlobalVariableSet(gNameTime0Bar, dtime);
     }
//---
   if(IsNewBar(gPeriodView))
     {
      datetime dtime = (datetime)GlobalVariableGet(gNameTime0Bar);
      dtime = dtime - PeriodSeconds(gPeriodView);
      UploadQuotes(gPeriodView, dtime, dtime);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsNewBar(tframe period)
  {
   datetime dtime = TrimTime(TimeCurrent(), gPeriodView);
   if(dtime != GlobalVariableGet(gNameTime0Bar))
     {
      GlobalVariableSet(gNameTime0Bar, dtime);
      return true;
     }
   return false;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
datetime TrimTime(datetime dtime, tframe period)
  {
   int persec = PeriodSeconds(period);
   return((datetime)(persec * MathFloor(dtime/persec)));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void UploadQuotes(tframe period, datetime dt1, datetime dt2)
  {
   MqlRates rates[];
   ResetLastError();
// считываем котировки за период [dt1, dt2]
   int numBars = CopyRates(_Symbol, period, dt1, dt2, rates);
   if(numBars < 0)
     {
      PrintFormat("%s ERROR: %i", __FUNCTION__, GetLastError());
      return;
     }
// формируем csv-текст
   string text = "";
   for(int j = 0; j < numBars; j++)
     {
      text += StringFormat("%s;%s;%s;%s;%s;%i\n",
                           TimeToString(rates[j].time),
                           DoubleToString(rates[j].open, _Digits),
                           DoubleToString(rates[j].high, _Digits),
                           DoubleToString(rates[j].low, _Digits),
                           DoubleToString(rates[j].close, _Digits),
                           rates[j].tick_volume);
     }
// сохраняем csv-текст
   if(SaveText(text, gPathCsv))
      PrintFormat("%s / %s / %s", __FUNCTION__, TimeToString(dt1), TimeToString(dt2));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool SaveText(string text, string path)
  {
// сохраняем текст в конец файла
   ResetLastError();
   int file = FileOpen(path, FILE_READ|FILE_WRITE|FILE_UNICODE);
   if(file != INVALID_HANDLE && FileSeek(file, 0, SEEK_END))
     {
      FileWriteString(file, text);
      FileClose(file);
     }
// проверяем код ошибки
   int rcode = GetLastError();
   if(rcode != ERR_SUCCESS)
     {
      PrintFormat("%s / ERROR: %i / %s", __FUNCTION__, rcode, path);
      return false;
     }
   return true;
  }
//+------------------------------------------------------------------+
csvSNIMOK
 

SanAlex:

Скриптом не лучше ???

Спасибо. Столько много вариантов, столько людей откликнулось даже не ожидал Спасибо Всем!

 
sig volt:

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

SanAlex:

Скриптом не лучше ???

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

 

SanAlex:


Хороший эксперт. Можно ли как то его улучшить чтобы он пачками котировки выгружал? Например пара EUR/USD котировки: М1-Mn и сразу по сотне активов. Мажоры, кроскурсы, индексы и прочее. Если по одной котировке выгружать и по одному таймфрейму это крайне накладно