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));
        }
Пример #4
0
        /// <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;
        }
Пример #5
0
 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;
 }
Пример #6
0
        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));
 }
Пример #12
0
        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();
            }
        }
Пример #13
0
 public Task AddAsync(TradingEngineSnapshot tradingEngineSnapshot)
 {
     throw new NotImplementedException();
 }
Пример #14
0
 private static IReadOnlyList <OpenPositionContract> GetPositions(TradingEngineSnapshot tradingEngineSnapshot)
 => !string.IsNullOrEmpty(tradingEngineSnapshot.PositionsJson)
         ? tradingEngineSnapshot.PositionsJson.DeserializeJson <List <OpenPositionContract> >()
         : new List <OpenPositionContract>();
Пример #15
0
 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));
 }
Пример #17
0
        /// <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();
            }
        }