alphavantagerb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|