Если текущий TimeFrame = M5, то CopyTime / CopyClose для TF = D1 всегда возвращает -1, а Bars - всегда 0

 

Добрый день,

Есть код загрузки истории для нескольких валютных пар. Переменная Currencies - список имен валют :

int Load(const int start, const int bars)
{
    for (int i = 0; i < Currencies.Total(); i++)
    {
        CSymbol * s = Currencies.At(i);
        
        double closes[];
        datetime times[];
CheckLoadHistory(s.Name, PERIOD_M1, SeriesInfoInteger(s.Name,PERIOD_M1,SERIES_TERMINAL_FIRSTDATE));
CheckLoadHistory(s.Name, _Period, SeriesInfoInteger(s.Name,_Period,SERIES_TERMINAL_FIRSTDATE));
        int currencyBars = Bars(s.Name, _Period);
        
        int countTimes = CopyTime(s.Name, _Period, start - 1, bars, s.Time);
        int countCloses = CopyClose(s.Name, _Period, start - 1, bars, s.Close);


datetime demo[];
int demoCount = CopyTime(s.Name, _Period, 0, currencyBars, demo);
Print(s.Name, " : ", currencyBars, " : ", countTimes, " : ", countCloses, " : ", demoCount);

        if (countTimes <= 0 || countCloses <= 0)
        {
            return(0);
        }
    }

    return(1);
}

Если валюты открыты в терминале и их таймфрейм примерно одинаков, например, M5 - H1, то функция Bars() и CopyTime() работают нормально, но если всем валютам поставиьт таймфрейм M5 или H1, а одной единственной - D1, то получими удручающую картину - Bars() и CopyTime() для этой валюты всегда возвращают 0 и -1 соответственно. Даже при предварительной попытке синхронизировать терминал с сервером через CheckLoadHistory(). Почему так?

На скриншоте видно, что все валюты нормально синхронизируются и копируют бары, а USDJPY открыты в окне с TF = D1, и для нее Bars всегда возвращает 0, а CopyTime и CopyClose - всегда -1. По-моему это баг?

Спасибо, Артем

Документация по MQL5: Доступ к таймсериям и индикаторам / Bars
Документация по MQL5: Доступ к таймсериям и индикаторам / Bars
  • www.mql5.com
Доступ к таймсериям и индикаторам / Bars - Документация по MQL5
Файлы:
Sync.png  196 kb
 

Графики - макс. баров в окне сколько?

PS так делаю

   CopyTime(_Symbol,PERIOD_CURRENT,SERIES_SERVER_FIRSTDATE,(int)TimeLocal(),synchroTimeforBars);
 
Silent:

Графики - макс. баров в окне сколько?

PS так делаю

Спасибо, вечером попробую.

В настройках выставил 5000, но иногда USDCAD и еще какая-то пара возвращают больше, примерно 5984, типа того, но не работает именно USDJPY, если переключить USDJPY на таймфрейм H1 или меньше - все подгружается вовремя.

Также вот в этом месте видно, что я пытался копировать не больше баров, чем возвращает функция Bars, так что там точно было не более 5000 баров, значит, ограничение MAXBARS здесь не мешает.

int currencyBars = Bars(s.Name, _Period);
datetime demo[];
int demoCount = CopyTime(s.Name, _Period, 0, currencyBars, demo);

Кстати, пробовал даже по одному бару копировать - результат такой же минус один (-1)

datetime demo[];

// в текущем окне PERIOD_CURRENT = M5, при этом текущий период в другом окне на паре USDJPY = PERIOD_D1

int demoCount1 = CopyTime("USDJPY", PERIOD_CURRENT, bars - 1, bars, demo); // -1
int demoCount2 = CopyTime("USDJPY", PERIOD_CURRENT, 0, 1, demo); // -1
int demoCount3 = CopyTime("USDJPY", PERIOD_CURRENT, 1, 1, demo); // -1
 
   datetime demo[];
   int demoCount2=CopyTime("USDJPY",PERIOD_CURRENT,0,1,demo); // -1
   Print("demoCount2 "+demoCount2);
   Print("demo[] "+demo[0]);
   int demoCount3=CopyTime("USDJPY",PERIOD_CURRENT,1,1,demo); // -1
   Print("demoCount3 "+demoCount3);
   Print("demo[] "+demo[0]);


