sqa 0.0.22 → 0.0.24
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.md +4 -0
- data/README.md +70 -0
- data/checksums/sqa-0.0.23.gem.sha512 +1 -0
- data/checksums/sqa-0.0.24.gem.sha512 +1 -0
- data/docs/ta_lib.md +160 -0
- data/lib/patches/dry-cli.rb +228 -0
- data/lib/sqa/cli.rb +16 -127
- data/lib/sqa/{analysis.rb → commands/analysis.rb} +17 -14
- data/lib/sqa/commands/base.rb +139 -0
- data/lib/sqa/{web.rb → commands/web.rb} +78 -38
- data/lib/sqa/commands.rb +22 -0
- data/lib/sqa/config.rb +22 -9
- data/lib/sqa/data_frame/yahoo_finance.rb +1 -0
- data/lib/sqa/indicator/average_true_range.rb +0 -10
- data/lib/sqa/init.rb +1 -1
- data/lib/sqa/plugin_manager.rb +20 -0
- data/lib/sqa/stock.rb +29 -0
- data/lib/sqa/strategy/common.rb +0 -2
- data/lib/sqa/version.rb +1 -1
- data/lib/sqa.rb +22 -2
- metadata +34 -13
data/lib/sqa/cli.rb
CHANGED
@@ -1,135 +1,40 @@
|
|
1
1
|
# lib/sqa/cli.rb
|
2
2
|
|
3
|
+
require 'dry/cli'
|
3
4
|
|
4
5
|
require_relative '../sqa'
|
6
|
+
require_relative 'commands'
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
module SQA
|
12
|
-
class CLI
|
13
|
-
include TTY::Option
|
14
|
-
|
15
|
-
header "Stock Quantitative Analysis (SQA)"
|
16
|
-
footer "WARNING: This is a toy, a play thing, not intended for serious use."
|
17
|
-
|
18
|
-
program "sqa"
|
19
|
-
desc "A collection of things"
|
20
|
-
|
21
|
-
example "sqa -c ~/.sqa.yml -p portfolio.csv -t trades.csv --data-dir ~/sqa_data"
|
22
|
-
|
23
|
-
|
24
|
-
option :config_file do
|
25
|
-
short "-c string"
|
26
|
-
long "--config string"
|
27
|
-
desc "Path to the config file"
|
8
|
+
module SQA::CLI
|
9
|
+
class << self
|
10
|
+
def run!
|
11
|
+
Dry::CLI.new(SQA::Commands).call
|
28
12
|
end
|
13
|
+
end
|
14
|
+
end
|
29
15
|
|
30
|
-
option :log_level do
|
31
|
-
short "-l string"
|
32
|
-
long "--log_level string"
|
33
|
-
# default SQA.config.log_level
|
34
|
-
desc "Set the log level (debug, info, warn, error, fatal)"
|
35
|
-
end
|
36
16
|
|
37
|
-
option :portfolio do
|
38
|
-
short "-p string"
|
39
|
-
long "--portfolio string"
|
40
|
-
# default SQA.config.portfolio_filename
|
41
|
-
desc "Set the filename of the portfolio"
|
42
|
-
end
|
43
17
|
|
44
18
|
|
45
|
-
|
46
|
-
short "-t string"
|
47
|
-
long "--trades string"
|
48
|
-
# default SQA.config.trades_filename
|
49
|
-
desc "Set the filename into which trades are stored"
|
50
|
-
end
|
19
|
+
__END__
|
51
20
|
|
52
21
|
|
53
|
-
option :data_dir do
|
54
|
-
long "--data-dir string"
|
55
|
-
# default SQA.config.data_dir
|
56
|
-
desc "Set the directory for the SQA data"
|
57
|
-
end
|
58
22
|
|
59
|
-
option :dump_config do
|
60
|
-
long "--dump-config path_to_file"
|
61
|
-
desc "Dump the current configuration"
|
62
|
-
end
|
63
23
|
|
64
|
-
|
65
|
-
|
66
|
-
long "--help"
|
67
|
-
desc "Print usage"
|
68
|
-
end
|
24
|
+
# header "Stock Quantitative Analysis (SQA)"
|
25
|
+
# footer "WARNING: This is a toy, a play thing, not intended for serious use."
|
69
26
|
|
70
|
-
|
71
|
-
|
72
|
-
desc "Print version"
|
73
|
-
end
|
27
|
+
# program "sqa"
|
28
|
+
# desc "A collection of things"
|
74
29
|
|
75
|
-
flag :debug do
|
76
|
-
short "-d"
|
77
|
-
long "--debug"
|
78
|
-
# default SQA.config.debug
|
79
|
-
desc "Turn on debugging output"
|
80
|
-
end
|
81
30
|
|
82
|
-
flag :verbose do
|
83
|
-
short "-v"
|
84
|
-
long "--verbose"
|
85
|
-
# default SQA.config.debug
|
86
|
-
desc "Print verbosely"
|
87
|
-
end
|
88
31
|
|
89
|
-
class << self
|
90
|
-
@@subclasses = []
|
91
|
-
@@commands_available = []
|
92
|
-
|
93
|
-
def names
|
94
|
-
'['+ @@commands_available.join('|')+']'
|
95
|
-
end
|
96
|
-
|
97
|
-
def inherited(subclass)
|
98
|
-
super
|
99
|
-
@@subclasses << subclass
|
100
|
-
@@commands_available << subclass.command.join
|
101
|
-
end
|
102
|
-
|
103
|
-
def command_descriptions
|
104
|
-
help_block = "Optional Command Available:"
|
105
|
-
|
106
|
-
@@commands_available.size.times do |x|
|
107
|
-
klass = @@subclasses[x]
|
108
|
-
help_block << "\n " + @@commands_available[x] + " - "
|
109
|
-
help_block << klass.desc.join
|
110
|
-
end
|
111
|
-
|
112
|
-
help_block
|
113
|
-
end
|
114
32
|
|
33
|
+
class << self
|
115
34
|
|
116
35
|
##################################################
|
117
36
|
def run(argv = ARGV)
|
118
|
-
cli = new
|
119
|
-
parser = cli.parse(argv)
|
120
|
-
params = parser.params
|
121
37
|
|
122
|
-
if params[:help]
|
123
|
-
print parser.help
|
124
|
-
exit(0)
|
125
|
-
|
126
|
-
elsif params.errors.any?
|
127
|
-
puts params.errors.summary
|
128
|
-
exit(1)
|
129
|
-
|
130
|
-
elsif params[:version]
|
131
|
-
puts SQA.version
|
132
|
-
exit(0)
|
133
38
|
|
134
39
|
elsif params[:dump_config]
|
135
40
|
SQA.config.config_file = params[:dump_config]
|
@@ -144,30 +49,14 @@ module SQA
|
|
144
49
|
SQA.config.from_file
|
145
50
|
end
|
146
51
|
|
52
|
+
|
53
|
+
|
147
54
|
# Override the defaults <- envars <- config file <- cli parameters
|
148
55
|
SQA.config.merge!(remove_temps params.to_h)
|
149
56
|
|
150
|
-
if SQA.debug? || SQA.verbose?
|
151
|
-
debug_me("config after CLI parameters"){[
|
152
|
-
"SQA.config"
|
153
|
-
]}
|
154
|
-
end
|
155
|
-
end
|
156
57
|
|
157
|
-
def remove_temps(a_hash)
|
158
|
-
temps = %i[ help version dump ]
|
159
|
-
# debug_me{[ :a_hash ]}
|
160
|
-
a_hash.reject{|k, _| temps.include? k}
|
161
58
|
end
|
162
59
|
end
|
163
60
|
end
|
164
61
|
end
|
165
62
|
|
166
|
-
require_relative 'analysis'
|
167
|
-
require_relative 'web'
|
168
|
-
|
169
|
-
# First Load TTY-Option's command content with all available commands
|
170
|
-
# then these have access to the entire ObjectSpace ...
|
171
|
-
SQA::CLI.command SQA::CLI.names
|
172
|
-
SQA::CLI.example SQA::CLI.command_descriptions
|
173
|
-
|
@@ -1,18 +1,26 @@
|
|
1
|
-
# lib/sqa/
|
1
|
+
# sqa/lib/sqa/commands/analysis.rb
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
include TTY::Option
|
3
|
+
class Commands::Analysis < Commands::Base
|
4
|
+
VERSION = "0.0.1-analysis"
|
6
5
|
|
7
|
-
|
6
|
+
Commands.register "analysis", self
|
8
7
|
|
9
|
-
|
8
|
+
desc "Provide an Analysis of a Portfolio"
|
10
9
|
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
end
|
11
|
+
def initialize
|
12
|
+
# TODO: something
|
15
13
|
end
|
14
|
+
|
15
|
+
def call(params)
|
16
|
+
config = super
|
17
|
+
|
18
|
+
puts <<~EOS
|
19
|
+
##################################
|
20
|
+
## Running the Analysis Command ##
|
21
|
+
##################################
|
22
|
+
EOS
|
23
|
+
end
|
16
24
|
end
|
17
25
|
|
18
26
|
__END__
|
@@ -270,11 +278,6 @@ tickers.each do |ticker|
|
|
270
278
|
values << row
|
271
279
|
end
|
272
280
|
|
273
|
-
# debug_me{[
|
274
|
-
# :result
|
275
|
-
# ]}
|
276
|
-
|
277
|
-
|
278
281
|
the_table = TTY::Table.new(headers, values)
|
279
282
|
|
280
283
|
puts
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# .../sqa/cli/commands/base.rb
|
2
|
+
|
3
|
+
# SQA.config will be built with its defaults
|
4
|
+
# and envar over-rides BEFORE a command is
|
5
|
+
# process. This means that options do not
|
6
|
+
# need to have a "default" value.
|
7
|
+
|
8
|
+
# Establish a Base command class that has global options
|
9
|
+
# available to all commands.
|
10
|
+
|
11
|
+
class Commands::Base < Dry::CLI::Command
|
12
|
+
# keys from Dry::Cli options which we do not want in the
|
13
|
+
# config object.
|
14
|
+
IGNORE_OPTIONS = %i[ version ]
|
15
|
+
|
16
|
+
global_header <<~EOS
|
17
|
+
|
18
|
+
SQA - Stock Quantitative Analysis
|
19
|
+
by: MadBomber
|
20
|
+
|
21
|
+
This is a work in progress. It is not fit for anything
|
22
|
+
other than play time. ** Do not ** use it to make any
|
23
|
+
kind of serious trading decisions.
|
24
|
+
|
25
|
+
EOS
|
26
|
+
|
27
|
+
global_footer <<~EOS
|
28
|
+
|
29
|
+
SARNING: This product is a work in progress. DO NOT USE
|
30
|
+
for serious trading decisions.
|
31
|
+
|
32
|
+
Copyright (c) 2023 - MadBomber Software
|
33
|
+
|
34
|
+
EOS
|
35
|
+
|
36
|
+
option :debug,
|
37
|
+
required: false,
|
38
|
+
type: :boolean,
|
39
|
+
desc: 'Print debug information',
|
40
|
+
aliases: %w[-d --debug]
|
41
|
+
|
42
|
+
option :verbose,
|
43
|
+
required: false,
|
44
|
+
type: :boolean,
|
45
|
+
desc: 'Print verbose information',
|
46
|
+
aliases: %w[-v --verbose]
|
47
|
+
|
48
|
+
|
49
|
+
option :version,
|
50
|
+
required: false,
|
51
|
+
type: :boolean,
|
52
|
+
default: false,
|
53
|
+
desc: 'Print version(s) and exit',
|
54
|
+
aliases: %w[--version]
|
55
|
+
|
56
|
+
|
57
|
+
option :config_file,
|
58
|
+
required: false,
|
59
|
+
type: :string,
|
60
|
+
desc: "Path to the config file"
|
61
|
+
|
62
|
+
|
63
|
+
option :log_level,
|
64
|
+
required: false,
|
65
|
+
type: :string,
|
66
|
+
values: %w[debug info warn error fatal ],
|
67
|
+
desc: "Set the log level"
|
68
|
+
|
69
|
+
|
70
|
+
option :portfolio,
|
71
|
+
required: false,
|
72
|
+
aliases: %w[ --portfolio --folio --file -f ],
|
73
|
+
type: :string,
|
74
|
+
desc: "Set the filename of the portfolio"
|
75
|
+
|
76
|
+
|
77
|
+
option :trades,
|
78
|
+
required: false,
|
79
|
+
aliases: %w[ --trades ],
|
80
|
+
type: :string,
|
81
|
+
desc: "Set the filename into which trades are stored"
|
82
|
+
|
83
|
+
|
84
|
+
option :data_dir,
|
85
|
+
required: false,
|
86
|
+
aliases: %w[ --data-dir --data --dir ],
|
87
|
+
type: :string,
|
88
|
+
desc: "Set the directory for the SQA data"
|
89
|
+
|
90
|
+
|
91
|
+
option :dump_config,
|
92
|
+
required: false,
|
93
|
+
type: :string,
|
94
|
+
desc: "Dump the current configuration to a file"
|
95
|
+
|
96
|
+
|
97
|
+
# All command class call methods should start with
|
98
|
+
# super so that this method is invoked.
|
99
|
+
#
|
100
|
+
# params is a Hash from Dry::CLI where keys are Symbol
|
101
|
+
|
102
|
+
def call(params)
|
103
|
+
show_versions_and_exit if params[:version]
|
104
|
+
|
105
|
+
unless params[:config_file].nil? || params[:config_file].empty?
|
106
|
+
SQA.config.config_file = params[:config_file]
|
107
|
+
SQA.config.from_file
|
108
|
+
end
|
109
|
+
|
110
|
+
update_config(params)
|
111
|
+
|
112
|
+
unless params[:dump_config].nil? || params[:dump_config].empty?
|
113
|
+
SQA.config.config_file = params[:dump_config]
|
114
|
+
SQA.config.dump_file
|
115
|
+
end
|
116
|
+
|
117
|
+
SQA.config
|
118
|
+
end
|
119
|
+
|
120
|
+
################################################
|
121
|
+
private
|
122
|
+
|
123
|
+
def show_versions_and_exit
|
124
|
+
self.class.ancestors.each do |ancestor|
|
125
|
+
next unless ancestor.const_defined?(:VERSION)
|
126
|
+
puts "#{ancestor}: #{ancestor::VERSION}"
|
127
|
+
end
|
128
|
+
|
129
|
+
puts "SQA: #{SQA::VERSION}" if SQA.const_defined?(:VERSION)
|
130
|
+
|
131
|
+
exit(0)
|
132
|
+
end
|
133
|
+
|
134
|
+
def update_config(params)
|
135
|
+
SQA.config.inject_additional_properties
|
136
|
+
my_hash = params.reject { |key, _| IGNORE_OPTIONS.include?(key) }
|
137
|
+
SQA.config.merge!(my_hash)
|
138
|
+
end
|
139
|
+
end
|
@@ -1,63 +1,103 @@
|
|
1
|
-
# lib/sqa/
|
1
|
+
# sqa/lib/sqa/commands/web.rb
|
2
2
|
|
3
|
-
|
3
|
+
class Commands::Web < Commands::Base
|
4
|
+
VERSION = "0.0.1-web"
|
4
5
|
|
6
|
+
Commands.register "web", self
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
desc "Start a web application"
|
9
|
+
|
10
|
+
option :image,
|
11
|
+
required: true,
|
12
|
+
type: :string,
|
13
|
+
desc: "The name of the image to use"
|
14
|
+
|
15
|
+
SQA::PluginManager.new_property(:restart, default: 'no', coerce: String)
|
16
|
+
|
17
|
+
option :restart,
|
18
|
+
aliases: %w[ --restart ],
|
19
|
+
type: :string,
|
20
|
+
default: "no",
|
21
|
+
values: %w[ no on-failure always unless-stopped ],
|
22
|
+
desc: "Restart policy to apply when a container exits"
|
23
|
+
|
24
|
+
SQA::PluginManager.new_property(:detach, default: 'no', coerce: String)
|
25
|
+
|
26
|
+
option :detach,
|
27
|
+
aliases: %w[ --detach ],
|
28
|
+
type: :boolean,
|
29
|
+
default: false,
|
30
|
+
desc: "Run container in background and print container ID"
|
31
|
+
|
32
|
+
SQA::PluginManager.new_property(:port, default: 4567, coerce: Integer)
|
9
33
|
|
10
|
-
|
34
|
+
option :port,
|
35
|
+
aliases: %w[ -p --port ],
|
36
|
+
type: :integer,
|
37
|
+
default: 4567,
|
38
|
+
desc: "The port where the web app will run"
|
11
39
|
|
12
|
-
desc "Run a web server"
|
13
40
|
|
14
|
-
|
15
|
-
|
41
|
+
def initialize
|
42
|
+
# TODO: make it happen
|
43
|
+
end
|
44
|
+
|
16
45
|
|
17
|
-
|
18
|
-
|
19
|
-
|
46
|
+
# params is Object from the ARGV parser
|
47
|
+
def call(params)
|
48
|
+
config = super
|
49
|
+
|
50
|
+
puts <<~EOS
|
51
|
+
###############################
|
52
|
+
## Running the Web Interface ##
|
53
|
+
###############################
|
20
54
|
EOS
|
55
|
+
end
|
56
|
+
end
|
21
57
|
|
22
|
-
argument :image do
|
23
|
-
required
|
24
|
-
desc "The name of the image to use"
|
25
|
-
end
|
26
58
|
|
27
|
-
keyword :restart do
|
28
|
-
default "no"
|
29
|
-
permit %w[no on-failure always unless-stopped]
|
30
|
-
desc "Restart policy to apply when a container exits"
|
31
|
-
end
|
32
59
|
|
33
|
-
|
34
|
-
|
35
|
-
|
60
|
+
__END__
|
61
|
+
|
62
|
+
require 'sinatra/base'
|
63
|
+
|
64
|
+
module SQA
|
65
|
+
class Web < Sinatra::Base
|
66
|
+
set :port, SQA.config.port || 4567
|
67
|
+
|
68
|
+
get '/' do
|
69
|
+
"Welcome to SQA Web Interface!"
|
36
70
|
end
|
37
71
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
72
|
+
|
73
|
+
get '/stocks/:ticker' do
|
74
|
+
ticker = params[:ticker]
|
75
|
+
stock = SQA::Stock.new(ticker: ticker, source: :alpha_vantage)
|
76
|
+
|
77
|
+
"Stock: #{stock.data.name}, Ticker: #{stock.data.ticker}"
|
42
78
|
end
|
43
79
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
80
|
+
|
81
|
+
get '/stocks/:ticker/indicators/:indicator' do
|
82
|
+
ticker = params[:ticker]
|
83
|
+
indicator = params[:indicator]
|
84
|
+
stock = SQA::Stock.new(ticker: ticker, source: :alpha_vantage)
|
85
|
+
|
86
|
+
indicator_value = SQA::Indicator.send(indicator, stock.df.adj_close_price, 14)
|
87
|
+
|
88
|
+
"Indicator #{indicator} for Stock #{ticker} is #{indicator_value}"
|
49
89
|
end
|
50
90
|
|
91
|
+
# TODO: Add more routes as needed to expose more functionality
|
51
92
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
93
|
+
# start the server if ruby file executed directly
|
94
|
+
run! if app_file == $0
|
95
|
+
end
|
56
96
|
end
|
57
97
|
|
58
|
-
__END__
|
59
98
|
|
60
99
|
|
100
|
+
###################################################
|
61
101
|
#!/usr/bin/env ruby
|
62
102
|
# experiments/sinatra_examples/svg_viewer.rb
|
63
103
|
# builds on md_viewer.rb
|
data/lib/sqa/commands.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# sqa/lib/sqa/commands.rb
|
2
|
+
|
3
|
+
# Adds command options to SQA.config
|
4
|
+
require_relative "plugin_manager"
|
5
|
+
|
6
|
+
module SQA::Commands
|
7
|
+
# Establish the command registry
|
8
|
+
extend Dry::CLI::Registry
|
9
|
+
end
|
10
|
+
|
11
|
+
Commands = SQA::Commands
|
12
|
+
|
13
|
+
|
14
|
+
load_these_first = [
|
15
|
+
"#{__dir__}/commands/base.rb",
|
16
|
+
].each { |file| require_relative file }
|
17
|
+
|
18
|
+
Dir.glob("#{__dir__}/commands/*.rb")
|
19
|
+
.reject{|file| load_these_first.include? file}
|
20
|
+
.each do |file|
|
21
|
+
require_relative file
|
22
|
+
end
|
data/lib/sqa/config.rb
CHANGED
@@ -6,10 +6,18 @@
|
|
6
6
|
# config file ..... overrides envar
|
7
7
|
# command line parameters ...... overrides config file
|
8
8
|
|
9
|
+
require 'yaml'
|
10
|
+
require 'toml-rb'
|
9
11
|
|
10
12
|
module SQA
|
13
|
+
# class Config < Hashie::Trash
|
14
|
+
# include Hashie::Extensions::IgnoreUndeclared
|
15
|
+
# include Hashie::Extensions::Coercion
|
16
|
+
|
17
|
+
|
11
18
|
class Config < Hashie::Dash
|
12
19
|
include Hashie::Extensions::Dash::PropertyTranslation
|
20
|
+
include Hashie::Extensions::MethodAccess
|
13
21
|
include Hashie::Extensions::Coercion
|
14
22
|
|
15
23
|
# FIXME: Getting undefined error PredefinedValues
|
@@ -19,7 +27,8 @@ module SQA
|
|
19
27
|
#
|
20
28
|
# include Hashie::Extensions::Dash::PredefinedValues
|
21
29
|
|
22
|
-
property :
|
30
|
+
property :command # a String currently, nil, analysis or web
|
31
|
+
property :config_file # a String filepath for the current config overriden by cli options
|
23
32
|
property :dump_config # a String filepath into which to dump the current config
|
24
33
|
|
25
34
|
property :data_dir, default: Nenv.home + "/sqa_data"
|
@@ -111,13 +120,10 @@ module SQA
|
|
111
120
|
raise BadParameterError, "No config file given"
|
112
121
|
end
|
113
122
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
else
|
119
|
-
type = "invalid"
|
120
|
-
end
|
123
|
+
`touch #{config_file}`
|
124
|
+
# unless File.exist?(config_file)
|
125
|
+
|
126
|
+
type = File.extname(config_file).downcase
|
121
127
|
|
122
128
|
if ".json" == type
|
123
129
|
dump_json
|
@@ -129,7 +135,14 @@ module SQA
|
|
129
135
|
dump_toml
|
130
136
|
|
131
137
|
else
|
132
|
-
raise BadParameterError, "Invalid Config File: #{config_file}"
|
138
|
+
raise BadParameterError, "Invalid Config File Type: #{config_file}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Method to dynamically extend properties from external sources (e.g., plugins)
|
143
|
+
def inject_additional_properties
|
144
|
+
SQA::PluginManager.registered_properties.each do |prop, options|
|
145
|
+
self.class.property(prop, options)
|
133
146
|
end
|
134
147
|
end
|
135
148
|
|
@@ -13,8 +13,6 @@ class SQA::Indicator; class << self
|
|
13
13
|
true_ranges = true_range(high_prices, low_prices, close_prices)
|
14
14
|
atr_values = []
|
15
15
|
|
16
|
-
# debug_me{[ :period, :true_ranges ]}
|
17
|
-
|
18
16
|
window_span = period - 1
|
19
17
|
|
20
18
|
true_ranges.size.times do |inx|
|
@@ -25,14 +23,6 @@ class SQA::Indicator; class << self
|
|
25
23
|
|
26
24
|
window = true_ranges[start_inx..end_inx]
|
27
25
|
|
28
|
-
# debug_me{[
|
29
|
-
# :inx,
|
30
|
-
# :start_inx,
|
31
|
-
# :end_inx,
|
32
|
-
# :window,
|
33
|
-
# "window.mean"
|
34
|
-
# ]}
|
35
|
-
|
36
26
|
atr_values << window.mean
|
37
27
|
end
|
38
28
|
|
data/lib/sqa/init.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
# lib/sqa/plugin_manager.rb
|
2
|
+
|
3
|
+
# This class gives plug-in commands a way
|
4
|
+
# to extend the SQA::Config class propertities.
|
5
|
+
|
6
|
+
module SQA
|
7
|
+
class PluginManager
|
8
|
+
@registered_properties = {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :registered_properties
|
12
|
+
|
13
|
+
# name (Symbol)
|
14
|
+
|
15
|
+
def new_property(name, options = {})
|
16
|
+
@registered_properties[name.to_sym] = options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/sqa/stock.rb
CHANGED
@@ -16,6 +16,11 @@ class SQA::Stock
|
|
16
16
|
attr_accessor :klass # class of historical and current prices
|
17
17
|
attr_accessor :transformers # procs for changing column values from String to Numeric
|
18
18
|
|
19
|
+
# Holds the SQA::Strategy class name which seems to work
|
20
|
+
# the best for this stock.
|
21
|
+
attr_accessor :strategy # TODO: make part of the @data object
|
22
|
+
|
23
|
+
|
19
24
|
def initialize(
|
20
25
|
ticker:,
|
21
26
|
source: :alpha_vantage
|
@@ -146,6 +151,30 @@ class SQA::Stock
|
|
146
151
|
end
|
147
152
|
|
148
153
|
|
154
|
+
def associate_best_strategy(strategies)
|
155
|
+
best_strategy = nil
|
156
|
+
best_accuracy = 0
|
157
|
+
|
158
|
+
strategies.each do |strategy|
|
159
|
+
accuracy = evaluate_strategy(strategy)
|
160
|
+
|
161
|
+
if accuracy > best_accuracy
|
162
|
+
best_strategy = strategy
|
163
|
+
best_accuracy = accuracy
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
self.strategy = best_strategy
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
def evaluate_strategy(strategy)
|
172
|
+
# TODO: Implement this method to evaluate the accuracy of the strategy
|
173
|
+
# on the historical data of this stock.
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
|
149
178
|
#############################################
|
150
179
|
## Class Methods
|
151
180
|
|