Example #1
0
        public override bool InitIndicatorsAsync()
        {
            string  directoryName   = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
            string  env             = TestMode ? "test" : "live";
            string  coinbaseRSIFile = Path.Combine(directoryName, $"data\\coinbase_{env}");
            Product product         = Products.FirstOrDefault(x => x.BaseCurrency == "BTC" && x.QuoteCurrency == "EUR");
            RelativeStrengthIndex relativeStrengthIndex = new RelativeStrengthIndex(coinbaseRSIFile, product);

            if (product != null)
            {
                relativeStrengthIndex.TechnicalIndicatorInformationBroadcast +=
                    delegate(Dictionary <string, string> input)
                {
                    TechnicalIndicatorInformationBroadcast?.Invoke(ApplicationName, input);
                };
                relativeStrengthIndex.ProcessLogBroadcast += delegate(MessageType messageType, string message)
                {
                    ProcessLogBroadcast?.Invoke(ApplicationName, messageType, message);
                };
                relativeStrengthIndex.UpdateProductHistoricCandles += UpdateProductHistoricCandlesAsync;
                relativeStrengthIndex.EnableRelativeStrengthIndexUpdater();
                return(true);
            }

            return(false);
        }
Example #2
0
        public void Load()
        {
            string json = null;

            try
            {
                if (string.IsNullOrEmpty(FileName))
                {
                    return;
                }
                if (!File.Exists(FileName))
                {
                    return;
                }
                json = File.ReadAllText(FileName);
                CoinbaseSettings coinbaseSettings = JsonSerializer.Deserialize <CoinbaseSettings>(json);
                if (coinbaseSettings == null)
                {
                    return;
                }
                coinbaseSettings.Accounts      = Accounts;
                coinbaseSettings.CurrentPrices = CurrentPrices;
                coinbaseSettings.Tickers       = Tickers;
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: Load\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }
        }
Example #3
0
        public virtual async Task ConnectAsync(string uriString)
        {
            try
            {
                await _ioConnectionSemaphoreSlim.WaitAsync();

                if (ClientWebSocket == null)
                {
                    return;
                }
                if (ClientWebSocket.State != WebSocketState.Open)
                {
                    await ClientWebSocket.ConnectAsync(new Uri(uriString), CancellationToken.None);
                }
            }
            catch (Exception ex)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: ConnectAsync\r\nException Stack Trace: {ex.StackTrace}");
            }
            finally
            {
                _ioConnectionSemaphoreSlim.Release();
            }
        }
        public async Task <List <HistoricRate> > UpdateProductHistoricCandlesAsync(Product product, DateTime startingDateTime, DateTime endingDateTime,
                                                                                   int granularity = 86400)
        {
            try
            {
                ProcessLogBroadcast?.Invoke(MessageType.General, $"[Binance] Updating Product Historic Candles.");
                Request request = new Request(_connectionAdapter.Authentication.EndpointUrl, "GET", $"/api/v1/klines?")
                {
                    RequestQuery =
                        $"symbol={product.ID.ToUpper()}&interval=5m&startTime={startingDateTime.GenerateDateTimeOffsetToUnixTimeMilliseconds()}&endTime={endingDateTime.GenerateDateTimeOffsetToUnixTimeMilliseconds()}"
                };
                string json = await _connectionAdapter.RequestUnsignedAsync(request);

                ProcessLogBroadcast?.Invoke(MessageType.JsonOutput, $"UpdateProductOrderBookAsync JSON:\r\n{json}");
                //check if we do not have any error messages
                ArrayList[] arrayListOfHistory = JsonSerializer.Deserialize <ArrayList[]>(json);
                HistoricRates = arrayListOfHistory.ToHistoricCandleList();
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: UpdateProductHistoricCandlesAsync\r\nException Stack Trace: {e.StackTrace}");
            }
            return(HistoricRates);
        }
        public async Task <BinanceOrder> BinanceCancelOrdersAsync(BinanceOrder binanceOrder)
        {
            try
            {
                ProcessLogBroadcast?.Invoke(MessageType.General, $"Cancelling order.");
                ServerTime serverTime = await UpdateTimeServerAsync();

                Request request = new Request(_connectionAdapter.Authentication.EndpointUrl,
                                              "DELETE",
                                              $"/api/v3/order?")
                {
                    RequestQuery =
                        $"symbol={binanceOrder.Symbol}&orderId={binanceOrder.ID}&timestamp={serverTime.ServerTimeLong}"
                };
                string json = await _connectionAdapter.RequestAsync(request);

                if (!string.IsNullOrEmpty(json))
                {
                    binanceOrder = JsonSerializer.Deserialize <BinanceOrder>(json);
                }
                ProcessLogBroadcast?.Invoke(MessageType.JsonOutput, $"BinanceCancelOrdersAsync JSON:\r\n{json}");
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: BinanceCancelOrdersAsync\r\nException Stack Trace: {e.StackTrace}");
            }
            return(binanceOrder);
        }
        public async Task <List <BinanceFill> > UpdateBinanceFillsAsync(Product product)
        {
            try
            {
                ProcessLogBroadcast?.Invoke(MessageType.General, $"Updating Fills Information.");
                ServerTime serverTime = await UpdateTimeServerAsync();

                Request request = new Request(_connectionAdapter.Authentication.EndpointUrl,
                                              "GET",
                                              $"/api/v3/myTrades?")
                {
                    RequestQuery =
                        $"symbol={product.ID}&recvWindow=5000&timestamp={serverTime.ServerTimeLong}&limit=10"
                };
                string json = await _connectionAdapter.RequestAsync(request);

                if (!string.IsNullOrEmpty(json))
                {
                    BinanceFill = JsonSerializer.Deserialize <List <BinanceFill> >(json);
                }
                ProcessLogBroadcast?.Invoke(MessageType.JsonOutput, $"UpdateAccountsAsync JSON:\r\n{json}");
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: UpdateFillsAsync\r\nException Stack Trace: {e.StackTrace}");
            }
            return(BinanceFill);
        }
        public async Task <BinanceOrder> BinancePostOrdersAsync(BinanceOrder order)
        {
            BinanceOrder binanceOrder = null;

            try
            {
                ProcessLogBroadcast?.Invoke(MessageType.General, $"[Binance] Post Order Information.");
                ServerTime serverTime = await UpdateTimeServerAsync();

                Request request = new Request(_connectionAdapter.Authentication.EndpointUrl, "POST",
                                              $"/api/v3/order?");
                if (order.OrderType == OrderType.Market)
                {
                    request.RequestQuery = $"timestamp={serverTime.ServerTimeLong}&symbol={order.Symbol.ToUpper()}" +
                                           $"&side={order.OrderSide.ToString().ToUpper()}" +
                                           $"&type={order.OrderType.ToString().ToUpper()}&quantity={order.OrderSize}";
                }
                else
                {
                    request.RequestQuery = $"timestamp={serverTime.ServerTimeLong}&symbol={order.Symbol.ToUpper()}" +
                                           $"&side={order.OrderSide.ToString().ToUpper()}&type={order.OrderType.ToString().ToUpper()}" +
                                           $"&quantity={order.OrderSize}&price={ order.LimitPrice}&timeInForce=GTC";
                }
                string json = await _connectionAdapter.RequestAsync(request);

                binanceOrder = JsonSerializer.Deserialize <BinanceOrder>(json);
                ProcessLogBroadcast?.Invoke(MessageType.JsonOutput, $"UpdateAccountsAsync JSON:\r\n{json}");
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: BinancePostOrdersAsync\r\nException Stack Trace: {e.StackTrace}");
            }
            return(binanceOrder);
        }
