public void SetUp() { _currentOrders = new List <Order>(); _currentPositions = new List <Position>(); _ordersHistory = new List <OrderHistory>(); _positionsHistory = new List <IPositionHistory>(); _tradingEngineSnapshot = new TradingEngineSnapshot(DateTime.UtcNow, string.Empty, DateTime.UtcNow, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, SnapshotStatus.Final); _tradingEngineSnapshotsRepositoryMock.Setup(o => o.GetLastAsync()) .ReturnsAsync(() => _tradingEngineSnapshot); _orderCacheMock.Setup(o => o.GetAllOrders()) .Returns(() => _currentOrders.ToImmutableArray()); _orderCacheMock.Setup(o => o.GetPositions()) .Returns(() => _currentPositions.ToImmutableArray()); _ordersHistoryRepositoryMock.Setup(o => o.GetLastSnapshot(It.IsAny <DateTime>())) .ReturnsAsync((DateTime date) => _ordersHistory); _positionsHistoryRepositoryMock.Setup(o => o.GetLastSnapshot(It.IsAny <DateTime>())) .ReturnsAsync((DateTime date) => _positionsHistory); _service = new SnapshotValidationService( _tradingEngineSnapshotsRepositoryMock.Object, _ordersHistoryRepositoryMock.Object, _positionsHistoryRepositoryMock.Object, _orderCacheMock.Object, EmptyLog.Instance); }
public static List <MarginTradingAccount> GetAccountsFromDraft(this TradingEngineSnapshot snapshot) { if (snapshot.Status != SnapshotStatus.Draft) { throw new ArgumentOutOfRangeException(nameof(snapshot.Status), DraftStatusMessage); } return(GetAccounts <MarginTradingAccount>(snapshot)); }
public static List <Position> GetPositionsFromDraft(this TradingEngineSnapshot snapshot) { if (snapshot.Status != SnapshotStatus.Draft) { throw new ArgumentOutOfRangeException(nameof(snapshot.Status), DraftStatusMessage); } return(GetPositions <Position>(snapshot)); }
/// <inheritdoc /> public async Task UpdateAsync(ImmutableArray <Position> positions, ImmutableArray <Order> orders, ImmutableArray <MarginTradingAccount> accounts, IEnumerable <BestPriceContract> fxRates, IEnumerable <BestPriceContract> cfdQuotes) { if (!_tradingDay.HasValue) { throw new InvalidOperationException("Unable to update snapshot: the draft snapshot provider has not been initialized yet"); } if (positions == null || !positions.Any()) { throw new ArgumentNullException(nameof(positions), @"Unable to update snapshot: positions list is empty"); } if (orders == null || !orders.Any()) { throw new ArgumentNullException(nameof(orders), @"Unable to update snapshot: orders list is empty"); } if (accounts == null || !accounts.Any()) { throw new ArgumentNullException(nameof(accounts), @"Unable to update snapshot: accounts list is empty"); } await EnsureSnapshotLoadedOrThrowAsync(); var fxPrices = fxRates?.ToDictionary(r => r.Id, r => r); var tradingPrices = cfdQuotes?.ToDictionary(q => q.Id, q => q); _snapshot = new TradingEngineSnapshot(_snapshot.TradingDay, _snapshot.CorrelationId, _snapshot.Timestamp, orders.ToJson(), positions.ToJson(), accounts.ToJson(), _snapshot .GetBestFxPrices() .Merge(fxPrices) .ToJson(), _snapshot .GetBestTradingPrices() .Merge(tradingPrices) .ToJson(), _snapshot.Status); // to force keeper deserialize updated values from json next time data is accessed _positions = null; _orders = null; _accounts = null; _fxPrices = null; _cfdQuotes = null; }
public TradingEngineSnapshotEntity(TradingEngineSnapshot tradingEngineSnapshot) { TradingDay = tradingEngineSnapshot.TradingDay; CorrelationId = tradingEngineSnapshot.CorrelationId; Timestamp = tradingEngineSnapshot.Timestamp; Orders = tradingEngineSnapshot.OrdersJson; Positions = tradingEngineSnapshot.PositionsJson; AccountStats = tradingEngineSnapshot.AccountsJson; BestFxPrices = tradingEngineSnapshot.BestFxPricesJson; BestPrices = tradingEngineSnapshot.BestTradingPricesJson; Status = tradingEngineSnapshot.Status; }
private async Task EnsureSnapshotLoadedOrThrowAsync() { if (_snapshot == null) { if (!_tradingDay.HasValue) { throw new InvalidOperationException("The draft snapshot provider has not been initialized yet"); } _snapshot = await _tradingEngineSnapshotsRepository.GetLastDraftAsync(_tradingDay) ?? throw new TradingSnapshotDraftNotFoundException(_tradingDay.Value); } }
public async Task AddAsync(TradingEngineSnapshot tradingEngineSnapshot) { using (var conn = new SqlConnection(_connectionString)) { await _log.WriteInfoAsync(nameof(TradingEngineSnapshotsRepository), nameof(AddAsync), $"Writing {tradingEngineSnapshot.TradingDay:yyyy-MM-dd} snapshot to repository with {tradingEngineSnapshot.CorrelationId} correlationId."); var entity = new TradingEngineSnapshotEntity(tradingEngineSnapshot); await conn.ExecuteAsync( $@"INSERT INTO {TableName} (TradingDay,CorrelationId,Timestamp,Orders,Positions,AccountStats,BestFxPrices,BestPrices,Status) VALUES (@TradingDay,@CorrelationId,@Timestamp,@Orders,@Positions,@AccountStats,@BestFxPrices,@BestPrices,@Status)", entity, commandTimeout : _settings.SnapshotInsertTimeoutSec); } }
private static List <T> GetOrders <T>(this TradingEngineSnapshot snapshot) { return(string.IsNullOrWhiteSpace(snapshot.OrdersJson) ? new List <T>() : snapshot.OrdersJson.DeserializeJson <List <T> >()); }
public static Dictionary <string, BestPriceContract> GetBestTradingPrices(this TradingEngineSnapshot snapshot) { return(string.IsNullOrWhiteSpace(snapshot.BestTradingPricesJson) ? new Dictionary <string, BestPriceContract>() : snapshot.BestTradingPricesJson.DeserializeJson <Dictionary <string, BestPriceContract> >()); }
public static List <AccountStatContract> GetAccounts(this TradingEngineSnapshot snapshot) { return(GetAccounts <AccountStatContract>(snapshot)); }
public static List <OpenPositionContract> GetPositions(this TradingEngineSnapshot snapshot) { return(GetPositions <OpenPositionContract>(snapshot)); }
public async Task <string> AddOrUpdateFakeTradingDataSnapshot(DateTime tradingDay, string correlationId, List <OrderContract> orders, List <OpenPositionContract> positions, List <AccountStatContract> accounts, Dictionary <string, BestPriceContract> bestFxPrices, Dictionary <string, BestPriceContract> bestTradingPrices) { if (_semaphoreSlim.CurrentCount == 0) { var handle = _semaphoreSlim.AvailableWaitHandle; var handleResult = handle.WaitOne(TimeSpan.FromMinutes(1)); if (!handleResult) { return("Operation timeout"); } } await _semaphoreSlim.WaitAsync(); try { var msg = $"TradingDay: {tradingDay:yyyy-MM-dd}, Orders: {orders.Count}, positions: {positions.Count}, accounts: {accounts.Count}, best FX prices: {bestFxPrices.Count}, best trading prices: {bestTradingPrices.Count}."; await _log.WriteInfoAsync(nameof(FakeSnapshotService), nameof(AddOrUpdateFakeTradingDataSnapshot), $"Starting to write trading data snapshot. {msg}"); var snapshot = await _tradingEngineSnapshotsRepository.Get(correlationId); if (snapshot != null) { orders = Union(orders, snapshot.GetOrders(), order => order.Id); positions = Union(positions, snapshot.GetPositions(), position => position.Id); accounts = Union(accounts, snapshot.GetAccounts(), account => account.AccountId); bestFxPrices = Union(bestFxPrices, snapshot.GetBestFxPrices()); bestTradingPrices = Union(bestTradingPrices, snapshot.GetBestTradingPrices()); } var newSnapshot = new TradingEngineSnapshot( tradingDay, correlationId, _dateService.Now(), positionsJson: positions.ToJson(), ordersJson: orders.ToJson(), accountsJson: accounts.ToJson(), bestFxPricesJson: bestFxPrices.ToJson(), bestTradingPricesJson: bestTradingPrices.ToJson(), status: SnapshotStatus.Final); await _tradingEngineSnapshotsRepository.AddAsync(newSnapshot); await _log.WriteInfoAsync(nameof(FakeSnapshotService), nameof(AddOrUpdateFakeTradingDataSnapshot), $"Trading data snapshot was written to the storage. {msg}"); return($"Trading data snapshot was written to the storage. {msg}"); } finally { _semaphoreSlim.Release(); } }
public Task AddAsync(TradingEngineSnapshot tradingEngineSnapshot) { throw new NotImplementedException(); }
private static IReadOnlyList <OpenPositionContract> GetPositions(TradingEngineSnapshot tradingEngineSnapshot) => !string.IsNullOrEmpty(tradingEngineSnapshot.PositionsJson) ? tradingEngineSnapshot.PositionsJson.DeserializeJson <List <OpenPositionContract> >() : new List <OpenPositionContract>();
private static IReadOnlyList <OrderContract> GetOrders(TradingEngineSnapshot tradingEngineSnapshot) => !string.IsNullOrEmpty(tradingEngineSnapshot.OrdersJson) ? tradingEngineSnapshot.OrdersJson.DeserializeJson <List <OrderContract> >() : new List <OrderContract>();
public static List <OrderContract> GetOrders(this TradingEngineSnapshot snapshot) { return(GetOrders <OrderContract>(snapshot)); }
/// <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(); } }