не воспроизводится

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

 
datetime demo[];
   int demoCount2=CopyTime("USDJPY",PERIOD_CURRENT,0,1,demo); // -1

К сожалению, такое у меня до сих пор воспроизводится - открыто 6 валютных пар, индюк вешаю на USDCAD на таймфрейме М5, а остальные GBPUSD / EURUSD / AUDUSD / USDJPY / USDCHF переключаю на D1, через 5 минут, пары на D1 перестают синхронизировать M5.

Ваш вариант действительно работает чуть лучше, копирует 4999 баров, но тоже промахивается на йене :(

 
Индикатор висит на М5, а запрашиваете D1, но в функциях Copy* нет PERIOD_D1, вижу только PERIOD_CURRENT и PERIOD_M1. Или я не понял?
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы графиков / Периоды графиков
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы графиков / Периоды графиков
  • www.mql5.com
Стандартные константы, перечисления и структуры / Константы графиков / Периоды графиков - Документация по MQL5
 
artemiusgreat:

К сожалению, такое у меня до сих пор воспроизводится - открыто 6 валютных пар, индюк вешаю на USDCAD на таймфрейме М5, а остальные GBPUSD / EURUSD / AUDUSD / USDJPY / USDCHF переключаю на D1, через 5 минут, пары на D1 перестают синхронизировать M5.

Ваш вариант действительно работает чуть лучше, копирует 4999 баров, но тоже промахивается на йене :(

Хм. А зачем индикатору открытые графики? Функциям Copy график не нужен. С них берётся период? с открытых графиков?

По выделенному. Период заканчивается - перестаёт работать. Период+новый бар приводит к сбою bars, так?

USDJPY отличается только кол-вом знаков.

Перепишите индикатор линейно, без ООП, и ошибка найдётся.

Документация по MQL5: Операции с графиками / ChartOpen
Документация по MQL5: Операции с графиками / ChartOpen
  • www.mql5.com
Операции с графиками / ChartOpen - Документация по MQL5
 
kPVT:
Индикатор висит на М5, а запрашиваете D1, но в функциях Copy* нет PERIOD_D1, вижу только PERIOD_CURRENT и PERIOD_M1. Или я не понял?

Нет, я не запрашиваю D1. Я всегда запрашиваю текущий период с разных валют, в моем случае - М5 для 6 разных валют, но если на графике с индикатором период М5, а другая валюта открыта на D1, то история по М5 для валюты на D1 не грузится.

https://c.mql5.com/3/19/Sync.png

Я открываю 6 графиков, USDJPY переключаю на TF = D1, потом в окно USDCAD переключаю на TF = M5, сюда же добавляю индикатор и пытаюсь сделать в нем Copy для 6 разных валют по TF = M5 - получаю (-1) для валюты, которая на графике D1 (почему-то воспроизводится только на USDJPY)

Функциям Copy график не нужен

Правильно, но возможно если открыт график с опр. TF, то этот TF начинает синхронизировать бары только на выбранном периоде. 

https://www.mql5.com/ru/docs/series/timeseries_access

Эта статья говорит, что МТ подкачивает историю в виде минутных баров и сохраняет ее в виде файлов с расширением HCC, но складывается ощущение, что если открыт график на TF  = D1, то обновляется эта история тоже не чаще 1 раза в день. А функции Bars() и Copy() не инициируют новый запрос на сервер (хотя должны бы), а просто проверяют что хранится локально у вас на компе.

Хранение промежуточных данных

Полученные с сервера данные автоматически распаковываются и сохраняются в специальном промежуточном формате HCC. Данные по каждому символу пишутся в отдельную папку каталог_терминала\bases\имя_сервера\history\имя_символа. Например, данные по символу EURUSD  с торгового сервера MetaQuotes-Demo будут находиться в папке каталаг_терминала\bases\MetaQuotes-Demo\history\EURUSD\.

Данные записываются в файлы с расширением .hcc, каждый файл хранит данные минутных баров за год. Например, файл 2009.hcc в папке EURUSD содержит минутные бары по символу EURUSD за 2009 год. Эти файлы используются для подготовки ценовых данных по всем таймфреймам и не предназначены для прямого доступа.
Получение данных нужного таймфрейма из промежуточных данных

Служебные файлы в формате HCC исполняют роль источника данных для построения ценовых данных по запрошенным таймфреймам в формате HC. Данные в формате HC являются таймсериями, максимально подготовленными для быстрого доступа. Они создаются только по запросу графика или mql5-программы в объеме, не превышающем значения параметра "Max bars in charts", и сохраняются для дальнейшего использования в файлах с расширением hc.

Для экономии ресурсов данные по таймфрейму загружаются и хранятся в оперативной памяти только по необходимости, при длительном отсутствии обращений к данным происходит выгрузка их из оперативной памяти с сохранением в файл. Для каждого таймфрейма данные подготавливаются независимо от наличия уже готовых данных для других таймфреймов. Правила формирования и доступности данных одинаковы для всех таймфреймов. Т.е. не смотря на то, что единицей хранения данных в формате HCC является минутный бар, наличие данных в формате HCC не означает наличие и доступность в том же объеме данных таймфрейма М1 в формате HC.

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


P.S. Только что перепроверил - если на текущем графике с индикатором выбрать М1 или D1 - все грузится, но если M1 < TF текущего графика > D1, то баров нет.

Например, чтобы вопроизвести - есть 2 пары - USDCAD на TF = M5 и USDJPY на TF = D1, на USDCAD вешаем любой индикатор и в него добавляем :

// этот код добавлен в индикатор на графике USDCAD с периодом M5
// в это же время параллельно открыт график USDJPY с периодом D1, на котором нет никаких индикаторов
double c1[], c2[], c3[];
        
int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS);
int cc1 = CopyClose("USDJPY", PERIOD_M1, 0, max_bars, c1);
int cc2 = CopyClose("USDJPY", PERIOD_M5, 0, max_bars, c2);
int cc3 = CopyClose("USDJPY", PERIOD_D1, 0, max_bars, c3);
Print(cc1, " : ", cc2, " : ", cc3);

// Результат Print(5000 : -1 : 5000)
 
artemiusgreat:

Нет, я не запрашиваю D1. Я всегда запрашиваю текущий период с разных валют, в моем случае - М5 для 6 разных валют, но если на графике с индикатором период М5, а другая валюта открыта на D1, то история по М5 для валюты на D1 не грузится.

https://c.mql5.com/3/19/Sync.png

Я открываю 6 графиков, USDJPY переключаю на TF = D1, потом в окно USDCAD переключаю на TF = M5, сюда же добавляю индикатор и пытаюсь сделать в нем Copy для 6 разных валют по TF = M5 - получаю (-1) для валюты, которая на графике D1 (почему-то воспроизводится только на USDJPY)

Правильно, но возможно если открыт график с опр. TF, то этот TF начинает синхронизировать бары только на выбранном периоде. 

https://www.mql5.com/ru/docs/series/timeseries_access

1 Эта статья говорит, что МТ подкачивает историю в виде минутных баров и сохраняет ее в виде файлов с расширением HCC, но складывается ощущение, что если открыт график на TF  = D1, то обновляется эта история тоже не чаще 1 раза в день. А функции Bars() и Copy() не инициируют новый запрос на сервер (хотя должны бы), а просто проверяют что хранится локально у вас на компе.


2 P.S. Только что перепроверил - если на текущем графике с индикатором выбрать М1 или D1 - все грузится, но если M1 < TF текущего графика > D1, то баров нет.

Например, чтобы вопроизвести - есть 2 пары - USDCAD на TF = M5 и USDJPY на TF = D1, на USDCAD вешаем любой индикатор и в него добавляем :

1 Другое место: "Служебные файлы в формате HCC исполняют роль источника данных для построения ценовых данных по запрошенным таймфреймам в формате HC...". Т. е., HCC - то, что на винте, HC - подготовленные в оперативке.

И это "Для экспертов и пользовательских индикаторов лучше использовать событийную модель обработки. Если при обработке события OnTick() или OnCalculate() не удалось получить все необходимые данные требуемой таймсерии, то следует выйти из обработчика события, рассчитывая на появление доступа к данным при следующем вызове обработчика."

2 -1 в индикаторе идут первые несколько тиков, пока синхронизируется, потом идут значения.

Попробуйте прикрутить пример синхронизации из справки (в Bars) или вот тут пример есть.

 
Silent:

1 Другое место: "Служебные файлы в формате HCC исполняют роль источника данных для построения ценовых данных по запрошенным таймфреймам в формате HC...". Т. е., HCC - то, что на винте, HC - подготовленные в оперативке.

И это "Для экспертов и пользовательских индикаторов лучше использовать событийную модель обработки. Если при обработке события OnTick() или OnCalculate() не удалось получить все необходимые данные требуемой таймсерии, то следует выйти из обработчика события, рассчитывая на появление доступа к данным при следующем вызове обработчика."

2 -1 в индикаторе идут первые несколько тиков, пока синхронизируется, потом идут значения.

Попробуйте прикрутить пример синхронизации из справки (в Bars) или вот тут пример есть.

Спасибо, я уже пробовал прикручивать аналог функции, которую вы выложили, только она в какой-то статье здесь называлась CheckLoadHistory() - в принципе, когда я ее использовал, то где-то раз в 20 минут на TF = М5 она даже что-то обновляла.

Вот, нашел статью - https://www.mql5.com/ru/docs/series/timeseries_access

Вообще надо метаквотам предложить добавить в язык систему callback, чтобы не надо было ждать и угадывать когда закончится асинхронный запрос, а просто подписаться на событие, передать событию ссылку на свой колбэк-обработчик и когда асинхронная функция закончит свое выполнение мы автоматом попадем в свой обработчик. В противном случае придется до посинения использовать Sleep(10) ...

Как одну из причин почему именно у меня, именно на USDJPY и именно на M5 синхронизация так тормозит - возможно из-за того что я тестирую только на демо сервер Alpari UK, а у них возможно кривые котировки по йене - кто знает ...

Я немного ускорил синхронизацию путем добавления таймера в индикатор - теперь индикатор каждую секунду долбит сервер функциями Copy() и таким образом есть шанс, что синхронизация займет от силы минуту, не больше.

Вроде бы дописал финальную альфа-версию. На обсуждение общественности выкладываю свой граальчег :)