Example #8
0
        public virtual async Task <bool> WebSocketCloseAsync()
        {
            try
            {
                await _ioSemaphoreSlim.WaitAsync();

                if (ClientWebSocket == null || !IsWebSocketConnected())
                {
                    return(false);
                }
                await ClientWebSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty,
                                                       CancellationToken.None);

                ClientWebSocket = new ClientWebSocket();
                return(true);
            }
            catch (Exception ex)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: WebSocketReceiveAsync\r\nException Stack Trace: {ex.StackTrace}");
            }
            finally
            {
                _ioSemaphoreSlim.Release();
            }

            return(false);
        }
Example #9
0
        public override async Task <Statistics> TwentyFourHoursRollingStatsAsync(Product product)
        {
            string json = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                            "Updating 24 hour stats Information.");
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "GET",
                                              $"/products/{product.ID}/stats");
                json = await ConnectionAdapter.RequestAsync(request);

                if (!string.IsNullOrEmpty(json))
                {
                    Statistics statistics = JsonSerializer.Deserialize <Statistics>(json);
                    Statistics[product.ID] = statistics;
                    return(statistics);
                }
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.JsonOutput,
                                            $"TwentyFourHoursRollingStatsAsync JSON:\r\n{json}");
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: TwentyFourHoursRollingStatsAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }
            return(null);
        }
Example #10
0
        private void Save()
        {
            string json = null;

            try
            {
                lock (_ioLock)
                {
                    if (string.IsNullOrEmpty(FileName))
                    {
                        string directoryName = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                        string env           = TestMode ? "test" : "live";
                        FileName = Path.Combine(directoryName, $"data\\coinbase_{env}.json");
                        if (!File.Exists(FileName))
                        {
                            File.Create(FileName).Close();
                        }
                    }

                    CoinbaseSettings coinbaseSettings = new CoinbaseSettings();
                    coinbaseSettings.Accounts      = Accounts;
                    coinbaseSettings.CurrentPrices = CurrentPrices;
                    coinbaseSettings.Tickers       = Tickers;
                    json = JsonSerializer.Serialize(coinbaseSettings, new JsonSerializerOptions {
                        WriteIndented = true
                    });
                    File.WriteAllText(FileName, json);
                }
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: Save\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }
        }
Example #11
0
        public virtual async Task <string> WebSocketSendAsync(string message)
        {
            try
            {
                await _ioSemaphoreSlim.WaitAsync();

                if (string.IsNullOrEmpty(message))
                {
                    return(null);
                }
                byte[] requestBytes = Encoding.UTF8.GetBytes(message);
                if (!IsWebSocketConnected())
                {
                    await ClientWebSocket.ConnectAsync(Authentication.WebSocketUri, CancellationToken.None);
                }
                ArraySegment <byte> subscribeRequest = new ArraySegment <byte>(requestBytes);
                await ClientWebSocket.SendAsync(subscribeRequest, WebSocketMessageType.Text, true,
                                                CancellationToken.None);

                if (!IsWebSocketConnected())
                {
                    return(null);
                }
                ArraySegment <byte>    receiveBuffer          = new ArraySegment <byte>(new byte[512 * 512 * 5]);
                WebSocketReceiveResult webSocketReceiveResult = await ClientWebSocket.ReceiveAsync(
                    receiveBuffer,
                    CancellationToken.None);

                if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close)
                {
                    ClientWebSocket.Abort();
                    return(null);
                }

                if (webSocketReceiveResult.Count == 0 || !receiveBuffer.Any() || receiveBuffer.Array == null)
                {
                    return(null);
                }
                return(Encoding.UTF8.GetString(receiveBuffer.Array, 0, webSocketReceiveResult.Count));
            }
            catch (Exception ex)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: WebSocketSendAsync\r\nException Stack Trace: {ex.StackTrace}");
                await ClientWebSocket.ConnectAsync(Authentication.WebSocketUri, CancellationToken.None);
            }
            finally
            {
                _ioSemaphoreSlim.Release();
            }

            return(null);
        }
