alphavantagerb 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/AlphavantageRB.gemspec +19 -0
- data/Gemfile +10 -0
- data/LICENSE.md +21 -0
- data/README.md +778 -0
- data/lib/Client.rb +70 -0
- data/lib/Crypto.rb +26 -0
- data/lib/Crypto_Timeseries.rb +67 -0
- data/lib/Errors.rb +9 -0
- data/lib/Exchange.rb +23 -0
- data/lib/Indicator.rb +135 -0
- data/lib/Sector.rb +34 -0
- data/lib/Stock.rb +49 -0
- data/lib/Timeseries.rb +76 -0
- data/lib/alphavantagerb.rb +13 -0
- data/lib/helper_function.rb +72 -0
- data/spec/config.yml +2 -0
- data/spec/lib/1.0.0/client.rb +44 -0
- data/spec/lib/1.0.0/crypto.rb +36 -0
- data/spec/lib/1.0.0/crypto_timeseries.rb +59 -0
- data/spec/lib/1.0.0/exchange.rb +49 -0
- data/spec/lib/1.0.0/indicator.rb +719 -0
- data/spec/lib/1.0.0/sector.rb +44 -0
- data/spec/lib/1.0.0/stock.rb +42 -0
- data/spec/lib/1.0.0/timeseries.rb +101 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/test_all.rb +8 -0
- metadata +98 -0
data/lib/Client.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Alphavantage
|
2
|
+
class Client
|
3
|
+
include HelperFunctions
|
4
|
+
|
5
|
+
def initialize key:, verbose: false
|
6
|
+
check_argument([true, false], verbose, "verbose")
|
7
|
+
@apikey = key
|
8
|
+
@base_uri = 'https://www.alphavantage.co'
|
9
|
+
@verbose = verbose
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :verbose
|
13
|
+
|
14
|
+
def verbose=(verbose)
|
15
|
+
check_argument([true, false], verbose, "verbose")
|
16
|
+
@verbose = verbose
|
17
|
+
end
|
18
|
+
|
19
|
+
def request(url)
|
20
|
+
send_url = "#{@base_uri}/query?#{url}&apikey=#{@apikey}"
|
21
|
+
puts "\n#{send_url}\n" if @verbose
|
22
|
+
begin
|
23
|
+
response = HTTParty.get(send_url)
|
24
|
+
rescue Exception => e
|
25
|
+
raise Alphavantage::Error.new message: "Failed request: #{e.message}"
|
26
|
+
end
|
27
|
+
data = response.body
|
28
|
+
begin
|
29
|
+
data = JSON.parse(data)
|
30
|
+
rescue Exception => e
|
31
|
+
raise Alphavantage::Error.new message: "Parsing failed",
|
32
|
+
data: data
|
33
|
+
end
|
34
|
+
if !data["Error Message"].nil?
|
35
|
+
raise Alphavantage::Error.new message: data["Error Message"], data: data
|
36
|
+
elsif !data["Information"].nil?
|
37
|
+
raise Alphavantage::Error.new message: data["Information"], data: data
|
38
|
+
end
|
39
|
+
return data
|
40
|
+
end
|
41
|
+
|
42
|
+
def download(url, file)
|
43
|
+
send_url = "#{@base_uri}/query?#{url}&datatype=csv&apikey=#{@apikey}"
|
44
|
+
begin
|
45
|
+
puts send_url if @verbose
|
46
|
+
uri = URI.parse(send_url)
|
47
|
+
uri.open{|csv| IO.copy_stream(csv, file)}
|
48
|
+
rescue Exception => e
|
49
|
+
raise Alphavantage::Error.new message: "Failed to save the CSV file: #{e.message}"
|
50
|
+
end
|
51
|
+
return "CSV saved in #{file}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def stock(symbol:, datatype: "json")
|
55
|
+
Alphavantage::Stock.new symbol: symbol, key: self, datatype: datatype
|
56
|
+
end
|
57
|
+
|
58
|
+
def exchange(from:, to:)
|
59
|
+
Alphavantage::Exchange.new from: from, to: to, key: self
|
60
|
+
end
|
61
|
+
|
62
|
+
def crypto(symbol:, market:, datatype: "json")
|
63
|
+
Alphavantage::Crypto.new symbol: symbol, key: self, datatype: datatype, market: market
|
64
|
+
end
|
65
|
+
|
66
|
+
def sector
|
67
|
+
Alphavantage::Sector.new key: self
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/Crypto.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Alphavantage
|
2
|
+
class Crypto
|
3
|
+
include HelperFunctions
|
4
|
+
|
5
|
+
def initialize symbol:, datatype: "json", key:, verbose: false, market:
|
6
|
+
check_argument([true, false], verbose, "verbose")
|
7
|
+
@client = return_client(key, verbose)
|
8
|
+
@symbol = symbol
|
9
|
+
@market = market
|
10
|
+
@datatype = datatype
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :symbol, :market
|
14
|
+
attr_reader :datatype
|
15
|
+
|
16
|
+
def datatype=(datatype)
|
17
|
+
check_argument(["json", "csv"], datatype, "datatype")
|
18
|
+
@datatype = datatype
|
19
|
+
end
|
20
|
+
|
21
|
+
def timeseries type: "intraday", market: @market, file: nil, datatype: @datatype
|
22
|
+
Alphavantage::Crypto_Timeseries.new type: type, market: market,
|
23
|
+
symbol: @symbol, datatype: datatype, file: file, key: @client
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Alphavantage
|
2
|
+
class Crypto_Timeseries
|
3
|
+
include HelperFunctions
|
4
|
+
|
5
|
+
def initialize type: "intraday", market:, symbol:, datatype: "json", file: nil,
|
6
|
+
key:, verbose: false
|
7
|
+
check_argument([true, false], verbose, "verbose")
|
8
|
+
@client = return_client(key, verbose)
|
9
|
+
check_argument(["json", "csv"], datatype, "datatype")
|
10
|
+
if datatype == "csv" && file.nil?
|
11
|
+
raise Alphavantage::Error.new message: "No file specified where to save the CSV data"
|
12
|
+
elsif datatype != "csv" && !file.nil?
|
13
|
+
raise Alphavantage::Error.new message: "Hash error: No file necessary"
|
14
|
+
end
|
15
|
+
|
16
|
+
@selected_time_series = which_series(type)
|
17
|
+
url = "function=#{@selected_time_series}&symbol=#{symbol}&market=#{market}"
|
18
|
+
return @client.download(url, file) if datatype == "csv"
|
19
|
+
@hash = @client.request(url)
|
20
|
+
metadata = @hash.dig("Meta Data") || {}
|
21
|
+
metadata.each do |key, val|
|
22
|
+
key_sym = key.downcase.gsub(/[0-9.]/, "").lstrip.gsub(" ", "_").to_sym
|
23
|
+
define_singleton_method(key_sym) do
|
24
|
+
return val
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@open = []; @high = []; @low = []; @close = []; @volume = [];
|
28
|
+
@open_usd = []; @high_usd = []; @low_usd = []; @close_usd = [];
|
29
|
+
@market_cap_usd = [];
|
30
|
+
|
31
|
+
begin
|
32
|
+
time_series = @hash.find{|key, val| key.include?("Time Series")}[1]
|
33
|
+
rescue Exception => e
|
34
|
+
raise Alphavantage::Error.new message: "No Time Series found: #{e.message}",
|
35
|
+
data: @hash
|
36
|
+
end
|
37
|
+
|
38
|
+
series = {}
|
39
|
+
convert_key = {}
|
40
|
+
time_series.values[0].keys.each do |key|
|
41
|
+
key_sym = recreate_metadata_key(key)
|
42
|
+
series[key_sym] = []
|
43
|
+
convert_key[key] = key_sym
|
44
|
+
end
|
45
|
+
time_series.each do |time, ts_hash|
|
46
|
+
ts_hash.each do |key, value|
|
47
|
+
series[convert_key[key]] << [time, value]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
series.keys.each do |key_sym|
|
51
|
+
define_singleton_method(key_sym) do |*args|
|
52
|
+
args ||= []
|
53
|
+
return return_series(series[key_sym], args[0])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
attr_reader :hash
|
59
|
+
|
60
|
+
def which_series(type)
|
61
|
+
check_argument(["intraday", "daily", "weekly", "monthly"], type, "type")
|
62
|
+
series = "DIGITAL_CURRENCY_"
|
63
|
+
series += type.upcase
|
64
|
+
return series
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/Errors.rb
ADDED
data/lib/Exchange.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Alphavantage
|
2
|
+
class Exchange
|
3
|
+
include HelperFunctions
|
4
|
+
|
5
|
+
def initialize from:, to:, key:, verbose: false
|
6
|
+
check_argument([true, false], verbose, "verbose")
|
7
|
+
@client = return_client(key, verbose)
|
8
|
+
@from = from
|
9
|
+
@to = to
|
10
|
+
@hash = @client.request("function=CURRENCY_EXCHANGE_RATE&from_currency=#{@from}&to_currency=#{@to}")
|
11
|
+
hash = @hash["Realtime Currency Exchange Rate"]
|
12
|
+
hash.each do |key, val|
|
13
|
+
key_sym = recreate_metadata_key(key)
|
14
|
+
define_singleton_method(key_sym) do
|
15
|
+
return val
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :hash
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/Indicator.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
module Alphavantage
|
2
|
+
class Indicator
|
3
|
+
include HelperFunctions
|
4
|
+
|
5
|
+
def initialize function:, symbol:, interval: "daily", time_period: "60",
|
6
|
+
series_type: "close", fastlimit: "0.01", slowlimit: "0.01",
|
7
|
+
fastperiod: "12", slowperiod: "26", signalperiod: "9",
|
8
|
+
fastmatype: "0", slowmatype: "0", signalmatype: "0",
|
9
|
+
fastkperiod: "5", slowkperiod: "3", slowdperiod: "3",
|
10
|
+
slowkmatype: "0", slowdmatype: "0", fastdperiod: "3",
|
11
|
+
fastdmatype: "0", matype: "0", timeperiod1: "7", timeperiod2: "14",
|
12
|
+
timeperiod3: "28", nbdevup: "2", nbdevdn: "2", acceleration: "0.01",
|
13
|
+
maximum: "0.20", key:, verbose: false
|
14
|
+
check_argument([true, false], verbose, "verbose")
|
15
|
+
@client = return_client(key, verbose)
|
16
|
+
check_argument(["SMA", "EMA", "WMA", "DEMA", "TEMA", "TRIMA", "KAMA", "T3",
|
17
|
+
"RSI","MAMA", "MACD", "MACDEXT", "STOCH", "STOCHF", "STOCHRSI", "WILLR",
|
18
|
+
"ADX", "ADXR", "APO", "PPO", "MOM", "BOP", "CCI", "CMO", "ROC", "ROCR",
|
19
|
+
"AROON", "AROONOSC", "MFI", "TRIX", "ULTOSC", "DX", "MINUS_DI",
|
20
|
+
"PLUS_DI", "MINUS_DM", "PLUS_DM", "BBANDS", "MIDPOINT", "MIDPRICE",
|
21
|
+
"SAR", "TRANGE", "ATR", "NATR", "AD", "ADOSC", "OBV", "HT_SINE",
|
22
|
+
"HT_TRENDLINE", "HT_TRENDMODE", "HT_DCPERIOD", "HT_DCPHASE",
|
23
|
+
"HT_PHASOR"], function, "function")
|
24
|
+
url = "function=#{function}&symbol=#{symbol}"
|
25
|
+
|
26
|
+
if ["SMA", "EMA", "WMA", "DEMA", "TEMA", "TRIMA", "KAMA", "T3", "RSI",
|
27
|
+
"MAMA", "MACD", "MACDEXT", "STOCH", "STOCHF", "STOCHRSI", "WILLR",
|
28
|
+
"ADX", "ADXR", "APO", "PPO", "MOM", "BOP", "CCI", "CMO", "ROC", "ROCR",
|
29
|
+
"AROON", "AROONOSC", "MFI", "TRIX", "ULTOSC", "DX", "MINUS_DI",
|
30
|
+
"PLUS_DI", "MINUS_DM", "PLUS_DM", "BBANDS", "MIDPOINT", "MIDPRICE",
|
31
|
+
"SAR", "TRANGE", "ATR", "NATR", "AD", "ADOSC", "OBV", "HT_SINE",
|
32
|
+
"HT_TRENDLINE", "HT_TRENDMODE", "HT_DCPERIOD", "HT_DCPHASE",
|
33
|
+
"HT_PHASOR"].include? function
|
34
|
+
check_argument(["1min", "5min", "15min", "30min", "60min", "daily", "weekly", "monthly"], interval, "interval")
|
35
|
+
url += "&interval=#{interval}"
|
36
|
+
end
|
37
|
+
if ["SMA", "EMA", "WMA", "DEMA", "TEMA", "TRIMA", "KAMA", "T3", "RSI",
|
38
|
+
"STOCHRSI", "WILLR", "ADX", "ADXR", "MOM", "CCI", "CMO", "ROC", "ROCR",
|
39
|
+
"AROON", "AROONOSC", "MFI", "TRIX", "DX", "MINUS_DI", "PLUS_DI",
|
40
|
+
"MINUS_DM", "PLUS_DM", "BBANDS", "MIDPOINT", "MIDPRICE", "ATR",
|
41
|
+
"NATR"].include? function
|
42
|
+
url += return_int_val(time_period, "time_period", "integer")
|
43
|
+
end
|
44
|
+
if ["SMA", "EMA", "WMA", "DEMA", "TEMA", "TRIMA", "KAMA", "T3", "RSI",
|
45
|
+
"MAMA", "MACD", "MACDEXT", "STOCHRSI", "APO", "PPO", "MOM", "ROC",
|
46
|
+
"ROCR", "TRIX", "BBANDS", "MIDPOINT", "HT_SINE", "HT_TRENDLINE",
|
47
|
+
"HT_TRENDMODE", "HT_DCPERIOD", "HT_DCPHASE", "HT_PHASOR", "CMO"].include? function
|
48
|
+
check_argument(["close", "open", "high", "low"], series_type, "series_type")
|
49
|
+
url += "&series_type=#{series_type}"
|
50
|
+
end
|
51
|
+
if ["MAMA"].include? function
|
52
|
+
url += return_int_val(fastlimit, "fastlimit", "float")
|
53
|
+
url += return_int_val(slowlimit, "slowlimit", "float")
|
54
|
+
end
|
55
|
+
if ["MACD", "MACDEXT", "APO", "PPO", "ADOSC"].include? function
|
56
|
+
url += return_int_val(fastperiod, "fastperiod", "integer")
|
57
|
+
url += return_int_val(slowperiod, "slowperiod", "integer")
|
58
|
+
end
|
59
|
+
if ["MACD", "MACDEXT"].include? function
|
60
|
+
url += return_int_val(signalperiod, "signalperiod", "integer")
|
61
|
+
end
|
62
|
+
if ["MACDEXT"].include? function
|
63
|
+
url += return_matype(fastmatype, "fastmatype")
|
64
|
+
url += return_matype(slowmatype, "slowmatype")
|
65
|
+
url += return_matype(signalmatype, "signalmatype")
|
66
|
+
end
|
67
|
+
if ["STOCH", "STOCHF", "STOCHRSI"].include? function
|
68
|
+
url += return_int_val(fastkperiod, "fastkperiod", "integer")
|
69
|
+
url += return_int_val(fastdperiod, "fastdperiod", "integer")
|
70
|
+
end
|
71
|
+
if ["STOCH"].include? function
|
72
|
+
url += return_int_val(slowkperiod, "slowkperiod", "integer")
|
73
|
+
url += return_int_val(signalperiod, "signalperiod", "integer")
|
74
|
+
url += return_matype(slowkmatype, "slowkmatype")
|
75
|
+
url += return_matype(slowdmatype, "slowdmatype")
|
76
|
+
end
|
77
|
+
if ["STOCH", "STOCHF", "STOCHRSI"].include? function
|
78
|
+
url += return_matype(fastdmatype, "fastdmatype")
|
79
|
+
end
|
80
|
+
if ["APO", "PPO", "BBANDS"].include? function
|
81
|
+
url += return_matype(matype, "matype")
|
82
|
+
end
|
83
|
+
if ["ULTOSC"].include? function
|
84
|
+
url += return_int_val(timeperiod1, "timeperiod1", "integer")
|
85
|
+
url += return_int_val(timeperiod2, "timeperiod2", "integer")
|
86
|
+
url += return_int_val(timeperiod3, "timeperiod3", "integer")
|
87
|
+
end
|
88
|
+
if ["BBANDS"].include? function
|
89
|
+
url += return_int_val(nbdevup, "nbdevup", "integer")
|
90
|
+
url += return_int_val(nbdevdn, "nbdevdn", "integer")
|
91
|
+
end
|
92
|
+
if ["SAR"].include? function
|
93
|
+
url += return_int_val(acceleration, "acceleration", "float")
|
94
|
+
url += return_int_val(maximum, "maximum", "float")
|
95
|
+
end
|
96
|
+
|
97
|
+
@hash = @client.request(url)
|
98
|
+
metadata = @hash.dig("Meta Data") || {}
|
99
|
+
metadata.each do |key, val|
|
100
|
+
key_sym = recreate_metadata_key(key)
|
101
|
+
define_singleton_method(key_sym) do
|
102
|
+
return val
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
begin
|
107
|
+
time_series = @hash.find{|key, val| key.include?("Technical Analysis")}[1]
|
108
|
+
rescue Exception => e
|
109
|
+
raise Alphavantage::Error.new message: "No Time Series found: #{e.message}",
|
110
|
+
data: @hash
|
111
|
+
end
|
112
|
+
|
113
|
+
series = {}
|
114
|
+
convert_key = {}
|
115
|
+
time_series.values[0].keys.each do |key|
|
116
|
+
key_sym = key.downcase.gsub(/[.\/]/, "").lstrip.gsub(" ", "_").to_sym
|
117
|
+
series[key_sym] = []
|
118
|
+
convert_key[key] = key_sym
|
119
|
+
end
|
120
|
+
time_series.each do |time, ts_hash|
|
121
|
+
ts_hash.each do |key, value|
|
122
|
+
series[convert_key[key]] << [time, value]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
series.keys.each do |key_sym|
|
126
|
+
define_singleton_method(key_sym) do |*args|
|
127
|
+
args ||= []
|
128
|
+
return return_series(series[key_sym], args[0])
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
attr_reader :hash
|
134
|
+
end
|
135
|
+
end
|
data/lib/Sector.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Alphavantage
|
2
|
+
class Sector
|
3
|
+
include HelperFunctions
|
4
|
+
|
5
|
+
def initialize key:, verbose: false
|
6
|
+
check_argument([true, false], verbose, "verbose")
|
7
|
+
@client = return_client(key, verbose)
|
8
|
+
@hash = @client.request("function=SECTOR")
|
9
|
+
metadata = @hash.dig("Meta Data") || {}
|
10
|
+
metadata.each do |key, val|
|
11
|
+
key_sym = key.downcase.gsub(/[0-9.]/, "").lstrip.gsub(" ", "_").to_sym
|
12
|
+
define_singleton_method(key_sym) do
|
13
|
+
return val
|
14
|
+
end
|
15
|
+
end
|
16
|
+
@hash.each do |key, val|
|
17
|
+
next if key == "Meta Data"
|
18
|
+
key = key.split(":")[1].lstrip
|
19
|
+
key = key.split(" ")
|
20
|
+
if key[0].to_i != 0
|
21
|
+
key[0] = key[0].to_i.humanize
|
22
|
+
end
|
23
|
+
key.delete_if{|k| k.include?("(")}
|
24
|
+
key = key.join("_")
|
25
|
+
key_sym = key.downcase.gsub("-", "_").to_sym
|
26
|
+
define_singleton_method(key_sym) do
|
27
|
+
return val
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :hash
|
33
|
+
end
|
34
|
+
end
|
data/lib/Stock.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Alphavantage
|
2
|
+
class Stock
|
3
|
+
include HelperFunctions
|
4
|
+
|
5
|
+
def initialize symbol:, datatype: "json", key:, verbose: false
|
6
|
+
check_argument([true, false], verbose, "verbose")
|
7
|
+
@client = return_client(key, verbose)
|
8
|
+
@symbol = symbol
|
9
|
+
@datatype = datatype
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :symbol
|
13
|
+
attr_reader :datatype
|
14
|
+
|
15
|
+
def datatype=(datatype)
|
16
|
+
check_argument(["json", "csv"], datatype, "datatype")
|
17
|
+
@datatype = datatype
|
18
|
+
end
|
19
|
+
|
20
|
+
def timeseries type: "daily", interval: nil, outputsize: "compact",
|
21
|
+
file: nil, datatype: @datatype, adjusted: false
|
22
|
+
Alphavantage::Timeseries.new type: type, interval: interval,
|
23
|
+
outputsize: outputsize, symbol: @symbol, datatype: datatype, file: file,
|
24
|
+
key: @client, adjusted: adjusted
|
25
|
+
end
|
26
|
+
|
27
|
+
def indicator function:, interval: "daily", time_period: "60",
|
28
|
+
series_type: "close", fastlimit: "0.01", slowlimit: "0.01",
|
29
|
+
fastperiod: "12", slowperiod: "26", signalperiod: "9",
|
30
|
+
fastmatype: "0", slowmatype: "0", signalmatype: "0",
|
31
|
+
fastkperiod: "5", slowkperiod: "3", slowdperiod: "3",
|
32
|
+
slowkmatype: "0", slowdmatype: "0", fastdperiod: "3",
|
33
|
+
fastdmatype: "0", matype: "0", timeperiod1: "7", timeperiod2: "14",
|
34
|
+
timeperiod3: "28", nbdevup: "2", nbdevdn: "2", acceleration: "0.01",
|
35
|
+
maximum: "0.20"
|
36
|
+
Alphavantage::Indicator.new function: function, symbol: @symbol,
|
37
|
+
interval: interval, time_period: time_period, series_type: series_type,
|
38
|
+
fastlimit: fastlimit, slowlimit: slowlimit, fastperiod: fastperiod,
|
39
|
+
slowperiod: slowperiod, signalperiod: signalperiod,
|
40
|
+
fastmatype: fastmatype, slowmatype: slowmatype,
|
41
|
+
signalmatype: signalmatype, fastkperiod: fastkperiod, slowkperiod: slowkperiod,
|
42
|
+
slowdperiod: slowdperiod, slowkmatype: slowkmatype, slowdmatype: slowdmatype,
|
43
|
+
fastdperiod: fastdperiod, fastdmatype: fastdmatype, matype: matype,
|
44
|
+
timeperiod1: timeperiod1, timeperiod2: timeperiod2, timeperiod3: timeperiod3,
|
45
|
+
nbdevup: nbdevup, nbdevdn: nbdevdn, acceleration: acceleration,
|
46
|
+
maximum: maximum, key: @client
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/Timeseries.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
module Alphavantage
|
2
|
+
class Timeseries
|
3
|
+
include HelperFunctions
|
4
|
+
|
5
|
+
def initialize type: "daily", interval: nil, outputsize: "compact",
|
6
|
+
symbol:, datatype: "json", file: nil, key:, verbose: false,
|
7
|
+
adjusted: false
|
8
|
+
check_argument([true, false], verbose, "verbose")
|
9
|
+
@client = return_client(key, verbose)
|
10
|
+
if type == "intraday"
|
11
|
+
interval ||= "1min"
|
12
|
+
check_argument(["1min", "5min", "15min", "30min", "60min"], interval, "interval")
|
13
|
+
check_argument([false], adjusted, "adjusted")
|
14
|
+
interval = "&interval=#{interval}"
|
15
|
+
else
|
16
|
+
check_argument([nil], interval, "interval")
|
17
|
+
interval = ""
|
18
|
+
end
|
19
|
+
check_argument(["compact", "full"], outputsize, "outputsize")
|
20
|
+
check_argument(["json", "csv"], datatype, "datatype")
|
21
|
+
if datatype == "csv" && file.nil?
|
22
|
+
raise Alphavantage::Error.new message: "No file specified where to save the CSV ata"
|
23
|
+
elsif datatype != "csv" && !file.nil?
|
24
|
+
raise Alphavantage::Error.new message: "Hash error: No file necessary"
|
25
|
+
end
|
26
|
+
|
27
|
+
@selected_time_series = which_series(type, adjusted)
|
28
|
+
url = "function=#{@selected_time_series}&symbol=#{symbol}#{interval}&outputsize=#{outputsize}"
|
29
|
+
return @client.download(url, file) if datatype == "csv"
|
30
|
+
@hash = @client.request(url)
|
31
|
+
metadata = @hash.dig("Meta Data") || {}
|
32
|
+
metadata.each do |key, val|
|
33
|
+
key_sym = recreate_metadata_key(key)
|
34
|
+
define_singleton_method(key_sym) do
|
35
|
+
return val
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
time_series = @hash.find{|key, val| key.include?("Time Series")}[1]
|
41
|
+
rescue Exception => e
|
42
|
+
raise Alphavantage::Error.new message: "No Time Series found: #{e.message}",
|
43
|
+
data: @hash
|
44
|
+
end
|
45
|
+
|
46
|
+
series = {}
|
47
|
+
convert_key = {}
|
48
|
+
time_series.values[0].keys.each do |key|
|
49
|
+
key_sym = key.downcase.gsub(/[0-9.]/, "").lstrip.gsub(" ", "_").to_sym
|
50
|
+
series[key_sym] = []
|
51
|
+
convert_key[key] = key_sym
|
52
|
+
end
|
53
|
+
time_series.each do |time, ts_hash|
|
54
|
+
ts_hash.each do |key, value|
|
55
|
+
series[convert_key[key]] << [time, value]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
series.keys.each do |key_sym|
|
59
|
+
define_singleton_method(key_sym) do |*args|
|
60
|
+
args ||= []
|
61
|
+
return return_series(series[key_sym], args[0])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_reader :hash
|
67
|
+
|
68
|
+
def which_series(type, adjusted)
|
69
|
+
check_argument(["intraday", "daily", "weekly", "monthly"], type, "type")
|
70
|
+
series = "TIME_SERIES_"
|
71
|
+
series += type.upcase
|
72
|
+
series += "_ADJUSTED" if adjusted
|
73
|
+
return series
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|