Пример #1
0
        public Task SubscribeStatistics(Action <StatisticsEventArgs> callback, Action <Exception> exception, CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource <object>();

            var binanceApi            = new BinanceApi();
            var symbolStatisticsCache = new SymbolStatisticsCache(binanceApi, new SymbolStatisticsWebSocketClient());

            symbolStatisticsCache.Subscribe(e =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    symbolStatisticsCache.Unsubscribe();
                    return;
                }

                var symbolsStats = e.Statistics.Select(s => NewSymbolStats(s)).ToList();

                try
                {
                    callback.Invoke(new StatisticsEventArgs {
                        Statistics = symbolsStats
                    });
                }
                catch (Exception ex)
                {
                    symbolStatisticsCache.Unsubscribe();
                    exception.Invoke(ex);
                    return;
                }
            });

            tcs.SetResult(null);

            return(tcs.Task);
        }
Пример #2
0
        public Task SubscribeOrderBook(string symbol, int limit, Action <OrderBookEventArgs> callback, Action <Exception> exception, CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource <object>();

            var binanceApi     = new BinanceApi();
            var orderBookCache = new OrderBookCache(binanceApi, new DepthWebSocketClient());

            orderBookCache.Subscribe(symbol, limit, e =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    orderBookCache.Unsubscribe();
                    return;
                }

                var orderBook = NewOrderBook(e.OrderBook);

                try
                {
                    callback.Invoke(new OrderBookEventArgs {
                        OrderBook = orderBook
                    });
                }
                catch (Exception ex)
                {
                    orderBookCache.Unsubscribe();
                    exception.Invoke(ex);
                    return;
                }
            });

            tcs.SetResult(null);

            return(tcs.Task);
        }
Пример #3
0
        public Task SubscribeTrades(string symbol, int limit, Action <TradeEventArgs> callback, Action <Exception> exception, CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource <object>();

            var binanceApi = new BinanceApi();
            var tradeCache = new TradeCache(binanceApi, new TradeWebSocketClient());

            tradeCache.Subscribe(symbol, limit, e =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    tradeCache.Unsubscribe();
                    return;
                }

                var trades = e.Trades.Select(t => NewTrade(t)).ToList();

                try
                {
                    callback.Invoke(new TradeEventArgs {
                        Trades = trades
                    });
                }
                catch (Exception ex)
                {
                    tradeCache.Unsubscribe();
                    exception.Invoke(ex);
                    return;
                }
            });

            tcs.SetResult(null);

            return(tcs.Task);
        }
Пример #4
0
        public async Task <IEnumerable <Core.Model.Symbol> > GetSymbolsAsync(CancellationToken cancellationToken)
        {
            var binanceApi = new BinanceApi();
            var result     = await binanceApi.GetSymbolsAsync(cancellationToken).ConfigureAwait(false);

            var symbols = result.Select(s => new Core.Model.Symbol
            {
                Name                 = $"{s.BaseAsset.Symbol}{s.QuoteAsset.Symbol}",
                ExchangeSymbol       = $"{s.BaseAsset.Symbol}{s.QuoteAsset.Symbol}",
                Exchange             = Exchange.Binance,
                NotionalMinimumValue = s.NotionalMinimumValue,
                BaseAsset            = new Core.Model.Asset {
                    Symbol = s.BaseAsset.Symbol, Precision = s.BaseAsset.Precision
                },
                Price = new Core.Model.InclusiveRange {
                    Increment = s.Price.Increment                                     /*, Minimum = s.Price.Minimum, Maximum = s.Price.Maximum*/
                },                                                                    // HACK : remove Price Min and Max because it realtime calcs hits performance.
                Quantity = new Core.Model.InclusiveRange {
                    Increment = s.Quantity.Increment, Minimum = s.Quantity.Minimum, Maximum = s.Quantity.Maximum
                },
                QuoteAsset = new Core.Model.Asset {
                    Symbol = s.QuoteAsset.Symbol, Precision = s.QuoteAsset.Precision
                },
                Status           = (Core.Model.SymbolStatus)s.Status,
                IsIcebergAllowed = s.IsIcebergAllowed,
                OrderTypes       = (IEnumerable <Core.Model.OrderType>)s.OrderTypes
            }).ToList();

            return(symbols);
        }