Example #12
0
        public async Task <List <Ticker> > UpdateTickersAsync(List <Product> products)
        {
            string json = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                            "Updating Update Tickers Information.");
                if (products == null || !products.Any())
                {
                    return(Tickers);
                }
                if (Tickers == null)
                {
                    Tickers = new List <Ticker>();
                }
                //Get price of all products
                foreach (Product product in products)
                {
                    Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "GET",
                                                  $"/products/{product.ID}/ticker");
                    json = await ConnectionAdapter.RequestAsync(request);

                    if (string.IsNullOrEmpty(json))
                    {
                        return(Tickers);
                    }
                    Ticker ticker = JsonSerializer.Deserialize <Ticker>(json);
                    Tickers?.RemoveAll(x => x.ProductID == product.ID);
                    if (ticker == null)
                    {
                        continue;
                    }
                    ticker.ProductID = product.ID;
                    Tickers.Add(ticker);
                }

                foreach (Ticker ticker in Tickers)
                {
                    if (decimal.TryParse(ticker.Price, out decimal decimalPrice))
                    {
                        CurrentPrices[ticker.ProductID] = decimalPrice;
                    }
                }
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: UpdateTickersAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(Tickers);
        }
Example #13
0
        public virtual async Task <string> RequestUnsignedAsync(IRequest request)
        {
            try
            {
                await _ioRequestSemaphoreSlim.WaitAsync();

                HttpResponseMessage response = null;
                HttpClient.DefaultRequestHeaders.Clear();
                HttpClient.DefaultRequestHeaders.Add("X-MBX-APIKEY", Authentication.ApiKey);
                switch (request.Method)
                {
                case "GET":
                    response = await HttpClient.GetAsync(
                        request.ComposeRequestUriAbsolute(Authentication.EndpointUrl));

                    break;

                case "POST":
                    response = await HttpClient.PostAsync(
                        request.ComposeRequestUriAbsolute(Authentication.EndpointUrl), new StringContent(""));

                    break;

                case "DELETE":
                    response = await HttpClient.DeleteAsync(
                        request.ComposeRequestUriAbsolute(Authentication.EndpointUrl));

                    break;

                default:
                    response = null;
                    break;
                }

                if (response == null)
                {
                    throw new Exception(
                              $"null response from RequestUnsignedAsync \r\n URI:{request.ComposeRequestUriAbsolute(Authentication.EndpointUrl)}");
                }
                return(await response.Content.ReadAsStringAsync());
            }
            catch (Exception ex)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: RequestUnsignedAsync\r\nException Stack Trace: {ex.StackTrace}");
            }
            finally
            {
                _ioRequestSemaphoreSlim.Release();
            }

            return(null);
        }
Example #14
0
        public async Task <Order> PostOrdersAsync(Order order)
        {
            string json        = null;
            Order  outputOrder = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General, "Updating Post Order Information.");
                object data;
                if (order.Type == OrderType.Market.GetStringValue() || string.IsNullOrEmpty(order.Price))
                {
                    data = new
                    {
                        size       = order.Size,
                        side       = order.Side,
                        type       = OrderType.Market.GetStringValue(),
                        product_id = order.ProductID,
                        stp        = order.SelfTradePreventionType
                    }
                }
                ;
                else
                {
                    data = new
                    {
                        size       = order.Size,
                        price      = order.Price,
                        side       = order.Side,
                        type       = OrderType.Limit.GetStringValue(),
                        product_id = order.ProductID,
                        stp        = order.SelfTradePreventionType
                    }
                };
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "POST", "/orders")
                {
                    RequestBody = JsonSerializer.Serialize(data)
                };
                json = await ConnectionAdapter.RequestAsync(request);

                outputOrder = JsonSerializer.Deserialize <Order>(json);
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: PostOrdersAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(outputOrder);
        }
        public async Task <ExchangeInfo> UpdateExchangeInfoAsync()
        {
            try
            {
                Request request = new Request(_connectionAdapter.Authentication.EndpointUrl, "GET",
                                              $"/api/v1/exchangeInfo");
                string json = await _connectionAdapter.RequestUnsignedAsync(request);

                ExchangeInfo = JsonSerializer.Deserialize <ExchangeInfo>(json);
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: UpdateExchangeInfoAsync\r\nException Stack Trace: {e.StackTrace}");
            }
            return(ExchangeInfo);
        }
Example #16
0
        public virtual async Task <bool> CloseFeed()
        {
            bool isClosed = false;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General, "Closing Feed Subscription.");
                isClosed = await ConnectionAdapter?.WebSocketCloseAsync();
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: CloseFeed\r\nException Stack Trace: {e.StackTrace}");
            }

            return(isClosed);
        }
