sqa-tai 0.1.2 → 0.4.0

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.
@@ -25,11 +25,12 @@ module SQA
25
25
  # Opens the documentation URL in the default browser
26
26
  # @return [Resource] self for chaining
27
27
  def open
28
- if RbConfig::CONFIG["host_os"] =~ /darwin/
28
+ case RbConfig::CONFIG["host_os"]
29
+ when /darwin/
29
30
  system("open", @url)
30
- elsif RbConfig::CONFIG["host_os"] =~ /linux|bsd/
31
+ when /linux|bsd/
31
32
  system("xdg-open", @url)
32
- elsif RbConfig::CONFIG["host_os"] =~ /mswin|mingw|cygwin/
33
+ when /mswin|mingw|cygwin/
33
34
  system("start", @url)
34
35
  else
35
36
  warn "Unable to open browser on this platform"
data/lib/sqa/tai/help.rb CHANGED
@@ -19,19 +19,24 @@ module SQA
19
19
  private
20
20
 
21
21
  def load_indicators
22
- json_path = File.join(__dir__, "help", "data.json")
23
- json_data = File.read(json_path)
24
- data = JSON.parse(json_data)
25
-
26
- # Convert to symbol keys for Ruby idioms
27
- data.transform_keys(&:to_sym).transform_values do |meta|
28
- {
29
- name: meta["name"],
30
- category: meta["category"].to_sym,
31
- path: meta["path"]
32
- }
22
+ read_indicators_json.transform_keys(&:to_sym).transform_values do |meta|
23
+ symbolize_indicator_meta(meta)
33
24
  end
34
25
  end
26
+
27
+ def read_indicators_json
28
+ json_path = File.join(__dir__, "help", "data.json")
29
+ JSON.parse(File.read(json_path))
30
+ end
31
+
32
+ # Convert a single indicator's metadata hash to symbol keys/values for Ruby idioms
33
+ def symbolize_indicator_meta(meta)
34
+ {
35
+ name: meta["name"],
36
+ category: meta["category"].to_sym,
37
+ path: meta["path"]
38
+ }
39
+ end
35
40
  end
36
41
  end
37
42
  end
@@ -3,6 +3,13 @@
3
3
  module SQA
4
4
  module TAI
5
5
  # Momentum Indicators
6
+ #
7
+ # :reek:DataClump and :reek:LongParameterList -- these methods
8
+ # intentionally mirror TA-Lib's own C function signatures (separate
9
+ # high/low/close/period args, up to 7 for macdext); bundling them into
10
+ # a value object would be a breaking public API change for this gem
11
+ # and its downstream consumers (sqa, sqa-cli, sqa-advisor) and their
12
+ # 133 published indicator doc pages.
6
13
  module MomentumIndicators
7
14
  # Relative Strength Index
8
15
  # @param prices [Array<Float>] Array of prices
@@ -13,7 +20,7 @@ module SQA
13
20
  validate_prices!(prices)
14
21
  validate_period!(period, prices.size)
15
22
 
16
- TALibFFI.rsi(prices, time_period: period)
23
+ Native.rsi(prices, time_period: period)
17
24
  end
18
25
 
19
26
  # Intraday Momentum Index
@@ -27,7 +34,7 @@ module SQA
27
34
  validate_prices!(close_prices)
28
35
  validate_period!(period, [open_prices.size, close_prices.size].min)
29
36
 
30
- TALibFFI.imi(open_prices, close_prices, time_period: period)
37
+ Native.imi([open_prices, close_prices], time_period: period)
31
38
  end
32
39
 
33
40
  # Moving Average Convergence/Divergence
@@ -40,19 +47,7 @@ module SQA
40
47
  check_available!
41
48
  validate_prices!(prices)
42
49
 
43
- result = TALibFFI.macd(
44
- prices,
45
- fast_period: fast_period,
46
- slow_period: slow_period,
47
- signal_period: signal_period
48
- )
49
-
50
- # Handle hash return format from newer ta_lib_ffi versions
51
- if result.is_a?(Hash)
52
- [result[:macd], result[:macd_signal], result[:macd_hist]]
53
- else
54
- result
55
- end
50
+ Native.macd(prices, fast_period:, slow_period:, signal_period:).values_at(:macd, :macd_signal, :macd_hist)
56
51
  end
