← 返回

Ошибка при чтении тиков из bin-хранилища, API 4.2.72

Записал Гидрой данные из источника RTS (всё подряд за несколько лет). Пытаюсь прочитать (без разницы, через API 4.2.72 или самой Гидрой c библиотеками 4.2.71) - время от времени вылезает exception:

Error System.ArgumentException: Decimal byte array constructor requires an array of length four containing valid decimal bytes. at System.Decimal.SetBits(Int32[] bits) at StockSharp.Algo.Storages.MarketDataStorageHelper.ReadDecimal(BitArrayReader reader, Decimal prevPrice) at StockSharp.Algo.Storages.MarketDataStorageHelper.ReadPriceEx(BitArrayReader reader, BinaryMetaInfo1 info) at StockSharp.Algo.Storages.TradeSerializer.MoveNext(MarketDataEnumerator enumerator) at StockSharp.Algo.Storages.BinaryMarketDataSerializer2.MarketDataEnumerator.MoveNext() at StockSharp.Algo.Storages.StorageHelper.RangeEnumerable1.RangeEnumerator.System.Collections.IEnumerator.MoveNext() at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() at StockSharp.Algo.Export.TextExporter.Do[TValue](IEnumerable1 values, String templateName) at Ecng.Common.Converter.<>c__DisplayClassf.<DoInCulture>b__e() at Ecng.Common.Converter.DoInCulture(CultureInfo cultureInfo, Func1 func) at StockSharp.Algo.Export.BaseExporter.Export(Type dataType, IEnumerable values) at StockSharp.Hydra.Controls.ExportProgress.<>c__DisplayClass6.<Start>b__4(Object s, DoWorkEventArgs e) at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)

На достаточно активных фьючах (RIZ4) такая ошибка появляется раз в несколько месяцев. В общем, прочитать полностью все сделки по конкретному фьючерсу удается редко.

Еще забавный баг в последней Гидре: почему-то разучилась создавать временные директории вида yyyy_MM_dd внутри \TemporaryFiles во время загрузки данных из RTS. Пишет ошибку "System.IO.DirectoryNotFoundException: Could not find a part of the path 'S:\Hydra\TemporaryFiles\2009_11_02\20091102.zip'". Насоздавал ей директорий вручную под каждую дату - всё завелось, она их даже удалила сама после использования.

本主题对您有帮助吗?

分享主题

评论 (23)

登录创建账户, 登录或注册以发表评论

asuilin
asuilin 作者

В дополнение, если сохранять не в bin а в CSV, Гидра сыплет такими ошибками в процессе скачивания RTS:

RTS-CSV 31.03.2015 8:46:51 +03:00 Info Старт загрузки сделок за 24.05.2011. RTS-CSV 31.03.2015 8:47:26 +03:00 Error System.InvalidCastException: Cannot convert with format HH:mm:ss.FFFFFF zzz to TimeSpan. ---> System.FormatException: String was not recognized as a valid DateTime. at System.DateTimeOffset.ParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles) at Ecng.Common.TimeHelper.ToDateTimeOffset(String value, String format) --- End of inner exception stack trace --- at Ecng.Common.TimeHelper.ToDateTimeOffset(String value, String format) at StockSharp.Algo.Storages.CsvMarketDataSerializer1.ParseTime(String str, DateTime date) at StockSharp.Algo.Storages.CsvMarketDataSerializer1.CsvMetaInfo.<>c__DisplayClass15.<Read>b__14() at Ecng.Common.Converter.<>c__DisplayClassf.<DoInCulture>b__e() at Ecng.Common.Converter.DoInCulture(CultureInfo cultureInfo, Func1 func) at StockSharp.Algo.Storages.MarketDataStorage2.GetInfo(Stream stream, DateTime date) at StockSharp.Algo.Storages.MarketDataStorage2.Save(IEnumerable1 data) at StockSharp.Hydra.Core.BaseHydraTask.SafeSave(Security security, Type messageType, Object arg, IEnumerable1 values, Func2 getTime, IEnumerable1 getErrors, Func4 getStorage) RTS-CSV 31.03.2015 8:47:26 +03:00 Info Для SVM1@FORTS загружено 4019 ExecutionMessage (Tick).

Ошибок много, в среднем одна ошибка на 5 скачанных инструментов.

Следующим шагом попробую отказаться от Гидры и напрямую дергать за RtsHistorySource.LoadTrades, с собственными хранилищами. Открытый код в Algo.History облегчил бы задачу.

