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.
- checksums.yaml +4 -4
- data/.goose/memory/development.txt +3 -0
- data/.semver +6 -0
- data/ARCHITECTURE.md +648 -0
- data/CHANGELOG.md +82 -0
- data/CLAUDE.md +653 -0
- data/COMMITS.md +196 -0
- data/DATAFRAME_ARCHITECTURE_REVIEW.md +421 -0
- data/NEXT-STEPS.md +154 -0
- data/README.md +812 -262
- data/TASKS.md +358 -0
- data/TEST_RESULTS.md +140 -0
- data/TODO.md +42 -0
- data/_notes.txt +25 -0
- data/bin/sqa-console +11 -0
- data/data/talk_talk.json +103284 -0
- data/develop_summary.md +313 -0
- data/docs/advanced/backtesting.md +206 -0
- data/docs/advanced/ensemble.md +68 -0
- data/docs/advanced/fpop.md +153 -0
- data/docs/advanced/index.md +112 -0
- data/docs/advanced/multi-timeframe.md +67 -0
- data/docs/advanced/pattern-matcher.md +75 -0
- data/docs/advanced/portfolio-optimizer.md +79 -0
- data/docs/advanced/portfolio.md +166 -0
- data/docs/advanced/risk-management.md +210 -0
- data/docs/advanced/strategy-generator.md +158 -0
- data/docs/advanced/streaming.md +209 -0
- data/docs/ai_and_ml.md +80 -0
- data/docs/api/dataframe.md +1115 -0
- data/docs/api/index.md +126 -0
- data/docs/assets/css/custom.css +88 -0
- data/docs/assets/js/mathjax.js +18 -0
- data/docs/concepts/index.md +68 -0
- data/docs/contributing/index.md +60 -0
- data/docs/data-sources/index.md +66 -0
- data/docs/data_frame.md +317 -97
- data/docs/factors_that_impact_price.md +26 -0
- data/docs/finviz.md +11 -0
- data/docs/fx_pro_bit.md +25 -0
- data/docs/genetic_programming.md +104 -0
- data/docs/getting-started/index.md +123 -0
- data/docs/getting-started/installation.md +229 -0
- data/docs/getting-started/quick-start.md +244 -0
- data/docs/i_gotta_an_idea.md +22 -0
- data/docs/index.md +163 -0
- data/docs/indicators/index.md +97 -0
- data/docs/indicators.md +110 -24
- data/docs/options.md +8 -0
- data/docs/strategies/bollinger-bands.md +146 -0
- data/docs/strategies/consensus.md +64 -0
- data/docs/strategies/custom.md +310 -0
- data/docs/strategies/ema.md +53 -0
- data/docs/strategies/index.md +92 -0
- data/docs/strategies/kbs.md +164 -0
- data/docs/strategies/macd.md +96 -0
- data/docs/strategies/market-profile.md +54 -0
- data/docs/strategies/mean-reversion.md +58 -0
- data/docs/strategies/rsi.md +95 -0
- data/docs/strategies/sma.md +55 -0
- data/docs/strategies/stochastic.md +63 -0
- data/docs/strategies/volume-breakout.md +54 -0
- data/docs/tags.md +7 -0
- data/docs/true_strength_index.md +46 -0
- data/docs/weighted_moving_average.md +48 -0
- data/examples/README.md +354 -0
- data/examples/advanced_features_example.rb +350 -0
- data/examples/fpop_analysis_example.rb +191 -0
- data/examples/genetic_programming_example.rb +148 -0
- data/examples/kbs_strategy_example.rb +208 -0
- data/examples/pattern_context_example.rb +300 -0
- data/examples/rails_app/Gemfile +34 -0
- data/examples/rails_app/README.md +416 -0
- data/examples/rails_app/app/assets/javascripts/application.js +107 -0
- data/examples/rails_app/app/assets/stylesheets/application.css +659 -0
- data/examples/rails_app/app/controllers/analysis_controller.rb +11 -0
- data/examples/rails_app/app/controllers/api/v1/stocks_controller.rb +227 -0
- data/examples/rails_app/app/controllers/application_controller.rb +22 -0
- data/examples/rails_app/app/controllers/backtest_controller.rb +11 -0
- data/examples/rails_app/app/controllers/dashboard_controller.rb +21 -0
- data/examples/rails_app/app/controllers/portfolio_controller.rb +7 -0
- data/examples/rails_app/app/views/analysis/show.html.erb +209 -0
- data/examples/rails_app/app/views/backtest/show.html.erb +171 -0
- data/examples/rails_app/app/views/dashboard/index.html.erb +118 -0
- data/examples/rails_app/app/views/dashboard/show.html.erb +408 -0
- data/examples/rails_app/app/views/errors/show.html.erb +17 -0
- data/examples/rails_app/app/views/layouts/application.html.erb +60 -0
- data/examples/rails_app/app/views/portfolio/index.html.erb +33 -0
- data/examples/rails_app/bin/rails +6 -0
- data/examples/rails_app/config/application.rb +45 -0
- data/examples/rails_app/config/boot.rb +5 -0
- data/examples/rails_app/config/database.yml +18 -0
- data/examples/rails_app/config/environment.rb +11 -0
- data/examples/rails_app/config/routes.rb +26 -0
- data/examples/rails_app/config.ru +8 -0
- data/examples/realtime_stream_example.rb +274 -0
- data/examples/sinatra_app/Gemfile +22 -0
- data/examples/sinatra_app/QUICKSTART.md +159 -0
- data/examples/sinatra_app/README.md +461 -0
- data/examples/sinatra_app/app.rb +344 -0
- data/examples/sinatra_app/config.ru +5 -0
- data/examples/sinatra_app/public/css/style.css +659 -0
- data/examples/sinatra_app/public/js/app.js +107 -0
- data/examples/sinatra_app/views/analyze.erb +306 -0
- data/examples/sinatra_app/views/backtest.erb +325 -0
- data/examples/sinatra_app/views/dashboard.erb +419 -0
- data/examples/sinatra_app/views/error.erb +58 -0
- data/examples/sinatra_app/views/index.erb +118 -0
- data/examples/sinatra_app/views/layout.erb +61 -0
- data/examples/sinatra_app/views/portfolio.erb +43 -0
- data/examples/strategy_generator_example.rb +346 -0
- data/hsa_portfolio.csv +11 -0
- data/justfile +0 -0
- data/lib/api/alpha_vantage_api.rb +462 -0
- data/lib/sqa/backtest.rb +329 -0
- data/lib/sqa/data_frame/alpha_vantage.rb +43 -65
- data/lib/sqa/data_frame/data.rb +92 -0
- data/lib/sqa/data_frame/yahoo_finance.rb +35 -43
- data/lib/sqa/data_frame.rb +148 -243
- data/lib/sqa/ensemble.rb +359 -0
- data/lib/sqa/fpop.rb +199 -0
- data/lib/sqa/gp.rb +259 -0
- data/lib/sqa/indicator.rb +5 -8
- data/lib/sqa/init.rb +15 -8
- data/lib/sqa/market_regime.rb +240 -0
- data/lib/sqa/multi_timeframe.rb +379 -0
- data/lib/sqa/pattern_matcher.rb +497 -0
- data/lib/sqa/portfolio.rb +260 -6
- data/lib/sqa/portfolio_optimizer.rb +377 -0
- data/lib/sqa/risk_manager.rb +442 -0
- data/lib/sqa/seasonal_analyzer.rb +209 -0
- data/lib/sqa/sector_analyzer.rb +300 -0
- data/lib/sqa/stock.rb +67 -125
- data/lib/sqa/strategy/bollinger_bands.rb +42 -0
- data/lib/sqa/strategy/consensus.rb +5 -2
- data/lib/sqa/strategy/kbs_strategy.rb +470 -0
- data/lib/sqa/strategy/macd.rb +46 -0
- data/lib/sqa/strategy/mp.rb +1 -1
- data/lib/sqa/strategy/stochastic.rb +60 -0
- data/lib/sqa/strategy/volume_breakout.rb +57 -0
- data/lib/sqa/strategy.rb +5 -0
- data/lib/sqa/strategy_generator.rb +947 -0
- data/lib/sqa/stream.rb +361 -0
- data/lib/sqa/version.rb +1 -7
- data/lib/sqa.rb +23 -16
- data/main.just +81 -0
- data/mkdocs.yml +288 -0
- data/trace.log +0 -0
- metadata +261 -51
- data/bin/sqa +0 -6
- data/lib/patches/dry-cli.rb +0 -228
- data/lib/sqa/activity.rb +0 -10
- data/lib/sqa/cli.rb +0 -62
- data/lib/sqa/commands/analysis.rb +0 -309
- data/lib/sqa/commands/base.rb +0 -139
- data/lib/sqa/commands/web.rb +0 -199
- data/lib/sqa/commands.rb +0 -22
- data/lib/sqa/constants.rb +0 -23
- data/lib/sqa/indicator/average_true_range.rb +0 -33
- data/lib/sqa/indicator/bollinger_bands.rb +0 -28
- data/lib/sqa/indicator/candlestick_pattern_recognizer.rb +0 -60
- data/lib/sqa/indicator/donchian_channel.rb +0 -29
- data/lib/sqa/indicator/double_top_bottom_pattern.rb +0 -34
- data/lib/sqa/indicator/elliott_wave_theory.rb +0 -57
- data/lib/sqa/indicator/exponential_moving_average.rb +0 -25
- data/lib/sqa/indicator/exponential_moving_average_trend.rb +0 -36
- data/lib/sqa/indicator/fibonacci_retracement.rb +0 -23
- data/lib/sqa/indicator/head_and_shoulders_pattern.rb +0 -26
- data/lib/sqa/indicator/market_profile.rb +0 -32
- data/lib/sqa/indicator/mean_reversion.rb +0 -37
- data/lib/sqa/indicator/momentum.rb +0 -28
- data/lib/sqa/indicator/moving_average_convergence_divergence.rb +0 -29
- data/lib/sqa/indicator/peaks_and_valleys.rb +0 -29
- data/lib/sqa/indicator/predict_next_value.rb +0 -202
- data/lib/sqa/indicator/relative_strength_index.rb +0 -47
- data/lib/sqa/indicator/simple_moving_average.rb +0 -24
- data/lib/sqa/indicator/simple_moving_average_trend.rb +0 -32
- data/lib/sqa/indicator/stochastic_oscillator.rb +0 -68
- data/lib/sqa/indicator/true_range.rb +0 -39
- data/lib/sqa/trade.rb +0 -26
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# SQA Rails Application
|
|
2
|
+
|
|
3
|
+
A comprehensive Rails 7.1 web application for stock market technical analysis using the SQA library. Features interactive charts, strategy backtesting, and market analysis with a modern, responsive UI.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### 📊 Interactive Dashboard
|
|
8
|
+
- Candlestick & line charts with Plotly.js
|
|
9
|
+
- Volume analysis with color-coded bars
|
|
10
|
+
- Technical indicators (RSI, MACD, SMA, EMA, Bollinger Bands)
|
|
11
|
+
- Key metrics cards (52-week high/low, RSI, market regime)
|
|
12
|
+
- Real-time price information
|
|
13
|
+
- Strategy comparison
|
|
14
|
+
|
|
15
|
+
### 🤖 Strategy Backtesting
|
|
16
|
+
- 6 built-in strategies (RSI, MACD, SMA, EMA, Bollinger Bands, KBS)
|
|
17
|
+
- Detailed performance metrics
|
|
18
|
+
- Strategy comparison and ranking
|
|
19
|
+
- Visual strategy selection
|
|
20
|
+
- Comprehensive backtest results
|
|
21
|
+
|
|
22
|
+
### 📈 Market Analysis
|
|
23
|
+
- Market regime detection (bull/bear/sideways)
|
|
24
|
+
- Seasonal pattern analysis
|
|
25
|
+
- FPOP (Future Period) analysis
|
|
26
|
+
- Risk metrics (VaR, Sharpe ratio, max drawdown)
|
|
27
|
+
|
|
28
|
+
### 🎨 Modern Rails UI
|
|
29
|
+
- Responsive design
|
|
30
|
+
- MVC architecture
|
|
31
|
+
- RESTful API endpoints
|
|
32
|
+
- Rails 7.1 conventions
|
|
33
|
+
- Turbo & Stimulus ready
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
### Prerequisites
|
|
38
|
+
|
|
39
|
+
- Ruby >= 3.2
|
|
40
|
+
- Rails >= 7.1
|
|
41
|
+
- SQLite3
|
|
42
|
+
- TA-Lib library
|
|
43
|
+
- Redis (for KBS)
|
|
44
|
+
|
|
45
|
+
### Install TA-Lib
|
|
46
|
+
|
|
47
|
+
**macOS:**
|
|
48
|
+
```bash
|
|
49
|
+
brew install ta-lib
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Ubuntu/Debian:**
|
|
53
|
+
```bash
|
|
54
|
+
sudo apt-get install ta-lib-dev
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Install Dependencies
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd examples/rails_app
|
|
61
|
+
bundle install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Database Setup
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
rails db:create
|
|
68
|
+
rails db:migrate
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Set Up API Keys
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
export AV_API_KEY="your_api_key_here"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Get a free API key from [Alpha Vantage](https://www.alphavantage.co/support/#api-key)
|
|
78
|
+
|
|
79
|
+
### Start Redis
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
redis-server
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Usage
|
|
86
|
+
|
|
87
|
+
### Start the Application
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
rails server
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Or using bin/rails:
|
|
94
|
+
```bash
|
|
95
|
+
./bin/rails server
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The application will start on `http://localhost:3000`
|
|
99
|
+
|
|
100
|
+
### Navigate the App
|
|
101
|
+
|
|
102
|
+
1. **Home Page** (`/`) - Landing page with quick links
|
|
103
|
+
2. **Dashboard** (`/dashboard/:ticker`) - Interactive charts and metrics
|
|
104
|
+
3. **Analysis** (`/analyze/:ticker`) - Market analysis and insights
|
|
105
|
+
4. **Backtest** (`/backtest/:ticker`) - Strategy backtesting interface
|
|
106
|
+
5. **Portfolio** (`/portfolio`) - Portfolio optimization (coming soon)
|
|
107
|
+
|
|
108
|
+
## Rails Structure
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
rails_app/
|
|
112
|
+
├── app/
|
|
113
|
+
│ ├── controllers/
|
|
114
|
+
│ │ ├── application_controller.rb
|
|
115
|
+
│ │ ├── dashboard_controller.rb
|
|
116
|
+
│ │ ├── analysis_controller.rb
|
|
117
|
+
│ │ ├── backtest_controller.rb
|
|
118
|
+
│ │ ├── portfolio_controller.rb
|
|
119
|
+
│ │ └── api/
|
|
120
|
+
│ │ └── v1/
|
|
121
|
+
│ │ └── stocks_controller.rb # API endpoints
|
|
122
|
+
│ ├── views/
|
|
123
|
+
│ │ ├── layouts/
|
|
124
|
+
│ │ │ └── application.html.erb # Main layout
|
|
125
|
+
│ │ ├── dashboard/
|
|
126
|
+
│ │ │ ├── index.html.erb # Home page
|
|
127
|
+
│ │ │ └── show.html.erb # Stock dashboard
|
|
128
|
+
│ │ ├── analysis/
|
|
129
|
+
│ │ │ └── show.html.erb # Analysis page
|
|
130
|
+
│ │ ├── backtest/
|
|
131
|
+
│ │ │ └── show.html.erb # Backtest page
|
|
132
|
+
│ │ ├── portfolio/
|
|
133
|
+
│ │ │ └── index.html.erb # Portfolio page
|
|
134
|
+
│ │ └── errors/
|
|
135
|
+
│ │ └── show.html.erb # Error page
|
|
136
|
+
│ └── assets/
|
|
137
|
+
│ ├── stylesheets/
|
|
138
|
+
│ │ └── application.css # Main stylesheet
|
|
139
|
+
│ └── javascripts/
|
|
140
|
+
│ └── application.js # Main JavaScript
|
|
141
|
+
├── config/
|
|
142
|
+
│ ├── application.rb # App configuration
|
|
143
|
+
│ ├── boot.rb # Boot configuration
|
|
144
|
+
│ ├── environment.rb # Environment setup
|
|
145
|
+
│ ├── database.yml # Database config
|
|
146
|
+
│ └── routes.rb # Routes definition
|
|
147
|
+
├── db/ # Database files
|
|
148
|
+
├── public/ # Static files
|
|
149
|
+
├── bin/
|
|
150
|
+
│ └── rails # Rails script
|
|
151
|
+
├── Gemfile # Ruby dependencies
|
|
152
|
+
├── config.ru # Rack config
|
|
153
|
+
└── README.md # This file
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Routes
|
|
157
|
+
|
|
158
|
+
| Route | Method | Controller#Action | Description |
|
|
159
|
+
|-------|--------|-------------------|-------------|
|
|
160
|
+
| `/` | GET | `dashboard#index` | Home page |
|
|
161
|
+
| `/dashboard/:ticker` | GET | `dashboard#show` | Stock dashboard |
|
|
162
|
+
| `/analyze/:ticker` | GET | `analysis#show` | Market analysis |
|
|
163
|
+
| `/backtest/:ticker` | GET | `backtest#show` | Strategy backtesting |
|
|
164
|
+
| `/portfolio` | GET | `portfolio#index` | Portfolio optimization |
|
|
165
|
+
| `/api/v1/stock/:ticker` | GET | `api/v1/stocks#show` | Get stock data |
|
|
166
|
+
| `/api/v1/indicators/:ticker` | GET | `api/v1/stocks#indicators` | Get indicators |
|
|
167
|
+
| `/api/v1/backtest/:ticker` | POST | `api/v1/stocks#backtest` | Run backtest |
|
|
168
|
+
| `/api/v1/analyze/:ticker` | GET | `api/v1/stocks#analyze` | Get analysis |
|
|
169
|
+
| `/api/v1/compare/:ticker` | POST | `api/v1/stocks#compare` | Compare strategies |
|
|
170
|
+
|
|
171
|
+
## API Endpoints
|
|
172
|
+
|
|
173
|
+
### GET /api/v1/stock/:ticker
|
|
174
|
+
|
|
175
|
+
Returns stock price data with OHLCV (Open, High, Low, Close, Volume).
|
|
176
|
+
|
|
177
|
+
**Example:**
|
|
178
|
+
```bash
|
|
179
|
+
curl http://localhost:3000/api/v1/stock/AAPL
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Response:**
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"ticker": "AAPL",
|
|
186
|
+
"current_price": 175.50,
|
|
187
|
+
"change": 2.30,
|
|
188
|
+
"change_percent": 1.33,
|
|
189
|
+
"high_52w": 198.23,
|
|
190
|
+
"low_52w": 124.17,
|
|
191
|
+
"dates": ["2023-01-01", ...],
|
|
192
|
+
"open": [170.0, ...],
|
|
193
|
+
"high": [172.0, ...],
|
|
194
|
+
"low": [169.5, ...],
|
|
195
|
+
"close": [171.0, ...],
|
|
196
|
+
"volume": [50000000, ...]
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### GET /api/v1/indicators/:ticker
|
|
201
|
+
|
|
202
|
+
Returns calculated technical indicators.
|
|
203
|
+
|
|
204
|
+
**Example:**
|
|
205
|
+
```bash
|
|
206
|
+
curl http://localhost:3000/api/v1/indicators/AAPL
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### POST /api/v1/backtest/:ticker
|
|
210
|
+
|
|
211
|
+
Runs a backtest for the specified strategy.
|
|
212
|
+
|
|
213
|
+
**Example:**
|
|
214
|
+
```bash
|
|
215
|
+
curl -X POST http://localhost:3000/api/v1/backtest/AAPL \
|
|
216
|
+
-H "Content-Type: application/json" \
|
|
217
|
+
-d '{"strategy":"RSI"}'
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### GET /api/v1/analyze/:ticker
|
|
221
|
+
|
|
222
|
+
Returns market analysis including regime, seasonal patterns, FPOP, and risk metrics.
|
|
223
|
+
|
|
224
|
+
### POST /api/v1/compare/:ticker
|
|
225
|
+
|
|
226
|
+
Compares all available strategies and returns results sorted by return.
|
|
227
|
+
|
|
228
|
+
## Technology Stack
|
|
229
|
+
|
|
230
|
+
### Backend
|
|
231
|
+
- **Rails 7.1** - Full-stack web framework
|
|
232
|
+
- **SQLite3** - Database
|
|
233
|
+
- **Puma** - Web server
|
|
234
|
+
- **SQA Library** - Stock analysis and backtesting
|
|
235
|
+
- **TA-Lib** - Technical analysis indicators
|
|
236
|
+
- **Polars** - High-performance DataFrames
|
|
237
|
+
- **Redis** - KBS blackboard persistence
|
|
238
|
+
|
|
239
|
+
### Frontend
|
|
240
|
+
- **Plotly.js** - Interactive financial charts
|
|
241
|
+
- **Turbo** - Single-page application speed
|
|
242
|
+
- **Stimulus** - JavaScript framework
|
|
243
|
+
- **Font Awesome** - Icons
|
|
244
|
+
- **Custom CSS3** - Responsive styling
|
|
245
|
+
|
|
246
|
+
## Development
|
|
247
|
+
|
|
248
|
+
### Rails Console
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
rails console
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Run Tests
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
rails test
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Database Operations
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
rails db:create # Create database
|
|
264
|
+
rails db:migrate # Run migrations
|
|
265
|
+
rails db:reset # Reset database
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Check Routes
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
rails routes
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Configuration
|
|
275
|
+
|
|
276
|
+
### Environment Variables
|
|
277
|
+
|
|
278
|
+
- `AV_API_KEY` - Alpha Vantage API key
|
|
279
|
+
- `RAILS_ENV` - Rails environment (development/production/test)
|
|
280
|
+
- `RAILS_MAX_THREADS` - Maximum threads (default: 5)
|
|
281
|
+
|
|
282
|
+
### Database
|
|
283
|
+
|
|
284
|
+
Edit `config/database.yml` to configure database settings.
|
|
285
|
+
|
|
286
|
+
### Asset Pipeline
|
|
287
|
+
|
|
288
|
+
Assets are automatically compiled in development. For production:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
rails assets:precompile
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Deployment
|
|
295
|
+
|
|
296
|
+
### Using Rails Server
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
rails server -e production -p 3000
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Using Puma
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
puma -C config/puma.rb
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Using Docker
|
|
309
|
+
|
|
310
|
+
```dockerfile
|
|
311
|
+
FROM ruby:3.3
|
|
312
|
+
WORKDIR /app
|
|
313
|
+
COPY Gemfile* ./
|
|
314
|
+
RUN bundle install
|
|
315
|
+
COPY . .
|
|
316
|
+
RUN rails assets:precompile
|
|
317
|
+
EXPOSE 3000
|
|
318
|
+
CMD ["rails", "server", "-b", "0.0.0.0"]
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Troubleshooting
|
|
322
|
+
|
|
323
|
+
### TA-Lib Not Found
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
# Reinstall TA-Lib
|
|
327
|
+
brew reinstall ta-lib # macOS
|
|
328
|
+
sudo apt-get install --reinstall ta-lib-dev # Ubuntu
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Redis Connection Error
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# Start Redis
|
|
335
|
+
redis-server &
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Database Issues
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
# Reset database
|
|
342
|
+
rails db:reset
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Port Already in Use
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
# Kill process on port 3000
|
|
349
|
+
lsof -ti:3000 | xargs kill -9
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Differences from Sinatra App
|
|
353
|
+
|
|
354
|
+
| Feature | Sinatra App | Rails App |
|
|
355
|
+
|---------|-------------|-----------|
|
|
356
|
+
| Framework | Lightweight | Full-featured |
|
|
357
|
+
| Structure | Flat | MVC architecture |
|
|
358
|
+
| Routing | Manual | Rails conventions |
|
|
359
|
+
| Database | Optional | Built-in (SQLite) |
|
|
360
|
+
| Asset Pipeline | Manual | Sprockets |
|
|
361
|
+
| ORM | None | Active Record |
|
|
362
|
+
| Testing | Manual | Built-in (Minitest) |
|
|
363
|
+
| Generators | None | Rails generators |
|
|
364
|
+
| Conventions | Minimal | Rails conventions |
|
|
365
|
+
|
|
366
|
+
## Performance Tips
|
|
367
|
+
|
|
368
|
+
1. **Enable Caching** - Use Rails caching for API responses
|
|
369
|
+
2. **Database Indexes** - Add indexes for frequently queried fields
|
|
370
|
+
3. **Asset Compression** - Use asset minification in production
|
|
371
|
+
4. **CDN** - Serve static assets from CDN
|
|
372
|
+
5. **Background Jobs** - Use Sidekiq for long-running tasks
|
|
373
|
+
|
|
374
|
+
## Security
|
|
375
|
+
|
|
376
|
+
- CSRF protection enabled
|
|
377
|
+
- API authentication recommended for production
|
|
378
|
+
- Environment variables for sensitive data
|
|
379
|
+
- Input validation on ticker symbols
|
|
380
|
+
- HTTPS recommended for production
|
|
381
|
+
|
|
382
|
+
## Contributing
|
|
383
|
+
|
|
384
|
+
Improvements welcome! Areas for contribution:
|
|
385
|
+
|
|
386
|
+
- [ ] Portfolio optimization interface
|
|
387
|
+
- [ ] User authentication and sessions
|
|
388
|
+
- [ ] Saved watchlists
|
|
389
|
+
- [ ] Real-time WebSocket updates
|
|
390
|
+
- [ ] Background job processing
|
|
391
|
+
- [ ] API rate limiting
|
|
392
|
+
- [ ] Caching layer
|
|
393
|
+
- [ ] Additional strategies
|
|
394
|
+
|
|
395
|
+
## License
|
|
396
|
+
|
|
397
|
+
MIT License - Same as SQA library
|
|
398
|
+
|
|
399
|
+
## Credits
|
|
400
|
+
|
|
401
|
+
- **SQA Library** - Stock analysis framework
|
|
402
|
+
- **Rails** - Web framework
|
|
403
|
+
- **Plotly.js** - Interactive charts
|
|
404
|
+
- **TA-Lib** - Technical analysis
|
|
405
|
+
- **Font Awesome** - Icons
|
|
406
|
+
|
|
407
|
+
## Links
|
|
408
|
+
|
|
409
|
+
- [SQA Repository](https://github.com/MadBomber/sqa)
|
|
410
|
+
- [Rails Documentation](https://guides.rubyonrails.org/)
|
|
411
|
+
- [Plotly.js Documentation](https://plotly.com/javascript/)
|
|
412
|
+
- [TA-Lib](http://ta-lib.org/)
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
**Disclaimer:** This software is for educational and research purposes only. Do not use for actual trading without proper due diligence. The authors are not responsible for financial losses.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Global functions for modal and navigation
|
|
2
|
+
|
|
3
|
+
function showTickerModal() {
|
|
4
|
+
document.getElementById('tickerModal').style.display = 'block';
|
|
5
|
+
document.getElementById('tickerInput').focus();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function closeTickerModal() {
|
|
9
|
+
document.getElementById('tickerModal').style.display = 'none';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function searchTicker(event) {
|
|
13
|
+
event.preventDefault();
|
|
14
|
+
|
|
15
|
+
const input = event.target.querySelector('input[type="text"]');
|
|
16
|
+
const ticker = input.value.trim().toUpperCase();
|
|
17
|
+
|
|
18
|
+
if (!ticker) {
|
|
19
|
+
alert('Please enter a stock ticker symbol');
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Validate ticker format (letters and optional dot)
|
|
24
|
+
if (!/^[A-Z]{1,5}(\.[A-Z]{1,2})?$/.test(ticker)) {
|
|
25
|
+
alert('Please enter a valid ticker symbol (e.g., AAPL, BRK.A)');
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Navigate to dashboard
|
|
30
|
+
window.location.href = `/dashboard/${ticker}`;
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Close modal when clicking outside
|
|
35
|
+
window.onclick = function(event) {
|
|
36
|
+
const modal = document.getElementById('tickerModal');
|
|
37
|
+
if (event.target === modal) {
|
|
38
|
+
closeTickerModal();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Keyboard shortcuts
|
|
43
|
+
document.addEventListener('keydown', function(event) {
|
|
44
|
+
// Ctrl/Cmd + K to open search
|
|
45
|
+
if ((event.ctrlKey || event.metaKey) && event.key === 'k') {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
showTickerModal();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Escape to close modal
|
|
51
|
+
if (event.key === 'Escape') {
|
|
52
|
+
closeTickerModal();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Utility functions
|
|
57
|
+
function formatCurrency(value) {
|
|
58
|
+
return new Intl.NumberFormat('en-US', {
|
|
59
|
+
style: 'currency',
|
|
60
|
+
currency: 'USD'
|
|
61
|
+
}).format(value);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function formatPercent(value) {
|
|
65
|
+
return `${value >= 0 ? '+' : ''}${value.toFixed(2)}%`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function formatNumber(value) {
|
|
69
|
+
return new Intl.NumberFormat('en-US').format(value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Show loading indicator
|
|
73
|
+
function showLoading(elementId) {
|
|
74
|
+
const element = document.getElementById(elementId);
|
|
75
|
+
if (element) {
|
|
76
|
+
element.innerHTML = '<p class="loading"><i class="fas fa-spinner fa-spin"></i> Loading...</p>';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Show error message
|
|
81
|
+
function showError(elementId, message) {
|
|
82
|
+
const element = document.getElementById(elementId);
|
|
83
|
+
if (element) {
|
|
84
|
+
element.innerHTML = `<p class="error"><i class="fas fa-exclamation-circle"></i> ${message}</p>`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Debounce function for performance
|
|
89
|
+
function debounce(func, wait) {
|
|
90
|
+
let timeout;
|
|
91
|
+
return function executedFunction(...args) {
|
|
92
|
+
const later = () => {
|
|
93
|
+
clearTimeout(timeout);
|
|
94
|
+
func(...args);
|
|
95
|
+
};
|
|
96
|
+
clearTimeout(timeout);
|
|
97
|
+
timeout = setTimeout(later, wait);
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Console welcome message
|
|
102
|
+
console.log('%cSQA Analytics', 'font-size: 24px; font-weight: bold; color: #2196F3;');
|
|
103
|
+
console.log('%cPowered by Ruby & Plotly.js', 'font-size: 14px; color: #666;');
|
|
104
|
+
console.log('');
|
|
105
|
+
console.log('Keyboard shortcuts:');
|
|
106
|
+
console.log(' Ctrl/Cmd + K: Open ticker search');
|
|
107
|
+
console.log(' Escape: Close modal');
|