Пример #5
0
        /// <summary>
        /// Example using manager without DI framework (not recommended).
        /// </summary>
        // ReSharper disable once InconsistentNaming
        // ReSharper disable once UnusedMember.Local
        private static void ExampleMainWithoutDI()
        {
            try
            {
                // Load configuration.
                var configuration = new ConfigurationBuilder()
                                    .SetBasePath(Directory.GetCurrentDirectory())
                                    .AddJsonFile("appsettings.json", true, false)
                                    .Build();

                // Get configuration settings.
                var symbols = configuration.GetSection("TradeHistory:Symbols").Get <string[]>()
                              ?? new string[] { Symbol.BTC_USDT };

                var limit = 25;
                try { limit = Convert.ToInt32(configuration.GetSection("TradeHistory")?["Limit"]); }
                catch { /* ignore */ }

                var loggerFactory = new LoggerFactory();
                loggerFactory.AddFile(configuration.GetSection("Logging:File"));

                // Initialize all the things... a DI framework could instantiate for you...
                var api         = new BinanceApi(BinanceHttpClient.Instance, logger: loggerFactory.CreateLogger <BinanceApi>());
                var tradeClient = new AggregateTradeClient(loggerFactory.CreateLogger <AggregateTradeClient>());
                var webSocket   = new DefaultWebSocketClient(logger: loggerFactory.CreateLogger <DefaultWebSocketClient>());
                var stream      = new BinanceWebSocketStream(webSocket, loggerFactory.CreateLogger <BinanceWebSocketStream>());
                var controller  = new BinanceWebSocketStreamController(api, stream, loggerFactory.CreateLogger <BinanceWebSocketStreamController>());
                var publisher   = new BinanceWebSocketStreamPublisher(controller, loggerFactory.CreateLogger <BinanceWebSocketStreamPublisher>());
                var client      = new AggregateTradeWebSocketClient(tradeClient, publisher, loggerFactory.CreateLogger <AggregateTradeWebSocketClient>());
                var cache       = new AggregateTradeWebSocketCache(api, client, loggerFactory.CreateLogger <AggregateTradeWebSocketCache>());

                // Add error event handler.
                controller.Error += (s, e) => HandleError(e.Exception);

                foreach (var symbol in symbols)
                {
                    // Subscribe to symbol with callback.
                    cache.Subscribe(symbol, limit, Display);

                    lock (_sync)
                    {
                        _message = symbol == symbols.Last()
                            ? $"Symbol: \"{symbol}\" ...press any key to exit."
                            : $"Symbol: \"{symbol}\" ...press any key to continue.";
                    }
                    Console.ReadKey(true);

                    // Unsubscribe from symbol.
                    cache.Unsubscribe();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine();
                Console.WriteLine("  ...press any key to close window.");
                Console.ReadKey(true);
            }
        }
Пример #6
0
        public async Task <ActionResult> Index()
        {
            var api = new BinanceApi();

            var time = await api.GetTimeAsync();

            return(Content($"Server Time: {time} UTC"));
        }
Пример #7
0
        private async void FormSymbolList_LoadAsync(object sender, EventArgs e)
        {
            var api     = new BinanceApi();
            var symbols = await api.GetSymbolsAsync();

            symbolList = symbols /*.Where(x => x.QuoteAsset.Symbol == "BTC")*/.OrderBy(x => x.BaseAsset.Symbol).Select(x => x.ToString()).ToList();
            comboBoxSymbols.DataSource = symbols /*.Where(x => x.QuoteAsset.Symbol == "BTC")*/.OrderBy(x => x.BaseAsset.Symbol).Select(x => x.BaseAsset.Symbol + " - " + x.QuoteAsset.Symbol).ToList();
        }
Пример #8
0
        public async Task <decimal> ValueBinance()
        {
            var api    = new BinanceApi();
            var answer = await api.GetExchangeRateAsync(Asset.ETH, Asset.BTC);

            Console.WriteLine($"Binance is {answer}");
            return(answer);
        }
Пример #9
0
        public async Task <IEnumerable <Core.Model.SymbolStats> > Get24HourStatisticsAsync(CancellationToken cancellationToken)
        {
            var binanceApi = new BinanceApi();
            var stats      = await binanceApi.Get24HourStatisticsAsync(cancellationToken).ConfigureAwait(false);

            var symbolsStats = stats.Select(s => NewSymbolStats(s)).ToList();

            return(symbolsStats);
        }
Пример #10
0
 public SignalRunner(ILogger <SignalRunner> logger, BinanceApi binanceApi, StrategyFactory strategyFactory, TelegramApi telegram)
 {
     _logger                  = logger;
     _binanceApi              = binanceApi;
     _strategyFactory         = strategyFactory;
     _telegram                = telegram;
     _candles                 = new Dictionary <long, Candle>();
     _cancellationTokenSource = new CancellationTokenSource();
 }
Пример #11
0
        public async Task <IEnumerable <Core.Model.Trade> > GetTradesAsync(string symbol, int limit, CancellationToken cancellationToken)
        {
            var binanceApi = new BinanceApi();
            var result     = await binanceApi.GetTradesAsync(symbol, limit, cancellationToken).ConfigureAwait(false);

            var trades = result.Select(t => NewTrade(t)).ToList();

            return(trades);
        }
Пример #12
0
        public async Task <IEnumerable <Core.Model.AggregateTrade> > GetAggregateTradesAsync(string symbol, int limit, CancellationToken cancellationToken)
        {
            var binanceApi = new BinanceApi();
            var trades     = await binanceApi.GetAggregateTradesAsync(symbol, limit, cancellationToken).ConfigureAwait(false);

            var aggregateTrades = trades.Select(at => NewAggregateTrade(at)).ToList();

            return(aggregateTrades);
        }
Пример #13
0
        public async Task <Core.Model.OrderBook> GetOrderBookAsync(string symbol, int limit, CancellationToken cancellationToken)
        {
            var binanceApi = new BinanceApi();
            var result     = await binanceApi.GetOrderBookAsync(symbol, limit, cancellationToken).ConfigureAwait(false);

            var orderBook = NewOrderBook(result);

            return(orderBook);
        }
Пример #14
0
        public async Task <IEnumerable <Core.Model.Candlestick> > GetCandlesticksAsync(string symbol, Core.Model.CandlestickInterval interval, DateTime startTime, DateTime endTime, int limit = 0, CancellationToken token = default)
        {
            var binanceApi          = new BinanceApi();
            var candlestickInterval = interval.ToBinanceCandlestickInterval();
            var results             = await binanceApi.GetCandlesticksAsync(symbol, candlestickInterval, startTime, endTime, limit, token).ConfigureAwait(false);

            var candlesticks = results.Select(cs => NewCandlestick(cs)).ToList();

            return(candlesticks);
        }
Пример #15
0
        private static void UpdateDbWithNewCoin()
        {
            using (MySqlConnection connection = new MySqlConnection(Properties.Settings.Default.DefaultConnection))
            {
                try
                {
                    AppDbContext myContext = new AppDbContext(connection, false);
                    Database.SetInitializer <AppDbContext>(null);

                    //List of coins saved in db
                    List <KuCoin>  dbKuCoinList  = myContext.KuCoin.ToList();
                    List <binance> dbBinanceList = myContext.Binance.ToList();

                    //List of coins from ZuCoin and BinanceCoin API
                    List <KuCoinCoin>  kuCoinList     = KucoinApi.GetZuCoinCoin(uriKucoin);
                    List <BinanceCoin> bianceCoinList = BinanceApi.GetData(uriBinance);

                    //Update KuCoin table
                    foreach (var token in kuCoinList)
                    {
                        if (dbKuCoinList.Where(p => p.kuCoinCoin == token.Coin).Select(p => p.Id).FirstOrDefault() == 0)
                        {
                            myContext.KuCoin.Add(new Model.KuCoin()
                            {
                                kuCoinName = token.Name,
                                kuCoinCoin = token.Coin,
                                DateAdded  = DateTime.Now
                            });
                        }
                    }

                    //Update Binance table
                    foreach (var token in bianceCoinList)
                    {
                        if (dbBinanceList.Where(p => p.binanceSymbol == token.Symbol).Select(p => p.Id).FirstOrDefault() == 0)
                        {
                            myContext.Binance.Add(new binance()
                            {
                                binanceSymbol     = token.Symbol,
                                binanceBaseAsset  = token.BaseAsset,
                                binanceQuoteAsset = token.QuoteAsset,
                                DateAdded         = DateTime.Now
                            });
                        }
                    }
                    myContext.SaveChanges();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            };
        }
Пример #16
0
        public static async Task Main(string[] args)
        {
            var api = new BinanceApi();

            if (await api.PingAsync())
            {
                Console.WriteLine("SUCCESSFUL!");
            }

            Console.WriteLine("...press any key to continue.");
            Console.ReadKey(true);
        }
        public static async Task ExampleMain(string[] args)
        {
            // Initialize with default services and no logger.
            var api = new BinanceApi();

            if (await api.PingAsync())
            {
                Console.WriteLine("SUCCESSFUL!");
            }

            Console.WriteLine("...press any key to continue.");
            Console.ReadKey(true);
        }
Пример #18
0
        public static async Task <decimal> GetPriceByDate(string symbol, DateTime date)
        {
            var api          = new BinanceApi();
            var candleSticks = await api.GetCandlesticksAsync(symbol, CandlestickInterval.Minute, date, date.AddMinutes(1));

            if (candleSticks != null && candleSticks.Any())
            {
                return(((candleSticks.First().High + candleSticks.First().Low) / 2m).RoundTo(8));
            }
            else
            {
                return(0m);
            }
        }
Пример #19
0
        public async Task <Core.Model.Order> PlaceOrder(Core.Model.User user, Core.Model.ClientOrder clientOrder, long recWindow = 0, CancellationToken cancellationToken = default)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var binanceApi = new BinanceApi();

            using var apiUser = new BinanceApiUser(user.ApiKey, user.ApiSecret);
            var order  = OrderHelper.GetOrder(apiUser, clientOrder);
            var result = await binanceApi.PlaceAsync(order).ConfigureAwait(false);

            return(NewOrder(user, result));
        }
Пример #20
0
        public void SendMoney(string WalletToSend)
        {
            switch (WalletToSend)
            {
            case "Binance":
                BinanceApi binanceApi = new BinanceApi();
                break;

            case "Bitfinex":
                break;

            case "Bitforex":
                break;
            }
        }
Пример #21
0
        public async Task <IEnumerable <Core.Model.AccountTrade> > GetAccountTradesAsync(Core.Model.User user, string symbol, DateTime startDate, DateTime endDate, long recWindow = 0, CancellationToken cancellationToken = default)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var binanceApi = new BinanceApi();

            using var apiUser = new BinanceApiUser(user.ApiKey, user.ApiSecret);
            var result = await binanceApi.GetAccountTradesAsync(apiUser, symbol, startDate, endDate, recWindow, cancellationToken).ConfigureAwait(false);

            var accountTrades = result.Select(at => NewAccountTrade(at)).ToList();

            return(accountTrades);
        }
