← 返回

Проблемы экспорта

Появилась потребность экспорта тиков в текстовый формат для загрузки в Amibroker. Использовал версию гидры 4.0.22 Обнаружил такие проблемы и неточности.

  1. Солюшн не собирается из-за постбилда плагина Plaza. Не находит какой-то файл. Мне не надо. Отключил.
  2. Экспорт не возможен без загрузки данных в грид. Это косяк, потому что на большое количество строк грид памяти жрёт немеряно. Нет информации об окончании экспорта, кроме отвисания формы. Поправил. И то, и другое и зависание. Раз доступ мне не дали, берите файлы отсюда.

评论 (36)

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

VassilSanych
VassilSanych 作者
  1. При указании в настройках целевой директории присутствует выбор между целевой директорией и директорией программы. Причём последняя выбрана по-умолчанию. Не знаю фича это или косяк, но выглядит, как косяк.
  2. Архитектурно программа везде вместо построчной обработки использует списки. Команда
Storage.GetTradeStorage(Security, SourcePath.SelectedSource)
                    .Load(FromDate, ToDate + TimeSpan.FromTicks(TimeSpan.TicksPerDay - 1))

вызывает волшебный метод

  public IEnumerable<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D> Load(DateTime \u0023\u003DqjMNbSyHi2wSfqMTxwOFw5w\u003D\u003D, DateTime \u0023\u003DqLRw2isZu\u0024Gi2kSql74F4hw\u003D\u003D)
  {
    Func<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>> func1 = (Func<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>>) null;
    Func<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>, bool> func2 = (Func<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>, bool>) null;
    \u0023\u003DqjscC_sD__Wz1R8OrZhlzyOI5tzzg7BToUBKXwTVqZO84NhphJRI0eyRNGeGaeg0l<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqAS4sOB3tWVQahGWJQZAVyQ\u003D\u003D, \u0023\u003DqBue7tPpoVUuUSzCh\u0024R8o6w\u003D\u003D>.\u0023\u003DqwQ1\u00246I4BPH\u0024l6LQCfG2RNtCtg2ZDZArxsDUMsokwWOY\u003D zdzArxsDuMsokwWoY = new \u0023\u003DqjscC_sD__Wz1R8OrZhlzyOI5tzzg7BToUBKXwTVqZO84NhphJRI0eyRNGeGaeg0l<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqAS4sOB3tWVQahGWJQZAVyQ\u003D\u003D, \u0023\u003DqBue7tPpoVUuUSzCh\u0024R8o6w\u003D\u003D>.\u0023\u003DqwQ1\u00246I4BPH\u0024l6LQCfG2RNtCtg2ZDZArxsDUMsokwWOY\u003D();
    zdzArxsDuMsokwWoY.\u0023\u003DqNggpJclGeVDD_hTLp8iTTQ\u003D\u003D = param0;
    zdzArxsDuMsokwWoY.\u0023\u003Dq0tOGvj3TpUouN1ux_qLJ0g\u003D\u003D = param1;
    zdzArxsDuMsokwWoY.\u0023\u003DqatTwgFVaPtUxSGplmCWi_A\u003D\u003D = this;
    if (zdzArxsDuMsokwWoY.\u0023\u003DqNggpJclGeVDD_hTLp8iTTQ\u003D\u003D > zdzArxsDuMsokwWoY.\u0023\u003Dq0tOGvj3TpUouN1ux_qLJ0g\u003D\u003D)
      throw new ArgumentOutOfRangeException(\u0023\u003DqiynfM61BKwvyYrVfBhgEI\u0024B5hL7s98VPGwOBoMznNsE\u003D.\u0023\u003DqZv2ypaOXYNZbZulAOMdGVg\u003D\u003D(-615884728), (object) zdzArxsDuMsokwWoY.\u0023\u003Dq0tOGvj3TpUouN1ux_qLJ0g\u003D\u003D, \u0023\u003DqiynfM61BKwvyYrVfBhgEI\u0024B5hL7s98VPGwOBoMznNsE\u003D.\u0023\u003DqZv2ypaOXYNZbZulAOMdGVg\u003D\u003D(-615888671));
    List<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D> list1 = new List<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D>();
    zdzArxsDuMsokwWoY.\u0023\u003DqNggpJclGeVDD_hTLp8iTTQ\u003D\u003D = MathHelper.Max(zdzArxsDuMsokwWoY.\u0023\u003DqNggpJclGeVDD_hTLp8iTTQ\u003D\u003D, this.FromDate);
    if (zdzArxsDuMsokwWoY.\u0023\u003Dq0tOGvj3TpUouN1ux_qLJ0g\u003D\u003D > this.ToDate)
      zdzArxsDuMsokwWoY.\u0023\u003Dq0tOGvj3TpUouN1ux_qLJ0g\u003D\u003D = this.ToDate.AddTicks(863999999999L);
    for (DateTime dateTime = zdzArxsDuMsokwWoY.\u0023\u003DqNggpJclGeVDD_hTLp8iTTQ\u003D\u003D.Date; dateTime <= zdzArxsDuMsokwWoY.\u0023\u003Dq0tOGvj3TpUouN1ux_qLJ0g\u003D\u003D; dateTime = dateTime.AddDays(1.0))
    {
      List<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D> list2 = list1;
      List<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D> list3 = this.\u0023\u003Dqku2X1xXOuql\u0024Cu2tld76CA\u003D\u003D(dateTime);
      if (func1 == null)
        func1 = new Func<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>>(this.\u0023\u003DqXCeEZYtkCEra\u0024qrnqe9hEw\u003D\u003D);
      Func<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>> selector1 = func1;
      IEnumerable<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>> source1 = Enumerable.Select<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>>((IEnumerable<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D>) list3, selector1);
      if (func2 == null)
        func2 = new Func<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>, bool>(zdzArxsDuMsokwWoY.\u0023\u003DqLaIGTCyJSPHR2oI13wYb1A\u003D\u003D);
      Func<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>, bool> predicate = func2;
      IEnumerable<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>> source2 = Enumerable.Where<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>>(source1, predicate);
      if (\u0023\u003DqjscC_sD__Wz1R8OrZhlzyOI5tzzg7BToUBKXwTVqZO84NhphJRI0eyRNGeGaeg0l<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqAS4sOB3tWVQahGWJQZAVyQ\u003D\u003D, \u0023\u003DqBue7tPpoVUuUSzCh\u0024R8o6w\u003D\u003D>.\u0023\u003DqE9hVdSYL5I2ieTBjraxX5RotRNF07gEFMvwNoPwOkgsDM59ZsIUpRxIDaPISoXVU == null)
        \u0023\u003DqjscC_sD__Wz1R8OrZhlzyOI5tzzg7BToUBKXwTVqZO84NhphJRI0eyRNGeGaeg0l<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqAS4sOB3tWVQahGWJQZAVyQ\u003D\u003D, \u0023\u003DqBue7tPpoVUuUSzCh\u0024R8o6w\u003D\u003D>.\u0023\u003DqE9hVdSYL5I2ieTBjraxX5RotRNF07gEFMvwNoPwOkgsDM59ZsIUpRxIDaPISoXVU = new Func<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>, \u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D>(\u0023\u003DqjscC_sD__Wz1R8OrZhlzyOI5tzzg7BToUBKXwTVqZO84NhphJRI0eyRNGeGaeg0l<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqAS4sOB3tWVQahGWJQZAVyQ\u003D\u003D, \u0023\u003DqBue7tPpoVUuUSzCh\u0024R8o6w\u003D\u003D>.\u0023\u003Dq7aL0H77QpSgfenltCnx_VQ\u003D\u003D);
      Func<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>, \u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D> selector2 = \u0023\u003DqjscC_sD__Wz1R8OrZhlzyOI5tzzg7BToUBKXwTVqZO84NhphJRI0eyRNGeGaeg0l<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, \u0023\u003DqAS4sOB3tWVQahGWJQZAVyQ\u003D\u003D, \u0023\u003DqBue7tPpoVUuUSzCh\u0024R8o6w\u003D\u003D>.\u0023\u003DqE9hVdSYL5I2ieTBjraxX5RotRNF07gEFMvwNoPwOkgsDM59ZsIUpRxIDaPISoXVU;
      IEnumerable<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D> collection = Enumerable.Select<\u0023\u003DqEF80Yvamo98ZmPyDgj9S83tqQZUTw9Y1GwDqtxtmj2w\u003D<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D, DateTime>, \u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D>(source2, selector2);
      list2.AddRange(collection);
    }
    return (IEnumerable<\u0023\u003DqdDI3Y3B9NuGEyhuWEKOMQw\u003D\u003D>) list1;
  }

