@page "/Trackers" @using System.Collections.Concurrent @using System.Timers @using Binance.Net.Interfaces @using BingX.Net.Interfaces @using Bitfinex.Net.Interfaces @using Bitget.Net.Interfaces; @using BitMart.Net.Interfaces; @using Bybit.Net.Interfaces @using CoinEx.Net.Interfaces @using Coinbase.Net.Interfaces @using CryptoExchange.Net.Interfaces @using CryptoCom.Net.Interfaces @using CryptoExchange.Net.SharedApis @using CryptoExchange.Net.Trackers.Trades @using GateIo.Net.Interfaces @using HTX.Net.Interfaces @using HyperLiquid.Net.Interfaces @using Kraken.Net.Interfaces @using Kucoin.Net.Clients @using Kucoin.Net.Interfaces @using Mexc.Net.Interfaces @using OKX.Net.Interfaces; @using WhiteBit.Net.Interfaces @inject IBinanceTrackerFactory binanceFactory @inject IBingXTrackerFactory bingXFactory @inject IBitfinexTrackerFactory bitfinexFactory @inject IBitgetTrackerFactory bitgetFactory @inject IBitMartTrackerFactory bitmartFactory @inject IBybitTrackerFactory bybitFactory @inject ICoinbaseTrackerFactory coinbaseFactory @inject ICoinExTrackerFactory coinExFactory @inject ICryptoComTrackerFactory cryptocomFactory @inject IGateIoTrackerFactory gateioFactory @inject IHTXTrackerFactory htxFactory @inject IHyperLiquidTrackerFactory hyperLiquidFactory @inject IKrakenTrackerFactory krakenFactory @inject IKucoinTrackerFactory kucoinFactory @inject IMexcTrackerFactory mexcFactory @inject IOKXTrackerFactory okxFactory @inject IWhiteBitTrackerFactory whitebitFactory @implements IDisposable

ETH-BTC trade Trackers, live updates:

@foreach (var tracker in _trackers.OrderBy(p => p.Exchange)) {

@tracker.Exchange

@foreach(var line in GetInfo(tracker)) {
@line
}
}
@code{ private List _trackers = new List(); private Timer _timer; protected override async Task OnInitializedAsync() { var usdtSymbol = new SharedSymbol(TradingMode.Spot, "BTC", "USDT"); _trackers = new List { { binanceFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { bingXFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { bitfinexFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { bitgetFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { bitmartFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { bybitFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { coinbaseFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { coinExFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { cryptocomFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { gateioFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { htxFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, // HyperLiquid doesn't support spot pair, but does have a futures BTC/USDC pair { hyperLiquidFactory.CreateTradeTracker(new SharedSymbol(TradingMode.PerpetualLinear, "BTC", "USDC"), period: TimeSpan.FromMinutes(5)) }, { krakenFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { kucoinFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { mexcFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { okxFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, { whitebitFactory.CreateTradeTracker(usdtSymbol, period: TimeSpan.FromMinutes(5)) }, }; await Task.WhenAll(_trackers.Select(b => b.StartAsync())); // Use a manual update timer so the page isn't refreshed too often _timer = new Timer(500); _timer.Start(); _timer.Elapsed += (o, e) => InvokeAsync(StateHasChanged); } private string[] GetInfo(ITradeTracker tracker) { var secondLastMinute = tracker.GetStats(DateTime.UtcNow.AddMinutes(-2), DateTime.UtcNow.AddMinutes(-1)); var lastMinute = tracker.GetStats(DateTime.UtcNow.AddMinutes(-1)); var compare = lastMinute.CompareTo(secondLastMinute); return [ $"{tracker.SymbolName} | {tracker.Status} - Synced from {tracker.SyncedFrom}", $"Total trades: {tracker.Count}", $"Trades last minute: {lastMinute.TradeCount}, minute before: {secondLastMinute.TradeCount}", $"Average weighted price: {lastMinute.VolumeWeightedAveragePrice}, minute before: {secondLastMinute.VolumeWeightedAveragePrice}, dif: {compare.VolumeWeightedAveragePriceDif.PercentageDifference}%" ]; } public void Dispose() { _timer.Stop(); _timer.Dispose(); foreach (var tracker in _trackers.Where(b => b.Status != CryptoExchange.Net.Objects.SyncStatus.Disconnected)) // It's not necessary to wait for this _ = tracker.StopAsync(); } }