Add YahooFinance module, historical quotes table
This commit is contained in:
93
lib/tradex/yahoo_finance.ex
Normal file
93
lib/tradex/yahoo_finance.ex
Normal file
@@ -0,0 +1,93 @@
|
||||
defmodule Tradex.YahooFinance do
|
||||
@moduledoc """
|
||||
Module to fetch historical stock quotes from Yahoo Finance's v8 API.
|
||||
"""
|
||||
|
||||
@yahoo_finance_url "https://query1.finance.yahoo.com/v8/finance/chart/"
|
||||
|
||||
@doc """
|
||||
Fetches historical stock quotes for a given symbol (ticker) within a date range.
|
||||
|
||||
## Parameters
|
||||
- symbol: The stock symbol (e.g., "ADBE" for Adobe).
|
||||
- start_date: The start date as a `DateTime`.
|
||||
- end_date: The end date as a `DateTime`.
|
||||
|
||||
## Returns
|
||||
- {:ok, list_of_quotes} on success.
|
||||
- {:error, reason} on failure.
|
||||
"""
|
||||
def fetch_historical_quotes(symbol, start_date, end_date) do
|
||||
# Convert dates to Unix timestamps
|
||||
start_unix = DateTime.to_unix(start_date)
|
||||
end_unix = DateTime.to_unix(end_date)
|
||||
|
||||
# Build the URL with query parameters
|
||||
url = "#{@yahoo_finance_url}#{symbol}?period1=#{start_unix}&period2=#{end_unix}&interval=1d"
|
||||
|
||||
# Make the HTTP GET request
|
||||
case HTTPoison.get(url) do
|
||||
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
|
||||
# Parse the JSON response
|
||||
parse_json(body)
|
||||
|
||||
{:ok, %HTTPoison.Response{status_code: status_code}} ->
|
||||
{:error, "Failed to fetch data. Status code: #{status_code}"}
|
||||
|
||||
{:error, reason} ->
|
||||
{:error, reason}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Parses the JSON response from Yahoo Finance's v8 API into a list of maps.
|
||||
|
||||
## Parameters
|
||||
- json_data: The JSON data as a string.
|
||||
|
||||
## Returns
|
||||
- {:ok, list_of_quotes} if the JSON is valid.
|
||||
- {:error, reason} if the JSON is invalid or an error occurs.
|
||||
"""
|
||||
defp parse_json(json_data) do
|
||||
case Jason.decode(json_data) do
|
||||
{:ok,
|
||||
%{
|
||||
"chart" => %{
|
||||
"result" => [
|
||||
%{
|
||||
"timestamp" => timestamps,
|
||||
"indicators" => %{
|
||||
"quote" => [%{"open" => opens, "high" => highs, "low" => lows, "close" => closes, "volume" => volumes}],
|
||||
"adjclose" => [%{"adjclose" => adj_closes}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}} ->
|
||||
# Combine the data into a list of maps
|
||||
quotes =
|
||||
[timestamps, opens, highs, lows, closes, adj_closes, volumes]
|
||||
|> Enum.zip()
|
||||
|> Enum.map(fn {timestamp, open, high, low, close, adj_close, volume} ->
|
||||
%{
|
||||
date: DateTime.from_unix!(timestamp),
|
||||
open: open,
|
||||
high: high,
|
||||
low: low,
|
||||
close: close,
|
||||
adj_close: adj_close,
|
||||
volume: volume
|
||||
}
|
||||
end)
|
||||
|
||||
{:ok, quotes}
|
||||
|
||||
{:ok, _} ->
|
||||
{:error, "No data found in the response"}
|
||||
|
||||
{:error, reason} ->
|
||||
{:error, "Failed to parse JSON response: #{reason}"}
|
||||
end
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user