Example #17
0
        public async Task <List <Account> > UpdateAccountsAsync(string accountId = "")
        {
            string json = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General, "Updating Account Information.");
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "GET",
                                              $"/accounts/{accountId}");
                json = await ConnectionAdapter.RequestAsync(request);

                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.JsonOutput,
                                            $"UpdateAccountsAsync JSON:\r\n{json}");
                //check if we do not have any error messages
                Accounts = JsonSerializer.Deserialize <List <Account> >(json);
                if (Accounts != null)
                {
                    Accounts.ForEach(account =>
                    {
                        AccountInfo ??= new Dictionary <string, decimal>();
                        if (account.Balance.ToDecimal() <= 0)
                        {
                            return;
                        }
                        if (AccountInfo.ContainsKey(account.Currency))
                        {
                            AccountInfo[account.Currency] = account.Balance.ToDecimal();
                        }
                        else
                        {
                            AccountInfo.Add(account.Currency, account.Balance.ToDecimal());
                        }
                    });
                    NotifyAccountInfo?.Invoke(ApplicationName, AccountInfo);
                    Save();
                }
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: UpdateAccountsAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(Accounts);
        }
Example #18
0
        public async Task <List <Order> > UpdateOrdersAsync(Product product = null)
        {
            string json = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General, "Updating Orders Information.");
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "GET",
                                              $"/orders?status=open&status=pending&status=active&product_id={product?.ID ?? string.Empty}");
                json = await ConnectionAdapter.RequestAsync(request);

                Orders = JsonSerializer.Deserialize <List <Order> >(json);
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: UpdateOrdersAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(Orders);
        }
        public virtual async Task <string> WebSocketReceiveAsync()
        {
            try
            {
                await _ioSemaphoreSlim.WaitAsync();

                if (ClientWebSocket == null || !IsWebSocketConnected())
                {
                    return(null);
                }
                ArraySegment <byte>    receiveBuffer          = new ArraySegment <byte>(new byte[512 * 512 * 5]);
                WebSocketReceiveResult webSocketReceiveResult = await ClientWebSocket.ReceiveAsync(
                    receiveBuffer,
                    CancellationToken.None);

                if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close)
                {
                    ClientWebSocket.Abort();
                    ClientWebSocket.Dispose();
                    return(null);
                }

                if (webSocketReceiveResult.Count == 0 || !receiveBuffer.Any() || receiveBuffer.Array == null)
                {
                    return(null);
                }
                return(Encoding.UTF8.GetString(receiveBuffer.Array, 0, webSocketReceiveResult.Count));
            }
            catch (Exception ex)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: WebSocketReceiveAsync\r\nException Stack Trace: {ex.StackTrace}");
            }
            finally
            {
                _ioSemaphoreSlim.Release();
            }

            return(null);
        }
Example #20
0
        public async Task <List <AccountHold> > UpdateAccountHoldsAsync(string accountId)
        {
            string json = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                            "Updating Account Holds Information.");
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "GET",
                                              $"/accounts/{accountId}/holds");
                json = await ConnectionAdapter.RequestAsync(request);

                AccountHolds = JsonSerializer.Deserialize <List <AccountHold> >(json);
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: UpdateAccountHoldsAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(AccountHolds);
        }
        public async Task <OrderBook> UpdateProductOrderBookAsync(Product product, int level = 2)
        {
            try
            {
                ProcessLogBroadcast?.Invoke(MessageType.General, $"[Binance] Updating Product Order Book.");
                Request request = new Request(_connectionAdapter.Authentication.EndpointUrl, "GET", $"/api/v3/depth?")
                {
                    RequestQuery = $"symbol={product.ID}&limit={level}"
                };
                string json = await _connectionAdapter.RequestUnsignedAsync(request);

                ProcessLogBroadcast?.Invoke(MessageType.JsonOutput, $"UpdateProductOrderBookAsync JSON:\r\n{json}");
                //check if we do not have any error messages
                OrderBook = JsonSerializer.Deserialize <OrderBook>(json);
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: UpdateAccountsAsync\r\nException Stack Trace: {e.StackTrace}");
            }
            return(OrderBook);
        }
Example #22
0
        public async Task <OrderBook> UpdateProductOrderBookAsync(Product product, int level = 2)
        {
            string json = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                            "Updating Product Orders Information.");
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "GET",
                                              $"/products/{product.ID}/book?level={level}");
                json = await ConnectionAdapter.RequestAsync(request);

                OrderBook = JsonSerializer.Deserialize <OrderBook>(json);
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: UpdateProductOrderBookAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(OrderBook);
        }