Пример #22
0
        public async Task <DataTable> GetVolumes()
        {
            BinanceApi api = new BinanceApi();

            await SetupCoinData();

            while (true)
            {
                foreach (DataRow pricer in CoinData.Rows)
                {
                    IEnumerable <Candlestick> eighthourcandles = await api.GetCandlesticksAsync(pricer[0].ToString(),
                                                                                                CandlestickInterval.Minutes_5, 0, 0L, 0L, CancellationToken.None);

                    IOrderedEnumerable <Candlestick> candlearray = eighthourcandles.OrderByDescending(e => e.CloseTime);
                    decimal averagevolumeeighthours = candlearray.Average(candlestick => candlestick.Volume);
                    decimal fifteenminavg           = (candlearray.ElementAt(1).Volume + candlearray.ElementAt(2).Volume +
                                                       candlearray.ElementAt(0).Volume) / 3;
                    DataRow row = CoinData.Rows.Cast <DataRow>().First(o => o[0].ToString() == pricer[0].ToString());
                    row[1] = DateTime.UtcNow;
                    row[2] = Decimal.Round(averagevolumeeighthours, MidpointRounding.AwayFromZero);
                    row[3] = PercentGive(candlearray.First().Volume, averagevolumeeighthours);
                    row[4] = PercentGive(fifteenminavg, averagevolumeeighthours);
                    int greencandles = 0;
                    int i            = 0;
                    while (i != 20)
                    {
                        if (candlearray.ElementAt(i).Close > candlearray.ElementAt(i + 1).Close)
                        {
                            greencandles++;
                        }
                        else
                        {
                            break;
                        }
                        i++;
                    }
                    row[5] = greencandles;
                    CoinData.DefaultView.RowFilter = "NowPercent > 0";
                    //var filtered = CoinData.Select().Where(o => Convert.ToDecimal(o[3].ToString()) > Convert.ToDecimal(o[4].ToString()));
                    DataViewColours();
                    coindatagridview.DataSource = CoinData;
                    coindatagridview.Sort(coindatagridview.Columns[3], ListSortDirection.Descending);
                }
            }

            return(CoinData);
        }
