Exemplo n.º 1
0
        private void Initialize()
        {
            _log.Info("Initializing last state from history if needed...");

            lock (_syncLastReset)
                _lastReset = _firstStateAfterResetTimeRepository.GetAsync().GetAwaiter().GetResult();

            // Initialize _allMarketCaps
            RefreshCoinMarketCapDataAsync().GetAwaiter().GetResult();

            // Restore top assets from DB
            var lastIndexHistory = _indexHistoryRepository.TakeLastAsync(1).GetAwaiter().GetResult().SingleOrDefault();

            // if found then restore _topAssets (constituents)
            if (lastIndexHistory != null)
            {
                lock (_syncLastIndexHistory)
                    _lastIndexHistory = lastIndexHistory;

                lock (_sync)
                    _topAssets.AddRange(lastIndexHistory.Weights.Keys);

                _log.Info("Initialized previous weights and market caps from history.");
            }
        }
        public async Task <IndexHistory> GetAsync(DateTime dateTime)
        {
            var model = await _storage.GetDataAsync(GetPartitionKey(dateTime), GetRowKey(dateTime));

            if (model == null)
            {
                return(null);
            }

            var blob = await _blobRepository.GetAsync(dateTime);

            if (blob == null)
            {
                return(null);
            }

            var tickPrices  = Mapper.Map <IReadOnlyCollection <TickPrice> >(blob.TickPrices);
            var assetPrices = Mapper.Map <IReadOnlyCollection <AssetPrice> >(blob.GetAssetPrices());

            var domain = new IndexHistory(
                model.Value,
                Mapper.Map <AssetMarketCap[]>(model.MarketCaps),
                model.Weights,
                tickPrices,
                assetPrices,
                model.MiddlePrices,
                model.Time,
                Mapper.Map <AssetSettings[]>(model.AssetsSettings));

            return(domain);
        }
Exemplo n.º 3
0
        private async Task SaveAsync(IndexState indexState, IndexHistory indexHistory)
        {
            // Save index state for the next execution
            await _indexStateRepository.SetAsync(indexState);

            // Save index history
            await _indexHistoryRepository.InsertAsync(indexHistory);
        }
        public async Task InsertAsync(IndexHistory domain)
        {
            // Table
            var entity = Mapper.Map <IndexHistoryEntity>(domain);

            entity.PartitionKey = GetPartitionKey(domain.Time);
            entity.RowKey       = GetRowKey(domain.Time);
            await _storage.InsertOrReplaceAsync(entity);

            // Blob
            var blob = Mapper.Map <IndexHistoryBlob>(domain);
            await _blobRepository.SaveAsync(blob);
        }
Exemplo n.º 5
0
        private void Publish(IndexHistory indexHistory)
        {
            var assetsInfo   = new List <Contract.AssetInfo>();
            var frozenAssets = indexHistory.AssetsSettings.Where(x => x.IsDisabled).Select(x => x.AssetId).ToList();

            foreach (var asset in indexHistory.Weights.Keys.ToList())
            {
                var isFrozen = frozenAssets.Contains(asset);

                assetsInfo.Add(new Contract.AssetInfo(asset, indexHistory.Weights[asset], indexHistory.MiddlePrices[asset], isFrozen));
            }

            // Publish index to RabbitMq
            var tickPrice = new Contract.IndexTickPrice(RabbitMqSource, _indexName.ToUpper(), indexHistory.Value, indexHistory.Value, indexHistory.Time, assetsInfo);

            _tickPricePublisher.Publish(tickPrice);
        }
