Beispiel #1
0
        /// <summary>
        /// Get candlesticks for a symbol. Candlesticks/K-Lines are uniquely identified by their open time.
        /// If startTime and endTime are not sent, the most recent candlesticks are returned.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="interval"></param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetCandlesticksAsync(this IKucoinHttpClient client, string symbol, CandlestickInterval interval, int limit = default, long startTime = default, long endTime = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            var request = new KucoinHttpRequest("/api/v1/klines");

            request.AddParameter("symbol", symbol.FormatSymbol());
            request.AddParameter("interval", interval.AsString());

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            if (startTime > 0)
            {
                request.AddParameter("startTime", startTime);
            }

            if (endTime > 0)
            {
                request.AddParameter("endTime", endTime);
            }

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
        /// <summary>
        /// Get candlesticks for a symbol. Candlesticks/K-Lines are uniquely identified by their open time.
        /// If startTime and endTime are not sent, the most recent candlesticks are returned.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="interval"></param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Task <string> GetCandlesticksAsync(this IBinanceHttpClient client, string symbol, CandlestickInterval interval, int limit = default, long startTime = default, long endTime = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            var request = new BinanceHttpRequest("/api/v1/klines", 2);

            request.AddParameter("symbol", symbol.FormatSymbol());
            request.AddParameter("interval", interval.AsString());

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            if (startTime > 0)
            {
                request.AddParameter("startTime", startTime);
            }

            if (endTime > 0)
            {
                request.AddParameter("endTime", endTime);
            }

            return(client.GetAsync(request, token));
        }
Beispiel #3
0
        public virtual void Subscribe(string symbol, CandlestickInterval interval, Action <CandlestickEventArgs> callback)
        {
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            Symbol = symbol.FormatSymbol();

            SubscribeTo($"{Symbol.ToLowerInvariant()}@kline_{interval.AsString()}", callback);
        }
        private async Task SubscribeToCandlestick(string symbol, CandlestickInterval interval)
        {
            var key = GetKey(symbol, interval);

            if (_candlestickSubscribers.ContainsKey(key))
            {
                return;
            }

            try
            {
                var subscriber = new CandlestickSubscriber()
                {
                    Symbol   = symbol,
                    Interval = interval
                };

                try
                {
                    await _candlestickSemaphore.WaitAsync();

                    if (_candlestickSubscribers.ContainsKey(key))
                    {
                        return;
                    }

                    _log.LogInformation($"Subscribe to candlestick {symbol} {interval.AsString()}");

                    _candlestickSubscribers[key] = subscriber;

                    subscriber.TokenSource = new CancellationTokenSource();
                    subscriber.CandlestickWebSocketClient = _serviceProvider.GetService <ICandlestickWebSocketClient>();
                    subscriber.SubscribeTask = subscriber.CandlestickWebSocketClient.SubscribeAsync(symbol, interval, _onCandlestickUpdate, subscriber.TokenSource.Token);

                    CandlestickDisconnectionTimerInitialize(subscriber);
                }
                finally
                {
                    _candlestickSemaphore.Release();
                }

                await subscriber.SubscribeTask;

                RemoveSubscriber(symbol, interval);
            }
            catch (Exception)
            {
                OnCandlesticDisconnect(symbol, interval, true);

                RemoveSubscriber(symbol, interval);
            }
        }
