@@ -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
99This 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
1111the data has been retrieved the program determines which stock had the highest year-end
1212closing 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
1820This 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
2224The 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
2931require ' concurrent'
32+ require ' csv'
3033require ' 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]
3846end
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)
4556end
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+
4766symbols = [' AAPL' , ' GOOG' , ' IBM' , ' ORCL' , ' MSFT' ]
4867year = 2008
4968
@@ -72,16 +91,16 @@ val (topStock, highestPrice) = getTopStock(symbols.length)
7291printf(" Top stock of %d is %s closing at price %f\n " , year, topStock, highestPrice)
7392// END:PART1
7493
75- // START:PART2
94+ // START:PART2
7695def 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
87106def 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```
0 commit comments