57
52
 
58
53
  # Stochastic Oscillator
@@ -69,21 +64,8 @@ module SQA
69
64
  validate_prices!(low)
70
65
  validate_prices!(close)
71
66
 
72
- result = TALibFFI.stoch(
73
- high,
74
- low,
75
- close,
76
- fastk_period: fastk_period,
77
- slowk_period: slowk_period,
78
- slowd_period: slowd_period
79
- )
80
-
81
- # Handle hash return format from newer ta_lib_ffi versions
82
- if result.is_a?(Hash)
83
- [result[:slow_k], result[:slow_d]]
84
- else
85
- result
86
- end
67
+ result = Native.stoch([high, low, close], fastk_period:, slowk_period:, slowd_period:)
68
+ [result[:slow_k], result[:slow_d]]
87
69
  end
88
70
 
89
71
  # Momentum
@@ -95,7 +77,7 @@ module SQA
95
77
  validate_prices!(prices)
96
78
  validate_period!(period, prices.size)
97
79
 
98
- TALibFFI.mom(prices, time_period: period)
80
+ Native.mom(prices, time_period: period)
99
81
  end
100
82
 
101
83
  # Commodity Channel Index
@@ -110,7 +92,7 @@ module SQA
110
92
  validate_prices!(low)
111
93
  validate_prices!(close)
112
94
 
113
- TALibFFI.cci(high, low, close, time_period: period)
95
+ Native.cci([high, low, close], time_period: period)
114
96
  end
115
97
 
116
98
  # Williams' %R
@@ -125,7 +107,7 @@ module SQA
125
107
  validate_prices!(low)
126
108
  validate_prices!(close)
127
109
 
128
- TALibFFI.willr(high, low, close, time_period: period)
110
+ Native.willr([high, low, close], time_period: period)
129
111
  end
130
112
 
131
113
  # Rate of Change
@@ -137,7 +119,7 @@ module SQA
137
119
  validate_prices!(prices)
138
120
  validate_period!(period, prices.size)
139
121
 
140
- TALibFFI.roc(prices, time_period: period)
122
+ Native.roc(prices, time_period: period)
141
123
  end
142
124
 
143
125
  # Rate of Change Percentage
@@ -149,7 +131,7 @@ module SQA
149
131
  validate_prices!(prices)
150
132
  validate_period!(period, prices.size)
151
133
 
152
- TALibFFI.rocp(prices, time_period: period)
134
+ Native.rocp(prices, time_period: period)
153
135
  end
154
136
 
155
137
  # Rate of Change Ratio
@@ -161,7 +143,7 @@ module SQA
161
143
  validate_prices!(prices)
162
144
  validate_period!(period, prices.size)
163
145
 
164
- TALibFFI.rocr(prices, time_period: period)
146
+ Native.rocr(prices, time_period: period)
165
147
  end
166
148
 
167
149
  # Percentage Price Oscillator
@@ -174,7 +156,7 @@ module SQA
174
156
  check_available!
175
157
  validate_prices!(prices)
176
158
 
177
- TALibFFI.ppo(prices, fast_period: fast_period, slow_period: slow_period, ma_type: ma_type)
159
+ Native.ppo(prices, fast_period:, slow_period:, ma_type:)
178
160
  end
179
161
 
180
162
  # Average Directional Movement Index
@@ -189,7 +171,7 @@ module SQA
189
171
  validate_prices!(low)
190
172
  validate_prices!(close)
191
173
 
192
- TALibFFI.adx(high, low, close, time_period: period)
174
+ Native.adx([high, low, close], time_period: period)
193
175
  end
194
176
 
195
177
  # Average Directional Movement Index Rating
@@ -204,7 +186,7 @@ module SQA
204
186
  validate_prices!(low)
205
187
  validate_prices!(close)
206
188
 
207
- TALibFFI.adxr(high, low, close, time_period: period)
189
+ Native.adxr([high, low, close], time_period: period)
208
190
  end
209
191
 
210
192
  # Absolute Price Oscillator
@@ -217,7 +199,7 @@ module SQA
217
199
  check_available!
218
200
  validate_prices!(prices)
219
201
 