Beispiel #5
0
        public virtual Task SubscribeAsync(Symbol symbol, CandlestickInterval interval, Action <CandlestickEventArgs> callback, CancellationToken token)
        {
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (!token.CanBeCanceled)
            {
                throw new ArgumentException("Token must be capable of being in the canceled state.", nameof(token));
            }

            token.ThrowIfCancellationRequested();

            return(SubscribeToAsync($"{symbol.ToLower()}@kline_{interval.AsString()}", symbol, callback, token));
        }
        private void OnCandlesticDisconnect(string symbol, CandlestickInterval interval, bool error = false)
        {
            var key = GetKey(symbol, interval);

            if (_candlestickSubscribers.ContainsKey(key))
            {
                var subscriber = _candlestickSubscribers[key];
                subscriber.TokenSource?.Cancel();
            }

            var logMessage = error ? "Error with candlestick websocket" : "Candlestick websocket disconnected";

            _log.LogInformation($"{logMessage} {symbol} {interval.AsString()}. Cache will be cleared");

            _onCandlestickErrorOrDisconnect(symbol, interval);
        }
        /// <summary>
        /// Get candlesticks for a symbol. Candlesticks/K-Lines are uniquely identified by their open time.
        /// If startTime and endTime are not sent, the most recent candlesticks are returned.
        /// </summary>
        /// <param name="client"></param>
        /// <param name="symbol"></param>
        /// <param name="interval"></param>
        /// <param name="limit">Default 500; max 500.</param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static async Task <string> GetCandlesticksAsync(this IBinanceHttpClient client, string symbol, CandlestickInterval interval, int limit = default, DateTime startTime = default, DateTime endTime = default, CancellationToken token = default)
        {
            Throw.IfNull(client, nameof(client));
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (client.RateLimiter != null)
            {
                await client.RateLimiter.DelayAsync(token : token)
                .ConfigureAwait(false);
            }

            var request = new BinanceHttpRequest("/api/v1/klines");

            request.AddParameter("symbol", symbol.FormatSymbol());
            request.AddParameter("interval", interval.AsString());

            if (limit > 0)
            {
                request.AddParameter("limit", limit);
            }

            if (startTime != default)
            {
                if (startTime.Kind != DateTimeKind.Utc)
                {
                    throw new ArgumentException("Date/Time must be UTC.", nameof(startTime));
                }

                request.AddParameter("startTime", startTime.ToTimestamp());
            }

            // ReSharper disable once InvertIf
            if (endTime != default)
            {
                if (endTime.Kind != DateTimeKind.Utc)
                {
                    throw new ArgumentException("Date/Time must be UTC.", nameof(endTime));
                }

                request.AddParameter("endTime", endTime.ToTimestamp());
            }

            return(await client.GetAsync(request, token)
                   .ConfigureAwait(false));
        }
        private void RemoveSubscriber(string symbol, CandlestickInterval interval)
        {
            var key = GetKey(symbol, interval);

            if (_candlestickSubscribers.ContainsKey(key))
            {
                var subscriber = _candlestickSubscribers[key];

                subscriber.CandlestickDisconnectionTimer?.Dispose();
                subscriber.TokenSource?.Dispose();
            }

            CandlestickSubscriber removedSubscriber = null;

            if (_candlestickSubscribers.TryRemove(key, out removedSubscriber))
            {
                _log.LogInformation($"subscriber removed for {symbol} {interval.AsString()}");
            }
        }
        public virtual Task SubscribeAsync(string symbol, CandlestickInterval interval, Action <CandlestickEventArgs> callback, CancellationToken token)
        {
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            if (!token.CanBeCanceled)
            {
                throw new ArgumentException("Token must be capable of being in the canceled state.", nameof(token));
            }

            token.ThrowIfCancellationRequested();

            Symbol = symbol.FormatSymbol();

            if (IsSubscribed)
            {
                throw new InvalidOperationException($"{nameof(CandlestickWebSocketClient)} is already subscribed to symbol: \"{symbol}\"");
            }

            return(SubscribeToAsync($"{Symbol.ToLower()}@kline_{interval.AsString()}", callback, token));
        }
Beispiel #10
0
        public async Task Candlestick(string symbol, CandlestickInterval interval,
                                      Action <CandlestickEventArgs> onUpdate,
                                      Action <string, CandlestickInterval> onError)
        {
            if (_candlestickSubscribers == null || !_candlestickSubscribers.ContainsKey($"{symbol}{interval.AsString()}"))
            {
                _onCandlestickUpdate = onUpdate ?? throw new ArgumentException(nameof(onUpdate));
                _onCandlestickError  = onError ?? throw new ArgumentException(nameof(onError));

                if (_candlestickSubscribers == null)
                {
                    _candlestickSubscribers = new ConcurrentDictionary <string, CandlestickSubscriber>();
                }

                await SubscribeToCandlestick(symbol, interval);
            }
        }
Beispiel #11
0
 public void SetCandlestick(string symbol, CandlestickInterval interval, ImmutableList <Candlestick> candlesticks)
 {
     _memoryCache.Set($"{symbol}{SYMBOL_CANDLESTICK}{interval.AsString()}", candlesticks, TimeSpan.FromMinutes(CACHE_TIME_IN_MINUTES));
 }
