FileSeek(HistoryHandle,0,SEEK_END) для FileOpenHistory - страница 2

 
Candid:


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

1-3. Есть, конечно. Проблем не видел. Протестировано. У меня так файлы для автономных графиков пишутся.

4. Это не так. Не совсем так. Всё зависит от того, как открыт файл. Если он открыт без поддержки системного кеша, то Flush() скидывает на диск. Иначе, система сама выбирает момент переноса на диск. В этом случае, Flush() заставляет систему досрочно скинуть данные на диск.

У Метаквотов в MQL файлы открываются с поддержкой системного кеша. Так что, Flush() не особо нужен. Само скидывается на диск. Проверял. К стати, именно Flush() дёргает диск. Без него система сама разруливает и оптимизирует.

5. Как это зачем? А как Вы проверите файл на целостность? Это не абстракция. Это реальность. Надо учесть все возможные последствия. Иначе это может плохо кончиться.

Расчёт позиции указателя = размер заголовка + (размер бара * (округляем в меньшую сторону((размер файла - размер заголовка) / размер бара)));

Код написал. Возражений по делу не было. Почему он не устраивает?

Candid:


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

Ноль не заметил. Суть таже.

datetime HstBarOpenTime = ...;   // Время последнего бара в файле.
datetime BarOpenTime = Time[0];  // Текущий бар для записи.
//-----------------------

if (BarOpenTime == 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);
 }
else
 {
  if (BarOpenTime > HstBarOpenTime)
   {  
    FileSeek(HistoryHandle, 0, 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);
    HstBarOpenTime = BarOpenTime;
   }
 }
Так пооптимизированнее будет.
 
Zhunko:

1-3. Есть, конечно. Проблем не видел. Протестировано. У меня так файлы для автономных графиков пишутся.

4. Это не так. Не совсем так. Всё зависит от того, как открыт файл. Если он открыт без поддержки системного кеша, то Flush() скидывает на диск. Иначе, система сама выбирает момент переноса на диск. В этом случае, Flush() заставляет систему досрочно скинуть данные на диск.

У Метаквотов в MQL файлы открываются с поддержкой системного кеша. Так что, Flush() не особо нужен. Само скидывается на диск. Проверял. К стати, именно Flush() дёргает диск. Без него система сама разруливает и оптимизирует.

5. Как это зачем? А как Вы проверите файл на целостность? Это не абстракция. Это реальность. Надо учесть все возможные последствия. Иначе это может плохо кончиться.

Расчёт позиции указателя = размер заголовка + (размер бара * (округляем в меньшую сторону((размер файла - размер заголовка) / размер бара)));

Код написал. Возражений по делу не было. Почему он не устраивает?

Ноль не заметил. Суть таже.

6. Так пооптимизированнее будет.



6. В чём оптимизация то? Убрали отладочный if?. А вот испортить вы его (мой код) испортили, из за -44 он будет давать ошибку, боюсь что по пунктам 1-3 вы действительно просто не увидели проблем, которые на самом деле были.

Ещё раз: я дал правильно работающий код. Я потерял полдня, чтобы от логичного варианта с -44 (с которого я начал) придти к этому "простому" решению. Мне не нужен другой код, Мне интересно, может ли быть другое объяснение того, что он работает правильно (кроме того, что я в первом посте предложил)?

Поймите, исторические данные сложный объект. Я конечно не знаю как именно их реализовали разработчики, но, например, легко можно представить, что это класс, содержащий массив для законченных баров и отдельную структуру нулевого бара. А оператор FileSeek перегружен (не прямая трансляция сишного аналога).

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

4. Верно ли я понял, что здесь написано: "вы написали не так, потому что это написали вы, а правильно будет так, как вы написали, когда это напишу я" :))) Сначала я пишу "Диск вы дёргаете только Flush' ем". Потом вы пишете " Это не так. ... Flush() скидывает на диск ... Flush() заставляет систему досрочно скинуть данные на диск".

Вы вообще зачем начинаете про системный кэш рассказывать? Чтобы намекнуть что собеседник этого не знает, или просто чтобы зафлудить исходный вопрос? Собеседник это знает, он просто не хочет заливать тему водой. Вы бы лучше подумали, зачем в коде образца (period_converter) Flush присутствует.

 
Zhunko:

2. Что у вас значит - дописывается?

Вот это наверное надо всё же пояснить.

1. Пишущий историю М1 скрипт по какой-то причине останавливается, например в 16:00:10, при этом начатый в 16:00 бар сохраняется на диске.

