Skip to content

Commit 3270635

Browse files
committed
Switched from Yahoo stock API to Alpha Vantage
1 parent 69abe62 commit 3270635

File tree

5 files changed

+125
-48
lines changed

5 files changed

+125
-48
lines changed

docs-source/dataflow_top_stock_calc.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ require 'open-uri'
2222
def get_year_end_closing(symbol, year, api_key)
2323
uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
2424
data = []
25-
URI.open(uri) do |f|
26-
CSV.parse(f, headers: true) do |row|
27-
data << row['close'] if row['timestamp'].include?(year.to_s)
28-
end
25+
csv = URI.parse(uri).read
26+
if csv.include?('call frequency')
27+
return :rate_limit_exceeded
28+
end
29+
CSV.parse(csv, headers: true) do |row|
30+
data << row['close'].to_f if row['timestamp'].include?(year.to_s)
2931
end
3032
price = data.max
31-
price.to_f
32-
[symbol, price.to_f]
33+
[symbol, price]
3334
end
3435

3536
def get_top_stock(symbols, year, timeout = 10)
@@ -38,6 +39,7 @@ def get_top_stock(symbols, year, timeout = 10)
3839

3940
stock_prices = symbols.collect{|symbol| Concurrent::dataflow{ get_year_end_closing(symbol, year, api_key) }}
4041
Concurrent::dataflow(*stock_prices) { |*prices|
42+
next :rate_limit_exceeded if prices.include?(:rate_limit_exceeded)
4143
prices.reduce(['', 0.0]){|highest, price| price.last > highest.last ? price : highest}
4244
}.value(timeout)
4345
end
@@ -51,11 +53,16 @@ def error_message
5153
end
5254

5355
symbols = ['AAPL', 'GOOG', 'IBM', 'ORCL', 'MSFT']
54-
year = 2008
56+
year = 2018
5557

56-
top_stock, highest_price = get_top_stock(symbols, year)
58+
result = get_top_stock(symbols, year)
5759

58-
puts "Top stock of #{year} is #{top_stock} closing at price $#{highest_price}"
60+
if result == :rate_limit_exceeded
61+
puts "API rate limit exceeded"
62+
else
63+
top_stock, highest_price = result
64+
puts "Top stock of #{year} is #{top_stock} closing at price $#{highest_price}"
65+
end
5966
```
6067

6168
#### The Scala Code

docs-source/future.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,42 @@ A fulfilled example:
2121

2222
```ruby
2323
require 'concurrent'
24-
require 'thread' # for Queue
25-
require 'open-uri' # for URI.open(uri)
24+
require 'csv'
25+
require 'open-uri'
2626

2727
class Ticker
28-
def get_year_end_closing(symbol, year)
29-
uri = "http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year}&g=m"
30-
data = URI.open(uri) {|f| f.collect{|line| line.strip } }
31-
data[1].split(',')[4].to_f
28+
def get_year_end_closing(symbol, year, api_key)
29+
uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
30+
data = []
31+
csv = URI.parse(uri).read
32+
if csv.include?('call frequency')
33+
return :rate_limit_exceeded
34+
end
35+
CSV.parse(csv, headers: true) do |row|
36+
data << row['close'].to_f if row['timestamp'].include?(year.to_s)
37+
end
38+
year_end = data.first
39+
year_end
40+
rescue => e
41+
p e
3242
end
3343
end
3444

45+
api_key = ENV['ALPHAVANTAGE_KEY']
46+
abort(error_message) unless api_key
47+
3548
# Future
36-
price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013) }
37-
price.state #=> :pending
38-
price.pending? #=> true
39-
price.value(0) #=> nil (does not block)
49+
price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013, api_key) }
50+
p price.state #=> :pending
51+
p price.pending? #=> true
52+
p price.value(0) #=> nil (does not block)
4053

4154
sleep(1) # do other stuff
4255

