| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.NetworkInformation;
- using System.Net.Sockets;
- using System.Runtime.InteropServices;
- using System.Runtime.Serialization.Json;
- using System.Text;
- //----------------------------------------------------------------
- //Module Name: $safeprojectname$
- //Purpose:
- //CopyRight: Muchinfo
- //History:
- //----------------------------------------------------------------
- //DateTime 2016/6/4 14:12:07
- //Author
- //Description Create
- //----------------------------------------------------------------
- using Muchinfo.MTPClient.Data;
- using Muchinfo.MTPClient.Data.Enums;
- using Muchinfo.MTPClient.Data.Model;
- using Muchinfo.MTPClient.Data.Model.Account;
- using Muchinfo.MTPClient.Data.Model.Analysis;
- using Muchinfo.MTPClient.Data.Model.Sale;
- using Muchinfo.MTPClient.Data.Quote;
- using Muchinfo.MTPClient.Data.Quote.Structs;
- namespace Muchinfo.MTPClient.Adapter.Quote
- {
- public class QuoteDateAdapter
- {
- private DateTime baseDateTime = new DateTime(1970, 1, 1, 8, 0, 0);
- // 一笔周期数据长度
- private const int CYCLE_LENGTH = 36;
- private const int TIK_LENGTH = 40; //一笔分笔数据
- private const int HEAD_LENGTH = 74;
- private const int LENGTH = 36;
- private const int c_goodsLength = 228; ////u商品字节长度
- private const int c_SaleGoodsLength = 56; ////发售商品长度
- private const int c_planheadLength = 8; ////结算计划长度
- private const int c_planRunSteps = 16; ////运行阶段时间数据长度
- /// <summary>
- /// 请求历史周期时间
- /// </summary>
- /// <param name="goods"></param>
- /// <param name="startTime"></param>
- /// <param name="endTime"></param>
- /// /// <param name="type"></param>
- /// <param name="count"></param>
- /// <returns></returns>
- public byte[] HistoryCycleBytesRequst(QuoteGoods goods, DateTime startTime, DateTime endTime, CycleType type, int count)
- {
- if (type == CycleType.TimeSharing)
- {
- type = CycleType.Minutes1;
- }
- var totalSeconds = (int)((endTime - baseDateTime).TotalSeconds - (startTime - baseDateTime).TotalSeconds);
- using (MemoryStream ms = new MemoryStream())
- {
- byte[] block = new byte[] { };
- Int16 exchangeCode = Convert.ToInt16(goods.ExchHqCode.Substring(0, 3));
- block = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(exchangeCode));
- ms.Write(block, 0, block.Length);
- block = Encoding.UTF8.GetBytes(goods.GoodsHqCode.ToUpper().PadRight(64, '\0'));
- ms.Write(block, 0, block.Length);
- block = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)type));
- ms.Write(block, 0, block.Length);
- block = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(count));
- ms.Write(block, 0, block.Length);
- Int32 utcTime = (int)(startTime - baseDateTime).TotalSeconds;
- block = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(utcTime));
- ms.Write(block, 0, block.Length);
- block = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(totalSeconds));
- ms.Write(block, 0, block.Length);
- return ms.ToArray();
- }
- }
- public GoodsHistoryCycle HistoryCycleBytesRespone(byte[] content)
- {
- if (content.Length < HEAD_LENGTH)
- {
- throw new Exception("数据长度过小Length:" + content.Length);
- }
- byte[] block = new byte[2];
- int index = 0;
- Array.Copy(content, index, block, 0, 2);
- index += 2;
- Int16 exchangeCode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(block, 0));
- block = new byte[64];
- Array.Copy(content, index, block, 0, 64);
- var goodsCode = Encoding.UTF8.GetString(block);
- goodsCode = goodsCode.Substring(0, goodsCode.IndexOf('\0')); ///处理商品有垃圾数据问题
- var goodsHistory = new GoodsHistoryCycle(exchangeCode + string.Empty, goodsCode, goodsCode);
- index += 64;
- block = new byte[2];
- Array.Copy(content, index, block, 0, 2);
- goodsHistory.CycleType = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(block, 0));
- index += 2;
- Array.Copy(content, index, block, 0, 2);
- goodsHistory.decimalPlace = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(block, 0));
- index += 2;
- block = new byte[4];
- Array.Copy(content, index, block, 0, 4);
- goodsHistory.Count = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block, 0));
- index += 4;
- if (goodsHistory.CycleType != (int)CycleType.Tik)
- {
- block = new byte[content.Length - HEAD_LENGTH];
- Array.Copy(content, index, block, 0, block.Length);
- goodsHistory.OhlcDataPoints = ConvertOHLC(block, goodsHistory.Count, goodsHistory.decimalPlace);
- }
- else
- {
- block = new byte[content.Length - HEAD_LENGTH];
- Array.Copy(content, index, block, 0, block.Length);
- goodsHistory.SubDataPoints = ConvertTik(block, goodsHistory.Count, goodsHistory.decimalPlace);
- }
- return goodsHistory;
- }
- /// <summary>
- /// 历史K线
- /// </summary>
- /// <param name="OHLCContent">K线数据</param>
- /// <param name="count"></param>
- /// <param name="decimalPlace"></param>
- /// <returns></returns>
- private List<OHLCDataPoints> ConvertOHLC(byte[] OHLCContent, int count, int decimalPlace)
- {
- var results = new List<OHLCDataPoints>();
- if (OHLCContent.Length != LENGTH * count)
- {
- throw new Exception("历史K线数据长度错误Length:" + OHLCContent.Length);
- }
- long index = 0;
- var powDecimal = Math.Pow(10, decimalPlace);
- byte[] block = new byte[4];
- for (int i = 0; i < count; i++)
- {
- var ohlcPoints = new OHLCDataPoints();
- block = new byte[4];
- Array.Copy(OHLCContent, index, block, 0, 4);
- ohlcPoints.Open = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block, 0)) / powDecimal;
- index += 4;
- Array.Copy(OHLCContent, index, block, 0, 4);
- ohlcPoints.High = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block, 0)) / powDecimal;
- index += 4;
- Array.Copy(OHLCContent, index, block, 0, 4);
- ohlcPoints.Low = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block, 0)) / powDecimal;
- index += 4;
- Array.Copy(OHLCContent, index, block, 0, 4);
- ohlcPoints.Close = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block, 0)) / powDecimal;
- #if DEBUG
- Console.WriteLine(ohlcPoints.Close);
- #endif
- index += 4;
- block = new byte[8];
- Array.Copy(OHLCContent, index, block, 0, 8);
- ohlcPoints.Volume = BitConverter.ToDouble(block, 0);
- index += 8;
- Array.Copy(OHLCContent, index, block, 0, 8);
- ohlcPoints.TotleTurnovers = BitConverter.ToDouble(block, 0);
- index += 8;
- block = new byte[4];
- Array.Copy(OHLCContent, index, block, 0, 4);
- var datetime = baseDateTime.AddSeconds(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block, 0)));
- #if DEBUG
- Console.WriteLine(datetime.ToString("yyyy-MM-dd HH:mm:ss"));
- #endif
- ohlcPoints.Date = datetime.ToOADate();
- index += 4;
- results.Add(ohlcPoints);
- }
- return results;
- }
- /// <summary>
- /// 转换Tik数据
- /// </summary>
- /// <param name="TikContent"></param>
- /// <param name="count"></param>
- /// <param name="decimalPlace">行情小数位</param>
- /// <returns></returns>
- private List<SubPenData> ConvertTik(byte[] TikContent, int count, int decimalPlace)
- {
- var results = new List<SubPenData>();
- if (TikContent.Length != TIK_LENGTH * count)
- {
- throw new Exception("历史Tik线数据长度错误Length:" + TikContent.Length);
- }
- long index = 0;
- var powDecimal = Math.Pow(10, decimalPlace);
- byte[] blockPrice = new byte[4];
- byte[] blockVolume = new byte[8];
- for (int i = 0; i < count; i++)
- {
- var penPoints = new SubPenData(decimalPlace);
- Array.Copy(TikContent, index, blockPrice, 0, 4);
- penPoints.Price = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(blockPrice, 0)) / powDecimal;
- index += 4;
- Array.Copy(TikContent, index, blockVolume, 0, 8);
- penPoints.CompleteQte = BitConverter.ToDouble(blockVolume, 0);
- index += 8;
- Array.Copy(TikContent, index, blockPrice, 0, 4);
- penPoints.BidPrice = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(blockPrice, 0)) / powDecimal;
- index += 4;
- Array.Copy(TikContent, index, blockVolume, 0, 8);
- penPoints.BidVolume = BitConverter.ToDouble(blockVolume, 0);
- index += 8;
- Array.Copy(TikContent, index, blockPrice, 0, 4);
- penPoints.AskPrice = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(blockPrice, 0)) / powDecimal;
- index += 4;
- Array.Copy(TikContent, index, blockVolume, 0, 8);
- penPoints.AskVolume = BitConverter.ToDouble(blockVolume, 0);
- index += 8;
- Array.Copy(TikContent, index, blockPrice, 0, 4);
- var datetime = baseDateTime.AddSeconds(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(blockPrice, 0)));
- #if DEBUG
- Console.WriteLine(datetime.ToString("yyyy-MM-dd HH:mm:ss"));
- #endif
- penPoints.Time = datetime;
- index += 4;
- results.Add(penPoints);
- }
- results.Reverse();
- return results;
- }
- /// <summary>
- /// 从行情获取商品组与商品信息.
- /// </summary>
- /// <param name="contentBytes">数据内容</param>
- /// <param name="goodsGroups">商品组信息</param>
- /// <returns>商品信息</returns>
- public List<QuoteGoods> ConvertGoodsWithsGoodsGroup(byte[] contentBytes, int count, ref List<GoodsGroup> goodsGroups)
- {
- var results = new List<QuoteGoods>();
- var dicGoodsGroups = new Dictionary<long, GoodsGroup>();
- if (contentBytes.Length != c_goodsLength * count)
- {
- throw new Exception("商品数据长度错误Length:" + contentBytes.Length);
- }
- long index = 0;
- // var powDecimal = Math.Pow(10, decimalPlace);
- byte[] block4b = new byte[4];
- byte[] block8b = new byte[8];
- byte[] blockstring = new byte[64];
- for (int i = 0; i < count; i++)
- {
- Array.Copy(contentBytes, index, blockstring, 0, 64);
- var goodsCode = Encoding.UTF8.GetString(blockstring).Trim('\0');
- index += 64;
- Array.Copy(contentBytes, index, blockstring, 0, 64);
- var goodsName = Encoding.UTF8.GetString(blockstring).Trim('\0');
- index += 64;
- Array.Copy(contentBytes, index, block4b, 0, 4);
- var exchangeCode = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- var qouteGoods = new QuoteGoods(exchangeCode.ToString(), goodsCode, goodsCode, QuoteCategoryType.Futures);
- qouteGoods.Name = goodsName;
- Array.Copy(contentBytes, index, block8b, 0, 8);
- var goodsGroupId = IPAddress.NetworkToHostOrder(BitConverter.ToInt64(block8b, 0));
- index += 8;
- Array.Copy(contentBytes, index, blockstring, 0, 64);
- var goodsGroupName = Encoding.UTF8.GetString(blockstring).Trim('\0'); ;
- index += 64;
- Array.Copy(contentBytes, index, block4b, 0, 4);
- var tradeMode = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- qouteGoods.TradeMode = (eTradeMode)tradeMode;
- dicGoodsGroups[goodsGroupId] = new GoodsGroup() { GoodsGroupid = goodsGroupId, GoodsGroupName = goodsGroupName, TradeMode = (eTradeMode)tradeMode };
- Array.Copy(contentBytes, index, block8b, 0, 8);
- var agreeUint = BitConverter.ToDouble(block8b, 0);
- index += 8;
- ////价格小数位
- Array.Copy(contentBytes, index, block4b, 0, 4);
- var decimalPlace = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- qouteGoods.DecimalPlaces = decimalPlace;
- ////市场类型ID
- Array.Copy(contentBytes, index, block4b, 0, 4);
- var marketypeID = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- ////商品id
- Array.Copy(contentBytes, index, block4b, 0, 4);
- var goodsId = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- qouteGoods.GoodsId = (uint)goodsId;
- qouteGoods.GoodsParameters = new GoodsParameters() { GoodsId = (uint)goodsId, AgreeUnit = Convert.ToDecimal(agreeUint), HqExchFigures = decimalPlace, SortId = goodsGroupId, MarketTypeID = marketypeID };
- dicGoodsGroups[goodsGroupId].MarketTypeID = marketypeID;
- results.Add(qouteGoods);
- }
- goodsGroups = dicGoodsGroups.Values.ToList();
- return results;
- }
- /// <summary>
- /// 从行情获取发售商品参数
- /// </summary>
- /// <param name="contentBytes">数据内容</param>
- /// <param name="goodsGroups">商品组信息</param>
- /// <returns>商品信息</returns>
- public List<SaleGoods> ConvertSaleGoodsParam(byte[] contentBytes, int count)
- {
- var results = new List<SaleGoods>();
- if (contentBytes.Length != c_SaleGoodsLength * count)
- {
- throw new Exception("商品数据长度错误Length:" + contentBytes.Length);
- }
- long index = 0;
- // var powDecimal = Math.Pow(10, decimalPlace);
- byte[] block4b = new byte[4];
- byte[] block8b = new byte[8];
- byte[] blockstring = new byte[32];
- for (int i = 0; i < count; i++)
- {
- var saleGoods = new SaleGoods();
- ////商品ID
- Array.Copy(contentBytes, index, block4b, 0, 4);
- var goodsId = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- saleGoods.GoodsId = (uint)goodsId;
- ////合约单位
- Array.Copy(contentBytes, index, blockstring, 0, 32);
- var agreeUnitString = Encoding.UTF8.GetString(blockstring).Trim('\0'); ;
- index += 32;
- saleGoods.AgreeUnitString = agreeUnitString;
- ////发售开始时间
- Array.Copy(contentBytes, index, block4b, 0, 4);
- saleGoods.ApplyStartTime = baseDateTime.AddSeconds(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0)));
- index += 4;
- ////发售结束时间
- Array.Copy(contentBytes, index, block4b, 0, 4);
- saleGoods.ApplyEndTime = baseDateTime.AddSeconds(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0)));
- index += 4;
- ////发售阶段
- Array.Copy(contentBytes, index, block4b, 0, 4);
- saleGoods.RunSteps = (eRunStep)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- ////发售价格
- Array.Copy(contentBytes, index, block8b, 0, 8);
- saleGoods.SalePrice = Convert.ToDecimal(BitConverter.ToDouble(block8b, 0));
- index += 8;
- results.Add(saleGoods);
- }
- return results;
- }
- /// <summary>
- /// 解析行情交易运行时间段
- /// </summary>
- /// <param name="contentBytes">数据内容</param>
- /// <returns></returns>
- public QuoteTradePlan ConvertTradePlans(byte[] contentBytes)
- {
- if (contentBytes.Length < c_planheadLength)
- {
- throw new Exception("查询结算计划数据长度过小Length:" + contentBytes.Length);
- }
- var quoteTrade = new QuoteTradePlan();
- uint index = 0;
- byte[] block4b = new byte[4];
- Array.Copy(contentBytes, index, block4b, 0, 4);
- var marketTypeid = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- quoteTrade.MarketTypeID = marketTypeid;
- Array.Copy(contentBytes, index, block4b, 0, 4);
- var count = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0)); ////数量
- index += 4;
- var subBlocks = new byte[contentBytes.Length - c_planheadLength];
- Array.Copy(contentBytes, index, subBlocks, 0, subBlocks.Length);
- if (subBlocks.Length != c_planRunSteps * count)
- {
- throw new Exception("结算计划时间段数据长度错误Length:" + subBlocks.Length);
- }
- index = 0;
- quoteTrade.OpenCloseDates = new List<OpenCloseDate>();
- for (int i = 0; i < count; i++)
- {
- var runSteps = new OpenCloseDate();
- Array.Copy(subBlocks, index, block4b, 0, 4);
- runSteps.TradeDay = baseDateTime.AddSeconds(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0)));
- index += 4;
- Array.Copy(subBlocks, index, block4b, 0, 4);
- runSteps.RunStep = (eRunStep)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0));
- index += 4;
- Array.Copy(subBlocks, index, block4b, 0, 4);
- runSteps.OpenDate = baseDateTime.AddSeconds(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0)));
- index += 4;
- Array.Copy(subBlocks, index, block4b, 0, 4);
- runSteps.CloseDate = baseDateTime.AddSeconds(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(block4b, 0)));
- index += 4;
- quoteTrade.OpenCloseDates.Add(runSteps);
- }
- return quoteTrade;
- }
- /// <summary>
- /// 使用json解析开收市计划
- /// </summary>
- /// <param name="contentBytes">Json数据</param>
- /// <param name="error">数据提示</param>
- /// <returns></returns>
- public List<QuoteTradePlan> ConvertFromJson(byte[] contentBytes, ref ErrorEntity error)
- {
- var quoteTradeList = new List<QuoteTradePlan>();
- try
- {
- var dataContractJson = new DataContractJsonSerializer(typeof(TimeSection[]));
- using (MemoryStream ms = new MemoryStream(contentBytes))
- {
- var runsteps = dataContractJson.ReadObject(ms) as TimeSection[];
- if (runsteps == null || !runsteps.Any())
- {
- error.ReturnDesc = "无结算计划数据!";
- error.ReturnCode = -1;
- return quoteTradeList;
- }
- var planDic = new Dictionary<uint, QuoteTradePlan>();
- for (int i = 0; i < runsteps.Count(); i++)
- {
- if (!planDic.ContainsKey(runsteps[i].GoodsId))
- {
- planDic[runsteps[i].GoodsId] = new QuoteTradePlan() { GoodsId = runsteps[i].GoodsId, MarketTypeID = runsteps[i].id, TradeDay = baseDateTime.AddSeconds(runsteps[i].TradeDay) };
- planDic[runsteps[i].GoodsId].OpenCloseDates = new List<OpenCloseDate>();
- }
- var planSection = new OpenCloseDate();
- planSection.OpenDate = baseDateTime.AddSeconds(runsteps[i].BeginTime);
- planSection.CloseDate = baseDateTime.AddSeconds(runsteps[i].EndTime);
- planSection.RunStep = (eRunStep)runsteps[i].RunStep;
- planDic[runsteps[i].GoodsId].OpenCloseDates.Add(planSection);
- }
- quoteTradeList = planDic.Values.ToList();
- }
- }
- catch (Exception ex)
- {
- error.ReturnDesc = ex.Message;
- error.ReturnCode = -1;
- }
- return quoteTradeList;
- }
- /// <summary>
- /// 使用json解析开收市计划
- /// </summary>
- /// <param name="contentBytes">Json数据</param>
- /// <param name="error">数据提示</param>
- /// <returns></returns>
- public List<MarketTypeStatus> ConvertFromMarketStatusJson(byte[] contentBytes, ref ErrorEntity error)
- {
- var quoteStatus = new List<MarketTypeStatus>();
- try
- {
- var dataContractJson = new DataContractJsonSerializer(typeof(MarketTypeStatus[]));
- using (MemoryStream ms = new MemoryStream(contentBytes))
- {
- var runsteps = dataContractJson.ReadObject(ms) as MarketTypeStatus[];
- if (runsteps == null || !runsteps.Any())
- {
- error.ReturnDesc = "无开收市计划数据!";
- error.ReturnCode = -1;
- return quoteStatus;
- }
- quoteStatus.AddRange(runsteps);
- return quoteStatus;
- }
- }
- catch (Exception ex)
- {
- error.ReturnDesc = ex.Message;
- error.ReturnCode = -1;
- }
- return quoteStatus;
- }
- /// <summary>
- /// 行情报文组装
- /// </summary>
- /// <param name="accountid">账号Id</param>
- /// <param name="token">令牌字串</param>
- /// <returns></returns>
- public byte[] QuoteCheckToken(uint accountid, string token)
- {
- using (MemoryStream ms = new MemoryStream())
- {
- byte[] block = new byte[] { };
- block = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(accountid));
- ms.Write(block, 0, block.Length);
- block = Encoding.UTF8.GetBytes(token.PadRight(64, '\0'));
- ms.Write(block, 0, block.Length);
- return ms.ToArray();
- }
- }
- }
- }
|