public async Task DelegateNotifyFillStatistics(string applicationName, FillStatistics fillStatistics) { if (_exchangeHubService.Clients == null) { return; } await _exchangeHubService.Clients.All.NotifyFillStatistics(applicationName, fillStatistics); }
public async Task RequestedFillStatistics(string applicationName, string symbol) { AbstractExchangePlugin abstractExchangePlugin = _exchangePluginService.PluginExchanges.FirstOrDefault(x => x.ApplicationName == applicationName); if (abstractExchangePlugin == null) { return; } Product product = new Product { ID = symbol }; FillStatistics fillStatistic = await abstractExchangePlugin.UpdateFillStatistics(product); await Clients.Caller.NotifyFillStatistics(abstractExchangePlugin.ApplicationName, fillStatistic); }
public virtual async Task <FillStatistics> UpdateFillStatistics(Product product, List <Fill> fills = null) { Product validatedProduct = Products.FirstOrDefault(p => p.ID == product.ID); if (validatedProduct == null) { return(null); } //We want to get the last price we sold //This will allow us to find out what price range to buy fills ??= await UpdateFillsAsync(validatedProduct); Accounts ??= new List <Account>(); List <MiniFill> miniFillSellAboveList = new List <MiniFill>(); List <MiniFill> miniFillBuyBelowList = new List <MiniFill>(); //Quote Currency Balance: example EUR / BTC Account selectedQuoteCurrencyAccount = Accounts.FirstOrDefault(account => account.Currency == validatedProduct.QuoteCurrency); if (selectedQuoteCurrencyAccount == null) { return(null); } //Base Currency Balance: example BTC / ETH Account selectedBaseCurrencyAccount = Accounts.FirstOrDefault(account => account.Currency == validatedProduct.BaseCurrency); if (selectedBaseCurrencyAccount == null) { return(null); } bool buyCompleted = false; bool sellCompleted = false; decimal quoteCurrencyAccumulatedBalance = 0; decimal baseCurrencyAccumulatedBalance = 0; foreach (Fill fill in fills) { //Get the final fill price decimal fillPrice; decimal fee; switch (fill.Side) { case "sell" when !sellCompleted: { //Quote currency fee EUR fee = fill.Fee.ToDecimal(); //Quote currency price EUR fillPrice = fill.Price.ToDecimal(); //Quote currency total fee EUR decimal buyBelowPrice = fillPrice - (fee / fill.Size.ToDecimal()); quoteCurrencyAccumulatedBalance += fillPrice * fill.Size.ToDecimal() + fee; if (quoteCurrencyAccumulatedBalance > selectedQuoteCurrencyAccount.Balance.ToDecimal()) { sellCompleted = true; } miniFillBuyBelowList.Add(new MiniFill { Price = buyBelowPrice, Size = fill.Size.ToDecimal() }); break; } case "buy" when !buyCompleted: { //Quote currency fee EUR fee = fill.Fee.ToDecimal(); //Quote currency price EUR fillPrice = fill.Price.ToDecimal(); //Quote currency total fee EUR decimal sellAbovePrice = (fee / fill.Size.ToDecimal()) + fillPrice; baseCurrencyAccumulatedBalance += fill.Size.ToDecimal(); if (baseCurrencyAccumulatedBalance > selectedBaseCurrencyAccount.Balance.ToDecimal()) { decimal sizeDifference = baseCurrencyAccumulatedBalance - selectedBaseCurrencyAccount.Balance.ToDecimal(); decimal fillSizeDifference = fill.Size.ToDecimal() - sizeDifference; if (fillSizeDifference <= 0) { fillSizeDifference = 1; } sellAbovePrice = (fee / fillSizeDifference) + fillPrice; buyCompleted = true; } miniFillSellAboveList.Add(new MiniFill { Price = sellAbovePrice, Size = fill.Size.ToDecimal() }); break; } } } FillStatistics fillStatistics = new FillStatistics { BaseCurrency = selectedBaseCurrencyAccount.Currency, MiniFillBuyBelowList = miniFillBuyBelowList, MiniFillSellAboveList = miniFillSellAboveList, ProductID = validatedProduct.ID, QuoteCurrency = selectedQuoteCurrencyAccount.Currency }; FillStatistics ??= new Dictionary <string, FillStatistics>(); if (!FillStatistics.ContainsKey(validatedProduct.ID)) { FillStatistics.Add(validatedProduct.ID, fillStatistics); } else { FillStatistics[validatedProduct.ID] = fillStatistics; } NotifyFillStatistics?.Invoke(ApplicationName, fillStatistics); return(fillStatistics); }