Видно, что несмотря на интерфейс IEnumerable, вывод производится не через yield return, а обычным списком в памяти. Т.е. возможные миллионы строк утрамбовываются в оперативную память. Не очень хорошее поведение для высоконагруженной системы. Данные всего за 2 недели по фьючерсу RI отъедают при этом памяти около 4Гб.

VassilSanych
VassilSanych 作者
  1. Но это ещё не все проблемы с памятью. Небольшой участок кода
using (var writer = new StreamWriter(_filename))
{
	var st = new StringTemplate(File.ReadAllText("txt_export_trades.st"));
	st.RegisterRenderer(typeof(DateTime), new AdvancedDateTimeRenderer());
	st.SetAttribute("security", Security.Id);
	st.SetAttribute("from", FromDate);
	st.SetAttribute("to", ToDate);
	st.SetAttribute("trades", trades);
	st.Write(new AutoIndentWriter(writer));
}

,который по идее должен обеспечивать потоковый вывод в файл с минимальными затратами памяти, съедает этой памяти ещё в 2 раза больше (около 5Гб), чем окунает мой компьютер в файл подкачки "по самые не хочу". 7) И это ещё не всё. После окончания экспорта и закрытия окна сделок память не очищается. Принудительная сборка мусора помогает слабо. Видимо где-то большие объёмы хранятся в статическом поле. Приходится для каждого экспорта перезапускать программу.