43-
price.value #=> 63.65 (after blocking if necessary)
44-
price.state #=> :fulfilled
45-
price.fulfilled? #=> true
46-
price.value #=> 63.65
56+
p price.value #=> 63.65 (after blocking if necessary)
57+
p price.state #=> :fulfilled
58+
p price.fulfilled? #=> true
59+
p price.value #=> 63.65
4760
```
4861

4962

docs-source/future.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
require 'concurrent'
2+
require 'csv'
3+
require 'open-uri'
4+
5+
class Ticker
6+
def get_year_end_closing(symbol, year, api_key)
7+
uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
8+
data = []
9+
csv = URI.parse(uri).read
10+
if csv.include?('call frequency')
11+
return :rate_limit_exceeded
12+
end
13+
CSV.parse(csv, headers: true) do |row|
14+
data << row['close'].to_f if row['timestamp'].include?(year.to_s)
15+
end
16+
year_end = data.first
17+
year_end
18+
rescue => e
19+
p e
20+
end
21+
end
22+
23+
api_key = ENV['ALPHAVANTAGE_KEY']
24+
abort(error_message) unless api_key
25+
26+
# Future
27+
price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013, api_key) }
28+
p price.state #=> :pending
29+
p price.pending? #=> true
30+
p price.value(0) #=> nil (does not block)
31+
32+
sleep(1) # do other stuff
33+
34+
p price.value #=> 63.65 (after blocking if necessary)
35+
p price.state #=> :fulfilled
36+
p price.fulfilled? #=> true
37+
p price.value #=> 63.65

docs-source/top-stock-scala/top-stock.rb

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
def get_year_end_closing(symbol, year, api_key)
66
uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
77
data = []
8-
URI.open(uri) do |f|
9-
CSV.parse(f, headers: true) do |row|
10-
data << row['close'] if row['timestamp'].include?(year.to_s)
11-
end
8+
csv = URI.parse(uri).read
9+
if csv.include?('call frequency')
10+
return :rate_limit_exceeded
11+
end
12+
CSV.parse(csv, headers: true) do |row|
13+
data << row['close'].to_f if row['timestamp'].include?(year.to_s)
1214
end
1315
price = data.max
14-
price.to_f
15-
[symbol, price.to_f]
16+
[symbol, price]
1617
end
1718

1819
def get_top_stock(symbols, year, timeout = 10)
@@ -21,6 +22,7 @@ def get_top_stock(symbols, year, timeout = 10)
2122

2223
stock_prices = symbols.collect{|symbol| Concurrent::dataflow{ get_year_end_closing(symbol, year, api_key) }}
2324
Concurrent::dataflow(*stock_prices) { |*prices|
25+
next :rate_limit_exceeded if prices.include?(:rate_limit_exceeded)
2426
prices.reduce(['', 0.0]){|highest, price| price.last > highest.last ? price : highest}
2527
}.value(timeout)
2628
end
@@ -34,8 +36,13 @@ def error_message
3436
end
3537

3638
symbols = ['AAPL', 'GOOG', 'IBM', 'ORCL', 'MSFT']
37-
year = 2008
39+
year = 2018
3840

39-
top_stock, highest_price = get_top_stock(symbols, year)
41+
result = get_top_stock(symbols, year)
4042

41-
puts "Top stock of #{year} is #{top_stock} closing at price $#{highest_price}"
43+
if result == :rate_limit_exceeded
44+
puts "API rate limit exceeded"
45+
else
46+
top_stock, highest_price = result
47+
puts "Top stock of #{year} is #{top_stock} closing at price $#{highest_price}"
48+
end

lib/concurrent-ruby/concurrent/scheduled_task.rb

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,29 +58,42 @@ module Concurrent
5858
# @example Basic usage
5959
#
6060
# require 'concurrent'
61-
# require 'thread' # for Queue
62-
# require 'open-uri' # for URI.open(uri)
61+
# require 'csv'
62+
# require 'open-uri'
6363
#
6464
# class Ticker
65-
# def get_year_end_closing(symbol, year)
66-
# uri = "http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year}&g=m"
67-
# data = URI.open(uri) {|f| f.collect{|line| line.strip } }
68-
# data[1].split(',')[4].to_f
69-
# end
65+
# def get_year_end_closing(symbol, year, api_key)
66+
# uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
67+
# data = []
68+
# csv = URI.parse(uri).read
69+
# if csv.include?('call frequency')
70+
# return :rate_limit_exceeded
71+
# end
72+
# CSV.parse(csv, headers: true) do |row|
73+
# data << row['close'].to_f if row['timestamp'].include?(year.to_s)
74+
# end
75+
# year_end = data.first
76+
# year_end
77+
# rescue => e
78+
# p e
79+
# end
7080
# end
7181
#
82+
# api_key = ENV['ALPHAVANTAGE_KEY']
83+
# abort(error_message) unless api_key
84+
#
7285
# # Future
73-
# price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013) }
86+
# price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013, api_key) }
7487
# price.state #=> :pending
75-
# sleep(1) # do other stuff
76-
# price.value #=> 63.65
77-
# price.state #=> :fulfilled
88+
# price.pending? #=> true
89+
# price.value(0) #=> nil (does not block)
7890
#
79-
# # ScheduledTask
80-
# task = Concurrent::ScheduledTask.execute(2){ Ticker.new.get_year_end_closing('INTC', 2013) }
81-
# task.state #=> :pending
82-
# sleep(3) # do other stuff
83-
# task.value #=> 25.96
91+
# sleep(1) # do other stuff
92+
#
93+
# price.value #=> 63.65 (after blocking if necessary)
94+
# price.state #=> :fulfilled
95+
# price.fulfilled? #=> true
96+
# price.value #=> 63.65
8497
#
8598
# @example Successful task execution
8699
#

0 commit comments

Comments
 (0)