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 +4 -4
- data/.rubocop.yml +3 -0
- data/lib/yahoo_finance_client/stock.rb +67 -0
- data/lib/yahoo_finance_client/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c3279a92de28429f202ecb5b00115c837826fe910fe7bf27b60d7e2f1772e40c
|
|
4
|
+
data.tar.gz: 28bd09c8d5f228f069ed75a57b786e250737f554dab0d7c59b7a7b1e69ee1c5c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6fdcf90496cd4efff95fa6a1ec7ab9729152e17341b24a45d15e299ac356dba96214272033fa3295aaaa69fd59caaa7f60ab416cecc034b02a6ce986f173c822
|
|
7
|
+
data.tar.gz: 39bfe49e50f2ef5ac851459ee4e07634a19b184ed4ed2774b4975fd15cd6fb7c274da1190590e4ab4b0c5b7f0afe7d36b37930daf9291d35861a373c5b4434f4
|
data/.rubocop.yml
CHANGED
|
@@ -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"]
|