Skip to content

Commit 9da7608

Browse files
committed
use alpha vantage to extract stock information
1 parent 66d8d91 commit 9da7608

File tree

3 files changed

+90
-36
lines changed

3 files changed

+90
-36
lines changed

doc/dataflow_top_stock_calc.md

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,51 @@ It as an example from chapter 1 "Introduction", section 1.2 "What's Scala?" of t
55
## What It Does
66

77
This program takes a list of one or more stock symbols and a year. It then concurrently
8-
obtains the relevant stock data from Yahoo's iChart service for each symbol. Once all
8+
obtains the relevant stock data from Alpha Vantage service for each symbol. Once all
99
the data has been retrieved the program determines which stock had the highest year-end
1010
closing price.
1111

12-
* A sample of the data can be downloaded [here](http://ichart.finance.yahoo.com/table.csv?s=AAPL&a=11&b=01&c=2008&d=11&e=31&f=2008&g=m).
12+
To use this example you need to obtain a free api key in [AlphaVantage](https://www.alphavantage.co/support/#api-key).
13+
1314

1415
#### The Ruby Code
1516

1617
```ruby
1718
require 'concurrent'
19+
require 'csv'
1820
require 'open-uri'
1921

20-
def get_year_end_closing(symbol, year)
21-
uri = "http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year}&g=m"
22-
data = open(uri) {|f| f.collect{|line| line.strip } }
23-
price = data[1].split(',')[4]
22+
def get_year_end_closing(symbol, year, api_key)
23+
uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
24+
data = []
25+
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
29+
end
30+
price = data.max
2431
price.to_f
2532
[symbol, price.to_f]
2633
end
2734

28-
def get_top_stock(symbols, year, timeout = 5)
29-
stock_prices = symbols.collect{|symbol| Concurrent::dataflow{ get_year_end_closing(symbol, year) }}
35+
def get_top_stock(symbols, year, timeout = 10)
36+
api_key = ENV['ALPHAVANTAGE_KEY']
37+
abort(error_message) unless api_key
38+
39+
stock_prices = symbols.collect{|symbol| Concurrent::dataflow{ get_year_end_closing(symbol, year, api_key) }}
3040
Concurrent::dataflow(*stock_prices) { |*prices|
3141
prices.reduce(['', 0.0]){|highest, price| price.last > highest.last ? price : highest}
3242
}.value(timeout)
3343
end
3444

45+
def error_message
46+
<<~EOF
47+
PLEASE provide a Alpha Vantage api key for the example to work
48+
usage:
49+
ALPHAVANTAGE_KEY=YOUR_API_KEY bundle exec ruby top-stock-scala/top-stock.rb
50+
EOF
51+
end
52+
3553
symbols = ['AAPL', 'GOOG', 'IBM', 'ORCL', 'MSFT']
3654
year = 2008
3755

@@ -60,16 +78,16 @@ val (topStock, highestPrice) = getTopStock(symbols.length)
6078
printf("Top stock of %d is %s closing at price %f\n", year, topStock, highestPrice)
6179
//END:PART1
6280

63-
//START:PART2
81+
//START:PART2
6482
def getYearEndClosing(symbol : String, year : Int) = {
6583
val url = "http://ichart.finance.yahoo.com/table.csv?s=" +
6684
symbol + "&a=11&b=01&c=" + year + "&d=11&e=31&f=" + year + "&g=m"
67-
85+
6886
val data = io.Source.fromURL(url).mkString
69-
val price = data.split("\n")(1).split(",")(4).toDouble
87+
val price = data.split("\n")(1).split(",")(4).toDouble
7088
(symbol, price)
71-
}
72-
//END:PART2
89+
}
90+
//END:PART2
7391

7492
//START:PART3
7593
def getTopStock(count : Int) : (String, Double) = {
@@ -79,6 +97,6 @@ def getTopStock(count : Int) : (String, Double) = {
7997
if (price > previousHigh._2) (symbol, price) else previousHigh
8098
}
8199
}
82-
}
100+
}
83101
//START:PART3
84102
```

doc/top-stock-scala/README.md

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,62 @@ It as an example from chapter 1 "Introduction", section 1.2 "What's Scala?" of t
77
## What It Does
88

99
This program takes a list of one or more stock symbols and a year. It then concurrently
10-
obtains the relevant stock data from Yahoo's iChart service for each symbol. Once all
10+
obtains the relevant stock data from Alpha Vantage service for each symbol. Once all
1111
the data has been retrieved the program determines which stock had the highest year-end
1212
closing price.
1313

14-
http://ichart.finance.yahoo.com/table.csv?s=AAPL&a=11&b=01&c=2008&d=11&e=31&f=2008&g=m
14+
To use this example you need to obtain a free api key in [AlphaVantage](https://www.alphavantage.co/support/#api-key).
15+
16+
https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=AAPL&apikey=1234567&datatype=csv"
1517

1618
### Run It
1719

1820
This example can be run from the console. From the root of the repo run:
1921

20-
> $ bundle exec ruby top-stock-scala/top-stock.rb
22+
> $ ALPHAVANTAGE_KEY=YOUR_API_KEY bundle exec ruby top-stock-scala/top-stock.rb
2123
2224
The output should be:
2325

24-
> Top stock of 2008 is GOOG closing at price $307.65
26+
> Top stock of 2008 is GOOG closing at price $307.65
2527
2628
#### The Ruby Code
2729

2830
```ruby
2931
require 'concurrent'
32+
require 'csv'
3033
require 'open-uri'
3134

32-
def get_year_end_closing(symbol, year)
33-
uri = "http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year}&g=m"
34-
data = open(uri) {|f| f.collect{|line| line.strip } }
35-
price = data[1].split(',')[4]
35+
def get_year_end_closing(symbol, year, api_key)
36+
uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
37+
data = []
38+
open(uri) do |f|
39+
CSV.parse(f, headers: true) do |row|
40+
data << row['close'] if row['timestamp'].include?(year.to_s)
41+
end
42+
end
43+
price = data.max
3644
price.to_f
3745
[symbol, price.to_f]
3846
end
3947

40-
def get_top_stock(symbols, year, timeout = 5)
41-
stock_prices = symbols.collect{|symbol| Concurrent::dataflow{ get_year_end_closing(symbol, year) }}
48+
def get_top_stock(symbols, year, timeout = 10)
49+
api_key = ENV['ALPHAVANTAGE_KEY']
50+
abort(error_message) unless api_key
51+
52+
stock_prices = symbols.collect{|symbol| Concurrent::dataflow{ get_year_end_closing(symbol, year, api_key) }}
4253
Concurrent::dataflow(*stock_prices) { |*prices|
4354
prices.reduce(['', 0.0]){|highest, price| price.last > highest.last ? price : highest}
4455
}.value(timeout)
4556
end
4657

58+
def error_message
59+
<<~EOF
60+
PLEASE provide a Alpha Vantage api key for the example to work
61+
usage:
62+
ALPHAVANTAGE_KEY=YOUR_API_KEY bundle exec ruby top-stock-scala/top-stock.rb
63+
EOF
64+
end
65+
4766
symbols = ['AAPL', 'GOOG', 'IBM', 'ORCL', 'MSFT']
4867
year = 2008
4968

@@ -72,16 +91,16 @@ val (topStock, highestPrice) = getTopStock(symbols.length)
7291
printf("Top stock of %d is %s closing at price %f\n", year, topStock, highestPrice)
7392
//END:PART1
7493

75-
//START:PART2
94+
//START:PART2
7695
def getYearEndClosing(symbol : String, year : Int) = {
7796
val url = "http://ichart.finance.yahoo.com/table.csv?s=" +
7897
symbol + "&a=11&b=01&c=" + year + "&d=11&e=31&f=" + year + "&g=m"
79-
98+
8099
val data = io.Source.fromURL(url).mkString
81-
val price = data.split("\n")(1).split(",")(4).toDouble
100+
val price = data.split("\n")(1).split(",")(4).toDouble
82101
(symbol, price)
83-
}
84-
//END:PART2
102+
}
103+
//END:PART2
85104

86105
//START:PART3
87106
def getTopStock(count : Int) : (String, Double) = {
@@ -91,6 +110,6 @@ def getTopStock(count : Int) : (String, Double) = {
91110
if (price > previousHigh._2) (symbol, price) else previousHigh
92111
}
93112
}
94-
}
113+
}
95114
//END:PART3
96115
```

doc/top-stock-scala/top-stock.rb

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
11
require 'concurrent'
2+
require 'csv'
23
require 'open-uri'
34

4-
def get_year_end_closing(symbol, year)
5-
uri = "http://ichart.finance.yahoo.com/table.csv?s=#{symbol}&a=11&b=01&c=#{year}&d=11&e=31&f=#{year}&g=m"
6-
data = open(uri) {|f| f.collect{|line| line.strip } }
7-
price = data[1].split(',')[4]
5+
def get_year_end_closing(symbol, year, api_key)
6+
uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv"
7+
data = []
8+
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
12+
end
13+
price = data.max
814
price.to_f
915
[symbol, price.to_f]
1016
end
1117

12-
def get_top_stock(symbols, year, timeout = 5)
13-
stock_prices = symbols.collect{|symbol| Concurrent::dataflow{ get_year_end_closing(symbol, year) }}
18+
def get_top_stock(symbols, year, timeout = 10)
19+
api_key = ENV['ALPHAVANTAGE_KEY']
20+
abort(error_message) unless api_key
21+
22+
stock_prices = symbols.collect{|symbol| Concurrent::dataflow{ get_year_end_closing(symbol, year, api_key) }}
1423
Concurrent::dataflow(*stock_prices) { |*prices|
1524
prices.reduce(['', 0.0]){|highest, price| price.last > highest.last ? price : highest}
1625
}.value(timeout)
1726
end
1827

28+
def error_message
29+
<<~EOF
30+
PLEASE provide a Alpha Vantage api key for the example to work
31+
usage:
32+
ALPHAVANTAGE_KEY=YOUR_API_KEY bundle exec ruby top-stock-scala/top-stock.rb
33+
EOF
34+
end
35+
1936
symbols = ['AAPL', 'GOOG', 'IBM', 'ORCL', 'MSFT']
2037
year = 2008
2138

0 commit comments

Comments
 (0)