sqa 0.0.31 → 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.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -0
  3. data/CLAUDE.md +21 -0
  4. data/README.md +60 -32
  5. data/Rakefile +52 -10
  6. data/docs/IMPROVEMENT_PLAN.md +531 -0
  7. data/docs/advanced/index.md +1 -13
  8. data/docs/api/dataframe.md +0 -1
  9. data/docs/api/index.md +547 -61
  10. data/docs/api-reference/alphavantageapi.md +1057 -0
  11. data/docs/api-reference/apierror.md +31 -0
  12. data/docs/api-reference/index.md +221 -0
  13. data/docs/api-reference/notimplemented.md +27 -0
  14. data/docs/api-reference/sqa.md +267 -0
  15. data/docs/api-reference/sqa_backtest.md +137 -0
  16. data/docs/api-reference/sqa_backtest_results.md +530 -0
  17. data/docs/api-reference/sqa_badparametererror.md +13 -0
  18. data/docs/api-reference/sqa_config.md +538 -0
  19. data/docs/api-reference/sqa_configurationerror.md +13 -0
  20. data/docs/api-reference/sqa_datafetcherror.md +56 -0
  21. data/docs/api-reference/sqa_dataframe.md +752 -0
  22. data/docs/api-reference/sqa_dataframe_alphavantage.md +30 -0
  23. data/docs/api-reference/sqa_dataframe_data.md +325 -0
  24. data/docs/api-reference/sqa_dataframe_yahoofinance.md +25 -0
  25. data/docs/api-reference/sqa_ensemble.md +413 -0
  26. data/docs/api-reference/sqa_fpop.md +211 -0
  27. data/docs/api-reference/sqa_geneticprogram.md +325 -0
  28. data/docs/api-reference/sqa_geneticprogram_individual.md +114 -0
  29. data/docs/api-reference/sqa_marketregime.md +212 -0
  30. data/docs/api-reference/sqa_multitimeframe.md +227 -0
  31. data/docs/api-reference/sqa_patternmatcher.md +195 -0
  32. data/docs/api-reference/sqa_pluginmanager.md +55 -0
  33. data/docs/api-reference/sqa_portfolio.md +455 -0
  34. data/docs/api-reference/sqa_portfolio_position.md +220 -0
  35. data/docs/api-reference/sqa_portfolio_trade.md +332 -0
  36. data/docs/api-reference/sqa_portfoliooptimizer.md +248 -0
  37. data/docs/api-reference/sqa_riskmanager.md +388 -0
  38. data/docs/api-reference/sqa_seasonalanalyzer.md +121 -0
  39. data/docs/api-reference/sqa_sectoranalyzer.md +163 -0
  40. data/docs/api-reference/sqa_stock.md +649 -0
  41. data/docs/api-reference/sqa_strategy.md +178 -0
  42. data/docs/api-reference/sqa_strategy_bollingerbands.md +26 -0
  43. data/docs/api-reference/sqa_strategy_common.md +29 -0
  44. data/docs/api-reference/sqa_strategy_consensus.md +129 -0
  45. data/docs/api-reference/sqa_strategy_ema.md +41 -0
  46. data/docs/api-reference/sqa_strategy_kbs.md +154 -0
  47. data/docs/api-reference/sqa_strategy_macd.md +26 -0
  48. data/docs/api-reference/sqa_strategy_mp.md +41 -0
  49. data/docs/api-reference/sqa_strategy_mr.md +41 -0
  50. data/docs/api-reference/sqa_strategy_random.md +41 -0
  51. data/docs/api-reference/sqa_strategy_rsi.md +41 -0
  52. data/docs/api-reference/sqa_strategy_sma.md +41 -0
  53. data/docs/api-reference/sqa_strategy_stochastic.md +26 -0
  54. data/docs/api-reference/sqa_strategy_volumebreakout.md +26 -0
  55. data/docs/api-reference/sqa_strategygenerator.md +298 -0
  56. data/docs/api-reference/sqa_strategygenerator_pattern.md +264 -0
  57. data/docs/api-reference/sqa_strategygenerator_patterncontext.md +326 -0
  58. data/docs/api-reference/sqa_strategygenerator_profitablepoint.md +424 -0
  59. data/docs/api-reference/sqa_stream.md +256 -0
  60. data/docs/api-reference/sqa_ticker.md +175 -0
  61. data/docs/api-reference/string.md +135 -0
  62. data/docs/assets/images/advanced-workflow.svg +89 -0
  63. data/docs/assets/images/architecture.svg +107 -0
  64. data/docs/assets/images/data-flow.svg +138 -0
  65. data/docs/assets/images/getting-started-workflow.svg +88 -0
  66. data/docs/assets/images/sqa.jpg +0 -0
  67. data/docs/assets/images/strategy-flow.svg +78 -0
  68. data/docs/assets/images/system-architecture.svg +150 -0
  69. data/docs/concepts/index.md +292 -27
  70. data/docs/data_frame.md +0 -1
  71. data/docs/getting-started/index.md +1 -30
  72. data/docs/getting-started/installation.md +2 -2
  73. data/docs/getting-started/quick-start.md +4 -4
  74. data/docs/index.md +26 -25
  75. data/docs/llms.txt +109 -0
  76. data/docs/strategies/bollinger-bands.md +1 -1
  77. data/docs/strategies/kbs.md +15 -14
  78. data/docs/strategies/rsi.md +1 -1
  79. data/docs/strategy.md +381 -3
  80. data/docs/terms_of_use.md +1 -1
  81. data/examples/README.md +10 -0
  82. data/lib/api/alpha_vantage_api.rb +3 -7
  83. data/lib/sqa/config.rb +109 -28
  84. data/lib/sqa/data_frame/alpha_vantage.rb +13 -3
  85. data/lib/sqa/data_frame/data.rb +13 -1
  86. data/lib/sqa/data_frame.rb +189 -41
  87. data/lib/sqa/errors.rb +79 -17
  88. data/lib/sqa/indicator.rb +17 -4
  89. data/lib/sqa/init.rb +70 -15
  90. data/lib/sqa/pattern_matcher.rb +4 -4
  91. data/lib/sqa/portfolio.rb +1 -1
  92. data/lib/sqa/sector_analyzer.rb +3 -11
  93. data/lib/sqa/stock.rb +236 -20
  94. data/lib/sqa/strategy.rb +62 -4
  95. data/lib/sqa/ticker.rb +107 -42
  96. data/lib/sqa/version.rb +1 -1
  97. data/lib/sqa.rb +16 -8
  98. data/mkdocs.yml +68 -117
  99. metadata +90 -36
  100. data/docs/README.md +0 -43
  101. data/docs/alpha_vantage_technical_indicators.md +0 -62
  102. data/docs/average_true_range.md +0 -9
  103. data/docs/bollinger_bands.md +0 -15
  104. data/docs/candlestick_pattern_recognizer.md +0 -4
  105. data/docs/donchian_channel.md +0 -5
  106. data/docs/double_top_bottom_pattern.md +0 -3
  107. data/docs/exponential_moving_average.md +0 -19
  108. data/docs/fibonacci_retracement.md +0 -30
  109. data/docs/head_and_shoulders_pattern.md +0 -3
  110. data/docs/market_profile.md +0 -4
  111. data/docs/momentum.md +0 -19
  112. data/docs/moving_average_convergence_divergence.md +0 -23
  113. data/docs/peaks_and_valleys.md +0 -11
  114. data/docs/relative_strength_index.md +0 -6
  115. data/docs/simple_moving_average.md +0 -8
  116. data/docs/stochastic_oscillator.md +0 -4
  117. data/docs/ta_lib.md +0 -160
  118. data/docs/true_range.md +0 -12
  119. data/docs/true_strength_index.md +0 -46
  120. data/docs/weighted_moving_average.md +0 -48
  121. data/examples/sinatra_app/Gemfile +0 -22
  122. data/examples/sinatra_app/QUICKSTART.md +0 -159
  123. data/examples/sinatra_app/README.md +0 -461
  124. data/examples/sinatra_app/app.rb +0 -344
  125. data/examples/sinatra_app/config.ru +0 -5
  126. data/examples/sinatra_app/public/css/style.css +0 -659
  127. data/examples/sinatra_app/public/js/app.js +0 -107
  128. data/examples/sinatra_app/views/analyze.erb +0 -306
  129. data/examples/sinatra_app/views/backtest.erb +0 -325
  130. data/examples/sinatra_app/views/dashboard.erb +0 -419
  131. data/examples/sinatra_app/views/error.erb +0 -58
  132. data/examples/sinatra_app/views/index.erb +0 -118
  133. data/examples/sinatra_app/views/layout.erb +0 -61
  134. data/examples/sinatra_app/views/portfolio.erb +0 -43
@@ -0,0 +1,752 @@
1
+ # 📦 SQA::DataFrame
2
+
3
+ !!! note "Description"
4
+ The website financial.yahoo.com no longer supports an API.
5
+ To get recent stock historical price updates you have
6
+ to scrape the webpage.
7
+
8
+ !!! abstract "Source Information"
9
+ **Defined in:** `lib/sqa/data_frame.rb:28`
10
+
11
+ **Inherits from:** `Object`
12
+
13
+ ## 🏭 Class Methods
14
+
15
+ ### `.is_date?(value)`
16
+
17
+ Checks if a value appears to be a date string.
18
+
19
+ !!! info "Parameters"
20
+
21
+ | Name | Type | Description |
22
+ |------|------|-------------|
23
+ | `value` | `Object` | Value to check |
24
+ !!! success "Returns"
25
+
26
+ **Type:** `Boolean`
27
+
28
+
29
+
30
+ true if value matches YYYY-MM-DD format
31
+
32
+ ??? info "Source Location"
33
+ `lib/sqa/data_frame.rb:246`
34
+
35
+ ---
36
+
37
+ ### `.load(source:, transformers: = {}, mapping: = {})`
38
+
39
+ Load a DataFrame from a file source
40
+ This is the primary method for loading persisted DataFrames
41
+
42
+ Note: For cached CSV files, transformers and mapping should typically be empty
43
+ since transformations were already applied when the data was first fetched.
44
+ We only apply them if the CSV has old-format column names that need migration.
45
+
46
+ !!! info "Parameters"
47
+
48
+ | Name | Type | Description |
49
+ |------|------|-------------|
50
+ | `source` | `String, Pathname` | Path to CSV file |
51
+ | `transformers` | `Hash` | Column transformations to apply (usually not needed for cached data) |
52
+ | `mapping` | `Hash` | Column name mappings (usually not needed for cached data) |
53
+ !!! success "Returns"
54
+
55
+ **Type:** `SQA::DataFrame`
56
+
57
+
58
+
59
+ Loaded DataFrame
60
+
61
+ ??? info "Source Location"
62
+ `lib/sqa/data_frame.rb:283`
63
+
64
+ ---
65
+
66
+ ### `.from_aofh(aofh, mapping: = {}, transformers: = {})`
67
+
68
+ Creates a DataFrame from an array of hashes.
69
+
70
+ !!! info "Parameters"
71
+
72
+ | Name | Type | Description |
73
+ |------|------|-------------|
74
+ | `aofh` | `Array<Hash>` | Array of hash records |
75
+ | `mapping` | `Hash` | Column name mappings to apply |
76
+ | `transformers` | `Hash` | Column transformers to apply |
77
+ !!! success "Returns"
78
+
79
+ **Type:** `SQA::DataFrame`
80
+
81
+
82
+
83
+ New DataFrame instance
84
+ !!! example "Usage Examples"
85
+
86
+ ```ruby
87
+ data = [{ "date" => "2024-01-01", "price" => 100.0 }]
88
+ df = SQA::DataFrame.from_aofh(data)
89
+ ```
90
+ ??? info "Source Location"
91
+ `lib/sqa/data_frame.rb:302`
92
+
93
+ ---
94
+
95
+ ### `.from_csv_file(source, mapping: = {}, transformers: = {})`
96
+
97
+ Creates a DataFrame from a CSV file.
98
+
99
+ !!! info "Parameters"
100
+
101
+ | Name | Type | Description |
102
+ |------|------|-------------|
103
+ | `source` | `String, Pathname` | Path to CSV file |
104
+ | `mapping` | `Hash` | Column name mappings to apply |
105
+ | `transformers` | `Hash` | Column transformers to apply |
106
+ !!! success "Returns"
107
+
108
+ **Type:** `SQA::DataFrame`
109
+
110
+
111
+
112
+ New DataFrame instance
113
+
114
+ ??? info "Source Location"
115
+ `lib/sqa/data_frame.rb:324`
116
+
117
+ ---
118
+
119
+ ### `.from_json_file(source, mapping: = {}, transformers: = {})`
120
+
121
+ Creates a DataFrame from a JSON file.
122
+
123
+ !!! info "Parameters"
124
+
125
+ | Name | Type | Description |
126
+ |------|------|-------------|
127
+ | `source` | `String, Pathname` | Path to JSON file containing array of objects |
128
+ | `mapping` | `Hash` | Column name mappings to apply |
129
+ | `transformers` | `Hash` | Column transformers to apply |
130
+ !!! success "Returns"
131
+
132
+ **Type:** `SQA::DataFrame`
133
+
134
+
135
+
136
+ New DataFrame instance
137
+
138
+ ??? info "Source Location"
139
+ `lib/sqa/data_frame.rb:335`
140
+
141
+ ---
142
+
143
+ ### `.generate_mapping(keys)`
144
+
145
+ Generates a mapping of original keys to underscored keys.
146
+
147
+ !!! info "Parameters"
148
+
149
+ | Name | Type | Description |
150
+ |------|------|-------------|
151
+ | `keys` | `Array<String>` | Original key names |
152
+ !!! success "Returns"
153
+
154
+ **Type:** `Hash{String => Symbol}`
155
+
156
+
157
+
158
+ Mapping from original to underscored keys
159
+
160
+ ??? info "Source Location"
161
+ `lib/sqa/data_frame.rb:344`
162
+
163
+ ---
164
+
165
+ ### `.underscore_key(key)`
166
+
167
+ Converts a key string to underscored snake_case format.
168
+
169
+ !!! info "Parameters"
170
+
171
+ | Name | Type | Description |
172
+ |------|------|-------------|
173
+ | `key` | `String` | Key to convert |
174
+ !!! success "Returns"
175
+
176
+ **Type:** `Symbol`
177
+
178
+
179
+
180
+ Underscored key as symbol
181
+ !!! example "Usage Examples"
182
+
183
+ ```ruby
184
+ underscore_key("closePrice") # => :close_price
185
+ underscore_key("Close Price") # => :close_price
186
+ ```
187
+ ??? info "Source Location"
188
+ `lib/sqa/data_frame.rb:359`
189
+
190
+ ---
191
+
192
+ ### `.sanitize_key()`
193
+
194
+ Converts a key string to underscored snake_case format.
195
+
196
+ !!! info "Parameters"
197
+
198
+ | Name | Type | Description |
199
+ |------|------|-------------|
200
+ | `key` | `String` | Key to convert |
201
+ !!! success "Returns"
202
+
203
+ **Type:** `Symbol`
204
+
205
+
206
+
207
+ Underscored key as symbol
208
+ !!! example "Usage Examples"
209
+
210
+ ```ruby
211
+ underscore_key("closePrice") # => :close_price
212
+ underscore_key("Close Price") # => :close_price
213
+ ```
214
+ ??? info "Source Location"
215
+ `lib/sqa/data_frame.rb:371`
216
+
217
+ ---
218
+
219
+ ### `.normalize_keys(hash, adapter_mapping: = {})`
220
+
221
+ Normalizes all keys in a hash to snake_case format.
222
+
223
+ !!! info "Parameters"
224
+
225
+ | Name | Type | Description |
226
+ |------|------|-------------|
227
+ | `hash` | `Hash` | Hash with keys to normalize |
228
+ | `adapter_mapping` | `Hash` | Optional pre-mapping to apply first |
229
+ !!! success "Returns"
230
+
231
+ **Type:** `Hash`
232
+
233
+
234
+
235
+ Hash with normalized keys
236
+
237
+ ??? info "Source Location"
238
+ `lib/sqa/data_frame.rb:378`
239
+
240
+ ---
241
+
242
+ ### `.rename(hash, mapping)`
243
+
244
+ Renames keys in a hash according to a mapping.
245
+
246
+ !!! info "Parameters"
247
+
248
+ | Name | Type | Description |
249
+ |------|------|-------------|
250
+ | `hash` | `Hash` | Hash to modify |
251
+ | `mapping` | `Hash` | Old key to new key mapping |
252
+ !!! success "Returns"
253
+
254
+ **Type:** `Hash`
255
+
256
+
257
+
258
+ Modified hash
259
+
260
+ ??? info "Source Location"
261
+ `lib/sqa/data_frame.rb:389`
262
+
263
+ ---
264
+
265
+ ### `.aofh_to_hofa(aofh, mapping: = {}, transformers: = {})`
266
+
267
+ Converts array of hashes to hash of arrays format.
268
+
269
+ !!! info "Parameters"
270
+
271
+ | Name | Type | Description |
272
+ |------|------|-------------|
273
+ | `aofh` | `Array<Hash>` | Array of hash records |
274
+ | `mapping` | `Hash` | Column name mappings (unused, for API compatibility) |
275
+ | `transformers` | `Hash` | Column transformers (unused, for API compatibility) |
276
+ !!! success "Returns"
277
+
278
+ **Type:** `Hash{String => Array}`
279
+
280
+
281
+
282
+ Hash with column names as keys and arrays as values
283
+
284
+ ??? info "Source Location"
285
+ `lib/sqa/data_frame.rb:400`
286
+
287
+ ---
288
+
289
+ ## 🔨 Instance Methods
290
+
291
+ ### `#data()`
292
+
293
+
294
+ !!! success "Returns"
295
+
296
+ **Type:** `Polars::DataFrame`
297
+
298
+
299
+
300
+ The underlying Polars DataFrame
301
+
302
+ ??? info "Source Location"
303
+ `lib/sqa/data_frame.rb:33`
304
+
305
+ ---
306
+
307
+ ### `#data=(value)`
308
+
309
+ Sets the attribute data
310
+
311
+ !!! info "Parameters"
312
+
313
+ | Name | Type | Description |
314
+ |------|------|-------------|
315
+ | `value` | `Any` | the value to set the attribute data to. |
316
+
317
+
318
+ ??? info "Source Location"
319
+ `lib/sqa/data_frame.rb:33`
320
+
321
+ ---
322
+
323
+ ### `#initialize(raw_data = nil, mapping: = {}, transformers: = {})`
324
+
325
+ Creates a new DataFrame instance.
326
+
327
+ !!! info "Parameters"
328
+
329
+ | Name | Type | Description |
330
+ |------|------|-------------|
331
+ | `raw_data` | `Hash, Array, Polars::DataFrame, nil` | Initial data for the DataFrame |
332
+ | `mapping` | `Hash` | Column name mappings to apply (old_name => new_name) |
333
+ | `transformers` | `Hash` | Column transformers to apply (column => lambda) |
334
+ !!! success "Returns"
335
+
336
+ **Type:** `DataFrame`
337
+
338
+
339
+
340
+ a new instance of DataFrame
341
+ !!! example "Usage Examples"
342
+
343
+ ```ruby
344
+ df = SQA::DataFrame.new(data, mapping: { "Close" => "close_price" })
345
+ ```
346
+
347
+ ```ruby
348
+ df = SQA::DataFrame.new(data, transformers: { "price" => ->(v) { v.to_f } })
349
+ ```
350
+ ??? info "Source Location"
351
+ `lib/sqa/data_frame.rb:47`
352
+
353
+ ---
354
+
355
+ ### `#apply_transformers!(transformers)`
356
+
357
+ Applies transformer functions to specified columns in place.
358
+
359
+ !!! info "Parameters"
360
+
361
+ | Name | Type | Description |
362
+ |------|------|-------------|
363
+ | `transformers` | `Hash{String, Symbol => Proc}` | Column name to transformer mapping |
364
+ !!! success "Returns"
365
+
366
+ **Type:** `void`
367
+
368
+
369
+ !!! example "Usage Examples"
370
+
371
+ ```ruby
372
+ df.apply_transformers!({ "price" => ->(v) { v.to_f }, "volume" => ->(v) { v.to_i } })
373
+ ```
374
+ ??? info "Source Location"
375
+ `lib/sqa/data_frame.rb:65`
376
+
377
+ ---
378
+
379
+ ### `#rename_columns!(mapping)`
380
+
381
+ Renames columns according to the provided mapping in place.
382
+
383
+ !!! info "Parameters"
384
+
385
+ | Name | Type | Description |
386
+ |------|------|-------------|
387
+ | `mapping` | `Hash{String, Symbol => String}` | Old column name to new column name mapping |
388
+ !!! success "Returns"
389
+
390
+ **Type:** `void`
391
+
392
+
393
+ !!! example "Usage Examples"
394
+
395
+ ```ruby
396
+ df.rename_columns!({ "open" => "open_price", "close" => "close_price" })
397
+ ```
398
+ ??? info "Source Location"
399
+ `lib/sqa/data_frame.rb:82`
400
+
401
+ ---
402
+
403
+ ### `#append!(other_df)`
404
+
405
+ Appends another DataFrame to this one in place.
406
+
407
+ !!! info "Parameters"
408
+
409
+ | Name | Type | Description |
410
+ |------|------|-------------|
411
+ | `other_df` | `SQA::DataFrame` | DataFrame to append |
412
+ !!! success "Returns"
413
+
414
+ **Type:** `void`
415
+
416
+
417
+ !!! example "Usage Examples"
418
+
419
+ ```ruby
420
+ df1.append!(df2)
421
+ ```
422
+ ??? info "Source Location"
423
+ `lib/sqa/data_frame.rb:107`
424
+
425
+ ---
426
+
427
+ ### `#concat!()`
428
+
429
+ Appends another DataFrame to this one in place.
430
+
431
+ !!! info "Parameters"
432
+
433
+ | Name | Type | Description |
434
+ |------|------|-------------|
435
+ | `other_df` | `SQA::DataFrame` | DataFrame to append |
436
+ !!! success "Returns"
437
+
438
+ **Type:** `void`
439
+
440
+
441
+ !!! example "Usage Examples"
442
+
443
+ ```ruby
444
+ df1.append!(df2)
445
+ ```
446
+ ??? info "Source Location"
447
+ `lib/sqa/data_frame.rb:124`
448
+
449
+ ---
450
+
451
+ ### `#concat_and_deduplicate!(other_df, sort_column: = "timestamp", descending: = false)`
452
+
453
+ Concatenate another DataFrame, remove duplicates, and sort
454
+ This is the preferred method for updating CSV data to prevent duplicates
455
+
456
+ NOTE: TA-Lib requires data in ascending (oldest-first) order. Using descending: true
457
+ will produce a warning and force ascending order to prevent silent calculation errors.
458
+
459
+ !!! info "Parameters"
460
+
461
+ | Name | Type | Description |
462
+ |------|------|-------------|
463
+ | `other_df` | `SQA::DataFrame` | DataFrame to append |
464
+ | `sort_column` | `String` | Column to use for deduplication and sorting (default: "timestamp") |
465
+ | `descending` | `Boolean` | Sort order - false for ascending (oldest first, TA-Lib compatible), true for descending |
466
+
467
+
468
+ ??? info "Source Location"
469
+ `lib/sqa/data_frame.rb:135`
470
+
471
+ ---
472
+
473
+ ### `#columns()`
474
+
475
+ Returns the column names of the DataFrame.
476
+
477
+
478
+ !!! success "Returns"
479
+
480
+ **Type:** `Array<String>`
481
+
482
+
483
+
484
+ List of column names
485
+
486
+ ??? info "Source Location"
487
+ `lib/sqa/data_frame.rb:159`
488
+
489
+ ---
490
+
491
+ ### `#keys()`
492
+
493
+ Returns the column names of the DataFrame.
494
+ Alias for {#columns}.
495
+
496
+
497
+ !!! success "Returns"
498
+
499
+ **Type:** `Array<String>`
500
+
501
+
502
+
503
+ List of column names
504
+
505
+ ??? info "Source Location"
506
+ `lib/sqa/data_frame.rb:167`
507
+
508
+ ---
509
+
510
+ ### `#vectors()`
511
+
512
+ Returns the column names of the DataFrame.
513
+ Alias for {#columns}.
514
+
515
+
516
+ !!! success "Returns"
517
+
518
+ **Type:** `Array<String>`
519
+
520
+
521
+
522
+ List of column names
523
+
524
+ ??? info "Source Location"
525
+ `lib/sqa/data_frame.rb:170`
526
+
527
+ ---
528
+
529
+ ### `#to_h()`
530
+
531
+ Converts the DataFrame to a Ruby Hash.
532
+
533
+
534
+ !!! success "Returns"
535
+
536
+ **Type:** `Hash{Symbol => Array}`
537
+
538
+
539
+
540
+ Hash with column names as keys and column data as arrays
541
+ !!! example "Usage Examples"
542
+
543
+ ```ruby
544
+ df.to_h # => { timestamp: ["2024-01-01", ...], close_price: [100.0, ...] }
545
+ ```
546
+ ??? info "Source Location"
547
+ `lib/sqa/data_frame.rb:179`
548
+
549
+ ---
550
+
551
+ ### `#to_csv(path_to_file)`
552
+
553
+ Writes the DataFrame to a CSV file.
554
+
555
+ !!! info "Parameters"
556
+
557
+ | Name | Type | Description |
558
+ |------|------|-------------|
559
+ | `path_to_file` | `String, Pathname` | Path to output CSV file |
560
+ !!! success "Returns"
561
+
562
+ **Type:** `void`
563
+
564
+
565
+
566
+ ??? info "Source Location"
567
+ `lib/sqa/data_frame.rb:187`
568
+
569
+ ---
570
+
571
+ ### `#size()`
572
+
573
+ Returns the number of rows in the DataFrame.
574
+
575
+
576
+ !!! success "Returns"
577
+
578
+ **Type:** `Integer`
579
+
580
+
581
+
582
+ Row count
583
+
584
+ ??? info "Source Location"
585
+ `lib/sqa/data_frame.rb:194`
586
+
587
+ ---
588
+
589
+ ### `#nrows()`
590
+
591
+ Returns the number of rows in the DataFrame.
592
+
593
+
594
+ !!! success "Returns"
595
+
596
+ **Type:** `Integer`
597
+
598
+
599
+
600
+ Row count
601
+
602
+ ??? info "Source Location"
603
+ `lib/sqa/data_frame.rb:197`
604
+
605
+ ---
606
+
607
+ ### `#length()`
608
+
609
+ Returns the number of rows in the DataFrame.
610
+
611
+
612
+ !!! success "Returns"
613
+
614
+ **Type:** `Integer`
615
+
616
+
617
+
618
+ Row count
619
+
620
+ ??? info "Source Location"
621
+ `lib/sqa/data_frame.rb:198`
622
+
623
+ ---
624
+
625
+ ### `#ncols()`
626
+
627
+ Returns the number of columns in the DataFrame.
628
+
629
+
630
+ !!! success "Returns"
631
+
632
+ **Type:** `Integer`
633
+
634
+
635
+
636
+ Column count
637
+
638
+ ??? info "Source Location"
639
+ `lib/sqa/data_frame.rb:203`
640
+
641
+ ---
642
+
643
+ ### `#fpl(column: = 'adj_close_price', fpop: = 14)`
644
+
645
+ FPL Analysis - Calculate Future Period Loss/Profit
646
+
647
+ !!! info "Parameters"
648
+
649
+ | Name | Type | Description |
650
+ |------|------|-------------|
651
+ | `column` | `String, Symbol` | Column name containing prices (default: "adj_close_price") |
652
+ | `fpop` | `Integer` | Future Period of Performance (days to look ahead) |
653
+ !!! success "Returns"
654
+
655
+ **Type:** `Array<Array<Float, Float>>`
656
+
657
+
658
+
659
+ Array of [min_delta, max_delta] pairs
660
+ !!! example "Usage Examples"
661
+
662
+ ```ruby
663
+ stock = SQA::Stock.new(ticker: 'AAPL')
664
+ fpl_data = stock.df.fpl(fpop: 10)
665
+ ```
666
+ ??? info "Source Location"
667
+ `lib/sqa/data_frame.rb:218`
668
+
669
+ ---
670
+
671
+ ### `#fpl_analysis(column: = 'adj_close_price', fpop: = 14)`
672
+
673
+ FPL Analysis with risk metrics and classification
674
+
675
+ !!! info "Parameters"
676
+
677
+ | Name | Type | Description |
678
+ |------|------|-------------|
679
+ | `column` | `String, Symbol` | Column name containing prices (default: "adj_close_price") |
680
+ | `fpop` | `Integer` | Future Period of Performance |
681
+ !!! success "Returns"
682
+
683
+ **Type:** `Array<Hash>`
684
+
685
+
686
+
687
+ Array of analysis hashes
688
+ !!! example "Usage Examples"
689
+
690
+ ```ruby
691
+ analysis = stock.df.fpl_analysis(fpop: 10)
692
+ analysis.first[:direction] # => :UP, :DOWN, :UNCERTAIN, or :FLAT
693
+ analysis.first[:magnitude] # => Average expected movement percentage
694
+ analysis.first[:risk] # => Volatility range
695
+ ```
696
+ ??? info "Source Location"
697
+ `lib/sqa/data_frame.rb:236`
698
+
699
+ ---
700
+
701
+ ### `#method_missing(method_name, *args, &block)`
702
+
703
+ Delegates unknown methods to the underlying Polars DataFrame.
704
+ This allows direct access to Polars methods like filter, select, etc.
705
+
706
+ !!! info "Parameters"
707
+
708
+ | Name | Type | Description |
709
+ |------|------|-------------|
710
+ | `method_name` | `Symbol` | Method name being called |
711
+ | `args` | `Array` | Method arguments |
712
+ | `block` | `Proc` | Optional block |
713
+ !!! success "Returns"
714
+
715
+ **Type:** `Object`
716
+
717
+
718
+
719
+ Result from Polars DataFrame method
720
+
721
+ ??? info "Source Location"
722
+ `lib/sqa/data_frame.rb:257`
723
+
724
+ ---
725
+
726
+ ### `#respond_to_missing?(method_name, include_private = false)`
727
+
728
+ Checks if the DataFrame responds to a method.
729
+
730
+ !!! info "Parameters"
731
+
732
+ | Name | Type | Description |
733
+ |------|------|-------------|
734
+ | `method_name` | `Symbol` | Method name to check |
735
+ | `include_private` | `Boolean` | Include private methods |
736
+ !!! success "Returns"
737
+
738
+ **Type:** `Boolean`
739
+
740
+
741
+
742
+ true if method is available
743
+
744
+ ??? info "Source Location"
745
+ `lib/sqa/data_frame.rb:267`
746
+
747
+ ---
748
+
749
+ ## 📝 Attributes
750
+
751
+ ### 🔄 `data` <small>read/write</small>
752
+