Exemplo n.º 6
0
        private async Task CalculateThenSaveAndPublishAsync()
        {
            _log.Info("Started calculating index...");

            var settings = Settings;

            var whiteListAssets = settings.Assets;

            if (!whiteListAssets.Any())
            {
                _log.Info("There are no assets in the white list, skipped index calculation.");
                return;
            }

            IReadOnlyCollection <string>         topAssets;
            IReadOnlyCollection <AssetMarketCap> allMarketCaps;

            lock (_sync)
            {
                allMarketCaps = _allMarketCaps.ToList();
                topAssets     = _topAssets; // Must be obtained from _topAssets (daily rebuild changes it)
            }
            if (!topAssets.Any())
            {
                _log.Info("There are no top assets yet, skipped index calculation.");
                return;
            }

            var lastIndex = await _indexStateRepository.GetAsync();

            var sources        = settings.Sources.ToList();
            var tickPrices     = _tickPricesService.GetTickPrices(sources);
            var assetPrices    = _tickPricesService.GetAssetPrices(sources);
            var assetsSettings = settings.AssetsSettings;
            var topUsingPrices = GetAssetsUsingPrices(topAssets, assetPrices, assetsSettings);

            // If just started and prices are not present yet, then skip.
            // If started more then {_waitForTopAssetsPricesFromStart} ago then write warning to DB and log.
            var areAllPricesPresent = await ArePricesPresentForAllAssets(topAssets, topUsingPrices);

            if (!areAllPricesPresent)
            {
                return;
            }

            // Auto freeze
            await AutoFreezeIfNeeded(topAssets, topUsingPrices, lastIndex, settings);

            assetsSettings = Settings.AssetsSettings;

            // Recalculate top weights
            var topSupplies   = new Dictionary <string, decimal>();
            var topMarketCaps = allMarketCaps.Where(x => topAssets.Contains(x.Asset)).ToList();

            foreach (var mc in topMarketCaps)
            {
                topSupplies.Add(mc.Asset, mc.CirculatingSupply);
            }

            var calculatedTopMarketCaps = CalculateMarketCaps(topAssets, topSupplies, topUsingPrices);

            lock (_sync)
            {
                _lastTopAssetMarketCaps.Clear();
                foreach (var mc in calculatedTopMarketCaps)
                {
                    _lastTopAssetMarketCaps[mc.Asset] = mc.MarketCap.Value;
                }
            }

            var calculatedTopWeights = CalculateWeightsOrderedByDesc(calculatedTopMarketCaps);

            // Calculate current index state
            var indexState = CalculateIndex(lastIndex, calculatedTopWeights, topUsingPrices);

            // Calculate current index history element
            var indexHistory = new IndexHistory(
                indexState.Value,
                calculatedTopMarketCaps,
                calculatedTopWeights,
                tickPrices.SelectMany(x => x.Value).ToList(),
                assetPrices.SelectMany(x => x.Value).ToList(),
                topUsingPrices,
                DateTime.UtcNow,
                assetsSettings);

            // if there was a reset then skip until next iteration which will have initial state
            if (State == null)
            {
                if (indexState.Value != InitialIndexValue)
                {
                    _log.Info($"Skipped saving and publishing index because of reset - previous state is null and current index not equals {InitialIndexValue}.");
                    return;
                }

                await _firstStateAfterResetTimeRepository.SetAsync(indexHistory.Time);

                lock (_syncLastReset)
                    _lastReset = indexHistory.Time;

                _log.Info($"Reset at: {indexHistory.Time.ToIsoDateTime()}.");
            }

            // Skip if changed to 'disabled'
            if (!Settings.Enabled)
            {
                _log.Info($"Skipped saving and publishing index because {nameof(Settings)}.{nameof(Settings.Enabled)} = {Settings.Enabled}.");
                return;
            }

            lock (_syncLastIndexHistory)
                _lastIndexHistory = indexHistory;

            await SaveAsync(indexState, indexHistory);

            Publish(indexHistory);

            await _indexHandler.HandleAsync(indexHistory);

            _log.Info($"Finished calculating index for {calculatedTopMarketCaps.Count} assets, value: {indexState.Value}.");
        }
        public Task HandleAsync(IndexHistory indexHistory)
        {
            try
            {
                lock (_sync24H)
                {
                    if (!_initialized)
                    {
                        Initialize();
                        _initialized = true;
                    }

                    _currentValue = indexHistory.Value;

                    _history24H[indexHistory.Time] = indexHistory.Value;

                    // remove old
                    foreach (var time in _history24H.Keys.ToList())
                    {
                        if (time < DateTime.UtcNow.AddDays(-1))
                        {
                            _history24H.Remove(time);
                        }
                    }

                    CalculateKeyNumbers24H();
                }

                lock (_sync5D)
                {
                    var newest = _history5D.Keys.LastOrDefault();

                    if (newest == default(DateTime) || // empty
                        indexHistory.Time - newest > TimeSpan.FromMinutes(5))
                    {
                        _chartHistory5DRepository.InsertOrReplaceAsync(indexHistory.Time, indexHistory.Value).GetAwaiter().GetResult();
                        _history5D[indexHistory.Time] = indexHistory.Value;

                        // remove old
                        foreach (var time in _history5D.Keys.ToList())
                        {
                            if (time < DateTime.UtcNow.AddDays(-5))
                            {
                                _history5D.Remove(time);
                            }
                        }

                        CalculateKeyNumbers5D();
                    }
                }

                lock (_sync30D)
                {
                    var newest = _history30D.Keys.LastOrDefault();

                    if (newest == default(DateTime) || // empty
                        indexHistory.Time - newest > TimeSpan.FromMinutes(30))
                    {
                        _chartHistory30DRepository.InsertOrReplaceAsync(indexHistory.Time, indexHistory.Value).GetAwaiter().GetResult();
                        _history30D[indexHistory.Time] = indexHistory.Value;

                        // remove old
                        foreach (var time in _history30D.Keys.ToList())
                        {
                            if (time < DateTime.UtcNow.AddDays(-30))
                            {
                                _history30D.Remove(time);
                            }
                        }

                        CalculateKeyNumbers30D();
                    }
                }
            }
            catch (Exception ex)
            {
                _log.Warning("Something went wrong in StatisticsService.", ex);
            }

            return(Task.CompletedTask);
        }