sqa 0.0.32 → 0.0.37
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 +92 -1
- data/README.md +4 -0
- data/Rakefile +52 -10
- data/docs/IMPROVEMENT_PLAN.md +531 -0
- data/docs/advanced/index.md +1 -13
- data/docs/api/index.md +547 -61
- data/docs/api-reference/alphavantageapi.md +1057 -0
- data/docs/api-reference/apierror.md +31 -0
- data/docs/api-reference/index.md +221 -0
- data/docs/api-reference/notimplemented.md +27 -0
- data/docs/api-reference/sqa.md +267 -0
- data/docs/api-reference/sqa_backtest.md +137 -0
- data/docs/api-reference/sqa_backtest_results.md +530 -0
- data/docs/api-reference/sqa_badparametererror.md +13 -0
- data/docs/api-reference/sqa_config.md +538 -0
- data/docs/api-reference/sqa_configurationerror.md +13 -0
- data/docs/api-reference/sqa_datafetcherror.md +56 -0
- data/docs/api-reference/sqa_dataframe.md +752 -0
- data/docs/api-reference/sqa_dataframe_alphavantage.md +30 -0
- data/docs/api-reference/sqa_dataframe_data.md +325 -0
- data/docs/api-reference/sqa_dataframe_yahoofinance.md +25 -0
- data/docs/api-reference/sqa_ensemble.md +413 -0
- data/docs/api-reference/sqa_fpop.md +211 -0
- data/docs/api-reference/sqa_geneticprogram.md +325 -0
- data/docs/api-reference/sqa_geneticprogram_individual.md +114 -0
- data/docs/api-reference/sqa_marketregime.md +212 -0
- data/docs/api-reference/sqa_multitimeframe.md +227 -0
- data/docs/api-reference/sqa_patternmatcher.md +195 -0
- data/docs/api-reference/sqa_pluginmanager.md +55 -0
- data/docs/api-reference/sqa_portfolio.md +455 -0
- data/docs/api-reference/sqa_portfolio_position.md +220 -0
- data/docs/api-reference/sqa_portfolio_trade.md +332 -0
- data/docs/api-reference/sqa_portfoliooptimizer.md +248 -0
- data/docs/api-reference/sqa_riskmanager.md +388 -0
- data/docs/api-reference/sqa_seasonalanalyzer.md +121 -0
- data/docs/api-reference/sqa_sectoranalyzer.md +163 -0
- data/docs/api-reference/sqa_stock.md +649 -0
- data/docs/api-reference/sqa_strategy.md +178 -0
- data/docs/api-reference/sqa_strategy_bollingerbands.md +26 -0
- data/docs/api-reference/sqa_strategy_common.md +29 -0
- data/docs/api-reference/sqa_strategy_consensus.md +129 -0
- data/docs/api-reference/sqa_strategy_ema.md +41 -0
- data/docs/api-reference/sqa_strategy_kbs.md +154 -0
- data/docs/api-reference/sqa_strategy_macd.md +26 -0
- data/docs/api-reference/sqa_strategy_mp.md +41 -0
- data/docs/api-reference/sqa_strategy_mr.md +41 -0
- data/docs/api-reference/sqa_strategy_random.md +41 -0
- data/docs/api-reference/sqa_strategy_rsi.md +41 -0
- data/docs/api-reference/sqa_strategy_sma.md +41 -0
- data/docs/api-reference/sqa_strategy_stochastic.md +26 -0
- data/docs/api-reference/sqa_strategy_volumebreakout.md +26 -0
- data/docs/api-reference/sqa_strategygenerator.md +298 -0
- data/docs/api-reference/sqa_strategygenerator_pattern.md +264 -0
- data/docs/api-reference/sqa_strategygenerator_patterncontext.md +326 -0
- data/docs/api-reference/sqa_strategygenerator_profitablepoint.md +424 -0
- data/docs/api-reference/sqa_stream.md +256 -0
- data/docs/api-reference/sqa_ticker.md +175 -0
- data/docs/api-reference/string.md +135 -0
- data/docs/assets/images/advanced-workflow.svg +89 -0
- data/docs/assets/images/architecture.svg +107 -0
- data/docs/assets/images/data-flow.svg +138 -0
- data/docs/assets/images/getting-started-workflow.svg +88 -0
- data/docs/assets/images/strategy-flow.svg +78 -0
- data/docs/assets/images/system-architecture.svg +150 -0
- data/docs/concepts/index.md +292 -19
- data/docs/getting-started/index.md +1 -14
- data/docs/index.md +26 -23
- data/docs/llms.txt +109 -0
- data/docs/strategies/kbs.md +15 -14
- data/docs/strategy.md +381 -3
- data/docs/terms_of_use.md +1 -1
- data/examples/README.md +10 -0
- data/lib/api/alpha_vantage_api.rb +3 -7
- data/lib/sqa/config.rb +109 -28
- data/lib/sqa/data_frame/data.rb +13 -1
- data/lib/sqa/data_frame.rb +168 -26
- data/lib/sqa/errors.rb +79 -17
- data/lib/sqa/init.rb +70 -15
- data/lib/sqa/pattern_matcher.rb +4 -4
- data/lib/sqa/portfolio.rb +1 -1
- data/lib/sqa/sector_analyzer.rb +3 -11
- data/lib/sqa/stock.rb +169 -15
- data/lib/sqa/strategy.rb +62 -4
- data/lib/sqa/ticker.rb +106 -48
- data/lib/sqa/version.rb +1 -1
- data/lib/sqa.rb +4 -4
- data/mkdocs.yml +68 -81
- metadata +89 -21
- data/docs/README.md +0 -43
- data/examples/sinatra_app/Gemfile +0 -42
- data/examples/sinatra_app/Gemfile.lock +0 -268
- data/examples/sinatra_app/QUICKSTART.md +0 -169
- data/examples/sinatra_app/README.md +0 -471
- data/examples/sinatra_app/RUNNING_WITHOUT_TALIB.md +0 -90
- data/examples/sinatra_app/TROUBLESHOOTING.md +0 -95
- data/examples/sinatra_app/app.rb +0 -404
- data/examples/sinatra_app/config.ru +0 -5
- data/examples/sinatra_app/public/css/style.css +0 -723
- data/examples/sinatra_app/public/debug_macd.html +0 -82
- data/examples/sinatra_app/public/js/app.js +0 -107
- data/examples/sinatra_app/start.sh +0 -53
- data/examples/sinatra_app/views/analyze.erb +0 -306
- data/examples/sinatra_app/views/backtest.erb +0 -325
- data/examples/sinatra_app/views/dashboard.erb +0 -831
- data/examples/sinatra_app/views/error.erb +0 -58
- data/examples/sinatra_app/views/index.erb +0 -118
- data/examples/sinatra_app/views/layout.erb +0 -61
- data/examples/sinatra_app/views/portfolio.erb +0 -43
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
# SQA Gem Improvement Plan
|
|
2
|
+
|
|
3
|
+
**Created:** 2025-11-23
|
|
4
|
+
**Status:** Pending Review
|
|
5
|
+
**Scope:** 17 files, 31 discrete changes across 4 phases
|
|
6
|
+
**Impact Analysis:** Verified against sqa_demo-sinatra and sqa-cli
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
This plan addresses code quality issues identified in a comprehensive review of the SQA codebase. All changes have been verified for backward compatibility with dependent gems.
|
|
13
|
+
|
|
14
|
+
### Dependent Gems Analyzed
|
|
15
|
+
|
|
16
|
+
| Gem | Impact | Notes |
|
|
17
|
+
|-----|--------|-------|
|
|
18
|
+
| sqa_demo-sinatra | ✅ All changes safe | Explicitly calls `SQA.init` |
|
|
19
|
+
| sqa-cli | ✅ All changes safe | Requires coordinated update (see separate plan) |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Phase 1: Critical Security & Correctness Fixes
|
|
24
|
+
|
|
25
|
+
**Priority:** Immediate
|
|
26
|
+
**Dependencies:** None
|
|
27
|
+
**Files:** 4
|
|
28
|
+
**Breaking Changes:** None
|
|
29
|
+
|
|
30
|
+
### Task 1.1: Fix Shell Injection Vulnerability
|
|
31
|
+
|
|
32
|
+
**File:** `lib/sqa/config.rb`
|
|
33
|
+
**Line:** 123
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
# FROM:
|
|
37
|
+
`touch #{config_file}`
|
|
38
|
+
|
|
39
|
+
# TO:
|
|
40
|
+
FileUtils.touch(config_file)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Requires:** Verify `require 'fileutils'` is present
|
|
44
|
+
**Risk:** None
|
|
45
|
+
**Test:** Verify config file creation works
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### Task 1.2: Replace Deprecated `has_key?` with `key?`
|
|
50
|
+
|
|
51
|
+
| File | Line | Change |
|
|
52
|
+
|------|------|--------|
|
|
53
|
+
| `lib/sqa/stock.rb` | 176 | `temp.has_key? "Information"` → `temp.key?("Information")` |
|
|
54
|
+
| `lib/sqa/ticker.rb` | 74 | `has_key?` → `key?` |
|
|
55
|
+
| `lib/sqa/config.rb` | 111 | `has_key?` → `key?` |
|
|
56
|
+
|
|
57
|
+
**Risk:** None
|
|
58
|
+
**Test:** Existing tests pass
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### Task 1.3: Fix String Raises to Proper Exception Classes
|
|
63
|
+
|
|
64
|
+
**File:** `lib/sqa/errors.rb` - Add new classes:
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
class DataFetchError < StandardError
|
|
68
|
+
attr_reader :original_error
|
|
69
|
+
def initialize(message, original: nil)
|
|
70
|
+
@original_error = original
|
|
71
|
+
super(message)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class ConfigurationError < StandardError; end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**File:** `lib/sqa/stock.rb` (Lines 106-108):
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
# FROM:
|
|
82
|
+
raise "Unable to fetch data for #{@ticker}...Error: #{e.message}"
|
|
83
|
+
|
|
84
|
+
# TO:
|
|
85
|
+
raise SQA::DataFetchError.new("Unable to fetch data for #{@ticker}: #{e.message}", original: e)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**File:** `lib/sqa/init.rb` (Line 34):
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
# FROM:
|
|
92
|
+
raise('Alpha Vantage API key not set...')
|
|
93
|
+
|
|
94
|
+
# TO:
|
|
95
|
+
raise SQA::ConfigurationError, 'Alpha Vantage API key not set...'
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Risk:** Low - More informative errors, generic rescue still catches them
|
|
99
|
+
**Test:** Add tests for new exception classes
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Task 1.4: Replace Bare Rescues with Specific Exception Types
|
|
104
|
+
|
|
105
|
+
**File:** `lib/sqa/stock.rb`
|
|
106
|
+
|
|
107
|
+
| Line | From | To |
|
|
108
|
+
|------|------|-----|
|
|
109
|
+
| 54 | `rescue => e` | `rescue StandardError => e` |
|
|
110
|
+
| 106 | `rescue => e` | `rescue Faraday::Error, StandardError => e` |
|
|
111
|
+
| 128 | `rescue => e` | `rescue StandardError => e` |
|
|
112
|
+
| 143 | `rescue` (bare) | `rescue ArgumentError, Date::Error => e` |
|
|
113
|
+
| 154 | `rescue => e` | `rescue StandardError => e` |
|
|
114
|
+
|
|
115
|
+
**Risk:** Low - Won't catch `Interrupt`/`SystemExit` (correct behavior)
|
|
116
|
+
**Test:** Verify error handling for expected failures
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Phase 2: Code Quality & Best Practices
|
|
121
|
+
|
|
122
|
+
**Priority:** High
|
|
123
|
+
**Dependencies:** Phase 1 complete
|
|
124
|
+
**Files:** 7
|
|
125
|
+
**Breaking Changes:** None
|
|
126
|
+
|
|
127
|
+
### Task 2.1: Replace Class Variables with Thread-Safe Alternatives
|
|
128
|
+
|
|
129
|
+
**File:** `lib/sqa/init.rb` (Lines 5-6, 34, 47-48, 52, 55)
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
# FROM:
|
|
133
|
+
@@data_dir = nil
|
|
134
|
+
@@av_api_key = nil
|
|
135
|
+
|
|
136
|
+
# TO:
|
|
137
|
+
class << self
|
|
138
|
+
attr_accessor :data_dir, :av_api_key
|
|
139
|
+
end
|
|
140
|
+
@data_dir = nil
|
|
141
|
+
@av_api_key = nil
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**File:** `lib/sqa/stock.rb` (Lines 196, 219)
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
# FROM:
|
|
148
|
+
@@top = nil
|
|
149
|
+
@@bottom = nil
|
|
150
|
+
|
|
151
|
+
# TO:
|
|
152
|
+
class << self
|
|
153
|
+
def top
|
|
154
|
+
@top ||= fetch_top_data
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def bottom
|
|
158
|
+
@bottom ||= fetch_bottom_data
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def reset_cache!
|
|
162
|
+
@top = nil
|
|
163
|
+
@bottom = nil
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**File:** `lib/sqa/ticker.rb` (Lines 16, 61, 67, 72) - Similar pattern
|
|
169
|
+
|
|
170
|
+
**Risk:** Medium - Changes shared state behavior
|
|
171
|
+
**Test:** Add thread-safety tests, verify existing tests pass
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Task 2.2: Remove `puts` from Error Classes
|
|
176
|
+
|
|
177
|
+
**File:** `lib/sqa/errors.rb` (Lines 5-14, 18-26)
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
# FROM:
|
|
181
|
+
class ApiError < RuntimeError
|
|
182
|
+
def self.raise(why)
|
|
183
|
+
puts "="*64
|
|
184
|
+
puts "== API Error"
|
|
185
|
+
puts why
|
|
186
|
+
puts "="*64
|
|
187
|
+
super
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# TO:
|
|
192
|
+
class ApiError < RuntimeError
|
|
193
|
+
def self.raise(why)
|
|
194
|
+
debug_me {"API Error: #{why}"}
|
|
195
|
+
super
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Requires:** `debug_me` gem available (per CLAUDE.md guidelines)
|
|
201
|
+
**Risk:** Low
|
|
202
|
+
**Test:** Verify errors still raise correctly
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### Task 2.3: Remove `puts` from Production Code
|
|
207
|
+
|
|
208
|
+
**File:** `lib/sqa/sector_analyzer.rb` (Lines 145-147)
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
# FROM:
|
|
212
|
+
puts "=" * 70
|
|
213
|
+
puts "Discovering patterns for #{sector.to_s.upcase} sector"
|
|
214
|
+
puts "=" * 70
|
|
215
|
+
|
|
216
|
+
# TO:
|
|
217
|
+
debug_me {"Discovering patterns for #{sector.to_s.upcase} sector"}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Risk:** None
|
|
221
|
+
**Test:** Verify sector analysis works
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Task 2.4: Simplify `method_missing` in DataFrame
|
|
226
|
+
|
|
227
|
+
**File:** `lib/sqa/data_frame.rb` (Lines 164-173)
|
|
228
|
+
|
|
229
|
+
**Option A - Simplified Dynamic (Recommended):**
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
# FROM:
|
|
233
|
+
def method_missing(method_name, *args, &block)
|
|
234
|
+
if @data.respond_to?(method_name)
|
|
235
|
+
self.class.send(:define_method, method_name) do |*method_args, &method_block|
|
|
236
|
+
@data.send(method_name, *method_args, &method_block)
|
|
237
|
+
end
|
|
238
|
+
send(method_name, *args, &block)
|
|
239
|
+
else
|
|
240
|
+
super
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# TO:
|
|
245
|
+
def method_missing(method_name, *args, &block)
|
|
246
|
+
return super unless @data.respond_to?(method_name)
|
|
247
|
+
@data.send(method_name, *args, &block)
|
|
248
|
+
end
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Risk:** Low - Removes dynamic method definition, keeps delegation
|
|
252
|
+
**Test:** Run all DataFrame tests
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### Task 2.5: Remove Unused Parameters
|
|
257
|
+
|
|
258
|
+
**File:** `lib/sqa/data_frame.rb` (Lines 200-209)
|
|
259
|
+
|
|
260
|
+
```ruby
|
|
261
|
+
# FROM:
|
|
262
|
+
def from_aofh(aofh, mapping: {}, transformers: {})
|
|
263
|
+
|
|
264
|
+
# TO:
|
|
265
|
+
def from_aofh(aofh)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Risk:** None - Parameters were never used
|
|
269
|
+
**Test:** Verify `from_aofh` works
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### Task 2.6: Fix Type Checking Pattern
|
|
274
|
+
|
|
275
|
+
**File:** `lib/sqa/strategy.rb` (Line 11)
|
|
276
|
+
|
|
277
|
+
```ruby
|
|
278
|
+
# FROM:
|
|
279
|
+
raise BadParameterError unless [Class, Method].include? a_strategy.class
|
|
280
|
+
|
|
281
|
+
# TO:
|
|
282
|
+
raise BadParameterError unless a_strategy.is_a?(Class) || a_strategy.is_a?(Method)
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**Risk:** None
|
|
286
|
+
**Test:** Existing tests pass
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
### Task 2.7: Remove Magic Placeholder Code
|
|
291
|
+
|
|
292
|
+
**File:** `lib/sqa/stock.rb` (Line 48)
|
|
293
|
+
|
|
294
|
+
```ruby
|
|
295
|
+
# FROM:
|
|
296
|
+
@data = SQA::DataFrame::Data.new(ticker: @ticker, source: @source, indicators: { xyzzy: "Magic" })
|
|
297
|
+
|
|
298
|
+
# TO:
|
|
299
|
+
@data = SQA::DataFrame::Data.new(ticker: @ticker, source: @source, indicators: {})
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Risk:** None
|
|
303
|
+
**Test:** Verify stock initialization
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Phase 3: Architecture & Design Improvements
|
|
308
|
+
|
|
309
|
+
**Priority:** Medium
|
|
310
|
+
**Dependencies:** Phases 1-2 complete
|
|
311
|
+
**Files:** 3
|
|
312
|
+
**Breaking Changes:** None (Task 3.1 revised)
|
|
313
|
+
|
|
314
|
+
### Task 3.1: Add Deprecation Warning for Auto-Initialization (REVISED)
|
|
315
|
+
|
|
316
|
+
**Original Plan:** Remove `SQA::Config.reset` at require time
|
|
317
|
+
**Revision:** Keep auto-init but add deprecation warning for future removal
|
|
318
|
+
|
|
319
|
+
**File:** `lib/sqa/config.rb` (Line 195)
|
|
320
|
+
|
|
321
|
+
```ruby
|
|
322
|
+
# FROM:
|
|
323
|
+
SQA::Config.reset
|
|
324
|
+
|
|
325
|
+
# TO:
|
|
326
|
+
unless SQA::Config.instance_variable_get(:@initialized)
|
|
327
|
+
warn "[SQA DEPRECATION] Auto-initialization at require time will be removed in v1.0. " \
|
|
328
|
+
"Please call SQA.init explicitly in your application startup."
|
|
329
|
+
SQA::Config.reset
|
|
330
|
+
end
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Rationale:** sqa-cli does not explicitly call `SQA.init` and would break. This gives dependent gems time to update.
|
|
334
|
+
|
|
335
|
+
**Coordination Required:**
|
|
336
|
+
- Update sqa-cli to call `SQA.init` explicitly (see separate plan)
|
|
337
|
+
- Remove auto-init in SQA v1.0
|
|
338
|
+
|
|
339
|
+
**Risk:** None - Backward compatible with warning
|
|
340
|
+
**Test:** Verify warning appears, initialization still works
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
### Task 3.2: Add Ascending Order Enforcement
|
|
345
|
+
|
|
346
|
+
**File:** `lib/sqa/data_frame.rb` (around line 85)
|
|
347
|
+
|
|
348
|
+
```ruby
|
|
349
|
+
def concat_and_deduplicate!(other_df, sort_column: "timestamp", descending: false)
|
|
350
|
+
if descending
|
|
351
|
+
warn "[SQA WARNING] TA-Lib requires ascending (oldest-first) order. Forcing descending: false"
|
|
352
|
+
descending = false
|
|
353
|
+
end
|
|
354
|
+
# ... rest of method
|
|
355
|
+
end
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
**Risk:** Low - Prevents silent data ordering bugs
|
|
359
|
+
**Test:** Add test for descending=true warning
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
### Task 3.3: Extract Faraday Connection to Configurable Dependency
|
|
364
|
+
|
|
365
|
+
**File:** `lib/sqa/stock.rb` (Line 6)
|
|
366
|
+
|
|
367
|
+
```ruby
|
|
368
|
+
# FROM:
|
|
369
|
+
CONNECTION = Faraday.new(url: "https://www.alphavantage.co")
|
|
370
|
+
|
|
371
|
+
# TO:
|
|
372
|
+
class << self
|
|
373
|
+
def connection
|
|
374
|
+
@connection ||= default_connection
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def connection=(conn)
|
|
378
|
+
@connection = conn
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def default_connection
|
|
382
|
+
Faraday.new(url: "https://www.alphavantage.co")
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def reset_connection!
|
|
386
|
+
@connection = nil
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Benefit:** Allows mocking in tests, custom configurations
|
|
392
|
+
**Risk:** Low - Default behavior unchanged
|
|
393
|
+
**Test:** Add tests for connection injection
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Phase 4: Documentation & Cleanup
|
|
398
|
+
|
|
399
|
+
**Priority:** Low
|
|
400
|
+
**Dependencies:** Phases 1-3 complete
|
|
401
|
+
**Files:** Multiple
|
|
402
|
+
**Breaking Changes:** None
|
|
403
|
+
|
|
404
|
+
### Task 4.1: Resolve TODO Comments
|
|
405
|
+
|
|
406
|
+
Create GitHub issues for each TODO, update code with issue references:
|
|
407
|
+
|
|
408
|
+
| File | Line | TODO |
|
|
409
|
+
|------|------|------|
|
|
410
|
+
| `lib/sqa.rb` | 4, 16-17 | Investigate |
|
|
411
|
+
| `lib/sqa/config.rb` | 23 (FIXME), 36, 43, 47, 96 | Create issues |
|
|
412
|
+
| `lib/api/alpha_vantage_api.rb` | 6 | Investigate |
|
|
413
|
+
| `lib/sqa/strategy.rb` | 24 | Investigate |
|
|
414
|
+
| `lib/sqa/init.rb` | 21 | Investigate |
|
|
415
|
+
|
|
416
|
+
**Deliverable:** GitHub issues created, TODOs updated
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
### Task 4.2: Fix Error Class Documentation
|
|
421
|
+
|
|
422
|
+
**File:** `lib/sqa/errors.rb`
|
|
423
|
+
|
|
424
|
+
Fix duplicated/incorrect docstring for `NotImplemented` class.
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
### Task 4.3: Standardize Method Naming (Optional)
|
|
429
|
+
|
|
430
|
+
**File:** `lib/sqa/stock.rb`
|
|
431
|
+
|
|
432
|
+
| Current | Proposed |
|
|
433
|
+
|---------|----------|
|
|
434
|
+
| `update_the_dataframe` | `update_dataframe` |
|
|
435
|
+
|
|
436
|
+
**Decision:** Add deprecation alias or rename directly?
|
|
437
|
+
**Risk:** Medium if renaming without deprecation
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## Implementation Order
|
|
442
|
+
|
|
443
|
+
```
|
|
444
|
+
Week 1: Phase 1 (Critical)
|
|
445
|
+
├── Task 1.1: Shell injection fix
|
|
446
|
+
├── Task 1.2: has_key? → key?
|
|
447
|
+
├── Task 1.3: String raises → exceptions
|
|
448
|
+
└── Task 1.4: Bare rescues → specific types
|
|
449
|
+
|
|
450
|
+
Week 2: Phase 2 (Quality) - Part 1
|
|
451
|
+
├── Task 2.1: Class variables → instance variables
|
|
452
|
+
├── Task 2.2: Remove puts from errors
|
|
453
|
+
└── Task 2.3: Remove puts from production
|
|
454
|
+
|
|
455
|
+
Week 3: Phase 2 (Quality) - Part 2
|
|
456
|
+
├── Task 2.4: Simplify method_missing
|
|
457
|
+
├── Task 2.5: Remove unused parameters
|
|
458
|
+
├── Task 2.6: Fix type checking
|
|
459
|
+
└── Task 2.7: Remove magic placeholder
|
|
460
|
+
|
|
461
|
+
Week 4: Phase 3 (Architecture)
|
|
462
|
+
├── Task 3.1: Add deprecation warning (coordinate with sqa-cli)
|
|
463
|
+
├── Task 3.2: Ascending order enforcement
|
|
464
|
+
└── Task 3.3: Configurable connection
|
|
465
|
+
|
|
466
|
+
Ongoing: Phase 4 (Docs)
|
|
467
|
+
├── Task 4.1-4.3: Documentation cleanup
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Testing Strategy
|
|
473
|
+
|
|
474
|
+
### Per-Phase Testing
|
|
475
|
+
- Run `rake test` after each task
|
|
476
|
+
- Verify no regressions
|
|
477
|
+
|
|
478
|
+
### Integration Testing
|
|
479
|
+
After all phases:
|
|
480
|
+
1. Install updated SQA locally
|
|
481
|
+
2. Run sqa_demo-sinatra test suite
|
|
482
|
+
3. Run sqa-cli test suite
|
|
483
|
+
4. Manual smoke testing of key features
|
|
484
|
+
|
|
485
|
+
### Test Coverage Additions
|
|
486
|
+
- New exception classes (Task 1.3)
|
|
487
|
+
- Thread-safety for class instance variables (Task 2.1)
|
|
488
|
+
- Connection injection (Task 3.3)
|
|
489
|
+
- Ascending order warning (Task 3.2)
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## Rollback Strategy
|
|
494
|
+
|
|
495
|
+
Each phase creates separate commits allowing:
|
|
496
|
+
- Independent review per phase
|
|
497
|
+
- Easy rollback if issues discovered
|
|
498
|
+
- Incremental release if needed
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
## Version Strategy
|
|
503
|
+
|
|
504
|
+
| Release | Changes |
|
|
505
|
+
|---------|---------|
|
|
506
|
+
| v0.0.33 | Current release |
|
|
507
|
+
| v0.0.34 | Phases 1-2 (non-breaking fixes) |
|
|
508
|
+
| v0.0.35 | Phase 3 (with deprecation warning) |
|
|
509
|
+
| v1.0.0 | Remove auto-initialization (breaking) |
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Coordination with Dependent Gems
|
|
514
|
+
|
|
515
|
+
### sqa-cli
|
|
516
|
+
- **Before SQA v0.0.35:** Update sqa-cli to call `SQA.init` explicitly
|
|
517
|
+
- See: `sqa-cli/docs/SQA_COMPATIBILITY_UPDATE.md`
|
|
518
|
+
|
|
519
|
+
### sqa_demo-sinatra
|
|
520
|
+
- **No changes required** - Already calls `SQA.init` explicitly
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Approval Checklist
|
|
525
|
+
|
|
526
|
+
- [ ] User approves Phase 1 tasks
|
|
527
|
+
- [ ] User approves Phase 2 tasks
|
|
528
|
+
- [ ] User approves Phase 3 tasks (revised)
|
|
529
|
+
- [ ] User approves Phase 4 tasks
|
|
530
|
+
- [ ] sqa-cli update plan approved
|
|
531
|
+
- [ ] Ready to begin implementation
|
data/docs/advanced/index.md
CHANGED
|
@@ -76,19 +76,7 @@ Future Period of Performance analysis for risk/reward calculations.
|
|
|
76
76
|
|
|
77
77
|
## Example Workflow
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
graph LR
|
|
81
|
-
A[Historical Data] --> B[Strategy Generator]
|
|
82
|
-
B --> C[Discovered Patterns]
|
|
83
|
-
C --> D[Generated Strategies]
|
|
84
|
-
D --> E[Genetic Programming]
|
|
85
|
-
E --> F[Optimized Parameters]
|
|
86
|
-
F --> G[Backtest]
|
|
87
|
-
G --> H{Results Good?}
|
|
88
|
-
H -->|Yes| I[Live Stream]
|
|
89
|
-
H -->|No| D
|
|
90
|
-
I --> J[Portfolio Management]
|
|
91
|
-
```
|
|
79
|
+

|
|
92
80
|
|
|
93
81
|
## Use Cases
|
|
94
82
|
|