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,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'boot'
4
+
5
+ require 'rails'
6
+ require 'active_model/railtie'
7
+ require 'active_job/railtie'
8
+ require 'active_record/railtie'
9
+ require 'action_controller/railtie'
10
+ require 'action_view/railtie'
11
+ require 'action_cable/railtie'
12
+ require 'rails/test_unit/railtie'
13
+
14
+ # Require the gems listed in Gemfile
15
+ Bundler.require(*Rails.groups)
16
+
17
+ module SqaRailsApp
18
+ class Application < Rails::Application
19
+ # Initialize configuration defaults for Rails 7.1
20
+ config.load_defaults 7.1
21
+
22
+ # Configuration for the application, engines, and railties
23
+ config.autoload_lib(ignore: %w(assets tasks))
24
+
25
+ # Add SQA library to load path
26
+ lib_path = File.expand_path('../../../lib', __dir__)
27
+ $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
28
+
29
+ # API-only mode for API namespace
30
+ config.api_only = false
31
+
32
+ # Enable sessions
33
+ config.session_store :cookie_store, key: '_sqa_rails_session'
34
+
35
+ # Assets
36
+ config.assets.paths << Rails.root.join('app', 'assets', 'stylesheets')
37
+ config.assets.paths << Rails.root.join('app', 'assets', 'javascripts')
38
+
39
+ # Time zone
40
+ config.time_zone = 'UTC'
41
+
42
+ # Eager load in production
43
+ config.eager_load = Rails.env.production?
44
+ end
45
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
4
+
5
+ require 'bundler/setup' # Set up gems listed in the Gemfile.
@@ -0,0 +1,18 @@
1
+ # SQLite3 database configuration
2
+
3
+ default: &default
4
+ adapter: sqlite3
5
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
6
+ timeout: 5000
7
+
8
+ development:
9
+ <<: *default
10
+ database: db/development.sqlite3
11
+
12
+ test:
13
+ <<: *default
14
+ database: db/test.sqlite3
15
+
16
+ production:
17
+ <<: *default
18
+ database: db/production.sqlite3
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Load the Rails application
4
+ require_relative 'application'
5
+
6
+ # Initialize SQA
7
+ require 'sqa'
8
+ SQA.init
9
+
10
+ # Initialize the Rails application
11
+ Rails.application.initialize!
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.routes.draw do
4
+ # Root route
5
+ root 'dashboard#index'
6
+
7
+ # Dashboard routes
8
+ get 'dashboard/:ticker', to: 'dashboard#show', as: :stock_dashboard
9
+ get 'analyze/:ticker', to: 'analysis#show', as: :stock_analysis
10
+ get 'backtest/:ticker', to: 'backtest#show', as: :stock_backtest
11
+ get 'portfolio', to: 'portfolio#index', as: :portfolio
12
+
13
+ # API routes
14
+ namespace :api do
15
+ namespace :v1 do
16
+ get 'stock/:ticker', to: 'stocks#show'
17
+ get 'indicators/:ticker', to: 'stocks#indicators'
18
+ post 'backtest/:ticker', to: 'stocks#backtest'
19
+ get 'analyze/:ticker', to: 'stocks#analyze'
20
+ post 'compare/:ticker', to: 'stocks#compare'
21
+ end
22
+ end
23
+
24
+ # Health check
25
+ get 'up', to: 'rails/health#show', as: :rails_health_check
26
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is used by Rack-based servers to start the application.
4
+
5
+ require_relative 'config/environment'
6
+
7
+ run Rails.application
8
+ Rails.application.load_server
@@ -0,0 +1,274 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Real-Time Stock Price Streaming
5
+ #
6
+ # This example shows how to use SQA::Stream to process live stock
7
+ # price updates and generate trading signals in real-time.
8
+
9
+ require 'sqa'
10
+
11
+ SQA.init
12
+
13
+ puts "=" * 60
14
+ puts "Real-Time Stock Price Streaming Example"
15
+ puts "=" * 60
16
+ puts
17
+
18
+ # Example 1: Basic Streaming with Single Strategy
19
+ puts "\n" + "=" * 60
20
+ puts "Example 1: Basic Streaming Setup"
21
+ puts "=" * 60
22
+ puts
23
+
24
+ stream = SQA::Stream.new(
25
+ ticker: 'AAPL',
26
+ window_size: 100,
27
+ strategies: [SQA::Strategy::RSI]
28
+ )
29
+
30
+ puts "Stream initialized:"
31
+ puts " Ticker: #{stream.ticker}"
32
+ puts " Window Size: #{stream.window_size}"
33
+ puts " Strategies: #{stream.strategies.size}"
34
+ puts
35
+
36
+ # Add signal callback
37
+ stream.on_signal do |signal, data|
38
+ puts "🔔 SIGNAL: #{signal.upcase}"
39
+ puts " Price: $#{data[:price].round(2)}"
40
+ puts " Time: #{data[:timestamp]}"
41
+ puts " Strategy Votes: #{data[:strategies_vote]}"
42
+ puts
43
+ end
44
+
45
+ # Add update callback (optional - for monitoring)
46
+ update_count = 0
47
+ stream.on_update do |data|
48
+ update_count += 1
49
+ if update_count % 10 == 0
50
+ puts "📊 Update ##{update_count}: Price=$#{data[:price].round(2)}"
51
+ end
52
+ end
53
+
54
+ puts "Callbacks registered. Simulating price updates..."
55
+ puts "-" * 60
56
+
57
+ # Simulate real-time price updates
58
+ # In production, these would come from a WebSocket or API
59
+ stock = SQA::Stock.new(ticker: 'AAPL')
60
+ prices = stock.df["adj_close_price"].to_a
61
+ volumes = stock.df["volume"].to_a
62
+ highs = stock.df["high_price"].to_a
63
+ lows = stock.df["low_price"].to_a
64
+
65
+ # Stream the last 150 data points as if they were real-time
66
+ prices.last(150).each_with_index do |price, i|
67
+ stream.update(
68
+ price: price,
69
+ volume: volumes.last(150)[i],
70
+ high: highs.last(150)[i],
71
+ low: lows.last(150)[i],
72
+ timestamp: Time.now - (150 - i) * 60 # 1-minute intervals
73
+ )
74
+
75
+ # Simulate delay (in production, this happens naturally)
76
+ # sleep(0.01) # Uncomment for slower demo
77
+ end
78
+
79
+ puts "-" * 60
80
+ puts "Streaming complete. Final statistics:"
81
+ stats = stream.stats
82
+ puts " Total Updates: #{stats[:updates]}"
83
+ puts " Current Price: $#{stats[:current_price].round(2)}"
84
+ puts " Price Range: $#{stats[:price_range][:min].round(2)} - $#{stats[:price_range][:max].round(2)}"
85
+ puts " Last Signal: #{stats[:last_signal].upcase}"
86
+ puts
87
+
88
+ # Example 2: Multi-Strategy Streaming
89
+ puts "\n" + "=" * 60
90
+ puts "Example 2: Multi-Strategy Consensus"
91
+ puts "=" * 60
92
+ puts
93
+
94
+ multi_stream = SQA::Stream.new(
95
+ ticker: 'MSFT',
96
+ window_size: 100,
97
+ strategies: [
98
+ SQA::Strategy::RSI,
99
+ SQA::Strategy::MACD,
100
+ SQA::Strategy::BollingerBands,
101
+ SQA::Strategy::Stochastic
102
+ ]
103
+ )
104
+
105
+ puts "Multi-strategy stream configured with:"
106
+ multi_stream.strategies.each_with_index do |strategy, i|
107
+ puts " #{i + 1}. #{strategy}"
108
+ end
109
+ puts
110
+
111
+ signal_log = []
112
+
113
+ multi_stream.on_signal do |signal, data|
114
+ signal_log << { signal: signal, price: data[:price], votes: data[:strategies_vote] }
115
+ puts "🎯 CONSENSUS SIGNAL: #{signal.upcase}"
116
+ puts " Price: $#{data[:price].round(2)}"
117
+ puts " Strategy Votes: #{data[:strategies_vote]}"
118
+ puts " Time: #{data[:timestamp].strftime('%Y-%m-%d %H:%M:%S')}"
119
+ puts
120
+ end
121
+
122
+ puts "Simulating market data stream..."
123
+ puts "-" * 60
124
+
125
+ # Simulate streaming
126
+ stock2 = SQA::Stock.new(ticker: 'MSFT')
127
+ prices2 = stock2.df["adj_close_price"].to_a
128
+ volumes2 = stock2.df["volume"].to_a
129
+
130
+ prices2.last(100).each_with_index do |price, i|
131
+ multi_stream.update(
132
+ price: price,
133
+ volume: volumes2.last(100)[i],
134
+ timestamp: Time.now - (100 - i) * 60
135
+ )
136
+ end
137
+
138
+ puts "-" * 60
139
+ puts "Multi-strategy streaming complete."
140
+ puts "Signal summary:"
141
+ signal_log.each_with_index do |log, i|
142
+ puts " #{i + 1}. #{log[:signal].to_s.upcase} at $#{log[:price].round(2)} (votes: #{log[:votes]})"
143
+ end
144
+ puts
145
+
146
+ # Example 3: Custom Indicator Access
147
+ puts "\n" + "=" * 60
148
+ puts "Example 3: Accessing Real-Time Indicators"
149
+ puts "=" * 60
150
+ puts
151
+
152
+ indicator_stream = SQA::Stream.new(
153
+ ticker: 'GOOGL',
154
+ window_size: 50
155
+ )
156
+
157
+ # Stream some data first
158
+ stock3 = SQA::Stock.new(ticker: 'GOOGL')
159
+ stock3.df["adj_close_price"].to_a.last(50).each do |price|
160
+ indicator_stream.update(price: price)
161
+ end
162
+
163
+ puts "Current market data:"
164
+ puts " Current Price: $#{indicator_stream.current_price.round(2)}"
165
+ puts " Recent Prices (last 5): #{indicator_stream.recent_prices(5).map { |p| p.round(2) }}"
166
+ puts
167
+
168
+ puts "Real-time indicators:"
169
+ rsi = indicator_stream.indicator(:rsi, period: 14)
170
+ sma_20 = indicator_stream.indicator(:sma, period: 20)
171
+ ema_12 = indicator_stream.indicator(:ema, period: 12)
172
+ macd_data = indicator_stream.indicator(:macd)
173
+
174
+ puts " RSI(14): #{rsi.last.round(2)}"
175
+ puts " SMA(20): $#{sma_20.last.round(2)}"
176
+ puts " EMA(12): $#{ema_12.last.round(2)}"
177
+ puts " MACD: #{macd_data[0].last.round(4)}"
178
+ puts " Signal: #{macd_data[1].last.round(4)}"
179
+ puts
180
+
181
+ # Example 4: Production-Style WebSocket Simulation
182
+ puts "\n" + "=" * 60
183
+ puts "Example 4: Production WebSocket Pattern"
184
+ puts "=" * 60
185
+ puts
186
+
187
+ class MockWebSocket
188
+ def initialize(ticker)
189
+ @ticker = ticker
190
+ @stock = SQA::Stock.new(ticker: ticker)
191
+ @prices = @stock.df["adj_close_price"].to_a
192
+ @index = @prices.size - 100
193
+ end
194
+
195
+ def on_message(&block)
196
+ @message_handler = block
197
+ end
198
+
199
+ def start
200
+ puts "📡 WebSocket connected to #{@ticker} market data feed"
201
+ puts " Streaming live prices..."
202
+ puts
203
+
204
+ # Simulate receiving messages
205
+ (@index...@prices.size).each do |i|
206
+ # Simulate WebSocket message
207
+ message = {
208
+ symbol: @ticker,
209
+ price: @prices[i],
210
+ volume: rand(1_000_000..10_000_000),
211
+ timestamp: Time.now
212
+ }
213
+
214
+ @message_handler.call(message) if @message_handler
215
+
216
+ # sleep(0.1) # Uncomment for slower demo
217
+ end
218
+
219
+ puts " WebSocket closed"
220
+ end
221
+ end
222
+
223
+ # Initialize stream for production pattern
224
+ production_stream = SQA::Stream.new(
225
+ ticker: 'TSLA',
226
+ window_size: 100,
227
+ strategies: [
228
+ SQA::Strategy::RSI,
229
+ SQA::Strategy::MACD,
230
+ SQA::Strategy::BollingerBands
231
+ ]
232
+ )
233
+
234
+ # Set up signal handling
235
+ production_stream.on_signal do |signal, data|
236
+ # In production, this would trigger:
237
+ # - Alert notifications
238
+ # - Automated trading execution
239
+ # - Logging to database
240
+ # - Risk management checks
241
+
242
+ puts "⚡ TRADING SIGNAL: #{signal.upcase}"
243
+ puts " Execute #{signal} order for #{data[:price]}"
244
+ puts " Consensus: #{data[:strategies_vote]}"
245
+ puts
246
+ end
247
+
248
+ # Set up WebSocket (mock)
249
+ ws = MockWebSocket.new('TSLA')
250
+
251
+ ws.on_message do |message|
252
+ # Feed WebSocket data into stream processor
253
+ production_stream.update(
254
+ price: message[:price],
255
+ volume: message[:volume],
256
+ timestamp: message[:timestamp]
257
+ )
258
+ end
259
+
260
+ # Start streaming
261
+ ws.start
262
+
263
+ puts "-" * 60
264
+ puts "Production simulation complete."
265
+ puts
266
+
267
+ puts "All streaming examples complete!"
268
+ puts
269
+ puts "In production, connect to real WebSocket feeds from:"
270
+ puts " - Alpha Vantage WebSocket API"
271
+ puts " - Yahoo Finance Streaming"
272
+ puts " - Interactive Brokers TWS API"
273
+ puts " - Polygon.io WebSocket"
274
+ puts " - Alpaca Markets WebSocket"
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ ruby '>= 3.2.0'
6
+
7
+ # Web framework
8
+ gem 'sinatra', '~> 4.0'
9
+ gem 'sinatra-contrib', '~> 4.0'
10
+ gem 'puma', '~> 6.0'
11
+
12
+ # JSON handling
13
+ gem 'json', '~> 2.7'
14
+
15
+ # SQA library (assumes it's in parent directory)
16
+ # In production, this would be:
17
+ # gem 'sqa'
18
+ # For development, we'll load from local path via require in app.rb
19
+
20
+ group :development do
21
+ gem 'rerun' # Auto-reload on file changes
22
+ end
@@ -0,0 +1,159 @@
1
+ # SQA Web App - Quick Start Guide
2
+
3
+ Get the SQA web application running in 5 minutes.
4
+
5
+ ## 1. Prerequisites
6
+
7
+ ```bash
8
+ # Install TA-Lib (macOS)
9
+ brew install ta-lib
10
+
11
+ # Start Redis
12
+ redis-server
13
+
14
+ # Set API key (optional, uses Yahoo Finance as fallback)
15
+ export AV_API_KEY="your_key_here"
16
+ ```
17
+
18
+ ## 2. Install Dependencies
19
+
20
+ ```bash
21
+ cd examples/sinatra_app
22
+ bundle install
23
+ ```
24
+
25
+ ## 3. Start the Application
26
+
27
+ ```bash
28
+ ruby app.rb
29
+ ```
30
+
31
+ The app will start on http://localhost:4567
32
+
33
+ ## 4. Quick Tour
34
+
35
+ ### Home Page
36
+ - Click on any quick link ticker (AAPL, MSFT, etc.)
37
+ - Or enter a custom ticker in the search box
38
+
39
+ ### Dashboard
40
+ - View interactive price charts (candlestick or line)
41
+ - See volume chart
42
+ - Check RSI and MACD indicators
43
+ - View key metrics (52-week high/low, current RSI, market regime)
44
+ - Compare all strategies at once
45
+
46
+ ### Analysis Page
47
+ - Market regime detection (bull/bear/sideways)
48
+ - Seasonal patterns (best months and quarters)
49
+ - FPOP (Future Period) analysis
50
+ - Risk metrics (VaR, Sharpe ratio, max drawdown)
51
+
52
+ ### Backtest Page
53
+ - Select a strategy (RSI, MACD, SMA, EMA, Bollinger Bands, KBS)
54
+ - View detailed backtest results
55
+ - Compare all strategies side-by-side
56
+
57
+ ## 5. Keyboard Shortcuts
58
+
59
+ - `Ctrl/Cmd + K` - Open ticker search
60
+ - `Escape` - Close modal
61
+
62
+ ## 6. API Examples
63
+
64
+ ### Get Stock Data
65
+ ```bash
66
+ curl http://localhost:4567/api/stock/AAPL
67
+ ```
68
+
69
+ ### Get Technical Indicators
70
+ ```bash
71
+ curl http://localhost:4567/api/indicators/AAPL
72
+ ```
73
+
74
+ ### Run Backtest
75
+ ```bash
76
+ curl -X POST http://localhost:4567/api/backtest/AAPL \
77
+ -d "strategy=RSI"
78
+ ```
79
+
80
+ ### Get Market Analysis
81
+ ```bash
82
+ curl http://localhost:4567/api/analyze/AAPL
83
+ ```
84
+
85
+ ### Compare Strategies
86
+ ```bash
87
+ curl -X POST http://localhost:4567/api/compare/AAPL
88
+ ```
89
+
90
+ ## 7. Development Mode
91
+
92
+ Auto-reload on file changes:
93
+
94
+ ```bash
95
+ gem install rerun
96
+ rerun 'ruby app.rb'
97
+ ```
98
+
99
+ ## 8. Troubleshooting
100
+
101
+ **Port already in use:**
102
+ ```bash
103
+ # Kill process on port 4567
104
+ lsof -ti:4567 | xargs kill -9
105
+ ```
106
+
107
+ **TA-Lib not found:**
108
+ ```bash
109
+ # Reinstall TA-Lib
110
+ brew reinstall ta-lib
111
+ ```
112
+
113
+ **Redis connection error:**
114
+ ```bash
115
+ # Start Redis
116
+ redis-server &
117
+ ```
118
+
119
+ **Stock data not loading:**
120
+ - Check internet connection
121
+ - Verify ticker symbol is valid
122
+ - Try a different ticker (e.g., AAPL, MSFT, GOOGL)
123
+
124
+ ## 9. Popular Tickers
125
+
126
+ Try these popular stocks:
127
+
128
+ **Tech:**
129
+ - AAPL (Apple)
130
+ - MSFT (Microsoft)
131
+ - GOOGL (Google)
132
+ - AMZN (Amazon)
133
+ - NVDA (NVIDIA)
134
+ - TSLA (Tesla)
135
+
136
+ **Finance:**
137
+ - JPM (JP Morgan)
138
+ - BAC (Bank of America)
139
+ - GS (Goldman Sachs)
140
+
141
+ **ETFs:**
142
+ - SPY (S&P 500)
143
+ - QQQ (NASDAQ 100)
144
+ - DIA (Dow Jones)
145
+
146
+ ## 10. Next Steps
147
+
148
+ - Explore different strategies on the Backtest page
149
+ - Compare seasonal patterns across multiple stocks
150
+ - Check market regime before making trade decisions
151
+ - Use FPOP analysis to identify high-probability setups
152
+
153
+ ## Support
154
+
155
+ See README.md for full documentation and API reference.
156
+
157
+ ---
158
+
159
+ Happy analyzing! 📊