2. Вы перезапускаете скрипт в 16:00:30. Вам нужно правильно достроить имеющий(загруженный при запуске с диска) незаконченный бар и правильно продолжить

Понятно, что если вы перезапустите скрипт после 16:01, вы проблемы просто не заметите.

Сразу скажу, что это отладочная ситуация, в реальности проблема "-44" возникает не только при искусственном "мгновенном" перезапуске, но это специфика задачи.

P.S. Пожалуй тут уже столько оффтопа, что имеет смысл сделать рисет :)

Вот фрагмент кода непосредственно после открытия файла истории при запуске скрипта

//  FileSeek(HistoryHandle,-44,SEEK_END);    // Этот вариант приводит к дыре в истории
  FileSeek(HistoryHandle,0,SEEK_END);        // Этот вариант работает правильно
  last_fpos=FileTell(HistoryHandle);
 
Candid:


6. В чём оптимизация то? Убрали отладочный if?. А вот испортить вы его (мой код) испортили, из за -44 он будет давать ошибку, боюсь что по пунктам 1-3 вы действительно просто не увидели проблем, которые на самом деле были.

Ещё раз: я дал правильно работающий код. Я потерял полдня, чтобы от логичного варианта с -44 (с которого я начал) придти к этому "простому" решению. Мне не нужен другой код, Мне интересно, может ли быть другое объяснение того, что он работает правильно (кроме того, что я в первом посте предложил)?

Поймите, исторические данные сложный объект. Я конечно не знаю как именно их реализовали разработчики, но, например, легко можно представить, что это класс, содержащий массив для законченных баров и отдельную структуру нулевого бара. А оператор FileSeek перегружен (не прямая трансляция сишного аналога).

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

4. Верно ли я понял, что здесь написано: "вы написали не так, потому что это написали вы, а правильно будет так, как вы написали, когда это напишу я" :))) Сначала я пишу "Диск вы дёргаете только Flush' ем". Потом вы пишете " Это не так. ... Flush() скидывает на диск ... Flush() заставляет систему досрочно скинуть данные на диск".

Вы вообще зачем начинаете про системный кэш рассказывать? Чтобы намекнуть что собеседник этого не знает, или просто чтобы зафлудить исходный вопрос? Собеседник это знает, он просто не хочет заливать тему водой. Вы бы лучше подумали, зачем в коде образца (period_converter) Flush присутствует.

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

Понять, что он работающий невозможно по причине неполного кода.

FileSeek() не оператор. Это функция. Очень странная и нелогичная перегрузка, если бы она была.

5. Отсутствие мусора не гарантирует. Зато гарантирует кратность 44 байтам. В МТ4 есть встроенный автоматический редактор истории. Но он очень тормознутый. Последний бар он с лёгкостью исправляет. Ни разу мне не удалось дождаться, когда исправит большую историю. Про уничтожение не понял.

4. Просто пояснил, что будет работать без Flush(). Разговор о Flush() с дёрганием диска Вы начали с фразы:

Candid:

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

Получается, мало того, что система уже сама сбросила на диск, что записано, а Вы ещё раз заставляете сбросить уже сброшенное. Возможно, она это каким-то способом оптимизирует. Не проверял.

Candid:

Вот это наверное надо всё же пояснить.

1. Пишущий историю М1 скрипт по какой-то причине останавливается, например в 16:00:10, при этом начатый в 16:00 бар сохраняется на диске.

2. Вы перезапускаете скрипт в 16:00:30. Вам нужно правильно достроить имеющий(загруженный при запуске с диска) незаконченный бар и правильно продолжить

Понятно, что если вы перезапустите скрипт после 16:01, вы проблемы просто не заметите.

Сразу скажу, что это отладочная ситуация, в реальности проблема "-44" возникает не только при искусственном "мгновенном" перезапуске, но это специфика задачи.

P.S. Пожалуй тут уже столько оффтопа, что имеет смысл сделать рисет :)

Вот фрагмент кода непосредственно после открытия файла истории при запуске скрипта

До меня дошло о каких дырах и о чём Вы пытаетесь сказать. Проще было весь код выложить. Сразу было бы понятно.

У себя эту проблему записи разделил на 2 задачи.

1. Просто записать последние данные, как в том коде, что выше.

2. Записать пропущенные данные.

Судя по продолжающемуся разговору, у Вас проблема во второй задаче. Только так и не понял при чём тут FileSeek().

Кстати, в периодконвертере, что в комплекте, это уже решено. Можно от туда взять и доделать, как надо под конкретную задачу.

 
Zhunko:

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

??? Количество операций в if-else вроде бы не зависит от порядка.
Очень странная и нелогичная перегрузка, если бы она была.

