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,310 @@
1
+ # Creating Custom Strategies
2
+
3
+ ## Overview
4
+
5
+ Learn how to create your own trading strategies in the SQA framework.
6
+
7
+ ## Strategy Interface
8
+
9
+ All strategies must implement a `self.trade(vector)` class method that returns `:buy`, `:sell`, or `:hold`.
10
+
11
+ ## Basic Template
12
+
13
+ ```ruby
14
+ # lib/sqa/strategy/my_strategy.rb
15
+
16
+ class SQA::Strategy::MyStrategy
17
+ def self.trade(vector)
18
+ # 1. Validate input
19
+ return :hold unless vector.respond_to?(:prices)
20
+ return :hold if vector.prices.nil? || vector.prices.size < 20
21
+
22
+ # 2. Extract data
23
+ prices = vector.prices
24
+
25
+ # 3. Calculate indicators
26
+ sma = SQAI.sma(prices, period: 20)
27
+ rsi = SQAI.rsi(prices, period: 14)
28
+
29
+ # 4. Implement trading logic
30
+ if rsi.last < 30 && prices.last > sma.last
31
+ :buy
32
+ elsif rsi.last > 70 && prices.last < sma.last
33
+ :sell
34
+ else
35
+ :hold
36
+ end
37
+ rescue => e
38
+ warn "MyStrategy error: #{e.message}"
39
+ :hold
40
+ end
41
+ end
42
+ ```
43
+
44
+ ## Step-by-Step Guide
45
+
46
+ ### 1. Create Strategy File
47
+
48
+ Create a new file in `lib/sqa/strategy/`:
49
+
50
+ ```bash
51
+ touch lib/sqa/strategy/my_strategy.rb
52
+ ```
53
+
54
+ ### 2. Define Strategy Class
55
+
56
+ ```ruby
57
+ class SQA::Strategy::MyStrategy
58
+ # Your implementation
59
+ end
60
+ ```
61
+
62
+ ### 3. Implement Trade Method
63
+
64
+ ```ruby
65
+ def self.trade(vector)
66
+ # Return :buy, :sell, or :hold
67
+ end
68
+ ```
69
+
70
+ ### 4. Add Error Handling
71
+
72
+ ```ruby
73
+ def self.trade(vector)
74
+ # Your logic
75
+ rescue => e
76
+ warn "Error: #{e.message}"
77
+ :hold # Safe default
78
+ end
79
+ ```
80
+
81
+ ### 5. Write Tests
82
+
83
+ Create `test/strategy/my_strategy_test.rb`:
84
+
85
+ ```ruby
86
+ require_relative '../test_helper'
87
+ require 'ostruct'
88
+
89
+ class MyStrategyTest < Minitest::Test
90
+ def test_buy_signal
91
+ prices = [100, 102, 104, 106, 108]
92
+ vector = OpenStruct.new(prices: prices)
93
+
94
+ signal = SQA::Strategy::MyStrategy.trade(vector)
95
+ assert_equal :buy, signal
96
+ end
97
+
98
+ def test_hold_when_no_data
99
+ vector = OpenStruct.new
100
+ signal = SQA::Strategy::MyStrategy.trade(vector)
101
+ assert_equal :hold, signal
102
+ end
103
+ end
104
+ ```
105
+
106
+ ## Advanced Example
107
+
108
+ ```ruby
109
+ class SQA::Strategy::AdvancedStrategy
110
+ # Constants for configuration
111
+ RSI_OVERSOLD = 30
112
+ RSI_OVERBOUGHT = 70
113
+ MIN_VOLUME_RATIO = 1.5
114
+
115
+ def self.trade(vector)
116
+ return :hold unless valid_vector?(vector)
117
+
118
+ analysis = analyze_market(vector)
119
+ generate_signal(analysis)
120
+ end
121
+
122
+ private
123
+
124
+ def self.valid_vector?(vector)
125
+ vector.respond_to?(:prices) &&
126
+ vector.respond_to?(:volumes) &&
127
+ vector.prices&.size >= 50
128
+ end
129
+
130
+ def self.analyze_market(vector)
131
+ {
132
+ rsi: SQAI.rsi(vector.prices, period: 14).last,
133
+ trend: detect_trend(vector.prices),
134
+ volume_spike: volume_spike?(vector.volumes)
135
+ }
136
+ end
137
+
138
+ def self.detect_trend(prices)
139
+ sma_short = SQAI.sma(prices, period: 20).last
140
+ sma_long = SQAI.sma(prices, period: 50).last
141
+
142
+ sma_short > sma_long ? :up : :down
143
+ end
144
+
145
+ def self.volume_spike?(volumes)
146
+ current = volumes.last
147
+ average = volumes.last(20).sum / 20.0
148
+ current > (average * MIN_VOLUME_RATIO)
149
+ end
150
+
151
+ def self.generate_signal(analysis)
152
+ if analysis[:rsi] < RSI_OVERSOLD &&
153
+ analysis[:trend] == :up &&
154
+ analysis[:volume_spike]
155
+ :buy
156
+ elsif analysis[:rsi] > RSI_OVERBOUGHT &&
157
+ analysis[:trend] == :down &&
158
+ analysis[:volume_spike]
159
+ :sell
160
+ else
161
+ :hold
162
+ end
163
+ end
164
+ end
165
+ ```
166
+
167
+ ## Best Practices
168
+
169
+ ### 1. Validate Input
170
+
171
+ ```ruby
172
+ return :hold unless vector.respond_to?(:prices)
173
+ return :hold if vector.prices.nil?
174
+ return :hold if vector.prices.size < minimum_required
175
+ ```
176
+
177
+ ### 2. Use Available Indicators
178
+
179
+ ```ruby
180
+ # All TA-Lib indicators available via SQAI
181
+ rsi = SQAI.rsi(prices, period: 14)
182
+ macd = SQAI.macd(prices)
183
+ bbands = SQAI.bbands(prices, period: 20)
184
+ ```
185
+
186
+ ### 3. Handle Errors Gracefully
187
+
188
+ ```ruby
189
+ rescue => e
190
+ warn "#{self.name} error: #{e.message}"
191
+ :hold
192
+ end
193
+ ```
194
+
195
+ ### 4. Test Edge Cases
196
+
197
+ - Empty data
198
+ - Insufficient data
199
+ - Nil values
200
+ - Extreme values
201
+
202
+ ### 5. Document Your Logic
203
+
204
+ ```ruby
205
+ # Buy when:
206
+ # 1. RSI indicates oversold (< 30)
207
+ # 2. Price above 20-day SMA (uptrend)
208
+ # 3. Volume confirms (> 1.5x average)
209
+ ```
210
+
211
+ ## Using Your Strategy
212
+
213
+ ### With Backtest
214
+
215
+ ```ruby
216
+ backtest = SQA::Backtest.new(
217
+ stock: stock,
218
+ strategy: SQA::Strategy::MyStrategy,
219
+ initial_cash: 10_000
220
+ )
221
+
222
+ results = backtest.run
223
+ ```
224
+
225
+ ### With Real-Time Stream
226
+
227
+ ```ruby
228
+ stream = SQA::Stream.new(
229
+ ticker: 'AAPL',
230
+ strategies: [SQA::Strategy::MyStrategy]
231
+ )
232
+
233
+ stream.on_signal do |signal, data|
234
+ puts "MyStrategy says: #{signal}"
235
+ end
236
+ ```
237
+
238
+ ### With Strategy Generator
239
+
240
+ ```ruby
241
+ # Discover patterns and auto-generate strategies
242
+ generator = SQA::StrategyGenerator.new(stock: stock)
243
+ patterns = generator.discover_patterns
244
+ strategy_code = generator.generate_strategy(pattern_index: 0)
245
+ ```
246
+
247
+ ## Common Patterns
248
+
249
+ ### Trend Following
250
+
251
+ ```ruby
252
+ if short_ma > long_ma
253
+ :buy
254
+ elsif short_ma < long_ma
255
+ :sell
256
+ else
257
+ :hold
258
+ end
259
+ ```
260
+
261
+ ### Mean Reversion
262
+
263
+ ```ruby
264
+ deviation = (price - average) / average
265
+ if deviation < -threshold
266
+ :buy
267
+ elsif deviation > threshold
268
+ :sell
269
+ else
270
+ :hold
271
+ end
272
+ ```
273
+
274
+ ### Momentum
275
+
276
+ ```ruby
277
+ if rsi < oversold_level
278
+ :buy
279
+ elsif rsi > overbought_level
280
+ :sell
281
+ else
282
+ :hold
283
+ end
284
+ ```
285
+
286
+ ### Breakout
287
+
288
+ ```ruby
289
+ if price > recent_high && volume > threshold
290
+ :buy
291
+ elsif price < recent_low && volume > threshold
292
+ :sell
293
+ else
294
+ :hold
295
+ end
296
+ ```
297
+
298
+ ## Next Steps
299
+
300
+ 1. Study existing strategies in `lib/sqa/strategy/`
301
+ 2. Read [Backtesting Guide](../advanced/backtesting.md)
302
+ 3. Explore [Strategy Generator](../advanced/strategy-generator.md)
303
+ 4. Learn about [Risk Management](../advanced/risk-management.md)
304
+
305
+ ## Related
306
+
307
+ - [KBS Strategy](kbs.md) - Rule-based strategies
308
+ - [Consensus](consensus.md) - Combining strategies
309
+ - [Backtesting](../advanced/backtesting.md) - Testing strategies
310
+
@@ -0,0 +1,53 @@
1
+ # EMA (Exponential Moving Average) Strategy
2
+
3
+ ## Overview
4
+
5
+ Similar to SMA but gives more weight to recent prices, making it more responsive to price changes.
6
+
7
+ ## How It Works
8
+
9
+ Uses EMA crossovers for signals:
10
+ - **Short EMA**: 12 or 20-period
11
+ - **Long EMA**: 26 or 50-period
12
+
13
+ ## Trading Signals
14
+
15
+ ### Buy Signal
16
+ Short EMA crosses above long EMA.
17
+
18
+ ### Sell Signal
19
+ Short EMA crosses below long EMA.
20
+
21
+ ## Usage Example
22
+
23
+ ```ruby
24
+ prices = stock.df["adj_close_price"].to_a
25
+
26
+ ema_short = SQAI.ema(prices, period: 12)
27
+ ema_long = SQAI.ema(prices, period: 26)
28
+
29
+ vector = OpenStruct.new(
30
+ ema_short: ema_short,
31
+ ema_long: ema_long
32
+ )
33
+
34
+ signal = SQA::Strategy::EMA.trade(vector)
35
+ ```
36
+
37
+ ## Characteristics
38
+
39
+ - **Complexity**: Low
40
+ - **Best Market**: Trending
41
+ - **Win Rate**: 45-55%
42
+
43
+ ## Strengths
44
+
45
+ ✅ Faster than SMA
46
+ ✅ Better for short-term trading
47
+ ✅ Reduces lag
48
+
49
+ ## Weaknesses
50
+
51
+ ❌ More false signals
52
+ ❌ Still lags in fast markets
53
+
@@ -0,0 +1,92 @@
1
+ # Trading Strategies
2
+
3
+ Explore SQA's comprehensive suite of trading strategies.
4
+
5
+ ## Overview
6
+
7
+ SQA provides 13+ built-in trading strategies, from simple moving average crossovers to advanced rule-based systems. All strategies follow a common interface and can be easily backtested or combined.
8
+
9
+ ## Strategy Categories
10
+
11
+ ### Trend-Following Strategies
12
+ Strategies that identify and follow market trends:
13
+
14
+ - **SMA Strategy** - Simple Moving Average crossovers
15
+ - **EMA Strategy** - Exponential Moving Average crossovers
16
+ - **MACD Strategy** - Moving Average Convergence Divergence
17
+
18
+ ### Momentum Strategies
19
+ Strategies based on price momentum and oscillators:
20
+
21
+ - **RSI Strategy** - Relative Strength Index (oversold/overbought)
22
+ - **Stochastic Strategy** - Stochastic oscillator crossovers
23
+
24
+ ### Volatility Strategies
25
+ Strategies that use volatility measures:
26
+
27
+ - **Bollinger Bands Strategy** - Price touches bands
28
+ - **ATR-based Strategies** - Average True Range volatility
29
+
30
+ ### Volume Strategies
31
+ Strategies incorporating volume analysis:
32
+
33
+ - **Volume Breakout** - High volume price breakouts
34
+
35
+ ### Mean Reversion
36
+ Strategies assuming prices return to average:
37
+
38
+ - **Mean Reversion Strategy** - Statistical mean reversion
39
+
40
+ ### Advanced Strategies
41
+ Complex, rule-based approaches:
42
+
43
+ - **KBS Strategy** - Knowledge-Based System with RETE engine
44
+ - **Consensus Strategy** - Aggregates multiple strategies
45
+
46
+ ## Using Strategies
47
+
48
+ ### Basic Usage
49
+
50
+ ```ruby
51
+ require 'sqa'
52
+ require 'ostruct'
53
+
54
+ # Create data vector
55
+ vector = OpenStruct.new(
56
+ rsi: { trend: :over_sold },
57
+ prices: [100, 102, 105, 103, 107]
58
+ )
59
+
60
+ # Execute strategy
61
+ signal = SQA::Strategy::RSI.trade(vector)
62
+ # => :buy, :sell, or :hold
63
+ ```
64
+
65
+ ### Backtesting
66
+
67
+ ```ruby
68
+ backtest = SQA::Backtest.new(
69
+ stock: stock,
70
+ strategy: SQA::Strategy::MACD,
71
+ initial_cash: 10_000
72
+ )
73
+
74
+ results = backtest.run
75
+ puts "Return: #{results.total_return}%"
76
+ ```
77
+
78
+ ## Strategy Comparison
79
+
80
+ | Strategy | Complexity | Best For | Typical Win Rate |
81
+ |----------|------------|----------|------------------|
82
+ | SMA | Low | Trending markets | 45-55% |
83
+ | RSI | Low | Range-bound markets | 50-60% |
84
+ | MACD | Medium | Trending markets | 45-55% |
85
+ | Bollinger Bands | Medium | Volatile markets | 50-60% |
86
+ | KBS | High | Complex rules | Varies |
87
+
88
+ ## Next Steps
89
+
90
+ - [Built-in Strategies](bollinger-bands.md) - Explore each strategy in detail
91
+ - [Custom Strategies](custom.md) - Create your own strategies
92
+ - [Backtesting](../advanced/backtesting.md) - Test strategies historically
@@ -0,0 +1,164 @@
1
+ # KBS (Knowledge-Based Strategy)
2
+
3
+ ## Overview
4
+
5
+ Advanced rule-based trading system using RETE forward-chaining inference engine. Combines multiple indicators with custom logic rules.
6
+
7
+ ## How It Works
8
+
9
+ Defines trading rules with conditions and actions:
10
+ - **Conditions** (`on`): Facts that must be true
11
+ - **Actions** (`perform`): What to do when conditions met
12
+
13
+ ## Rule Definition
14
+
15
+ ```ruby
16
+ strategy = SQA::Strategy::KBS.new(load_defaults: true)
17
+ kb = strategy.kb
18
+
19
+ # Add custom rule
20
+ strategy.add_rule :buy_oversold_uptrend do
21
+ on :rsi, { level: :oversold }
22
+ on :trend, { short_term: :up }
23
+ perform do
24
+ kb.assert(:signal, { action: :buy, confidence: :high })
25
+ end
26
+ end
27
+ ```
28
+
29
+ ## Default Rules
30
+
31
+ The KBS strategy includes 10 default rules:
32
+ 1. Buy on RSI oversold in uptrend
33
+ 2. Sell on RSI overbought in downtrend
34
+ 3. Buy on bullish MACD crossover
35
+ 4. Sell on bearish MACD crossover
36
+ 5. Buy at lower Bollinger Band
37
+ 6. Sell at upper Bollinger Band
38
+ 7. Buy on stochastic oversold crossover
39
+ 8. Sell on stochastic overbought crossover
40
+ 9. Buy on SMA golden cross
41
+ 10. Sell on SMA death cross
42
+
43
+ ## Usage Example
44
+
45
+ ```ruby
46
+ # Use with default rules
47
+ strategy = SQA::Strategy::KBS.new(load_defaults: true)
48
+
49
+ # Provide market data
50
+ prices = stock.df["adj_close_price"].to_a
51
+ vector = OpenStruct.new(
52
+ rsi: SQAI.rsi(prices, period: 14),
53
+ prices: prices
54
+ )
55
+
56
+ signal = strategy.execute(vector)
57
+ ```
58
+
59
+ ## Advanced Example
60
+
61
+ ```ruby
62
+ # Create custom strategy without defaults
63
+ strategy = SQA::Strategy::KBS.new(load_defaults: false)
64
+ kb = strategy.kb
65
+
66
+ # Define sophisticated multi-condition rule
67
+ strategy.add_rule :strong_buy do
68
+ on :rsi, { level: :oversold }
69
+ on :macd, { crossover: :bullish }
70
+ on :volume, { level: :high }
71
+ without :position # Don't buy if already holding
72
+
73
+ perform do
74
+ kb.assert(:signal, {
75
+ action: :buy,
76
+ confidence: :high,
77
+ reason: :triple_confirmation
78
+ })
79
+ end
80
+ end
81
+
82
+ # Execute
83
+ signal = strategy.execute(vector)
84
+ ```
85
+
86
+ ## Confidence Levels
87
+
88
+ Signals include confidence scoring:
89
+ - **High**: 1.0
90
+ - **Medium**: 0.6
91
+ - **Low**: 0.3
92
+
93
+ Multiple rules can fire, with aggregate confidence determining final signal.
94
+
95
+ ## Characteristics
96
+
97
+ - **Complexity**: High
98
+ - **Best Market**: All markets (depends on rules)
99
+ - **Win Rate**: Varies (50-70% with good rules)
100
+
101
+ ## Strengths
102
+
103
+ ✅ Highly customizable
104
+ ✅ Combines multiple indicators
105
+ ✅ Confidence scoring
106
+ ✅ Forward-chaining inference
107
+ ✅ Can encode expert knowledge
108
+
109
+ ## Weaknesses
110
+
111
+ ❌ Complex to configure
112
+ ❌ Requires domain knowledge
113
+ ❌ Can be slow with many rules
114
+ ❌ Overfitting risk
115
+
116
+ ## Tips
117
+
118
+ 1. **Start Simple**: Begin with 2-3 rules
119
+ 2. **Test Thoroughly**: Backtest each rule independently
120
+ 3. **Avoid Conflicts**: Ensure rules don't contradict
121
+ 4. **Use Confidence**: Combine weak signals for stronger conviction
122
+ 5. **Monitor Performance**: Track which rules fire most often
123
+
124
+ ## Available Facts
125
+
126
+ The KBS strategy processes these fact types:
127
+ - `:rsi` - RSI indicator data
128
+ - `:macd` - MACD crossovers
129
+ - `:trend` - Price trend analysis
130
+ - `:bollinger` - Bollinger Band position
131
+ - `:stochastic` - Stochastic oscillator
132
+ - `:volume` - Volume analysis
133
+ - `:sma_crossover` - SMA crossovers
134
+
135
+ ## DSL Keywords
136
+
137
+ - `on` - Assert condition (fact must exist with attributes)
138
+ - `without` - Negated condition (fact must NOT exist)
139
+ - `perform` - Action to execute when rule fires
140
+
141
+ ## Important Note
142
+
143
+ Due to KBS gem DSL limitations, you must use `kb.assert` (not just `assert`) inside `perform` blocks:
144
+
145
+ ```ruby
146
+ # CORRECT
147
+ kb = strategy.kb
148
+ strategy.add_rule :my_rule do
149
+ on :condition
150
+ perform { kb.assert(:signal, { action: :buy }) }
151
+ end
152
+
153
+ # INCORRECT
154
+ strategy.add_rule :my_rule do
155
+ on :condition
156
+ perform { assert(:signal, { action: :buy }) } # Won't work!
157
+ end
158
+ ```
159
+
160
+ ## Related
161
+
162
+ - [Strategy Generator](../advanced/strategy-generator.md) - Auto-generate rules
163
+ - [Genetic Programming](../genetic_programming.md) - Optimize rule parameters
164
+
@@ -0,0 +1,96 @@
1
+ # MACD Strategy
2
+
3
+ ## Overview
4
+
5
+ Moving Average Convergence Divergence (MACD) is a trend-following momentum indicator that shows the relationship between two moving averages.
6
+
7
+ ## How It Works
8
+
9
+ MACD consists of three components:
10
+ - **MACD Line**: 12-period EMA - 26-period EMA
11
+ - **Signal Line**: 9-period EMA of MACD Line
12
+ - **Histogram**: MACD Line - Signal Line
13
+
14
+ ## Trading Signals
15
+
16
+ ### Buy Signal (Bullish Crossover)
17
+ MACD line crosses **above** the signal line.
18
+
19
+ ```ruby
20
+ SQA::Strategy::MACD.trade(vector) # => :buy
21
+ ```
22
+
23
+ ### Sell Signal (Bearish Crossover)
24
+ MACD line crosses **below** the signal line.
25
+
26
+ ```ruby
27
+ SQA::Strategy::MACD.trade(vector) # => :sell
28
+ ```
29
+
30
+ ## Usage Example
31
+
32
+ ```ruby
33
+ stock = SQA::Stock.new(ticker: 'AAPL')
34
+ prices = stock.df["adj_close_price"].to_a
35
+
36
+ # Calculate MACD
37
+ macd_line, signal_line, histogram = SQAI.macd(
38
+ prices,
39
+ fast_period: 12,
40
+ slow_period: 26,
41
+ signal_period: 9
42
+ )
43
+
44
+ vector = OpenStruct.new(
45
+ macd: [macd_line, signal_line, histogram]
46
+ )
47
+
48
+ signal = SQA::Strategy::MACD.trade(vector)
49
+ ```
50
+
51
+ ## Parameters
52
+
53
+ | Parameter | Default | Description |
54
+ |-----------|---------|-------------|
55
+ | Fast Period | 12 | Fast EMA period |
56
+ | Slow Period | 26 | Slow EMA period |
57
+ | Signal Period | 9 | Signal line EMA period |
58
+
59
+ ## Characteristics
60
+
61
+ | Attribute | Value |
62
+ |-----------|-------|
63
+ | Complexity | Medium |
64
+ | Best Market | Trending |
65
+ | Win Rate | 45-55% |
66
+ | Time Horizon | Medium to long term |
67
+
68
+ ## Strengths
69
+
70
+ - ✅ Excellent trend following
71
+ - ✅ Combines trend and momentum
72
+ - ✅ Clear crossover signals
73
+ - ✅ Can detect trend changes early
74
+
75
+ ## Weaknesses
76
+
77
+ - ❌ Lags in fast markets
78
+ - ❌ Whipsaws in ranging markets
79
+ - ❌ False signals during consolidation
80
+
81
+ ## Tips
82
+
83
+ 1. **Confirm with Trend**: Best in established trends
84
+ 2. **Histogram Divergence**: Watch for divergence with price
85
+ 3. **Zero Line Cross**: Additional confirmation signal
86
+ 4. **Multiple Timeframes**: Align daily and weekly signals
87
+
88
+ ## Related Strategies
89
+
90
+ - [EMA](ema.md) - Uses moving average crossovers
91
+ - [SMA](sma.md) - Similar crossover approach
92
+ - [RSI](rsi.md) - Complementary momentum indicator
93
+
94
+ ## Further Reading
95
+
96
+ - [MACD on Investopedia](https://www.investopedia.com/terms/m/macd.asp)