stockcruncher 1.3.0 → 1.4.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/.gitlab-ci.yml +4 -3
- data/.rubocop.yml +1 -0
- data/README.md +23 -6
- data/lib/stockcruncher/alphavantage.rb +5 -6
- data/lib/stockcruncher/cli.rb +21 -4
- data/lib/stockcruncher/config.rb +40 -0
- data/lib/stockcruncher/influxdb.rb +15 -4
- data/lib/stockcruncher/stats.rb +1 -1
- data/lib/stockcruncher/version.rb +1 -1
- data/spec/stockcruncher/cli_spec.rb +12 -0
- data/spec/stockcruncher/stubs/servers_stubs.rb +7 -0
- data/stockcruncher.gemspec +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aff25a8077f9f28f5a5a82e91d1f7bc75bebc6c2f84a71b56bc40c003d2ed2fb
|
4
|
+
data.tar.gz: fd3e9d18afdc9b7a2a32353b2a1705e21873b6eec4e53ee1e78fb3adcb6f7456
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39e33d26ee32fd116eaf6421149721a678ffbcbab220c9ffbe00e7e5138320ea5d46e557c62fbdfa201364939764f21568fc9df0e0c8321fc69cc82961c8a7d2
|
7
|
+
data.tar.gz: 121229b80af6b2945acd446dfd2dfa5313ba3f4afaa900c834e1c262c2aa1161808074aad04d6e4a96f40b757f5568a4a3d1c024f64189867b4d2d6b544b1969
|
data/.gitlab-ci.yml
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
|
1
2
|
image: ruby:2.4
|
2
3
|
|
4
|
+
before_script:
|
5
|
+
- bundle install
|
6
|
+
|
3
7
|
rubocop:
|
4
8
|
stage: test
|
5
|
-
before_script:
|
6
|
-
- gem install --silent rubocop
|
7
9
|
script:
|
8
10
|
- rubocop
|
9
11
|
|
@@ -25,7 +27,6 @@ git_history:
|
|
25
27
|
rspec:
|
26
28
|
stage: test
|
27
29
|
script:
|
28
|
-
- bundle install
|
29
30
|
- rspec
|
30
31
|
artifacts:
|
31
32
|
paths:
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -5,12 +5,14 @@
|
|
5
5
|
[![Gem Version][gem-img]][gem]
|
6
6
|
|
7
7
|
1. [Overview](#overview)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
1. [Description](#description)
|
9
|
+
1. [Setup](#setup)
|
10
|
+
1. [Usage](#usage)
|
11
|
+
1. [Environment variables](#environment-variables)
|
12
|
+
1. [Examples](#examples)
|
13
|
+
1. [Limitations](#limitations)
|
14
|
+
1. [Development](#development)
|
15
|
+
1. [Miscellaneous](#miscellaneous)
|
14
16
|
|
15
17
|
## Overview
|
16
18
|
|
@@ -41,6 +43,17 @@ An interactive help is available with:
|
|
41
43
|
|
42
44
|
$ stockcruncher help [subcommand]
|
43
45
|
|
46
|
+
## Environment variables
|
47
|
+
|
48
|
+
Parameters in /etc/stockcruncher/stockcrunucher.yml can be overloaded with
|
49
|
+
environment variables.
|
50
|
+
Environment variables should match SCR_<COMPONENTID>_<ITEM>.
|
51
|
+
Component ID are as follow.
|
52
|
+
- AlphaVantage: AV
|
53
|
+
- InfluxDB: IDB
|
54
|
+
Items are upcase keys. See template /etc/stockcruncher/stockcrunucher.yml for
|
55
|
+
reference.
|
56
|
+
|
44
57
|
## Examples
|
45
58
|
|
46
59
|
To get daily time serie data of a symbol:
|
@@ -51,6 +64,10 @@ To get last day endpoint data of a symbol:
|
|
51
64
|
|
52
65
|
$ stockcruncher quote AAPL
|
53
66
|
|
67
|
+
To override a parameter with environment variable:
|
68
|
+
|
69
|
+
$ SCR_IDB_HOST=192.168.0.80; stockcruncher quote AAPL
|
70
|
+
|
54
71
|
## Limitations
|
55
72
|
|
56
73
|
Data are currently scraped from AlphaVantage API.
|
@@ -39,7 +39,7 @@ module StockCruncher
|
|
39
39
|
# Main method to crunch data.
|
40
40
|
def crunch_daily(symbol, fullsize)
|
41
41
|
url = API_URL + parameters(symbol, 'TIME_SERIES_DAILY')
|
42
|
-
url +=
|
42
|
+
url += "&datatype=csv&outputsize=#{fullsize ? 'full' : 'compact'}"
|
43
43
|
res = request(url)
|
44
44
|
transform_daily(res.body)
|
45
45
|
end
|
@@ -63,9 +63,9 @@ module StockCruncher
|
|
63
63
|
|
64
64
|
# Set parameters of api call
|
65
65
|
def parameters(symbol, serie)
|
66
|
-
p =
|
67
|
-
p +=
|
68
|
-
p +=
|
66
|
+
p = "function=#{serie}"
|
67
|
+
p += "&symbol=#{symbol}"
|
68
|
+
p += "&apikey=#{@config[self.class.name.split('::').last]['apikey']}"
|
69
69
|
p
|
70
70
|
end
|
71
71
|
|
@@ -87,8 +87,7 @@ module StockCruncher
|
|
87
87
|
raise StandardError, 'No data' if rawdata.match?(/Error Message/)
|
88
88
|
|
89
89
|
values = prepare_daily_timeserie(rawdata)
|
90
|
-
|
91
|
-
values
|
90
|
+
calculate_missing_data(values)
|
92
91
|
end
|
93
92
|
|
94
93
|
# Method to transform quote result to hash
|
data/lib/stockcruncher/cli.rb
CHANGED
@@ -45,12 +45,20 @@ module StockCruncher
|
|
45
45
|
default: false,
|
46
46
|
desc: 'Full data size.'
|
47
47
|
)
|
48
|
+
option(
|
49
|
+
:catchup,
|
50
|
+
aliases: ['-u'],
|
51
|
+
type: :boolean,
|
52
|
+
default: false,
|
53
|
+
desc: 'Catch up the missing data only.'
|
54
|
+
)
|
48
55
|
def daily(symbol)
|
49
56
|
opts = options.dup
|
50
57
|
config = YAML.load_file(opts['config'])
|
51
58
|
cruncher = StockCruncher::AlphaVantage.new(config, opts['insecure'])
|
52
59
|
data = cruncher.crunch_daily(symbol, opts['full'])
|
53
|
-
StockCruncher::InfluxDB.new(config)
|
60
|
+
influx = StockCruncher::InfluxDB.new(config)
|
61
|
+
influx.export_history(symbol, data, opts['catchup'])
|
54
62
|
puts JSON.pretty_generate(data) unless opts['quiet']
|
55
63
|
end
|
56
64
|
|
@@ -63,20 +71,29 @@ module StockCruncher
|
|
63
71
|
default: false,
|
64
72
|
desc: 'Recalculate all MA historical values.'
|
65
73
|
)
|
74
|
+
option(
|
75
|
+
:catchup,
|
76
|
+
aliases: ['-u'],
|
77
|
+
type: :boolean,
|
78
|
+
default: false,
|
79
|
+
desc: 'Catch up the missing data only.'
|
80
|
+
)
|
66
81
|
def movingaverages(symbol)
|
67
82
|
opts = options.dup
|
68
83
|
config = YAML.load_file(opts['config'])
|
69
|
-
StockCruncher::InfluxDB.new(config)
|
84
|
+
influx = StockCruncher::InfluxDB.new(config)
|
85
|
+
influx.moving_averages(symbol, opts['all'], opts['catchup'])
|
70
86
|
end
|
71
87
|
|
72
88
|
desc('quote SYMBOL [options]',
|
73
89
|
'Crunch SYMBOL stock market data for last day quote.')
|
74
90
|
def quote(symbol)
|
75
91
|
opts = options.dup
|
76
|
-
config =
|
92
|
+
config = StockCruncher::Config.load(opts['config'])
|
77
93
|
cruncher = StockCruncher::AlphaVantage.new(config, opts['insecure'])
|
78
94
|
data = cruncher.crunch_quote(symbol)
|
79
|
-
StockCruncher::InfluxDB.new(config)
|
95
|
+
influx = StockCruncher::InfluxDB.new(config)
|
96
|
+
influx.export_last_day(data)
|
80
97
|
puts JSON.pretty_generate(data) unless opts['quiet']
|
81
98
|
end
|
82
99
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
module StockCruncher
|
7
|
+
# this is a module to load configuration file and environment variable
|
8
|
+
module Config
|
9
|
+
module_function
|
10
|
+
|
11
|
+
# Load config file and override with env variables
|
12
|
+
def load(file)
|
13
|
+
config = YAML.load_file(file)
|
14
|
+
overload_alphavantage(config)
|
15
|
+
overload_influxdb(config)
|
16
|
+
end
|
17
|
+
|
18
|
+
def overload(config, prefix, component, items)
|
19
|
+
items.each do |key|
|
20
|
+
var = "#{prefix}#{key.upcase}"
|
21
|
+
config[component][key] = ENV[var] unless ENV[var].nil?
|
22
|
+
end
|
23
|
+
config
|
24
|
+
end
|
25
|
+
|
26
|
+
def overload_alphavantage(config)
|
27
|
+
prefix = 'SCR_AV_'
|
28
|
+
component = 'AlphaVantage'
|
29
|
+
items = %w[apikey]
|
30
|
+
overload(config, prefix, component, items)
|
31
|
+
end
|
32
|
+
|
33
|
+
def overload_influxdb(config)
|
34
|
+
prefix = 'SCR_IDB_'
|
35
|
+
component = 'InfluxDB'
|
36
|
+
items = %w[scheme host port user password dbname]
|
37
|
+
overload(config, prefix, component, items)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -20,15 +20,22 @@ module StockCruncher
|
|
20
20
|
data['columns'].zip(data['values'].transpose).to_h
|
21
21
|
end
|
22
22
|
|
23
|
+
def get_ma_values(symbol, fullsize)
|
24
|
+
values = %w[ema200]
|
25
|
+
data = query('ema', symbol, values, fullsize)
|
26
|
+
data['columns'].zip(data['values'].transpose).to_h
|
27
|
+
end
|
28
|
+
|
23
29
|
# Method to calculate moving averages based on last day values
|
24
|
-
def moving_averages(symbol, fullsize)
|
30
|
+
def moving_averages(symbol, fullsize, catchup)
|
25
31
|
series = get_daily_values(symbol, fullsize)
|
32
|
+
mas = catchup ? get_ma_values(symbol, fullsize) : {}
|
26
33
|
tags = create_tags(symbol)
|
27
34
|
series['close'].each_index do |i|
|
28
35
|
date = series['time'][i]
|
29
36
|
serie = series['close'][i, 201]
|
30
37
|
weights = series['volume'][i, 201]
|
31
|
-
write_moving_averages(tags, serie, weights, date)
|
38
|
+
write_moving_averages(tags, serie, weights, date) unless mas.key? date
|
32
39
|
break unless fullsize
|
33
40
|
end
|
34
41
|
end
|
@@ -39,8 +46,12 @@ module StockCruncher
|
|
39
46
|
end
|
40
47
|
|
41
48
|
# Method to export historical data to database
|
42
|
-
def export_history(symbol, timeseries)
|
49
|
+
def export_history(symbol, timeseries, catchup)
|
43
50
|
tags = create_tags(symbol)
|
51
|
+
if catchup
|
52
|
+
series = get_daily_values(symbol, true)
|
53
|
+
series['time'].each { |date| timeseries.delete(date) }
|
54
|
+
end
|
44
55
|
timeseries.each_pair do |date, values|
|
45
56
|
write('daily', tags, values, date)
|
46
57
|
end
|
@@ -95,7 +106,7 @@ module StockCruncher
|
|
95
106
|
def write(name, tags, values, date)
|
96
107
|
url = "#{@cfg['scheme']}://#{@cfg['host']}:#{@cfg['port']}/write?" \
|
97
108
|
"db=#{@cfg['dbname']}"
|
98
|
-
timestamp = DateTime.parse(date
|
109
|
+
timestamp = DateTime.parse("#{date}T18:00:00").strftime('%s%N')
|
99
110
|
body = "#{name},#{format_values(tags)} #{format_values(values)} " \
|
100
111
|
"#{timestamp}"
|
101
112
|
request(url, body)
|
data/lib/stockcruncher/stats.rb
CHANGED
@@ -26,12 +26,24 @@ describe StockCruncher::CLI do # rubocop:disable Metrics/BlockLength
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
context 'daily SYM -u -c spec/files/stockcruncher.yml' do
|
30
|
+
it 'Get the daily time serie for SYM.' do
|
31
|
+
expect { start(self) }.to output(daily).to_stdout
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
29
35
|
context 'movingaverages SYM -c spec/files/stockcruncher.yml' do
|
30
36
|
it 'Get the daily time serie for SYM.' do
|
31
37
|
expect { start(self) }.to output('').to_stdout
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
41
|
+
context 'movingaverages SYM -u -c spec/files/stockcruncher.yml' do
|
42
|
+
it 'Get the daily time serie for SYM.' do
|
43
|
+
expect { start(self) }.to output('').to_stdout
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
35
47
|
context 'quote NODATA -c spec/files/stockcruncher.yml' do
|
36
48
|
it 'Should not get any data and should fail.' do
|
37
49
|
expect { start(self) }.to raise_error(SystemExit)
|
@@ -12,6 +12,10 @@ daily = "timestamp,open,high,low,close,volume\r\n2020-08-03,23.8500,24.6500," \
|
|
12
12
|
"\n2020-07-29,24.7500,25.0300,24.0400,24.5600,4605804\r\n2020-07-28," \
|
13
13
|
"25.9900,26.0700,24.5100,24.7500,6904261\r\n"
|
14
14
|
d_err = "{\n \"Error Message\": \"Invalid API call.\"\n}"
|
15
|
+
i_ema = "q=SELECT ema200 FROM ema WHERE symbol = 'SYM' ORDER BY time DESC"
|
16
|
+
maval = '{"results":[{"statement_id":0,"series":[{"name":"ema","columns":[' \
|
17
|
+
'"time","ema200"],"values":[["2017-' \
|
18
|
+
'03-01T18:00:00Z",1]]}]}]}'
|
15
19
|
mvavg = '{"results":[{"statement_id":0,"series":[{"name":"daily","columns":[' \
|
16
20
|
'"time","close","change","changePercent","volume"],"values":[["2017-' \
|
17
21
|
'03-01T18:00:00Z",1,0,0,1],["2017-03-02T18:00:00Z",1,0,0,1],["2017-0' \
|
@@ -35,6 +39,9 @@ RSpec.configure do |config|
|
|
35
39
|
'function=TIME_SERIES_DAILY&symbol=SYM&apikey=demo' \
|
36
40
|
'&datatype=csv&outputsize=compact')
|
37
41
|
.to_return('status' => 200, 'body' => daily, 'headers' => {})
|
42
|
+
stub_request(:post, 'http://localhost:8086/query?db=test')
|
43
|
+
.with(body: i_ema)
|
44
|
+
.to_return('status' => 204, 'body' => maval, 'headers' => {})
|
38
45
|
stub_request(:post, 'http://localhost:8086/query?db=test')
|
39
46
|
.to_return('status' => 204, 'body' => mvavg, 'headers' => {})
|
40
47
|
stub_request(:post, 'http://localhost:8086/write?db=test')
|
data/stockcruncher.gemspec
CHANGED
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.4.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:
|
11
|
+
date: 2021-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0.
|
61
|
+
version: '0.90'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0.
|
68
|
+
version: '0.90'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: webmock
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,6 +129,7 @@ files:
|
|
129
129
|
- lib/stockcruncher.rb
|
130
130
|
- lib/stockcruncher/alphavantage.rb
|
131
131
|
- lib/stockcruncher/cli.rb
|
132
|
+
- lib/stockcruncher/config.rb
|
132
133
|
- lib/stockcruncher/cruncher.rb
|
133
134
|
- lib/stockcruncher/influxdb.rb
|
134
135
|
- lib/stockcruncher/stats.rb
|