В результате экспортировал RIH2 гидрой в 6 приёмов за 1 час, закрыв все приложения, ибо при работе программы с файлом подкачки ничего другое не работает в принципе. После чего за 2 минуты загрузил полученные файлы в Amibroker с расходованием максимально около 100MB памяти. Как говорится, почувствуйте разницу.

Mikhail Sukhov
Mikhail Sukhov

Проблема известная и уже была исправлена в дев ветке (появился IMarketDataStorage.Read). Кроме экспорта Гидры, так как сами мы из Гидры ничего не экспортируем. Можем дать доступ с учетом того, что доделаете выгрузку данных в файл через новый итерационный способ (типа yield).

VassilSanych
VassilSanych 作者

Mikhail Sukhov: Можем дать доступ с учетом того, что доделаете выгрузку данных в файл через новый итерационный способ (типа yield). Если доступ к данным позволяет (не всё сверху до низу списками), сделаю.

VassilSanych
VassilSanych 作者

PS Если кому надо, шаблон выгрузки в формате, который нравится Амиброкеру:

$trades:{$it.Security.Code$;$it.Time; format="yyyyMMdd"$;$it.Time; format="HHmmss"$;$it.Price$;$it.Volume$
}$
VassilSanych
VassilSanych 作者

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

Mikhail Sukhov
Mikhail Sukhov
  1. При экспорте данных БД не используется.
  2. Дайте свой логин на коде плексе, чтобы я вас к проекту подключил.
  3. Насчет верха и низа не понял, что это вообще такое.
VassilSanych
VassilSanych 作者

4.1 не выгружает данные, загруженные версией 4.0.22. Метод Load работает так, как будто данных в папке нет. На первый взгляд поведение в доступном коде не отличается.

Mikhail Sukhov
Mikhail Sukhov

VassilSanych: 4.1 не выгружает данные, загруженные версией 4.0.22. Метод Load работает так, как будто данных в папке нет. На первый взгляд поведение в доступном коде не отличается.

http://stocksharp.com/posts/m/17173/