Example #23
0
        public override async Task <List <HistoricRate> > UpdateProductHistoricCandlesAsync(
            HistoricCandlesSearch historicCandlesSearch)
        {
            string json = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                            "Updating Product Historic Candles Information.");
                if (historicCandlesSearch.StartingDateTime.AddMilliseconds((double)historicCandlesSearch
                                                                           .Granularity) >= historicCandlesSearch.EndingDateTime)
                {
                    return(null);
                }
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "GET",
                                              $"/products/{historicCandlesSearch.Symbol}/candles?start={historicCandlesSearch.StartingDateTime:o}&end={historicCandlesSearch.EndingDateTime:o}&granularity={(int) historicCandlesSearch.Granularity}");
                json = await ConnectionAdapter.RequestAsync(request);

                if (json.StartsWith('[') && json.EndsWith(']'))
                {
                    ArrayList[] candles = JsonSerializer.Deserialize <ArrayList[]>(json);
                    HistoricRates = candles.ToHistoricRateList();
                    HistoricRates.Reverse();
                }
                else
                {
                    ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.JsonOutput,
                                                $"Method: UpdateProductHistoricCandlesAsync\r\nJSON: {json}");
                }
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: UpdateProductHistoricCandlesAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(HistoricRates);
        }
        public async Task <BinanceAccount> UpdateBinanceAccountAsync()
        {
            try
            {
                ProcessLogBroadcast?.Invoke(MessageType.General, $"[Binance] Updating Account Information.");
                ServerTime serverTime = await UpdateTimeServerAsync();

                Request request = new Request(_connectionAdapter.Authentication.EndpointUrl, "GET", $"/api/v3/account?")
                {
                    RequestQuery = $"timestamp={serverTime.ServerTimeLong}"
                };
                string json = await _connectionAdapter.RequestAsync(request);

                ProcessLogBroadcast?.Invoke(MessageType.JsonOutput, $"UpdateAccountsAsync JSON:\r\n{json}");
                //check if we do not have any error messages
                BinanceAccount = JsonSerializer.Deserialize <BinanceAccount>(json);
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: UpdateAccountsAsync\r\nException Stack Trace: {e.StackTrace}");
            }
            return(BinanceAccount);
        }
