sqa 0.0.17 → 0.0.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +170 -36
- data/checksums/sqa-0.0.18.gem.sha512 +1 -0
- data/checksums/sqa-0.0.19.gem.sha512 +1 -0
- data/lib/patches/string.rb +58 -0
- data/lib/sqa/data_frame.rb +9 -7
- data/lib/sqa/stock.rb +1 -1
- data/lib/sqa/version.rb +1 -1
- data/lib/sqa.rb +10 -4
- metadata +17 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8dd5577340edd8f74a73428779129e4f97bcfbb4b8eaa23ce02c6b1f290baa4
|
4
|
+
data.tar.gz: fa03b7e2203edbb69da04b9ff022776a6932a481e33a7290e4ff46b573375a89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca34483321c0ac6391d322acef9ed2a9ba5d1e87db15201d4c89f760346e1c620b1ce5182cf203c393b118703a743bf535f84e52f099bad12445eacc1b82d39b
|
7
|
+
data.tar.gz: 89cb9767f3febdc9e20970e0d73a679f378f75260b4e6b146bd413dc49d942200a60f03c2ecb7f02ae6e87662ece5744fa45aead39d147fa7aad81d2037128fc
|
data/README.md
CHANGED
@@ -1,22 +1,13 @@
|
|
1
|
-
**Replacing Daru** with Hashie::Mash
|
2
|
-
|
3
|
-
This is branch hashie_df
|
4
|
-
|
5
1
|
# SQA - Simple Qualitative Analysis
|
6
2
|
|
7
|
-
This is a very simplistic set of tools for running technical analysis on a stock portfolio. Simplistic means it is not reliable nor intended for any kind of financial use. Think of it as a training tool. I do. Its helping me understand why I need professional help from people who know what they are doing.
|
3
|
+
This is a very simplistic set of tools for running technical analysis (quantitative and qualitative) on a stock portfolio. Simplistic means it is not reliable nor intended for any kind of mission-critical financial use. Think of it as a training tool. I do. Its helping me understand why I need professional help from people who know what they are doing.
|
8
4
|
|
9
|
-
The BUY/SELL signals that it generates
|
5
|
+
The BUY/SELL signals that it generates should not be taken seriously. **DO NOT USE** this library when real money is at stake. If you lose your shirt playing in the stock market don't come crying to me. I think playing in the market is like playing in the street. You are going to get run over.
|
10
6
|
|
11
7
|
## This is a Work in Progress
|
12
8
|
|
13
|
-
I
|
14
|
-
|
15
|
-
### DARU or RedAmber
|
9
|
+
I am experimenting with different gems to support various functionality. Sometimes they do not work out well. For example I've gone through two different gems to implement the data frame capability. Neither did what I wanted so I ended up creating my own data frame class based upon the old tried and true Hashie library.
|
16
10
|
|
17
|
-
I'm just really using `daru` for its data frame object; However, I just learned about the RedAmber data frame object in Ruby based off of Apache Arrow. I'm going to look at that product since it is actively maintained.
|
18
|
-
|
19
|
-
https://github.com/red-data-tools/red_amber
|
20
11
|
|
21
12
|
## Installation
|
22
13
|
|
@@ -28,62 +19,200 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
28
19
|
|
29
20
|
gem install sqa
|
30
21
|
|
31
|
-
|
22
|
+
### Semantic Versioning
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
SQA.version # returns SemVersion object
|
26
|
+
exit(1) unless SQA.version >= SemVersion("1.0.0")
|
27
|
+
```
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
**Do not use!** but its okay to play with.
|
32
32
|
|
33
|
-
|
33
|
+
`SQA` can be used from the command line or as a library in your own application.
|
34
34
|
|
35
|
-
|
35
|
+
`SQA` has a command line component.
|
36
36
|
|
37
|
-
|
37
|
+
```plaintext
|
38
|
+
$ sqa --help
|
39
|
+
Stock Quantitative Analysis (SQA)
|
38
40
|
|
39
|
-
|
41
|
+
Usage: sqa [analysis|web] [OPTIONS]
|
42
|
+
|
43
|
+
A collection of things
|
44
|
+
|
45
|
+
Options:
|
46
|
+
-c, --config string Path to the config file
|
47
|
+
--data-dir string Set the directory for the SQA data
|
48
|
+
-d, --debug Turn on debugging output
|
49
|
+
--dump-config path_to_file Dump the current configuration
|
50
|
+
-h, --help Print usage
|
51
|
+
-l, --log_level string Set the log level (debug, info, warn, error,
|
52
|
+
fatal)
|
53
|
+
-p, --portfolio string Set the filename of the portfolio
|
54
|
+
-t, --trades string Set the filename into which trades are
|
55
|
+
stored
|
56
|
+
-v, --verbose Print verbosely
|
57
|
+
--version Print version
|
58
|
+
|
59
|
+
Examples:
|
60
|
+
sqa -c ~/.sqa.yml -p portfolio.csv -t trades.csv --data-dir ~/sqa_data
|
61
|
+
|
62
|
+
Optional Command Available:
|
63
|
+
analysis - Provide an Analysis of a Portfolio
|
64
|
+
web - Run a web server
|
65
|
+
|
66
|
+
WARNING: This is a toy, a play thing, not intended for serious use.
|
67
|
+
```
|
68
|
+
### Setup a Config File
|
69
|
+
|
70
|
+
You will need to create a directory to store the `sqa` data and a configuration file. You can start by doing this:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
gem install sqa
|
74
|
+
mkdir ~/Documents/sqa_data
|
75
|
+
sqa --data-dir ~/Documents/sqa_data --dump-config ~/.sqa.yml
|
76
|
+
```
|
77
|
+
|
78
|
+
By default `SQA` looks for a configuration file named `.sqa.yml` in the current directory. If it does not find one there it looks in the home directory. You can use the `--config` CLI option to specify a path to your custom config file name.
|
79
|
+
|
80
|
+
|
81
|
+
### AlphaVantage
|
82
|
+
|
83
|
+
`SQA` makes use of the `AlphaVantage` API to get some stock related information. You will need an API key in order to use this functionality. They have a free rate limited API key which allows 5 accesses per second; total of 100 accesses in a day. If you are doing more than that you are not playing an ought to purchase one of there serious API key plans.
|
84
|
+
|
85
|
+
[https://www.alphavantage.co/](https://www.alphavantage.co/)
|
40
86
|
|
41
|
-
**Do not use!**
|
42
87
|
|
43
88
|
## Playing in IRB
|
44
89
|
|
45
|
-
You can play around in IRB with the SQA framework
|
90
|
+
You can play around in IRB with the SQA framework.
|
91
|
+
|
46
92
|
|
47
93
|
### With Stocks and Indicators
|
48
94
|
|
49
|
-
You will need some CSV files.
|
95
|
+
You will need some CSV files. If you ask for a stock to which you have not existing historical price data in a CSV file, `SQA` can use either Alpha Vantage or Yahoo Finance to get some data. I like Alpha Vantage better because it has a well defined and documented API. Yahoo Finance on the other hand does not. You can manually download historical stock price data from Yahoo Finance into you `sqa data directory`
|
96
|
+
|
97
|
+
Historical price data is kept in the `SQA.data_dir` in a CSV file whose name is all lowercase. If you download the CSV file for the stock symbol "AAPL" it should be saved in you `SQA.data_dir` as `aapl.csv`
|
50
98
|
|
51
99
|
#### Get Historical Prices
|
52
100
|
|
53
|
-
Go to https::/finance.yahoo.com and down some historical price data for your favorite stocks. Put those CSV files
|
101
|
+
Go to https::/finance.yahoo.com and down some historical price data for your favorite stocks. Put those CSV files into the `SQA.data_dir`.
|
54
102
|
|
55
103
|
You may need to create a `portfolio.csv` file or you may not. TODO
|
56
104
|
|
57
|
-
The CSV files will be named by the stock's ticker symbol. For example:
|
105
|
+
The CSV files will be named by the stock's ticker symbol. For example: `aapl.csv`
|
106
|
+
|
107
|
+
### Playing in the IRB - Setup
|
58
108
|
|
59
109
|
```ruby
|
60
110
|
require 'sqa'
|
61
|
-
|
62
|
-
|
63
|
-
|
111
|
+
require 'sqa/cli'
|
112
|
+
|
113
|
+
# You can pass a set of CLI options in a String
|
114
|
+
SQA.init "-c ~/.sqa.yml"
|
64
115
|
|
65
|
-
|
66
|
-
|
116
|
+
aapl = SQA::Stock.new(ticker: 'aapl', source: :alpha_vantage)
|
117
|
+
#=> aapl with 1207 data points from 2019-01-02 to 2023-10-17
|
118
|
+
```
|
119
|
+
|
120
|
+
`aapl.df` is the data frame. It is implemented as a Hashie::Mash obect -- a Hash or Arrays.
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
aapl.df.keys
|
124
|
+
#=> [:timestamp, :open_price, :high_price, :low_price, :close_price, :adj_close_price, :volume]
|
67
125
|
|
68
|
-
aapl
|
126
|
+
aapl.df.adj_close_price.last(5)
|
127
|
+
#=> [179.8, 180.71, 178.85, 178.72, 177.15]
|
69
128
|
```
|
70
129
|
|
71
|
-
`aapl.
|
72
|
-
|
130
|
+
`aapl.data` is basic static data, company name, industry etc. It is also implemented as a Hassie::Mash object but is primary treated as a plain hash object.
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
aapl.data.keys
|
134
|
+
#=> [:ticker, :source, :indicators, :overview]
|
135
|
+
|
136
|
+
aapl.data.source
|
137
|
+
=> "alpha_vantage"
|
138
|
+
|
139
|
+
aapl.data.overciew.keys
|
140
|
+
=> [:symbol, :asset_type, :name, :description, :cik, :exchange, :currency, :country, :sector, :industry, :address, :fiscal_year_end, :latest_quarter, :market_capitalization, :ebitda, :pe_ratio, :peg_ratio, :book_value, :dividend_per_share, :dividend_yield, :eps, :revenue_per_share_ttm, :profit_margin, :operating_margin_ttm, :return_on_assets_ttm, :return_on_equity_ttm, :revenue_ttm, :gross_profit_ttm, :diluted_epsttm, :quarterly_earnings_growth_yoy, :quarterly_revenue_growth_yoy, :analyst_target_price, :trailing_pe, :forward_pe, :price_to_sales_ratio_ttm, :price_to_book_ratio, :ev_to_revenue, :ev_to_ebitda, :beta, :"52_week_high", :"52_week_low", :"50_day_moving_average", :"200_day_moving_average", :shares_outstanding, :dividend_date, :ex_dividend_date]
|
141
|
+
|
142
|
+
```
|
143
|
+
|
144
|
+
### Playing in the IRB - Statistics
|
145
|
+
|
146
|
+
Basic statistics are available on all of the SQA::DataFrame arrays.
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
require 'amazing_print' # to get the ap command
|
150
|
+
|
151
|
+
# Look at some summary stats on the last 5 days of
|
152
|
+
# adjusted closing pricess of AAPL
|
153
|
+
ap aapl.df.adj_close_price.last(5).summary
|
154
|
+
{
|
155
|
+
:frequencies => {
|
156
|
+
179.8 => 1,
|
157
|
+
180.71 => 1,
|
158
|
+
178.85 => 1,
|
159
|
+
178.72 => 1,
|
160
|
+
177.15 => 1
|
161
|
+
},
|
162
|
+
:max => 180.71,
|
163
|
+
:mean => 179.046,
|
164
|
+
:median => 178.85,
|
165
|
+
:midrange => 178.93,
|
166
|
+
:min => 177.15,
|
167
|
+
:mode => nil,
|
168
|
+
:proportions => {
|
169
|
+
179.8 => 0.2,
|
170
|
+
180.71 => 0.2,
|
171
|
+
178.85 => 0.2,
|
172
|
+
178.72 => 0.2,
|
173
|
+
177.15 => 0.2
|
174
|
+
},
|
175
|
+
:quartile1 => 178.85,
|
176
|
+
:quartile2 => 179.8,
|
177
|
+
:quartile3 => 180.71,
|
178
|
+
:range => 3.5600000000000023,
|
179
|
+
:size => 5,
|
180
|
+
:sum => 895.23,
|
181
|
+
:sample_coefficient_of_variation => 0.006644656242680533,
|
182
|
+
:sample_kurtosis => 2.089087404921432,
|
183
|
+
:sample_size => 5,
|
184
|
+
:sample_skewness => -0.2163861377512453,
|
185
|
+
:sample_standard_deviation => 1.1896991216269788,
|
186
|
+
:sample_standard_error => 0.532049621745943,
|
187
|
+
:sample_variance => 1.415384000000005,
|
188
|
+
:sample_zscores => {
|
189
|
+
179.8 => 0.6337736880639895,
|
190
|
+
180.71 => 1.3986729667618856,
|
191
|
+
178.85 => -0.16474753695031497,
|
192
|
+
178.72 => -0.2740188624785824,
|
193
|
+
177.15 => -1.5936802553969298
|
194
|
+
}
|
195
|
+
}
|
196
|
+
#=> nil
|
197
|
+
```
|
198
|
+
|
199
|
+
### Playing in the IRB - Indicators
|
200
|
+
|
73
201
|
The SQA::Indicator class methods use Arrays not the DataFrame
|
74
202
|
Here is an example:
|
75
203
|
|
76
204
|
|
77
205
|
```ruby
|
78
|
-
prices = aapl.df.adj_close_price
|
206
|
+
prices = aapl.df.adj_close_price
|
79
207
|
period = 14 # size of the window in prices to analyze
|
80
208
|
|
81
209
|
rsi = SQA::Indicator.rsi(prices, period)
|
210
|
+
#=> {:rsi=>63.46652828230407, :trend=>:normal}
|
82
211
|
```
|
83
212
|
|
84
|
-
###
|
213
|
+
### Playing in the IRB - Strategies
|
85
214
|
|
86
|
-
The strategies work off of an Object that contains the information required to make its recommendation.
|
215
|
+
The strategies work off of an Object that contains the information required to make its recommendation. Building on the previous Ruby snippet ...
|
87
216
|
|
88
217
|
```ruby
|
89
218
|
require 'ostruct'
|
@@ -100,19 +229,24 @@ ss.add SQA::Strategy::RSI
|
|
100
229
|
|
101
230
|
# This is an Array with each "trade" method
|
102
231
|
# that is defined in each strategy added
|
103
|
-
ss.strategies
|
232
|
+
ap ss.strategies
|
233
|
+
[
|
234
|
+
[0] SQA::Strategy::Random#trade(vector),
|
235
|
+
[1] SQA::Strategy::RSI#trade(vector)
|
236
|
+
]
|
104
237
|
|
105
238
|
# Execute those strategies
|
106
239
|
results = ss.execute(vector)
|
240
|
+
#=> [:hold, :hold]
|
107
241
|
```
|
108
242
|
|
109
243
|
`results` is an Array with an entry for each strategy executed. The entries are either :buy, :sell or :hold.
|
110
244
|
|
111
245
|
Currently the strategies are executed sequentially so the results can easily be mapped back to which strategy produced which result. In the future that will change so that the strategies are executed concurrently. When that change is introduced the entries in the `results` object will change -- most likely to an Array of Hashes.
|
112
246
|
|
113
|
-
|
247
|
+
Any specific strategy may not work on every stock. Using the historical data, it is possible to see which strategy works better for a specific stock. **Of course the statistical motto is that historical performance is not a fail-proof indicator for future performance.**
|
114
248
|
|
115
|
-
|
249
|
+
The strategies that come with the `SQA::Strategy` class are examples only. Its expected that you will come up with your own. If you do, consider sharing them.
|
116
250
|
|
117
251
|
## Contributing
|
118
252
|
|
@@ -0,0 +1 @@
|
|
1
|
+
0b3d327017ae67b0ce46082acff8bebdb4a981575e9818418c7279de286a233dde003877f3907b37f3f7e0de236015b4ee4404818d692509c805641862025bc6
|
@@ -0,0 +1 @@
|
|
1
|
+
be42cf0864e1e35a06e177102943577683057e0023751a35421939fc6e096b0e1d16d2e218e33c9c363b45a5a9f57ed22d4361766365154433f5eb371210fb48
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# sqa/lib/patches/string.rb
|
2
|
+
|
3
|
+
|
4
|
+
#####################################################################
|
5
|
+
###
|
6
|
+
## File: string.rb
|
7
|
+
## Desc: Monkey to the String class.
|
8
|
+
#
|
9
|
+
|
10
|
+
class String
|
11
|
+
|
12
|
+
##################################
|
13
|
+
## Convert CamelCase to camel_case
|
14
|
+
def to_underscore
|
15
|
+
self.gsub(/::/, '/')
|
16
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
17
|
+
.gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("- ", "_")
|
18
|
+
.downcase
|
19
|
+
end
|
20
|
+
|
21
|
+
alias :to_snakecase :to_underscore
|
22
|
+
alias :snakecase :to_underscore
|
23
|
+
alias :snake_case :to_underscore
|
24
|
+
alias :underscore :to_underscore
|
25
|
+
|
26
|
+
|
27
|
+
##################################
|
28
|
+
## Convert camel_case to CamelCase
|
29
|
+
def to_camelcase
|
30
|
+
self.gsub(/\/(.?)/) { "::" + $1.upcase }
|
31
|
+
.gsub(/(^|_)(.)/) { $2.upcase }
|
32
|
+
end
|
33
|
+
|
34
|
+
alias :camelcase :to_camelcase
|
35
|
+
alias :camelize :to_camelcase
|
36
|
+
|
37
|
+
|
38
|
+
##################################
|
39
|
+
## Convert "CamelCase" into CamelCase
|
40
|
+
def to_constant
|
41
|
+
names = self.split('::')
|
42
|
+
names.shift if names.empty? || names.first.empty?
|
43
|
+
|
44
|
+
constant = Object
|
45
|
+
names.each do |name|
|
46
|
+
if '1.9' == RUBY_VERSION[0,3]
|
47
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
48
|
+
else
|
49
|
+
constant = constant.const_get(name) || constant.const_missing(name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
constant
|
53
|
+
end
|
54
|
+
|
55
|
+
alias :constantize :to_constant
|
56
|
+
end
|
57
|
+
|
58
|
+
|
data/lib/sqa/data_frame.rb
CHANGED
@@ -74,9 +74,11 @@ class SQA::DataFrame
|
|
74
74
|
def_delegator :@data, :[]=, :[]=
|
75
75
|
|
76
76
|
|
77
|
+
# same as values.transpose
|
78
|
+
# TODO: do benchmark to see if the transpose method if faster
|
77
79
|
def rows
|
78
80
|
result = []
|
79
|
-
|
81
|
+
size.times do |x|
|
80
82
|
entry = row(x)
|
81
83
|
result << entry
|
82
84
|
end
|
@@ -110,14 +112,14 @@ class SQA::DataFrame
|
|
110
112
|
end
|
111
113
|
|
112
114
|
|
113
|
-
def append(new_df)
|
115
|
+
def append!(new_df)
|
114
116
|
raise(BadParameterError, "Key mismatch") if keys != new_df.keys
|
115
117
|
|
116
118
|
keys.each do |key|
|
117
119
|
@data[key] += new_df[key]
|
118
120
|
end
|
119
121
|
end
|
120
|
-
alias_method :concat
|
122
|
+
alias_method :concat!, :append!
|
121
123
|
|
122
124
|
|
123
125
|
# Creates a new instance with new keys
|
@@ -144,7 +146,7 @@ class SQA::DataFrame
|
|
144
146
|
# price: -> (v) {v.to_f.round(3)}
|
145
147
|
# }
|
146
148
|
#
|
147
|
-
def coerce_vectors(transformers)
|
149
|
+
def coerce_vectors!(transformers)
|
148
150
|
transformers.each_pair do |key, transformer|
|
149
151
|
@data[key].map!{|v| transformer.call(v)}
|
150
152
|
end
|
@@ -170,8 +172,8 @@ class SQA::DataFrame
|
|
170
172
|
#################################################
|
171
173
|
class << self
|
172
174
|
|
173
|
-
def
|
174
|
-
base_df.
|
175
|
+
def concat(base_df, other_df)
|
176
|
+
base_df.concat!(other_df)
|
175
177
|
end
|
176
178
|
|
177
179
|
|
@@ -191,7 +193,7 @@ class SQA::DataFrame
|
|
191
193
|
end
|
192
194
|
|
193
195
|
unless transformers.empty?
|
194
|
-
df.coerce_vectors(transformers)
|
196
|
+
df.coerce_vectors!(transformers)
|
195
197
|
end
|
196
198
|
|
197
199
|
df
|
data/lib/sqa/stock.rb
CHANGED
data/lib/sqa/version.rb
CHANGED
data/lib/sqa.rb
CHANGED
@@ -16,13 +16,13 @@ end
|
|
16
16
|
#############################################
|
17
17
|
## Additional Libraries
|
18
18
|
|
19
|
-
require '
|
20
|
-
require 'alphavantage' # TODO: add rate limiter to it; ** PR submitted! **
|
19
|
+
require 'alphavantage'
|
21
20
|
require 'api_key_manager'
|
22
21
|
require 'amazing_print'
|
23
|
-
require 'descriptive_statistics'
|
24
22
|
require 'faraday'
|
25
23
|
require 'hashie'
|
24
|
+
require 'lite/statistics'
|
25
|
+
require 'lite/statistics/monkey_patches' # patch to Enumerable
|
26
26
|
require 'nenv'
|
27
27
|
require 'sem_version'
|
28
28
|
require 'sem_version/core_ext'
|
@@ -30,6 +30,12 @@ require 'tty-option'
|
|
30
30
|
require 'tty-table'
|
31
31
|
|
32
32
|
|
33
|
+
#############################################
|
34
|
+
## Apply core class monkey patches
|
35
|
+
|
36
|
+
require_relative "patches/string.rb"
|
37
|
+
|
38
|
+
|
33
39
|
#############################################
|
34
40
|
## SQA soecufuc code
|
35
41
|
|
@@ -45,7 +51,7 @@ require_relative 'sqa/init.rb'
|
|
45
51
|
|
46
52
|
require_relative "sqa/config"
|
47
53
|
require_relative "sqa/constants" # SMELL: more app than gem
|
48
|
-
require_relative "sqa/data_frame"
|
54
|
+
require_relative "sqa/data_frame"
|
49
55
|
require_relative "sqa/indicator"
|
50
56
|
require_relative "sqa/portfolio"
|
51
57
|
require_relative "sqa/strategy"
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dewayne VanHoozer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - '='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 7.0.6
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - '='
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 7.0.6
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: alphavantage
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,7 +39,7 @@ dependencies:
|
|
53
39
|
- !ruby/object:Gem::Version
|
54
40
|
version: '0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
42
|
+
name: faraday
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - ">="
|
@@ -67,33 +53,33 @@ dependencies:
|
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: hashie
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
|
-
- - "
|
59
|
+
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
61
|
+
version: 4.1.0
|
76
62
|
type: :runtime
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
|
-
- - "
|
66
|
+
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
68
|
+
version: 4.1.0
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
70
|
+
name: lite-statistics
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
|
-
- - "
|
73
|
+
- - ">="
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
75
|
+
version: '0'
|
90
76
|
type: :runtime
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
|
-
- - "
|
80
|
+
- - ">="
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
82
|
+
version: '0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: nenv
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -242,6 +228,8 @@ files:
|
|
242
228
|
- checksums/sqa-0.0.13.gem.sha512
|
243
229
|
- checksums/sqa-0.0.15.gem.sha512
|
244
230
|
- checksums/sqa-0.0.17.gem.sha512
|
231
|
+
- checksums/sqa-0.0.18.gem.sha512
|
232
|
+
- checksums/sqa-0.0.19.gem.sha512
|
245
233
|
- checksums/sqa-0.0.2.gem.sha512
|
246
234
|
- checksums/sqa-0.0.3.gem.sha512
|
247
235
|
- checksums/sqa-0.0.4.gem.sha512
|
@@ -276,6 +264,7 @@ files:
|
|
276
264
|
- docs/stochastic_oscillator.md
|
277
265
|
- docs/strategy.md
|
278
266
|
- docs/true_range.md
|
267
|
+
- lib/patches/string.rb
|
279
268
|
- lib/sqa.rb
|
280
269
|
- lib/sqa/activity.rb
|
281
270
|
- lib/sqa/analysis.rb
|
@@ -349,7 +338,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
349
338
|
- !ruby/object:Gem::Version
|
350
339
|
version: '0'
|
351
340
|
requirements: []
|
352
|
-
rubygems_version: 3.4.
|
341
|
+
rubygems_version: 3.4.21
|
353
342
|
signing_key:
|
354
343
|
specification_version: 4
|
355
344
|
summary: sqa - Stock Qualitative Analysis
|