В общем , повозился и выяснил.
Это – БАГ.
То ли в гидре то ли еще где в недрах C#
Проверял Так.
Модифицировал Гидру, а именно ф-ию OnMarketDepthsChanged. Смысл в том, что я создаю свой текстовый файл, в который пишу стаканы для "SBER@EQBR" и RIZ2@RTS". При этом запоминаю момент, когда пришло управление в ф-ию OnMarketDepthsChanged() и записываю это время в свой файл вместе со временем MarketDepth.LastChangeTime.
Как видно из дальнейших логов эти два времени в точности совпадают.
Прочая функциональность гидры осталась без изменений:
private void OnMarketDepthsChanged(IEnumerable<MarketDepth> depths)
{
DateTime dtCur = DateTime.Now;
depths.ForEach(d =>
{
//Trace.WriteLine("MDA " +dc.Security+":"+dc._DebugId+":"+ dc.LastChangeTime.ToString("HHmmss.fff"));
if (d.Bids.Length > 0 || d.Asks.Length > 0)
{
_depthsBuffer.Add(d.Security, d.Clone());
}
});
if (null != sm_FlogDepth)
{
var testDepth = depths.Where(dtst => ((dtst.Security.Id == "SBER@EQBR") || (dtst.Security.Id == "RIZ2@RTS")));
foreach (MarketDepth myD in testDepth)
{
if (myD.Bids.Length > 0 || myD.Asks.Length > 0)
{
sm_FlogDepth.Write(myD.Security.Id);
sm_FlogDepth.Write(",");
sm_FlogDepth.Write(dtCur.ToString());
sm_FlogDepth.Write(".");
sm_FlogDepth.Write(dtCur.Millisecond);
sm_FlogDepth.Write(",");
sm_FlogDepth.Write(myD.LastChangeTime.ToString());
sm_FlogDepth.Write(".");
sm_FlogDepth.Write(myD.LastChangeTime.Millisecond);
sm_FlogDepth.Write(",");
sm_FlogDepth.Write(myD.Latency.ToString());
sm_FlogDepth.Write(",");
sm_FlogDepth.Write(myD.Asks[0].Price);
sm_FlogDepth.Write("(");
sm_FlogDepth.Write(myD.Asks[0].Volume);
sm_FlogDepth.Write(")-");
sm_FlogDepth.Write(myD.Bids[0].Price);
sm_FlogDepth.Write("(");
sm_FlogDepth.Write(myD.Bids[0].Volume);
sm_FlogDepth.Write(")");
sm_FlogDepth.WriteLine();
}
}
if (testDepth.Any())
sm_FlogDepth.Flush();
}
}
Далее читаю записанные данные, сохраненные гидрой. Для этого использовал доработанный вариант SampleStorage. Вот полный код:
namespace SampleStorage
{
using System;
using System.Collections.Generic;
using System.Linq;
using Ecng.Common;
using StockSharp.Algo.Storages;
using StockSharp.Algo.Testing;
using StockSharp.BusinessEntities;
class Program
{
struct depthDebugView
{
public DateTime LastChangeTime;
public Quote BestAsk;
public Quote BestBid;
public depthDebugView(MarketDepth t)
{
LastChangeTime = t.LastChangeTime;
BestAsk = t.BestAsk;
BestBid = t.BestBid;
}
// Получить строковое представление.
public override string ToString()
{
return LastChangeTime.ToString() + "." + LastChangeTime.Millisecond.ToString() + ","
+ BestAsk.Price.ToString() + "(" + BestAsk.Volume.ToString() + ")"
+ "-" + BestBid.Price.ToString() + "(" + BestBid.Volume.ToString() + ")";
}
};
static void Main()
{
// создаем тестовый инструмент
var security = new Security
{
Id = "RIZ2@RTS",
};
var storage = new StorageRegistry();
string dPATH = "E:\\TradeDB\\Hydra\\Data";
// получаем хранилище для тиковых сделок
var tradeStorage = storage.GetTradeStorage(security, new LocalMarketDataDrive(dPATH));
// загружаем сделки
DateTime dtDayToLoad = new DateTime(2012, 10, 24);
var trList = tradeStorage.Load(dtDayToLoad);
// получаем хранилище для стаканов
var depthStorage = storage.GetMarketDepthStorage(security, new LocalMarketDataDrive(dPATH));
// загружаем стаканы
var depthData = depthStorage.Load(dtDayToLoad);
// Фикс проблемы со временем - всем элементам принудительно ставим DateTimeKind.Local
// Иначе - где-то Local, а где-то Unspecified => проблемы с конвертацией
foreach (MarketDepth t in depthData)
{
t.LastChangeTime = DateTime.SpecifyKind(t.LastChangeTime, DateTimeKind.Local);
}
//Берем нужный кусок данных из загруженных стаканов
DateTime dtLoadFromTime = new DateTime(2012, 10, 24, 15, 48, 30, DateTimeKind.Local);
DateTime dtLoadToTime = new DateTime(2012, 10, 24, 15, 50, 00, DateTimeKind.Local);
var depthData2 = depthData.Where(d => dtLoadFromTime <= d.LastChangeTime && d.LastChangeTime <= dtLoadToTime);
var depthDebug = depthData2.Select(d => new depthDebugView(d));
//Здесь ставим брякпойнт и наблюдаем содержимое depthDebug
//Сравниваем его с сохраненным ранее логом от модифицированной Гидры
Console.WriteLine("Количество загруженных сделок: " + trList.Count());
foreach (Trade t in trList)
{
Console.WriteLine(t.Time + "(" + t.Latency.TotalSeconds + "c) : " + t.Price + " : " + t.Volume + "( " + t.OrderDirection + " )");
System.Threading.Thread.Sleep(32);
}
foreach (MarketDepth t in depthData2)
{
Console.WriteLine(t.LastChangeTime + " : " + t.BestBid.Price + " - " + t.BestAsk.Price + " : " + (t.BestBid.Volume - t.BestAsk.Volume));
System.Threading.Thread.Sleep(32);
}
Console.ReadLine();
}
}
}
И так, результат.
Вот, что реально приходило в OnMarketDepthsChanged() и должно было быть сохранено. Данные по моим собственным логам:
RIZ2@RTS,2012-10-24 15:49:01.424,2012-10-24 15:49:01.424,-04:00:00,145750(38)-145740(4)
RIZ2@RTS,2012-10-24 15:49:01.658,2012-10-24 15:49:01.658,-04:00:00,145750(35)-145740(4)
RIZ2@RTS,2012-10-24 15:49:01.736,2012-10-24 15:49:01.736,-04:00:00,145750(4)-145740(7)
RIZ2@RTS,2012-10-24 15:49:01.970,2012-10-24 15:49:01.970,-04:00:00,145760(36)-145750(4)
RIZ2@RTS,2012-10-24 15:49:02.158,2012-10-24 15:49:02.158,-04:00:00,145750(3)-145740(4)
RIZ2@RTS,2012-10-24 15:49:02.392,2012-10-24 15:49:02.392,-04:00:00,145750(3)-145740(7)
RIZ2@RTS,2012-10-24 15:49:02.516,2012-10-24 15:49:02.516,-04:00:00,145760(26)-145740(6)
RIZ2@RTS,2012-10-24 15:49:02.719,2012-10-24 15:49:02.719,-04:00:00,145750(3)-145740(14)
RIZ2@RTS,2012-10-24 15:49:02.922,2012-10-24 15:49:02.922,-04:00:00,145750(7)-145740(13)
RIZ2@RTS,2012-10-24 15:49:03.156,2012-10-24 15:49:03.156,-04:00:00,145750(7)-145740(3)
RIZ2@RTS,2012-10-24 15:49:03.296,2012-10-24 15:49:03.296,-04:00:00,145750(7)-145740(3)
RIZ2@RTS,2012-10-24 15:49:03.484,2012-10-24 15:49:03.484,-04:00:00,145750(7)-145740(22)
А вот, что было затем прочитано из хранилища:
+ [32] {2012-10-24 15:48:37.436,145750(38)-145740(4)} SampleStorage.Program.depthDebugView
+ [33] {2012-10-24 15:48:37.670,145750(35)-145740(4)} SampleStorage.Program.depthDebugView
+ [34] {2012-10-24 15:48:37.748,145750(4)-145740(7)} SampleStorage.Program.depthDebugView
+ [35] {2012-10-24 15:48:37.982,145760(36)-145750(4)} SampleStorage.Program.depthDebugView
+ [36] {2012-10-24 15:48:38.169,145750(3)-145740(4)} SampleStorage.Program.depthDebugView
+ [37] {2012-10-24 15:48:38.403,145750(3)-145740(7)} SampleStorage.Program.depthDebugView
+ [38] {2012-10-24 15:48:38.527,145760(26)-145740(6)} SampleStorage.Program.depthDebugView
+ [39] {2012-10-24 15:48:38.729,145750(3)-145740(14)} SampleStorage.Program.depthDebugView
+ [40] {2012-10-24 15:48:38.931,145750(7)-145740(13)} SampleStorage.Program.depthDebugView
+ [41] {2012-10-24 15:48:39.165,145750(7)-145740(3)} SampleStorage.Program.depthDebugView
+ [42] {2012-10-24 15:48:39.305,145750(7)-145740(3)} SampleStorage.Program.depthDebugView
+ [43] {2012-10-24 15:48:39.492,145750(7)-145740(22)} SampleStorage.Program.depthDebugView
************************************
+ [154] {2012-10-24 15:49:01.425,145800(1)-145790(16)} SampleStorage.Program.depthDebugView
+ [155] {2012-10-24 15:49:01.612,145810(31)-145790(16)} SampleStorage.Program.depthDebugView
+ [156] {2012-10-24 15:49:01.861,145810(29)-145790(16)} SampleStorage.Program.depthDebugView
+ [157] {2012-10-24 15:49:01.985,145810(30)-145790(19)} SampleStorage.Program.depthDebugView
+ [158] {2012-10-24 15:49:02.219,145810(29)-145790(18)} SampleStorage.Program.depthDebugView
+ [159] {2012-10-24 15:49:02.421,145810(31)-145790(18)} SampleStorage.Program.depthDebugView
+ [160] {2012-10-24 15:49:02.686,145880(1)-145820(14)} SampleStorage.Program.depthDebugView
+ [161] {2012-10-24 15:49:02.748,145830(10)-145820(14)} SampleStorage.Program.depthDebugView
+ [162] {2012-10-24 15:49:02.997,145880(19)-145870(2)} SampleStorage.Program.depthDebugView
+ [163] {2012-10-24 15:49:03.75,145990(72)-145880(2)} SampleStorage.Program.depthDebugView
+ [164] {2012-10-24 15:49:03.246,145950(5)-145900(5)} SampleStorage.Program.depthDebugView
+ [165] {2012-10-24 15:49:03.292,145950(10)-145890(4)} SampleStorage.Program.depthDebugView
Обратите внимание на времена и значения Асков-Бидов. Все прочитанные данные получили отрицательное смещение по времени на ~14 секунд.