Пример #23
0
        public async Task <IEnumerable <Core.Model.Order> > GetOpenOrdersAsync(Core.Model.User user, string symbol = null, long recWindow = 0, Action <Exception> exception = default, CancellationToken cancellationToken = default)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var binanceApi = new BinanceApi();

            using (var apiUser = new BinanceApiUser(user.ApiKey, user.ApiSecret))
            {
                var result = await binanceApi.GetOpenOrdersAsync(apiUser, symbol, recWindow, cancellationToken).ConfigureAwait(false);

                var orders = result.Select(o => NewOrder(user, o)).ToList();
                return(orders);
            }
        }
Пример #24
0
        public virtual void Initialize()
        {
            Api = new BinanceApi();

            var apiKey    = genericProperties.Get(SettingName.API_KEY, string.Empty);
            var secretKey = genericProperties.Get(SettingName.SECRET_KEY, string.Empty);

            if (!string.IsNullOrEmpty(apiKey) && !string.IsNullOrEmpty(secretKey))
            {
                User = new BinanceApiUser(apiKey, secretKey);
            }

            var jArrayProperties = SettingsHelper.GetJArrayHuntingProperties(TypeName);

            if (jArrayProperties != null)
            {
                GenericPropertySerializer.DeserializePropertiesFromArray(Properties, jArrayProperties);
            }
        }