Example #25
0
        public async Task <List <Fill> > UpdateFillsAsync(Product product)
        {
            string json = null;

            try
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General, "Updating Fills Information.");
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "GET",
                                              $"/fills?product_id={product.ID ?? string.Empty}");
                json = await ConnectionAdapter.RequestAsync(request);

                if (!string.IsNullOrEmpty(json))
                {
                    Fills = JsonSerializer.Deserialize <List <Fill> >(json);
                }
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: UpdateFillsAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(Fills);
        }
        private async void ProcessHistoryQuarterlyChartDownload()
        {
            await _processHistorySemaphoreSlim.WaitAsync();

            try
            {
                string fileName = FileName + $"_{RelativeStrengthIndexSettings.Product.ID.ToLower()}_15M.csv";
                string data     = "DateTime,High,Open,Close,Low,Volume,MA7,RSI14\n";
                //Validate file
                if (!File.Exists(fileName))
                {
                    if (!Directory.Exists(Path.GetDirectoryName(fileName)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(fileName));
                    }
                    File.Create(fileName).Close();
                    SaveAnalyticData(fileName, data);
                }

                //Initialise fields
                const int            period      = 14;
                const int            maPeriod    = 7;
                const int            granularity = 900;
                DateTime             startingDateTime;
                HistoricRate         previousHistoricRate = null;
                decimal              increases            = 0;
                decimal              decreases            = 0;
                Queue <HistoricRate> maQueue = new Queue <HistoricRate>();
                //Check if we have an empty file or not
                if (string.IsNullOrWhiteSpace(RelativeStrengthIndexSettings
                                              .HistoricChartPreviousHistoricDateTimeQuarterly))
                {
                    startingDateTime = new DateTime(2015, 4, 23).Date;
                    RelativeStrengthIndexSettings.HistoricChartAverageGainQuarterly        = 0;
                    RelativeStrengthIndexSettings.HistoricChartAverageLossQuarterly        = 0;
                    RelativeStrengthIndexSettings.HistoricChartCurrentPeriodCountQuarterly = 0;
                    RelativeStrengthIndexSettings.RelativeIndexQuarterly = -1;
                }
                else
                {
                    startingDateTime = RelativeStrengthIndexSettings.HistoricChartPreviousHistoricDateTimeQuarterly
                                       .ToDateTime().AddMinutes(15);
                    previousHistoricRate = new HistoricRate
                    {
                        Close       = RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateCloseQuarterly,
                        Open        = RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateOpenQuarterly,
                        Low         = RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateLowQuarterly,
                        High        = RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateHighQuarterly,
                        Volume      = RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateVolumeQuarterly,
                        DateAndTime = RelativeStrengthIndexSettings.HistoricChartPreviousHistoricDateTimeQuarterly
                                      .ToDateTime()
                    };
                }

                //Begin data parsing
                DateTime now = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour,
                                            DateTime.Now.Minute, 0);
                while (startingDateTime < now)
                {
                    DateTime endingDateTime = startingDateTime.AddDays(2);
                    //Get the latest historic data
                    HistoricCandlesSearch historicCandlesSearch = new HistoricCandlesSearch
                    {
                        Symbol           = RelativeStrengthIndexSettings.Product.ID,
                        StartingDateTime = startingDateTime,
                        EndingDateTime   = endingDateTime,
                        Granularity      = (Granularity)granularity
                    };
                    //Prevent overloaded calls by delaying for 1 second before call
                    await Task.Delay(1000);

                    //Get the latest historic data
                    List <HistoricRate> result = await UpdateProductHistoricCandles(historicCandlesSearch);

                    if (!result.Any())
                    {
                        //in the case that no data is available but current search date is not current date
                        startingDateTime = new DateTime(startingDateTime.Year, startingDateTime.Month, 1, 0, 0, 0)
                                           .AddMonths(1);
                        continue;
                    }

                    //Iterate though the historic data
                    foreach (HistoricRate rate in result)
                    {
                        if (rate.DateAndTime >= now)
                        {
                            break;
                        }
                        if (previousHistoricRate != null &&
                            previousHistoricRate.DateAndTime.ToString("dd/MM/yyyy HH:mm") ==
                            rate.DateAndTime.ToString("dd/MM/yyyy HH:mm"))
                        {
                            continue;
                        }
                        //Moving Average 7 days
                        if (maQueue.Count == maPeriod)
                        {
                            maQueue.Dequeue();
                        }
                        maQueue.Enqueue(rate);
                        //Calculate RSI 14 days
                        if (RelativeStrengthIndexSettings.HistoricChartCurrentPeriodCountQuarterly > 0)
                        {
                            decimal change = rate.Close - previousHistoricRate.Close;
                            if (change > 0)
                            {
                                increases += change;
                                if (RelativeStrengthIndexSettings.HistoricChartCurrentPeriodCountQuarterly > period)
                                {
                                    RelativeStrengthIndexSettings.HistoricChartAverageGainQuarterly =
                                        (RelativeStrengthIndexSettings.HistoricChartAverageGainQuarterly *
                                         (period - 1) + change) / period;
                                    RelativeStrengthIndexSettings.HistoricChartAverageLossQuarterly =
                                        RelativeStrengthIndexSettings.HistoricChartAverageLossQuarterly * (period - 1) /
                                        period;
                                }
                            }
                            else if (change < 0)
                            {
                                decreases += change * -1;
                                if (RelativeStrengthIndexSettings.HistoricChartCurrentPeriodCountQuarterly > period)
                                {
                                    RelativeStrengthIndexSettings.HistoricChartAverageGainQuarterly =
                                        RelativeStrengthIndexSettings.HistoricChartAverageGainQuarterly * (period - 1) /
                                        period;
                                    RelativeStrengthIndexSettings.HistoricChartAverageLossQuarterly =
                                        (RelativeStrengthIndexSettings.HistoricChartAverageLossQuarterly *
                                         (period - 1) + change * -1) / period;
                                }
                            }

                            if (RelativeStrengthIndexSettings.HistoricChartCurrentPeriodCountQuarterly >= period)
                            {
                                if (RelativeStrengthIndexSettings.HistoricChartCurrentPeriodCountQuarterly == period)
                                {
                                    RelativeStrengthIndexSettings.HistoricChartAverageGainQuarterly =
                                        increases / period;
                                    RelativeStrengthIndexSettings.HistoricChartAverageLossQuarterly =
                                        decreases / period;
                                }

                                if (RelativeStrengthIndexSettings.HistoricChartCurrentPeriodCountQuarterly >= period)
                                {
                                    RelativeStrengthIndexSettings.RelativeIndexQuarterly =
                                        RelativeStrengthIndexSettings.HistoricChartAverageLossQuarterly == 0
                                            ? 100
                                            : Math.Round(
                                            100 - 100 /
                                            (1 + RelativeStrengthIndexSettings.HistoricChartAverageGainQuarterly /
                                             RelativeStrengthIndexSettings.HistoricChartAverageLossQuarterly),
                                            2);
                                }
                                //Generate data
                                data =
                                    $"{rate.DateAndTime}," +
                                    $"{rate.High}," +
                                    $"{rate.Open}," +
                                    $"{rate.Close}," +
                                    $"{rate.Low}," +
                                    $"{rate.Volume}," +
                                    $"{maQueue.Average(x => x.Close)}," +
                                    $"{RelativeStrengthIndexSettings.RelativeIndexQuarterly}" +
                                    "\n";
                                SaveAnalyticData(fileName, data);
                            }
                        }

                        previousHistoricRate = rate;
                        RelativeStrengthIndexSettings.HistoricChartCurrentPeriodCountQuarterly++;
                    }

                    startingDateTime = previousHistoricRate.DateAndTime.AddMinutes(15);
                    if (previousHistoricRate != null)
                    {
                        RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateCloseQuarterly =
                            previousHistoricRate.Close;
                        RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateOpenQuarterly =
                            previousHistoricRate.Open;
                        RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateLowQuarterly =
                            previousHistoricRate.Low;
                        RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateHighQuarterly =
                            previousHistoricRate.High;
                        RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateVolumeQuarterly =
                            previousHistoricRate.Volume;
                        RelativeStrengthIndexSettings.HistoricChartPreviousHistoricDateTimeQuarterly =
                            previousHistoricRate.DateAndTime.ToString();
                        Dictionary <string, string> indicatorInformation = new Dictionary <string, string>
                        {
                            ["RSI-15MIN"] =
                                RelativeStrengthIndexSettings.RelativeIndexQuarterly.ToString(CultureInfo
                                                                                              .InvariantCulture),
                            ["RSI-1HOUR"] =
                                RelativeStrengthIndexSettings.RelativeIndexHourly
                                .ToString(CultureInfo.InvariantCulture),
                            ["RSI-1DAY"] =
                                RelativeStrengthIndexSettings.RelativeIndexDaily.ToString(CultureInfo.InvariantCulture),
                            ["OPEN-15MIN"] =
                                RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateOpenQuarterly.ToString(
                                    CultureInfo.InvariantCulture),
                            ["OPEN-1HOUR"] =
                                RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateOpenHourly.ToString(
                                    CultureInfo.InvariantCulture),
                            ["OPEN-1DAY"] =
                                RelativeStrengthIndexSettings.HistoricChartPreviousHistoricRateOpen.ToString(CultureInfo
                                                                                                             .InvariantCulture)
                        };
                        TechnicalIndicatorInformationBroadcast?.Invoke(indicatorInformation);
                        Save();
                    }
                }
            }
            catch (Exception ex)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: ProcessHistoryHourlyChartDownload\r\nException Stack Trace: {ex.StackTrace}");
            }
            finally
            {
                _processHistorySemaphoreSlim.Release();
            }
        }
