diff --git a/Gemfile.lock b/Gemfile.lock index 651c29f..20c4890 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - yahoo_finance_client (0.3.0) + yahoo_finance_client (0.3.1) csv httparty (~> 0.21.0) diff --git a/lib/yahoo_finance_client/stock.rb b/lib/yahoo_finance_client/stock.rb index 23172d8..1ccd5f4 100644 --- a/lib/yahoo_finance_client/stock.rb +++ b/lib/yahoo_finance_client/stock.rb @@ -145,7 +145,9 @@ def build_quote_hash(quote, price, dividend, eps) volume: quote["regularMarketVolume"], pe_ratio: quote["trailingPE"], eps: eps, dividend: dividend, dividend_yield: calculate_yield(dividend, price), payout_ratio: calculate_payout(dividend, eps), - ma50: quote["fiftyDayAverage"], ma200: quote["twoHundredDayAverage"] + ma50: quote["fiftyDayAverage"], ma200: quote["twoHundredDayAverage"], + ex_dividend_date: parse_unix_date(quote["exDividendDate"]), + dividend_date: parse_unix_date(quote["dividendDate"]) } end @@ -161,6 +163,12 @@ def calculate_payout(dividend, eps) (dividend / eps * 100).round(2) end + def parse_unix_date(value) + return nil unless value.is_a?(Numeric) && value.positive? + + Time.at(value).utc.to_date + end + def fetch_from_cache(key) cached_entry = @cache[key] return unless cached_entry && Time.now - cached_entry[:timestamp] < CACHE_TTL diff --git a/lib/yahoo_finance_client/version.rb b/lib/yahoo_finance_client/version.rb index 8c29c5d..9d48879 100644 --- a/lib/yahoo_finance_client/version.rb +++ b/lib/yahoo_finance_client/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module YahooFinanceClient - VERSION = "0.3.0" + VERSION = "0.3.1" end diff --git a/spec/yahoo_finance_client/stock_spec.rb b/spec/yahoo_finance_client/stock_spec.rb index 9137221..d2469ad 100644 --- a/spec/yahoo_finance_client/stock_spec.rb +++ b/spec/yahoo_finance_client/stock_spec.rb @@ -41,7 +41,8 @@ "epsTrailingTwelveMonths" => 5.88, "dividendRate" => 0.96, "fiftyDayAverage" => 148.5, - "twoHundredDayAverage" => 145.0 + "twoHundredDayAverage" => 145.0, + "exDividendDate" => 1_710_374_400 } ] } @@ -62,7 +63,9 @@ dividend_yield: 0.64, payout_ratio: 16.33, ma50: 148.5, - ma200: 145.0 + ma200: 145.0, + ex_dividend_date: Date.new(2024, 3, 14), + dividend_date: nil } end @@ -76,6 +79,12 @@ expect(result).to eq(expected_quote) end + it "returns ex_dividend_date as a Date" do + result = described_class.get_quote(symbol) + expect(result[:ex_dividend_date]).to be_a(Date) + expect(result[:ex_dividend_date]).to eq(Date.new(2024, 3, 14)) + end + it "caches the quote data" do described_class.get_quote(symbol) cache = described_class.instance_variable_get(:@cache) @@ -130,7 +139,9 @@ dividend_yield: 0.64, payout_ratio: 16.33, ma50: 148.5, - ma200: 145.0 + ma200: 145.0, + ex_dividend_date: Date.new(2024, 3, 14), + dividend_date: nil } end @@ -164,7 +175,9 @@ dividend_yield: 0.64, payout_ratio: 16.33, ma50: 148.5, - ma200: 145.0 + ma200: 145.0, + ex_dividend_date: Date.new(2024, 3, 14), + dividend_date: nil } end @@ -183,7 +196,8 @@ "epsTrailingTwelveMonths" => 5.96, "dividendRate" => 0.96, "fiftyDayAverage" => 150.0, - "twoHundredDayAverage" => 147.0 + "twoHundredDayAverage" => 147.0, + "exDividendDate" => 1_710_374_400 } ] } @@ -204,7 +218,9 @@ dividend_yield: 0.62, payout_ratio: 16.11, ma50: 150.0, - ma200: 147.0 + ma200: 147.0, + ex_dividend_date: Date.new(2024, 3, 14), + dividend_date: nil } end @@ -269,9 +285,48 @@ dividend_yield: nil, payout_ratio: nil, ma50: 138.0, - ma200: 135.0 + ma200: 135.0, + ex_dividend_date: nil, + dividend_date: nil ) end + + it "returns nil for ex_dividend_date when exDividendDate is missing" do + result = described_class.get_quote("GOOG") + expect(result[:ex_dividend_date]).to be_nil + end + end + + context "when exDividendDate is zero" do + let(:response_body) do + { + "quoteResponse" => { + "result" => [ + { + "symbol" => "TEST", + "shortName" => "Test Inc.", + "regularMarketPrice" => 100.0, + "regularMarketChange" => 0, + "regularMarketChangePercent" => 0, + "regularMarketVolume" => 10_000, + "trailingPE" => nil, + "epsTrailingTwelveMonths" => nil, + "exDividendDate" => 0 + } + ] + } + }.to_json + end + + before do + stub_request(:get, "#{base_url}/v7/finance/quote?symbols=TEST&crumb=#{crumb}") + .to_return(status: 200, body: response_body) + end + + it "returns nil for ex_dividend_date" do + result = described_class.get_quote("TEST") + expect(result[:ex_dividend_date]).to be_nil + end end context "when stock has negative EPS" do @@ -317,7 +372,9 @@ dividend_yield: 0.0, payout_ratio: nil, ma50: 195.0, - ma200: 180.0 + ma200: 180.0, + ex_dividend_date: nil, + dividend_date: nil ) end end @@ -338,7 +395,8 @@ "epsTrailingTwelveMonths" => 5.88, "dividendRate" => 0.96, "fiftyDayAverage" => 148.5, - "twoHundredDayAverage" => 145.0 + "twoHundredDayAverage" => 145.0, + "exDividendDate" => 1_710_374_400 } ] } @@ -369,7 +427,9 @@ dividend_yield: 0.64, payout_ratio: 16.33, ma50: 148.5, - ma200: 145.0 + ma200: 145.0, + ex_dividend_date: Date.new(2024, 3, 14), + dividend_date: nil ) end end @@ -402,7 +462,8 @@ "epsTrailingTwelveMonths" => 5.88, "dividendRate" => 0.96, "fiftyDayAverage" => 148.5, - "twoHundredDayAverage" => 145.0 + "twoHundredDayAverage" => 145.0, + "exDividendDate" => 1_710_374_400 } ] } @@ -434,7 +495,9 @@ dividend_yield: 0.64, payout_ratio: 16.33, ma50: 148.5, - ma200: 145.0 + ma200: 145.0, + ex_dividend_date: Date.new(2024, 3, 14), + dividend_date: nil ) end end @@ -471,7 +534,7 @@ "regularMarketChangePercent" => 1.0, "regularMarketVolume" => 100_000, "trailingPE" => 25.5, "epsTrailingTwelveMonths" => 5.88, "dividendRate" => 0.96, "fiftyDayAverage" => 148.5, - "twoHundredDayAverage" => 145.0 + "twoHundredDayAverage" => 145.0, "exDividendDate" => 1_710_374_400 }, { "symbol" => "MSFT", "shortName" => "Microsoft Corp.", @@ -479,7 +542,7 @@ "regularMarketChangePercent" => 0.53, "regularMarketVolume" => 90_000, "trailingPE" => 35.0, "epsTrailingTwelveMonths" => 10.86, "dividendRate" => 3.0, "fiftyDayAverage" => 375.0, - "twoHundredDayAverage" => 360.0 + "twoHundredDayAverage" => 360.0, "exDividendDate" => 1_715_644_800 } ] } @@ -519,7 +582,7 @@ "regularMarketChangePercent" => 1.0, "regularMarketVolume" => 100_000, "trailingPE" => 25.5, "epsTrailingTwelveMonths" => 5.88, "dividendRate" => 0.96, "fiftyDayAverage" => 148.5, - "twoHundredDayAverage" => 145.0 + "twoHundredDayAverage" => 145.0, "exDividendDate" => 1_710_374_400 } ] } @@ -545,7 +608,7 @@ { symbol: "AAPL", name: "Apple Inc.", price: 150.0, change: 1.5, percent_change: 1.0, volume: 100_000, pe_ratio: 25.5, eps: 5.88, dividend: 0.96, dividend_yield: 0.64, payout_ratio: 16.33, - ma50: 148.5, ma200: 145.0 } + ma50: 148.5, ma200: 145.0, ex_dividend_date: Date.new(2024, 3, 14), dividend_date: nil } end let(:response_body) do { @@ -557,7 +620,7 @@ "regularMarketChangePercent" => 0.53, "regularMarketVolume" => 90_000, "trailingPE" => 35.0, "epsTrailingTwelveMonths" => 10.86, "dividendRate" => 3.0, "fiftyDayAverage" => 375.0, - "twoHundredDayAverage" => 360.0 + "twoHundredDayAverage" => 360.0, "exDividendDate" => 1_715_644_800 } ] } @@ -642,7 +705,7 @@ "regularMarketChangePercent" => 1.0, "regularMarketVolume" => 100_000, "trailingPE" => 25.5, "epsTrailingTwelveMonths" => 5.88, "dividendRate" => 0.96, "fiftyDayAverage" => 148.5, - "twoHundredDayAverage" => 145.0 + "twoHundredDayAverage" => 145.0, "exDividendDate" => 1_710_374_400 } ] }