/// <summary> /// Downloads all symbols from the exchanges and filters out the coins with enough 24hr Volume /// </summary> /// <returns></returns> private void FindCoinsWithEnoughVolume() { _symbols = new List <ExtendedSymbol>(); var allSymbolsMeta = _api.GetMarketSymbolsMetadataAsync().Result; var allTickers = _api.GetTickersAsync().Result; // for each symbol foreach (var metadata in allSymbolsMeta) { string symbol = metadata.MarketSymbol.ToUpperInvariant(); if (!IsValidCurrency(symbol)) { // ignore, symbol has wrong currency continue; } // check 24hr volume var ticker = allTickers.FirstOrDefault(e => e.Key == symbol).Value; var volume = ticker.Volume.QuoteCurrencyVolume; if (_api is ExchangeBittrexAPI) { // bittrex reports wrong volume :-( volume = ticker.Volume.BaseCurrencyVolume; } if (volume < _settings.Min24HrVolume) { // ignore since 24hr volume is too low continue; } if (ticker.Ask < _settings.MinPrice) { Trace.WriteLine($"Ignoring because price is too low: {ticker.Ask}"); continue; } SymbolTrend fourHourTrend = new SymbolTrend(4); SymbolTrend oneHourTrend = new SymbolTrend(1); // add to list ExtendedSymbol extendedSymbol = new ExtendedSymbol() { Symbol = metadata, Ticker = ticker, Trends = new SymbolTrend[2] }; extendedSymbol.Trends[0] = fourHourTrend; extendedSymbol.Trends[1] = oneHourTrend; _symbols.Add(extendedSymbol); } _symbols = _symbols.OrderBy(e => e.Symbol.MarketSymbol).ToList(); }
public async Task <ExchangeRates> GetRatesAsync() { await new SynchronizationContextRemover(); var rates = await _ExchangeAPI.GetTickersAsync(); lock (notFoundSymbols) { var exchangeRates = rates.Select(t => CreateExchangeRate(t)) .Where(t => t != null) .ToArray(); return(new ExchangeRates(exchangeRates)); } }
public async Task <PairRate[]> GetRatesAsync(CancellationToken cancellationToken) { await new SynchronizationContextRemover(); var rates = await _ExchangeAPI.GetTickersAsync(); var exchangeRateTasks = rates .Where(t => t.Value.Ask != 0m && t.Value.Bid != 0m) .Select(t => CreateExchangeRate(t)); var exchangeRates = await Task.WhenAll(exchangeRateTasks); return(exchangeRates .Where(t => t != null) .ToArray()); }
public async Task <List <MarketSummary> > GetMarketSummaries(string quoteCurrency) { var result = new List <MarketSummary>(); if (_exchange == Exchange.Huobi || _exchange == Exchange.Okex || _exchange == Exchange.Gdax || _exchange == Exchange.GdaxSimulation) { result = await GetExtendedMarketSummaries(quoteCurrency); } else { //Global.Logger.Information($"Starting GetMarketSummaries _api.GetTickersAsync()"); //var watch1 = System.Diagnostics.Stopwatch.StartNew(); var summaries = _api.GetTickersAsync().Result; //watch1.Stop(); //Global.Logger.Warning($"Ended GetMarketSummaries _api.GetTickersAsync() in #{watch1.Elapsed.TotalSeconds} seconds"); //if (summaries.Any()) //{ // var tasks = new Task[summaries.Count()]; // var cts = new CancellationTokenSource(); // var po = new ParallelOptions // { // CancellationToken = cts.Token, // MaxDegreeOfParallelism = Environment.ProcessorCount // }; // Parallel.ForEach(summaries, po, (summary, state, index) => // { // tasks[(int)index] = Task.Run(() => // { // var info = GetSymbolInfo(summary.Key).Result; // result.Add(new MarketSummary() // { // CurrencyPair = new CurrencyPair() { BaseCurrency = info.MarketCurrency, QuoteCurrency = info.BaseCurrency }, // MarketName = summary.Key, // Ask = summary.Value.Ask, // Bid = summary.Value.Bid, // Last = summary.Value.Last, // Volume = summary.Value.Volume.ConvertedVolume, // }); // }); // }); // Task.WaitAll(tasks); foreach (var summary in summaries) { var info = await GetSymbolInfo(summary.Key); result.Add(new MarketSummary() { CurrencyPair = new CurrencyPair() { BaseCurrency = info.MarketCurrency, QuoteCurrency = info.BaseCurrency }, MarketName = summary.Key, Ask = summary.Value.Ask, Bid = summary.Value.Bid, Last = summary.Value.Last, Volume = summary.Value.Volume.ConvertedVolume, }); } } return(result); }
public async void StartYourEngines() { logger.Trace("Enumerate Markets"); // enumerate all markets // coins to remove like stable-coins and BTC, ETH. string[] coinsToRemove = { "USDC", "BUSD", "USDT", "DAI", "BTC", "ETH", "PAX", "XRP" }; var tickers = await api.GetTickersAsync(); tickers = tickers.Where(t => t.Value.Volume.QuoteCurrency == QUOTECURRENCY && !coinsToRemove.Contains(t.Value.Volume.BaseCurrency) ); logger.Trace($"Enumerated {tickers.Count()} markets."); foreach (var ticker in tickers) { this.Assets.Add(new Asset { Ticker = ticker.Key, BaseCurrency = ticker.Value.Volume.BaseCurrency }); } var currentTime = DateTime.UtcNow; var minutesAway1 = 60 - currentTime.Minute; var minutesAway2 = 45 - currentTime.Minute; var minutesAway3 = 30 - currentTime.Minute; var minutesAway4 = 15 - currentTime.Minute; var minutesAway = new int[] { minutesAway1, minutesAway2, minutesAway3, minutesAway4 }.Where(a => a > 0).Min(); logger.Trace($"App starting in {minutesAway} minutes."); // Update 15-minute candle once per 15-minutes. timer = new Timer(async(objState) => await doWork(objState)); timer.Change((minutesAway * 60 + 15) * 1000, FIFTEENMINUTES); // don't start exactly on the hour so that the server has prepared the 15minute candle. offset by 15 seconds. // start up web socket. if (socket == null) { var numOfTickers = this.Assets.Count(); socket = await api.GetTickersWebSocketAsync(items => { for (int i = 0; i < numOfTickers; i++) { var tkr = this.Assets[i].Ticker; var foundTkr = items.FirstOrDefault(p => p.Key == tkr); var asset = this.Assets[i]; if (foundTkr.Value != null) { asset.Price = foundTkr.Value.Last; asset.Ask = foundTkr.Value.Ask; asset.Bid = foundTkr.Value.Bid; // adjust the stoploss. asset.adjustStopLoss(); if (asset.HasTrade && asset.CanSell && (asset.Price < asset.StopLoss)) { this.doSell(asset); } } } }, tickers.Select(t => t.Key).ToArray()); } }
public async void StartYourEngines() { logger.Trace("Enumerate Markets"); // enumerate all markets var tickers = await api.GetTickersAsync(); tickers = tickers.Where(t => t.Value.Volume.QuoteCurrency == QUOTECURRENCY && !coinsToRemove.Contains(t.Value.Volume.BaseCurrency) ); logger.Trace($"Enumerated {tickers.Count()} markets."); foreach (var ticker in tickers) { var newAsset = new Asset { Ticker = ticker.Key, BaseCurrency = ticker.Value.Volume.BaseCurrency }; // recover stopped bot. var foundTkr = openTickers.FirstOrDefault(o => o.Item1 == newAsset.Ticker); if (foundTkr.Item1 != null) { newAsset.HasTrade = true; newAsset.BuyPrice = foundTkr.Item2; } this.Assets.Add(newAsset); } var currentTime = DateTime.UtcNow; var remainder = (currentTime.Hour * 3600 + currentTime.Minute * 60 + currentTime.Second) % CANDLEPERIODSECS; var secondsAway = CANDLEPERIODSECS - remainder + 60; // don't start exactly on the hour so that the server has prepared the 5minute candle. offset by 60 seconds. var startTime = currentTime.AddSeconds(secondsAway); logger.Trace($"App starting in {secondsAway} seconds at {startTime}"); // Update 15-minute candle once per 15-minutes. timer = new Timer(async(objState) => await doWork(objState)); timer.Change(secondsAway * 1000, CANDLEPERIODSECS * 1000); // power up socket listener. //var socket = await api.GetTickersWebSocketAsync(items => { // foreach (var asset in this.Assets) // { // var foundTkr = items.FirstOrDefault(p => p.Key == asset.Ticker); // if (foundTkr.Key != null) // { // asset.UpdatePrices(foundTkr.Value.Last, foundTkr.Value.Ask, foundTkr.Value.Bid); // if (asset.HasTrade) // { // asset.adjustStopLoss(TAKEPROFITPERCENTAGE); // if (asset.Price < asset.StopLoss) // { // doSell(asset); // } // } // } // } //}, this.Assets.Select(a => a.Ticker).ToArray()); //socket.ConnectInterval = new TimeSpan(0, 0, 30); }