Ну я долго над примером не думал, возможно он не самый удачный :). Смысл думаю понятен, файл истории - это не обычный файл и там могут быть капканы.

До меня дошло о каких дырах и о чём Вы пытаетесь сказать. Проще было весь код выложить. Сразу было бы понятно.

У себя эту проблему записи разделил на 2 задачи.

1. Просто записать последние данные, как в том коде, что выше.

2. Записать пропущенные данные.

Судя по продолжающемуся разговору, у Вас проблема во второй задаче. Только так и не понял при чём тут FileSeek().

Хм, не поленюсь ещё раз повторить, что у меня проблемы нет, я её решил. С помощью FileSeek() :). Просто решение оказалось несколько "нетривиальным" :) и мне захотелось найти для него какую-то логику.
Но вы уверены что до вас дошло? Повторю ещё раз, ваш код уничтожает загруженный при запуске нулевой бар.
 

Candid:
1. ??? Количество операций в if-else вроде бы не зависит от порядка.

2. Ну я долго над примером не думал, возможно он не самый удачный :). Смысл думаю понятен, файл истории - это не обычный файл и там могут быть капканы.

3. Хм, не поленюсь ещё раз повторить, что у меня проблемы записи нет, я её решил. С помощью FileSeek() :). Просто решение оказалось несколько "нетривиальным" :) и мне захотелось найти для него какую-то логику.

1. В одном "if-else" нет, но там их два.

2. Это обычный файл с обычным чередованием баров. В 5 есть заморочки. Там не так просто. Сам не разбирался. Это со слов того, кто разбирался.

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

 
Zhunko:

1. В одном "if-else" нет, но там их два.

2. Это обычный файл с обычным чередованием баров. В 5 есть заморочки. Там не так просто. Сам не разбирался. Это со слов того, кто разбирался.

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


1. вариант 1: проверка условия - исполнение - переход

вариант 2: проверка условия - переход - исполнение

Я что-то упустил?

2. Ну вот в 4 он получается тоже необычным.

3. пост номер 4 этой ветки, там вся логика (точнее "нелогика" :) ). Я гарантирую, что между фрагментами ничего с last_fpos и HstBarOpenTime не делается. Кстати, в первом фрагменте есть ещё пропущенная из-за очевидности строка

datetime HstBarOpenTime = Time[0];


 
Candid:


1. вариант 1: проверка условия - исполнение - переход

вариант 2: проверка условия - переход - исполнение

Я что-то упустил?

2. Ну вот в 4 он получается тоже необычным.

3. пост номер 4 этой ветки, там вся логика (точнее "нелогика" :) ). Я гарантирую, что между фрагментами ничего с last_fpos и HstBarOpenTime не делается. Кстати, в первом фрагменте есть ещё пропущенная из-за очевидности строка

datetime HstBarOpenTime = Time[0];


1. Потому что "равно" бывает чаще, чем "больше". Это в динамике. Ещё бывает "меньше", но это очень редко.

2. Это Вы что-то упустили в своей логике. У меня таких заморочек не было.

3. Там нет самого главного. Где цикл по барам, логика установки файлового указателя до этого цикла, выбор начала чтения и начала записи? Почти ничего нет. Вы же против абстракции.

 
Zhunko:

1. Потому что "равно" бывает чаще, чем "больше". Это в динамике.

2. Это Вы что-то упустили в своей логике. У меня таких заморочек не было.

3. Там нет самого главного. Где цикл по барам, логика установки файлового указателя до этого цикла, выбор начала чтения и начала записи? Почти ничего нет. Вы же против абстракции.


1. Рискну предположить, что проверка условий "равно" и "больше" занимает одинаковое время. Далее исполняется один и тот же код, разница только в том, что в одном случае переход делается до исполнения, а в другом после. Внутренний if история отдельная и к оптимизации отношения практически не имеет.

2. Вы не обижайтесь, но чем дольше длится дискуссия, тем крепче у меня впечатление, что вы "убитого" бара легко могли просто не заметить. Вы проверьте свой код всё же, похоже с тех пор как он запускался много билдов МТ4 утекло.

3. Там нет цикла по барам, я же сказал что данные получаются из Интернета, BarOpenTime получается непосредственно из приходящей временной отметки. Соответственно начало чтения и записи всегда больше или равно HstBarOpenTime. Я не зря оставил в коде отладочный if с принтом, он ясно показывает что при описанной мной выше отладочной ситуации в это место скрипт попадает сразу после открытия файла истории. Впрочем я об этом уже говорил кажется.