void IEventConsumer <StopOutEventArgs> .ConsumeEvent(object sender, StopOutEventArgs ea) { var account = ea.Account; var orders = ea.Orders; var eventTime = _dateService.Now(); var accountMarginEventMessage = AccountMarginEventMessageConverter.Create(account, true, eventTime); var accuracy = _assetsCache.GetAssetAccuracy(account.BaseAssetId); var totalPnl = Math.Round(orders.Sum(x => x.GetTotalFpl()), accuracy); _threadSwitcher.SwitchThread(async() => { _operationsLogService.AddLog("stopout", account.ClientId, account.Id, "", ea.ToJson()); var marginEventTask = _rabbitMqNotifyService.AccountMarginEvent(accountMarginEventMessage); _notifyService.NotifyAccountStopout(account.ClientId, account.Id, orders.Length, totalPnl); var notificationTask = SendMarginEventNotification(account.ClientId, string.Format(MtMessages.Notifications_StopOutNotification, orders.Length, totalPnl, account.BaseAssetId)); var clientEmail = await _clientAccountService.GetEmail(account.ClientId); var emailTask = !string.IsNullOrEmpty(clientEmail) ? _emailService.SendStopOutEmailAsync(clientEmail, account.BaseAssetId, account.Id) : Task.CompletedTask; await Task.WhenAll(marginEventTask, notificationTask, emailTask); }); }
public async Task SendMarginCallEmailAsync(IMarginTradingAccount account) { var clientEmail = await _clientAccountService.GetEmail(account.ClientId); if (string.IsNullOrEmpty(clientEmail)) { return; } var message = _templateGenerator.Generate(GetMarginCallTemplate(account.LegalEntity), new { account.BaseAssetId, AccountId = account.Id, System.DateTime.UtcNow.Year }); await _emailSender.SendAsync( new EmailMessage { HtmlBody = message, Subject = "Margin call" }, new EmailAddressee { EmailAddress = clientEmail }); }
void IEventConsumer <MarginCallEventArgs> .ConsumeEvent(object sender, MarginCallEventArgs ea) { var account = ea.Account; var eventTime = _dateService.Now(); var(level, lastNotifications) = LevelAndNotificationsCache(ea.MarginCallLevel); if (lastNotifications == null) { return; } var accountMarginEventMessage = AccountMarginEventMessageConverter.Create(account, level, eventTime); _threadSwitcher.SwitchThread(async() => { if (lastNotifications.TryGetValue(account.Id, out var lastNotification) && lastNotification.AddMinutes(_settings.Throttling.MarginCallThrottlingPeriodMin) > eventTime) { _log.WriteInfo(nameof(MarginCallConsumer), nameof(IEventConsumer <MarginCallEventArgs> .ConsumeEvent), $"MarginCall event is ignored for accountId {account.Id} because of throttling: event time {eventTime}, last notification was sent at {lastNotification}"); return; } var marginEventTask = _rabbitMqNotifyService.AccountMarginEvent(accountMarginEventMessage); _operationsLogService.AddLog($"margin call: {level.ToString()}", account.Id, "", ea.ToJson()); var clientEmail = await _clientAccountService.GetEmail(account.ClientId); var emailTask = !string.IsNullOrEmpty(clientEmail) ? _emailService.SendMarginCallEmailAsync(clientEmail, account.BaseAssetId, account.Id) : Task.CompletedTask; await Task.WhenAll(marginEventTask, emailTask); lastNotifications.AddOrUpdate(account.Id, eventTime, (s, times) => eventTime); }); }
void IEventConsumer <MarginCallEventArgs> .ConsumeEvent(object sender, MarginCallEventArgs ea) { var account = ea.Account; var eventTime = _dateService.Now(); var accountMarginEventMessage = AccountMarginEventMessageConverter.Create(account, false, eventTime); _threadSwitcher.SwitchThread(async() => { if (LastNotifications.TryGetValue(account.Id, out var lastNotification) && lastNotification.AddMinutes(NotificationsTimeout) > eventTime) { return; } var marginEventTask = _rabbitMqNotifyService.AccountMarginEvent(accountMarginEventMessage); _operationsLogService.AddLog("margin call", account.ClientId, account.Id, "", ea.ToJson()); var marginUsageLevel = account.GetMarginUsageLevel(); var marginUsedPerc = marginUsageLevel == 0 ? 0 : 1 / marginUsageLevel; var notificationTask = SendMarginEventNotification(account.ClientId, string.Format( MtMessages.Notifications_MarginCall, marginUsedPerc, account.BaseAssetId)); var clientEmail = await _clientAccountService.GetEmail(account.ClientId); var emailTask = !string.IsNullOrEmpty(clientEmail) ? _emailService.SendMarginCallEmailAsync(clientEmail, account.BaseAssetId, account.Id) : Task.CompletedTask; await Task.WhenAll(marginEventTask, notificationTask, emailTask); LastNotifications.AddOrUpdate(account.Id, eventTime, (s, time) => eventTime); }); }
public void PerformEmailNotification(DateTime calculationTime) { _threadSwitcher.SwitchThread(async() => { await _semaphore.WaitAsync(); try { var processedCalculations = (await _overnightSwapHistoryRepository.GetAsync(calculationTime, null)) .Where(x => x.IsSuccess && x.Time >= calculationTime) .ToList(); var notifications = processedCalculations .GroupBy(x => x.ClientId) .Select(c => new OvernightSwapNotification { CliendId = c.Key, CalculationsByAccount = c.GroupBy(a => a.AccountId) .Select(a => { var account = _accountsCacheService.Get(c.Key, a.Key); if (account == null) { return(null); } return(new OvernightSwapNotification.AccountCalculations() { AccountId = a.Key, AccountCurrency = account.BaseAssetId, Calculations = a.Select(calc => { var instrumentName = _assetPairsCache.GetAssetPairByIdOrDefault(calc.Instrument)?.Name ?? calc.Instrument; return new OvernightSwapNotification.SingleCalculation { Instrument = instrumentName, Direction = calc.Direction == OrderDirection.Buy ? "Long" : "Short", Volume = calc.Volume, SwapRate = calc.SwapRate, Cost = calc.Value, PositionId = calc.OpenOrderId, }; }).ToList() }); }).Where(x => x != null).ToList() } ); var clientsWithIncorrectMail = new List <string>(); var clientsSentEmails = new List <string>(); foreach (var notification in notifications) { try { var clientEmail = await _clientAccountService.GetEmail(notification.CliendId); if (string.IsNullOrEmpty(clientEmail)) { clientsWithIncorrectMail.Add(notification.CliendId); continue; } await _emailService.SendOvernightSwapEmailAsync(clientEmail, notification); clientsSentEmails.Add(notification.CliendId); } catch (Exception e) { await _log.WriteErrorAsync(nameof(OvernightSwapNotificationService), nameof(PerformEmailNotification), e, DateTime.UtcNow); } } if (clientsWithIncorrectMail.Any()) { await _log.WriteWarningAsync(nameof(OvernightSwapNotificationService), nameof(PerformEmailNotification), $"Emails of some clients are incorrect: {string.Join(", ", clientsWithIncorrectMail)}.", DateTime.UtcNow); } if (clientsSentEmails.Any()) { await _log.WriteInfoAsync(nameof(OvernightSwapNotificationService), nameof(PerformEmailNotification), $"Emails sent to: {string.Join(", ", clientsSentEmails)}.", DateTime.UtcNow); } } finally { _semaphore.Release(); } }); }