public async Task <AccountInfo> GetAccountInfoAsync(User user, CancellationToken cancellationToken) { if (user == null) { throw new ArgumentNullException(nameof(user)); } var options = new KucoinClientOptions { ApiCredentials = new KucoinApiCredentials(user.ApiKey, user.ApiSecret, user.ApiPassPhrase) }; var accountInfo = new AccountInfo { User = user, Exchange = Exchange.Kucoin }; using (var kucoinClient = new KucoinClient(options)) { var accounts = await kucoinClient.GetAccountsAsync(accountType : KucoinAccountType.Trade).ConfigureAwait(false); foreach (var balance in accounts.Data) { accountInfo.Balances.Add(new AccountBalance { Asset = balance.Currency, Free = balance.Available, Locked = balance.Holds }); } } return(accountInfo); }
public async Task <IEnumerable <Candlestick> > GetCandlesticksAsync(string symbol, CandlestickInterval interval, DateTime startTime, DateTime endTime, int limit = 0, CancellationToken token = default) { var candlestickInterval = interval.ToKucoinCandlestickInterval(); using var kucoinClient = new KucoinClient(); var result = await kucoinClient.GetKlinesAsync(symbol, candlestickInterval, startTime, endTime).ConfigureAwait(false); Candlestick f(KucoinKline k) { return(new Candlestick { Symbol = symbol, Exchange = Exchange.Kucoin, Interval = interval, OpenTime = k.StartTime, Open = k.Open, High = k.High, Low = k.Low, Close = k.Close, Volume = k.Volume }); }; var candlesticks = (from k in result.Data select f(k)).ToList(); return(candlesticks); }
public async Task <IEnumerable <Symbol> > GetSymbolsAsync(CancellationToken cancellationToken) { using var kucoinClient = new KucoinClient(); var result = await kucoinClient.GetSymbolsAsync().ConfigureAwait(false); var symbols = result.Data.Select(s => new Symbol { Name = $"{s.BaseCurrency}{s.QuoteCurrency}", Exchange = Exchange.Kucoin, NameDelimiter = NameDelimiter, ExchangeSymbol = s.Symbol, NotionalMinimumValue = s.QuoteMinSize, BaseAsset = new Asset { Symbol = s.BaseCurrency }, QuoteAsset = new Asset { Symbol = s.QuoteCurrency }, Price = new InclusiveRange { Increment = s.PriceIncrement, Maximum = s.QuoteMaxSize, Minimum = s.PriceIncrement }, Quantity = new InclusiveRange { Increment = s.BaseIncrement, Maximum = s.BaseMaxSize, Minimum = s.BaseIncrement }, SymbolStatistics = new SymbolStats { Symbol = s.Symbol }, OrderTypes = new[] { OrderType.Limit, OrderType.Market, OrderType.StopLoss, OrderType.StopLossLimit, OrderType.TakeProfit, OrderType.TakeProfitLimit } }).ToList(); var currencies = await kucoinClient.GetCurrenciesAsync().ConfigureAwait(false);
public async Task SubscribeStatistics(IEnumerable <string> symbols, Action <StatisticsEventArgs> callback, Action <Exception> exception, CancellationToken cancellationToken) { var kucoinSocketClient = new KucoinSocketClient(); CallResult <UpdateSubscription> result = null; try { var kucoinClient = new KucoinClient(); foreach (var symbol in symbols) { result = await kucoinSocketClient.SubscribeToSnapshotUpdatesAsync(symbol, async data => { if (cancellationToken.IsCancellationRequested) { await kucoinSocketClient.Unsubscribe(result.Data).ConfigureAwait(false); return; } try { var symbolStats = new SymbolStats { Symbol = data.Symbol, Exchange = Exchange.Kucoin, CloseTime = data.Timestamp, Volume = data.Volume, LowPrice = data.Low, HighPrice = data.High, LastPrice = data.LastPrice, PriceChange = data.ChangePrice, PriceChangePercent = data.ChangePercentage * 100 }; callback.Invoke(new StatisticsEventArgs { Statistics = new[] { symbolStats } }); } catch (Exception ex) { await kucoinSocketClient.Unsubscribe(result.Data).ConfigureAwait(false); exception.Invoke(ex); return; } }); } } catch (Exception) { if (result != null) { await kucoinSocketClient.Unsubscribe(result.Data).ConfigureAwait(false); } throw; } }
public static WebCallResult <KucoinTick> getTicketKuCoin(string symbol) { KucoinClientOptions clientOptions = new KucoinClientOptions(); clientOptions.ApiCredentials = new KucoinApiCredentials(KCAPIKEY, APISecretKucoin, KCAPIPASSPHRASE); KucoinClient kucoin = new KucoinClient(clientOptions); return(kucoin.GetTicker(symbol)); }
public static WebCallResult <KucoinFullOrderBook> getOrderBookKuCoin(string symbol, string side) { KucoinClientOptions clientOptions = new KucoinClientOptions(); clientOptions.ApiCredentials = new KucoinApiCredentials(KCAPIKEY, APISecretKucoin, KCAPIPASSPHRASE); KucoinClient kucoin = new KucoinClient(clientOptions); return(kucoin.GetOrderBook(symbol)); }
public async Task <string> CancelOrderAsync(User user, string symbol, string orderId, string newClientOrderId = null, long recWindow = 0, CancellationToken cancellationToken = default(CancellationToken)) { var options = new KucoinClientOptions { ApiCredentials = new KucoinApiCredentials(user.ApiKey, user.ApiSecret, user.ApiPassPhrase) }; var kucoinClient = new KucoinClient(options); var result = await kucoinClient.CancelOrderAsync(orderId).ConfigureAwait(false); return(result.Data.CancelledOrderIds.First()); }
public async Task <IEnumerable <Symbol> > GetSymbolsAsync(CancellationToken cancellationToken) { using (var kucoinClient = new KucoinClient()) { var result = await kucoinClient.GetSymbolsAsync().ConfigureAwait(false); var symbols = result.Data.Select(s => new Symbol { Name = $"{s.BaseCurrency}{s.QuoteCurrency}", Exchange = Exchange.Kucoin, NameDelimiter = "-", ExchangeSymbol = s.Symbol, NotionalMinimumValue = s.QuoteMinSize, BaseAsset = new Asset { Symbol = s.BaseCurrency }, QuoteAsset = new Asset { Symbol = s.QuoteCurrency }, Price = new InclusiveRange { Increment = s.PriceIncrement, Maximum = s.QuoteMaxSize, Minimum = s.PriceIncrement }, Quantity = new InclusiveRange { Increment = s.BaseIncrement, Maximum = s.BaseMaxSize, Minimum = s.BaseIncrement }, SymbolStatistics = new SymbolStats { Symbol = s.Symbol }, OrderTypes = new[] { OrderType.Limit, OrderType.Market, OrderType.StopLoss, OrderType.StopLossLimit, OrderType.TakeProfit, OrderType.TakeProfitLimit } }).ToList(); var currencies = await kucoinClient.GetCurrenciesAsync().ConfigureAwait(false); Asset f(Asset a, KucoinCurrency c) { a.Precision = c.Precision; return(a); }; (from s in symbols join c in currencies.Data on s.BaseAsset.Symbol equals c.Currency select f(s.BaseAsset, c)).ToList(); (from s in symbols join c in currencies.Data on s.QuoteAsset.Symbol equals c.Currency select f(s.QuoteAsset, c)).ToList(); return(symbols); } }
public async Task <IEnumerable <Order> > GetOpenOrdersAsync(User user, string symbol = null, long recWindow = 0, Action <Exception> exception = null, CancellationToken cancellationToken = default) { if (user == null) { throw new ArgumentNullException(nameof(user)); } var options = new KucoinClientOptions { ApiCredentials = new KucoinApiCredentials(user.ApiKey, user.ApiSecret, user.ApiPassPhrase) }; using (var kucoinClient = new KucoinClient(options)) { var results = await kucoinClient.GetOrdersAsync(null, null, null, null, null, KucoinOrderStatus.Active).ConfigureAwait(false); var orders = (from o in results.Data.Items select new Order { User = user, Symbol = o.Symbol, Exchange = Exchange.Kucoin, Id = o.Id, ClientOrderId = o.ClientOrderId, Price = o.Price, OriginalQuantity = o.Quantity, TimeInForce = o.TimeInForce.ToTradeViewTimeInForce(), Type = o.Type.ToTradeViewOrderType(), Side = o.Side.ToTradeViewOrderSide(), StopPrice = o.StopPrice, IcebergQuantity = o.VisibleIcebergSize, Time = o.CreatedAt, //Fills = o.Fills?.Select(f => new Interface.Model.Fill //{ // Price = f.Price, // Quantity = f.Quantity, // Commission = f.Commission, // CommissionAsset = f.CommissionAsset, // TradeId = f.TradeId //}) }).ToList(); return(orders); } }
public async Task <IEnumerable <Trade> > GetTradesAsync(string symbol, int limit, CancellationToken cancellationToken) { var kucoinClint = new KucoinClient(); var result = await kucoinClint.GetSymbolTradesAsync(symbol).ConfigureAwait(false); var trades = result.Data.Select(t => new Trade { Symbol = symbol, Exchange = Exchange.Kucoin, Id = t.Sequence, Price = t.Price, Quantity = t.Quantity, Time = t.Timestamp, IsBuyerMaker = t.Side == KucoinOrderSide.Sell ? true : false }).ToList(); return(trades); }
public async Task <OrderBook> GetOrderBookAsync(string symbol, int limit, CancellationToken cancellationToken) { using var kucoinClient = new KucoinClient(); var result = await kucoinClient.GetAggregatedPartialOrderBookAsync(symbol, limit).ConfigureAwait(false); var orderBook = new OrderBook { Symbol = symbol, Exchange = Exchange.Kucoin, FirstUpdateId = result.Data.Sequence, LastUpdateId = result.Data.Sequence }; orderBook.Asks = (from ask in result.Data.Asks select new OrderBookPriceLevel { Price = ask.Price, Quantity = ask.Quantity }).ToList(); orderBook.Bids = (from bid in result.Data.Bids select new OrderBookPriceLevel { Price = bid.Price, Quantity = bid.Quantity }).ToList(); return(orderBook); }
public static void SetResponse(KucoinClient client, string responseData, HttpStatusCode statusCode = HttpStatusCode.OK) { var expectedBytes = Encoding.UTF8.GetBytes(responseData); var responseStream = new MemoryStream(); responseStream.Write(expectedBytes, 0, expectedBytes.Length); responseStream.Seek(0, SeekOrigin.Begin); var response = new Mock <IResponse>(); response.Setup(c => c.StatusCode).Returns(statusCode); response.Setup(c => c.IsSuccessStatusCode).Returns(statusCode == HttpStatusCode.OK); response.Setup(c => c.GetResponseStreamAsync()).Returns(Task.FromResult((Stream)responseStream)); var request = new Mock <IRequest>(); request.Setup(c => c.Uri).Returns(new Uri("http://www.test.com")); request.Setup(c => c.GetResponseAsync(It.IsAny <CancellationToken>())).Returns(Task.FromResult(response.Object)); var factory = Mock.Get(client.Spot.RequestFactory); factory.Setup(c => c.Create(It.IsAny <HttpMethod>(), It.IsAny <string>(), It.IsAny <int>())) .Returns(request.Object); }
public async Task <Order> PlaceOrder(User user, ClientOrder clientOrder, long recWindow = 0, CancellationToken cancellationToken = default) { if (user == null) { throw new ArgumentNullException(nameof(user)); } if (clientOrder == null) { throw new ArgumentNullException(nameof(clientOrder)); } var options = new KucoinClientOptions { ApiCredentials = new KucoinApiCredentials(user.ApiKey, user.ApiSecret, user.ApiPassPhrase) }; using (var kucoinClient = new KucoinClient(options)) { var placeOrderResult = await kucoinClient.PlaceOrderAsync( clientOrder.Symbol, clientOrder.Side.ToKucoinOrderSide(), clientOrder.Type.ToKucoinNewOrderType(), clientOrder.Price, clientOrder.Quantity, null, clientOrder.TimeInForce.ToKucoinTimeInForce(), null, null, null, null, null, null, null, clientOrder.StopPrice, null, null ).ConfigureAwait(false); if (!placeOrderResult.Success) { throw new Exception($"Error Code : {placeOrderResult.Error.Code} Message : {placeOrderResult.Error.Message}"); } var orderResult = await kucoinClient.GetOrderAsync(placeOrderResult.Data.OrderId).ConfigureAwait(false); if (orderResult.Success) { var order = new Order { User = user, Exchange = Exchange.Kucoin, Symbol = orderResult.Data.Symbol, //Id = orderResult.Data.Id, ClientOrderId = orderResult.Data.ClientOrderId, Price = orderResult.Data.Price, OriginalQuantity = orderResult.Data.Quantity, TimeInForce = orderResult.Data.TimeInForce.ToTradeViewTimeInForce(), Type = orderResult.Data.Type.ToTradeViewOrderType(), Side = orderResult.Data.Side.ToTradeViewOrderSide(), StopPrice = orderResult.Data.StopPrice, IcebergQuantity = orderResult.Data.VisibleIcebergSize, Time = orderResult.Data.CreatedAt }; return(order); } else { throw new Exception($"Error Code : {orderResult.Error.Code} Message : {orderResult.Error.Message}"); } } }
/// <inheritdoc /> protected override async Task <CallResult <UpdateSubscription> > SubscribeAsync <T>(string url, object?request, string?identifier, bool authenticated, Action <DataEvent <T> > dataHandler) { SocketConnection? socketConnection; SocketSubscription subscription; var released = false; await semaphoreSlim.WaitAsync().ConfigureAwait(false); try { socketConnection = GetSocketConnection(url, authenticated); if (socketConnection == null) { KucoinToken token; var clientOptions = KucoinClient.DefaultOptions.Copy(); KucoinApiCredentials?thisCredentials = (KucoinApiCredentials?)authProvider?.Credentials; if (thisCredentials != null) { clientOptions.FuturesApiCredentials = new KucoinApiCredentials(thisCredentials.Key !.GetString(), thisCredentials.Secret !.GetString(), thisCredentials.PassPhrase.GetString()); } // Create new socket IWebsocket socket; if (SocketFactory is WebsocketFactory) { using (var restClient = new KucoinClient(clientOptions)) { WebCallResult <KucoinToken> tokenResult = await((KucoinClientFutures)restClient.Futures).GetWebsocketToken(authenticated).ConfigureAwait(false); if (!tokenResult) { return(new CallResult <UpdateSubscription>(null, tokenResult.Error)); } token = tokenResult.Data; } socket = CreateSocket(token.Servers.First().Endpoint + "?token=" + token.Token); } else { socket = CreateSocket("test"); } socketConnection = new SocketConnection(this, socket); foreach (var kvp in genericHandlers) { socketConnection.AddSubscription(SocketSubscription.CreateForIdentifier(NextId(), kvp.Key, false, kvp.Value)); } } subscription = AddSubscription(request, identifier, true, socketConnection, dataHandler); if (SocketCombineTarget == 1) { // Can release early when only a single sub per connection semaphoreSlim.Release(); released = true; } var connectResult = await ConnectIfNeededAsync(socketConnection, authenticated).ConfigureAwait(false); if (!connectResult) { return(new CallResult <UpdateSubscription>(null, connectResult.Error)); } } finally { //When the task is ready, release the semaphore. It is vital to ALWAYS release the semaphore when we are ready, or else we will end up with a Semaphore that is forever locked. //This is why it is important to do the Release within a try...finally clause; program execution may crash or take a different path, this way you are guaranteed execution if (!released) { semaphoreSlim.Release(); } } if (request != null) { var subResult = await SubscribeAndWaitAsync(socketConnection, request, subscription).ConfigureAwait(false); if (!subResult) { await socketConnection.CloseAsync(subscription).ConfigureAwait(false); return(new CallResult <UpdateSubscription>(null, subResult.Error)); } } else { subscription.Confirmed = true; } socketConnection.ShouldReconnect = true; return(new CallResult <UpdateSubscription>(new UpdateSubscription(socketConnection, subscription), null)); }