/// <summary> /// Get historical stock quotes from Yahoo Finance /// </summary> /// <param name="country"></param> /// <param name="stockId"></param> /// <param name="start"></param> /// <param name="end"></param> /// <param name="writeToErrorLogAction"></param> /// <returns></returns> public override async Task <IReadOnlyList <IStockQuoteFromDataSource> > GetHistoricalQuotesAsync(Country country, string stockId, DateTime start, DateTime end, Action <Exception> writeToErrorLogAction) { string stockFullId = country == Country.USA ? stockId : $"{stockId}.{country.GetShortName()}"; string yahooSingleQuoteUrl = string.Format(Configuration["YahooFinanceURL"], stockFullId); (string HtmlContent, IReadOnlyList <Cookie> Cookies)response = await GetHttpContentAsync(yahooSingleQuoteUrl).ConfigureAwait(false); IStockQuoteFromDataSource yahooQuote = _parser.ParseSingleQuote(country, stockId, response.HtmlContent, writeToErrorLogAction); IReadOnlyList <Cookie> cookies = response.Cookies; if (!(yahooQuote is YahooFinanceDataResult yahooResult) || string.IsNullOrEmpty(yahooResult.Crumb)) { return(null); } string startTimestamp = new DateTime(start.Year, start.Month, start.Day, 0, 0, 0).ToUnixTimestamp(); string endTimestamp = new DateTime(end.Year, end.Month, end.Day, 23, 59, 59).ToUnixTimestamp(); string yahooHistoricalUrl = string.Format(Configuration["YahooHistoricalDataUrl"], stockFullId, startTimestamp, endTimestamp, yahooResult.Crumb); (string HtmlContent, IReadOnlyList <Cookie> Cookies)response2 = await GetHttpContentAsync(yahooHistoricalUrl, cookies).ConfigureAwait(false); IReadOnlyList <IStockQuoteFromDataSource> quotes = _parser.ParseMultiQuotes(country, stockId, response2.HtmlContent, writeToErrorLogAction); return(quotes.Where(a => a.TradeDateTime >= start && a.TradeDateTime <= end).ToList()); }
private void RemoveStockQuote(List <IStock> stocks, IStockQuoteFromDataSource stockQuote) { IStock stock = stocks.Find(x => string.Equals(x.StockId, stockQuote.StockId, StringComparison.OrdinalIgnoreCase)); if (stock != null) { stocks.Remove(stock); } }
public void DataSourceRealTimeWithInternetPriceTest(Country country, string stockId) { IConfiguration config = TestServiceProvider.GetTestConfiguration(); IStockQuoteDataSourceOperations operations = new StockQuoteDataSourceOperations(); IStockQuoteParser parser = new AlphaVantageParser(); AlphaVantageDataSource source = new AlphaVantageDataSource(config, operations, parser); IStockQuoteFromDataSource quote = source.GetMostRecentQuoteAsync(country, stockId, WriteToErrorLogAction).Result; Assert.NotNull(quote); Assert.True(quote.IsValid); }
public void GetMostRecentQuoteTest(Country country, string stockId) { IConfiguration config = TestServiceProvider.GetTestConfiguration(); IStockQuoteProvider provider = new StockQuoteSourceProvider(config, country); IStockQuoteDataSource yahooSource = provider.GetStockDataSources().FirstOrDefault(a => a.Source == Contracts.StockQuoteSource.Yahoo); Assert.NotNull(yahooSource); IStockQuoteFromDataSource result = yahooSource.GetMostRecentQuoteAsync(country, stockId, WriteToErrorLogAction).Result; Assert.NotNull(result); Assert.True(result.IsValid); }
public void ParseSingleQuoteTest() { Country country = Country.USA; string stockId = "HDV"; AlphaVantageParser parser = new AlphaVantageParser(); string jsonContent = TestUtilities.ReadTestFile(Av5MinsJsonFile); IStockQuoteFromDataSource quote = parser.ParseSingleQuote(country, stockId, jsonContent, WriteToErrorLogAction); Assert.NotNull(quote); Assert.True(quote.IsValid); }
public void ParseSingleQuoteEmptyInputTest() { Country country = Country.USA; string stockId = "HDV"; AlphaVantageParser parser = new AlphaVantageParser(); _isWriteToErrorLogActionRan = false; IStockQuoteFromDataSource quote = parser.ParseSingleQuote(country, stockId, null, WriteToErrorLogAction); Assert.Null(quote); Assert.True(_isWriteToErrorLogActionRan); }
static void PrintQuote(IStockQuoteFromDataSource quote) { if (quote == null) { return; } Console.WriteLine("Date: " + quote.TradeDateTime); Console.WriteLine("Open: " + quote.OpenPrice); Console.WriteLine("Close: " + quote.ClosePrice); Console.WriteLine("High: " + quote.HighPrice); Console.WriteLine("Low: " + quote.LowPrice); Console.WriteLine("Volume: " + quote.Volume); Console.WriteLine(); }
static async Task RunAlphaVantageSource(string stockId) { IStockQuoteDataSource alphaVantageDataSource = GetAlphaVantageDataSource(_provider); if (alphaVantageDataSource == null) { Console.WriteLine("Error : Yahoo data source object is null"); return; } IStockQuoteFromDataSource quote = await alphaVantageDataSource.GetMostRecentQuoteAsync(_country, stockId, WriteToError).ConfigureAwait(false); if (quote != null) { PrintQuote(quote); } }
public void ParseSingleQuoteTest() { Country country = Country.USA; string stockId = "DRV"; string htmlContent = TestUtilities.ReadTestFile(YahooHtmlTestFilename); IStockQuoteParser parser = new YahooFinanceParser(); IStockQuoteFromDataSource quote = parser.ParseSingleQuote(country, stockId, htmlContent, WriteToErrorLogAction); Assert.NotNull(quote); Assert.True(quote.IsValid); Assert.Equal(14.63m, quote.ClosePrice); Assert.Equal(15.0686m, quote.HighPrice); Assert.Equal(14.611m, quote.LowPrice); Assert.Equal(14.79m, quote.OpenPrice); Assert.Equal(67165, quote.Volume); Assert.Equal(stockId, quote.StockId); Assert.Equal(country, quote.Country); Assert.Equal(2018, quote.TradeDateTime.Year); Assert.Equal(3, quote.TradeDateTime.Month); Assert.Equal(2, quote.TradeDateTime.Day); Assert.Equal(15, quote.TradeDateTime.Hour); Assert.Equal(59, quote.TradeDateTime.Minute); }
private async Task <IStockQuoteFromDataSource> GetStockPricesFromDataSourceInternalAsync(CountryKind country, string stockId) { // TODO: 3 moves to constant ? for (int retry = 0; retry < 3; retry++) { foreach (IStockQuoteDataSource source in BaseData.GetStockDataSources()) { IStockQuoteFromDataSource stockData = null; try { stockData = await source.GetMostRecentQuoteAsync(country.ConvertToTTStockQuoteSourceCountry(), stockId, WriteToErrorLog).ConfigureAwait(false); } catch { } if (TestStatus && (stockData?.IsValid != true)) { continue; } if (!TestStatus && (stockData?.IsValid != true || !BaseData.CurrentTime.IsSameDay(stockData.TradeDateTime))) { continue; } return(stockData); } } return(null); }
private (decimal?NInSystem, decimal?highestPriceInSystem, decimal?lowestPriceInSystem) DailyPriceCalculationSystem(BuySellStrategyType type, IReadOnlyList <IStockPriceHistory> recentStockPriceHistory, decimal todayATR, IStockQuoteFromDataSource todayPriceDataFromDataSource) { decimal[] lowPrices = null; decimal[] highPrices = null; decimal?[] ATRs = null; decimal? lowestPrice = null; decimal? highestPrice = null; decimal? todayN = null; if (recentStockPriceHistory.Count >= type.GetSellIntValue()) { lowPrices = recentStockPriceHistory.Take(type.GetSellIntValue()).Select(a => a.LowPrice).ToArray(); ATRs = recentStockPriceHistory.Take(type.GetSellIntValue() - 1).Select(a => a.ATR).ToArray(); } if (recentStockPriceHistory.Count() >= type.GetBuyIntValue()) { highPrices = recentStockPriceHistory.Take(type.GetBuyIntValue()).Select(a => a.HighPrice).ToArray(); ATRs = recentStockPriceHistory.Take(type.GetBuyIntValue() - 1).Select(a => a.ATR).ToArray(); } if (lowPrices != null) { lowestPrice = _baseData.CalculateLowestPrice(lowPrices, todayPriceDataFromDataSource.LowPrice); } if (highPrices != null) { highestPrice = _baseData.CalculateHighestPrice(highPrices, todayPriceDataFromDataSource.HighPrice); } if (ATRs != null) { List <decimal> validATRList = new List <decimal>(); foreach (decimal?item in ATRs) { if (item.HasValue) { validATRList.Add(item.Value); } } if (validATRList.Count() == type.GetBuyIntValue() - 1) { todayN = _baseData.CalculateTodayN(validATRList.ToArray(), todayATR); } } return(todayN, highestPrice, lowestPrice); }
public async Task InsertToDatabase(IStockQuoteFromDataSource stockData) { // get previous close price , if none, it's the first record and then insert to db IReadOnlyList <IStockPriceHistory> previousPrices = await _database.GetStockPriceHistoryAsync(stockData.Country.ConvertToTT2Country(), stockData.StockId, stockData.TradeDateTime, 1).ConfigureAwait(false); IStockPriceHistory previousStockPriceHistory = previousPrices?.FirstOrDefault(); if (previousStockPriceHistory == null) { //string msg = $"The stock data {GetStockFullID(todayPriceFromDataSource.StockId)} from data sourceKind doesn't have the previous closed price, so it will NOT be added to database"; //WriteToErrorLog(msg); IStockPriceHistory priceHist = new StockPriceHistory(stockData.Country.ConvertToTT2Country(), stockData.StockId, stockData.TradeDateTime) { OpenPrice = stockData.OpenPrice, ClosePrice = stockData.ClosePrice, HighPrice = stockData.HighPrice, LowPrice = stockData.LowPrice, Volume = stockData.Volume }; await _database.AddOrUpdateStockPriceHistoryAsync(priceHist).ConfigureAwait(false); return; } // get the max days of SystemN IReadOnlyList <IStockPriceHistory> recentStockPriceHistory = await _database.GetStockPriceHistoryAsync(stockData.Country.ConvertToTT2Country(), stockData.StockId, stockData.TradeDateTime, _maxCalculationDay - 1).ConfigureAwait(false); // if there exists previous closed price, then calculate today's ATR decimal todayATR = _baseData.CalculateTodayATR(stockData.HighPrice, stockData.LowPrice, previousStockPriceHistory.ClosePrice); (decimal? N20, decimal? HighIn20, decimal? LowIn10) = DailyPriceCalculationSystem(BuySellStrategyType.N20, recentStockPriceHistory, todayATR, stockData); (decimal? N40, decimal? HighIn40, decimal? LowIn15) = DailyPriceCalculationSystem(BuySellStrategyType.N40, recentStockPriceHistory, todayATR, stockData); (decimal? N60, decimal? HighIn60, decimal? LowIn20) = DailyPriceCalculationSystem(BuySellStrategyType.N60, recentStockPriceHistory, todayATR, stockData); decimal?MA20 = CalculateMovingAverage(20, recentStockPriceHistory, stockData); decimal?MA40 = CalculateMovingAverage(40, recentStockPriceHistory, stockData); decimal?MA60 = CalculateMovingAverage(60, recentStockPriceHistory, stockData); decimal?MA120 = CalculateMovingAverage(120, recentStockPriceHistory, stockData); decimal?MA240 = CalculateMovingAverage(240, recentStockPriceHistory, stockData); IStockPriceHistory priceHistory = new StockPriceHistory(stockData.Country.ConvertToTT2Country(), stockData.StockId, stockData.TradeDateTime) { OpenPrice = stockData.OpenPrice, ClosePrice = stockData.ClosePrice, HighPrice = stockData.HighPrice, LowPrice = stockData.LowPrice, Volume = stockData.Volume, ATR = todayATR, N20 = N20, N40 = N40, N60 = N60, HighIn20 = HighIn20, LowIn10 = LowIn10, HighIn40 = HighIn40, LowIn15 = LowIn15, HighIn60 = HighIn60, LowIn20 = LowIn20, MA20 = MA20, MA40 = MA40, MA60 = MA60, MA120 = MA120, MA240 = MA240 }; await _database.AddOrUpdateStockPriceHistoryAsync(priceHistory).ConfigureAwait(false); }
private decimal?CalculateMovingAverage(int days, IReadOnlyList <IStockPriceHistory> recentStockPriceHistory, IStockQuoteFromDataSource todayPriceDataFromDataSource) { if (recentStockPriceHistory.Count() >= days - 1) { decimal[] closePrices = recentStockPriceHistory.Take(days - 1).Select(a => a.ClosePrice).ToArray(); return((closePrices.Sum() + todayPriceDataFromDataSource.ClosePrice) / (decimal)days); } return(null); }