Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Very rare data coming from futures kline and ticker channel #1144

Open
UtkuX opened this issue Sep 5, 2022 · 1 comment
Open

Very rare data coming from futures kline and ticker channel #1144

UtkuX opened this issue Sep 5, 2022 · 1 comment

Comments

@UtkuX
Copy link

UtkuX commented Sep 5, 2022

Hello, I'm trying to get data from sockets. While receiving data from the aggTrade channel without any problems, data from other channels is very rare. I'm not very good at C#, is there a problem with my code or the socket itself? I would really appreciate if you can help.

using System.Collections.Concurrent;
using Binance.Net.Clients;
using Binance.Net.Enums;
using Binance.Net.Interfaces;
using Binance.Net.Objects.Models.Spot.Socket;
using CryptoExchange.Net.Sockets;

namespace ConsoleApp1;

public class BinanceCoins
{
    public ConcurrentDictionary<string, ConcurrentDictionary<DateTime,KlineDataContainer>> KlineDictionary { get; }
    public ConcurrentDictionary<string, TradeDataContainer> TickerDictionary { get; }
    public ConcurrentDictionary<string, TickerDataContainer> DictVolume { get; }

    private BinanceSocketClient _socketClient;
    private List<string> _symbols;
    

    public BinanceCoins(List<string> symbols)
    {
        _socketClient = new BinanceSocketClient();
        _symbols = symbols;
        KlineDictionary = new ConcurrentDictionary<string, ConcurrentDictionary<DateTime,KlineDataContainer>>();
        TickerDictionary = new ConcurrentDictionary<string, TradeDataContainer>();
        DictVolume = new ConcurrentDictionary<string, TickerDataContainer>();
    }

    public async Task<bool> StartAsync()
    {
        var klineSubscription = await _socketClient.UsdFuturesStreams.SubscribeToKlineUpdatesAsync(_symbols, KlineInterval.OneMinute, ProcessKlineUpdate);
        if(!klineSubscription.Success)
        {
            Console.WriteLine("Failed to subscribe klines: " + klineSubscription.Error);
            return false;
        }
        var tickerSubscription = await _socketClient.UsdFuturesStreams.SubscribeToTickerUpdatesAsync(_symbols, ProcessTickerUpdate);
        if (!tickerSubscription.Success)
        {
            Console.WriteLine("Failed to subscribe trades: " + tickerSubscription.Error);
            return false;
        }
            
        var tradeSubscription = await _socketClient.UsdFuturesStreams.SubscribeToAggregatedTradeUpdatesAsync(_symbols, ProcessTradeUpdate);
        if (tradeSubscription.Success) return true;
        Console.WriteLine("Failed to subscribe trades: " + tradeSubscription.Error);
        
        await klineSubscription.Data.CloseAsync();
        return false;

    }

    private void ProcessTickerUpdate(DataEvent<IBinanceTick> dataEvent)
    {
        if (DictVolume.TryGetValue(dataEvent.Data.Symbol, out _))
        {
            DictVolume[dataEvent.Data.Symbol] = new TickerDataContainer
            {
                VolumeQ = dataEvent.Data.QuoteVolume
            };
        }
        else
        {
            DictVolume.TryAdd(dataEvent.Data.Symbol, new TickerDataContainer
            {
                VolumeQ = dataEvent.Data.QuoteVolume
            });
        }
    }
    private void ProcessKlineUpdate(DataEvent<IBinanceStreamKlineData> dataEvent)
    {
        if (KlineDictionary.TryGetValue(dataEvent.Data.Symbol, out var existingItem))
        {
            existingItem[dataEvent.Data.Data.OpenTime] = new KlineDataContainer
            {
                SecondTime = dataEvent.Timestamp.Second,
                OpenPrice = dataEvent.Data.Data.OpenPrice,
                HighPrice = dataEvent.Data.Data.HighPrice,
                LowPrice = dataEvent.Data.Data.LowPrice,
                ClosePrice = dataEvent.Data.Data.ClosePrice,
                IsClosed = dataEvent.Data.Data.Final
            };
        }
        else
        {
            KlineDictionary.TryAdd(dataEvent.Data.Symbol, new ConcurrentDictionary<DateTime, KlineDataContainer>());
            {
                KlineDictionary[dataEvent.Data.Symbol].TryAdd(dataEvent.Data.Data.OpenTime, new KlineDataContainer
                {
                    SecondTime = dataEvent.Timestamp.Second,
                    OpenPrice = dataEvent.Data.Data.OpenPrice,
                    HighPrice = dataEvent.Data.Data.HighPrice,
                    LowPrice = dataEvent.Data.Data.LowPrice,
                    ClosePrice = dataEvent.Data.Data.ClosePrice,
                    IsClosed = dataEvent.Data.Data.Final
                });
            }
        }

        Task.Run(() =>
        {
            var kline = KlineDictionary[dataEvent.Data.Symbol];
            var klineKeysMin = new List<DateTime>(kline.Keys);
            if (klineKeysMin.Count <= 4) return;
            if (!kline.ContainsKey(klineKeysMin.Min())) return;
            if (kline[klineKeysMin.Min()].IsClosed)
            {
                kline.TryRemove(klineKeysMin.Min(), out _);
            }
        });
    }

    private void ProcessTradeUpdate(DataEvent<BinanceStreamAggregatedTrade> dataEvent)
    {
        if (TickerDictionary.TryGetValue(dataEvent.Data.Symbol, out _))
        {
            TickerDictionary[dataEvent.Data.Symbol] = new TradeDataContainer
            {
                LastPrice = dataEvent.Data.Price,
                Volume = dataEvent.Data.Quantity
            };
        }
        else
        {
            TickerDictionary.TryAdd(dataEvent.Data.Symbol, new TradeDataContainer
            {
                LastPrice = dataEvent.Data.Price,
                Volume = dataEvent.Data.Quantity
            });
        }
    }
}

public class KlineDataContainer
{
    public int SecondTime { get; init; }
    public decimal HighPrice { get; init; }
    public decimal OpenPrice { get; init; }
    public decimal LowPrice { get; init; }
    public decimal ClosePrice { get; init; }
    public bool IsClosed { get; init; }
}
public class TradeDataContainer
{
    public decimal LastPrice { get; init; }
    public decimal Volume { get; init; }
}

public class TickerDataContainer
{
    public decimal VolumeQ { get; init; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
@UtkuX and others