Example #27
0
        public virtual async Task <string> RequestAsync(IRequest request)
        {
            try
            {
                await _ioRequestSemaphoreSlim.WaitAsync();

                StringContent       requestBody = new StringContent("");
                HttpResponseMessage response;
                Uri absoluteUri;
                if (Authentication == null)
                {
                    throw new Exception("Invalid Authentication.");
                }
                if (string.IsNullOrEmpty(Authentication.Passphrase))
                {
                    request.RequestSignature = Authentication.ComputeSignature(request.RequestQuery);
                    request.RequestQuery     = null;
                    absoluteUri = request.ComposeRequestUriAbsolute(Authentication.EndpointUrl);
                    HttpClient.DefaultRequestHeaders.Clear();
                    HttpClient.DefaultRequestHeaders.Add("X-MBX-APIKEY", Authentication.ApiKey);
                    HttpClient.DefaultRequestHeaders.Accept.Add(
                        new MediaTypeWithQualityHeaderValue("application/json")); //ACCEPT header
                }
                else
                {
                    AuthenticationSignature authenticationSignature = Authentication.ComputeSignature(request);
                    requestBody = request.GetRequestBody();
                    absoluteUri = request.AbsoluteUri;
                    HttpClient.DefaultRequestHeaders.Clear();
                    //The api key as a string.
                    HttpClient.DefaultRequestHeaders.Add("CB-ACCESS-KEY", Authentication.ApiKey);
                    //The passphrase you specified when creating the API key.
                    HttpClient.DefaultRequestHeaders.Add("CB-ACCESS-PASSPHRASE", Authentication.Passphrase);
                    //The base64-encoded signature (see Signing a Message).
                    HttpClient.DefaultRequestHeaders.Add("CB-ACCESS-SIGN", authenticationSignature.Signature);
                    // A timestamp for your request.
                    HttpClient.DefaultRequestHeaders.Add("CB-ACCESS-TIMESTAMP", authenticationSignature.Timestamp);
                    //user-agent header
                    HttpClient.DefaultRequestHeaders.Add("User-Agent", "sefbkn.github.io");
                }

                switch (request.Method)
                {
                case "GET":
                    response = await HttpClient.GetAsync(absoluteUri);

                    break;

                case "POST":
                    response = await HttpClient.PostAsync(absoluteUri, requestBody);

                    break;

                case "DELETE":
                    response = await HttpClient.DeleteAsync(absoluteUri);

                    break;

                default:
                    throw new NotImplementedException("The supplied HTTP method is not supported: " +
                                                      request.Method);
                }

                if (response == null)
                {
                    throw new Exception(
                              $"null response from RequestAsync \r\n URI:{request.AbsoluteUri} \r\n:Request Body:{requestBody}");
                }
                return(await response.Content.ReadAsStringAsync());
            }
            catch (Exception ex)
            {
                ProcessLogBroadcast?.Invoke(MessageType.Error,
                                            $"Method: RequestAsync\r\nException Stack Trace: {ex.StackTrace}");
                await ClientWebSocket.ConnectAsync(Authentication.WebSocketUri, CancellationToken.None);
            }
            finally
            {
                _ioRequestSemaphoreSlim.Release();
            }

            return(null);
        }
Example #28
0
        public async Task <List <Order> > CancelOrdersAsync(Product product)
        {
            string       json         = null;
            List <Order> ordersOutput = new List <Order>();

            try
            {
                if (product == null)
                {
                    return(ordersOutput);
                }
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                            "Updating Cancel Orders Information.");
                Request request = new Request(ConnectionAdapter.Authentication.EndpointUrl, "DELETE",
                                              $"/orders?product_id={product.ID ?? string.Empty}");
                json = await ConnectionAdapter.RequestAsync(request);

                if (!json.StartsWith('[') && !json.EndsWith(']'))
                {
                    string orderId = JsonSerializer.Deserialize <string>(json);
                    if (string.IsNullOrEmpty(orderId))
                    {
                        return(ordersOutput);
                    }
                    ordersOutput = Orders.Where(x => x.ID == orderId)?.ToList();
                    int removed = Orders.RemoveAll(x => x.ID == orderId);
                    ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                                removed > 0
                            ? $"Removing Order IDs: {orderId} from Orders."
                            : $"No update from order cancel\r\nRequested URL: {request.RequestUrl}");
                    if (!ordersOutput.Any())
                    {
                        ordersOutput.Add(new Order {
                            ID = orderId
                        });
                    }
                    return(ordersOutput);
                }
                else
                {
                    List <string> orderIds = JsonSerializer.Deserialize <string[]>(json)?.ToList();
                    if (orderIds == null)
                    {
                        return(ordersOutput);
                    }
                    ordersOutput = Orders.Where(x => orderIds.Contains(x.ID))?.ToList();
                    int removed = Orders.RemoveAll(x => orderIds.Contains(x.ID));
                    ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                                removed > 0
                            ? $"Removing Order IDs: {orderIds} from Orders."
                            : $"No update from order cancel\r\nRequested URL: {request.RequestUrl}");
                    if (!ordersOutput.Any())
                    {
                        ordersOutput = (from id in orderIds select new Order {
                            ID = id
                        })?.ToList();
                    }
                    return(ordersOutput);
                }
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: CancelOrdersAsync\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
            }

            return(ordersOutput);
        }
