← Voltar

Конвертация исторических файлов QScalp в формат StockSharp

Привет всем алготрейдерам!

Хочу поделиться своим решение для тестирования скальперских и ХФТ стратегий. Долгое время я использую замечательный привод Морошкина (бесплатную версию 🙂 ). И недавно решил автоматизировать несколько стратегий на базе StockSharp.

Но для этого нужны исторические данные, в частности стаканы. У StockSharp есть программа Гидра, которая по идее позволяет качать все необходимое, но ее нужно держать постоянно включенной. Для меня это не вариант, так как я постоянно занят, и интернет не всегда стабильный.

Но недавно я узнал, что QScalp сам пишет историю и бесплатно ее выкладывает через брокера IT Invest.

В итоге, я написал конвертор данных QScalp в формат StockSharp!

Просто установите программу и скачайте исторические данные формата QSH для QScalp по одной из ссылок ниже

http://www.itinvest.ru/software/spo/qscalp/history/

ftp://athistory.zerich.com/

Теперь осталось только указать в конвертере путь к скаченным файлам и к папке хранения исторических данных StockSharp, и нажать кнопку “Запустить”!

Вуаля, теперь у вас есть высококачественные исторические данные для тестирования своих стратегий!

PS Торопитесь пока бесплатно ;))

PPS Шутка))

Всем удачной торговли!

Присоединиться и редактировать код можно по https://github.com/stocksharp/Qsh2Bin

скомпилированную программу по https://github.com/StockSharp/Qsh2Bin/releases

Este tópico foi útil?

Compartilhar tópico

Comentários (70)

Entrar ou Criar conta, Faça login ou cadastre-se para deixar um comentário

Bond
Bond

Исторические данные можно скачать только за один день? А за период времени? И какая глубина этих исторических данных?

nuan
nuan

Собственно можно залить уже установленную версию, т.к. у меня при установки вылетает ошибка... Что-то то там с манифестом.

Mikhail Sukhov
Mikhail Sukhov

nuan: Что-то то там с манифестом.

Это значит, что не в программе ошибка. Манифест - это ОС.

nuan
nuan

СВЕДЕНИЯ О ВЕРСИИ ПЛАТФОРМЫ Windows : 6.1.7601.65536 (Win32NT) Common Language Runtime : 4.0.30319.18034 System.Deployment.dll : 4.0.30319.17929 built by: FX45RTMREL clr.dll : 4.0.30319.18034 built by: FX45RTMGDR dfdll.dll : 4.0.30319.17929 built by: FX45RTMREL dfshim.dll : 4.0.31106.0 (Main.031106-0000)

ИСТОЧНИКИ URL-адрес развертывания : file:///C:/Users/Nuan/Desktop/data/publish/Qsh2Bin.application

УДОСТОВЕРЕНИЯ Удостоверение развертывания : Qsh2Bin.application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=58b400c5ccdd6861, processorArchitecture=msil

СВОДКА ПРИЛОЖЕНИЯ

  • Устанавливаемое приложение.

СВОДКА ОШИБОК Ниже приводится сводка ошибок, сведения об этих ошибках перечислены далее в журнале.

  • В результате активизации C:\Users\Nuan\Desktop\data\publish\Qsh2Bin.application произошла ошибка с исключением. Определены следующие сообщения о сбоях:
    • Исключение чтения манифеста из file:///C:/Users/Nuan/Desktop/data/publish/Application%20Files/Qsh2Bin_1_0_0_0/Qsh2Bin.exe.manifest: возможно, манифест неправильный или файл не может быть открыт.
    • Манифест приложения семантически неправилен.
    • Файл значка, указанный в манифесте приложения, неправильный.

СВОДКА СБОЯ ТРАНЗАКЦИИ СОХРАНЕНИЯ КОМПОНЕНТА Не определена никакая ошибка транзакции.

ПРЕДУПРЕЖДЕНИЯ Во время этой операции предупреждения не выводились.

СОСТОЯНИЕ ВЫПОЛНЕНИЯ ОПЕРАЦИИ

  • [17.10.2013 22:51:47] : Активация C:\Users\Nuan\Desktop\data\publish\Qsh2Bin.application начата.
  • [17.10.2013 22:51:53] : Обработка манифеста развертывания успешно завершена.
  • [17.10.2013 22:51:53] : Начата установка приложения.