Пример #25
0
        public async Task SubscribeAccountInfo(Core.Model.User user, Action <AccountInfoEventArgs> callback, Action <Exception> exception, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var binanceApi    = new BinanceApi();
            var apiUser       = new BinanceApiUser(user.ApiKey, user.ApiSecret);
            var streamControl = new UserDataWebSocketStreamControl(binanceApi);
            var listenKey     = await streamControl.OpenStreamAsync(apiUser).ConfigureAwait(false);

            var accountInfoCache = new AccountInfoCache(binanceApi, new UserDataWebSocketClient());

            accountInfoCache.Subscribe(listenKey, apiUser, e =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    accountInfoCache.Unsubscribe();
                    streamControl.Dispose();
                    apiUser.Dispose();
                    return;
                }

                var accountInfo  = GetAccountInfo(e.AccountInfo);
                accountInfo.User = user;

                try
                {
                    callback.Invoke(new AccountInfoEventArgs {
                        AccountInfo = accountInfo
                    });
                }
                catch (Exception ex)
                {
                    accountInfoCache.Unsubscribe();
                    streamControl.Dispose();
                    apiUser.Dispose();
                    exception.Invoke(ex);
                    return;
                }
            });
        }
Пример #26
0
        public async Task <Core.Model.AccountInfo> GetAccountInfoAsync(Core.Model.User user, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var binanceApi = new BinanceApi();

            using var apiUser = new BinanceApiUser(user.ApiKey, user.ApiSecret);
            var result = await binanceApi.GetAccountInfoAsync(apiUser, 0, cancellationToken).ConfigureAwait(false);

            var accountInfo = GetAccountInfo(result);

            user.RateLimiter = new Core.Model.RateLimiter {
                IsEnabled = result.User.RateLimiter.IsEnabled
            };
            accountInfo.User = user;
            return(accountInfo);
        }