Mikhail Sukhov
Mikhail Sukhov
  1. Какая версия Гидры.
  2. Если битый файл удалить и повторно перезакачать, будет ли ошибка? Если да, то скажите дату и инструмент.
asuilin
asuilin 作者

Mikhail Sukhov:

  1. Какая версия Гидры.
  2. Если битый файл удалить и повторно перезакачать, будет ли ошибка? Если да, то скажите дату и инструмент.
  1. 4.2.71
  2. Ошибка возникает на любом инструменте с достаточно большим количеством трейдов. На RI/SI, например, мне редко удавалось прочитать без ошибки тиковую историю любого фьючерса за три месяца. С перезакачкой не очень понятно, Гидра же хранит где-то в недрах метаинформацию о том, что скачалось? Если просто удалить файлы и закачать заново, ничего не сломается?

Через RtsHistorySource вроде бы нормально заливается в память, т.е. проблема в хранилище.

Mikhail Sukhov
Mikhail Sukhov

asuilin: С перезакачкой не очень понятно, Гидра же хранит где-то в недрах метаинформацию о том, что скачалось? Если просто удалить файлы и закачать заново, ничего не сломается?

Можно просто удалить битые даты и сбросить кэш дат в Гидре. Или удалить этот файл вручную.

asuilin
asuilin 作者

Кеш дат это tradesDates.bin?

Mikhail Sukhov
Mikhail Sukhov

Да

asuilin
asuilin 作者

Михаил, а не могли бы вы публиковать отладочную информацию в NuGet? Хрен ведь поймешь, на какой конкретной дате оно спотыкается внутри итератора. См. http://www.arturdr.ru/net/publikatsiya-ishodnikov-vmeste-s-nuget-plyus-ishodniki-av-infrastructure-web/ и https://docs.nuget.org/create/creating-and-publishing-a-symbol-package

asuilin
asuilin 作者

Перезакачка полечила одну битую дату, но не полечила другую. На RIZ4@FORTS для 2014_12_09 (9 декабря) данные остаются битыми после нескольких перезакачек. Файл приложу, если найду как это сделать.

Mikhail Sukhov
Mikhail Sukhov

asuilin: Перезакачка полечила одну битую дату, но не полечила другую. На RIZ4@FORTS для 2014_12_09 (9 декабря) данные остаются битыми после нескольких перезакачек. Файл приложу, если найду как это сделать.

Наверное не поняли. Надо удалить дату. Тоесть не перезаписывать файл, а новый создавать нужно.

asuilin
asuilin 作者

Mikhail Sukhov: Наверное не поняли. Надо удалить дату. Тоесть не перезаписывать файл, а новый создавать нужно. Да, конечно я так и делал. Под перезакачкой имелась в виду повторная заливка этой даты в Гидре.

asuilin
asuilin 作者

Кажется, мне быстрее будет реализовать собственное хранилище, имплементирующее IMarketDataStorage. Проблема в том, что у него есть свойство IMarketDataDrive Drive, а у него, в свою очередь, есть IMarketDataStorageDrive GetStorageDrive(). А IMarketDataStorageDrive оперирует бинарыми данными и рассчитан на формат StockSharp. Какой тогда смысл в этих интерфейсах, если ни с чем, кроме закрытого бинарного формата, они работать не могут? Или реализация GetStorageDrive() не обязательна и можно там сделать заглушку?

Mikhail Sukhov
Mikhail Sukhov

asuilin:

Mikhail Sukhov: Наверное не поняли. Надо удалить дату. Тоесть не перезаписывать файл, а новый создавать нужно. Да, конечно я так и делал. Под перезакачкой имелась в виду повторная заливка этой даты в Гидре.

Тоесть ошибка за 2014_12_09 по RIZ4 стабильно воспроизводится?

asuilin
asuilin 作者

Mikhail Sukhov: Тоесть ошибка за 2014_12_09 по RIZ4 стабильно воспроизводится?

Да, у меня цикл удаляем - скачиваем - читаем - получаем ошибку воспроизвёлся раз пять. Вы бы посмотрели файлик то?

Mikhail Sukhov
Mikhail Sukhov

asuilin:

Mikhail Sukhov: Тоесть ошибка за 2014_12_09 по RIZ4 стабильно воспроизводится?

Да, у меня цикл удаляем - скачиваем - читаем - получаем ошибку воспроизвёлся раз пять. Вы бы посмотрели файлик то?