220
- TALibFFI.apo(prices, fast_period: fast_period, slow_period: slow_period, ma_type: ma_type)
202
+ Native.apo(prices, fast_period:, slow_period:, ma_type:)
221
203
  end
222
204
 
223
205
  # Aroon
@@ -230,14 +212,8 @@ module SQA
230
212
  validate_prices!(high)
231
213
  validate_prices!(low)
232
214
 
233
- result = TALibFFI.aroon(high, low, time_period: period)
234
-
235
- # Handle hash return format from newer ta_lib_ffi versions
236
- if result.is_a?(Hash)
237
- [result[:aroon_down], result[:aroon_up]]
238
- else
239
- result
240
- end
215
+ result = Native.aroon([high, low], time_period: period)
216
+ [result[:aroon_down], result[:aroon_up]]
241
217
  end
242
218
 
243
219
  # Aroon Oscillator
@@ -250,7 +226,7 @@ module SQA
250
226
  validate_prices!(high)
251
227
  validate_prices!(low)
252
228
 
253
- TALibFFI.aroonosc(high, low, time_period: period)
229
+ Native.aroonosc([high, low], time_period: period)
254
230
  end
255
231
 
256
232
  # Balance of Power
@@ -266,7 +242,7 @@ module SQA
266
242
  validate_prices!(low)
267
243
  validate_prices!(close)
268
244
 
269
- TALibFFI.bop(open, high, low, close)
245
+ Native.bop([open, high, low, close])
270
246
  end
271
247
 
272
248
  # Chande Momentum Oscillator
@@ -278,7 +254,7 @@ module SQA
278
254
  validate_prices!(prices)
279
255
  validate_period!(period, prices.size)
280
256
 
281
- TALibFFI.cmo(prices, time_period: period)
257
+ Native.cmo(prices, time_period: period)
282
258
  end
283
259
 
284
260
  # Directional Movement Index
@@ -293,7 +269,7 @@ module SQA
293
269
  validate_prices!(low)
294
270
  validate_prices!(close)
295
271
 
296
- TALibFFI.dx(high, low, close, time_period: period)
272
+ Native.dx([high, low, close], time_period: period)
297
273
  end
298
274
 
299
275
  # MACD with Controllable MA Type
@@ -309,22 +285,15 @@ module SQA
309
285
  check_available!
310
286
  validate_prices!(prices)
311
287
 
312
- result = TALibFFI.macdext(
288
+ Native.macdext(
313
289
  prices,
314
- fast_period: fast_period,
315
- fast_ma_type: fast_ma_type,
316
- slow_period: slow_period,
317
- slow_ma_type: slow_ma_type,
318
- signal_period: signal_period,
319
- signal_ma_type: signal_ma_type
320
- )
321
-
322
- # Handle hash return format from newer ta_lib_ffi versions
323
- if result.is_a?(Hash)
324
- [result[:macd], result[:macd_signal], result[:macd_hist]]
325
- else
326
- result
327
- end
290
+ fast_period:,
291
+ fast_ma_type:,
292
+ slow_period:,
293
+ slow_ma_type:,
294
+ signal_period:,
295
+ signal_ma_type:
296
+ ).values_at(:macd, :macd_signal, :macd_hist)
328
297
  end
329
298
 
330
299
  # MACD Fix 12/26
@@ -335,14 +304,7 @@ module SQA
335
304
  check_available!
336
305
  validate_prices!(prices)
337
306
 
338
- result = TALibFFI.macdfix(prices, signal_period: signal_period)
339
-
340
- # Handle hash return format from newer ta_lib_ffi versions
341
- if result.is_a?(Hash)
342
- [result[:macd], result[:macd_signal], result[:macd_hist]]
343
- else
344
- result
345
- end
307
+ Native.macdfix(prices, signal_period:).values_at(:macd, :macd_signal, :macd_hist)
346
308
  end
347
309
 
348
310
  # Money Flow Index
@@ -359,7 +321,7 @@ module SQA
359
321
  validate_prices!(close)
360
322
  validate_prices!(volume)
361
323
 
362
- TALibFFI.mfi(high, low, close, volume, time_period: period)
324
+ Native.mfi([high, low, close, volume], time_period: period)
363
325
  end
364
326
 
365
327
  # Minus Directional Indicator
@@ -374,7 +336,7 @@ module SQA
374
336
  validate_prices!(low)
