public PositionDTO NetPosition(NetPositionFormDTO form) { var cache = WebCache.Instance; var prodDef = cache.ProdDefs.FirstOrDefault(o => o.Id == form.securityId); if (prodDef.QuoteType == enmQuoteType.Closed || prodDef.QuoteType == enmQuoteType.Inactive) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, Resources.Resource.ProductClosed)); } var quote = cache.Quotes.FirstOrDefault(o => o.Id == form.securityId); var positionService = new PositionService(); var closedPosition = positionService.DoClosePosition(UserId, form.posId, form.securityId, Quotes.GetLastPrice(quote)); var posIdToFollowClose = closedPosition.Id; Task.Run(() => { YJYGlobal.LogLine("NEW THREAD: check and CLOSE follow positions for pos " + posIdToFollowClose); var checkAndCloseFollowPositions = PositionService.CheckAndCloseFollowPositions(posIdToFollowClose); MessageService.AddAutoCloseMessages(checkAndCloseFollowPositions); }); var result = Mapper.Map <PositionDTO>(closedPosition); return(result); }
public void SendMDS1Request() { if (Session != null) { try { //Product Definition Request var order = new Message(); order.Header.SetField(new MsgType("MDS1")); order.SetField(new UserRequestID("ProdDef")); Session.Send(order); //} } catch (Exception e) { YJYGlobal.LogLine("send mds1 request failed"); YJYGlobal.LogException(e); } } else { //// This probably won't ever happen. //Console.WriteLine("Can't send message: session not created."); throw new Exception("fix session is null."); } }
//private IRedisTypedClient<Quote> redisQuoteClient; //private IRedisTypedClient<ProdDef> redisProdDefClient; // public IRedisTypedClient<> //public AyondoFixFeedApp() //{ //var basicRedisClientManager = YJYGlobal.GetNewBasicRedisClientManager(); //redisQuoteClient = YJYGlobal.BasicRedisClientManager.GetClient().As<Quote>(); //redisProdDefClient = basicRedisClientManager.GetClient().As<ProdDef>(); //} public void ToAdmin(Message message, SessionID sessionID) { YJYGlobal.LogLine("ToAdmin: "); if (message.Header.GetString(Tags.MsgType) == MsgType.LOGON) { YJYGlobal.LogLine(" sending username and password..."); //demo message.SetField(new Username(_username)); message.SetField(new Password(_password)); //message.SetField(new Username("thcnprices")); //message.SetField(new Password("sl6map3go")); ////demo UAT //message.SetField(new Username("thcnuatprices")); //message.SetField(new Password("slktrp2")); } //message.SetField(new Username("thcntrade")); //message.SetField(new Password("d093gos3j")); //message.SetField(new Username("tradeheroprices")); //message.SetField(new Password("4gs9k2osw")); }
public void ToApp(Message message, SessionID sessionId) { YJYGlobal.LogLine("ToApp: "); YJYGlobal.LogLine(message.ToString()); //message.SetField(new MsgType("MDS1")); //message.SetField(new UserRequestID("test1111")); }
private static void SaveTicks(object state) { while (true) { try { IList <Quote> quotes = new List <Quote>(); while (!myApp.QueueQuotesForTick.IsEmpty) { Quote obj; var tryDequeue = myApp.QueueQuotesForTick.TryDequeue(out obj); quotes.Add(obj); } using (var redisClient = YJYGlobal.PooledRedisClientsManager.GetClient()) { var redisTickClient = redisClient.As <Tick>(); var redisProdDefClient = redisClient.As <ProdDef>(); var prodDefs = redisProdDefClient.GetAll(); if (quotes.Count > 0) { //the time of the last message received from Ayondo var dtAyondoNow = quotes.Max(o => o.Time); var openingProds = prodDefs.Where( o => o.QuoteType == enmQuoteType.Open || o.QuoteType == enmQuoteType.PhoneOnly).ToList(); var dtBeginSave = DateTime.Now; foreach (var prodDef in openingProds) { var quotesByProd = quotes.Where(o => o.Id == prodDef.Id).ToList(); UpdateRedisTick(redisTickClient, prodDef.Id, dtAyondoNow, quotesByProd, TickSize.OneMinute); UpdateRedisTick(redisTickClient, prodDef.Id, dtAyondoNow, quotesByProd, TickSize.TenMinute); UpdateRedisTick(redisTickClient, prodDef.Id, dtAyondoNow, quotesByProd, TickSize.OneHour); } YJYGlobal.LogLine("\t" + " Ticks " + openingProds.Count + "/" + quotes.Count + " " + " Time: " + quotes.Min(o => o.Time).ToString(YJYGlobal.DATETIME_MASK_MILLI_SECOND) + " ~ " + quotes.Max(o => o.Time).ToString(YJYGlobal.DATETIME_MASK_MILLI_SECOND) + " Saved to Redis " + (DateTime.Now - dtBeginSave).TotalMilliseconds); } } } catch (Exception e) { YJYGlobal.LogException(e); } Thread.Sleep(_intervalTicks); } }
public void OnLogon(SessionID sessionID) { YJYGlobal.LogLine("OnLogon: "); Session = Session.LookupSession(sessionID); DD = Session.ApplicationDataDictionary; SendMDS1Request(); }
private static TimeSpan LogEndOfJob(TimeSpan execTime) { YJYGlobal.LogLine("-"); YJYGlobal.LogLine("................................................................................"); YJYGlobal.LogLine(" TH_JOBS FINISHED: @ (local) " + DateTime.Now.ToString("dd MMM yyyy HH:mm") + ", execTime was " + execTime.TotalMinutes.ToString("000.00") + " min(s) ..."); YJYGlobal.LogLine(" (fullArgs: " + fullArgs + ")"); YJYGlobal.LogLine("................................................................................"); YJYGlobal.LogLine("-"); return(execTime); }
private MessageTicker(IHubConnectionContext <dynamic> clients) { Clients = clients; _db = YJYEntities.Create(); YJYGlobal.LogLine("Starting MessageTicker..."); _timer = new Timer(Start, null, _updateInterval, TimeSpan.FromMilliseconds(-1)); }
static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs) { YJYGlobal.LogLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}."); var context = exceptionReceivedEventArgs.ExceptionReceivedContext; YJYGlobal.LogLine("Exception context for troubleshooting:"); YJYGlobal.LogLine($"- Endpoint: {context.Endpoint}"); YJYGlobal.LogLine($"- Entity Path: {context.EntityPath}"); YJYGlobal.LogLine($"- Executing Action: {context.Action}"); return(Task.CompletedTask); }
private QuoteFeedTicker(IHubConnectionContext <dynamic> clients) { Clients = clients; //var basicRedisClientManager = YJYGlobal.GetNewBasicRedisClientManager(); //_redisClient = YJYGlobal.BasicRedisClientManager.GetClient().As<Quote>(); YJYGlobal.LogLine("Starting QuoteFeedTicker..."); //Start(); //_timer = new Timer(Start, null, _updateInterval, TimeSpan.FromMilliseconds(-1)); }
public static void Run() { YJYGlobal.LogLine("Starting..."); queueClient = new QueueClient(ServiceBusConnectionString, QueueName); // Register QueueClient's MessageHandler and receive messages in a loop RegisterOnMessageHandlerAndReceiveMessages(); YJYGlobal.LogLine("Receiving messages..."); while (true) { Thread.Sleep(TimeSpan.FromSeconds(1)); } }
private static void LogJobStartup()//(tradeheroEntities db, bool isMonitoring) { //if (!isMonitoring) //{ YJYGlobal.LogLine("***************************************************"); YJYGlobal.LogLine("*** TH_JOBS STARTUP - (local) " + DateTime.Now.ToString("dd MMM yyyy HH:mm") + " ***"); YJYGlobal.LogLine("***************************************************"); YJYGlobal.LogLine("-"); YJYGlobal.LogLine("this host: " + System.Environment.MachineName); //YJYGlobal.LogLine("constr: " + db.Database.Connection.ConnectionString); YJYGlobal.LogLine("curdir: " + Environment.CurrentDirectory); YJYGlobal.LogLine("fullArgs: " + fullArgs); YJYGlobal.LogLine("logDir: " + logDir); YJYGlobal.LogLine("-"); //} }
private static void SendProdDefRequest(object state) { while (true) { try { YJYGlobal.LogLine("sending mds1 request..."); myApp.SendMDS1Request(); } catch (Exception e) { YJYGlobal.LogLine("sending mds1 request failed"); YJYGlobal.LogException(e); } Thread.Sleep(_intervalProdDefRequest); } }
private static void SaveQuotes(object state) { while (true) { try { IList <Quote> quotes = new List <Quote>(); while (!myApp.QueueQuotes.IsEmpty) { Quote obj; var tryDequeue = myApp.QueueQuotes.TryDequeue(out obj); quotes.Add(obj); } if (quotes.Count > 0) { var distinctQuotes = quotes.GroupBy(o => o.Id).Select(o => o.OrderByDescending(p => p.Time).First()).ToList(); var dtBeginSave = DateTime.Now; using (var redisClient = YJYGlobal.PooledRedisClientsManager.GetClient()) { var redisQuoteClient = redisClient.As <Quote>(); redisQuoteClient.StoreAll(distinctQuotes); } YJYGlobal.LogLine("Quote: " + distinctQuotes.Count + "/" + quotes.Count + " (distinct/raw) " + " Time: " + quotes.Min(o => o.Time).ToString(YJYGlobal.DATETIME_MASK_MILLI_SECOND) + " ~ " + quotes.Max(o => o.Time).ToString(YJYGlobal.DATETIME_MASK_MILLI_SECOND) + ". Saved to redis " + (DateTime.Now - dtBeginSave).TotalMilliseconds); } } catch (Exception e) { YJYGlobal.LogException(e); } Thread.Sleep(_intervalQuotes); } }
static async Task ProcessMessagesAsync(Message message, CancellationToken token) { // Process the message //YJYGlobal.LogLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber}"); try { var posToClose = Serialization.ByteArrayToObject(message.Body) as PosToClose; YJYGlobal.LogLine( $"Received: {posToClose.Id} {posToClose.closeType} {posToClose.closePx} {posToClose.closePxTime}"); var autoClosePosition = PositionService.AutoClosePosition(posToClose); var checkAndCloseFollowPositions = PositionService.CheckAndCloseFollowPositions(autoClosePosition.Id); MessageService.AddAutoCloseMessage(autoClosePosition); MessageService.AddAutoCloseMessages(checkAndCloseFollowPositions); YJYGlobal.LogLine( $"pos closed: {autoClosePosition.Id} type:{autoClosePosition.CloseType} pl:{autoClosePosition.PL}"); // Complete the message so that it is not received again. // This can be done only if the queueClient is created in ReceiveMode.PeekLock mode (which is default). await queueClient.CompleteAsync(message.SystemProperties.LockToken); // Note: Use the cancellationToken passed as necessary to determine if the queueClient has already been closed. // If queueClient has already been Closed, you may chose to not call CompleteAsync() or AbandonAsync() etc. calls // to avoid unnecessary exceptions. } catch (Exception e) { YJYGlobal.LogException(e); await queueClient.AbandonAsync(message.SystemProperties.LockToken); } }
private static void SaveProdDefs(object state) { while (true) { try { //new prod list from Ayondo MDS2 IList <ProdDef> listNew = new List <ProdDef>(); while (!myApp.QueueProdDefs.IsEmpty) { ProdDef obj; var tryDequeue = myApp.QueueProdDefs.TryDequeue(out obj); listNew.Add(obj); } if (listNew.Count > 0) { YJYGlobal.LogLine("Saving " + listNew.Count + " ProdDefs to Redis..."); using (var redisClient = YJYGlobal.PooledRedisClientsManager.GetClient()) { var redisProdDefClient = redisClient.As <ProdDef>(); //current redis list var listOld = redisProdDefClient.GetAll(); IList <ProdDef> listToSave = new List <ProdDef>(); foreach (var newProdDef in listNew) { var old = listOld.FirstOrDefault(o => o.Id == newProdDef.Id); if (old != null) //updating prod def in redis { //update open/close time/price depending on state change if (old.QuoteType != enmQuoteType.Closed && newProdDef.QuoteType == enmQuoteType.Closed) //xxx -> close { YJYGlobal.LogLine("PROD CLOSED " + newProdDef.Id + " " + newProdDef.Name + " time: " + newProdDef.Time + " offer: " + newProdDef.Offer + " bid: " + newProdDef.Bid); old.LastClose = newProdDef.Time; } else if (old.QuoteType != enmQuoteType.Open && old.QuoteType != enmQuoteType.PhoneOnly && (newProdDef.QuoteType == enmQuoteType.Open || newProdDef.QuoteType == enmQuoteType.PhoneOnly)) //xxx -> open/phone { YJYGlobal.LogLine("PROD OPENED " + newProdDef.Id + " " + newProdDef.Name + " time: " + newProdDef.Time + " offer: " + newProdDef.Offer + " bid: " + newProdDef.Bid); //open time old.LastOpen = newProdDef.Time; //open prices old.OpenAsk = newProdDef.Offer; old.OpenBid = newProdDef.Bid; //preclose if (old.LastClose == null || //last close time and this open time is not the same day (regarding session refresh time) Products.GetLocalDateRegardingSessionRefreshTime(old.LastClose.Value, newProdDef) < Products.GetLocalDateRegardingSessionRefreshTime(newProdDef.Time, newProdDef) ) { old.PreClose = Quotes.GetClosePrice(newProdDef) ?? //when close ask/bid is null, get from ask/bid Quotes.GetLastPrice(newProdDef); } } //update fields old.Time = newProdDef.Time; old.QuoteType = newProdDef.QuoteType; old.Name = newProdDef.Name; old.Symbol = newProdDef.Symbol; old.AssetClass = newProdDef.AssetClass; old.Bid = newProdDef.Bid; old.Offer = newProdDef.Offer; old.CloseBid = newProdDef.CloseBid; old.CloseAsk = newProdDef.CloseAsk; old.Shortable = newProdDef.Shortable; old.MinSizeShort = newProdDef.MinSizeShort; old.MaxSizeShort = newProdDef.MaxSizeShort; old.MinSizeLong = newProdDef.MinSizeLong; old.MaxSizeLong = newProdDef.MaxSizeLong; old.MaxLeverage = newProdDef.MaxLeverage; old.PLUnits = newProdDef.PLUnits; old.LotSize = newProdDef.LotSize; old.Ccy2 = newProdDef.Ccy2; old.Prec = newProdDef.Prec; old.SMD = newProdDef.SMD; old.GSMD = newProdDef.GSMD; old.GSMS = newProdDef.GSMS; old.SessionTime = newProdDef.SessionTime; old.SessionZone = newProdDef.SessionZone; listToSave.Add(old); } else //appending new prod def into redis { listToSave.Add(newProdDef); } } redisProdDefClient.StoreAll(listToSave); } } } catch (Exception e) { YJYGlobal.LogException(e); } Thread.Sleep(_intervalProdDefs); } }
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); } }
private static void SaveKLine(object state) { while (true) { try { IList <Quote> newQuotes = new List <Quote>(); while (!myApp.QueueQuotesForKLine.IsEmpty) { Quote obj; var tryDequeue = myApp.QueueQuotesForKLine.TryDequeue(out obj); newQuotes.Add(obj); } using (var redisClient = YJYGlobal.PooledRedisClientsManager.GetClient()) { var redisProdDefClient = redisClient.As <ProdDef>(); var redisKLineClient = redisClient.As <KLine>(); var prodDefs = redisProdDefClient.GetAll(); //need to get prod def from redis because we need to get o.LastClose, which does not always have value in myApp.ProdDefs if (newQuotes.Count > 0) { var dtAyondoNow = newQuotes.Max(o => o.Time); //the time of the last message received from Ayondo var dtNow = DateTime.UtcNow; var oneMinuteAgo = dtNow.AddMinutes(-1); var openOrRecentlyClosedProdDefs = prodDefs.Where(o => (o.QuoteType == enmQuoteType.Open || o.QuoteType == enmQuoteType.PhoneOnly) || //is open (o.QuoteType == enmQuoteType.Closed && o.LastClose > oneMinuteAgo) //recently closed ) .ToList(); var dtBeginSave = DateTime.Now; foreach (var prodDef in openOrRecentlyClosedProdDefs) { var quotesByProd = newQuotes.Where(o => o.Id == prodDef.Id).ToList(); if (prodDef.QuoteType == enmQuoteType.Closed) //recently closed { quotesByProd = quotesByProd.Where(o => o.Time <= prodDef.LastClose.Value).ToList(); //make sure that quotes' time is within prods' opening time } UpdateKLine(quotesByProd, redisKLineClient, prodDef, dtAyondoNow, KLineSize.OneMinute); UpdateKLine(quotesByProd, redisKLineClient, prodDef, dtAyondoNow, KLineSize.FiveMinutes); UpdateKLine(quotesByProd, redisKLineClient, prodDef, dtAyondoNow, KLineSize.FifteenMinutes); UpdateKLine(quotesByProd, redisKLineClient, prodDef, dtAyondoNow, KLineSize.SixtyMinutes); UpdateKLine(quotesByProd, redisKLineClient, prodDef, dtAyondoNow, KLineSize.Day); } YJYGlobal.LogLine("\t\t" + " KLine " + openOrRecentlyClosedProdDefs.Count + "/" + newQuotes.Count + " " + " Time: " + newQuotes.Min(o => o.Time).ToString(YJYGlobal.DATETIME_MASK_MILLI_SECOND) + " ~ " + newQuotes.Max(o => o.Time).ToString(YJYGlobal.DATETIME_MASK_MILLI_SECOND) + " Saved to Redis " + (DateTime.Now - dtBeginSave).TotalMilliseconds); } } } catch (Exception e) { YJYGlobal.LogException(e); } Thread.Sleep(_intervalKLine); } }
private static void UpdateRedisTick(IRedisTypedClient <Tick> redisTickClient, int secId, DateTime dtAyondoNow, IList <Quote> quotes, TickSize tickSize) { //redis tick list var list = redisTickClient.Lists[Ticks.GetTickListNamePrefix(tickSize) + secId]; if (quotes.Count == 0) //fill in non-changing ticks { if (list.Count > 0) { var last = list[list.Count - 1]; //redis last tick is newer if (last.T >= dtAyondoNow) { return;//impossible } //update last tick in redis if (Ticks.IsTickEqual(last.T, dtAyondoNow, tickSize)) { //do nothing } else //append new tick with the same price as redis last { list.Add(new Tick() { P = last.P, T = dtAyondoNow }); } } } else { var lastQuote = quotes.OrderByDescending(o => o.Time).First(); var newTick = new Tick { P = Quotes.GetLastPrice(lastQuote), T = dtAyondoNow }; if (list.Count == 0) //new products coming { list.Add(newTick); return; } var last = list[list.Count - 1]; //redis last tick is newer if (last.T >= dtAyondoNow) { return;//impossible } //update last tick in redis if (Ticks.IsTickEqual(last.T, dtAyondoNow, tickSize)) { ////last price dominate //list[list.Count - 1] = newTick; //first price dominate //do nothing } else //append new last tick { list.Add(newTick); } } //clear history/prevent data increasing for good var clearWhenSize = Ticks.GetClearWhenSize(tickSize); var clearToSize = Ticks.GetClearToSize(tickSize); if (list.Count > clearWhenSize) //data count at most possible size (in x days ) { YJYGlobal.LogLine("Tick " + tickSize + " " + secId + " Clearing data from " + list.Count + " to " + clearToSize); var ticks = list.GetAll(); var newTicks = ticks.Skip(ticks.Count - clearToSize); list.RemoveAll(); list.AddRange(newTicks); } }
static int Main(string[] args) { GetProgramVariables(args); CreateLogDirectory(); SetupLogger(); Environment.CurrentDirectory = exeDir; // set curdir so local ./caches works when running in SQL Agent //bool isMonitoring = args.Contains("-Monitor") && args.Length == 1; DateTime startupTime = DateTime.Now; bool completedWithoutError = true; LogJobStartup();//(db, isMonitoring); try { if (args.Contains("-AyondoFixFeed")) { AyondoFixFeedWorker.Run(); } if (args.Contains("-PositionCheck")) { PositionCheck.Run(); } if (args.Contains("-PositionClose")) { PositionClose.Run(); } return(0); } catch (Exception ex) { YJYGlobal.LogLine("EXCEPTION MAIN THREAD ### [" + ex.GetType().ToString() + "] " + ex.Message + " ###"); YJYGlobal.LogException(ex); completedWithoutError = false; return(1); } finally { TimeSpan execTime = DateTime.Now.Subtract(startupTime); //// wait for child foreground threads to end //foreach (Thread t in thc.Global.ForegroundThreads) //{ // //Global.LogLine("joining thread '" + t.Name + "'..."); // t.Join(); //} //JobsGlobal.LogLine("all foreground threads join-completed."); //if (!isMonitoring) //{ execTime = LogEndOfJob(execTime); //} Trace.Close(); if (completedWithoutError) { File.Move(logFullPath, logFullPath.Replace("INPROCESS.", "OK.") + "_" + execTime.TotalMinutes.ToString("0") + ".MINS.LOG"); } else { File.Move(logFullPath, logFullPath.Replace("INPROCESS.", "FAILED.") + "_" + execTime.TotalMinutes.ToString("0") + ".MINS.LOG"); } } }
private static void SaveRawTicks(object state) { while (true) { try { IList <Quote> quotes = new List <Quote>(); while (!myApp.QueueQuotesForRawTick.IsEmpty) { Quote obj; var tryDequeue = myApp.QueueQuotesForRawTick.TryDequeue(out obj); quotes.Add(obj); } if (quotes.Count > 0) { var quoteGroups = quotes.GroupBy(o => o.Id).ToList(); var dtBeginSave = DateTime.Now; var count = 0; //var entitiesToSaveToDB = new List<QuoteHistory>(); using (var redisClient = YJYGlobal.PooledRedisClientsManager.GetClient()) { var redisTickClient = redisClient.As <Tick>(); foreach (var quoteGroup in quoteGroups) { if (!myApp.ProdDefs.ContainsKey(quoteGroup.Key)) //no product definition { YJYGlobal.LogLine("SaveRawTicks: no prodDef. tick ignored " + quoteGroup.Key); continue; } var prodDef = myApp.ProdDefs[quoteGroup.Key]; if (prodDef.QuoteType != enmQuoteType.Open && prodDef.QuoteType != enmQuoteType.PhoneOnly) //not open not phoneOnly { YJYGlobal.LogLine("\tSaveRawTicks: prod not opening. tick ignored. " + prodDef.Id + " " + prodDef.Name); continue; } var list = redisTickClient.Lists[Ticks.GetTickListNamePrefix(TickSize.Raw) + quoteGroup.Key]; var ticksToAdd = quoteGroup.Select(o => new Tick { P = Quotes.GetLastPrice(o), T = o.Time }) .OrderBy(o => o.T) .ToList(); list.AddRange(ticksToAdd); count++; //clear history to prevent data size get too big var clearWhenSize = Ticks.GetClearWhenSize(TickSize.Raw); var clearToSize = Ticks.GetClearToSize(TickSize.Raw); if (list.Count > clearWhenSize) { YJYGlobal.LogLine("Raw Ticks " + quoteGroup.Key + " Clearing data from " + list.Count + " to " + clearToSize); var ticks = list.GetAll(); var newTicks = ticks.Skip(ticks.Count - clearToSize); list.RemoveAll(); list.AddRange(newTicks); } } } YJYGlobal.LogLine("\t" + TickSize.Raw + " Ticks " + count + "/" + quoteGroups.Count + "/" + quotes.Count + " " + " Time: " + quotes.Min(o => o.Time).ToString(YJYGlobal.DATETIME_MASK_MILLI_SECOND) + " ~ " + quotes.Max(o => o.Time).ToString(YJYGlobal.DATETIME_MASK_MILLI_SECOND) + " Saved to Redis " + (DateTime.Now - dtBeginSave).TotalMilliseconds); } } catch (Exception e) { YJYGlobal.LogException(e); } Thread.Sleep(_intervalRawTicks); } }
public void OnLogout(SessionID sessionID) { YJYGlobal.LogLine("OnLogout: "); }
public void OnCreate(SessionID sessionID) { YJYGlobal.LogLine("OnCreate: "); }
public static void Run() { YJYGlobal.LogLine("Starting..."); //var mapper = MapperConfig.GetAutoMapperConfiguration().CreateMapper(); _queueClient = new QueueClient(ServiceBusConnectionString, QueueName); while (true) { try { using (var redisClient = YJYGlobal.PooledRedisClientsManager.GetClient()) { var redisProdDefClient = redisClient.As <ProdDef>(); var redisQuoteClient = redisClient.As <Quote>(); //var redisTickClient = redisClient.As<Tick>(); using (var db = YJYEntities.Create()) { var openPositions = db.Positions.Where(o => o.ClosedAt == null).ToList(); var prodDefs = redisProdDefClient.GetAll(); var quotes = redisQuoteClient.GetAll(); var openPositionsNotSent = openPositions.Where(o => !_sentPosIds.ContainsKey(o.Id)).ToList(); if (new Random().NextDouble() > 0.9) { YJYGlobal.LogLine(openPositionsNotSent.Count + "/" + openPositions.Count + " (notSent/all) open positions."); } var messages = new List <Message>(); var posIds = new List <int>(); var groups = openPositionsNotSent.GroupBy(o => o.SecurityId).ToList(); foreach (var group in groups) //foreach security { var secId = group.Key; //YJYGlobal.LogLine("sec: " + secId + " alert_count: " + group.Count()); var prodDef = prodDefs.FirstOrDefault(o => o.Id == secId); var quote = quotes.FirstOrDefault(o => o.Id == secId); if (prodDef == null || quote == null) { YJYGlobal.LogLine("cannot find prodDef/quote " + secId); continue; } if (prodDef.QuoteType == enmQuoteType.Closed || prodDef.QuoteType == enmQuoteType.Inactive) { //YJYGlobal.LogLine("prod " + prodDef.Id + " quoteType is " + prodDef.QuoteType); continue; } //if (DateTime.UtcNow - quote.Time > _tolerance) //{ // YJYGlobal.LogLine("quote " + quote.Id + " too old " + quote.Time); // continue; //} ////get historical highest and lowest price //decimal highestBid; //decimal lowestAsk; //var ticks = redisTickClient.Lists[Ticks.GetTickListNamePrefix(TickSize.Raw) + prodDef.Id].GetAll(); //var dtUtcNow = DateTime.UtcNow; //if (!_lastFetchTill.ContainsKey(prodDef.Id)) //{s // var historyTicks = ticks.Select(o => o.Time > dtUtcNow - _tolerance).ToList(); //} var last = Quotes.GetLastPrice(quote); foreach (var p in group) //foreach alert belong to a security { //position goes to 0% var upl = Trades.CalculatePL(p, last, false); var inv = p.Invest.Value.ToString("0"); var lev = p.Leverage.Value.ToString("0"); var setPx = p.SettlePrice.Value.ToString("F" + prodDef.Prec); if (upl + p.Invest <= 0) { YJYGlobal.LogLine( $"position {p.Id} ({(p.Side.Value ? "↗" : "↘")} {inv}x{lev} at {setPx}) CLOSED at {last} PL {upl.ToString("0.00")}"); posIds.Add(p.Id); messages.Add(new Message(Serialization.ObjectToByteArray( new PosToClose() { Id = p.Id, closeType = PositionCloseType.Liquidate, closePx = last, closePxTime = quote.Time, }))); continue; } //stop if (p.StopPx != null) { if (p.Side.Value && last <= p.StopPx || !p.Side.Value && last >= p.StopPx) { YJYGlobal.LogLine( $"position {p.Id} ({(p.Side.Value ? "↗" : "↘")} {inv}x{lev} at {setPx}) STOPPED at {last} PL {upl.ToString("0.00")}"); posIds.Add(p.Id); messages.Add(new Message(Serialization.ObjectToByteArray( new PosToClose() { Id = p.Id, closeType = PositionCloseType.Stop, closePx = last, closePxTime = quote.Time, }))); continue; } } //take if (p.TakePx != null) { if (p.Side.Value && last >= p.TakePx || !p.Side.Value && last <= p.TakePx) { YJYGlobal.LogLine( $"position {p.Id} ({(p.Side.Value ? "↗" : "↘")} {inv}x{lev} at {setPx}) TAKEN at {last} PL {upl.ToString("0.00")}"); posIds.Add(p.Id); messages.Add(new Message(Serialization.ObjectToByteArray( new PosToClose() { Id = p.Id, closeType = PositionCloseType.Take, closePx = last, closePxTime = quote.Time, }))); continue; } } } //db.SaveChanges(); } if (messages.Count > 0) { _queueClient.SendAsync(messages); foreach (var posId in posIds) { _sentPosIds.Add(posId, DateTime.UtcNow); } } } } } catch (Exception e) { YJYGlobal.LogException(e); } //YJYGlobal.LogLine(""); Thread.Sleep(_sleepInterval); } }
public void FromAdmin(Message message, SessionID sessionID) { YJYGlobal.LogLine("FromAdmin: "); }
public PositionDTO NewPosition(NewPositionFormDTO form) { if (form.invest <= 0 || form.invest > 10000) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "invalid invest")); } if (form.leverage < 1) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "invalid leverage")); } var user = GetUser(); var balance = db.Balances.FirstOrDefault(o => o.Id == user.ActiveBalanceId); if (balance.Amount < form.invest) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, Resources.Resource.NotEnoughBalance)); } var cache = WebCache.Instance; decimal spread = 0.0005M; //点差,默认万分之五 var spreadMisc = db.Miscs.FirstOrDefault(m => m.Key == "spread"); if (spreadMisc != null) { decimal.TryParse(spreadMisc.Value, out spread); } var prodDef = cache.ProdDefs.FirstOrDefault(o => o.Id == form.securityId); if (prodDef.QuoteType == enmQuoteType.Closed || prodDef.QuoteType == enmQuoteType.Inactive) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, Resources.Resource.ProductClosed)); } //if (form.leverage > prodDef.MaxLeverage) if (form.leverage > MAX_LEVERAGE) { throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "exceeded max leverage")); } var quote = cache.Quotes.FirstOrDefault(o => o.Id == form.securityId); var positionService = new PositionService(); var price = Quotes.GetLastPrice(quote); if (form.isLong) //买多,买入价 = 买入价 + 加点差 { price = (1 + spread) * price; } else //买空, 买入价 = 买入价 - 加点差 { price = (1 - spread) * price; } var newPosition = positionService.CreateNewPosition(UserId, form.securityId, form.invest, form.isLong, form.leverage, price); var posIdToFollow = newPosition.Id; Task.Run(() => { YJYGlobal.LogLine("NEW THREAD: check and OPEN follow positions for pos " + posIdToFollow); PositionService.CheckAndOpenFollowPositions(posIdToFollow); }); var posDTO = new PositionDTO() { id = newPosition.Id, isLong = newPosition.Side.Value, settlePrice = newPosition.SettlePrice.Value, invest = newPosition.Invest.Value, leverage = newPosition.Leverage.Value, createAt = newPosition.CreateTime.Value, }; return(posDTO); }
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()); } }