Example #29
0
        public override async Task <bool> InitAsync(bool testMode)
        {
            try
            {
                TestMode = testMode;
                if (string.IsNullOrEmpty(INIFilePath))
                {
                    string directoryName = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
                    INIFilePath = Path.Combine(directoryName, "coinbase.config.ini");
                    LoadINI(INIFilePath);
                }
                else
                {
                    LoadINI(INIFilePath);
                }

                Load();
                await UpdateProductsAsync();
                await UpdateAccountsAsync();

                if (Accounts != null && Accounts.Any())
                {
                    await UpdateAccountHistoryAsync(Accounts[0].ID);
                    await UpdateAccountHoldsAsync(Accounts[0].ID);

                    List <Product> products = new List <Product>
                    {
                        Products.FirstOrDefault(x => x.BaseCurrency == "BTC" && x.QuoteCurrency == "EUR")
                    };
                    products.RemoveAll(x => x == null);
                    if (products.Any())
                    {
                        //UpdateProductOrderBookAsync(products[0]).Wait();
                        //UpdateOrdersAsync().Wait();
                        //UpdateFillsAsync(products[0]).Wait();
                        //UpdateTickersAsync(products).Wait();
                        ChangeFeed(products);
                    }

                    ////market order
                    ////buy
                    //Order marketOrderBuy = new Order {Size = "0.1", Side = OrderSide.Buy, Type = OrderType.Market, ProductID = "BTC-EUR"};
                    //Order marketBuyOrderResponse = await _exchangeService.PostOrdersAsync(marketOrderBuy);
                    ////sell
                    //Order marketOrderSell = new Order { Size = "0.1", Side = OrderSide.Sell, Type = OrderType.Market, ProductID = "BTC-EUR" };
                    //Order marketSellOrderResponse = await _exchangeService.PostOrdersAsync(marketOrderSell);
                    ////limit order
                    //Order limitOrder = new Order { Size = "0.1", Side = OrderSide.Buy, Type = OrderType.Limit, ProductID = "BTC-EUR", Price = "1000" };
                    //Order limitOrderResponse = await _exchangeService.PostOrdersAsync(limitOrder);
                    ////cancel order
                    //await _exchangeService.CancelOrdersAsync(limitOrderResponse);
                    //List<HistoricRate> historicRates =  await _exchangeService.UpdateProductHistoricCandlesAsync(products[0],
                    //    DateTime.Now.AddHours(-2).ToUniversalTime(),
                    //    DateTime.Now.ToUniversalTime(), 900);//15 minutes
                    // }
                }
            }
            catch (Exception e)
            {
                ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                            $"Method: InitAsync\r\nException Stack Trace: {e.StackTrace}");
            }

            return(false);
        }
Example #30
0
        public override Task ChangeFeed(List <Product> products)
        {
            return(Task.Run(() =>
            {
                ThreadPool.QueueUserWorkItem(x =>
                {
                    SubscribedPrices = new Dictionary <string, decimal>();
                    if (products == null)
                    {
                        return;
                    }
                    string json = null;
                    try
                    {
                        ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                                    "Subscribing to Feed Information.");
                        if (SubscribeProducts != null && SubscribeProducts.Any())
                        {
                            //unsubscribe
                            ConnectionAdapter.WebSocketSendAsync(SubscribeProducts.ToUnSubscribeString()).GetAwaiter();
                        }
                        SubscribeProducts = products;
                        json = ConnectionAdapter.WebSocketSendAsync(SubscribeProducts.ToSubscribeString()).Result;
                        if (string.IsNullOrEmpty(json))
                        {
                            return;
                        }
                        ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.General,
                                                    "Started Processing Feed Information.");
                        ConnectionAdapter.ConnectAsync(ConnectionAdapter.Authentication.WebSocketUri.ToString()).GetAwaiter();
                        while (ConnectionAdapter.IsWebSocketConnected())
                        {
                            json = ConnectionAdapter.WebSocketReceiveAsync().ConfigureAwait(false).GetAwaiter()
                                   .GetResult();
                            Feed feed = JsonSerializer.Deserialize <Feed>(json);
                            if (feed == null || feed.Type == "error")
                            {
                                return;
                            }
                            CurrentPrices[feed.ProductID] = feed.Price.ToDecimal();
                            SubscribedPrices[feed.ProductID] = feed.Price.ToDecimal();
                            Product product = Products.FirstOrDefault(x => x.ID == feed.ProductID);
                            if (product != null)
                            {
                                Statistics twentyFourHourPrice = TwentyFourHoursRollingStatsAsync(product).Result;
                                decimal change = ((twentyFourHourPrice.Last.ToDecimal() - twentyFourHourPrice.High.ToDecimal()) / Math.Abs(twentyFourHourPrice.High.ToDecimal()));
                                decimal percentage = change * 100;
                            }
                            feed.CurrentPrices = CurrentPrices;
                            CurrentFeed = feed;

                            NotifyCurrentPrices?.Invoke(ApplicationName, SubscribedPrices);
                            //FeedBroadcast?.Invoke(ApplicationName, feed);
                        }
                    }
                    catch (Exception e)
                    {
                        ProcessLogBroadcast?.Invoke(ApplicationName, MessageType.Error,
                                                    $"Method: StartProcessingFeed\r\nException Stack Trace: {e.StackTrace}\r\nJSON: {json}");
                    }
                });
            }));
        }