public AccountsMarginLevelResponse GetAccountsMarginLevels(decimal threshold) { var accounts = _accountsCacheService.GetAll() .Select(a => new AccountsMarginLevelContract { AccountId = a.Id, ClientId = a.ClientId, TradingConditionId = a.TradingConditionId, BaseAssetId = a.BaseAssetId, Balance = a.Balance, MarginLevel = a.GetMarginUsageLevel(), OpenedPositionsCount = a.GetOpenPositionsCount(), UsedMargin = a.GetUsedMargin(), TotalBalance = a.GetTotalCapital() }) .Where(a => a.MarginLevel <= threshold) .ToArray(); return(new AccountsMarginLevelResponse { DateTime = _dateService.Now(), Levels = accounts }); }
public async Task <InitDataBackendResponse> InitData([FromBody] ClientIdBackendRequest request) { if (string.IsNullOrWhiteSpace(request?.ClientId)) { throw new ArgumentNullException(nameof(ClientIdBackendRequest.ClientId)); } var accounts = _accountsCacheService.GetAll(request.ClientId).ToArray(); if (accounts.Length == 0 && !_marginSettings.IsLive) { accounts = await _accountManager.CreateDefaultAccounts(request.ClientId); } if (accounts.Length == 0) { return(InitDataBackendResponse.CreateEmpty()); } var assets = _accountAssetsCacheService.GetClientAssets(accounts); var result = BackendContractFactory.CreateInitDataBackendResponse(accounts, assets, _marginSettings.IsLive); result.IsLive = _marginSettings.IsLive; return(result); }
private void ValidateClient(string clientId) { var userAccounts = _accountsCacheService.GetAll(clientId); if (!userAccounts.Any()) { throw new ArgumentException("Invalid ClientId"); } }
public async Task DumpReportData() { var positions = _ordersCache.GetPositions(); var accountStat = _accountsCacheService.GetAll(); await Task.WhenAll( _openPositionsRepository.Dump(positions), _accountStatRepository.Dump(accountStat)); }
private void HandleOvernightMarginWarnings() { foreach (var account in _accountsCacheService.GetAll()) { var accountOvernightUsedMargin = _accountUpdateService.CalculateOvernightUsedMargin(account); var accountLevel = account.GetAccountLevel(accountOvernightUsedMargin); if (accountLevel == AccountLevel.StopOut) { _marginCallEventChannel.SendEvent(this, new MarginCallEventArgs(account, AccountLevel.OvernightMarginCall)); } } }
public async Task <string> MakeTradingDataSnapshot(DateTime tradingDay, string correlationId) { if (!_scheduleSettingsCacheService.TryGetPlatformCurrentDisabledInterval(out var disabledInterval)) { throw new Exception( "Trading should be stopped for whole platform in order to make trading data snapshot."); } if (disabledInterval.Start.AddDays(-1) > tradingDay.Date || disabledInterval.End < tradingDay.Date) { throw new Exception( $"{nameof(tradingDay)}'s Date component must be from current disabled interval's Start -1d to End: [{disabledInterval.Start.AddDays(-1)}, {disabledInterval.End}]."); } await _semaphoreSlim.WaitAsync(); try { var orders = _orderReader.GetAllOrders(); var positions = _orderReader.GetPositions(); var accountStats = _accountsCacheService.GetAll(); var bestFxPrices = _fxRateCacheService.GetAllQuotes(); var bestPrices = _quoteCacheService.GetAllQuotes(); await _tradingEngineSnapshotsRepository.Add(tradingDay, correlationId, _dateService.Now(), orders.Select(x => x.ConvertToContract(_orderReader)).ToJson(), positions.Select(x => x.ConvertToContract(_orderReader)).ToJson(), accountStats.Select(x => x.ConvertToContract()).ToJson(), bestFxPrices.ToDictionary(q => q.Key, q => q.Value.ConvertToContract()).ToJson(), bestPrices.ToDictionary(q => q.Key, q => q.Value.ConvertToContract()).ToJson()); return($@"Trading data snapshot was written to the storage. Orders: {orders.Length}, positions: {positions.Length}, accounts: {accountStats.Count}, best FX prices: {bestFxPrices.Count}, best trading prices: {bestPrices.Count}."); } finally { _semaphoreSlim.Release(); } }
public Task Handle(MarketStateChangedEvent e, ICommandSender sender) { if (!e.IsEnabled) { return(Task.CompletedTask); } // resuming liquidations on corresponding accounts upon market open _accountsCacheService.GetAll() .Where(a => a.IsInLiquidation()) .SelectMany(a => _ordersCache.Positions.GetPositionsByAccountIds(a.Id)) .GroupBy(p => p.AccountId) .Where(AnyAssetRelatesToMarket) .ForEach(account => SendResumeCommand(account.Key)); return(Task.CompletedTask); #region internal functions bool AnyAssetRelatesToMarket(IGrouping <string, Position> positions) => positions .Select(p => _assetPairsCache.GetAssetPairById(p.AssetPairId)) .Any(assetPair => assetPair.MarketId == e.Id); void SendResumeCommand(string accountId) { var account = _accountsCacheService.Get(accountId); sender.SendCommand(new ResumeLiquidationInternalCommand { OperationId = account.LiquidationOperationId, CreationTime = DateTime.UtcNow, IsCausedBySpecialLiquidation = false, ResumeOnlyFailed = true, Comment = "Trying to resume liquidation because market has been opened" }, _cqrsContextNamesSettings.TradingEngine); } #endregion }
public Task <List <AccountStatContract> > GetAllAccountStats() { var stats = _accountsCacheService.GetAll(); return(Task.FromResult(stats.Select(x => x.ConvertToContract()).ToList())); }
public MarginTradingAccountBackendContract[] GetAllAccounts() { var accounts = _accountsCacheService.GetAll(); return(accounts.Select(item => item.ToFullBackendContract(_marginSettings.IsLive)).ToArray()); }
public IActionResult GetAllMarginTradingAccounts(string clientId) { var accounts = _accountsCacheService.GetAll(clientId); return(Ok(accounts)); }
/// <inheritdoc /> public async Task <string> MakeTradingDataSnapshot(DateTime tradingDay, string correlationId, SnapshotStatus status = SnapshotStatus.Final) { if (!_scheduleSettingsCacheService.TryGetPlatformCurrentDisabledInterval(out var disabledInterval)) { //TODO: remove later (if everything will work and we will never go to this branch) _scheduleSettingsCacheService.MarketsCacheWarmUp(); if (!_scheduleSettingsCacheService.TryGetPlatformCurrentDisabledInterval(out disabledInterval)) { throw new Exception( $"Trading should be stopped for whole platform in order to make trading data snapshot. Current schedule: {_scheduleSettingsCacheService.GetPlatformTradingSchedule()?.ToJson()}"); } } if (disabledInterval.Start.AddDays(-1) > tradingDay.Date || disabledInterval.End < tradingDay.Date) { throw new Exception( $"{nameof(tradingDay)}'s Date component must be from current disabled interval's Start -1d to End: [{disabledInterval.Start.AddDays(-1)}, {disabledInterval.End}]."); } if (Lock.CurrentCount == 0) { throw new InvalidOperationException("Trading data snapshot creation is already in progress"); } // We must be sure all messages have been processed by history brokers before starting current state validation. // If one or more queues contain not delivered messages the snapshot can not be created. _queueValidationService.ThrowExceptionIfQueuesNotEmpty(true); // Before starting snapshot creation the current state should be validated. var validationResult = await _snapshotValidationService.ValidateCurrentStateAsync(); if (!validationResult.IsValid) { var ex = new InvalidOperationException( $"The trading data snapshot might be corrupted. The current state of orders and positions is incorrect. Check the dbo.BlobData table for more info: container {LykkeConstants.MtCoreSnapshotBlobContainer}, correlationId {correlationId}"); await _log.WriteFatalErrorAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), validationResult.ToJson(), ex); await _blobRepository.WriteAsync(LykkeConstants.MtCoreSnapshotBlobContainer, correlationId, validationResult); } else { await _log.WriteInfoAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), "The current state of orders and positions is correct."); } await Lock.WaitAsync(); try { var orders = _orderReader.GetAllOrders(); var ordersJson = orders.Select(o => o.ConvertToSnapshotContract(_orderReader, status)).ToJson(); await _log.WriteInfoAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), $"Preparing data... {orders.Length} orders prepared."); var positions = _orderReader.GetPositions(); var positionsJson = positions.Select(p => p.ConvertToSnapshotContract(_orderReader, status)).ToJson(); await _log.WriteInfoAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), $"Preparing data... {positions.Length} positions prepared."); var accountStats = _accountsCacheService.GetAll(); var accountsJson = accountStats.Select(a => a.ConvertToSnapshotContract(status)).ToJson(); await _log.WriteInfoAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), $"Preparing data... {accountStats.Count} accounts prepared."); var bestFxPrices = _fxRateCacheService.GetAllQuotes(); var bestFxPricesData = bestFxPrices.ToDictionary(q => q.Key, q => q.Value.ConvertToContract()).ToJson(); await _log.WriteInfoAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), $"Preparing data... {bestFxPrices.Count} best FX prices prepared."); var bestPrices = _quoteCacheService.GetAllQuotes(); var bestPricesData = bestPrices.ToDictionary(q => q.Key, q => q.Value.ConvertToContract()).ToJson(); await _log.WriteInfoAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), $"Preparing data... {bestPrices.Count} best trading prices prepared."); var msg = $"TradingDay: {tradingDay:yyyy-MM-dd}, Orders: {orders.Length}, positions: {positions.Length}, accounts: {accountStats.Count}, best FX prices: {bestFxPrices.Count}, best trading prices: {bestPrices.Count}."; await _log.WriteInfoAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), $"Starting to write trading data snapshot. {msg}"); var snapshot = new TradingEngineSnapshot( tradingDay, correlationId, _dateService.Now(), ordersJson: ordersJson, positionsJson: positionsJson, accountsJson: accountsJson, bestFxPricesJson: bestFxPricesData, bestTradingPricesJson: bestPricesData, status: status); await _tradingEngineSnapshotsRepository.AddAsync(snapshot); await _log.WriteInfoAsync(nameof(SnapshotService), nameof(MakeTradingDataSnapshot), $"Trading data snapshot was written to the storage. {msg}"); return($"Trading data snapshot was written to the storage. {msg}"); } finally { Lock.Release(); } }