yahoo_finance_client 0.1.4 → 0.1.6
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/CHANGELOG.md +8 -0
- data/README.md +1 -1
- data/lib/yahoo_finance_client/stock.rb +72 -38
- 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: 88b5aae44ab5936bfba0fec79d7497662637c55bf54965dfe11a20eb1facc762
|
4
|
+
data.tar.gz: 77e5908ab205b355680db2eb81d290284ef98b629bf01b4eff3a27204d657682
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d43ddf2d142468824d65b967b992621d956fc2e3dde5cc109821b1068ab73ebc3201ec5f53973fdcb0a459d941c38df47e2cbab4b002a06a78f4af082bf36456
|
7
|
+
data.tar.gz: 2628a14bc00d61a618d87a929d198749cb0661d69aa6e95ea18e1751b394003c306b68d855ea7ba3b4c6344db33af210eed74bbc4eabe6e673a480aca10874c3
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
A basic client to query Yahoo! Finance API.
|
4
4
|
|
5
|
-
Work in process, it might work, or not
|
5
|
+
Work in process, it might work, or not. It seems that Yahoo! disabled that kind of API access lately.
|
6
6
|
|
7
7
|
It was created to support https://github.com/fleveque/dividend-portfolio pet project.
|
8
8
|
|
@@ -9,55 +9,89 @@ module YahooFinanceClient
|
|
9
9
|
BASE_URL = "https://query1.finance.yahoo.com/v7/finance/quote"
|
10
10
|
COOKIE_URL = "https://fc.yahoo.com"
|
11
11
|
CRUMB_URL = "https://query1.finance.yahoo.com/v1/test/getcrumb"
|
12
|
+
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64)"
|
13
|
+
CACHE_TTL = 300 # Cache time-to-live in seconds (e.g., 5 minutes)
|
12
14
|
|
13
|
-
|
15
|
+
@cache = {}
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
response = HTTParty.get(url, headers: { "User-Agent" => USER_AGENT })
|
17
|
+
class << self
|
18
|
+
def get_quote(symbol)
|
19
|
+
cache_key = "quote_#{symbol}"
|
20
|
+
cached_data = fetch_from_cache(cache_key)
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
return cached_data if cached_data
|
23
|
+
|
24
|
+
data = fetch_quote_data(symbol)
|
25
|
+
store_in_cache(cache_key, data) if data[:error].nil?
|
26
|
+
data
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
-
"#{BASE_URL}?symbols=#{symbol}&crumb=#{crumb}"
|
30
|
-
end
|
29
|
+
private
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
def fetch_quote_data(symbol)
|
32
|
+
cookie = fetch_cookie
|
33
|
+
crumb = fetch_crumb(cookie)
|
34
|
+
url = build_url(symbol, crumb)
|
35
|
+
pp url
|
36
|
+
response = HTTParty.get(url, headers: { "User-Agent" => USER_AGENT })
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
if response.success?
|
39
|
+
parse_response(response.body, symbol)
|
40
|
+
else
|
41
|
+
{ error: "Yahoo Finance connection failed" }
|
42
|
+
end
|
43
|
+
end
|
41
44
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
def build_url(symbol, crumb)
|
46
|
+
"#{BASE_URL}?symbols=#{symbol}&crumb=#{crumb}"
|
47
|
+
end
|
45
48
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
def fetch_cookie
|
50
|
+
response = HTTParty.get(COOKIE_URL, headers: { "User-Agent" => USER_AGENT })
|
51
|
+
response.headers["set-cookie"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def fetch_crumb(cookie)
|
55
|
+
response = HTTParty.get(CRUMB_URL, headers: { "User-Agent" => USER_AGENT, "Cookie" => cookie })
|
56
|
+
response.body
|
50
57
|
end
|
51
|
-
end
|
52
58
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
def parse_response(body, symbol)
|
60
|
+
data = JSON.parse(body)
|
61
|
+
quote = data.dig("quoteResponse", "result", 0)
|
62
|
+
|
63
|
+
if quote
|
64
|
+
format_quote(quote)
|
65
|
+
else
|
66
|
+
{ error: "No data was found for #{symbol}" }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def format_quote(quote)
|
71
|
+
{
|
72
|
+
symbol: quote["symbol"],
|
73
|
+
price: quote["regularMarketPrice"],
|
74
|
+
change: quote["regularMarketChange"],
|
75
|
+
percent_change: quote["regularMarketChangePercent"],
|
76
|
+
volume: quote["regularMarketVolume"]
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def fetch_from_cache(key)
|
81
|
+
cached_entry = @cache[key]
|
82
|
+
return unless cached_entry
|
83
|
+
|
84
|
+
if Time.now - cached_entry[:timestamp] < CACHE_TTL
|
85
|
+
cached_entry[:data]
|
86
|
+
else
|
87
|
+
@cache.delete(key)
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def store_in_cache(key, data)
|
93
|
+
@cache[key] = { data: data, timestamp: Time.now }
|
94
|
+
end
|
61
95
|
end
|
62
96
|
end
|
63
97
|
end
|