sqa 0.0.24 → 0.0.31

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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/.goose/memory/development.txt +3 -0
  3. data/.semver +6 -0
  4. data/ARCHITECTURE.md +648 -0
  5. data/CHANGELOG.md +82 -0
  6. data/CLAUDE.md +653 -0
  7. data/COMMITS.md +196 -0
  8. data/DATAFRAME_ARCHITECTURE_REVIEW.md +421 -0
  9. data/NEXT-STEPS.md +154 -0
  10. data/README.md +812 -262
  11. data/TASKS.md +358 -0
  12. data/TEST_RESULTS.md +140 -0
  13. data/TODO.md +42 -0
  14. data/_notes.txt +25 -0
  15. data/bin/sqa-console +11 -0
  16. data/data/talk_talk.json +103284 -0
  17. data/develop_summary.md +313 -0
  18. data/docs/advanced/backtesting.md +206 -0
  19. data/docs/advanced/ensemble.md +68 -0
  20. data/docs/advanced/fpop.md +153 -0
  21. data/docs/advanced/index.md +112 -0
  22. data/docs/advanced/multi-timeframe.md +67 -0
  23. data/docs/advanced/pattern-matcher.md +75 -0
  24. data/docs/advanced/portfolio-optimizer.md +79 -0
  25. data/docs/advanced/portfolio.md +166 -0
  26. data/docs/advanced/risk-management.md +210 -0
  27. data/docs/advanced/strategy-generator.md +158 -0
  28. data/docs/advanced/streaming.md +209 -0
  29. data/docs/ai_and_ml.md +80 -0
  30. data/docs/api/dataframe.md +1115 -0
  31. data/docs/api/index.md +126 -0
  32. data/docs/assets/css/custom.css +88 -0
  33. data/docs/assets/js/mathjax.js +18 -0
  34. data/docs/concepts/index.md +68 -0
  35. data/docs/contributing/index.md +60 -0
  36. data/docs/data-sources/index.md +66 -0
  37. data/docs/data_frame.md +317 -97
  38. data/docs/factors_that_impact_price.md +26 -0
  39. data/docs/finviz.md +11 -0
  40. data/docs/fx_pro_bit.md +25 -0
  41. data/docs/genetic_programming.md +104 -0
  42. data/docs/getting-started/index.md +123 -0
  43. data/docs/getting-started/installation.md +229 -0
  44. data/docs/getting-started/quick-start.md +244 -0
  45. data/docs/i_gotta_an_idea.md +22 -0
  46. data/docs/index.md +163 -0
  47. data/docs/indicators/index.md +97 -0
  48. data/docs/indicators.md +110 -24
  49. data/docs/options.md +8 -0
  50. data/docs/strategies/bollinger-bands.md +146 -0
  51. data/docs/strategies/consensus.md +64 -0
  52. data/docs/strategies/custom.md +310 -0
  53. data/docs/strategies/ema.md +53 -0
  54. data/docs/strategies/index.md +92 -0
  55. data/docs/strategies/kbs.md +164 -0
  56. data/docs/strategies/macd.md +96 -0
  57. data/docs/strategies/market-profile.md +54 -0
  58. data/docs/strategies/mean-reversion.md +58 -0
  59. data/docs/strategies/rsi.md +95 -0
  60. data/docs/strategies/sma.md +55 -0
  61. data/docs/strategies/stochastic.md +63 -0
  62. data/docs/strategies/volume-breakout.md +54 -0
  63. data/docs/tags.md +7 -0
  64. data/docs/true_strength_index.md +46 -0
  65. data/docs/weighted_moving_average.md +48 -0
  66. data/examples/README.md +354 -0
  67. data/examples/advanced_features_example.rb +350 -0
  68. data/examples/fpop_analysis_example.rb +191 -0
  69. data/examples/genetic_programming_example.rb +148 -0
  70. data/examples/kbs_strategy_example.rb +208 -0
  71. data/examples/pattern_context_example.rb +300 -0
  72. data/examples/rails_app/Gemfile +34 -0
  73. data/examples/rails_app/README.md +416 -0
  74. data/examples/rails_app/app/assets/javascripts/application.js +107 -0
  75. data/examples/rails_app/app/assets/stylesheets/application.css +659 -0
  76. data/examples/rails_app/app/controllers/analysis_controller.rb +11 -0
  77. data/examples/rails_app/app/controllers/api/v1/stocks_controller.rb +227 -0
  78. data/examples/rails_app/app/controllers/application_controller.rb +22 -0
  79. data/examples/rails_app/app/controllers/backtest_controller.rb +11 -0
  80. data/examples/rails_app/app/controllers/dashboard_controller.rb +21 -0
  81. data/examples/rails_app/app/controllers/portfolio_controller.rb +7 -0
  82. data/examples/rails_app/app/views/analysis/show.html.erb +209 -0
  83. data/examples/rails_app/app/views/backtest/show.html.erb +171 -0
  84. data/examples/rails_app/app/views/dashboard/index.html.erb +118 -0
  85. data/examples/rails_app/app/views/dashboard/show.html.erb +408 -0
  86. data/examples/rails_app/app/views/errors/show.html.erb +17 -0
  87. data/examples/rails_app/app/views/layouts/application.html.erb +60 -0
  88. data/examples/rails_app/app/views/portfolio/index.html.erb +33 -0
  89. data/examples/rails_app/bin/rails +6 -0
  90. data/examples/rails_app/config/application.rb +45 -0
  91. data/examples/rails_app/config/boot.rb +5 -0
  92. data/examples/rails_app/config/database.yml +18 -0
  93. data/examples/rails_app/config/environment.rb +11 -0
  94. data/examples/rails_app/config/routes.rb +26 -0
  95. data/examples/rails_app/config.ru +8 -0
  96. data/examples/realtime_stream_example.rb +274 -0
  97. data/examples/sinatra_app/Gemfile +22 -0
  98. data/examples/sinatra_app/QUICKSTART.md +159 -0
  99. data/examples/sinatra_app/README.md +461 -0
  100. data/examples/sinatra_app/app.rb +344 -0
  101. data/examples/sinatra_app/config.ru +5 -0
  102. data/examples/sinatra_app/public/css/style.css +659 -0
  103. data/examples/sinatra_app/public/js/app.js +107 -0
  104. data/examples/sinatra_app/views/analyze.erb +306 -0
  105. data/examples/sinatra_app/views/backtest.erb +325 -0
  106. data/examples/sinatra_app/views/dashboard.erb +419 -0
  107. data/examples/sinatra_app/views/error.erb +58 -0
  108. data/examples/sinatra_app/views/index.erb +118 -0
  109. data/examples/sinatra_app/views/layout.erb +61 -0
  110. data/examples/sinatra_app/views/portfolio.erb +43 -0
  111. data/examples/strategy_generator_example.rb +346 -0
  112. data/hsa_portfolio.csv +11 -0
  113. data/justfile +0 -0
  114. data/lib/api/alpha_vantage_api.rb +462 -0
  115. data/lib/sqa/backtest.rb +329 -0
  116. data/lib/sqa/data_frame/alpha_vantage.rb +43 -65
  117. data/lib/sqa/data_frame/data.rb +92 -0
  118. data/lib/sqa/data_frame/yahoo_finance.rb +35 -43
  119. data/lib/sqa/data_frame.rb +148 -243
  120. data/lib/sqa/ensemble.rb +359 -0
  121. data/lib/sqa/fpop.rb +199 -0
  122. data/lib/sqa/gp.rb +259 -0
  123. data/lib/sqa/indicator.rb +5 -8
  124. data/lib/sqa/init.rb +15 -8
  125. data/lib/sqa/market_regime.rb +240 -0
  126. data/lib/sqa/multi_timeframe.rb +379 -0
  127. data/lib/sqa/pattern_matcher.rb +497 -0
  128. data/lib/sqa/portfolio.rb +260 -6
  129. data/lib/sqa/portfolio_optimizer.rb +377 -0
  130. data/lib/sqa/risk_manager.rb +442 -0
  131. data/lib/sqa/seasonal_analyzer.rb +209 -0
  132. data/lib/sqa/sector_analyzer.rb +300 -0
  133. data/lib/sqa/stock.rb +67 -125
  134. data/lib/sqa/strategy/bollinger_bands.rb +42 -0
  135. data/lib/sqa/strategy/consensus.rb +5 -2
  136. data/lib/sqa/strategy/kbs_strategy.rb +470 -0
  137. data/lib/sqa/strategy/macd.rb +46 -0
  138. data/lib/sqa/strategy/mp.rb +1 -1
  139. data/lib/sqa/strategy/stochastic.rb +60 -0
  140. data/lib/sqa/strategy/volume_breakout.rb +57 -0
  141. data/lib/sqa/strategy.rb +5 -0
  142. data/lib/sqa/strategy_generator.rb +947 -0
  143. data/lib/sqa/stream.rb +361 -0
  144. data/lib/sqa/version.rb +1 -7
  145. data/lib/sqa.rb +23 -16
  146. data/main.just +81 -0
  147. data/mkdocs.yml +288 -0
  148. data/trace.log +0 -0
  149. metadata +261 -51
  150. data/bin/sqa +0 -6
  151. data/lib/patches/dry-cli.rb +0 -228
  152. data/lib/sqa/activity.rb +0 -10
  153. data/lib/sqa/cli.rb +0 -62
  154. data/lib/sqa/commands/analysis.rb +0 -309
  155. data/lib/sqa/commands/base.rb +0 -139
  156. data/lib/sqa/commands/web.rb +0 -199
  157. data/lib/sqa/commands.rb +0 -22
  158. data/lib/sqa/constants.rb +0 -23
  159. data/lib/sqa/indicator/average_true_range.rb +0 -33
  160. data/lib/sqa/indicator/bollinger_bands.rb +0 -28
  161. data/lib/sqa/indicator/candlestick_pattern_recognizer.rb +0 -60
  162. data/lib/sqa/indicator/donchian_channel.rb +0 -29
  163. data/lib/sqa/indicator/double_top_bottom_pattern.rb +0 -34
  164. data/lib/sqa/indicator/elliott_wave_theory.rb +0 -57
  165. data/lib/sqa/indicator/exponential_moving_average.rb +0 -25
  166. data/lib/sqa/indicator/exponential_moving_average_trend.rb +0 -36
  167. data/lib/sqa/indicator/fibonacci_retracement.rb +0 -23
  168. data/lib/sqa/indicator/head_and_shoulders_pattern.rb +0 -26
  169. data/lib/sqa/indicator/market_profile.rb +0 -32
  170. data/lib/sqa/indicator/mean_reversion.rb +0 -37
  171. data/lib/sqa/indicator/momentum.rb +0 -28
  172. data/lib/sqa/indicator/moving_average_convergence_divergence.rb +0 -29
  173. data/lib/sqa/indicator/peaks_and_valleys.rb +0 -29
  174. data/lib/sqa/indicator/predict_next_value.rb +0 -202
  175. data/lib/sqa/indicator/relative_strength_index.rb +0 -47
  176. data/lib/sqa/indicator/simple_moving_average.rb +0 -24
  177. data/lib/sqa/indicator/simple_moving_average_trend.rb +0 -32
  178. data/lib/sqa/indicator/stochastic_oscillator.rb +0 -68
  179. data/lib/sqa/indicator/true_range.rb +0 -39
  180. data/lib/sqa/trade.rb +0 -26