СВЕДЕНИЯ ОБ ОШИБКЕ Во время выполнения этой операции обнаружены следующие ошибки.

  • [17.10.2013 22:51:53] System.Deployment.Application.InvalidDeploymentException (ManifestParse)
    • Исключение чтения манифеста из file:///C:/Users/Nuan/Desktop/data/publish/Application%20Files/Qsh2Bin_1_0_0_0/Qsh2Bin.exe.manifest: возможно, манифест неправильный или файл не может быть открыт.
    • Источник: System.Deployment
    • Запись изменений стека: в System.Deployment.Application.ManifestReader.FromDocument(String localPath, ManifestType manifestType, Uri sourceUri) в System.Deployment.Application.DownloadManager.DownloadApplicationManifest(AssemblyManifest deploymentManifest, String targetDir, Uri deploymentUri, IDownloadNotification notification, DownloadOptions options, Uri& appSourceUri, String& appManifestPath) в System.Deployment.Application.DownloadManager.DownloadApplicationManifest(AssemblyManifest deploymentManifest, String targetDir, Uri deploymentUri, Uri& appSourceUri, String& appManifestPath) в System.Deployment.Application.ApplicationActivator.DownloadApplication(SubscriptionState subState, ActivationDescription actDesc, Int64 transactionId, TempDirectory& downloadTemp) в System.Deployment.Application.ApplicationActivator.InstallApplication(SubscriptionState& subState, ActivationDescription actDesc) в System.Deployment.Application.ApplicationActivator.PerformDeploymentActivation(Uri activationUri, Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings browserSettings, String& errorPageUrl) в System.Deployment.Application.ApplicationActivator.ActivateDeploymentWorker(Object state) --- Внутреннее исключение --- System.Deployment.Application.InvalidDeploymentException (ManifestSemanticValidation)
    • Манифест приложения семантически неправилен.
    • Источник: System.Deployment
    • Запись изменений стека: в System.Deployment.Application.Manifest.AssemblyManifest.ValidateSemanticsForApplicationRole() в System.Deployment.Application.Manifest.AssemblyManifest.ValidateSemantics(ManifestType manifestType) в System.Deployment.Application.ManifestReader.FromDocument(String localPath, ManifestType manifestType, Uri sourceUri) --- Внутреннее исключение --- System.Deployment.Application.InvalidDeploymentException (InvalidManifest)
    • Файл значка, указанный в манифесте приложения, неправильный.
    • Источник: System.Deployment
    • Запись изменений стека: в System.Deployment.Application.Manifest.AssemblyManifest.ValidateSemanticsForApplicationRole()

СВЕДЕНИЯ О ТРАНЗАКЦИИ СОХРАНЕНИЯ КОМПОНЕНТА Нет доступных сведений о транзакции.

Mikhail Sukhov
Mikhail Sukhov

Типа мне разбираться?😂 Гуглите.

nuan
nuan

дык я и прошу проинсталенную уже ) чтобы и мне не разбираться с установкой )

longtrades
longtrades

Скажите, пожалуйста, какая версия стокшарпа сможет открыть эти архивные файлы ?

А то у меня вобще какая то проблема с доставанием инфы из базы данных: Версия 4.1.19.1 пишу трейды в базу :


                        trader.NewTrades += trades => this.GuiAsync(() =>
                        {
                            var secgroup = trades.GroupBy(x => x.Security);
                            foreach (var sec in secgroup)
                            {
                                if (sec.Key.MinStepSize != 0)
                                {
                                    var tradestorage = storage.GetTradeStorage(sec.Key);
                                    tradestorage.AppendOnlyNew = true;
                                    tradestorage.Save(sec);
                                }
                            }

                        });

Потом пробую дастать трейды из той же базы в той же программе :


            var startTime = new DateTime(2013, 11, 18);
            var stopTime = new DateTime(2013, 11, 20);

            // создаем тестовый инструмент, на котором будет производится тестирование
            var security = new Security
            {
                Id = "RIZ3@FORTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными
                Code = "RIZ3",
                Name = "RTS-12.13",
                MinStepSize = 10,
                MinStepPrice = 6.5m,
                MinPrice = 10,
                MaxPrice = 1000000,
                ExchangeBoard = ExchangeBoard.Forts,
            };

            security.LastTrade = new Trade { Price = 143000 };

            // тестовый портфель
            var portfolio = new Portfolio
            {
                Name = "test account",
                BeginValue = 1000000,
            };

            // создаем шлюз для эмуляции
            // инициализируем настройки (инструмент в истории обновляется раз в секунду)
            var Trader = new EmulationTrader(
                new[] { security },
                new[] { portfolio })
            {
                MarketTimeChangedInterval = TimeSpan.FromMilliseconds(10),
                StorageRegistry = storage,

                // использовать стаканы
                UseMarketDepth = true,

                // использовать свечки
               // UseCandlesTimeFrame = emulationInfo.UseCandleTimeFrame,
            };

            // проверка что стаканы соответствуют сделкам. Улучшает реалистичность тестирования.
            Trader.MarketEmulator.Settings.SyncDepthToTrades = true;

            // сведение сделки в эмуляторе если цена коснулась нашей лимитной заявки. 
            // Если выключено - требуется "прохождение цены сквозь уровень"
            // (более "суровый" режим тестирования.)
            Trader.MarketEmulator.Settings.FillOnTouch = false;

            security.Trader = Trader;

            Trader.RegisterMarketDepth(security);

            // соединяемся с трейдером и запускаем экспорт,
            // чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader
            Trader.Connect();
            Trader.StartExport();

            Trader.Start(startTime, stopTime);

Но почему то в трейдере нет ни одного трейда , они вобще должны там быть или они будут появлятся в процессе тестирования ?

longtrades
longtrades

Проверил версию 4.1.14.1, тоже самое Трейдов нет , Может я что-то не так делаю ?