Файл смотреть нет смысла. Есть смысл устранить проблему, если она есть. Попробовал Гидрой из Гита скачать за указанную дату. Скачалось и прочиталось. Все Гидрой. Попробуете последней с Гита? Я правильно понимаю, что вы выставили в настройках нужную дату, выбрали нужный инструмент и закачали 1 день? После этого попытались его прочитать.

asuilin
asuilin 作者

Да, всё так и делал. Написал тест, сгенерировал 1М трейдов, записал и прочитал - все отработало. Сейчас пробую сделать всё без Гидры, напрямую через RtsHistorySource и запись трейдов в хранилище, вдруг заработает. Заодно это быстрее, чем Гидра, работающая в один поток. Вопрос - при записи/чтении трейды никак не переупорядочиваются по номеру тика? Т.е. если я запишу сначала вечерние трейды за день, а потом утренние, они и читаться будут в том же порядке?

Кстати, посмотрел, что Гидра записала в CSV формат - во всех трейдах пустые даты. Не зря она сыпала ошибками, сама с собой не где то смогла договориться о формате дат в строках.

Mikhail Sukhov
Mikhail Sukhov

Вы не поняли. Надо через гидру.

asuilin
asuilin 作者

Mikhail Sukhov: Вы не поняли. Надо через гидру.

Мне не надо через Гидру, мне надо решить мою простейшую задачу - загрузить и прочитать данные RTS. Через код ее оказалось удобнее и быстрее решать, Гидра дергает за те же классы, какая разница. Итак, более детальное тестирование показало, что сбой в конкретной дате зависит от того, загружались ли следующие даты. Пример - при загрузке 17 марта 2015 и 18 марта сбоит чтение фьючерса GDM5 за 17 марта. При загрузке только 17 марта все ОК. Возможно, в следующем дне догружаются какие-то хвосты от предыдущего и неудачно дописываются в конец файла.

Тестировалось на версии API 4.2.75, которая датируется в NuGet 1 апреля, т.е. свежак. Код теста прилагаю, попробуйте запустить у себя. Сначала надо загрузить пакеты из NuGet (Manage Nuget Packages) и поправить в коде пути для загрузки.

Mikhail Sukhov
Mikhail Sukhov

asuilin:

Mikhail Sukhov: Вы не поняли. Надо через гидру.

Мне не надо через Гидру

Мне надо определить ошибку, если она есть. Если вы хотите получать ответы бесплатно, то лучше вам все же следовать тем предписаниям, что я пишу. Ну или все самостоятельно далее.

asuilin
asuilin 作者

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

Mikhail Sukhov
Mikhail Sukhov

Я попробовал ваши шаги. О результатах отписал выше.

asuilin
asuilin 作者

Mikhail Sukhov: Я попробовал ваши шаги. О результатах отписал выше. Именно поэтому я сделал тест, работающий в изолированных стерильных условиях, чтобы ошибка была более воспроизводимой. Ошибка ведь в хранилище, а не в Гидре, значит хранилище и надо тестировать, без десятка дополнительных слоёв кода вокруг.

Вообще, по всем правилам здравого смысла продукт уровня StockSharp, тем более работающий с крупными деньгами, должен быть покрыт функциональными и unit тестами вдоль и поперёк. Их абсолютное отсутствие на GitHub и стремление искать ошибки вручную через интерфейс Гидры порождает вопросы...

asuilin
asuilin 作者

Моя версия с багом дозаписи в .bin файл подтвердилась. RTSHistorySource возвращает сделки не только за заданный день, но и небольшой хвост от предыдущего дня - не разбирался почему, возможно так устроены данные FORTS. Этот хвост дописывается в хранилище предыдущего дня, в котором уже есть данные, и где-то в этом месте нарушается структура хранилища. Если перед записью отфильтровать этот хвост, т.е. записывать за один раз данные строго одного дня, то все работает. Все фьючерсы RTS за месяц прекрасно записались и прочитались. Михаил, все вводные данные у вас есть, можете исправлять баг, можете нет, дело ваше. Я буду делать свой сторадж на SQLite, так надёжнее и проще в поддержке.

Mikhail Sukhov
Mikhail Sukhov

asuilin: должен быть покрыт функциональными и unit тестами вдоль и поперёк. Их абсолютное отсутствие на GitHub и стремление искать ошибки вручную через интерфейс Гидры порождает вопросы...

Вас кто-то останавливает? http://stocksharp.com/forum/4893/Sovmiestnaia-rabota-v-GitHub/