Beispiel #12
0
        public virtual ICandlestickClient Unsubscribe(string symbol, CandlestickInterval interval, Action <CandlestickEventArgs> callback)
        {
            Throw.IfNullOrWhiteSpace(symbol, nameof(symbol));

            symbol = symbol.FormatSymbol();

            Logger?.LogDebug($"{nameof(CandlestickClient)}.{nameof(Unsubscribe)}: \"{symbol}\" \"{interval.AsString()}\" (callback: {(callback == null ? "no" : "yes")}).  [thread: {Thread.CurrentThread.ManagedThreadId}]");

            UnsubscribeStream(GetStreamName(symbol, interval), callback);

            return(this);
        }
Beispiel #13
0
        private async Task SubscribeToCandlestick(string symbol, CandlestickInterval interval, bool reConnect = false)
        {
            _log.LogInformation($"Subscribe to candlestick {symbol} {interval.AsString()}");

            var key = GetKey(symbol, interval);

            if (_candlestickSubscribers.ContainsKey(key) && !reConnect)
            {
                return;
            }

            try
            {
                CandlestickSubscriber subscriber = _candlestickSubscribers.ContainsKey(key) ? _candlestickSubscribers[key] : null;

                if (subscriber != null)
                {
                    subscriber.TokenSource.Cancel();
                    subscriber.TokenSource.Dispose();
                }
                else
                {
                    subscriber = new CandlestickSubscriber()
                    {
                        Symbol   = symbol,
                        Interval = interval
                    };

                    CandlestickReConnectionTimerInitialize(subscriber);

                    _candlestickSubscribers[key] = subscriber;
                }

                subscriber.TokenSource = new CancellationTokenSource();
                subscriber.CandlestickWebSocketClient = _serviceProvider.GetService <ICandlestickWebSocketClient>();
                subscriber.SubscribeTask = subscriber.CandlestickWebSocketClient.SubscribeAsync(symbol, interval, _onCandlestickUpdate, subscriber.TokenSource.Token);

                await subscriber.SubscribeTask;
            }
            catch (Exception ex)
            {
                if (_candlestickSubscribers.ContainsKey(key))
                {
                    var subscriber = _candlestickSubscribers[key];

                    subscriber.CandlestickReConnectionTimer?.Dispose();
                    subscriber.TokenSource?.Dispose();

                    CandlestickSubscriber removedSubscriber = null;

                    if (_candlestickSubscribers.TryRemove(key, out removedSubscriber))
                    {
                        _log.LogInformation($"subscriber removed for {symbol} {interval.AsString()}");
                    }
                }

                _log.LogError($"Error with candlestick websocket {ex.Message}", ex);

                _onCandlestickError?.Invoke(symbol, interval);
            }
        }
Beispiel #14
0
        /// <summary>
        /// Convert symbol and <see cref="CandlestickInterval"/> to stream name.
        /// </summary>
        /// <param name="symbol"></param>
        /// <param name="interval"></param>
        /// <returns></returns>
        public static string GetStreamName(string symbol, CandlestickInterval interval)
        {
            Throw.IfNullOrEmpty(symbol, nameof(symbol));

            return($"{symbol.ToLowerInvariant()}@kline_{interval.AsString()}");
        }
Beispiel #15
0
 private static string GetStreamName(string symbol, CandlestickInterval interval)
 => $"{symbol.ToLowerInvariant()}@kline_{interval.AsString()}";
Beispiel #16
0
 private static string GetKey(string symbol, CandlestickInterval interval)
 {
     return($"{symbol}{interval.AsString()}");
 }
Beispiel #17
0
 public void ClearCandlestick(string symbol, CandlestickInterval interval)
 {
     _memoryCache.Remove($"{symbol}{SYMBOL_CANDLESTICK}{interval.AsString()}");
 }
Beispiel #18
0
 public ImmutableList <Candlestick> GetCandlesticks(string symbol, CandlestickInterval interval)
 {
     return(_memoryCache.Get <ImmutableList <Candlestick> >($"{symbol}{SYMBOL_CANDLESTICK}{interval.AsString()}"));
 }