public static DateTime GetKLineTime(DateTime quoteTime, KLineSize klineSize, ProdDef prodDef = null) { if (klineSize == KLineSize.Day) { return(Products.GetLocalDateRegardingSessionRefreshTime(quoteTime, prodDef)); } PeriodAttribute attr = GetAttribute <PeriodAttribute>(klineSize); int period = attr.Period; return(DateTimes.GetPeriodStartTime(quoteTime, period)); }
public static decimal?GetOpenPrice(ProdDef prodDef) { if (prodDef.OpenAsk == null || prodDef.OpenBid == null) { return(null); } int c1 = BitConverter.GetBytes(decimal.GetBits(prodDef.OpenAsk.Value)[3])[2]; int c2 = BitConverter.GetBytes(decimal.GetBits(prodDef.OpenBid.Value)[3])[2]; int decimalCount = Math.Max(c1, c2); return(Math.Round((prodDef.OpenAsk.Value + prodDef.OpenBid.Value) / 2, decimalCount, MidpointRounding.AwayFromZero)); }
public static DateTime GetLocalDateRegardingSessionRefreshTime(DateTime dt, ProdDef prodDef) { var offset = GetTimeZoneOffset(prodDef.SessionZone); var localTime = dt.AddHours(offset); var localSessionTime = DateTime.ParseExact(prodDef.SessionTime, "HH:mm:ss", null); //compare local quote time to local session refresh time var sQuote = localTime.Hour * 3600 + localTime.Minute * 60 + localTime.Second; var sSession = localSessionTime.Hour * 3600 + localSessionTime.Minute * 60 + localSessionTime.Second; if (sQuote < sSession) { return(localTime.Date); } else { return(localTime.Date.AddDays(1)); } }
private static void UpdateKLine(List <Quote> quotes, IRedisTypedClient <KLine> redisKLineClient, ProdDef prodDef, DateTime dtAyondoNow, KLineSize kLineSize) { var list = redisKLineClient.Lists[KLines.GetKLineListNamePrefix(kLineSize) + prodDef.Id]; if (quotes.Count == 0) //no quotes received, then should just fill the non-changing candle { if (kLineSize != KLineSize.Day) //no need to fill the non-changing candle for day kline { if (list.Count != 0) { var last = list[list.Count - 1]; var klineTime = KLines.GetKLineTime(dtAyondoNow, kLineSize, prodDef); if (prodDef.QuoteType == enmQuoteType.Closed) { klineTime = KLines.GetKLineTime(prodDef.LastClose.Value, kLineSize); } if (klineTime > last.T) //a new candle? { //fill the non-changing candle list.Add(new KLine() { T = klineTime, O = last.C, C = last.C, H = last.C, L = last.C, }); } } } } else { var orderedQuotes = quotes.OrderBy(o => o.Time).ToList(); var firstQuote = orderedQuotes.First(); var lastQuote = orderedQuotes.Last(); var klineTime1 = KLines.GetKLineTime(firstQuote.Time, kLineSize, prodDef); var klineTime2 = KLines.GetKLineTime(lastQuote.Time, kLineSize, prodDef); //var list = redisKLineClient.Lists[KLines.GetKLineListNamePrefix(kLineSize) + prodDef.Id]; if (klineTime1 != klineTime2 && kLineSize != KLineSize.Day) //quotes range more than 1 candle { var list1 = orderedQuotes.Where(o => o.Time < klineTime2).ToList(); var list2 = orderedQuotes.Where(o => o.Time >= klineTime2).ToList(); var k1 = new KLine() { T = klineTime1, O = Quotes.GetLastPrice(list1.First()), C = Quotes.GetLastPrice(list1.Last()), H = list1.Max(o => Quotes.GetLastPrice(o)), L = list1.Min(o => Quotes.GetLastPrice(o)), }; var k2 = new KLine() { T = klineTime2, O = Quotes.GetLastPrice(list2.First()), C = Quotes.GetLastPrice(list2.Last()), H = list2.Max(o => Quotes.GetLastPrice(o)), L = list2.Min(o => Quotes.GetLastPrice(o)), }; if (list.Count == 0) { list.Add(k1); list.Add(k2); } else { var last = list[list.Count - 1]; if (last.T < klineTime1) //2 new candles to append { list.Add(k1); list.Add(k2); } else if (last.T == klineTime1) //update last 1, append 1 new { list[list.Count - 1] = new KLine() { T = last.T, O = last.O, C = k1.C, H = Math.Max(last.H, k1.H), L = Math.Min(last.L, k1.L), }; list.Add(k2); } else { //should not be here } } } else //quotes range within 1 candle { var k = new KLine() { T = klineTime1, O = Quotes.GetLastPrice(firstQuote), C = Quotes.GetLastPrice(lastQuote), H = orderedQuotes.Max(o => Quotes.GetLastPrice(o)), L = orderedQuotes.Min(o => Quotes.GetLastPrice(o)), }; if (list.Count == 0) { list.Add(k); } else { var last = list[list.Count - 1]; if (last.T < k.T) //append 1 new { list.Add(k); } else if (last.T == k.T) //update last 1 { list[list.Count - 1] = new KLine() { T = last.T, O = last.O, C = k.C, H = Math.Max(last.H, k.H), L = Math.Min(last.L, k.L), }; } else { //should not be here } } } } //clear history/prevent data increasing for good var clearWhenSize = KLines.GetClearWhenSize(kLineSize); var clearToSize = KLines.GetClearToSize(kLineSize); if (list.Count > clearWhenSize) //data count at most possible size (in x days ) { YJYGlobal.LogLine("KLine " + kLineSize + " " + prodDef.Id + " Clearing data from " + list.Count + " to " + clearToSize); var klines = list.GetAll(); var newKLines = klines.Skip(klines.Count - clearToSize); list.RemoveAll(); list.AddRange(newKLines); } }
public void FromApp(Message message, SessionID sessionID) { //YJYGlobal.LogLine("FromApp: cracking message..."); ////-------clear inactive products------------- //if (_activeProdIds.Count==121) //{ // var redisProdDefClient = YJYGlobal.BasicRedisClientManager.GetClient().As<ProdDef>(); // var allIds = redisProdDefClient.GetAll().Select(o => o.Id).ToList(); // var removeIds = allIds.Where(o => !_activeProdIds.Contains(o)).ToList(); // redisProdDefClient.DeleteByIds(removeIds); // allIds = redisQuoteClient.GetAll().Select(o => o.Id).ToList(); // removeIds = allIds.Where(o => !_activeProdIds.Contains(o)).ToList(); // redisQuoteClient.DeleteByIds(removeIds); // var redis = YJYGlobal.BasicRedisClientManager.GetClient(); // var keys = redis.SearchKeys("tick:*"); // foreach (var key in keys) // { // var secId = Convert.ToInt32(key.Replace("tick:", "")); // if (!_activeProdIds.Contains(secId)) // redis.RemoveEntry(key); // } //}//--------------------------------------------- string msgType = message.Header.GetString(Tags.MsgType); if (msgType == MsgType.QUOTE) { Crack(message, sessionID); } else if (msgType == "MDS2") { /*other new fields: * MDS_SFACTOR: This is the slippage factor for a product. It is a value used in margin calculations. * * MDS_SFACTOR is Slippage Factor. It is used in the margin calculation. * MDS_MULT is a scaling factor used in some PL calculations. It's important for spread bets (which you do not trade). */ //YJYGlobal.LogLine(message.ToString()); //YJYGlobal.LogLine(GetMessageString(message)); var id = Convert.ToInt32(message.GetString(Tags.SecurityID)); var time = message.Header.GetDateTime(Tags.SendingTime); var quoteType = (enmQuoteType)message.GetInt(Tags.QuoteType); var name = message.GetString(Tags.Symbol); var symbol = message.GetString(DD.FieldsByName["MDS_BBC"].Tag); var assetClass = message.GetString(DD.FieldsByName["MDS_ASSETCLASS"].Tag); //some security MDS2 dont have Bid/Offer... var bid = message.Any(o => o.Key == Tags.BidPx) ? message.GetDecimal(Tags.BidPx) : (decimal?)null; var offer = message.Any(o => o.Key == Tags.OfferPx) ? message.GetDecimal(Tags.OfferPx) : (decimal?)null; //some security MDS2 dont have MDS_CLOSEBID/MDS_CLOSEASK... var closeBid = message.Any(o => o.Key == DD.FieldsByName["MDS_CLOSEBID"].Tag) ? message.GetDecimal(DD.FieldsByName["MDS_CLOSEBID"].Tag) : (decimal?)null; var closeAsk = message.Any(o => o.Key == DD.FieldsByName["MDS_CLOSEASK"].Tag) ? message.GetDecimal(DD.FieldsByName["MDS_CLOSEASK"].Tag) : (decimal?)null; // var shortable = Convert.ToBoolean(message.GetString(DD.FieldsByName["MDS_SHORTABLE"].Tag)); var minSizeShort = message.GetDecimal(DD.FieldsByName["MDS_MinSizeShort"].Tag); var maxSizeShort = message.GetDecimal(DD.FieldsByName["MDS_MaxSizeShort"].Tag); var minSizeLong = message.GetDecimal(DD.FieldsByName["MDS_MinSizeLong"].Tag); var maxSizeLong = message.GetDecimal(DD.FieldsByName["MDS_MaxSizeLong"].Tag); var maxLeverage = message.GetDecimal(DD.FieldsByName["MDS_EFFLEVERAGE"].Tag); var plUnits = message.GetDecimal(DD.FieldsByName["MDS_PLUNITS"].Tag); var lotSize = message.GetDecimal(DD.FieldsByName["MDS_LOTSIZE"].Tag); var ccy2 = message.GetString(DD.FieldsByName["MDS_CCY2"].Tag); var prec = message.GetInt(DD.FieldsByName["MDS_PREC"].Tag); var smd = message.Any(o => o.Key == DD.FieldsByName["MDS_SMD"].Tag) ?message.GetDecimal(DD.FieldsByName["MDS_SMD"].Tag):(decimal?)null; var gsmd = message.Any(o => o.Key == DD.FieldsByName["MDS_GSMD"].Tag) ? message.GetDecimal(DD.FieldsByName["MDS_GSMD"].Tag) : (decimal?)null; var gsms = message.Any(o => o.Key == DD.FieldsByName["MDS_GSMS"].Tag) ? message.GetDecimal(DD.FieldsByName["MDS_GSMS"].Tag) : (decimal?)null; //var sFactor = message.GetDecimal(DD.FieldsByName["MDS_SFACTOR"].Tag); //var tickTime = message.Any(o=>o.Key== DD.FieldsByName["MDS_TICKTIME"].Tag)? message.GetDateTime(DD.FieldsByName["MDS_TICKTIME"].Tag):(DateTime?)null; var sessionTime = message.GetString(DD.FieldsByName["MDS_SESSIONTIME"].Tag); var sessionZone = message.GetString(DD.FieldsByName["MDS_SESSIONZONE"].Tag); //var mult = message.GetDecimal(DD.FieldsByName["MDS_MULT"].Tag); QueueProdDefs.Enqueue(new ProdDef { Id = id, Time = time, QuoteType = quoteType, Name = name, Symbol = symbol, AssetClass = assetClass, Bid = bid, Offer = offer, CloseBid = closeBid, CloseAsk = closeAsk, Shortable = shortable, MinSizeShort = minSizeShort, MaxSizeShort = maxSizeShort, MinSizeLong = minSizeLong, MaxSizeLong = maxSizeLong, MaxLeverage = maxLeverage, PLUnits = plUnits, LotSize = lotSize, Ccy2 = ccy2, Prec = prec, SMD = smd, GSMD = gsmd, GSMS = gsms, SessionTime = sessionTime, SessionZone = sessionZone, }); ProdDefs[id] = new ProdDef { Id = id, Time = time, QuoteType = quoteType, Name = name, Symbol = symbol, AssetClass = assetClass, Bid = bid, Offer = offer, CloseBid = closeBid, CloseAsk = closeAsk, Shortable = shortable, MinSizeShort = minSizeShort, MaxSizeShort = maxSizeShort, MinSizeLong = minSizeLong, MaxSizeLong = maxSizeLong, MaxLeverage = maxLeverage, PLUnits = plUnits, LotSize = lotSize, Ccy2 = ccy2, Prec = prec, SMD = smd, GSMD = gsmd, GSMS = gsms, SessionTime = sessionTime, SessionZone = sessionZone, }; } else { YJYGlobal.LogLine("Unknown MsgType: " + message.ToString()); } }