Пример #27
0
        public async Task <string> CancelOrderAsync(Core.Model.User user, string symbol, string orderId, string newClientOrderId = null, long recWindow = 0, CancellationToken cancellationToken = default)
        {
            if (orderId == null)
            {
                throw new ArgumentNullException(nameof(orderId));
            }

            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var binanceApi = new BinanceApi();
            var id         = Convert.ToInt64(orderId, CultureInfo.InvariantCulture);

            using var apiUser = new BinanceApiUser(user.ApiKey, user.ApiSecret);
            var result = await binanceApi.CancelOrderAsync(apiUser, symbol, id, newClientOrderId, recWindow, cancellationToken).ConfigureAwait(false);

            return(result);
        }
Пример #28
0
        private async Task <DataTable> SetupCoinData()
        {
            if (CoinData.Rows.Count == 0)
            {
                BinanceApi api = new BinanceApi();

                coinprices = await api.GetPricesAsync(CancellationToken.None); // Grab all coin symbols

                _pricesArray = coinprices.ToArray().Where(o =>
                                                          o.Symbol == "BTCUSDT" || o.Symbol == "ETHBTC" || o.Symbol.EndsWith("ETH"));
                foreach (SymbolPrice price in _pricesArray)
                {
                    DataRow row = CoinData.NewRow();
                    row[0] = price.Symbol;
                    row[1] = DateTime.UtcNow;
                    CoinData.Rows.Add(row);
                }
            }
            return(CoinData);
        }
Пример #29
0
        public Task SubscribeCandlesticks(string symbol, Core.Model.CandlestickInterval candlestickInterval, int limit, Action <CandlestickEventArgs> callback, Action <Exception> exception, CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource <object>();

            var binanceApi       = new BinanceApi();
            var interval         = candlestickInterval.ToBinanceCandlestickInterval();
            var candlestickCache = new CandlestickCache(binanceApi, new CandlestickWebSocketClient());

            candlestickCache.Subscribe(symbol, interval, limit, e =>
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    candlestickCache.Unsubscribe();
                    return;
                }

                var candlesticks = (from c in e.Candlesticks select NewCandlestick(c)).ToList();

                try
                {
                    callback.Invoke(new CandlestickEventArgs {
                        Candlesticks = candlesticks
                    });
                }
                catch (Exception ex)
                {
                    candlestickCache.Unsubscribe();
                    exception.Invoke(ex);
                    return;
                }
            });

            tcs.SetResult(null);

            return(tcs.Task);
        }