Alexander
Alexander

Куда пост делся про метод Read? :) Что-то изменилось?

VassilSanych
VassilSanych 作者

Это где я писал про производительность? Был не прав. Мой косяк.

VassilSanych
VassilSanych 作者

Метод Read работает. Но сути это в целом не меняет. Память как жралась, так и жрётся (может быть меньше на самую малость). Проблема скорее всего в методе вывода в файл. Профайлером памяти не мерял ещё. Свой код оттестирую, выложу - сами посмотрите.

VassilSanych
VassilSanych 作者

VassilSanych: Память как жралась, так и жрётся (может быть меньше на самую малость). Проблема скорее всего в методе вывода в файл. В общем так оно и есть. Запустил профилировщик памяти на данных RI за 2 дня (снапшот за 3 дня в оперативке не помещается), остановил после минуты работы. См. memory.png До кучи запустил профилировщик времени на тех же данных, но дождался окончания работы (работает очень медленно) См. time.png Видимо используется слишком сложная библиотека форматирования по шаблону, предназначенная не столько для больших объёмов, сколько для сложной структуры данных.

Mikhail Sukhov
Mikhail Sukhov

VassilSanych: Видимо используется слишком сложная библиотека форматирования по шаблону, предназначенная не столько для больших объёмов, сколько для сложной структуры данных.

Согласен. Я экспортирую все в ручную, если требуется. Но для универсальности решил взять StringTemplate. Может есть какие-то другие альтернативы?

VassilSanych
VassilSanych 作者

Выложил.

Заодно поймал ошибку экспорта в эксель: слишком много строк для XLS (больше 65000). XLSX поддерживает гораздо больше строк. Но всё-равно проблему наверное стоит решать дроблением файлов.

Mikhail Sukhov
Mikhail Sukhov

VassilSanych: XLSX поддерживает гораздо больше строк. Но всё-равно проблему наверное стоит решать дроблением файлов.

Раньше использовался коммерческий компонент. Сейчас он не используется, а используется NPOI. Может быть попробовать новые версии http://code.google.com/p/npoi/ ? Вышла какая-то, правда в бета режиме.

Alexander
Alexander

Mikhail Sukhov:

VassilSanych: XLSX поддерживает гораздо больше строк. Но всё-равно проблему наверное стоит решать дроблением файлов.

Раньше использовался коммерческий компонент. Сейчас он не используется, а используется NPOI. Может быть попробовать новые версии http://code.google.com/p/npoi/ ? Вышла какая-то, правда в бета режиме.

не надо. я обновлял, полезли ворнинги. от npoi зависит другой компонент ещё

VassilSanych
VassilSanych 作者

Выложил изменение: Ограничил количество данных, выгружаемых в XLS, как и количество данных отображаемых в списке. Если кому надо, делайте дробление / пейджинг. А так хоть работает стабильно.

VassilSanych
VassilSanych 作者

Переделал для себя экспорт в текст через библиотеку SmartFormat. Память не жрёт. Работает в несколько раз быстрее. Нада?

Mikhail Sukhov
Mikhail Sukhov

VassilSanych: Переделал для себя экспорт в текст через библиотеку SmartFormat. Память не жрёт. Работает в несколько раз быстрее. Нада?

https://github.com/scottrippey/SmartFormat/wiki Это? Давайте. Только можно ее под 4.0 перекомпилировать, чтобы не было предупреждений компилятора.

Mikhail Sukhov
Mikhail Sukhov

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

VassilSanych
VassilSanych 作者

Mikhail Sukhov: Порефакторил ваши изменения. ReadRange не работает (возвращает данные только за первый день) выгрузка в эксель опять отваливается (во вкладке присутствуют ещё строки, кроме строк данных) PS Поправка: ReadRange не включает последнюю дату. Так оно должно быть? PPS Поправка 2: не из-за лишней строки, а из-за потерянного конца цикла


Поправил поведение экспорта для соответствия поведению ReadRange, исправил экспорт в эксель

Mikhail Sukhov
Mikhail Sukhov

VassilSanych:

Mikhail Sukhov: Порефакторил ваши изменения. ReadRange не работает (возвращает данные только за первый день) выгрузка в эксель опять отваливается (во вкладке присутствуют ещё строки, кроме строк данных) PS Поправка: ReadRange не включает последнюю дату. Так оно должно быть?

Нет, это баг, поправлю.

По выгрузке данных:

  1. pdb файл не так интересен для разработки, как xml.
  2. В релиз режиме будет работать быстрее. А так как это форматирование может вызывать много раз, то это даже необходимо.
  3. Увидел, что SmartFormat собран только под .NET 3.5 Предлагаю его пересобрать под 4.0. А вообще, проект жив?
  4. Может эти строчки для форматирования занести в app.config? И использовать сразу несколько форматов. Например, для Ами, Метаса и т.д.?
  5. Как насчет сделать выгрузку таким образом и для других типов данных? Например, для тех же свечек.
VassilSanych
VassilSanych 作者

Mikhail Sukhov: С прогресс баром лучше было бы сделать, чтобы он опирался на даты. Новая дата - увеличили прогресс. Для того, чтобы такое поведение было возможно не только в методах с перебором в цикле (как сейчас), но и, допустим, в выгрузке в XML, необходимо, чтобы ReadRange принимал на вход делегат информирования и сам дёргал его по приращению даты или по каждой сделке. Второй вариант даже лучше: можно, например, счётчик на форме нарисовать. Обновлять такой счётчик по каждой сделке конечно нельзя (WPF будет жрать больше половины ресурсов), но вполне можно обновлять переменную по делегату, а форму - по таймеру.

Mikhail Sukhov
Mikhail Sukhov

VassilSanych: Для того, чтобы такое поведение было возможно не только в методах с перебором в цикле (как сейчас), но и, допустим, в выгрузке в XML, необходимо, чтобы ReadRange принимал на вход делегат информирования и сам дёргал его по приращению даты или по каждой сделке.

Зачем, если можно не устраивать перекрестную зависимость и сделать код элегантнее?


var totalDates = to - from;
var percPerDate = 100 / totalDates;

for from to
{
  foreach (var trade in Read(curr))
  {
    FormatToFile(trade);
  }

  progress.Value += percPerDate;
}

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

VassilSanych
VassilSanych 作者

Делегат - это не перекрёстная зависимость, а всего-лишь обратный вызов (декларироваться он может и там же, где и Read). Если в вызове нет необходимости, такому параметру можно просто присваивать null в перегруженном методе.

Mikhail Sukhov: Зачем, если можно не устраивать перекрестную зависимость и сделать код элегантнее?

var totalDates = to - from; var percPerDate = 100 / totalDates;

for from to { foreach (var trade in Read(curr)) { FormatToFile(trade); }

progress.Value += percPerDate; }

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

Сейчас примерно так, как описано и работает.
Но экспорт в XML, например, принимает на вход коллекцию и инкапсулирует её перебор.
Т.е. нет доступа к элементу коллекции во время его получения. 
VassilSanych
VassilSanych 作者

VassilSanych: Но экспорт в XML, например, принимает на вход коллекцию и инкапсулирует её перебор.

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

Mikhail Sukhov
Mikhail Sukhov

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

Это плохой стиль, потому что такие делегаты нужны только для GUI. Смешивать данные и GUI не очень хорошее решение.

VassilSanych
VassilSanych 作者

Если это баг, то придётся править выгрузку назад (и прогресс), потому что я её уже поправил. Строго говоря по английски to - означает до (не включая), а включая - thru

  1. не согласен: pdb необходим для отладки и более точной информации об ошибках в рантайме 2-3. сборка SmartFormat в References собрана мной в релиз-режиме 4.0 Client
  2. строка и так читается из текстового файла 5-6 на данный момент мне это не интересно (свечки Ами и так сам рисует, а Метас я не использую). Тот формат, который я оставил, более-менее соответствует изначальному формату Финама и воспринимается Амиброкером (код инструмента удобен для автоматического создания инструмента в Ами при загрузке и стыковке данных из нескольких файлов)

