stockcruncher 1.0.1 → 1.2.1
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 +4 -4
- data/CHANGELOG +23 -0
- data/README.md +13 -4
- data/lib/stockcruncher.rb +2 -2
- data/lib/stockcruncher/alphavantage.rb +80 -17
- data/lib/stockcruncher/cli.rb +39 -16
- data/lib/stockcruncher/cruncher.rb +6 -11
- data/lib/stockcruncher/influxdb.rb +63 -0
- data/lib/stockcruncher/version.rb +1 -1
- data/spec/files/SYM.daily +49 -0
- data/spec/files/SYM.quote +10 -0
- data/spec/files/stockcruncher.yml +7 -0
- data/spec/stockcruncher/cli_spec.rb +25 -3
- data/spec/stockcruncher/stubs/servers_stubs.rb +22 -2
- metadata +5 -3
- data/spec/stockcruncher/alphavantage_spec.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4729948dfb9635323240f73d947c2257b1ca4b8a6c2a065a812a8726f502599
|
4
|
+
data.tar.gz: 3686ad0bbb61ef2a3801a2a2c1b3258b543da3015c49b2c959570c9d7b0e8a3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24120c82f3e7cd9d622bcf1636ee528ea69d170fe0f60951b33b34754870a1b92837d5f2cbcd3f59ab4be85264195e7c2058036a557e8b486c8fe55cf81e5c18
|
7
|
+
data.tar.gz: e849aea61ae75175742d97611cffdc889aa3c95394aec2cc8ccbe93ed35bafc6958984fb0fc92b08190a41003c183b753ad287a51676990eee855d32f43bfceb
|
data/CHANGELOG
CHANGED
@@ -5,3 +5,26 @@ Changelog
|
|
5
5
|
-----
|
6
6
|
|
7
7
|
- Initial version
|
8
|
+
|
9
|
+
1.1.0
|
10
|
+
-----
|
11
|
+
|
12
|
+
- Add InfluxDB as database.
|
13
|
+
- WIP for daily time serie.
|
14
|
+
|
15
|
+
1.1.1
|
16
|
+
-----
|
17
|
+
|
18
|
+
- Rescue error on no data
|
19
|
+
|
20
|
+
1.2.0
|
21
|
+
-----
|
22
|
+
|
23
|
+
- daily subcommand now recalculates missing data
|
24
|
+
- daily subcommand also writes data to database
|
25
|
+
|
26
|
+
1.2.1
|
27
|
+
-----
|
28
|
+
|
29
|
+
- Refactor to preprocess data in source class
|
30
|
+
- Refactor to print pretty json instead of comma separated striing
|
data/README.md
CHANGED
@@ -25,29 +25,38 @@ to write the data in a database for later calculation and use.
|
|
25
25
|
|
26
26
|
$ gem install stockcruncher
|
27
27
|
$ mkdir /etc/stockcruncher && cd /etc/stockcruncher
|
28
|
-
$ echo
|
28
|
+
$ echo 'AlphaVantage:' > stockcruncher.yml
|
29
|
+
$ echo ' apikey: CHANGEME' >> stockcruncher.yml
|
30
|
+
$ echo 'InfluxDB:' >> stockcruncher.yml
|
31
|
+
$ echo ' scheme: http' >> stockcruncher.yml
|
32
|
+
$ echo ' host: localhost' >> stockcruncher.yml
|
33
|
+
$ echo ' port: 8086' >> stockcruncher.yml
|
34
|
+
$ echo ' user: CHANGEMEAGAIN' >> stockcruncher.yml
|
35
|
+
$ echo ' password: CHANGEMETOO' >> stockcruncher.yml
|
36
|
+
$ echo ' dbname: stock' >> stockcruncher.yml
|
29
37
|
|
30
38
|
## Usage
|
31
39
|
|
32
40
|
An interactive help is available with:
|
33
41
|
|
34
|
-
$ stockcruncher help
|
42
|
+
$ stockcruncher help [subcommand]
|
35
43
|
|
36
44
|
## Examples
|
37
45
|
|
38
46
|
To get daily time serie data of a symbol:
|
39
47
|
|
40
|
-
$ stockcruncher
|
48
|
+
$ stockcruncher daily AAPL
|
41
49
|
|
42
50
|
To get last day endpoint data of a symbol:
|
43
51
|
|
44
|
-
$ stockcruncher
|
52
|
+
$ stockcruncher quote AAPL
|
45
53
|
|
46
54
|
## Limitations
|
47
55
|
|
48
56
|
Data are currently scraped from AlphaVantage API.
|
49
57
|
More source could be great especially because AlphaVantage doesn't provide EU
|
50
58
|
intraday data.
|
59
|
+
InfluxDB is used as database to keep time series data.
|
51
60
|
|
52
61
|
## Development
|
53
62
|
|
data/lib/stockcruncher.rb
CHANGED
@@ -7,35 +7,98 @@ module StockCruncher
|
|
7
7
|
# This is an data cruncher class for AlphaVantage API.
|
8
8
|
class AlphaVantage < Cruncher
|
9
9
|
API_URL = 'https://www.alphavantage.co/query?'
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
|
11
|
+
# Method to calculate missing data (previousClose, change, changePercent)
|
12
|
+
def calculate_missing_data(hash)
|
13
|
+
keys = hash.keys
|
14
|
+
hash.each_with_index do |(date, v), index|
|
15
|
+
prevday = keys[index + 1]
|
16
|
+
next if prevday.nil?
|
17
|
+
|
18
|
+
prevclose = hash[prevday]['close']
|
19
|
+
hash[date] = v.merge(generate_missing_data(v['close'], prevclose))
|
20
|
+
end
|
21
|
+
hash
|
22
|
+
end
|
23
|
+
|
24
|
+
# Method to calculate change difference
|
25
|
+
def change(value, base)
|
26
|
+
(value - base).round(4).to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
# Method to calculate percentage of change
|
30
|
+
def change_percent(value, base)
|
31
|
+
((value / base - 1) * 100).round(4).to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
# Method to create a new hash from two arrays of keys and values
|
35
|
+
def create_hash(descriptions, values)
|
36
|
+
descriptions.split(',').zip(values.split(',')).to_h
|
37
|
+
end
|
14
38
|
|
15
39
|
# Main method to crunch data.
|
16
|
-
def
|
17
|
-
|
18
|
-
|
40
|
+
def crunch_daily(symbol, fullsize)
|
41
|
+
url = API_URL + parameters(symbol, 'TIME_SERIES_DAILY')
|
42
|
+
url += '&datatype=csv&outputsize=' + (fullsize ? 'full' : 'compact')
|
43
|
+
res = request(url)
|
44
|
+
transform_daily(res.body)
|
45
|
+
end
|
19
46
|
|
20
|
-
|
47
|
+
# Main method to crunch data.
|
48
|
+
def crunch_quote(symbol)
|
49
|
+
url = API_URL + parameters(symbol, 'GLOBAL_QUOTE')
|
50
|
+
url += '&datatype=csv'
|
21
51
|
res = request(url)
|
22
|
-
|
52
|
+
transform_quote(res.body)
|
23
53
|
end
|
24
54
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
55
|
+
# Method to generate missing data
|
56
|
+
def generate_missing_data(current, previous)
|
57
|
+
{
|
58
|
+
'previousClose' => previous,
|
59
|
+
'change' => change(current.to_f, previous.to_f),
|
60
|
+
'changePercent' => change_percent(current.to_f, previous.to_f)
|
61
|
+
}
|
32
62
|
end
|
33
63
|
|
64
|
+
# Set parameters of api call
|
34
65
|
def parameters(symbol, serie)
|
35
|
-
p = 'function=' +
|
66
|
+
p = 'function=' + serie
|
36
67
|
p += '&symbol=' + symbol
|
37
68
|
p += '&apikey=' + @config[self.class.name.split('::').last]['apikey']
|
38
69
|
p
|
39
70
|
end
|
71
|
+
|
72
|
+
# Method to transform raw data to constructed hash
|
73
|
+
def prepare_daily_timeserie(data)
|
74
|
+
lines = data.split("\r\n")
|
75
|
+
desc = lines.shift.split(',').drop(1)
|
76
|
+
hash = {}
|
77
|
+
lines.each do |line|
|
78
|
+
values = line.split(',')
|
79
|
+
date = values.shift
|
80
|
+
hash[date] = desc.zip(values).to_h
|
81
|
+
end
|
82
|
+
hash
|
83
|
+
end
|
84
|
+
|
85
|
+
# Method to transform daily result to nested hash
|
86
|
+
def transform_daily(rawdata)
|
87
|
+
raise StandardError, 'No data' if rawdata.match?(/Error Message/)
|
88
|
+
|
89
|
+
values = prepare_daily_timeserie(rawdata)
|
90
|
+
values = calculate_missing_data(values)
|
91
|
+
values
|
92
|
+
end
|
93
|
+
|
94
|
+
# Method to transform quote result to hash
|
95
|
+
def transform_quote(rawdata)
|
96
|
+
raise StandardError, 'No data' if rawdata.match?(/{}/)
|
97
|
+
|
98
|
+
values = create_hash(*rawdata.split("\r\n"))
|
99
|
+
values['close'] = values.delete('price')
|
100
|
+
values['changePercent'] = values['changePercent'].delete('%')
|
101
|
+
values
|
102
|
+
end
|
40
103
|
end
|
41
104
|
end
|
data/lib/stockcruncher/cli.rb
CHANGED
@@ -1,20 +1,14 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require 'json'
|
4
5
|
require 'thor'
|
6
|
+
require 'yaml'
|
5
7
|
|
6
8
|
module StockCruncher
|
7
9
|
# Simple CLI for StockCruncher
|
8
10
|
class CLI < Thor
|
9
|
-
|
10
|
-
def version
|
11
|
-
puts "StockCruncher version #{StockCruncher::VERSION}"
|
12
|
-
end
|
13
|
-
|
14
|
-
desc('crunch SYMBOL TIMESERIES [options]',
|
15
|
-
'Crunch SYMBOL stock market data for time series.' \
|
16
|
-
'Possible timeseries: daily, quote_endpoint.')
|
17
|
-
option(
|
11
|
+
class_option(
|
18
12
|
:config,
|
19
13
|
aliases: ['-c'],
|
20
14
|
type: :string,
|
@@ -22,13 +16,28 @@ module StockCruncher
|
|
22
16
|
desc: 'Yaml formatted config file to load ' \
|
23
17
|
'(default to /etc/stockcruncher/stockcruncher.yml).'
|
24
18
|
)
|
25
|
-
|
26
|
-
:
|
27
|
-
aliases: ['-
|
19
|
+
class_option(
|
20
|
+
:insecure,
|
21
|
+
aliases: ['-k'],
|
22
|
+
type: :boolean,
|
23
|
+
default: false,
|
24
|
+
desc: 'Ignore SSL certificate (default to false).'
|
25
|
+
)
|
26
|
+
class_option(
|
27
|
+
:quiet,
|
28
|
+
aliases: ['-q'],
|
28
29
|
type: :boolean,
|
29
30
|
default: false,
|
30
|
-
desc: '
|
31
|
+
desc: 'Run silently (default to false).'
|
31
32
|
)
|
33
|
+
|
34
|
+
desc 'version', 'Print stockcruncher current version'
|
35
|
+
def version
|
36
|
+
puts "StockCruncher version #{StockCruncher::VERSION}"
|
37
|
+
end
|
38
|
+
|
39
|
+
desc('daily SYMBOL [options]',
|
40
|
+
'Crunch SYMBOL stock market data for daily time series.')
|
32
41
|
option(
|
33
42
|
:full,
|
34
43
|
aliases: ['-f'],
|
@@ -36,10 +45,24 @@ module StockCruncher
|
|
36
45
|
default: false,
|
37
46
|
desc: 'Full data size.'
|
38
47
|
)
|
39
|
-
def
|
48
|
+
def daily(symbol)
|
49
|
+
opts = options.dup
|
50
|
+
config = YAML.load_file(opts['config'])
|
51
|
+
cruncher = StockCruncher::AlphaVantage.new(config, opts['insecure'])
|
52
|
+
data = cruncher.crunch_daily(symbol, opts['full'])
|
53
|
+
StockCruncher::InfluxDB.new(config).export_history(symbol, data)
|
54
|
+
puts JSON.pretty_generate(data) unless opts['quiet']
|
55
|
+
end
|
56
|
+
|
57
|
+
desc('quote SYMBOL [options]',
|
58
|
+
'Crunch SYMBOL stock market data for last day quote.')
|
59
|
+
def quote(symbol)
|
40
60
|
opts = options.dup
|
41
|
-
|
42
|
-
cruncher.
|
61
|
+
config = YAML.load_file(opts['config'])
|
62
|
+
cruncher = StockCruncher::AlphaVantage.new(config, opts['insecure'])
|
63
|
+
data = cruncher.crunch_quote(symbol)
|
64
|
+
StockCruncher::InfluxDB.new(config).export_last_day(data)
|
65
|
+
puts JSON.pretty_generate(data) unless opts['quiet']
|
43
66
|
end
|
44
67
|
end
|
45
68
|
end
|
@@ -2,27 +2,22 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'net/http'
|
5
|
-
require 'yaml'
|
6
5
|
|
7
6
|
module StockCruncher
|
8
7
|
# This is an data cruncher abstract class.
|
9
8
|
class Cruncher
|
10
|
-
# Class
|
11
|
-
def initialize(
|
12
|
-
@config =
|
13
|
-
|
14
|
-
|
15
|
-
# Method to load configurations described in config_file.
|
16
|
-
def load_conf(file)
|
17
|
-
YAML.load_file(file)
|
9
|
+
# Class constructor method
|
10
|
+
def initialize(config, insecure = false)
|
11
|
+
@config = config
|
12
|
+
@insecure = insecure
|
18
13
|
end
|
19
14
|
|
20
15
|
# Method to send http get request
|
21
|
-
def request(url
|
16
|
+
def request(url)
|
22
17
|
uri = URI.parse(url)
|
23
18
|
http = Net::HTTP.new(uri.host, uri.port)
|
24
19
|
http.use_ssl = uri.scheme.eql?('https')
|
25
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if insecure
|
20
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @insecure
|
26
21
|
req = Net::HTTP::Get.new(uri.request_uri)
|
27
22
|
http.request(req)
|
28
23
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'date'
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
module StockCruncher
|
8
|
+
# this is a class to write time series to database
|
9
|
+
class InfluxDB
|
10
|
+
# Class constructor method
|
11
|
+
def initialize(config, insecure = false)
|
12
|
+
@cfg = config[self.class.name.split('::').last]
|
13
|
+
@insecure = insecure
|
14
|
+
end
|
15
|
+
|
16
|
+
# Method to export latest data to database
|
17
|
+
def export_last_day(values)
|
18
|
+
tags = { 'symbol' => values.delete('symbol') }
|
19
|
+
date = values.delete('latestDay')
|
20
|
+
write('daily', tags, values, date)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Method to export historical data to database
|
24
|
+
def export_history(symbol, timeseries)
|
25
|
+
tags = { 'symbol' => symbol }
|
26
|
+
timeseries.each_pair do |date, values|
|
27
|
+
write('daily', tags, values, date)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Method to format and array of values into comma separated string
|
32
|
+
def format_values(values)
|
33
|
+
string = ''
|
34
|
+
values.each_pair do |k, v|
|
35
|
+
string += "#{k}=#{v}"
|
36
|
+
string += ',' unless k == values.keys.last
|
37
|
+
end
|
38
|
+
string
|
39
|
+
end
|
40
|
+
|
41
|
+
# Method to send http post request
|
42
|
+
def request(url, body)
|
43
|
+
uri = URI.parse(url)
|
44
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
45
|
+
http.use_ssl = uri.scheme.eql?('https')
|
46
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @insecure
|
47
|
+
req = Net::HTTP::Post.new(uri.request_uri)
|
48
|
+
req.basic_auth(@cfg['user'], @cfg['password'])
|
49
|
+
req.body = body
|
50
|
+
http.request(req)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Method to write data in bucket
|
54
|
+
def write(name, tags, values, date)
|
55
|
+
url = "#{@cfg['scheme']}://#{@cfg['host']}:#{@cfg['port']}/write?" \
|
56
|
+
"db=#{@cfg['dbname']}"
|
57
|
+
timestamp = DateTime.parse(date + 'T18:00:00').strftime('%s%N')
|
58
|
+
body = "#{name},#{format_values(tags)} #{format_values(values)} " \
|
59
|
+
"#{timestamp}"
|
60
|
+
request(url, body)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
{
|
2
|
+
"2020-08-03": {
|
3
|
+
"open": "23.8500",
|
4
|
+
"high": "24.6500",
|
5
|
+
"low": "23.7400",
|
6
|
+
"close": "24.5500",
|
7
|
+
"volume": "3112972",
|
8
|
+
"previousClose": "23.8100",
|
9
|
+
"change": "0.74",
|
10
|
+
"changePercent": "3.1079"
|
11
|
+
},
|
12
|
+
"2020-07-31": {
|
13
|
+
"open": "24.0100",
|
14
|
+
"high": "24.5100",
|
15
|
+
"low": "23.5900",
|
16
|
+
"close": "23.8100",
|
17
|
+
"volume": "5482485",
|
18
|
+
"previousClose": "23.6600",
|
19
|
+
"change": "0.15",
|
20
|
+
"changePercent": "0.634"
|
21
|
+
},
|
22
|
+
"2020-07-30": {
|
23
|
+
"open": "24.4700",
|
24
|
+
"high": "24.6600",
|
25
|
+
"low": "23.5200",
|
26
|
+
"close": "23.6600",
|
27
|
+
"volume": "6466738",
|
28
|
+
"previousClose": "24.5600",
|
29
|
+
"change": "-0.9",
|
30
|
+
"changePercent": "-3.6645"
|
31
|
+
},
|
32
|
+
"2020-07-29": {
|
33
|
+
"open": "24.7500",
|
34
|
+
"high": "25.0300",
|
35
|
+
"low": "24.0400",
|
36
|
+
"close": "24.5600",
|
37
|
+
"volume": "4605804",
|
38
|
+
"previousClose": "24.7500",
|
39
|
+
"change": "-0.19",
|
40
|
+
"changePercent": "-0.7677"
|
41
|
+
},
|
42
|
+
"2020-07-28": {
|
43
|
+
"open": "25.9900",
|
44
|
+
"high": "26.0700",
|
45
|
+
"low": "24.5100",
|
46
|
+
"close": "24.7500",
|
47
|
+
"volume": "6904261"
|
48
|
+
}
|
49
|
+
}
|
@@ -1,8 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'json'
|
3
4
|
require 'spec_helper'
|
4
5
|
|
5
|
-
|
6
|
+
daily = File.read('spec/files/SYM.daily')
|
7
|
+
quote = File.read('spec/files/SYM.quote')
|
8
|
+
|
9
|
+
describe StockCruncher::CLI do # rubocop:disable Metrics/BlockLength
|
6
10
|
context 'version' do
|
7
11
|
it 'prints the version.' do
|
8
12
|
out = "StockCruncher version #{StockCruncher::VERSION}\n"
|
@@ -10,9 +14,27 @@ describe StockCruncher::CLI do
|
|
10
14
|
end
|
11
15
|
end
|
12
16
|
|
13
|
-
context '
|
17
|
+
context 'daily NODATA -c spec/files/stockcruncher.yml' do
|
18
|
+
it 'Should not get any data and should fail.' do
|
19
|
+
expect { start(self) }.to raise_error(SystemExit)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'daily SYM -c spec/files/stockcruncher.yml' do
|
24
|
+
it 'Get the daily time serie for SYM.' do
|
25
|
+
expect { start(self) }.to output(daily).to_stdout
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'quote NODATA -c spec/files/stockcruncher.yml' do
|
30
|
+
it 'Should not get any data and should fail.' do
|
31
|
+
expect { start(self) }.to raise_error(SystemExit)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'quote SYM -c spec/files/stockcruncher.yml' do
|
14
36
|
it 'Get the quote for SYM.' do
|
15
|
-
expect { start(self) }.to output(
|
37
|
+
expect { start(self) }.to output(quote).to_stdout
|
16
38
|
end
|
17
39
|
end
|
18
40
|
|
@@ -2,15 +2,35 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
+
quote = 'symbol,open,high,low,price,volume,latestDay,previousClose,change,ch' \
|
6
|
+
"angePercent\r\nSYM,100.0000,100.1000,99.9000,100.0000,4,2020-07-30," \
|
7
|
+
"100.0000,0.0000,0.0000%\r\n"
|
8
|
+
q_err = '{}'
|
9
|
+
daily = "timestamp,open,high,low,close,volume\r\n2020-08-03,23.8500,24.6500," \
|
10
|
+
"23.7400,24.5500,3112972\r\n2020-07-31,24.0100,24.5100,23.5900,23.81" \
|
11
|
+
"00,5482485\r\n2020-07-30,24.4700,24.6600,23.5200,23.6600,6466738\r" \
|
12
|
+
"\n2020-07-29,24.7500,25.0300,24.0400,24.5600,4605804\r\n2020-07-28," \
|
13
|
+
"25.9900,26.0700,24.5100,24.7500,6904261\r\n"
|
14
|
+
d_err = "{\n \"Error Message\": \"Invalid API call.\"\n}"
|
15
|
+
|
5
16
|
RSpec.configure do |config|
|
6
17
|
config.before(:each) do
|
7
18
|
# requests an API without extra arguments
|
19
|
+
stub_request(:get, 'https://www.alphavantage.co/query?' \
|
20
|
+
'function=GLOBAL_QUOTE&symbol=NODATA&apikey=demo&datatype=csv')
|
21
|
+
.to_return('status' => 200, 'body' => q_err, 'headers' => {})
|
8
22
|
stub_request(:get, 'https://www.alphavantage.co/query?' \
|
9
23
|
'function=GLOBAL_QUOTE&symbol=SYM&apikey=demo&datatype=csv')
|
10
|
-
.to_return('status' => 200, 'body' =>
|
24
|
+
.to_return('status' => 200, 'body' => quote, 'headers' => {})
|
25
|
+
stub_request(:get, 'https://www.alphavantage.co/query?' \
|
26
|
+
'function=TIME_SERIES_DAILY&symbol=NODATA&apikey=demo' \
|
27
|
+
'&datatype=csv&outputsize=compact')
|
28
|
+
.to_return('status' => 200, 'body' => d_err, 'headers' => {})
|
11
29
|
stub_request(:get, 'https://www.alphavantage.co/query?' \
|
12
30
|
'function=TIME_SERIES_DAILY&symbol=SYM&apikey=demo' \
|
13
31
|
'&datatype=csv&outputsize=compact')
|
14
|
-
.to_return('status' => 200, 'body' =>
|
32
|
+
.to_return('status' => 200, 'body' => daily, 'headers' => {})
|
33
|
+
stub_request(:post, 'http://localhost:8086/write?db=test')
|
34
|
+
.to_return('status' => 204, 'body' => '', 'headers' => {})
|
15
35
|
end
|
16
36
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stockcruncher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Delaplace
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -130,10 +130,12 @@ files:
|
|
130
130
|
- lib/stockcruncher/alphavantage.rb
|
131
131
|
- lib/stockcruncher/cli.rb
|
132
132
|
- lib/stockcruncher/cruncher.rb
|
133
|
+
- lib/stockcruncher/influxdb.rb
|
133
134
|
- lib/stockcruncher/version.rb
|
135
|
+
- spec/files/SYM.daily
|
136
|
+
- spec/files/SYM.quote
|
134
137
|
- spec/files/stockcruncher.yml
|
135
138
|
- spec/spec_helper.rb
|
136
|
-
- spec/stockcruncher/alphavantage_spec.rb
|
137
139
|
- spec/stockcruncher/cli_spec.rb
|
138
140
|
- spec/stockcruncher/stubs/servers_stubs.rb
|
139
141
|
- spec/stockcruncher_spec.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe StockCruncher::AlphaVantage do
|
6
|
-
context 'crunch SYM daily -c spec/files/stockcruncher.yml' do
|
7
|
-
it 'requests a source and get the result.' do
|
8
|
-
expect { start(self) }.to output("{}\n").to_stdout
|
9
|
-
end
|
10
|
-
end
|
11
|
-
context 'crunch SYM weekly -c spec/files/stockcruncher.yml' do
|
12
|
-
it 'requests a not implemented time serie.' do
|
13
|
-
expect { start(self) }.to raise_error(SystemExit)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|