sqa 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 911775606b7e0fa046261c5a9bc4d3be21ca9caf38c37011141f1393ac6e5063
4
- data.tar.gz: d70ae996a39dbe7c386750286cb4cc437681d584945b31104e91b06c30b1600f
3
+ metadata.gz: b7733f5cb84c4ccbad5e68105e818b35f1aca450fd97eeb3186cfb9a1962d44e
4
+ data.tar.gz: a9b2bf2a0fa6a91de1367fd73beac6a28d263024ded37c216520120cc3181cc9
5
5
  SHA512:
6
- metadata.gz: '0074688f69947d20d5aae7c81b090a91fb4f06862084b2349b248ecdf2e17376f47d5a1acffbfb7b2700865cf25f5ff5ba054514d00ed88750f46224b4c9360e'
7
- data.tar.gz: 38d1ebf511e9dfa2b87084ed77093e2fc03ccf6eeb6a00e42d1060acca82e135d0b4c0d36a25d9f9bc4a2dd9adf91749a6640aab14b304e33f24fee0c3eb7e15
6
+ metadata.gz: 27280c675c37a92f450d5108c40848cc65a3975e8e783ca25cbbee0bfa18b1c570d697c4c33d4fd73d84c57d717df3e6cbb8667c51fb3ed8fe48df509f9d1f7e
7
+ data.tar.gz: 475333a102814f5bef21dbea61126bf6b0b61836cccb6a333acc2dbcaa2ba5bc14c8c9191b31065777ca984fcec883fb37da36b07a9121f2afeb0a0004bc841b
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 are part of a game. **DO NOT USE** when real money is at stake.
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'm making use of lots of gems which may not be part of the gemspec at this time. I will be adding them as they make the final cut as to fitness for the intended function. Some gems are configurable. For example the default for the plotting library is `gruff`. There are several available that the `daru` gem can use.
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
- ## ShoutOut To `daru`
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
- **D**ata **A**nalysis in **RU**by
33
+ `SQA` can be used from the command line or as a library in your own application.
34
34
 
35
- http://github.com/v0dro/daru
35
+ `SQA` has a command line component.
36
36
 
37
- Its `DataFrame` class is a very interesting in memory data structure.
37
+ ```plaintext
38
+ $ sqa --help
39
+ Stock Quantitative Analysis (SQA)
38
40
 
39
- ## Usage
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 in two different areas. First is the stocks and indicators. The second is with trading strategies.
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 in to the `sqa_data` directory in your HOME directory.
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: AAPL.csv
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
- # TODO: See the documentation on configurable items
62
- # Omit to use defaults
63
- SQA::Config.from_file(path_to_config_file)
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
- # initialize framework from configuration values
66
- SQA.init
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 = SQA::Stock.new('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.df` is the Daru::DataFrame
72
- see the `daru` gem for how to manipulate the DataFrame
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.to_a
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
- ### With Strategies
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. Build on the previous Ruby snippet ...
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
- ### See my **experiments** Repository in the **stocks** Directory
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
- I have a program `analysis.rb` that I'm writing along with this `sqa` gem. Its intended as a practical example/test case for how the gem can be used to analyze a complete portfolio one stock at a time.
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
data/lib/sqa/stock.rb CHANGED
@@ -104,7 +104,7 @@ class SQA::Stock
104
104
  @df.append(df2)
105
105
 
106
106
  if @df.nrows > df_nrows
107
- @df.to_csv(file_path)
107
+ @df.to_csv(@df_path)
108
108
  end
109
109
  end
110
110
 
data/lib/sqa/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SQA
4
- VERSION = "0.0.17"
4
+ VERSION = "0.0.18"
5
5
 
6
6
  class << self
7
7
  def version
data/lib/sqa.rb CHANGED
@@ -20,9 +20,10 @@ require 'active_support/core_ext/string'
20
20
  require 'alphavantage' # TODO: add rate limiter to it; ** PR submitted! **
21
21
  require 'api_key_manager'
22
22
  require 'amazing_print'
23
- require 'descriptive_statistics'
24
23
  require 'faraday'
25
24
  require 'hashie'
25
+ require 'lite/statistics'
26
+ require 'lite/statistics/monkey_patches' # patch to Enumerable
26
27
  require 'nenv'
27
28
  require 'sem_version'
28
29
  require 'sem_version/core_ext'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
4
+ version: 0.0.18
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-09 00:00:00.000000000 Z
11
+ date: 2023-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: descriptive_statistics
56
+ name: faraday
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,33 +67,33 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: faraday
70
+ name: hashie
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: 4.1.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: 4.1.0
83
83
  - !ruby/object:Gem::Dependency
84
- name: hashie
84
+ name: lite-statistics
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 4.1.0
89
+ version: '0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: 4.1.0
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: nenv
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -242,6 +242,7 @@ files:
242
242
  - checksums/sqa-0.0.13.gem.sha512
243
243
  - checksums/sqa-0.0.15.gem.sha512
244
244
  - checksums/sqa-0.0.17.gem.sha512
245
+ - checksums/sqa-0.0.18.gem.sha512
245
246
  - checksums/sqa-0.0.2.gem.sha512
246
247
  - checksums/sqa-0.0.3.gem.sha512
247
248
  - checksums/sqa-0.0.4.gem.sha512
@@ -349,7 +350,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
349
350
  - !ruby/object:Gem::Version
350
351
  version: '0'
351
352
  requirements: []
352
- rubygems_version: 3.4.20
353
+ rubygems_version: 3.4.21
353
354
  signing_key:
354
355
  specification_version: 4
355
356
  summary: sqa - Stock Qualitative Analysis