yahoo_finance_client 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e431bef79d59f2f41862b78bae97b9b0935d764c2772dd34d64185c55a1bfac
4
- data.tar.gz: 244e81d428f6db8662943c978fca0bc8849657cb6272f5cf9d6e86703bc9586d
3
+ metadata.gz: c3279a92de28429f202ecb5b00115c837826fe910fe7bf27b60d7e2f1772e40c
4
+ data.tar.gz: 28bd09c8d5f228f069ed75a57b786e250737f554dab0d7c59b7a7b1e69ee1c5c
5
5
  SHA512:
6
- metadata.gz: e5515556391d51378e7a483efa7dbc01bbfe899c4040cf25c2b0f51ec15c2c506e61cdb91add0297e2746681dd073fb29e199c9c0c6ef54bc1083326e62940e8
7
- data.tar.gz: 1b42eaaeaa692b2449710cbd291bf432b8ba4e8b82f1754319da81a441bb18bb1a2cd4149f5a5e4e3ac0774b8e7af23d800b5b114e79a7b5e355fa927527e286
6
+ metadata.gz: 6fdcf90496cd4efff95fa6a1ec7ab9729152e17341b24a45d15e299ac356dba96214272033fa3295aaaa69fd59caaa7f60ab416cecc034b02a6ce986f173c822
7
+ data.tar.gz: 39bfe49e50f2ef5ac851459ee4e07634a19b184ed4ed2774b4975fd15cd6fb7c274da1190590e4ab4b0c5b7f0afe7d36b37930daf9291d35861a373c5b4434f4
data/.rubocop.yml CHANGED
@@ -10,6 +10,9 @@ Lint/EmptyClass:
10
10
  Metrics/AbcSize:
11
11
  Max: 25
12
12
 
13
+ Metrics/ClassLength:
14
+ Max: 150
15
+
13
16
  Metrics/MethodLength:
14
17
  Max: 11
15
18
 
@@ -9,6 +9,7 @@ module YahooFinanceClient
9
9
  QUOTE_PATH = "/v7/finance/quote"
10
10
  CACHE_TTL = 300
11
11
  MAX_RETRIES = 2
12
+ BATCH_SIZE = 50
12
13
  AUTH_ERROR_PATTERNS = [/invalid cookie/i, /invalid crumb/i, /unauthorized/i].freeze
13
14
 
14
15
  @cache = {}
@@ -19,8 +20,35 @@ module YahooFinanceClient
19
20
  fetch_from_cache(cache_key) || fetch_and_cache(cache_key, symbol)
20
21
  end
21
22
 
23
+ def get_quotes(symbols)
24
+ return {} if symbols.nil? || symbols.empty?
25
+
26
+ results, uncached = partition_cached(symbols)
27
+ fetch_uncached_quotes(uncached, results)
28
+ results
29
+ end
30
+
22
31
  private
23
32
 
33
+ def partition_cached(symbols)
34
+ results = {}
35
+ uncached = []
36
+ symbols.each do |symbol|
37
+ cached = fetch_from_cache("quote_#{symbol}")
38
+ cached ? results[symbol] = cached : uncached << symbol
39
+ end
40
+ [results, uncached]
41
+ end
42
+
43
+ def fetch_uncached_quotes(uncached, results)
44
+ uncached.each_slice(BATCH_SIZE) do |batch|
45
+ fetch_quotes_data(batch).each do |sym, data|
46
+ store_in_cache("quote_#{sym}", data)
47
+ results[sym] = data
48
+ end
49
+ end
50
+ end
51
+
24
52
  def fetch_and_cache(cache_key, symbol)
25
53
  data = fetch_quote_data(symbol)
26
54
  store_in_cache(cache_key, data) if data[:error].nil?
@@ -39,6 +67,19 @@ module YahooFinanceClient
39
67
  end
40
68
  end
41
69
 
70
+ def fetch_quotes_data(symbols)
71
+ retries = 0
72
+ symbols_param = symbols.join(",")
73
+ begin
74
+ response = make_authenticated_request(symbols_param)
75
+ handle_batch_response(response, symbols)
76
+ rescue AuthenticationError
77
+ retries += 1
78
+ retry if retries <= MAX_RETRIES
79
+ symbols.each_with_object({}) { |s, h| h[s] = { error: "Authentication failed after #{MAX_RETRIES} retries" } }
80
+ end
81
+ end
82
+
42
83
  def make_authenticated_request(symbol)
43
84
  session = Session.instance
44
85
  session.ensure_authenticated
@@ -54,6 +95,20 @@ module YahooFinanceClient
54
95
  response.success? ? parse_response(response.body, symbol) : { error: "Yahoo Finance connection failed" }
55
96
  end
56
97
 
98
+ def handle_batch_response(response, symbols)
99
+ if auth_error?(response)
100
+ Session.instance.invalidate!
101
+ raise AuthenticationError, "Authentication failed"
102
+ end
103
+ unless response.success?
104
+ return symbols.each_with_object({}) do |s, h|
105
+ h[s] = { error: "Yahoo Finance connection failed" }
106
+ end
107
+ end
108
+
109
+ parse_batch_response(response.body, symbols)
110
+ end
111
+
57
112
  def auth_error?(response)
58
113
  response.code == 401 || AUTH_ERROR_PATTERNS.any? { |p| response.body.to_s.match?(p) }
59
114
  end
@@ -63,6 +118,18 @@ module YahooFinanceClient
63
118
  quote ? format_quote(quote) : { error: "No data was found for #{symbol}" }
64
119
  end
65
120
 
121
+ def parse_batch_response(body, symbols)
122
+ results = JSON.parse(body).dig("quoteResponse", "result") || []
123
+ found = results.each_with_object({}) do |quote, hash|
124
+ formatted = format_quote(quote)
125
+ hash[formatted[:symbol]] = formatted
126
+ end
127
+
128
+ symbols.each_with_object(found) do |symbol, hash|
129
+ hash[symbol] ||= { error: "No data was found for #{symbol}" }
130
+ end
131
+ end
132
+
66
133
  def format_quote(quote)
67
134
  price = quote["regularMarketPrice"]
68
135
  dividend = quote["dividendRate"]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module YahooFinanceClient
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yahoo_finance_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francesc Leveque