diff --git a/Test/PbTickCodecTestV2.cs b/Test/PbTickCodecTestV2.cs index 61d962a..d1a4957 100644 --- a/Test/PbTickCodecTestV2.cs +++ b/Test/PbTickCodecTestV2.cs @@ -16,6 +16,11 @@ public void Test2List() } static void Main(string[] args) + { + + } + + static void Main4(string[] args) { List oldPrevList = new List(); List oldCurrList = new List(); diff --git a/Test/Test.csproj b/Test/Test.csproj index be78cc7..3d37fe9 100644 --- a/Test/Test.csproj +++ b/Test/Test.csproj @@ -38,6 +38,10 @@ + + ..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll + True + @@ -63,6 +67,9 @@ QuantBox.Data.Serializer + + + diff --git a/Test/packages.config b/Test/packages.config index 7e5ac42..88d50d3 100644 --- a/Test/packages.config +++ b/Test/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/csharp/QuantBox.Data.Serializer/V2/DepthItem.cs b/csharp/QuantBox.Data.Serializer/V2/DepthItem.cs new file mode 100644 index 0000000..aa50f08 --- /dev/null +++ b/csharp/QuantBox.Data.Serializer/V2/DepthItem.cs @@ -0,0 +1,31 @@ +namespace QuantBox.Data.Serializer.V2 +{ + public class DepthItem + { + public int Price; + public int Size; + public int Count; + + public DepthItem() + { + + } + + public DepthItem(int price, int size, int count) + { + Price = price; + Size = size; + Count = count; + } + + public bool IsZero + { + get + { + return Price == 0 + && Size == 0 + && Count == 0; + } + } + } +} \ No newline at end of file diff --git a/csharp/QuantBox.Data.Serializer/V2/DepthList.cs b/csharp/QuantBox.Data.Serializer/V2/DepthList.cs index a63c255..55a3138 100644 --- a/csharp/QuantBox.Data.Serializer/V2/DepthList.cs +++ b/csharp/QuantBox.Data.Serializer/V2/DepthList.cs @@ -7,36 +7,6 @@ namespace QuantBox.Data.Serializer.V2 { public class DepthList { - // 一定要关闭才行 - // 1.只有买价,先AddStart(1),然后SetAsk(2),SetEnd(2) - // 2.只有卖价,先AddStart(1),然后SetAsk(1),SetEnd(2) - // 3.啥都没有,先AddStart(1),然后SetAsk(1),SetEnd(1) - public int Start; - public int AskPrice1; - public int End; - public readonly List List = new List(); - - public void AddStart(int price, int size, int count) - { - List.Clear(); - List.Add(new DepthItem(price, size, count)); - Start = price; - } - - public void Add(int price, int size, int count) - { - List.Add(new DepthItem(price, size, count)); - } - - public void SetAskPrice1(int price) - { - AskPrice1 = price; - } - - public void SetEnd(int price) - { - End = price; - } } } diff --git a/csharp/QuantBox.Data.Serializer/V2/DepthListHelper.cs b/csharp/QuantBox.Data.Serializer/V2/DepthListHelper.cs new file mode 100644 index 0000000..8388ce4 --- /dev/null +++ b/csharp/QuantBox.Data.Serializer/V2/DepthListHelper.cs @@ -0,0 +1,448 @@ +using System; +using System.Collections.Generic; + +namespace QuantBox.Data.Serializer.V2 +{ + public class DepthListHelper + { + #region Listе㷨 + public static void ExpandTwoListsToSameLength(List oldPrevList, List oldCurrList, int startPrice, int endPrice, List newPrevList, List newCurrList) + { + newPrevList.Clear(); + newCurrList.Clear(); + + if (oldPrevList == null) + oldPrevList = new List(); + if (oldCurrList == null) + oldCurrList = new List(); + + DepthItem prevItem = null; + + // һ¼ʼ + var i = 0; + var j = 0; + for (; i < oldCurrList.Count; ++i) { + var currItem = oldCurrList[i]; + + // бݵķΧ + if (currItem.Price < startPrice) + continue; + if (currItem.Price > endPrice) + break; + + for (; j < oldPrevList.Count; ++j) { + prevItem = oldPrevList[j]; + + + if (prevItem.Price < startPrice) + continue; + // &&ԭcurrڷΧڣprevڷΧ + if (prevItem.Price > endPrice && currItem.Price > endPrice) + break; + + if (currItem.Price == prevItem.Price) { + // ߶,ֱ߶ + newPrevList.Add(prevItem); + newCurrList.Add(currItem); + + // ָ붼ƶ + ++j; + break; + } + if (currItem.Price < prevItem.Price) { + // еļ۸СµĸƣȻµָƶ + newCurrList.Add(currItem); + newPrevList.Add(new DepthItem() { Price = currItem.Price }); + break; + } + // ϵļ۸СϵĸƣȻ + newPrevList.Add(prevItem); + newCurrList.Add(new DepthItem() { Price = prevItem.Price }); + } + + // ʷѾˢ꣬ǰĻ + if (j == oldPrevList.Count) { + if (currItem.Price > endPrice) + break; + + // ֻݣûݵ + if (prevItem == null || currItem.Price > prevItem.Price) { + newCurrList.Add(currItem); + newPrevList.Add(new DepthItem() { Price = currItem.Price }); + } + } + } + // ǰѾˢ꣬ȥˢʷ + for (; j < oldPrevList.Count; ++j) { + prevItem = oldPrevList[j]; + + // ֻʷû + if (prevItem.Price < startPrice) + continue; + if (prevItem.Price > endPrice) + break; + + newPrevList.Add(prevItem); + newCurrList.Add(new DepthItem() { Price = prevItem.Price }); + } + } + + public static void SizeMinusInTwoLists(List oldPrevList, List oldCurrList, List newList) + { + if (oldPrevList.Count != oldCurrList.Count) { + + } + + newList.Clear(); + for (var i = 0; i < oldPrevList.Count; ++i) { + var prevItem = oldPrevList[i]; + var currItem = oldCurrList[i]; + newList.Add(new DepthItem(currItem.Price, currItem.Size - prevItem.Size, currItem.Count - prevItem.Count)); + } + } + + public static void SizeAddInTwoLists(List oldPrevList, List oldCurrList, List newList) + { + if (oldPrevList.Count != oldCurrList.Count) { + + } + + newList.Clear(); + for (var i = 0; i < oldPrevList.Count; ++i) { + var prevItem = oldPrevList[i]; + var currItem = oldCurrList[i]; + // Ϊ0Чʾ + var size = currItem.Size + prevItem.Size; + if (size != 0) + newList.Add(new DepthItem(currItem.Price, size, currItem.Count + prevItem.Count)); + } + } + + public static void PriceMinusInOneList(List oldList, List newList) + { + newList.Clear(); + + DepthItem prevItem = null; + + for (var i = 0; i < oldList.Count; ++i) { + var currItem = oldList[i]; + // Ϊ0Ķ + if (currItem.Size == 0) + continue; + + if (prevItem == null) { + newList.Add(currItem); + } + else { + newList.Add(new DepthItem(currItem.Price - prevItem.Price - 1, currItem.Size, currItem.Count)); + } + + prevItem = currItem; + } + } + + public static void PriceAddInOneList(IEnumerable oldList, List newList) + { + newList.Clear(); + + DepthItem prevItem = null; + + foreach (var currItem in oldList) { + if (prevItem == null) { + prevItem = currItem; + newList.Add(currItem); + } + else { + prevItem = new DepthItem(currItem.Price + prevItem.Price + 1, currItem.Size, currItem.Count); + newList.Add(prevItem); + } + } + } + #endregion + + #region Listṹת + public static int GetDepthTick14(DepthTick tick, int pos) + { + var fromNext = tick; + + switch (pos) { + case 1: + return fromNext.Value1; + case 2: + return fromNext.Value2; + case 3: + return fromNext.Value3; + case 4: + return fromNext.Value4; + case 5: + return fromNext.Value5; + case 6: + return fromNext.Value6; + case 7: + return fromNext.Value7; + case 8: + return fromNext.Value8; + case 9: + return fromNext.Value9; + case 10: + return fromNext.Value10; + case 11: + return fromNext.Value11; + case 12: + return fromNext.Value12; + case 13: + return fromNext.Value13; + case 14: + return fromNext.Value14; + } + return 0; + } + + public static void SetDepthTick14(DepthTick tick, int pos, int value) + { + var fromNext = tick; + switch (pos) { + case 1: + fromNext.Value1 = value; + break; + case 2: + fromNext.Value2 = value; + break; + case 3: + fromNext.Value3 = value; + break; + case 4: + fromNext.Value4 = value; + break; + case 5: + fromNext.Value5 = value; + break; + case 6: + fromNext.Value6 = value; + break; + case 7: + fromNext.Value7 = value; + break; + case 8: + fromNext.Value8 = value; + break; + case 9: + fromNext.Value9 = value; + break; + case 10: + fromNext.Value10 = value; + break; + case 11: + fromNext.Value11 = value; + break; + case 12: + fromNext.Value12 = value; + break; + case 13: + fromNext.Value13 = value; + break; + case 14: + fromNext.Value14 = value; + break; + } + } + + public static void SetDepthTick(DepthTick tick, int pos, int value) + { + var from_next = tick; + + while (pos > 0) { + if (from_next == null) + return; + + if (pos <= 14) { + SetDepthTick14(from_next, pos, value); + } + + pos -= 14; + + if (pos > 0) { + if (from_next.Next == null) + from_next.Next = new DepthTick(); + from_next = from_next.Next; + } + } + } + + public static int GetDepthTick(DepthTick tick, int pos) + { + var from_next = tick; + + while (pos > 0) { + if (from_next == null) + return 0; + + if (pos <= 14) { + return GetDepthTick14(from_next, pos); + } + + pos -= 14; + + if (pos > 0) { + if (from_next.Next == null) + return 0; + from_next = from_next.Next; + } + } + + return 0; + } + + public static void ListToStruct(IEnumerable list, int dataCount, DepthTick tick) + { + var pos = 0; + foreach (var currItem in list) { + switch (dataCount) { + case 1: + SetDepthTick(tick, ++pos, currItem.Price); + break; + case 2: + SetDepthTick(tick, ++pos, currItem.Price); + SetDepthTick(tick, ++pos, currItem.Size); + break; + case 3: + SetDepthTick(tick, ++pos, currItem.Price); + SetDepthTick(tick, ++pos, currItem.Size); + SetDepthTick(tick, ++pos, currItem.Count); + break; + } + } + } + + public static void StructToList(DepthTick tick, int dataCount, List list) + { + list.Clear(); + + var fromNext = tick; + + DepthItem item = null; + var pos = 0; + + while (fromNext != null) { + for (var i = 1; i <= 14; ++i) { + pos += 1; + if (dataCount == 3) { + switch (pos % dataCount) { + case 1: + item = new DepthItem(); + item.Price = GetDepthTick14(fromNext, i); + break; + case 2: + item.Size = GetDepthTick14(fromNext, i); + break; + case 0: + item.Count = GetDepthTick14(fromNext, i); + list.Add(item); + break; + } + } + else if (dataCount == 2) { + switch (pos % dataCount) { + case 1: + item = new DepthItem(); + item.Price = GetDepthTick14(fromNext, i); + break; + case 0: + item.Size = GetDepthTick14(fromNext, i); + list.Add(item); + break; + } + } + else if (dataCount == 1) { + switch (pos % dataCount) { + case 0: + item = new DepthItem(); + item.Price = GetDepthTick14(fromNext, i); + list.Add(item); + break; + } + } + } + + // ָһ + fromNext = fromNext.Next; + } + + // ṹص㣬ЩΪյݼ,Ҫɾȥ + for (var j = list.Count - 1; j >= 0; --j) { + if (list[j].IsZero) { + list.RemoveAt(j); + } + else { + break; + } + } + } + #endregion + + /// + /// ֻ۸ȷ + /// δ + /// ֻۣ0һλþһ + /// ֻۣ=list.count˵count=2,һ۾list.count-1=1 + /// ûУlist.count=0;-1 + /// + /// + /// + /// + public static int FindAsk1Position(List list, int askPrice1) + { + if (list == null || list.Count == 0) + return -1; + + var i = 0; + for (; i < list.Count; ++i) { + var currItem = list[i]; + if (currItem.Price > askPrice1) { + return i - 1; + } + if (currItem.Price == askPrice1) { + return i; + } + } + + return i; + } + + public static int FindAsk1Position(List list, double askPrice1) + { + if (list == null || list.Count == 0) + return -1; + + var i = 0; + for (; i < list.Count; i++) { + var currItem = list[i]; + if (currItem.Price > askPrice1) { + return i - 1; + } + if (Math.Abs(currItem.Price - askPrice1) < double.Epsilon) { + return i; + } + } + return i; + } + + public static int FindAsk1PositionDescending(List list, double askPrice1) + { + if (list == null || list.Count == 0) + return -1; + + var i = 0; + for (; i < list.Count; ++i) { + var currItem = list[i]; + if (currItem.Price < askPrice1) { + return i - 1; + } + if (Math.Abs(currItem.Price - askPrice1) < double.Epsilon) { + return i; + } + } + return i; + } + } +} \ No newline at end of file diff --git a/csharp/QuantBox.Data.Serializer/V2/PbTickCodec.cs b/csharp/QuantBox.Data.Serializer/V2/PbTickCodec.cs index e0c4c06..d0d9bb4 100644 --- a/csharp/QuantBox.Data.Serializer/V2/PbTickCodec.cs +++ b/csharp/QuantBox.Data.Serializer/V2/PbTickCodec.cs @@ -776,14 +776,13 @@ public List Restore(IEnumerable list) if (list == null) return null; - var _list = new List(); - + var ticks = new List(); PbTick last = null; foreach (var item in list) { last = Restore(last, item); - _list.Add(last); + ticks.Add(last); } - return _list; + return ticks; } public List Diff(IEnumerable list) @@ -791,15 +790,14 @@ public List Diff(IEnumerable list) if (list == null) return null; - var _list = new List(); - + var ticks = new List(); PbTick last = null; foreach (var item in list) { var diff = Diff(last, item); last = item; - _list.Add(diff); + ticks.Add(diff); } - return _list; + return ticks; } public List Data2View(IEnumerable ticks, bool descending) diff --git a/csharp/QuantBox.Data.Serializer/V2/PbTickSerializer.cs b/csharp/QuantBox.Data.Serializer/V2/PbTickSerializer.cs index 2846496..11ebaa5 100644 --- a/csharp/QuantBox.Data.Serializer/V2/PbTickSerializer.cs +++ b/csharp/QuantBox.Data.Serializer/V2/PbTickSerializer.cs @@ -39,16 +39,14 @@ public PbTick Write(PbTick data, Stream dest) public void Write(IEnumerable list, Stream stream) { - foreach (var item in list) - { + foreach (var item in list) { Write(item, stream); } } public void Write(IEnumerable list, string output) { - using (Stream stream = File.Open(output, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read)) - { + using (Stream stream = File.Open(output, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read)) { Write(list, stream); stream.Close(); } @@ -59,20 +57,16 @@ public static void WriteCsv(IEnumerable list, string output) if (list == null) return; - var Codec = new PbTickCodec(); + var codec = new PbTickCodec(); // 将差分数据生成界面数据 - IEnumerable _list = Codec.Data2View(Codec.Restore(list), false); + IEnumerable views = codec.Data2View(codec.Restore(list), false); // 保存 - using (TextWriter stream = new StreamWriter(output)) - { - var t = new PbTickView(); + using (TextWriter stream = new StreamWriter(output)) { stream.WriteLine(PbTickView.ToCsvHeader()); - - foreach (var l in _list) - { - stream.WriteLine(l); + foreach (var view in views) { + stream.WriteLine(view); } stream.Close(); } @@ -91,37 +85,30 @@ public PbTick ReadOne(Stream source) raw.PrepareObjectAfterRead(Codec.Config); _lastRead = Codec.Restore(_lastRead, raw); - if (_lastRead.Config.Version != 2) - { + if (_lastRead.Config.Version != 2) { throw new ProtobufDataZeroException("only support pd0 file version 2", _lastRead.Config.Version, 2); } - + return _lastRead; } public List Read(Stream stream) { - var _list = new List(); - - while (true) - { + var list = new List(); + while (true) { var resotre = ReadOne(stream); - if (resotre == null) - { + if (resotre == null) { break; } - - _list.Add(resotre); + list.Add(resotre); } stream.Close(); - - return _list; + return list; } public List Read(string input) { - using (Stream stream = File.Open(input, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { + using (Stream stream = File.Open(input, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { return Read(stream); } } diff --git a/csharp/QuantBox.Data.Serializer/V2/TickWriter.cs b/csharp/QuantBox.Data.Serializer/V2/TickWriter.cs index 93d3ded..748d5ba 100644 --- a/csharp/QuantBox.Data.Serializer/V2/TickWriter.cs +++ b/csharp/QuantBox.Data.Serializer/V2/TickWriter.cs @@ -12,7 +12,7 @@ public class TickWriter : IDisposable { public class WriterDataItem { - public WriterDataItem(FileStream stream, PbTickSerializer serializer, string path,string symbol) + public WriterDataItem(FileStream stream, PbTickSerializer serializer, string path, string symbol) { Stream = stream; Serializer = serializer; @@ -43,8 +43,7 @@ public string FullPath public void Close() { - lock(locker) - { + lock (locker) { Serializer.Reset(); if (Stream == null) @@ -57,13 +56,11 @@ public void Close() public void Write() { - lock (locker) - { + lock (locker) { if (Tick == null) return; - if (Stream == null) - { + if (Stream == null) { // 换天时,必须重置记录器,不然记录的数据是差分后数据,导致新文件无法解读 Serializer.Reset(); @@ -73,25 +70,23 @@ public void Write() Serializer.Write(Tick, Stream); Tick = null; //HasData = true; - + FlushInWriter(); } } public void FlushInWriter() { - lock (locker) - { + lock (locker) { if (Stream == null) return; var ts = (DateTime.Now - LastWriteTime).TotalSeconds; // 与上次一写入相比大于10s就写入 // 但对于行情很少不变动的,会出现没有机会写入的情况,所以需要定时器来帮忙 - if (ts >= 10) - { + if (ts >= 10) { //if(HasData) - Stream.Flush(true); + Stream.Flush(true); //HasData = false; LastWriteTime = DateTime.Now; } @@ -100,23 +95,20 @@ public void FlushInWriter() public void FlushInTimer() { - lock (locker) - { + lock (locker) { if (Stream == null) return; var ts = (DateTime.Now - LastWriteTime).TotalSeconds; // 每10秒写一次 - if (ts >= 10) - { + if (ts >= 10) { //if (HasData) - Stream.Flush(true); + Stream.Flush(true); //HasData = false; // 1分钟没有写入数据就关闭文件句柄 // 这样留下机会可以进行删除 - if (ts > 1 * 60) - { + if (ts > 1 * 60) { Close(); } } @@ -135,7 +127,7 @@ public TickWriter(string path) _Timer.Elapsed += this.OnTimerElapsed; // 每15秒遍历一次 - _Timer.Interval = 1000*15; + _Timer.Interval = 1000 * 15; _Timer.Start(); } @@ -146,10 +138,8 @@ private void OnTimerElapsed(object sender, ElapsedEventArgs args) public void Close() { - lock (locker) - { - foreach (var item in Items.Values) - { + lock (locker) { + foreach (var item in Items.Values) { item.Write(); item.Close(); } @@ -159,10 +149,8 @@ public void Close() public void FlushInTimer() { - lock (locker) - { - foreach (var item in Items.Values) - { + lock (locker) { + foreach (var item in Items.Values) { item.FlushInTimer(); } } @@ -170,14 +158,11 @@ public void FlushInTimer() public void AddInstrument(string symbol, double tickSize, double factor, int Time_ssf_Diff) { - lock (locker) - { + lock (locker) { WriterDataItem item; - if (!Items.TryGetValue(symbol, out item)) - { + if (!Items.TryGetValue(symbol, out item)) { var serializer = new PbTickSerializer(); - if (tickSize > 0) - { + if (tickSize > 0) { serializer.Codec.Config.SetTickSize(tickSize); serializer.Codec.TickSize = serializer.Codec.Config.GetTickSize(); } @@ -187,14 +172,11 @@ public void AddInstrument(string symbol, double tickSize, double factor, int Tim Items.Add(symbol, new WriterDataItem(null, serializer, _path, symbol)); } - else - { + else { // 有可能要不关软件,连续工作,但tickSize又发生了变化 var serializer = item.Serializer; - if (serializer != null) - { - if (tickSize > 0) - { + if (serializer != null) { + if (tickSize > 0) { serializer.Codec.Config.SetTickSize(tickSize); serializer.Codec.TickSize = serializer.Codec.Config.GetTickSize(); } @@ -208,11 +190,9 @@ public void AddInstrument(string symbol, double tickSize, double factor, int Tim public void RemoveInstrument(string symbol) { - lock (locker) - { + lock (locker) { WriterDataItem item; - if (Items.TryGetValue(symbol, out item)) - { + if (Items.TryGetValue(symbol, out item)) { item.Close(); Items.Remove(symbol); } @@ -222,19 +202,17 @@ public void RemoveInstrument(string symbol) public bool Write(PbTick tick) { WriterDataItem item; - if (Items.TryGetValue(tick.Static.Symbol, out item)) - { + if (Items.TryGetValue(tick.Static.Symbol, out item)) { Write(item, tick); return true; } return false; } - public void Write(WriterDataItem item,PbTick tick) + public void Write(WriterDataItem item, PbTick tick) { // 对于换交易日,应当将前一天的关闭 - if (item.TradingDay != tick.TradingDay) - { + if (item.TradingDay != tick.TradingDay) { item.Close(); item.TradingDay = tick.TradingDay; }