Индикатор предназначен для торговли по статистическому арбитражу и корреляции валют. Предложения, обсуждение и замечания по улучшению принимаются, но на мое усмотрение.

Enjoy and have profit :)

Документация по MQL5: Доступ к таймсериям и индикаторам / Организация доступа к данным
Документация по MQL5: Доступ к таймсериям и индикаторам / Организация доступа к данным
  • www.mql5.com
Доступ к таймсериям и индикаторам / Организация доступа к данным - Документация по MQL5
Файлы:
Grail.png  282 kb
 
Silent:

1 Другое место: "Служебные файлы в формате HCC исполняют роль источника данных для построения ценовых данных по запрошенным таймфреймам в формате HC...". Т. е., HCC - то, что на винте, HC - подготовленные в оперативке.

И это "Для экспертов и пользовательских индикаторов лучше использовать событийную модель обработки. Если при обработке события OnTick() или OnCalculate() не удалось получить все необходимые данные требуемой таймсерии, то следует выйти из обработчика события, рассчитывая на появление доступа к данным при следующем вызове обработчика."

2 -1 в индикаторе идут первые несколько тиков, пока синхронизируется, потом идут значения.

Попробуйте прикрутить пример синхронизации из справки (в Bars) или вот тут пример есть.

В указанной вами ветке нашел решение предложенное Urain - открытие / закрытие графиков :)

Знаю, костыль костыльный, но обновляется любая история, Вот код :

int Load()
{
    for (int i = 0; i < Currencies.Total(); i++)
    {
        CSymbol * s = Currencies.At(i);
       
        Bars(s.Name, _Period);
       
        int countTimes = CopyTime(s.Name, _Period, 0, MaxBars, s.Time);
        int countCloses = CopyClose(s.Name, _Period, 0, MaxBars, s.Close);

        if (countTimes <= 0 || countCloses <= 0)
        {
            ChartClose(ChartOpen(s.Name, _Period));
            CustomLog(StringFormat("ERROR : No bars for %s", s.Name));
            return(0);
        }
    }

    CustomLog("INFO : History loaded");

    return(1);
}
Причина обращения: