FileSeek(HistoryHandle,0,SEEK_END) для FileOpenHistory

 

Она что, ставит указатель не на конец файла, а на начало нулевого бара?

Если это не так, то просто мистика получается, просто пусть кто-нибудь скажет "да" чтобы я успокоился :))

 

да )))

 
Уф, спасибо )
 

Это:

FileSeek(HistoryHandle, 0, SEEK_END);

ставит файловый указатель в конец файла, а не на нулевой бар. Нулевой бар на 44 байта ближе к началу.

Так на нулевой бар:

FileSeek(HistoryHandle, -44, SEEK_END);
 
Zhunko:

Это:

ставит файловый указатель в конец файла, а не на нулевой бар. Нулевой бар на 44 байта ближе к началу.

Так на нулевой бар:


Я вам весь код не дам, но ситуация такая. Я открываю уже имеющийся файл истории и собираюсь его дописывать. Поэтому после открытия я делаю

  datetime HstBarOpenTime0 = Time[0];  
  FileSeek(HistoryHandle,0,SEEK_END);
  last_fpos=FileTell(HistoryHandle);

Затем я дописываю историю

      if (BarOpenTime > HstBarOpenTime) {
        last_fpos = FileTell(HistoryHandle);
        FileWriteInteger(HistoryHandle,BarOpenTime,LONG_VALUE);
        FileWriteDouble (HistoryHandle,_Open,DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_Low,DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_High,DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_Close,DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_V1,DOUBLE_VALUE);
        FileFlush(HistoryHandle);
        HstBarOpenTime = BarOpenTime;
      } else {  //  if (BarOpenTime > HstBarOpenTime)
        if (BarOpenTime == HstBarOpenTime0) Print("1: Time[0]=",TimeToStr(Time[0]),", HstBarOpenTime is ",TimeToStr(HstBarOpenTime));
        FileSeek(HistoryHandle,last_fpos,SEEK_SET);
        FileWriteInteger(HistoryHandle,BarOpenTime,LONG_VALUE);
        FileWriteDouble (HistoryHandle,_Open,DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_Low,DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_High,DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_Close,DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_V1,DOUBLE_VALUE);
        FileFlush(HistoryHandle);
      }

Оператор

if (BarOpenTime == HstBarOpenTime0)

отслеживает ситуацию, когда в момент запуска скрипта нулевой бар файла ещё будет дописываться. last_fpos в этот момент указывает на конец файла. То есть по вашей трактовке у меня будет два бара с одинаковым временем. Но на самом деле всё вполне замечательно. А вот если в первом фрагменте задавать смещение -44, у меня в момент дописывания стабильно возникала дыра в 1 бар.

Предложите альтернативные объяснения?

 

Какое ещё объяснение?

Конец файла это конец нулевого бара, а не начало. Чтобы писать на нулевой бар, надо сдвинуться от конца к началу файла на 44 байта. Больше ничего не хотел сказать. Просто поправил evillive.

 
Zhunko:

Какое ещё объяснение?

Конец файла это конец нулевого бара, а не начало. Чтобы писать на нулевой бар, надо сдвинуться от конца к началу файла на 44 байта. Болше ничего не хотел сказать. Просто поправил evillive.


Вы код в моём примере смотрели?
 

Так должно быть:

      if (BarOpenTime > HstBarOpenTime)
       {
        FileWriteInteger(HistoryHandle, BarOpenTime, LONG_VALUE);
        FileWriteDouble (HistoryHandle,_Open, DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_Low, DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_High, DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_Close, DOUBLE_VALUE);
        FileWriteDouble (HistoryHandle,_V1, DOUBLE_VALUE);
        FileFlush(HistoryHandle);
        HstBarOpenTime = BarOpenTime;
       }
      else
       {
        if (BarOpenTime == HstBarOpenTime0)
         {
          Print("1: Time[0]=",TimeToStr(Time[0]), ", HstBarOpenTime is ", TimeToStr(HstBarOpenTime));
          FileSeek(HistoryHandle, -44, SEEK_END);
          FileWriteInteger(HistoryHandle,BarOpenTime, LONG_VALUE);
          FileWriteDouble (HistoryHandle,_Open, DOUBLE_VALUE);
          FileWriteDouble (HistoryHandle,_Low, DOUBLE_VALUE);
          FileWriteDouble (HistoryHandle,_High, DOUBLE_VALUE);
          FileWriteDouble (HistoryHandle,_Close, DOUBLE_VALUE);
          FileWriteDouble (HistoryHandle,_V1, DOUBLE_VALUE);
          FileFlush(HistoryHandle);
         }
       }

Лучше всё это массивом писать. Сначала время, потом массив DOUBLE. Побыстрее будет.

Хотя, отсчитывать от конца это не совсем правильно. Вдруг какой-то мусор запишется от сбоя, некратный 44 байтам.

 
Zhunko:

Так должно быть:

Лучше всё это массивом писать. Сначала время, потом массив DOUBLE. Побыстрее будет.

Хотя, отсчитывать от конца это не совсем правильно. Вдруг какой-то мусор запишется от сбоя, некратный 44 байтам.


Не понял. Так допишется старый нулевой бар и на этом всё закончится. Вы точно обратили внимание что HstBarOpenTime0 и HstBarOpenTime это разные переменные?

Ещё раз о смысле примера. Он показывает, что после установки указателя на конец файла нулевой бар дописывается. А вовсе не начинается новый.

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

У меня есть альтернативое объяснение :). Вы или никогда не попадали в ситуацию, когда необходимо продолжить прерванную запись уже начатого бара, или просто не замечали, что при "правильной" установке указателя прежний бар уничтожается.

Что касается записи массивом, то я не уверен в таком уж выигрыше на пяти элементах. А вот нарываться на ещё какую-нибудь специфику работы с историей совсем не хочется. К тому же при работе с автономным графиком (а для чего ещё делают свою историю?) это заведомо не главный источник проблем со скоростью. А если котировки ещё и из Интернета идут, то ... ну вобщем скорость в этом коде не главное :))

P.S. Единственная альтернатива отсчёту от конца - читать при открытии файл полностью. А вот это на многомегабайтных файлах уже вполне заметным тормозом может быть. Гораздо легче просто проверить конец файла после открытия, прочитав ту же Time[0].

 
Candid:


1. Не понял. Так допишется старый нулевой бар и на этом всё закончится. Вы точно обратили внимание что HstBarOpenTime0 и HstBarOpenTime0 это разные переменные?

2. Ещё раз о смысле примера. Он показывает, что после установки указателя на конец файла нулевой бар дописывается. А вовсе не начинается новый.

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

3. У меня есть альтернативое объяснение :). Вы или никогда не попадали в ситуацию, когда необходимо продолжить прерванную запись уже начатого бара, или просто не замечали, что при "правильной" установке указателя прежний бар уничтожается.

4. Что касается записи массивом, то я не уверен в таком уж выигрыше на пяти элементах. А вот нарываться на ещё какую-нибудь специфику работы с историей совсем не хочется. К тому же при работе с автономным графиком (а для чего ещё делают свою историю?) это заведомо не главный источник проблем со скоростью. А если котировки ещё и из Интернета идут, то ... ну вобщем скорость в этом коде не главное :))

5. P.S. Единственная альтернатива отсчёту от конца - читать при открытии файл полностью. А вот это на многомегабайтных файлах уже вполне заметным тормозом может быть. Гораздо легче просто проверить конец файла после открытия, прочитав ту же Time[0].

1. Если время последнего записанного бара совпадает с записываемым, то надо записать со сдвигом -44 байта. Если записываемое время больше, чем у последнего бара, то пишем в конец файла. Если время меньше, игнорируем запись. Разве есть ещё варианты?

2. Что у вас значит - дописывается? См. п.1. Для меня "дописывается" и "начинается новый" одно и тоже. Со сдвигом в -44 байта перезаписывается последний нулевой бар.

3. Тут нет открытия. Всё так и работает. Прерванная запись продолжается с -44 байта.

4. Одна транзакция слишком продолжительна. Надо писать как можно большими объёмами. Можете проверить. Скоро можно будет записывать структуру баров за один раз. Особенно это важно при записи тиков. Бывает 400 тиков в минуту. Зачем 2400 раз дёргать диск? Можно в 6 раз меньше. Я даже оптимизирую запись изменяющихся данных. Т.е. не весь бар перезаписываю. Правда, это почти никак не влияет на скорость. Только ресурс диска экономится. Запись 8 байтов или 44 байтов происходит за почти одно время.

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

 
Zhunko:

1. Если время последнего записанного бара совпадает с записываемым, то надо записать со сдвигом -44 байта. Если записываемое время больше, чем у последнего бара, то пишем в конец файла. Если время меньше, игнорируем запись. Разве есть ещё варианты?

2. Что у вас значит - дописывается? См. п.1. Для меня "дописывается" и "начинается новый" одно и тоже. Со сдвигом в -44 байта перезаписывается последний нулевой бар.

3. Тут нет открытия. Всё так и работает. Прерванная запись продолжается с -44 байта.

4. Одна транзакция слишком продолжительна. Надо писать как можно большими объёмами. Можете проверить. Скоро можно будет записывать структуру баров за один раз. Особенно это важно при записи тиков. Бывает 400 тиков в минуту. Зачем 2400 раз дёргать диск? Можно в 6 раз меньше. Я даже оптимизирую запись изменяющихся данных. Т.е. не весь бар перезаписываю. Правда, это почти никак не влияет на скорость. Только ресурс диска экономится. Запись 8 байтов или 44 байтов происходит за почти одно время.

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


1,2, 3 - У вас код подтверждающий есть, или вы просто считаете что так должно быть?

4. Диск вы дёргаете только Flush' ем. Но на автономном графике это плата за оперативное обновление картинки. Вы говорите как бы правильные, но слишком абстрактные вещи. Есть специфика задач и есть специфика MQL, шаблон тут не годится.

5. При чем тут размер? Нужен не размер, а позиция для возобновления записи. Вы похоже опять абстрактную мудрость мне предлагали? ("отсчитывать от конца это не совсем правильно. Вдруг какой-то мусор запишется от сбоя, некратный 44 байтам")

P.S. Вообще, давайте не расширять тему. Вопрос очень конкретный, как правильнее FileSeek(HistoryHandle,0,SEEK_END) или FileSeek(HistoryHandle,-44,SEEK_END). Ответом может быть только код. Я свой дал.

P.P.S.HstBarOpenTime0 и HstBarOpenTime конечно а не HstBarOpenTime0 и HstBarOpenTime0

Причина обращения: