sqa-tai 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c708d46e3d535588af3a14a4d209e32e79a34fa11733c3a20cec8e8a25ddf8f
4
- data.tar.gz: 665274f5b878d3165f50edfc78a6c6903c95f3696483357d07b12b929f2a00fb
3
+ metadata.gz: fb0c8beef02e005aa23c29fd805d7d68067f816286ccf41f747f9cdcf3dc7918
4
+ data.tar.gz: 485f49c5d3636dd5d4814f6c011fcd2b50848697ba1193faa3d0958ed155208f
5
5
  SHA512:
6
- metadata.gz: 72e84001d6624688c24800916e2d9651a13d4047e3dc10e6dd53725b1ea464748890df15e4c35b74e1def91429dc2819750d87529cdb86f2d4fa3a8295fca706
7
- data.tar.gz: b0a2341c3d7777326cddd41f50254f9ff5a290c73b63a6782495fc5c94a29759daa7d0d752cc82e1ea2cd3f1f749bb866ed69f76ba89d12cb1afc13959851a66
6
+ metadata.gz: f833ff859431d01643f78e7748ae6ff865886bc05f1ba29dedd498285698a191bf5101bc4abc20894adcfdd5cb245157bd5b9ca3a224bbca52be58470565d6f8
7
+ data.tar.gz: f3103d7e14e368cfbc134c93873bcae59144229a484459858460d89cec2cd058e5deaa127a7bb73fecfee2fcd73001383cffd070cde8386b367117ea1057378a
data/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+ - Help system for accessing indicator documentation (`SQA::TAI.help`)
12
+ - Returns URLs to online documentation for any indicator
13
+ - Supports searching by name, filtering by category, and listing all indicators
14
+ - Auto-generated from mkdocs documentation files via `rake help:generate`
15
+ - Flexible API returns HelpResource objects with URL, name, and category
16
+ - Optional browser integration to open documentation directly
17
+ - Zeitwerk-compatible file structure with `help.rb` and `help_resource.rb`
18
+
10
19
  ## [0.1.1] 2025-11-13
11
20
  ### Added
12
21
  - Intraday Momentum Index (IMI) indicator
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sqa-tai (0.1.1)
4
+ sqa-tai (0.1.2)
5
5
  ta_lib_ffi (~> 0.3)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -86,6 +86,34 @@ if SQA::TAI.available?
86
86
  end
87
87
  ```
88
88
 
89
+ ## Getting Help on Indicators
90
+
91
+ Access comprehensive documentation for any indicator directly from your code:
92
+
93
+ ```ruby
94
+ # Get documentation URL for an indicator
95
+ help = SQA::TAI.help(:sma)
96
+ puts help.url
97
+ # => https://madbomber.github.io/sqa-tai/indicators/overlap/sma/
98
+
99
+ # Open documentation in browser
100
+ SQA::TAI.help(:rsi, open: true)
101
+
102
+ # Search for indicators
103
+ SQA::TAI.help(search: "momentum")
104
+ # => {mom: "https://...", cmo: "https://...", ...}
105
+
106
+ # List all indicators in a category
107
+ SQA::TAI.help(category: :momentum_indicators)
108
+ # => {rsi: "https://...", macd: "https://...", ...}
109
+
110
+ # Get all available indicators
111
+ SQA::TAI.help(:all)
112
+ # => {sma: "https://...", ema: "https://...", ...}
113
+ ```
114
+
115
+ See the [Help System Guide](https://madbomber.github.io/sqa-tai/getting-started/help/) for more details.
116
+
89
117
  ## Available Indicators (136 Total)
90
118
 
91
119
  ### Overlap Studies (15)
data/Rakefile CHANGED
@@ -11,3 +11,72 @@ Rake::TestTask.new(:test) do |t|
11
11
  end
12
12
 
13
13
  task default: :test
14
+
15
+ namespace :help do
16
+ desc "Generate help mappings from documentation files"
17
+ task :generate do
18
+ require "fileutils"
19
+
20
+ indicators = {}
21
+ category_mapping = {
22
+ "overlap" => :overlap_studies,
23
+ "momentum" => :momentum_indicators,
24
+ "volatility" => :volatility_indicators,
25
+ "volume" => :volume_indicators,
26
+ "price_transform" => :price_transform,
27
+ "statistical" => :statistical_functions,
28
+ "cycle" => :cycle_indicators,
29
+ "patterns" => :pattern_recognition
30
+ }
31
+
32
+ # Scan docs directory
33
+ Dir.glob("docs/indicators/**/*.md").sort.each do |file|
34
+ next if file.include?("index.md")
35
+
36
+ # Extract indicator name from filename
37
+ indicator = File.basename(file, ".md").to_sym
38
+
39
+ # Extract category from path
40
+ path_category = File.dirname(file).split("/").last
41
+ category = category_mapping[path_category] || path_category.to_sym
42
+
43
+ # Read first heading for name
44
+ name = nil
45
+ File.open(file, "r") do |f|
46
+ f.each_line do |line|
47
+ if line.start_with?("# ")
48
+ name = line.gsub(/^#\s*/, "").strip
49
+ # Remove content after parentheses if present
50
+ name = name.split("(").first.strip if name.include?("(")
51
+ break
52
+ end
53
+ end
54
+ end
55
+
56
+ # Build path relative to docs/
57
+ path = file.gsub("docs/", "").gsub(".md", "")
58
+
59
+ indicators[indicator] = {
60
+ name: name || indicator.to_s.upcase,
61
+ category: category,
62
+ path: path
63
+ }
64
+ end
65
+
66
+ # Convert to JSON-friendly format (strings instead of symbols)
67
+ json_data = indicators.transform_keys(&:to_s).transform_values do |meta|
68
+ {
69
+ "name" => meta[:name],
70
+ "category" => meta[:category].to_s,
71
+ "path" => meta[:path]
72
+ }
73
+ end
74
+
75
+ # Write to JSON file
76
+ require "json"
77
+ json_output = JSON.pretty_generate(json_data)
78
+ File.write("lib/sqa/tai/help/data.json", json_output)
79
+ puts "✓ Generated help data for #{indicators.size} indicators"
80
+ puts " File: lib/sqa/tai/help/data.json"
81
+ end
82
+ end
@@ -0,0 +1,697 @@
1
+ {
2
+ "ht_dcperiod": {
3
+ "name": "HT_DCPERIOD",
4
+ "category": "cycle_indicators",
5
+ "path": "indicators/cycle/ht_dcperiod"
6
+ },
7
+ "ht_dcphase": {
8
+ "name": "HT_DCPHASE",
9
+ "category": "cycle_indicators",
10
+ "path": "indicators/cycle/ht_dcphase"
11
+ },
12
+ "ht_phasor": {
13
+ "name": "HT_PHASOR",
14
+ "category": "cycle_indicators",
15
+ "path": "indicators/cycle/ht_phasor"
16
+ },
17
+ "ht_sine": {
18
+ "name": "HT_SINE",
19
+ "category": "cycle_indicators",
20
+ "path": "indicators/cycle/ht_sine"
21
+ },
22
+ "ht_trendmode": {
23
+ "name": "HT_TRENDMODE",
24
+ "category": "cycle_indicators",
25
+ "path": "indicators/cycle/ht_trendmode"
26
+ },
27
+ "adx": {
28
+ "name": "ADX",
29
+ "category": "momentum_indicators",
30
+ "path": "indicators/momentum/adx"
31
+ },
32
+ "adxr": {
33
+ "name": "Average Directional Movement Index Rating",
34
+ "category": "momentum_indicators",
35
+ "path": "indicators/momentum/adxr"
36
+ },
37
+ "apo": {
38
+ "name": "Absolute Price Oscillator",
39
+ "category": "momentum_indicators",
40
+ "path": "indicators/momentum/apo"
41
+ },
42
+ "aroon": {
43
+ "name": "Aroon Indicator",
44
+ "category": "momentum_indicators",
45
+ "path": "indicators/momentum/aroon"
46
+ },
47
+ "aroonosc": {
48
+ "name": "Aroon Oscillator",
49
+ "category": "momentum_indicators",
50
+ "path": "indicators/momentum/aroonosc"
51
+ },
52
+ "bop": {
53
+ "name": "Balance of Power",
54
+ "category": "momentum_indicators",
55
+ "path": "indicators/momentum/bop"
56
+ },
57
+ "cci": {
58
+ "name": "Commodity Channel Index",
59
+ "category": "momentum_indicators",
60
+ "path": "indicators/momentum/cci"
61
+ },
62
+ "cmo": {
63
+ "name": "Chande Momentum Oscillator",
64
+ "category": "momentum_indicators",
65
+ "path": "indicators/momentum/cmo"
66
+ },
67
+ "dx": {
68
+ "name": "Directional Movement Index",
69
+ "category": "momentum_indicators",
70
+ "path": "indicators/momentum/dx"
71
+ },
72
+ "imi": {
73
+ "name": "Intraday Momentum Index",
74
+ "category": "momentum_indicators",
75
+ "path": "indicators/momentum/imi"
76
+ },
77
+ "macd": {
78
+ "name": "MACD",
79
+ "category": "momentum_indicators",
80
+ "path": "indicators/momentum/macd"
81
+ },
82
+ "macdext": {
83
+ "name": "MACD with Controllable MA Type",
84
+ "category": "momentum_indicators",
85
+ "path": "indicators/momentum/macdext"
86
+ },
87
+ "macdfix": {
88
+ "name": "Moving Average Convergence Divergence - Fixed Parameters",
89
+ "category": "momentum_indicators",
90
+ "path": "indicators/momentum/macdfix"
91
+ },
92
+ "mfi": {
93
+ "name": "MFI",
94
+ "category": "momentum_indicators",
95
+ "path": "indicators/momentum/mfi"
96
+ },
97
+ "minus_di": {
98
+ "name": "Minus Directional Indicator",
99
+ "category": "momentum_indicators",
100
+ "path": "indicators/momentum/minus_di"
101
+ },
102
+ "minus_dm": {
103
+ "name": "Minus Directional Movement",
104
+ "category": "momentum_indicators",
105
+ "path": "indicators/momentum/minus_dm"
106
+ },
107
+ "mom": {
108
+ "name": "Momentum",
109
+ "category": "momentum_indicators",
110
+ "path": "indicators/momentum/mom"
111
+ },
112
+ "plus_di": {
113
+ "name": "Plus Directional Indicator",
114
+ "category": "momentum_indicators",
115
+ "path": "indicators/momentum/plus_di"
116
+ },
117
+ "plus_dm": {
118
+ "name": "Plus Directional Movement",
119
+ "category": "momentum_indicators",
120
+ "path": "indicators/momentum/plus_dm"
121
+ },
122
+ "ppo": {
123
+ "name": "Percentage Price Oscillator",
124
+ "category": "momentum_indicators",
125
+ "path": "indicators/momentum/ppo"
126
+ },
127
+ "roc": {
128
+ "name": "Rate of Change",
129
+ "category": "momentum_indicators",
130
+ "path": "indicators/momentum/roc"
131
+ },
132
+ "rocp": {
133
+ "name": "Rate of Change Percentage",
134
+ "category": "momentum_indicators",
135
+ "path": "indicators/momentum/rocp"
136
+ },
137
+ "rocr": {
138
+ "name": "Rate of Change Ratio",
139
+ "category": "momentum_indicators",
140
+ "path": "indicators/momentum/rocr"
141
+ },
142
+ "rocr100": {
143
+ "name": "Rate of Change Ratio 100 Scale",
144
+ "category": "momentum_indicators",
145
+ "path": "indicators/momentum/rocr100"
146
+ },
147
+ "rsi": {
148
+ "name": "RSI",
149
+ "category": "momentum_indicators",
150
+ "path": "indicators/momentum/rsi"
151
+ },
152
+ "stoch": {
153
+ "name": "Stochastic Oscillator",
154
+ "category": "momentum_indicators",
155
+ "path": "indicators/momentum/stoch"
156
+ },
157
+ "stochf": {
158
+ "name": "STOCHF",
159
+ "category": "momentum_indicators",
160
+ "path": "indicators/momentum/stochf"
161
+ },
162
+ "stochrsi": {
163
+ "name": "Stochastic Relative Strength Index",
164
+ "category": "momentum_indicators",
165
+ "path": "indicators/momentum/stochrsi"
166
+ },
167
+ "trix": {
168
+ "name": "TRIX",
169
+ "category": "momentum_indicators",
170
+ "path": "indicators/momentum/trix"
171
+ },
172
+ "ultosc": {
173
+ "name": "Ultimate Oscillator",
174
+ "category": "momentum_indicators",
175
+ "path": "indicators/momentum/ultosc"
176
+ },
177
+ "willr": {
178
+ "name": "Williams %R",
179
+ "category": "momentum_indicators",
180
+ "path": "indicators/momentum/willr"
181
+ },
182
+ "accbands": {
183
+ "name": "ACCBANDS",
184
+ "category": "overlap_studies",
185
+ "path": "indicators/overlap/accbands"
186
+ },
187
+ "bbands": {
188
+ "name": "BBANDS",
189
+ "category": "overlap_studies",
190
+ "path": "indicators/overlap/bbands"
191
+ },
192
+ "dema": {
193
+ "name": "DEMA",
194
+ "category": "overlap_studies",
195
+ "path": "indicators/overlap/dema"
196
+ },
197
+ "ema": {
198
+ "name": "EMA",
199
+ "category": "overlap_studies",
200
+ "path": "indicators/overlap/ema"
201
+ },
202
+ "kama": {
203
+ "name": "KAMA",
204
+ "category": "overlap_studies",
205
+ "path": "indicators/overlap/kama"
206
+ },
207
+ "ma": {
208
+ "name": "MA",
209
+ "category": "overlap_studies",
210
+ "path": "indicators/overlap/ma"
211
+ },
212
+ "sma": {
213
+ "name": "SMA",
214
+ "category": "overlap_studies",
215
+ "path": "indicators/overlap/sma"
216
+ },
217
+ "t3": {
218
+ "name": "T3",
219
+ "category": "overlap_studies",
220
+ "path": "indicators/overlap/t3"
221
+ },
222
+ "tema": {
223
+ "name": "TEMA",
224
+ "category": "overlap_studies",
225
+ "path": "indicators/overlap/tema"
226
+ },
227
+ "trima": {
228
+ "name": "TRIMA",
229
+ "category": "overlap_studies",
230
+ "path": "indicators/overlap/trima"
231
+ },
232
+ "vwap": {
233
+ "name": "VWAP",
234
+ "category": "overlap_studies",
235
+ "path": "indicators/overlap/vwap"
236
+ },
237
+ "wma": {
238
+ "name": "WMA",
239
+ "category": "overlap_studies",
240
+ "path": "indicators/overlap/wma"
241
+ },
242
+ "cdl_2crows": {
243
+ "name": "Two Crows Pattern",
244
+ "category": "pattern_recognition",
245
+ "path": "indicators/patterns/cdl_2crows"
246
+ },
247
+ "cdl_3blackcrows": {
248
+ "name": "Three Black Crows Pattern",
249
+ "category": "pattern_recognition",
250
+ "path": "indicators/patterns/cdl_3blackcrows"
251
+ },
252
+ "cdl_3inside": {
253
+ "name": "Three Inside Up/Down Pattern",
254
+ "category": "pattern_recognition",
255
+ "path": "indicators/patterns/cdl_3inside"
256
+ },
257
+ "cdl_3linestrike": {
258
+ "name": "Three Line Strike Pattern",
259
+ "category": "pattern_recognition",
260
+ "path": "indicators/patterns/cdl_3linestrike"
261
+ },
262
+ "cdl_3outside": {
263
+ "name": "Three Outside Up/Down Pattern",
264
+ "category": "pattern_recognition",
265
+ "path": "indicators/patterns/cdl_3outside"
266
+ },
267
+ "cdl_3starsinsouth": {
268
+ "name": "Three Stars in the South Pattern",
269
+ "category": "pattern_recognition",
270
+ "path": "indicators/patterns/cdl_3starsinsouth"
271
+ },
272
+ "cdl_3whitesoldiers": {
273
+ "name": "Three White Soldiers Pattern",
274
+ "category": "pattern_recognition",
275
+ "path": "indicators/patterns/cdl_3whitesoldiers"
276
+ },
277
+ "cdl_abandonedbaby": {
278
+ "name": "Abandoned Baby Pattern",
279
+ "category": "pattern_recognition",
280
+ "path": "indicators/patterns/cdl_abandonedbaby"
281
+ },
282
+ "cdl_advanceblock": {
283
+ "name": "Advance Block Pattern",
284
+ "category": "pattern_recognition",
285
+ "path": "indicators/patterns/cdl_advanceblock"
286
+ },
287
+ "cdl_belthold": {
288
+ "name": "Belt Hold Pattern",
289
+ "category": "pattern_recognition",
290
+ "path": "indicators/patterns/cdl_belthold"
291
+ },
292
+ "cdl_breakaway": {
293
+ "name": "Breakaway Pattern",
294
+ "category": "pattern_recognition",
295
+ "path": "indicators/patterns/cdl_breakaway"
296
+ },
297
+ "cdl_closingmarubozu": {
298
+ "name": "Closing Marubozu Pattern",
299
+ "category": "pattern_recognition",
300
+ "path": "indicators/patterns/cdl_closingmarubozu"
301
+ },
302
+ "cdl_concealbabyswall": {
303
+ "name": "Concealing Baby Swallow Pattern",
304
+ "category": "pattern_recognition",
305
+ "path": "indicators/patterns/cdl_concealbabyswall"
306
+ },
307
+ "cdl_counterattack": {
308
+ "name": "Counterattack Pattern",
309
+ "category": "pattern_recognition",
310
+ "path": "indicators/patterns/cdl_counterattack"
311
+ },
312
+ "cdl_darkcloudcover": {
313
+ "name": "Dark Cloud Cover Pattern",
314
+ "category": "pattern_recognition",
315
+ "path": "indicators/patterns/cdl_darkcloudcover"
316
+ },
317
+ "cdl_doji": {
318
+ "name": "CDL_DOJI",
319
+ "category": "pattern_recognition",
320
+ "path": "indicators/patterns/cdl_doji"
321
+ },
322
+ "cdl_dojistar": {
323
+ "name": "CDL_DOJISTAR",
324
+ "category": "pattern_recognition",
325
+ "path": "indicators/patterns/cdl_dojistar"
326
+ },
327
+ "cdl_dragonflydoji": {
328
+ "name": "Dragonfly Doji Pattern",
329
+ "category": "pattern_recognition",
330
+ "path": "indicators/patterns/cdl_dragonflydoji"
331
+ },
332
+ "cdl_engulfing": {
333
+ "name": "Engulfing Pattern",
334
+ "category": "pattern_recognition",
335
+ "path": "indicators/patterns/cdl_engulfing"
336
+ },
337
+ "cdl_eveningdojistar": {
338
+ "name": "CDL_EVENINGDOJISTAR",
339
+ "category": "pattern_recognition",
340
+ "path": "indicators/patterns/cdl_eveningdojistar"
341
+ },
342
+ "cdl_eveningstar": {
343
+ "name": "CDL_CDL_EVENINGSTAR",
344
+ "category": "pattern_recognition",
345
+ "path": "indicators/patterns/cdl_eveningstar"
346
+ },
347
+ "cdl_gapsidesidewhite": {
348
+ "name": "CDL_GAPSIDESIDEWHITE",
349
+ "category": "pattern_recognition",
350
+ "path": "indicators/patterns/cdl_gapsidesidewhite"
351
+ },
352
+ "cdl_gravestonedoji": {
353
+ "name": "CDL_CDL_GRAVESTONEDOJI",
354
+ "category": "pattern_recognition",
355
+ "path": "indicators/patterns/cdl_gravestonedoji"
356
+ },
357
+ "cdl_hammer": {
358
+ "name": "Hammer Pattern",
359
+ "category": "pattern_recognition",
360
+ "path": "indicators/patterns/cdl_hammer"
361
+ },
362
+ "cdl_hangingman": {
363
+ "name": "CDL_HANGINGMAN",
364
+ "category": "pattern_recognition",
365
+ "path": "indicators/patterns/cdl_hangingman"
366
+ },
367
+ "cdl_harami": {
368
+ "name": "CDL_CDL_HARAMI",
369
+ "category": "pattern_recognition",
370
+ "path": "indicators/patterns/cdl_harami"
371
+ },
372
+ "cdl_haramicross": {
373
+ "name": "CDL_HARAMICROSS",
374
+ "category": "pattern_recognition",
375
+ "path": "indicators/patterns/cdl_haramicross"
376
+ },
377
+ "cdl_highwave": {
378
+ "name": "CDL_CDL_HIGHWAVE",
379
+ "category": "pattern_recognition",
380
+ "path": "indicators/patterns/cdl_highwave"
381
+ },
382
+ "cdl_hikkake": {
383
+ "name": "CDL_CDL_HIKKAKE",
384
+ "category": "pattern_recognition",
385
+ "path": "indicators/patterns/cdl_hikkake"
386
+ },
387
+ "cdl_hikkakemod": {
388
+ "name": "CDL_CDL_HIKKAKEMOD",
389
+ "category": "pattern_recognition",
390
+ "path": "indicators/patterns/cdl_hikkakemod"
391
+ },
392
+ "cdl_homingpigeon": {
393
+ "name": "CDL_CDL_HOMINGPIGEON",
394
+ "category": "pattern_recognition",
395
+ "path": "indicators/patterns/cdl_homingpigeon"
396
+ },
397
+ "cdl_identical3crows": {
398
+ "name": "CDL_IDENTICAL3CROWS",
399
+ "category": "pattern_recognition",
400
+ "path": "indicators/patterns/cdl_identical3crows"
401
+ },
402
+ "cdl_inneck": {
403
+ "name": "CDL_INNECK",
404
+ "category": "pattern_recognition",
405
+ "path": "indicators/patterns/cdl_inneck"
406
+ },
407
+ "cdl_inside": {
408
+ "name": "CDL_INSIDE - See Three Inside Up/Down",
409
+ "category": "pattern_recognition",
410
+ "path": "indicators/patterns/cdl_inside"
411
+ },
412
+ "cdl_invertedhammer": {
413
+ "name": "CDL_CDL_INVERTEDHAMMER",
414
+ "category": "pattern_recognition",
415
+ "path": "indicators/patterns/cdl_invertedhammer"
416
+ },
417
+ "cdl_kicking": {
418
+ "name": "CDL_KICKING",
419
+ "category": "pattern_recognition",
420
+ "path": "indicators/patterns/cdl_kicking"
421
+ },
422
+ "cdl_kickingbylength": {
423
+ "name": "CDL_CDL_KICKINGBYLENGTH",
424
+ "category": "pattern_recognition",
425
+ "path": "indicators/patterns/cdl_kickingbylength"
426
+ },
427
+ "cdl_ladderbottom": {
428
+ "name": "CDL_CDL_LADDERBOTTOM",
429
+ "category": "pattern_recognition",
430
+ "path": "indicators/patterns/cdl_ladderbottom"
431
+ },
432
+ "cdl_longleggeddoji": {
433
+ "name": "CDL_CDL_LONGLEGGEDDOJI",
434
+ "category": "pattern_recognition",
435
+ "path": "indicators/patterns/cdl_longleggeddoji"
436
+ },
437
+ "cdl_longline": {
438
+ "name": "CDL_LONGLINE",
439
+ "category": "pattern_recognition",
440
+ "path": "indicators/patterns/cdl_longline"
441
+ },
442
+ "cdl_marubozu": {
443
+ "name": "CDL_CDL_MARUBOZU",
444
+ "category": "pattern_recognition",
445
+ "path": "indicators/patterns/cdl_marubozu"
446
+ },
447
+ "cdl_matchinglow": {
448
+ "name": "CDL_MATCHINGLOW",
449
+ "category": "pattern_recognition",
450
+ "path": "indicators/patterns/cdl_matchinglow"
451
+ },
452
+ "cdl_mathold": {
453
+ "name": "CDL_CDL_MATHOLD",
454
+ "category": "pattern_recognition",
455
+ "path": "indicators/patterns/cdl_mathold"
456
+ },
457
+ "cdl_meetinglines": {
458
+ "name": "CDL_MEETINGLINES",
459
+ "category": "pattern_recognition",
460
+ "path": "indicators/patterns/cdl_meetinglines"
461
+ },
462
+ "cdl_morningdojistar": {
463
+ "name": "CDL_MORNINGDOJISTAR",
464
+ "category": "pattern_recognition",
465
+ "path": "indicators/patterns/cdl_morningdojistar"
466
+ },
467
+ "cdl_morningstar": {
468
+ "name": "CDL_MORNINGSTAR",
469
+ "category": "pattern_recognition",
470
+ "path": "indicators/patterns/cdl_morningstar"
471
+ },
472
+ "cdl_onneck": {
473
+ "name": "CDL_ONNECK",
474
+ "category": "pattern_recognition",
475
+ "path": "indicators/patterns/cdl_onneck"
476
+ },
477
+ "cdl_piercing": {
478
+ "name": "CDL_CDL_PIERCING",
479
+ "category": "pattern_recognition",
480
+ "path": "indicators/patterns/cdl_piercing"
481
+ },
482
+ "cdl_rickshawman": {
483
+ "name": "CDL_CDL_RICKSHAWMAN",
484
+ "category": "pattern_recognition",
485
+ "path": "indicators/patterns/cdl_rickshawman"
486
+ },
487
+ "cdl_risefall3methods": {
488
+ "name": "CDL_CDL_RISEFALL3METHODS",
489
+ "category": "pattern_recognition",
490
+ "path": "indicators/patterns/cdl_risefall3methods"
491
+ },
492
+ "cdl_separatinglines": {
493
+ "name": "CDL_SEPARATINGLINES",
494
+ "category": "pattern_recognition",
495
+ "path": "indicators/patterns/cdl_separatinglines"
496
+ },
497
+ "cdl_shootingstar": {
498
+ "name": "CDL_CDL_SHOOTINGSTAR",
499
+ "category": "pattern_recognition",
500
+ "path": "indicators/patterns/cdl_shootingstar"
501
+ },
502
+ "cdl_shortline": {
503
+ "name": "CDL_SHORTLINE",
504
+ "category": "pattern_recognition",
505
+ "path": "indicators/patterns/cdl_shortline"
506
+ },
507
+ "cdl_spinningtop": {
508
+ "name": "CDL_CDL_SPINNINGTOP",
509
+ "category": "pattern_recognition",
510
+ "path": "indicators/patterns/cdl_spinningtop"
511
+ },
512
+ "cdl_stalledpattern": {
513
+ "name": "CDL_STALLEDPATTERN",
514
+ "category": "pattern_recognition",
515
+ "path": "indicators/patterns/cdl_stalledpattern"
516
+ },
517
+ "cdl_sticksandwich": {
518
+ "name": "CDL_STICKSANDWICH",
519
+ "category": "pattern_recognition",
520
+ "path": "indicators/patterns/cdl_sticksandwich"
521
+ },
522
+ "cdl_takuri": {
523
+ "name": "CDL_CDL_TAKURI",
524
+ "category": "pattern_recognition",
525
+ "path": "indicators/patterns/cdl_takuri"
526
+ },
527
+ "cdl_tasukigap": {
528
+ "name": "CDL_TASUKIGAP",
529
+ "category": "pattern_recognition",
530
+ "path": "indicators/patterns/cdl_tasukigap"
531
+ },
532
+ "cdl_thrusting": {
533
+ "name": "CDL_THRUSTING",
534
+ "category": "pattern_recognition",
535
+ "path": "indicators/patterns/cdl_thrusting"
536
+ },
537
+ "cdl_tristar": {
538
+ "name": "CDL_TRISTAR",
539
+ "category": "pattern_recognition",
540
+ "path": "indicators/patterns/cdl_tristar"
541
+ },
542
+ "cdl_unique3river": {
543
+ "name": "CDL_UNIQUE3RIVER",
544
+ "category": "pattern_recognition",
545
+ "path": "indicators/patterns/cdl_unique3river"
546
+ },
547
+ "cdl_upsidegap2crows": {
548
+ "name": "CDL_UPSIDEGAP2CROWS",
549
+ "category": "pattern_recognition",
550
+ "path": "indicators/patterns/cdl_upsidegap2crows"
551
+ },
552
+ "cdl_xsidegap3methods": {
553
+ "name": "CDL_XSIDEGAP3METHODS",
554
+ "category": "pattern_recognition",
555
+ "path": "indicators/patterns/cdl_xsidegap3methods"
556
+ },
557
+ "avgprice": {
558
+ "name": "AVGPRICE",
559
+ "category": "price_transform",
560
+ "path": "indicators/price_transform/avgprice"
561
+ },
562
+ "medprice": {
563
+ "name": "Median Price",
564
+ "category": "price_transform",
565
+ "path": "indicators/price_transform/medprice"
566
+ },
567
+ "typprice": {
568
+ "name": "Typical Price",
569
+ "category": "price_transform",
570
+ "path": "indicators/price_transform/typprice"
571
+ },
572
+ "wclprice": {
573
+ "name": "Weighted Close Price",
574
+ "category": "price_transform",
575
+ "path": "indicators/price_transform/wclprice"
576
+ },
577
+ "beta": {
578
+ "name": "Beta Coefficient",
579
+ "category": "statistical_functions",
580
+ "path": "indicators/statistical/beta"
581
+ },
582
+ "correl": {
583
+ "name": "CORREL",
584
+ "category": "statistical_functions",
585
+ "path": "indicators/statistical/correl"
586
+ },
587
+ "linearreg": {
588
+ "name": "Linear Regression",
589
+ "category": "statistical_functions",
590
+ "path": "indicators/statistical/linearreg"
591
+ },
592
+ "linearreg_angle": {
593
+ "name": "Linear Regression Angle",
594
+ "category": "statistical_functions",
595
+ "path": "indicators/statistical/linearreg_angle"
596
+ },
597
+ "linearreg_intercept": {
598
+ "name": "Linear Regression Intercept",
599
+ "category": "statistical_functions",
600
+ "path": "indicators/statistical/linearreg_intercept"
601
+ },
602
+ "linearreg_slope": {
603
+ "name": "Linear Regression Slope",
604
+ "category": "statistical_functions",
605
+ "path": "indicators/statistical/linearreg_slope"
606
+ },
607
+ "stddev": {
608
+ "name": "Standard Deviation",
609
+ "category": "statistical_functions",
610
+ "path": "indicators/statistical/stddev"
611
+ },
612
+ "tsf": {
613
+ "name": "Time Series Forecast",
614
+ "category": "statistical_functions",
615
+ "path": "indicators/statistical/tsf"
616
+ },
617
+ "var": {
618
+ "name": "Variance",
619
+ "category": "statistical_functions",
620
+ "path": "indicators/statistical/var"
621
+ },
622
+ "atr": {
623
+ "name": "Average True Range",
624
+ "category": "volatility_indicators",
625
+ "path": "indicators/volatility/atr"
626
+ },
627
+ "ht_trendline": {
628
+ "name": "HT_TRENDLINE",
629
+ "category": "volatility_indicators",
630
+ "path": "indicators/volatility/ht_trendline"
631
+ },
632
+ "keltner": {
633
+ "name": "Keltner Channels",
634
+ "category": "volatility_indicators",
635
+ "path": "indicators/volatility/keltner"
636
+ },
637
+ "mama": {
638
+ "name": "MAMA",
639
+ "category": "volatility_indicators",
640
+ "path": "indicators/volatility/mama"
641
+ },
642
+ "mavp": {
643
+ "name": "Moving Average with Variable Period",
644
+ "category": "volatility_indicators",
645
+ "path": "indicators/volatility/mavp"
646
+ },
647
+ "midpoint": {
648
+ "name": "Midpoint Over Period",
649
+ "category": "volatility_indicators",
650
+ "path": "indicators/volatility/midpoint"
651
+ },
652
+ "midprice": {
653
+ "name": "Midpoint Price",
654
+ "category": "volatility_indicators",
655
+ "path": "indicators/volatility/midprice"
656
+ },
657
+ "natr": {
658
+ "name": "NATR",
659
+ "category": "volatility_indicators",
660
+ "path": "indicators/volatility/natr"
661
+ },
662
+ "sar": {
663
+ "name": "Parabolic SAR",
664
+ "category": "volatility_indicators",
665
+ "path": "indicators/volatility/sar"
666
+ },
667
+ "sarext": {
668
+ "name": "Parabolic SAR Extended",
669
+ "category": "volatility_indicators",
670
+ "path": "indicators/volatility/sarext"
671
+ },
672
+ "trange": {
673
+ "name": "True Range",
674
+ "category": "volatility_indicators",
675
+ "path": "indicators/volatility/trange"
676
+ },
677
+ "ad": {
678
+ "name": "AD",
679
+ "category": "volume_indicators",
680
+ "path": "indicators/volume/ad"
681
+ },
682
+ "adosc": {
683
+ "name": "ADOSC",
684
+ "category": "volume_indicators",
685
+ "path": "indicators/volume/adosc"
686
+ },
687
+ "cmf": {
688
+ "name": "CMF",
689
+ "category": "volume_indicators",
690
+ "path": "indicators/volume/cmf"
691
+ },
692
+ "obv": {
693
+ "name": "On Balance Volume",
694
+ "category": "volume_indicators",
695
+ "path": "indicators/volume/obv"
696
+ }
697
+ }
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module SQA
6
+ module TAI
7
+ module Help
8
+ # Represents help documentation for a specific indicator
9
+ class Resource
10
+ attr_reader :indicator, :name, :category, :url
11
+
12
+ def initialize(indicator, name, category, path)
13
+ @indicator = indicator
14
+ @name = name
15
+ @category = category
16
+ @url = "#{BASE_URL}/#{path}/"
17
+ end
18
+
19
+ # Returns URI object for the documentation URL
20
+ # @return [URI::HTTPS]
21
+ def uri
22
+ @uri ||= URI.parse(@url)
23
+ end
24
+
25
+ # Opens the documentation URL in the default browser
26
+ # @return [Resource] self for chaining
27
+ def open
28
+ if RbConfig::CONFIG["host_os"] =~ /darwin/
29
+ system("open", @url)
30
+ elsif RbConfig::CONFIG["host_os"] =~ /linux|bsd/
31
+ system("xdg-open", @url)
32
+ elsif RbConfig::CONFIG["host_os"] =~ /mswin|mingw|cygwin/
33
+ system("start", @url)
34
+ else
35
+ warn "Unable to open browser on this platform"
36
+ end
37
+ self
38
+ end
39
+
40
+ # Fetches the documentation content from the URL
41
+ # @return [String] HTML content of the documentation page
42
+ def fetch
43
+ require "net/http"
44
+ Net::HTTP.get(uri)
45
+ end
46
+
47
+ # Returns formatted help information
48
+ # @return [String]
49
+ def to_s
50
+ category_label = @category.to_s.split('_').map(&:capitalize).join(' ')
51
+ <<~HELP
52
+ Indicator: #{@indicator.to_s.upcase} (#{@name})
53
+ Category: #{category_label}
54
+ Website: #{@url}
55
+ HELP
56
+ end
57
+
58
+ # Returns detailed information about the help resource
59
+ # @return [String]
60
+ def inspect
61
+ "#<SQA::TAI::Help::Resource #{indicator} (#{category}): #{url}>"
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module SQA
6
+ module TAI
7
+ # Help module containing documentation metadata and URLs
8
+ module Help
9
+ # Base URL for the documentation site
10
+ BASE_URL = "https://madbomber.github.io/sqa-tai"
11
+
12
+ class << self
13
+ # Lazy-loaded indicator metadata
14
+ # @return [Hash] Indicator metadata with symbolized keys
15
+ def indicators
16
+ @indicators ||= load_indicators
17
+ end
18
+
19
+ private
20
+
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
+ }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ # Load help resource class
41
+ require_relative "help/resource"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SQA
4
4
  module TAI
5
- VERSION = "0.1.1"
5
+ VERSION = "0.1.2"
6
6
  end
7
7
  end
data/lib/sqa/tai.rb CHANGED
@@ -16,6 +16,9 @@ require_relative "tai/cycle_indicators"
16
16
  require_relative "tai/statistical_functions"
17
17
  require_relative "tai/pattern_recognition"
18
18
 
19
+ # Require help system
20
+ require_relative "tai/help"
21
+
19
22
  module SQA
20
23
  module TAI
21
24
  class Error < StandardError; end
@@ -49,6 +52,68 @@ module SQA
49
52
  "Please install it from https://ta-lib.org/"
50
53
  end
51
54
 
55
+ # Get help documentation for indicators
56
+ #
57
+ # @param indicator [Symbol, nil] The indicator to get help for
58
+ # @param options [Hash] Options for help output
59
+ # @option options [Symbol] :category Filter by category
60
+ # @option options [String] :search Search for indicators
61
+ # @option options [Boolean] :open Open URL in browser
62
+ # @option options [Symbol] :format Return format (:uri, :hash, or Help::Resource)
63
+ #
64
+ # @return [Help::Resource, Hash, String, URI] Help information
65
+ #
66
+ # @example Get help for SMA
67
+ # SQA::TAI.help(:sma)
68
+ # # => #<SQA::TAI::Help::Resource ...>
69
+ #
70
+ # @example Open help in browser
71
+ # SQA::TAI.help(:rsi, open: true)
72
+ #
73
+ # @example List all momentum indicators
74
+ # SQA::TAI.help(category: :momentum_indicators)
75
+ #
76
+ # @example Search for indicators
77
+ # SQA::TAI.help(search: "moving average")
78
+ #
79
+ def help(indicator = nil, **options)
80
+ # List all indicators
81
+ if indicator == :all
82
+ return Help.indicators.transform_values { |meta| "#{Help::BASE_URL}/#{meta[:path]}/" }
83
+ end
84
+
85
+ # Category listing
86
+ if options[:category]
87
+ category_indicators = Help.indicators.select { |_k, v| v[:category] == options[:category] }
88
+ return category_indicators.transform_values { |meta| "#{Help::BASE_URL}/#{meta[:path]}/" }
89
+ end
90
+
91
+ # Search
92
+ if options[:search]
93
+ query = options[:search].downcase
94
+ matches = Help.indicators.select do |k, v|
95
+ k.to_s.include?(query) || v[:name].downcase.include?(query)
96
+ end
97
+ return matches.transform_values { |meta| "#{Help::BASE_URL}/#{meta[:path]}/" }
98
+ end
99
+
100
+ # Single indicator
101
+ meta = Help.indicators[indicator]
102
+ raise ArgumentError, "Unknown indicator: #{indicator}" unless meta
103
+
104
+ resource = Help::Resource.new(indicator, meta[:name], meta[:category], meta[:path])
105
+
106
+ # Open in browser if requested
107
+ resource.open if options[:open]
108
+
109
+ # Return format
110
+ case options[:format]
111
+ when :uri then resource.uri
112
+ when :hash then {name: meta[:name], category: meta[:category], url: resource.url}
113
+ else resource # Return Help::Resource object (responds to to_s)
114
+ end
115
+ end
116
+
52
117
  private
53
118
 
54
119
  def validate_prices!(prices)
data/mkdocs.yml CHANGED
@@ -145,6 +145,7 @@ nav:
145
145
  - Installation: getting-started/installation.md
146
146
  - Quick Start: getting-started/quick-start.md
147
147
  - Basic Usage: getting-started/basic-usage.md
148
+ - Help System: getting-started/help.md
148
149
  - Indicators:
149
150
  - Overview: indicators/index.md
150
151
  - Overlap Studies:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqa-tai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
@@ -127,6 +127,9 @@ files:
127
127
  - lib/extensions/ta_lib_ffi.rb
128
128
  - lib/sqa/tai.rb
129
129
  - lib/sqa/tai/cycle_indicators.rb
130
+ - lib/sqa/tai/help.rb
131
+ - lib/sqa/tai/help/data.json
132
+ - lib/sqa/tai/help/resource.rb
130
133
  - lib/sqa/tai/momentum_indicators.rb
131
134
  - lib/sqa/tai/overlap_studies.rb
132
135
  - lib/sqa/tai/pattern_recognition.rb