Вообще конечно круче было бы заменить SmartFormat (который подтормаживает из-за рефлексии) на кодогенерацию обычного string.Format по шаблону T4, но больно много работы.

Mikhail Sukhov
Mikhail Sukhov

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

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

VassilSanych:

  1. не согласен: pdb необходим для отладки и более точной информации об ошибках в рантайме 2-3. сборка SmartFormat в References собрана мной в релиз-режиме 4.0 Client
  2. строка и так читается из текстового файла 5-6 на данный момент мне это не интересно (свечки Ами и так сам рисует, а Метас я не использую). Тот формат, который я оставил, более-менее соответствует изначальному формату Финама и воспринимается Амиброкером (код инструмента удобен для автоматического создания инструмента в Ами при загрузке и стыковке данных из нескольких файлов)
  1. xml еще лучше для intellisence
  2. что такое client?
  3. все правильно. только сейчас при каждом апдейте Гидры вам нужно будет переписывать свой файл заново. Ваш формат не подходит, так как он номер игнорирует, а для коммон формата нужны все поля. Поэтому и предлагаю добавить поддержку нескольких форматов.
  4. Ами умеет делать насколько я знаю только ТФ свечки, и не произвольного интервала. Поэтому, для таких ограниченных программ я в Гидру и добавил формирование свечек, чтобы они интерпретировались как обычные свечки, и тем самым могли бы отрисовываться. Более того, при небольшом телодвижении можно сделать через Гидру RT feed.

VassilSanych: Вообще конечно круче было бы заменить SmartFormat (который подтормаживает из-за рефлексии) на кодогенерацию обычного string.Format по шаблону T4, но больно много работы.

А сколько по времени сейчас для РИ 1 день выгружается?

VassilSanych
VassilSanych 作者

Mikhail Sukhov:

  1. xml еще лучше для intellisence
  2. что такое client?
  3. все правильно. только сейчас при каждом апдейте Гидры вам нужно будет переписывать свой файл заново. Ваш формат не подходит, так как он номер игнорирует, а для коммон формата нужны все поля. Поэтому и предлагаю добавить поддержку нескольких форматов.
  4. Ами умеет делать насколько я знаю только ТФ свечки, и не произвольного интервала. Поэтому, для таких ограниченных программ я в Гидру и добавил формирование свечек, чтобы они интерпретировались как обычные свечки, и тем самым могли бы отрисовываться. Более того, при небольшом телодвижении можно сделать через Гидру RT feed.
  1. Одно другому не мешает.
  2. Уменьшенный вариант .Net Framework. Считается самым совместимым.
  3. Это уж как хотите. Ами номер не нужен.
  4. Ами делает разные свечки. Даже 100-тиковые и со сдвигом.

=Mikhail Sukhov: А сколько по времени сейчас для РИ 1 день выгружается? Минут десять. String.Format - минуту.

VassilSanych
VassilSanych 作者

Mikhail Sukhov: Я уже залил фикс, но все равно мне кажется чтение диапазоном не совсем хорошая вещь для данного случая (написал выше). Сообщение заметил только сейчас. Выгрузку не правил.

VassilSanych
VassilSanych 作者

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

Всё это гипотетически, потому что конкретно мне нынешней функциональности экспорта пока достаточно.

Alexander
Alexander

Убрал pdb файл, залил release версию String.Format под .Net 4.0 pdb файлам не место в Reference

VassilSanych
VassilSanych 作者

Alexander Mukhanchikov: Убрал pdb файл .... pdb файлам не место в Reference Нет желания иметь полный StackTrace, номеров строк в сообщениях об ошибках, возможности построчной отладки? Как хотите.

Alexander
Alexander

VassilSanych:

Alexander Mukhanchikov: Убрал pdb файл .... pdb файлам не место в Reference Нет желания иметь полный StackTrace, номеров строк в сообщениях об ошибках, возможности построчной отладки? Как хотите.

в продакшен системе ничего это в принципе не должно быть. к тому же String.Format - сторонняя библиотека.

если надо отлаживаться при девелопменте - используйте локальный pdb файл.