How to retrieve historical prices from Yahoo Finance using C#
Introduction
This C# recipe shows how you can retrieve historical prices from Yahoo Finance using API and writing the results to Excel
Note
Yahoo Finance's API is free to use for personal use only. See full terms here 'Yahoo Finance API Terms of use'
Ingredients
The recipe uses the ServiceStack.Text Nuget package. You can install it using Nuget Package manager:
Install-Package ServiceStack.Text
From v4.0.62+ ServiceStack.Text is free!
C# Code Snippet
// retrieve monthly prices for Microsoft
var symbol = "MSFT";
// retrieve pries
var monthlyPricesJson =
$"https://query1.finance.yahoo.com/v7/finance/chart/MSFT?interval=1d&range=1mo"
.GetJsonFromUrl();
var monthlyPrices = monthlyPricesJson.FromJson<YahooRoot>().chart.result.First();
// populate excel spreadsheet with rices
// Step 3
string Path = @"C:\Temp\ExcelRecipes\";
var fileName = "yahoo_finance.xlsx";
var fileInfo = new FileInfo(Path + fileName);
using (var excelFile = new ExcelPackage(fileInfo))
{
// add worksheet if not exists
if (!excelFile.Workbook.Worksheets.Any(ar => ar.Name == "Prices"))
excelFile.Workbook.Worksheets.Add("Prices");
var ws = excelFile.Workbook.Worksheets["Prices"];
// headers
ws.Cells[1, 1].Value = "Ticker";
ws.Cells[1, 2].Value = "Timestamp";
ws.Cells[1, 3].Value = "Close";
ws.Cells[1, 4].Value = "Open";
ws.Cells[1, 5].Value = "Low";
ws.Cells[1, 6].Value = "High";
ws.Cells[1, 7].Value = "Volume";
// content
int row = 2;
int index = 0;
foreach (var unixTimeStamp in monthlyPrices.timestamp)
{
ws.Cells[row, 1].Value = symbol;
// timestamp given in unix epoch
ws.Cells[row, 2].Value = DateTimeOffset.FromUnixTimeSeconds(unixTimeStamp).DateTime;
// apply date format style for Timestamp
ws.Cells[row, 2].Style.Numberformat.Format = DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
var price = monthlyPrices.indicators.quote[0];
ws.Cells[row, 3].Value = price.close[index];
ws.Cells[row, 4].Value = price.open[index];
ws.Cells[row, 5].Value = price.low[index];
ws.Cells[row, 6].Value = price.high[index];
ws.Cells[row, 7].Value = price.volume[index];
row++;
index++;
}
// format
excelFile.Save();
}
public class YahooRoot
{
public Chart chart { get; set; }
}
public class Chart
{
public List<Result> result { get; set; }
public object error { get; set; }
}
public class Result
{
public Meta meta { get; set; }
public List<int> timestamp { get; set; }
public Indicators indicators { get; set; }
}
public class Indicators
{
public List<Quote> quote { get; set; }
public List<Adjclose> adjclose { get; set; }
}
public class Quote
{
public List<double> open { get; set; }
public List<double> high { get; set; }
public List<double> low { get; set; }
public List<double> close { get; set; }
public List<int> volume { get; set; }
}
public class Adjclose
{
public List<double> adjclose { get; set; }
}
public class Pre
{
public string timezone { get; set; }
public int start { get; set; }
public int end { get; set; }
public int gmtoffset { get; set; }
}
public class Regular
{
public string timezone { get; set; }
public int start { get; set; }
public int end { get; set; }
public int gmtoffset { get; set; }
}
public class Post
{
public string timezone { get; set; }
public int start { get; set; }
public int end { get; set; }
public int gmtoffset { get; set; }
}
public class CurrentTradingPeriod
{
public Pre pre { get; set; }
public Regular regular { get; set; }
public Post post { get; set; }
}
public class Meta
{
public string currency { get; set; }
public string symbol { get; set; }
public string exchangeName { get; set; }
public string instrumentType { get; set; }
public int firstTradeDate { get; set; }
public int regularMarketTime { get; set; }
public int gmtoffset { get; set; }
public string timezone { get; set; }
public string exchangeTimezoneName { get; set; }
public double regularMarketPrice { get; set; }
public double chartPreviousClose { get; set; }
public int priceHint { get; set; }
public CurrentTradingPeriod currentTradingPeriod { get; set; }
public string dataGranularity { get; set; }
public string range { get; set; }
public List<string> validRanges { get; set; }
}