sqa 0.0.4 → 0.0.5

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: 0f6d2b8e3a8092a5c423c86ebb5a2058d3d1ce9b1f617084009dcb63600fdc88
4
- data.tar.gz: 1b26d1cd8cc77d50567e20cd939c99d103b877681c65dd0cfa72a08feec55ae4
3
+ metadata.gz: 54f8ba7f993ae95bf01b2cdeeb32c76b17b02df6799dc046b85fde9b3d54f202
4
+ data.tar.gz: 91ea7ae14f99322618c3854f7ac16c4ee79c9a7d39609228d589528c381644df
5
5
  SHA512:
6
- metadata.gz: f6f3691cfe84cab52cd2001151e8fdcd2b23951466349b1285c7120b3a170906aa197194d08312f032090659748667393d182fe1e7c69e65a124361d48dc4b44
7
- data.tar.gz: 3a9229b9a64d3306efe90b9bc364c39ef1042ff549709447888df6db9c6c9fbe469a767d1dce667b91edca6b0b80f2df609effe2b3ce7be009d8db14415d28ed
6
+ metadata.gz: 7f20d2ed8800c892905e1155006794832af992c7f1309121860e62cc010b26d23af4d04f6e0b03775b4db0a8dbcafca321ea4c0a39ffc7f6533d6f75bbb59976
7
+ data.tar.gz: 014345e1802899212fb443bec50783988b535d143f7f8fae50ebbacf4a0a9bf52144d6417b395f342fa0f68d94aceb7878179e9eac2bf429f980af9689dd9249
data/README.md CHANGED
@@ -4,23 +4,109 @@ This is a very simplistic set of tools for running technical analysis on a stock
4
4
 
5
5
  The BUY/SELL signals that it generates are part of a game. **DO NOT USE** when real money is at stake.
6
6
 
7
+ ## This is a Work in Progress
8
+
9
+ 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.
10
+
7
11
  ## Installation
8
12
 
9
13
  Install the gem and add to the application's Gemfile by executing:
10
14
 
11
- $ bundle add sqa
15
+ bundle add sqa
12
16
 
13
17
  If bundler is not being used to manage dependencies, install the gem by executing:
14
18
 
15
- $ gem install sqa
19
+ gem install sqa
20
+
21
+ ## ShoutOut To `daru`
22
+
23
+ **D**ata **A**nalysis in **RU**by
24
+
25
+ http://github.com/v0dro/daru
26
+
27
+ Its `DataFrame` class is a very interesting in memory data structure.
16
28
 
17
29
  ## Usage
18
30
 
19
- Do not use!
31
+ **Do not use!**
32
+
33
+ ## Playing in IRB
34
+
35
+ 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.
36
+
37
+ ### With Stocks and Indicators
38
+
39
+ You will need some CSV files.
40
+
41
+ #### Get Historical Prices
42
+
43
+ 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.
44
+
45
+ You may need to create a `portfolio.csv` file or you may not. TODO
46
+
47
+ The CSV files will be named by the stock's ticker symbol. For example: AAPL.csv
48
+
49
+ ```ruby
50
+ require 'sqa'
51
+ # TODO: See the documentation on configurable items
52
+ # Omit to use defaults
53
+ SQA::Config.from_file(path_to_config_file)
54
+
55
+ # initialize framework from configuration values
56
+ SQA.init
57
+
58
+ aapl = SQA::Stock.new('aapl')
59
+ ```
60
+
61
+ `aapl.df` is the Daru::DataFrame
62
+ see the `daru` gem for how to manipulate the DataFrame
63
+ The SQA::Indicator class methods use Arrays not the DataFrame
64
+ Here is an example:
65
+
66
+
67
+ ```ruby
68
+ prices = aapl.df.adj_close_price.to_a
69
+ period = 14 # size of the window in prices to analyze
70
+
71
+ rsi = SQA::Indicator.rsi(prices, period)
72
+ ```
73
+
74
+ ### With Strategies
75
+
76
+ The strategies work off of an Object that contains the information required to make its recommendation. Build on the previous Ruby snippet ...
77
+
78
+ ```ruby
79
+ require 'ostruct'
80
+ vector = OpenStruct.new
81
+ vector.rsi = rsi
82
+
83
+ # Load some trading strategies
84
+ ss = SWA::Strategy.new
85
+ ss.auto_load # loads everything in the lib/sqa/strategy folder
86
+
87
+ # Select some strategies to execute
88
+ ss.add SWA::Strategy::Random # 3-sided coin flip
89
+ ss.add SQA::Strategy::RSI
90
+
91
+ # This is an Array with each "trade" method
92
+ # that is defined in each strategy added
93
+ ss.strategies
94
+
95
+ # Execute those strategies
96
+ results = ss.execute(vector)
97
+ ```
98
+
99
+ `results` is an Array with an entry for each strategy executed. The entries are either :buy, :sell or :hold.
100
+
101
+ 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.
102
+
103
+ ### See my **experiments** Repository in the **stocks** Directory
104
+
105
+ 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.
20
106
 
21
107
  ## Contributing
22
108
 
23
- I can always use some help on this stuff. Got an idea for a new metric or analysis? Want to improve the math? Make the signals better? Let's collaborate!
109
+ I can always use some help on this stuff. Got an idea for a new indicator or strategy? Want to improve the math? Make the signals better? Let's collaborate!
24
110
 
25
111
  Bug reports and pull requests are welcome on GitHub at https://github.com/MadBomber/sqa.
26
112
 
@@ -0,0 +1 @@
1
+ a307251c474edb1367cd0d0a7d2cc663acf98052d070273ff157a155370f87cb43fe10c33403fa53e7b07c9a649d00ef12013c7194fd19ee73c1955e0146b046
@@ -13,4 +13,17 @@ class SQA::DataFrame < Daru::DataFrame
13
13
  df[:ticker] = ticker
14
14
  df
15
15
  end
16
+
17
+ def self.load(filename)
18
+ source = path(filename)
19
+ type = source.extname.downcase
20
+
21
+ if ".csv" == type
22
+ @df = Daru::DataFrame.from_csv(source)
23
+ elsif ".json" == type
24
+ @df = Daru::DataFrame.from_json(source)
25
+ else
26
+ raise SQA::BadParamenterError, "supports csv or json only"
27
+ end
28
+ end
16
29
  end
@@ -0,0 +1,9 @@
1
+ # lib/sqa/portfolio.rb
2
+
3
+ class SQA::Portfolio
4
+ attr_accessor :df
5
+
6
+ def initialize(filename="portfolio.csv")
7
+ @df = SQA::DataFrame.load(filename)
8
+ end
9
+ end
data/lib/sqa/trade.rb ADDED
@@ -0,0 +1,24 @@
1
+ # lib/sqa/trade.rb
2
+
3
+
4
+ class SQA::Trade
5
+ attr_accessor :df
6
+
7
+ def initialize(filename="trades.csv")
8
+ @df = SQA::DataFrame.load(filename)
9
+ end
10
+
11
+ def place(signal, ticker, shares, price=nil)
12
+ # TODO: insert row into @df
13
+
14
+ uuid = rand(100000) # FIXME: place holder
15
+ end
16
+
17
+ def confirm(uuid, shares, price)
18
+ # TODO: update the row in the data frame
19
+ end
20
+
21
+ def save
22
+ # TODO: save the data frame
23
+ end
24
+ end
data/lib/sqa/version.rb CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SQA
4
4
  module Version
5
- VERSION = "0.0.4"
5
+ VERSION = "0.0.5"
6
6
  end
7
7
  end
data/lib/sqa.rb CHANGED
@@ -4,10 +4,6 @@ require 'active_support'
4
4
  require 'active_support/core_ext/string'
5
5
  require 'daru'
6
6
  require 'date'
7
-
8
- require 'debug_me'
9
- include DebugMe
10
-
11
7
  require 'descriptive_statistics'
12
8
  require 'mixlib/config'
13
9
  require 'nenv'
@@ -20,6 +16,22 @@ end
20
16
 
21
17
 
22
18
  module SQA
19
+ Signal = {
20
+ hold: 0,
21
+ buy: 1,
22
+ sell: 2
23
+ }.freeze
24
+
25
+ Trend = {
26
+ up: 0,
27
+ down: 1
28
+ }.freeze
29
+
30
+ Swing = {
31
+ valley: 0,
32
+ peak: 1,
33
+ }.freeze
34
+
23
35
  module Config
24
36
  extend Mixlib::Config
25
37
  config_strict_mode true
@@ -40,8 +52,10 @@ end
40
52
  require_relative "sqa/data_frame"
41
53
  require_relative "sqa/errors"
42
54
  require_relative "sqa/indicator"
55
+ require_relative "sqa/portfolio"
43
56
  require_relative "sqa/strategy"
44
57
  require_relative "sqa/stock"
58
+ require_relative "sqa/trade"
45
59
  require_relative "sqa/version"
46
60
 
47
61
 
metadata CHANGED
@@ -1,15 +1,183 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
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-08-17 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-08-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: active_support
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: daru
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: descriptive_statistics
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: gruff
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mixlib-config
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: nenv
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: version_gem
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: amazing_print
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: bundler
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: debug_me
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: minitest
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rake
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
13
181
  description: Simplistic playpen (e.g. not for serious use) for doing technical analysis
14
182
  of stock prices.
15
183
  email:
@@ -29,6 +197,7 @@ files:
29
197
  - checksums/sqa-0.0.2.gem.sha512
30
198
  - checksums/sqa-0.0.3.gem.sha512
31
199
  - checksums/sqa-0.0.4.gem.sha512
200
+ - checksums/sqa-0.0.5.gem.sha512
32
201
  - docs/README.md
33
202
  - docs/average_true_range.md
34
203
  - docs/bollinger_bands.md
@@ -78,9 +247,10 @@ files:
78
247
  - lib/sqa/indicator/simple_moving_average_trend.rb
79
248
  - lib/sqa/indicator/stochastic_oscillator.rb
80
249
  - lib/sqa/indicator/true_range.rb
81
- - lib/sqa/protfolio.rb
250
+ - lib/sqa/portfolio.rb
82
251
  - lib/sqa/stock.rb
83
252
  - lib/sqa/strategy.rb
253
+ - lib/sqa/strategy/README.md
84
254
  - lib/sqa/strategy/common.rb
85
255
  - lib/sqa/strategy/consensus.rb
86
256
  - lib/sqa/strategy/ema.rb
@@ -90,7 +260,7 @@ files:
90
260
  - lib/sqa/strategy/random.rb
91
261
  - lib/sqa/strategy/rsi.rb
92
262
  - lib/sqa/strategy/sma.rb
93
- - lib/sqa/strategyREADME.md
263
+ - lib/sqa/trade.rb
94
264
  - lib/sqa/version.rb
95
265
  homepage: https://github.com/MadBomber/sqa
96
266
  licenses:
data/lib/sqa/protfolio.rb DELETED
@@ -1,8 +0,0 @@
1
- # lib/sqa/portfolio.rb
2
-
3
- # A collection of stocks
4
- # primary id is ticker its unique
5
-
6
- class SQA::Portfolio < ActiveRecord::Base
7
- has_many :stocks # use ticker as the foreign key
8
- end
File without changes