Skip to content

Commit

Permalink
Added a method to get the spark chart info
Browse files Browse the repository at this point in the history
  • Loading branch information
ooples committed Jan 21, 2023
1 parent 9c993af commit f77a7d9
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 7 deletions.
12 changes: 11 additions & 1 deletion src/Helpers/DateTimeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@
public static class DateTimeHelper
{
/// <summary>
/// Yahoo Finance requires all dates to be in the Unix format which is the amount of seconds since Jan 1, 1970
/// Converts a date to the Unix format which is the amount of seconds since Jan 1, 1970
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static long ToUnixTimestamp(this DateTime dateTime)
{
return new DateTimeOffset(dateTime).ToUnixTimeSeconds();
}

/// <summary>
/// Converts a data from the Unix format which is the amount of seconds since Jan 1, 1970 to a normal date
/// </summary>
/// <param name="unixTimestamp"></param>
/// <returns></returns>
public static DateTime FromUnixTimeStamp(this long unixTimestamp)
{
return DateTimeOffset.FromUnixTimeSeconds(unixTimestamp).DateTime;
}
}
20 changes: 20 additions & 0 deletions src/Helpers/DownloadHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,26 @@ internal static async Task<string> DownloadChartDataAsync(string symbol, TimeRan
}
}

/// <summary>
/// Downloads the spark chart json data using the chosen symbol
/// </summary>
/// <param name="symbol"></param>
/// <param name="timeRange"></param>
/// <param name="timeInterval"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
internal static async Task<string> DownloadSparkChartDataAsync(string symbol, TimeRange timeRange, TimeInterval timeInterval)
{
if (string.IsNullOrWhiteSpace(symbol))
{
throw new ArgumentException("Symbol Parameter Can't Be Empty Or Null");
}
else
{
return await DownloadRawDataAsync(BuildYahooSparkChartUrl(symbol, timeRange, timeInterval));
}
}

/// <summary>
/// Downloads the stats json data using the chosen symbol
/// </summary>
Expand Down
3 changes: 1 addition & 2 deletions src/Helpers/InsightsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ internal class InsightsHelper : YahooJsonBase
/// <typeparam name="T"></typeparam>
/// <param name="jsonData"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
internal override IEnumerable<T> ParseYahooJsonData<T>(string jsonData)
{
var insights = JsonSerializer.Deserialize<InsightsData>(jsonData);

return insights != null ? (IEnumerable<T>)insights.Finance.Result : Enumerable.Empty<T>();
return insights != null ? Enumerable.Cast<T>(new InsightsResult[] { insights.Finance.Result }) : Enumerable.Empty<T>();
}
}
17 changes: 17 additions & 0 deletions src/Helpers/SparkChartHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace OoplesFinance.YahooFinanceAPI.Helpers;

internal class SparkChartHelper : YahooJsonBase
{
/// <summary>
/// Parses the raw json data for the Spark Chart data
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="jsonData"></param>
/// <returns></returns>
internal override IEnumerable<T> ParseYahooJsonData<T>(string jsonData)
{
var sparkChartData = JsonSerializer.Deserialize<SparkChartData>(jsonData);

return sparkChartData != null ? Enumerable.Cast<T>(new SparkInfo[] { sparkChartData.Result }) : Enumerable.Empty<T>();
}
}
16 changes: 12 additions & 4 deletions src/Helpers/UrlHelper.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using OoplesFinance.YahooFinanceAPI.Enums;
using System.Reflection;

namespace OoplesFinance.YahooFinanceAPI.Helpers;
namespace OoplesFinance.YahooFinanceAPI.Helpers;