Trader.RegisterTrades(security); тоже не помогает :(

Mikhail Sukhov
Mikhail Sukhov

longtrades: Проверил версию 4.1.14.1, тоже самое Трейдов нет , Может я что-то не так делаю ?

А что вы вообще делаете?

longtrades
longtrades

Постоянно пишу все новые треды в базу , потом хочу тестировать на этой истории .

risty
risty

вставил в исходники текущую версию API с поддержкой четверной версии qsh файлов (http://www.qscalp.ru/download) http://dropmefiles.com/XqiuN

Mikhail Sukhov
Mikhail Sukhov

risty: вставил в исходники текущую версию API с поддержкой четверной версии qsh файлов (http://www.qscalp.ru/download) http://dropmefiles.com/XqiuN

Залили бы сразу в репозитарий. Потеряется же.

risty
risty

Михаил Сухов:

risty: вставил в исходники текущую версию API с поддержкой четверной версии qsh файлов (http://www.qscalp.ru/download) http://dropmefiles.com/XqiuN

Залили бы сразу в репозитарий. Потеряется же.

не умею )

LiCiSin
LiCiSin

risty:

Михаил Сухов:

risty: вставил в исходники текущую версию API с поддержкой четверной версии qsh файлов (http://www.qscalp.ru/download) http://dropmefiles.com/XqiuN

Залили бы сразу в репозитарий. Потеряется же.

не умею ) ну вот уже потерялись-время ханения вышло.... давай исходники -а я залью.

XMbIPb
XMbIPb

Сейчас история только клиентам ITinvest доступна или вообще прикрыли лавочку?

Mikhail Sukhov
Mikhail Sukhov

У айти абонентка за быть их клиентом?

Церих тоже скоро лавочку прикроет

risty
risty

http://dropmefiles.com/P5alg - перезалил. До гитхаба все никак не добраться (

nikitao
nikitao

А можно перезалить, а то файл уже удален? Спасибо

Mikhail Sukhov
Mikhail Sukhov

Обновил сырцы. Качается так же с Гита. ОЛ от Цериха конвертирует.

M1k3
M1k3

Mikhail Sukhov: Обновил сырцы. Качается так же с Гита. ОЛ от Цериха конвертирует. А можно это все запустить без actipro за 650$? А то что-то не получается. Да и вообще не понятно, аналогов actipro нет для stocksharp в виде telerik или чего-то другого, чтобы не платить так сильно за разработку 1-го приложения, которое может в итоге и не понадобиться? Некоторых отпугивает...

Mikhail Sukhov
Mikhail Sukhov

M1k3: Некоторых отпугивает...

Финансовые рынки - не место для трусов.

Pantov
Pantov

Подскажите, что за ошибка: Имя параметра: item в StockSharp.Algo.OrderLogHelper.GetOrderLogCancelReason(ExecutionMessage item) в f:\develop\StockSharp_436\Algo\OrderLogHelper.cs:строка 128 в StockSharp.Algo.OrderLogMarketDepthBuilder.Update(ExecutionMessage item) в f:\develop\StockSharp_436\Algo\OrderLogMarketDepthBuilder.cs:строка 167 в StockSharp.Algo.Connector.ProcessOrderLogMessage(Security security, ExecutionMessage message) в f:\develop\StockSharp_436\Algo\Connector_ProcessMessage.cs:строка 1047 2015/06/04 19:00:00.126|Error |HistoryEmulationConnector|System.ArgumentException: Строка лога заявок не содержит информацию о причине отмены заявки. Имя параметра: item

В ОЛ сформированного данной программой.

Mikhail Sukhov
Mikhail Sukhov

Pantov: Подскажите, что за ошибка: Имя параметра: item в StockSharp.Algo.OrderLogHelper.GetOrderLogCancelReason(ExecutionMessage item) в f:\develop\StockSharp_436\Algo\OrderLogHelper.cs:строка 128

https://github.com/StockSharp/StockSharp

Mikhail Sukhov
Mikhail Sukhov

Придется переконвертировать ОЛ, если кто уже сделал. Забыл заполнить одно из важных полей https://github.com/AntonySS/Qsh2Bin/commit/ae2470db4092ab93ad69305430058bc473786831

Может быть кто-то выложил сконвертированные файлы, чтобы не заниматься одним и тем же?

vkaliteevsky
vkaliteevsky

Пожалуйста, выложите скомпилированную версию программы!

Mikhail Sukhov
Mikhail Sukhov

vkaliteevsky: Пожалуйста, выложите скомпилированную версию программы!

Выложил

M1k3
M1k3

Mikhail Sukhov:

vkaliteevsky: Пожалуйста, выложите скомпилированную версию программы!

Выложил

А можно попросить у вас прямую ссылку на *.exe?

ionn
ionn

Не работает конвертация, скачал историю с цериха. ордерлог видит в qsh, сохраняет пачками по 1000 записей, но в папке с инструментом в результате только файл orderlog.bin размером 7 килобайт.

Mikhail Sukhov
Mikhail Sukhov

Запустил, проверил, работает.

ionn
ionn

я качал с гитхаба скомпилированную прогу, и сам компилировал из исходников - результат одинаков.

сюда передается массив сообщений: registry.GetOrderLogMessageStorage(security).Save(secData.Item4);

но в файл orderlog.bin ничего не записывается и что там в Save() происходит мне не ведомо... запускал на разных машинах...

Куда смотреть? Где копать?

Mikhail Sukhov
Mikhail Sukhov

ionn: и что там в Save() происходит мне не ведомо...

Куда смотреть? Где копать?

https://github.com/StockSharp/StockSharp/

ionn
ionn

выяснил что в ExecutionMessage не проставляется transactionId, он всегда равен 0. поэтому ничего не сохраняется, если убрать AppendOnlyNew или проставить свой transactionId то всё сохраняется - но по этой истории тестирование все равно не работает, свечки не формируются

хотя qscalp проигрывает скаченные файлы нормально.

Mikhail Sukhov
Mikhail Sukhov

Доработал чуть утилиту. Добавил файл настроек и файл с ранее обработанными файлами (это если экспорт перезапускается, чтобы не конвертировать все заново).

Добавил поддежку CSV формата. У Ку Скальпа есть своя утилита, но она у меня почему-то падает. Плюс она без графического интерфейса, а значит нужно писать скрипт (опять же делать индекс-файл с обработанными файлами).

Ну что, может сейчас уже кто-то решится сделать мини сервер истории с паблик доступом? Может скинутся, и купить Amazon S3? Там есть веб интерфейс и настройка прав доступа (в том числе и публичное использование). За 100GB придется заплатить 36 долларов в год. Этого размера вполне хватит для ОЛ истории.

Я готов оплатить место сам, но администрировать не берусь. Если кто-то все настроит, то давайте туда зальем данные (пока доступ не отрубили).

Pantov
Pantov

Как их истории торгов от ИК «ЦЕРИХ» с помощью Qsh2Bin получить: quotes.bin trades.bin security.bin, а не orderlog.bin?

Спасибо.

Mikhail Sukhov
Mikhail Sukhov

Pantov: Как их истории торгов от ИК «ЦЕРИХ» с помощью Qsh2Bin получить: quotes.bin trades.bin security.bin, а не orderlog.bin?

Спасибо.

Через Гидру.

Pantov
Pantov

Mikhail Sukhov:

Pantov: Как их истории торгов от ИК «ЦЕРИХ» с помощью Qsh2Bin получить: quotes.bin trades.bin security.bin, а не orderlog.bin?

Спасибо.

Через Гидру.

Спасибо. все сделал, но даже в Гидре есть только BIDы и в ОЛ и в конвертированных стаканах. Какие надо учесть ньюансы, что не так?

Mikhail Sukhov
Mikhail Sukhov

Pantov: все сделал, но даже в Гидре есть только BIDы и в ОЛ и в конвертированных стаканах. Какие надо учесть ньюансы, что не так?

https://github.com/StockSharp/Qsh2Bin/commit/8a314f967e918658219d6e44e4d5133b7e9e076f

Хочу к чему ОЛ при таком ДолларРубле...

Pantov
Pantov

Mikhail Sukhov:

Pantov: все сделал, но даже в Гидре есть только BIDы и в ОЛ и в конвертированных стаканах. Какие надо учесть ньюансы, что не так?

https://github.com/StockSharp/Qsh2Bin/commit/8a314f967e918658219d6e44e4d5133b7e9e076f

Хочу к чему ОЛ при таком ДолларРубле...

Все заработало, получил, что хотел, спасибо Михаил. Готов оплатить помощь, скажите куда.

Mikhail Sukhov
Mikhail Sukhov

Pantov: Все заработало, получил, что хотел, спасибо Михаил. Готов оплатить помощь, скажите куда.

Лучше выложите сконвертированное куда-то, чтобы не делать одно и то же всем.

Mikhail Sukhov
Mikhail Sukhov

https://github.com/StockSharp/Qsh2Bin/releases/tag/1.0.4

Фильтр по инструменту. Фикс экспорта в csv.

vk37
vk37

У меня получился несколько иной алгоритм конвертации. Возможно, кому-то окажется полезным:

if (ol.Flags.HasFlag(OrdLogFlags.Add))                           
{
    // Action 1 - заявка добавлена
    msg.OrderState = StockSharpOrderState.Active;
    msg.Action = 1;
}
else if (ol.Flags.HasFlag(OrdLogFlags.Fill))
{
    // Action 2 - заявка сведена в сделку
    msg.OrderState = StockSharpOrderState.Done;
    msg.Action = 2;
}
else
{
    // Action 0 - заявка удалена
    msg.OrderState = StockSharpOrderState.Done;
    msg.Action = 0;
}

if (ol.Flags.HasFlag(OrdLogFlags.NonZeroReplAct))
    msg.ReplAct = -1;

if (ol.Flags.HasFlag(OrdLogFlags.SessIdChanged))
    msg.SessId = -1;

var status = 0;

if (ol.Flags.HasFlag(OrdLogFlags.Canceled))
    status |= 0x200000;

if (ol.Flags.HasFlag(OrdLogFlags.CanceledGroup))
    status |= 0x400000;

if (ol.Flags.HasFlag(OrdLogFlags.Moved))
    status |= 0x100000;

if (ol.Flags.HasFlag(OrdLogFlags.Buy))
    msg.Side = Side.Buy;
else if (ol.Flags.HasFlag(OrdLogFlags.Sell))
    msg.Side = Side.Sell;
else
    throw new ArgumentException("Не задано направление заявки");

if (ol.Flags.HasFlag(OrdLogFlags.Quote))
{
    // котировочная
    msg.TimeInForce = StockSharpTimeInForce.PutInQueue;
    status |= 0x01;
}

if (ol.Flags.HasFlag(OrdLogFlags.Counter))
{
    // встречная
    msg.TimeInForce = StockSharpTimeInForce.CancelBalance;
    status |= 0x02;
}

if (ol.Flags.HasFlag(OrdLogFlags.FillOrKill))
{
    // fill-or-kill
    msg.TimeInForce = StockSharpTimeInForce.MatchOrCancel;
    status |= 0x80000;
}

if (ol.Flags.HasFlag(OrdLogFlags.NonSystem))
    status |= 0x04;

if (ol.Flags.HasFlag(OrdLogFlags.EndOfTransaction))
    status |= 0x1000;

if (ol.Flags.HasFlag(OrdLogFlags.CrossTrade))
    status |= 0x20000000;

msg.Status = status;

По 3 дням стакан построить не получилось: предполагаю что запись данных была выполнена с ошибками. Даты и время ошибок: 13.10.2014 Пн 19:00:55.878 11.06.2015 Чт 18:56:21.672 18.09.2015 Пт 18:51:07.919

sharafievrr
sharafievrr

После конвертации в из qsh в bin подкладываю данные в директорию где хранятся данные для гидры. Но при попытке получить тики по этому инструменту гидра говорит что данных нет. Что надо сделать чтобы гидра увидела файлы с сконвертированной историей?

Lexuz77
Lexuz77

sharafievrr: После конвертации в из qsh в bin подкладываю данные в директорию где хранятся данные для гидры. Но при попытке получить тики по этому инструменту гидра говорит что данных нет. Что надо сделать чтобы гидра увидела файлы с сконвертированной историей? Присоединяюсь к вопросу - ни гидра, ни дизайнер бетка эти данные (bin) не видит :(

Mikhail Sukhov
Mikhail Sukhov

Новая версия 1.0.5:

  1. Многопоточная обработка. Лучше запускать, если инструменты разбиты по разным файлам, как это сделано у Цериха.
  2. Преобрезование Order log в стаканы. Глубика по-умолчанию 5, правится в настройках в конфиг-файле.
  3. Фильтр инструментов по маске, перечисление через запятую. Например, SBER,RTS-*,BR будет означать поиск инструментов с названием SBER, вме инструменты, начинающиеся с RTS- и все инструменты, содержащие в названии BR (SBER, BRENT и т.д.).

Скачать

Напишите пожелание по утилите. Интересен ли вам сервис от Цериха, нужны ли в работе такие данные. Кто знает что стало с аналогичным сервисом от IT Invest?

JaguarFX
JaguarFX
JaguarFX

Программа очень и очень нужная для тестирования hft-стратегий на предмет того не являются ли они тестовыми граалыми, у которых чудо-доходность обусловлена исключительно несовершенством тестера (а-ля такого Мой hft-грааль). А так же подобные данные позволяют "исследовать" микроструктуру рынка на предмет реальных возможностей для заработка на фреймах ниже М1. Основное пожелание - интегрировать в следующую версию S#.Data данный сайт Цериха как доп. источник для скачивания данных с конвертацией "на лету" в формат bin с формированием OL или стаканов по выбору пользователя.

Mikhail Sukhov
Mikhail Sukhov

Лебедев Сергей: Основное пожелание - интегрировать в следующую версию S#.Data данный сайт Цериха как доп. источник для скачивания данных с конвертацией "на лету" в формат bin с формированием OL или стаканов по выбору пользователя.

Сайт поддерживает неофициально. Вполне вероятно, что у Цериха не хватает ресурсов, и он может быть закрыт в любое время. Тратить ресурсы на такую задачу нам не сильно охота. Да и что там автоматизировать? Закачку c FTP? Это делается любым download manager-ом на 1-2-3.

Константин
Константин

Конвертор не работает с файлами типа:

Название.AuxInfo.qsh Ошибка: Qsh2Bin 12.02.2018 19:27:26 Error "System.AggregateException: Произошла одна или несколько ошибок. ---> System.ArgumentOutOfRangeException: Время в формате UTC, представленное при применении смещения, должно находиться в диапазоне от 0 до 10 000 лет. Имя параметра: offset в System.DateTimeOffset.ValidateDate(DateTime dateTime, TimeSpan offset) в System.DateTimeOffset..ctor(DateTime dateTime, TimeSpan offset) в Ecng.Common.TimeHelper.ApplyTimeZone(DateTime dt, TimeZoneInfo zone) в StockSharp.Qsh2StockSharp.MainWindow.<>c__DisplayClass16_1.<ConvertFile>b__9(Int32 key, AuxInfo info) в QScalp.History.Reader.V4.AuxInfoStream.Read(Boolean push) в QScalp.History.Reader.V4.QshReaderImpl.Read(Boolean push) в StockSharp.Qsh2StockSharp.MainWindow.ConvertFile(String fileName, IStorageRegistry registry, StorageFormats format, ExchangeBoard board, String securityLike, Dictionary2 orderLog2OrderBookBuilders, Int32 orderBookMaxDepth) в StockSharp.Qsh2StockSharp.MainWindow.<>c__DisplayClass14_0.<ConvertDirectory>b__0(String f) в MoreLinq.MoreEnumerable.ForEach(IEnumerable1 source, Action1 action) в StockSharp.Qsh2StockSharp.MainWindow.ConvertDirectory(String path, IStorageRegistry registry, StorageFormats format, ExchangeBoard board, String securityLike, Boolean multithread, Dictionary2 orderLog2OrderBookBuilders, Int32 orderBookMaxDepth) в StockSharp.Qsh2StockSharp.MainWindow.<>c__DisplayClass13_0.<Convert_OnClick>b__0() в System.Threading.Tasks.Task.Execute() --- Конец трассировки внутреннего стека исключений --- ---> (Внутреннее исключение #0) System.ArgumentOutOfRangeException: Время в формате UTC, представленное при применении смещения, должно находиться в диапазоне от 0 до 10 000 лет. Имя параметра: offset в System.DateTimeOffset.ValidateDate(DateTime dateTime, TimeSpan offset) в System.DateTimeOffset..ctor(DateTime dateTime, TimeSpan offset) в Ecng.Common.TimeHelper.ApplyTimeZone(DateTime dt, TimeZoneInfo zone) в StockSharp.Qsh2StockSharp.MainWindow.<>c__DisplayClass16_1.<ConvertFile>b__9(Int32 key, AuxInfo info) в QScalp.History.Reader.V4.AuxInfoStream.Read(Boolean push) в QScalp.History.Reader.V4.QshReaderImpl.Read(Boolean push) в StockSharp.Qsh2StockSharp.MainWindow.ConvertFile(String fileName, IStorageRegistry registry, StorageFormats format, ExchangeBoard board, String securityLike, Dictionary2 orderLog2OrderBookBuilders, Int32 orderBookMaxDepth) в StockSharp.Qsh2StockSharp.MainWindow.<>c__DisplayClass14_0.<ConvertDirectory>b__0(String f) в MoreLinq.MoreEnumerable.ForEach(IEnumerable1 source, Action1 action) в StockSharp.Qsh2StockSharp.MainWindow.ConvertDirectory(String path, IStorageRegistry registry, StorageFormats format, ExchangeBoard board, String securityLike, Boolean multithread, Dictionary2 orderLog2OrderBookBuilders, Int32 orderBookMaxDepth) в StockSharp.Qsh2StockSharp.MainWindow.<>c__DisplayClass13_0.<Convert_OnClick>b__0() в System.Threading.Tasks.Task.Execute()<--- "

Mikhail Sukhov
Mikhail Sukhov

Поправил утилиту, чтобы поддерживала новый формат.

Утилитой кто-то пользуется? Или ОЛ уже интересен только единицам?

Дмитрий_ nik
torontoxx
torontoxx

Mikhail Sukhov: Поправил утилиту, чтобы поддерживала новый формат.

Утилитой кто-то пользуется? Или ОЛ уже интересен только единицам?

Здравствуйте. Я пользуюсь утилитой. Огромное за нее спасибо - очень полезная вещь. Но я обнаружил, что утилита неправильно собирает стакан. Как я это обнаружил. Я добавил в утилиту функцию подсчета суммарного объема стакана по бидам и аскам (глубина стакана 50) и сохранения суммарного объема, а также лучшей цены в файл. Т.е. я добавил после строки 509 метода ConvertFile файла MainWindow.xaml.cs следующий код (под спойлером):


var bestBidQuote = builder.Depth.GetBestBid();

decimal BestBidPrice = (bestBidQuote == null) ? 0 : bestBidQuote.Price;

decimal BidVolume = 0;

var quotes = builder.Depth.Bids.Take(orderBookMaxDepth).ToArray();

foreach (var item in quotes)
{

	BidVolume += item.Volume;
}

var bestAskQuote = builder.Depth.GetBestAsk();

decimal BestAskPrice = (bestAskQuote == null) ? 0 : bestAskQuote.Price;

decimal AskVolume = 0;

var quotes = builder.Depth.Asks.Take(orderBookMaxDepth).ToArray();

foreach (var item in quotes)
{

	AskVolume += item.Volume;
}

... сохраняем BestBidPrice, BidVolume, BestAskPrice, AskVolume в файл ...


Далее я протестировал утилиту на исторических данных фьючерса на индекс РТС (RTS-3.19), скаченных с сайта цериха и сравнил полученные объемы стакана с объемами, которые выводит QScalp на этих же исторических данных. Результаты отличались: объемы, рассчитанные утилитой на порядок превышали объемы QScalp. Я пришел к выводу, что проблема в коде в строках 438 - 441 метода ConvertFile файла MainWindow.xaml.cs:


else if (ol.Flags.Contains(OrdLogFlags.Moved))
{

	status |= 0x100000;
}

По совету пользователя vk37 от 26.01.2016 я установил OrderState = Done для заявок с флагом Moved:


else if (ol.Flags.Contains(OrdLogFlags.Moved))
{

    status |= 0x100000;
    msg.OrderState = OrderStates.Done;
}

И утилита стала считать объемы стакана правильно. Скажите пожалуйста, насколько мое решение верно? Пользователь vk37 в своем сообщении от 26.01.2016 вообще советует устанавливать OrderState = Done для всех заявок из ордерлога, кроме добавляемых заявок (с флагом Add). Скажите пожалуйста, насколько его совет правильный?

Но это еще не все. Когда я стал сравнивать лучшие цены и суммарные объемы стакана после вечернего клиринга с данными, выводимыми QScalp, то обнаружил, что они отличаются: объемы рассчитанные утилитой в разы превышали объемы QScalp. Я пришел к выводу, что утилита при сборке стакана некорректно обрабатывает вечерний клиринг, фактически не очищая стакан. Вот пример результата работы утилиты в вечерний клиринг:

  1. Перед вечерним клирингом (время 18:44:59.926) суммарный объем по бидам = 2186, по аскам = 1889.
  2. При обработке всех последующих заявок из ордерлога в период вечернего клиринга получаем пустой стакан (список котировок по бидам и аскам, а также лучшие цены пустые).
  3. Начало вечерней сессии (время 19:0:0.347). Поступила заявка, в результате которой получаем лучшую цену по аскам, а суммарный объем по аскам = 2612, что фактически составляет суммарный объем до клиринга плюс объем заявок, поступивших в период вечернего клиринга.
  4. Аналогично с бидами: время 19:0:0.505, поступает заявка, в результате которой получаем лучшую цену по бидам, а суммарный объем по бидам = 2536, что фактически составляет суммарный объем до клиринга плюс объем заявок, поступивших в период вечернего клиринга.

Я решил очищать стакан в вечерний клиринг просто создавая новый экземпляр builder:


builder = new PlazaOrderLogMarketDepthBuilder(securityId);

Теперь результаты утилиты и QScalp совпадают.

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

Константин
Константин

Я юзаю сею утиль

torontoxx
torontoxx

Хотя нет, утилита все еще неудовлетворительно собирает стакан. Стал на истории сравнивать лучшие цены, рассчитанные утилитой с лучшими ценами, выводимыми QScalp и обнаружил, что разница между ними большая. Для фьючерса на индекс РТС за 25 февраля, например разница составляет 2-3 шага цены (20-30 пунктов)

torontoxx
torontoxx

Все-таки интересно, почему лучшие цены в стакане, собранным утилитой (PlazaOrderLogMarketDepthBuilder) отличаются от лучших цен QScalp. Неужели один из двух дает неверный результат? Или я что-то не понимаю...

Дмитрий_
Дмитрий_

Добрый день.

Подскажите пожалуйста.

Имею данные (c ftp://athistory.zerich.com/). GAZP.2019-01-30.Deals.qsh GAZP.2019-01-30.Quotes.qsh LKOH.2019-01-30.Deals.qsh LKOH.2019-01-30.Quotes.qsh

Снимок.PNG Пробовал ставить и MICEX площадку и бинарные данные.

Стаканы грузятся корректно, но сделки не совсем.

Для Газпрома цену нужно разделить на 100 и тогда ок. Снимок.PNG

Для Лукойла цену нужно разделить на 2 и тогда ок. Снимок.PNG

Почему так получается?

torontoxx
torontoxx

Дмитрий Антипов: Добрый день.

Подскажите пожалуйста.

Почему так получается?

Может надо цену умножать на шаг (priceStep) по аналогии с заявками из ордерлога?

Дмитрий_
Дмитрий_

torontoxx:

Дмитрий Антипов: Добрый день.

Подскажите пожалуйста.

Почему так получается?

Может надо цену умножать на шаг (priceStep) по аналогии с заявками из ордерлога?

Подскажите пожалуйста, на какой строке проекта находится данная "аналогия с заявками из ордерлога"?

Отследил чтение. Нужно в этом методе что-то менять? Снимок.PNG

torontoxx
torontoxx

Дмитрий Антипов:

torontoxx:

Дмитрий Антипов: Добрый день.

Подскажите пожалуйста.

Почему так получается?

Может надо цену умножать на шаг (priceStep) по аналогии с заявками из ордерлога?

Подскажите пожалуйста, на какой строке проекта находится данная "аналогия с заявками из ордерлога"?

Отследил чтение. Нужно в этом методе что-то менять? Снимок.PNG

Попробуйте поменять строку №380 в файле MainWindow.xaml.cs:

Старая строка: TradePrice = deal.Price, Исправленная срока: TradePrice = deal.Price * priceStep,

Viacheslav
Viacheslav

Коллеги, правильно ли я понимаю, что файлы сделок и стаканов на athistory.zerich.com и http://qsh.qscalp.ru/scalping.pro - это данные по Московской бирже?

torontoxx
torontoxx

Viacheslav: Коллеги, правильно ли я понимаю, что файлы сделок и стаканов на athistory.zerich.com и http://qsh.qscalp.ru/scalping.pro - это данные по Московской бирже?

Надо полагать, да

Sun_Storm
Sun_Storm

Добрый день. Пробую сейчас сконвертировать данные через этот конвертер. Данные беру отсюда: http://erinrv.qscalp.ru, за апрель Возникли следующие ошибки: При загрузке данных стаканов по акциям Сбербанка возникала ошибка и данные не грузились. Проблему я решил, порывшись в исходниках. там в исходном файле в начале торгов есть строки с ценой и объемом 0 и типом Unknown. Когда тип Unknown, программа сразу выдает исключение:


switch (q.Type)
{
	case QuoteType.Unknown:
	case QuoteType.Free:
	case QuoteType.Spread:
		throw new ArgumentException(q.Type.ToString());

Написал пока так для себя, не знаю, как в С# принято такое обрабатывать, когда у нас только 2 значения side:


switch (q.Type)
{
	case QuoteType.Free:
	case QuoteType.Spread:
		throw new ArgumentException(q.Type.ToString());
	case QuoteType.Unknown:
		\\throw new ArgumentException(q.Type.ToString());
		side = 0;
		break;

Второй ошибкой является то, что для всех стаканов (файл quotes) время проставляется одно и то же для каждой строчки на весь файл. Эта ошибка проявляется и для акций и для фьючерсов. Пока не могу её побороть. сохранение в файл делается средствами StockSharp.Algo.Storages, все исходники там, как я понимаю. По отладке не могу понять, какие параметры должны быть у pair, чтобы в строке registry.GetQuoteMessageStorage(pair.Key, format: format).Save(pair.Value.Item1); запись происходила как надо. Пробовал менять LocalTime и ServerTime для каждого набора, всё равно сохраняет неправильно (со временем 35517549, например)

Sun_Storm
Sun_Storm

Опытным путем разобрался с проблемой времени! Если у вас в папке, из которой вы конвертируете, лежат сразу 3 файла на день из архива http://erinrv.qscalp.ru (Deals, Quotes И AuxInfo), то конвертация будет некорректной! Я скачивал сразу все 3 файла, и из одной папки конвертировал, поэтому была ошибка. Если в папке лежат 2 файла на день - Deals, Quotes, то всё конвертируется нормально (если не считать ошибки по акциям, описанной мной выше)

UPD: В общем это я поспешил, что разобрался, всё равно время некорректно ставится. Ошибка плавающая... Я в потоках этих не разбираюсь... Однако, если прописать вместо ServerTime = currentDate.ApplyTimeZone(TimeHelper.Moscow), ServerTime = qr.CurrentDateTime.ApplyTimeZone(TimeHelper.Moscow), то вроде будет работать и время сменяться. Только в файлах начало дня при таком раскладе будет 4 часа.

traveller
traveller

Тип Unknown для quotes действительно надо фильтровать, в файле MainWindow.xaml.cs я добавил Where var quotes2 = quotes**.Where(q => q.Type != QuoteType.Unknown)**.Select(... что позволяет сразу выкинуть этот тип из рассмотрения.

И цена бывает иногда нулевая, тоже можно фильтровать при желании.

Для правки времени согласен с постом выше, можно использовать ServerTime = qr.CurrentDateTime.ApplyTimeZone(TimeHelper.Moscow) и тогда присвоение currentDate выше можно удалить, оно нигде не используется.

MichaelShpin
MichaelShpin

Писал подобную утилиту для TSLab и тоже заметил проблему рассинхронизации стакана и сделок. Как я понял эту проблему:

  • Есть лаг между событием на бирже и записью в локальный фаил. Он может достигать существенное количество секунд.
  • Записанный отдельно стакан в Quotes.qsh не имеет того самого реального (биржевого события), а только время локальной записи.
  • Сделка же летит сразу со временем, и можно увидеть этот лаг между временем записи и времен в самой сделке.
    При генерации из ордер лога всё хорошо, так как в логе есть все записи, а вот с акциями придётся наворачивать.

Как поступил я.

Если акция я просто создаю сразу 2 QshReader для Deals.qsh и Quotes.qsh. И начинаю их читать опираясь на внутреннее время записи QshReader CurrentDateTime, и стакан синхронизирую относительно времени сделки.



if (readers.Count > 1)
				{
					while (true)
					{
						if (readers.All(qr => qr.CurrentDateTime == DateTime.MaxValue))
							break;

						QshReader rd = readers.OrderBy(qr => qr.CurrentDateTime).First();
						rd.Read(true);
					}

					foreach (QshReader r in readers)
						r.Dispose();
				}
				else 
				{
					QshReader qr = readers[0];

					while (qr.CurrentDateTime != DateTime.MaxValue)
						qr.Read(true);

					qr.Dispose();
				}

Есть засада, что стаканы до первой сделки придётся проигнорировать, но в моей задаче была цель узнать лучший Бид/Аск в момент сделки и я её так решил.

Надеюсь помог.

Думаю скоро погружусь в эту задачу и для StokSharp

GIP
GIP

Позвольте глупый вопрос... При импорте данных QSH по инструменту RIZ2019 за 20.11.19 первая строка: 064624425;+03:00;637098399844250000;38091733454;143780;1;Buy;Done;PutInQueue;;;; 64624425 это время в миллисекундах с начала дня, получается 18 часов? Или это 06:46? Первая сделка должна проходить в 10:00 мск.

samosh
samosh

Здравствуйте, у меня Qsh2bin не видит файлы QSH

Di
Di

Я не трейдер, меня попросили сконвертировать данные в csv или txt, нашел вашу утилиту, но она выдает ошибку при конвертации. qsh.7z исходные файлы и то что получается SBER@FORTS.7z

Что делаю не так?

Mikhail Sukhov
Mikhail Sukhov

Обновил утилиту. Перевел на 17ую версию, заобно пофиксил ошибки. Бинарники так же по ссылке https://github.com/StockSharp/Qsh2Bin/releases

Важный момент при анализе записей. QSH не имеет признака временной зоны у времени. Поэтому понять в какой временной зоне записаны данные невозможно. С большей вероятностью она может быть или Московская или UTC. Точно могу сказать, что Церих и Айти в разных временных зонах пишут данные.

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

Как решить это проблему. Конечно же, надо писать всё в UTC. Но данные и формат уже легаси, поэтому в утилите две выпадающих списка. Один для установка временной зоны локальной отметки, другой для биржевой.

После конвертации может Гидрой или через S#.Storage API просмотреть полученные данные на предмет времени. Если начало торгов что-то вроде 7 часов утра - значит временная зона была в UTC.

Пишите о своём опыте использования. Ошибки старайтесь сами исправить, исходники на Гите. Папку с рефами не заливал, чтобы не захламлять дистрибутив. Думаю, кто умеет код пистать, эту проблему порешает.

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

nik
zoh
zoh

Mikhail Sukhov: Обновил утилиту. Перевел на 17ую версию, заобно пофиксил ошибки. Бинарники так же по ссылке https://github.com/StockSharp/Qsh2Bin/releases

Важный момент при анализе записей. QSH не имеет признака временной зоны у времени. Поэтому понять в какой временной зоне записаны данные невозможно. С большей вероятностью она может быть или Московская или UTC. Точно могу сказать, что Церих и Айти в разных временных зонах пишут данные.

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

Как решить это проблему. Конечно же, надо писать всё в UTC. Но данные и формат уже легаси, поэтому в утилите две выпадающих списка. Один для установка временной зоны локальной отметки, другой для биржевой.

После конвертации может Гидрой или через S#.Storage API просмотреть полученные данные на предмет времени. Если начало торгов что-то вроде 7 часов утра - значит временная зона была в UTC.

Пишите о своём опыте использования. Ошибки старайтесь сами исправить, исходники на Гите. Папку с рефами не заливал, чтобы не захламлять дистрибутив. Думаю, кто умеет код пистать, эту проблему порешает.

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

А АйТи ещё продолжает шарить записи с qscalp ?