@@ -0,0 +1,43 @@
1
+ <div class="dashboard">
2
+ <div class="dashboard-header">
3
+ <div class="ticker-info">
4
+ <h1><i class="fas fa-briefcase"></i> Portfolio Optimization</h1>
5
+ <p style="color: var(--text-secondary); margin-top: 0.5rem;">
6
+ Optimize allocation across multiple stocks for maximum risk-adjusted returns
7
+ </p>
8
+ </div>
9
+ </div>
10
+
11
+ <div class="chart-container">
12
+ <div class="chart-header">
13
+ <h2><i class="fas fa-layer-group"></i> Coming Soon</h2>
14
+ </div>
15
+ <div style="padding: 3rem 2rem; text-align: center;">
16
+ <div style="font-size: 5rem; color: var(--primary-color); margin-bottom: 2rem;">
17
+ <i class="fas fa-tools"></i>
18
+ </div>
19
+ <h3 style="font-size: 2rem; margin-bottom: 1rem; color: var(--text-primary);">
20
+ Portfolio Optimization Feature
21
+ </h3>
22
+ <p style="font-size: 1.1rem; color: var(--text-secondary); max-width: 600px; margin: 0 auto 2rem; line-height: 1.8;">
23
+ This feature will allow you to optimize portfolio allocation across multiple stocks
24
+ using various methods including Maximum Sharpe ratio, Minimum Variance, and Risk Parity.
25
+ </p>
26
+ <div style="background: var(--light-bg); padding: 2rem; border-radius: 12px; max-width: 800px; margin: 0 auto;">
27
+ <h4 style="margin-bottom: 1rem; color: var(--text-primary);">Planned Features:</h4>
28
+ <ul style="text-align: left; max-width: 500px; margin: 0 auto; line-height: 2;">
29
+ <li><i class="fas fa-check-circle" style="color: var(--success-color);"></i> Maximum Sharpe Ratio Optimization</li>
30
+ <li><i class="fas fa-check-circle" style="color: var(--success-color);"></i> Minimum Variance Portfolio</li>
31
+ <li><i class="fas fa-check-circle" style="color: var(--success-color);"></i> Risk Parity Allocation</li>
32
+ <li><i class="fas fa-check-circle" style="color: var(--success-color);"></i> Efficient Frontier Visualization</li>
33
+ <li><i class="fas fa-check-circle" style="color: var(--success-color);"></i> Multi-stock Correlation Analysis</li>
34
+ </ul>
35
+ </div>
36
+ <div style="margin-top: 2rem;">
37
+ <a href="/" class="btn btn-primary">
38
+ <i class="fas fa-home"></i> Back to Home
39
+ </a>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
@@ -0,0 +1,346 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Strategy Generator - Reverse Engineering Profitable Trades
5
+ #
6
+ # This example demonstrates how to use SQA::StrategyGenerator to:
7
+ # 1. Detect inflection points (turning points) in price history
8
+ # 2. Identify which inflection points preceded profitable moves
9
+ # 3. Discover which indicators were active at those points
10
+ # 4. Generate trading strategies from discovered patterns
11
+ # 5. Backtest the generated strategies
12
+ #
13
+ # FPOP (Future Period of Performance): The number of days to look ahead
14
+ # from an inflection point to measure if price change exceeds threshold.
15
+
16
+ require 'sqa'
17
+
18
+ SQA.init
19
+
20
+ puts "=" * 70
21
+ puts "Strategy Generator: Mining Profitable Patterns"
22
+ puts "=" * 70
23
+ puts
24
+
25
+ # Load stock data
26
+ puts "Loading stock data for AAPL..."
27
+ stock = SQA::Stock.new(ticker: 'AAPL')
28
+ puts "Loaded #{stock.df.data.height} days of price history"
29
+ puts
30
+
31
+ # Example 1: Basic Pattern Discovery with FPOP
32
+ puts "\n" + "=" * 70
33
+ puts "Example 1: Discovering Patterns with FPOP (Future Period of Performance)"
34
+ puts "=" * 70
35
+ puts
36
+
37
+ generator = SQA::StrategyGenerator.new(
38
+ stock: stock,
39
+ min_gain_percent: 10.0, # Find inflection points that lead to ≥10% gain
40
+ fpop: 10, # Look 10 days ahead from inflection point
41
+ inflection_window: 3 # 3-day window for detecting local min/max
42
+ )
43
+
44
+ # Discover patterns
45
+ patterns = generator.discover_patterns(min_pattern_frequency: 3)
46
+
47
+ # Print discovered patterns
48
+ generator.print_patterns(max_patterns: 10)
49
+
50
+ # Example 2: Generate Strategies from Patterns
51
+ puts "\n" + "=" * 70
52
+ puts "Example 2: Generating Strategies from Top Patterns"
53
+ puts "=" * 70
54
+ puts
55
+
56
+ if patterns.any?
57
+ # Generate top 3 strategies
58
+ strategies = generator.generate_strategies(top_n: 3, strategy_type: :class)
59
+
60
+ puts "Generated #{strategies.size} strategies from top patterns"
61
+ puts
62
+
63
+ # Test each generated strategy
64
+ strategies.each_with_index do |strategy, i|
65
+ puts "-" * 70
66
+ puts "Testing Generated Strategy ##{i + 1}"
67
+ puts "Pattern: #{strategy.pattern}"
68
+ puts
69
+
70
+ backtest = SQA::Backtest.new(
71
+ stock: stock,
72
+ strategy: strategy,
73
+ initial_capital: 10_000.0,
74
+ commission: 1.0
75
+ )
76
+
77
+ results = backtest.run
78
+
79
+ puts "Backtest Results:"
80
+ puts " Total Return: #{results.total_return.round(2)}%"
81
+ puts " Sharpe Ratio: #{results.sharpe_ratio.round(2)}"
82
+ puts " Max Drawdown: #{results.max_drawdown.round(2)}%"
83
+ puts " Win Rate: #{results.win_rate.round(2)}%"
84
+ puts " Total Trades: #{results.total_trades}"
85
+ puts
86
+ end
87
+ end
88
+
89
+ # Example 3: Different Gain Thresholds
90
+ puts "\n" + "=" * 70
91
+ puts "Example 3: Comparing Different Gain Thresholds"
92
+ puts "=" * 70
93
+ puts
94
+
95
+ gain_thresholds = [5.0, 10.0, 15.0, 20.0]
96
+
97
+ gain_thresholds.each do |threshold|
98
+ puts "-" * 70
99
+ puts "Target Gain: #{threshold}%"
100
+ puts
101
+
102
+ gen = SQA::StrategyGenerator.new(
103
+ stock: stock,
104
+ min_gain_percent: threshold,
105
+ fpop: 10
106
+ )
107
+
108
+ patterns = gen.discover_patterns(min_pattern_frequency: 2)
109
+
110
+ if patterns.any?
111
+ top_pattern = patterns.first
112
+ puts "Top Pattern Found:"
113
+ puts " Frequency: #{top_pattern.frequency} occurrences"
114
+ puts " Average Gain: #{top_pattern.avg_gain.round(2)}%"
115
+ puts " Average Holding: #{top_pattern.avg_holding_days.round(1)} days"
116
+ puts " Conditions: #{top_pattern.conditions}"
117
+ else
118
+ puts "No patterns found for #{threshold}% gain threshold"
119
+ end
120
+ puts
121
+ end
122
+
123
+ # Example 4: Different FPOP Periods
124
+ puts "\n" + "=" * 70
125
+ puts "Example 4: Short-term vs Long-term FPOP"
126
+ puts "=" * 70
127
+ puts
128
+
129
+ fpop_configs = [
130
+ { name: "Short-term", fpop: 5 },
131
+ { name: "Medium-term", fpop: 15 },
132
+ { name: "Long-term", fpop: 30 }
133
+ ]
134
+
135
+ fpop_configs.each do |config|
136
+ puts "-" * 70
137
+ puts "#{config[:name]} FPOP (#{config[:fpop]} days)"
138
+ puts
139
+
140
+ gen = SQA::StrategyGenerator.new(
141
+ stock: stock,
142
+ min_gain_percent: 10.0,
143
+ fpop: config[:fpop]
144
+ )
145
+
146
+ patterns = gen.discover_patterns(min_pattern_frequency: 2)
147
+
148
+ if patterns.any?
149
+ puts "Discovered #{patterns.size} patterns"
150
+ puts "Top Pattern:"
151
+ top = patterns.first
152
+ puts " Frequency: #{top.frequency}"
153
+ puts " Avg Gain: #{top.avg_gain.round(2)}%"
154
+ puts " Avg Holding: #{top.avg_holding_days.round(1)} days"
155
+ puts " Conditions: #{top.conditions.keys.join(', ')}"
156
+ else
157
+ puts "No patterns found"
158
+ end
159
+ puts
160
+ end
161
+
162
+ # Example 5: Export Patterns to CSV
163
+ puts "\n" + "=" * 70
164
+ puts "Example 5: Exporting Patterns"
165
+ puts "=" * 70
166
+ puts
167
+
168
+ generator = SQA::StrategyGenerator.new(
169
+ stock: stock,
170
+ min_gain_percent: 10.0,
171
+ fpop: 10
172
+ )
173
+
174
+ patterns = generator.discover_patterns(min_pattern_frequency: 2)
175
+
176
+ if patterns.any?
177
+ output_file = "/tmp/sqa_discovered_patterns.csv"
178
+ generator.export_patterns(output_file)
179
+ puts "Patterns exported successfully!"
180
+ puts "View with: cat #{output_file}"
181
+ puts
182
+ end
183
+
184
+ # Example 6: Generate and Compare Multiple Strategies
185
+ puts "\n" + "=" * 70
186
+ puts "Example 6: Strategy Performance Comparison"
187
+ puts "=" * 70
188
+ puts
189
+
190
+ generator = SQA::StrategyGenerator.new(
191
+ stock: stock,
192
+ min_gain_percent: 10.0,
193
+ fpop: 10
194
+ )
195
+
196
+ patterns = generator.discover_patterns(min_pattern_frequency: 3)
197
+
198
+ if patterns.size >= 3
199
+ puts "Comparing Top 3 Discovered Strategies vs Traditional Strategies"
200
+ puts "-" * 70
201
+ puts
202
+
203
+ comparison = []
204
+
205
+ # Test discovered strategies
206
+ [0, 1, 2].each do |i|
207
+ strategy = generator.generate_strategy(pattern_index: i, strategy_type: :class)
208
+
209
+ backtest = SQA::Backtest.new(
210
+ stock: stock,
211
+ strategy: strategy,
212
+ initial_capital: 10_000.0,
213
+ commission: 1.0
214
+ )
215
+
216
+ results = backtest.run
217
+
218
+ comparison << {
219
+ name: "Discovered ##{i + 1}",
220
+ return: results.total_return,
221
+ sharpe: results.sharpe_ratio,
222
+ drawdown: results.max_drawdown,
223
+ win_rate: results.win_rate,
224
+ trades: results.total_trades
225
+ }
226
+ end
227
+
228
+ # Test traditional strategies for comparison
229
+ traditional_strategies = [
230
+ { name: "RSI", class: SQA::Strategy::RSI },
231
+ { name: "MACD", class: SQA::Strategy::MACD },
232
+ { name: "Bollinger Bands", class: SQA::Strategy::BollingerBands }
233
+ ]
234
+
235
+ traditional_strategies.each do |strat|
236
+ backtest = SQA::Backtest.new(
237
+ stock: stock,
238
+ strategy: strat[:class],
239
+ initial_capital: 10_000.0,
240
+ commission: 1.0
241
+ )
242
+
243
+ results = backtest.run
244
+
245
+ comparison << {
246
+ name: strat[:name],
247
+ return: results.total_return,
248
+ sharpe: results.sharpe_ratio,
249
+ drawdown: results.max_drawdown,
250
+ win_rate: results.win_rate,
251
+ trades: results.total_trades
252
+ }
253
+ end
254
+
255
+ # Print comparison table
256
+ puts "Strategy Performance Comparison:"
257
+ puts "-" * 70
258
+ printf("%-20s %10s %10s %12s %10s %8s\n",
259
+ "Strategy", "Return %", "Sharpe", "Drawdown %", "Win Rate", "Trades")
260
+ puts "-" * 70
261
+
262
+ comparison.sort_by { |s| -s[:return] }.each do |s|
263
+ printf("%-20s %10.2f %10.2f %12.2f %9.1f%% %8d\n",
264
+ s[:name],
265
+ s[:return],
266
+ s[:sharpe],
267
+ s[:drawdown],
268
+ s[:win_rate],
269
+ s[:trades])
270
+ end
271
+ puts "-" * 70
272
+ puts
273
+
274
+ # Find best performer
275
+ best = comparison.max_by { |s| s[:return] }
276
+ puts "🏆 Best Performer: #{best[:name]}"
277
+ puts " Total Return: #{best[:return].round(2)}%"
278
+ puts " Sharpe Ratio: #{best[:sharpe].round(2)}"
279
+ puts
280
+ end
281
+
282
+ # Example 7: Aggressive Pattern Mining
283
+ puts "\n" + "=" * 70
284
+ puts "Example 7: Aggressive Pattern Discovery (High Gains)"
285
+ puts "=" * 70
286
+ puts
287
+
288
+ aggressive_gen = SQA::StrategyGenerator.new(
289
+ stock: stock,
290
+ min_gain_percent: 20.0, # Very high gain target
291
+ fpop: 15
292
+ )
293
+
294
+ aggressive_patterns = aggressive_gen.discover_patterns(min_pattern_frequency: 1)
295
+
296
+ if aggressive_patterns.any?
297
+ puts "Aggressive patterns found for 20%+ gains:"
298
+ aggressive_gen.print_patterns(max_patterns: 5)
299
+
300
+ # Test the most aggressive pattern
301
+ puts "Testing Most Aggressive Pattern:"
302
+ puts "-" * 70
303
+
304
+ aggressive_strategy = aggressive_gen.generate_strategy(
305
+ pattern_index: 0,
306
+ strategy_type: :class
307
+ )
308
+
309
+ backtest = SQA::Backtest.new(
310
+ stock: stock,
311
+ strategy: aggressive_strategy,
312
+ initial_capital: 10_000.0,
313
+ commission: 1.0
314
+ )
315
+
316
+ results = backtest.run
317
+
318
+ puts "Results:"
319
+ puts " Total Return: #{results.total_return.round(2)}%"
320
+ puts " Sharpe Ratio: #{results.sharpe_ratio.round(2)}"
321
+ puts " Max Drawdown: #{results.max_drawdown.round(2)}%"
322
+ puts " Win Rate: #{results.win_rate.round(2)}%"
323
+ puts " Total Trades: #{results.total_trades}"
324
+ puts
325
+ puts "⚠️ Note: High gain patterns often have lower frequency and higher risk"
326
+ else
327
+ puts "No patterns found for 20%+ gains (criteria too strict)"
328
+ end
329
+ puts
330
+
331
+ puts "=" * 70
332
+ puts "Strategy Generation Complete!"
333
+ puts "=" * 70
334
+ puts
335
+ puts "Key Takeaways:"
336
+ puts "1. Pattern discovery identifies what indicators were active at profitable points"
337
+ puts "2. Higher gain thresholds yield fewer but potentially more profitable patterns"
338
+ puts "3. Different holding periods reveal different trading styles"
339
+ puts "4. Generated strategies can outperform traditional single-indicator strategies"
340
+ puts "5. Always backtest discovered patterns before live trading"
341
+ puts
342
+ puts "Next Steps:"
343
+ puts "- Combine with Genetic Programming to optimize pattern parameters"
344
+ puts "- Use KBS to create rule-based strategies from complex patterns"
345
+ puts "- Test on multiple stocks to find universal patterns"
346
+ puts "- Walk-forward validate patterns on out-of-sample data"
data/hsa_portfolio.csv ADDED
@@ -0,0 +1,11 @@
1
+ # hsa_portfolio.csv
2
+ # health savings account hationalhr.com via oddball
3
+ # Fund %
4
+ #
5
+ # Ticker, Name, Shares (actually %)
6
+ #
7
+ HCB1B,HCB INTEREST BEARING ACCOUNT,10
8
+ VFIAX,VANGUARD 500 INDEX ADMIRAL,10
9
+ VSCIX,VANGUARD SMALL CAP INDEX INST,10
10
+ VSGIX,VANGUARD SMALL CP GROWTH IDX I,30
11
+ VIPIX,VANGUARD INFLATION PROTECTED I,40
data/justfile ADDED
File without changes