internal static class UrlHelper
{
Expand Down Expand Up @@ -54,6 +51,17 @@ internal static Uri BuildYahooChartUrl(string symbol, TimeRange timeRange, TimeI
new(string.Format(CultureInfo.InvariantCulture, $"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}?" +
$"range={GetTimeRangeString(timeRange)}&interval={GetTimeIntervalString(timeInterval)}"));

/// <summary>
/// Creates a url that will be used to get spark chart data for a selected symbol
/// </summary>
/// <param name="symbol"></param>
/// <param name="timeRange"></param>
/// <param name="timeInterval"></param>
/// <returns></returns>
internal static Uri BuildYahooSparkChartUrl(string symbol, TimeRange timeRange, TimeInterval timeInterval) =>
new(string.Format(CultureInfo.InvariantCulture, $"https://query2.finance.yahoo.com/v8/finance/spark?interval=" +
$"{GetTimeIntervalString(timeInterval)}&range={GetTimeRangeString(timeRange)}&symbols={symbol}?"));

/// <summary>
/// Creates a url that will be used to get stats for a selected symbol
/// </summary>
Expand Down
33 changes: 33 additions & 0 deletions src/Models/SparkChartData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace OoplesFinance.YahooFinanceAPI.Models;

public class SparkInfo
{
[JsonPropertyName("timestamp")]
public List<int?> Timestamp { get; set; } = new();

[JsonPropertyName("symbol")]
public string Symbol { get; set; } = string.Empty;

[JsonPropertyName("previousClose")]
public object PreviousClose { get; set; } = new();

[JsonPropertyName("chartPreviousClose")]
public double? ChartPreviousClose { get; set; }

[JsonPropertyName("dataGranularity")]
public int? DataGranularity { get; set; }

[JsonPropertyName("end")]
public object End { get; set; } = new();

[JsonPropertyName("start")]
public object Start { get; set; } = new();

[JsonPropertyName("close")]
public List<double?> Close { get; set; } = new();
}

public class SparkChartData
{
public SparkInfo Result { get; set; } = new();
}
14 changes: 14 additions & 0 deletions src/YahooClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,23 @@ public async Task<IEnumerable<BalanceSheetStatement>> GetBalanceSheetHistoryQuar
/// Gets chart info data for the selected stock symbol
/// </summary>
/// <param name="symbol"></param>
/// <param name="timeRange"></param>
/// <param name="timeInterval"></param>
/// <returns></returns>
public async Task<IEnumerable<ChartResult>> GetChartInfoAsync(string symbol, TimeRange timeRange, TimeInterval timeInterval)
{
return new ChartHelper().ParseYahooJsonData<ChartResult>(await DownloadChartDataAsync(symbol, timeRange, timeInterval));
}

/// <summary>
/// Gets spark chart info data for the selected stock symbol
/// </summary>
/// <param name="symbol"></param>
/// <param name="timeRange"></param>
/// <param name="timeInterval"></param>
/// <returns></returns>
public async Task<SparkInfo> GetSparkChartInfoAsync(string symbol, TimeRange timeRange, TimeInterval timeInterval)
{
return new SparkChartHelper().ParseYahooJsonData<SparkInfo>(await DownloadSparkChartDataAsync(symbol, timeRange, timeInterval)).First();
}
}
1 change: 1 addition & 0 deletions tests/TestConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@
var cashflowStatementHistoryQuarterlyList = await yahooClient.GetCashflowStatementHistoryQuarterlyAsync(symbol);
var balanceSheetHistoryQuarterlyList = await yahooClient.GetBalanceSheetHistoryQuarterlyAsync(symbol);
var chartInfoList = await yahooClient.GetChartInfoAsync(symbol, TimeRange._1Day, TimeInterval._1Minute);
var sparkChartInfoList = await yahooClient.GetSparkChartInfoAsync(symbol, TimeRange._1Month, TimeInterval._1Day);

Console.WriteLine();
26 changes: 26 additions & 0 deletions tests/UnitTests/YahooClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -991,4 +991,30 @@ public async Task GetChartInfo_ThrowsException_WhenEmptySymbolIsUsed()
// Assert
await result.Should().ThrowAsync<ArgumentException>().WithMessage("Symbol Parameter Can't Be Empty Or Null");
}

[Fact]
public async Task GetSparkChartInfo_ThrowsException_WhenNoSymbolIsFound()
{
// Arrange
var symbol = "OOPLES";

// Act
var result = async () => await _sut.GetSparkChartInfoAsync(symbol, TimeRange._1Day, TimeInterval._1Minute);

// Assert
await result.Should().ThrowAsync<InvalidOperationException>().WithMessage("Requested Information Not Available On Yahoo Finance");
}

[Fact]
public async Task GetSparkChartInfo_ThrowsException_WhenEmptySymbolIsUsed()
{
// Arrange
var symbol = "";

// Act
var result = async () => await _sut.GetSparkChartInfoAsync(symbol, TimeRange._1Day, TimeInterval._1Minute);

// Assert
await result.Should().ThrowAsync<ArgumentException>().WithMessage("Symbol Parameter Can't Be Empty Or Null");
}
}

0 comments on commit f77a7d9

Please sign in to comment.