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); }
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}"); } }
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}×tamp={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×tamp={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); }
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); }
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); }
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}"); } }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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(); } }
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); }
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); }
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); }
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}"); } }); })); }