@@ -7,43 +7,62 @@ It as an example from chapter 1 "Introduction", section 1.2 "What's Scala?" of t
7
7
## What It Does
8
8
9
9
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
11
11
the data has been retrieved the program determines which stock had the highest year-end
12
12
closing price.
13
13
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 "
15
17
16
18
### Run It
17
19
18
20
This example can be run from the console. From the root of the repo run:
19
21
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
21
23
22
24
The output should be:
23
25
24
- > Top stock of 2008 is GOOG closing at price $307.65
26
+ > Top stock of 2008 is GOOG closing at price $307.65
25
27
26
28
#### The Ruby Code
27
29
28
30
``` ruby
29
31
require ' concurrent'
32
+ require ' csv'
30
33
require ' open-uri'
31
34
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
36
44
price.to_f
37
45
[symbol, price.to_f]
38
46
end
39
47
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) }}
42
53
Concurrent ::dataflow(* stock_prices) { |* prices |
43
54
prices.reduce([' ' , 0.0 ]){|highest , price | price.last > highest.last ? price : highest}
44
55
}.value(timeout)
45
56
end
46
57
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
+
47
66
symbols = [' AAPL' , ' GOOG' , ' IBM' , ' ORCL' , ' MSFT' ]
48
67
year = 2008
49
68
@@ -72,16 +91,16 @@ val (topStock, highestPrice) = getTopStock(symbols.length)
72
91
printf(" Top stock of %d is %s closing at price %f\n " , year, topStock, highestPrice)
73
92
// END:PART1
74
93
75
- // START:PART2
94
+ // START:PART2
76
95
def getYearEndClosing (symbol : String , year : Int ) = {
77
96
val url = " http://ichart.finance.yahoo.com/table.csv?s=" +
78
97
symbol + " &a=11&b=01&c=" + year + " &d=11&e=31&f=" + year + " &g=m"
79
-
98
+
80
99
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
82
101
(symbol, price)
83
- }
84
- // END:PART2
102
+ }
103
+ // END:PART2
85
104
86
105
// START:PART3
87
106
def getTopStock (count : Int ) : (String , Double ) = {
@@ -91,6 +110,6 @@ def getTopStock(count : Int) : (String, Double) = {
91
110
if (price > previousHigh._2) (symbol, price) else previousHigh
92
111
}
93
112
}
94
- }
113
+ }
95
114
// END:PART3
96
115
```
0 commit comments