Пример #30
0
        private static async Task Main()
        {
            var assets = new List <Asset>();

            var api = new BinanceApi();

            // Get the current timestamp.
            var timestamp = await api.GetTimestampAsync();

            // Get latest currency pairs (symbols).
            var symbols = (await api.GetSymbolsAsync()).ToList();

            // Get assets.
            foreach (var symbol in symbols)
            {
                if (!assets.Contains(symbol.BaseAsset))
                {
                    assets.Add(symbol.BaseAsset);
                }

                if (!assets.Contains(symbol.QuoteAsset))
                {
                    assets.Add(symbol.QuoteAsset);
                }
            }

            // Read the symbol template file.
            var lines = (await File.ReadAllLinesAsync("Symbol.template.cs")).ToList();

            // Replace remarks.
            var index = lines.FindIndex(l => l.Contains("<remarks></remarks>"));

            lines[index] = $"    /// <remarks>File generated by {nameof(BinanceCodeGenerator)} tool.</remarks>";

            // Replace timestamp.
            index        = lines.FindIndex(l => l.Contains("<<insert timestamp>>"));
            lines[index] = $"        public static readonly long LastUpdateAt = {timestamp};";

            index = lines.FindIndex(l => l.Contains("<<insert symbols>>"));
            lines.RemoveAt(index);

            // Sort symbols.
            symbols.Sort();

            var groups = symbols.GroupBy(s => s.QuoteAsset);

            // Insert definition for each currency pair (symbol).
            foreach (var group in groups)
            {
                lines.Insert(index++, $"        // {group.First().QuoteAsset}");

                foreach (var symbol in group)
                {
                    lines.Insert(index++, $"        public static Symbol {symbol.BaseAsset}_{symbol.QuoteAsset} => Cache.Get(\"{symbol.BaseAsset}{symbol.QuoteAsset}\");");
                }

                lines.Insert(index++, string.Empty);
            }
            lines.RemoveAt(index);

            index = lines.FindIndex(l => l.Contains("<<insert symbol definitions>>"));
            lines.RemoveAt(index);

            foreach (var symbol in symbols)
            {
                var orderTypes = string.Join(",", symbol.OrderTypes.Select(_ => "OrderType." + _));
                lines.Insert(index++, $"                        new Symbol(SymbolStatus.{symbol.Status}, Asset.{symbol.BaseAsset}, Asset.{symbol.QuoteAsset}, ({Convert.ToString(symbol.Quantity.Minimum, CultureInfo.InvariantCulture)}m, {Convert.ToString(symbol.Quantity.Maximum, CultureInfo.InvariantCulture)}m, {Convert.ToString(symbol.Quantity.Increment, CultureInfo.InvariantCulture)}m), ({Convert.ToString(0, CultureInfo.InvariantCulture)}m, {Convert.ToString(0, CultureInfo.InvariantCulture)}m, {Convert.ToString(symbol.Price.Increment, CultureInfo.InvariantCulture)}m), {Convert.ToString(symbol.NotionalMinimumValue, CultureInfo.InvariantCulture)}m, {symbol.IsIcebergAllowed.ToString().ToLowerInvariant()}, new List<OrderType> {{{orderTypes}}}),");
            }

            // Save the generated source code (replacing original).
            await File.WriteAllLinesAsync("../../../../../src/Binance/Symbol.cs", lines);

            // Read the asset template file.
            lines = (await File.ReadAllLinesAsync("Asset.template.cs")).ToList();

            // Replace remarks.
            index        = lines.FindIndex(l => l.Contains("<remarks></remarks>"));
            lines[index] = $"    /// <remarks>File generated by {nameof(BinanceCodeGenerator)} tool.</remarks>";

            // Replace timestamp.
            index        = lines.FindIndex(l => l.Contains("<<insert timestamp>>"));
            lines[index] = $"        public static readonly long LastUpdateAt = {timestamp};";

            index = lines.FindIndex(l => l.Contains("<<insert assets>>"));
            lines.RemoveAt(index);

            // Sort assets.
            assets.Sort();

            // Insert definition for each asset.
            foreach (var asset in assets)
            {
                lines.Insert(index++, $"        public static Asset {asset} => Cache.Get(\"{asset}\");");
            }

            index = lines.FindIndex(l => l.Contains("<<insert asset definitions>>"));
            lines.RemoveAt(index);

            foreach (var asset in assets)
            {
                lines.Insert(index++, $"                        new Asset(\"{asset}\", {Convert.ToString(asset.Precision, CultureInfo.InvariantCulture)}),");
            }

            // Save the generated source code (replacing original).
            await File.WriteAllLinesAsync("../../../../../src/Binance/Asset.cs", lines);

            Console.WriteLine("Successfully generated new Symbol.cs and Asset.cs files.");
            Console.WriteLine();
            Console.WriteLine("  ...press any key to close window.");
            Console.ReadKey(true);
        }