375
337
  validate_prices!(close)
376
338
 
377
- TALibFFI.minus_di(high, low, close, time_period: period)
339
+ Native.minus_di([high, low, close], time_period: period)
378
340
  end
379
341
 
380
342
  # Minus Directional Movement
@@ -387,7 +349,7 @@ module SQA
387
349
  validate_prices!(high)
388
350
  validate_prices!(low)
389
351
 
390
- TALibFFI.minus_dm(high, low, time_period: period)
352
+ Native.minus_dm([high, low], time_period: period)
391
353
  end
392
354
 
393
355
  # Plus Directional Indicator
@@ -402,7 +364,7 @@ module SQA
402
364
  validate_prices!(low)
403
365
  validate_prices!(close)
404
366
 
405
- TALibFFI.plus_di(high, low, close, time_period: period)
367
+ Native.plus_di([high, low, close], time_period: period)
406
368
  end
407
369
 
408
370
  # Plus Directional Movement
@@ -415,19 +377,21 @@ module SQA
415
377
  validate_prices!(high)
416
378
  validate_prices!(low)
417
379
 
418
- TALibFFI.plus_dm(high, low, time_period: period)
380
+ Native.plus_dm([high, low], time_period: period)
419
381
  end
420
382
 
421
383
  # Rate of Change Ratio 100 scale
422
384
  # @param prices [Array<Float>] Array of prices
423
385
  # @param period [Integer] Time period (default: 10)
424
386
  # @return [Array<Float>] ROCR100 values
387
+ # :reek:UncommunicativeMethodName -- ROCR100 is TA-Lib's own
388
+ # canonical indicator name; renaming it breaks the public API.
425
389
  def rocr100(prices, period: 10)
426
390
  check_available!
427
391
  validate_prices!(prices)
428
392
  validate_period!(period, prices.size)
429
393
 
430
- TALibFFI.rocr100(prices, time_period: period)
394
+ Native.rocr100(prices, time_period: period)
431
395
  end
432
396
 
433
397
  # Stochastic Fast
@@ -443,20 +407,8 @@ module SQA
443
407
  validate_prices!(low)
444
408
  validate_prices!(close)
445
409
 
446
- result = TALibFFI.stochf(
447
- high,
448
- low,
449
- close,
450
- fastk_period: fastk_period,
451
- fastd_period: fastd_period
452
- )
453
-
454
- # Handle hash return format from newer ta_lib_ffi versions
455
- if result.is_a?(Hash)
456
- [result[:fast_k], result[:fast_d]]
457
- else
458
- result
459
- end
410
+ result = Native.stochf([high, low, close], fastk_period:, fastd_period:)
411
+ [result[:fast_k], result[:fast_d]]
460
412
  end
461
413
 
462
414
  # Stochastic RSI
@@ -469,19 +421,8 @@ module SQA
469
421
  check_available!
470
422
  validate_prices!(prices)
471
423
 
472
- result = TALibFFI.stochrsi(
473
- prices,
474
- time_period: period,
475
- fastk_period: fastk_period,
476
- fastd_period: fastd_period
477
- )
478
-
479
- # Handle hash return format from newer ta_lib_ffi versions
480
- if result.is_a?(Hash)
481
- [result[:fast_k], result[:fast_d]]
482
- else
483
- result
484
- end
424
+ result = Native.stochrsi(prices, time_period: period, fastk_period:, fastd_period:)
425
+ [result[:fast_k], result[:fast_d]]
485
426
  end
486
427
 
487
428
  # 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
@@ -493,7 +434,7 @@ module SQA
493
434
  validate_prices!(prices)
494
435
  validate_period!(period, prices.size)
495
436
 
496
- TALibFFI.trix(prices, time_period: period)
437
+ Native.trix(prices, time_period: period)
497
438
  end
498
439
 
499
440
  # Ultimate Oscillator
@@ -510,7 +451,7 @@ module SQA
510
451
  validate_prices!(low)
511
452
  validate_prices!(close)
512
453
 
513
- TALibFFI.ultosc(high, low, close, time_period1: period1, time_period2: period2, time_period3: period3)
454
+ Native.ultosc([high, low, close], time_period1: period1, time_period2: period2, time_period3: period3)
514
455
  end
515
456
  end
516
457
  end