sqa 0.0.32 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +92 -1
- data/README.md +4 -0
- data/Rakefile +52 -10
- data/docs/IMPROVEMENT_PLAN.md +531 -0
- data/docs/advanced/index.md +1 -13
- data/docs/api/index.md +547 -61
- data/docs/api-reference/alphavantageapi.md +1057 -0
- data/docs/api-reference/apierror.md +31 -0
- data/docs/api-reference/index.md +221 -0
- data/docs/api-reference/notimplemented.md +27 -0
- data/docs/api-reference/sqa.md +267 -0
- data/docs/api-reference/sqa_backtest.md +137 -0
- data/docs/api-reference/sqa_backtest_results.md +530 -0
- data/docs/api-reference/sqa_badparametererror.md +13 -0
- data/docs/api-reference/sqa_config.md +538 -0
- data/docs/api-reference/sqa_configurationerror.md +13 -0
- data/docs/api-reference/sqa_datafetcherror.md +56 -0
- data/docs/api-reference/sqa_dataframe.md +752 -0
- data/docs/api-reference/sqa_dataframe_alphavantage.md +30 -0
- data/docs/api-reference/sqa_dataframe_data.md +325 -0
- data/docs/api-reference/sqa_dataframe_yahoofinance.md +25 -0
- data/docs/api-reference/sqa_ensemble.md +413 -0
- data/docs/api-reference/sqa_fpop.md +211 -0
- data/docs/api-reference/sqa_geneticprogram.md +325 -0
- data/docs/api-reference/sqa_geneticprogram_individual.md +114 -0
- data/docs/api-reference/sqa_marketregime.md +212 -0
- data/docs/api-reference/sqa_multitimeframe.md +227 -0
- data/docs/api-reference/sqa_patternmatcher.md +195 -0
- data/docs/api-reference/sqa_pluginmanager.md +55 -0
- data/docs/api-reference/sqa_portfolio.md +455 -0
- data/docs/api-reference/sqa_portfolio_position.md +220 -0
- data/docs/api-reference/sqa_portfolio_trade.md +332 -0
- data/docs/api-reference/sqa_portfoliooptimizer.md +248 -0
- data/docs/api-reference/sqa_riskmanager.md +388 -0
- data/docs/api-reference/sqa_seasonalanalyzer.md +121 -0
- data/docs/api-reference/sqa_sectoranalyzer.md +163 -0
- data/docs/api-reference/sqa_stock.md +649 -0
- data/docs/api-reference/sqa_strategy.md +178 -0
- data/docs/api-reference/sqa_strategy_bollingerbands.md +26 -0
- data/docs/api-reference/sqa_strategy_common.md +29 -0
- data/docs/api-reference/sqa_strategy_consensus.md +129 -0
- data/docs/api-reference/sqa_strategy_ema.md +41 -0
- data/docs/api-reference/sqa_strategy_kbs.md +154 -0
- data/docs/api-reference/sqa_strategy_macd.md +26 -0
- data/docs/api-reference/sqa_strategy_mp.md +41 -0
- data/docs/api-reference/sqa_strategy_mr.md +41 -0
- data/docs/api-reference/sqa_strategy_random.md +41 -0
- data/docs/api-reference/sqa_strategy_rsi.md +41 -0
- data/docs/api-reference/sqa_strategy_sma.md +41 -0
- data/docs/api-reference/sqa_strategy_stochastic.md +26 -0
- data/docs/api-reference/sqa_strategy_volumebreakout.md +26 -0
- data/docs/api-reference/sqa_strategygenerator.md +298 -0
- data/docs/api-reference/sqa_strategygenerator_pattern.md +264 -0
- data/docs/api-reference/sqa_strategygenerator_patterncontext.md +326 -0
- data/docs/api-reference/sqa_strategygenerator_profitablepoint.md +424 -0
- data/docs/api-reference/sqa_stream.md +256 -0
- data/docs/api-reference/sqa_ticker.md +175 -0
- data/docs/api-reference/string.md +135 -0
- data/docs/assets/images/advanced-workflow.svg +89 -0
- data/docs/assets/images/architecture.svg +107 -0
- data/docs/assets/images/data-flow.svg +138 -0
- data/docs/assets/images/getting-started-workflow.svg +88 -0
- data/docs/assets/images/strategy-flow.svg +78 -0
- data/docs/assets/images/system-architecture.svg +150 -0
- data/docs/concepts/index.md +292 -19
- data/docs/getting-started/index.md +1 -14
- data/docs/index.md +26 -23
- data/docs/llms.txt +109 -0
- data/docs/strategies/kbs.md +15 -14
- data/docs/strategy.md +381 -3
- data/docs/terms_of_use.md +1 -1
- data/examples/README.md +10 -0
- data/lib/api/alpha_vantage_api.rb +3 -7
- data/lib/sqa/config.rb +109 -28
- data/lib/sqa/data_frame/data.rb +13 -1
- data/lib/sqa/data_frame.rb +168 -26
- data/lib/sqa/errors.rb +79 -17
- data/lib/sqa/init.rb +70 -15
- data/lib/sqa/pattern_matcher.rb +4 -4
- data/lib/sqa/portfolio.rb +1 -1
- data/lib/sqa/sector_analyzer.rb +3 -11
- data/lib/sqa/stock.rb +169 -15
- data/lib/sqa/strategy.rb +62 -4
- data/lib/sqa/ticker.rb +106 -48
- data/lib/sqa/version.rb +1 -1
- data/lib/sqa.rb +4 -4
- data/mkdocs.yml +68 -81
- metadata +89 -21
- data/docs/README.md +0 -43
- data/examples/sinatra_app/Gemfile +0 -42
- data/examples/sinatra_app/Gemfile.lock +0 -268
- data/examples/sinatra_app/QUICKSTART.md +0 -169
- data/examples/sinatra_app/README.md +0 -471
- data/examples/sinatra_app/RUNNING_WITHOUT_TALIB.md +0 -90
- data/examples/sinatra_app/TROUBLESHOOTING.md +0 -95
- data/examples/sinatra_app/app.rb +0 -404
- data/examples/sinatra_app/config.ru +0 -5
- data/examples/sinatra_app/public/css/style.css +0 -723
- data/examples/sinatra_app/public/debug_macd.html +0 -82
- data/examples/sinatra_app/public/js/app.js +0 -107
- data/examples/sinatra_app/start.sh +0 -53
- data/examples/sinatra_app/views/analyze.erb +0 -306
- data/examples/sinatra_app/views/backtest.erb +0 -325
- data/examples/sinatra_app/views/dashboard.erb +0 -831
- data/examples/sinatra_app/views/error.erb +0 -58
- data/examples/sinatra_app/views/index.erb +0 -118
- data/examples/sinatra_app/views/layout.erb +0 -61
- data/examples/sinatra_app/views/portfolio.erb +0 -43
data/docs/index.md
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
# SQA - Simple Qualitative Analysis
|
|
2
2
|
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
|
|
3
|
+
<div style="display: flex; align-items: flex-start; gap: 2rem; margin-bottom: 2rem;">
|
|
4
|
+
<div style="flex: 0 0 400px;">
|
|
5
|
+
<img src="assets/images/sqa.jpg" alt="SQA - Simple Qualitative Analysis" style="width: 100%; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
|
|
6
|
+
</div>
|
|
7
|
+
<div style="flex: 1;">
|
|
8
|
+
<h2 style="margin-top: 0;">Key Features</h2>
|
|
9
|
+
<ul>
|
|
10
|
+
<li><strong>High Performance</strong> - Rust-backed Polars DataFrames (30x faster)</li>
|
|
11
|
+
<li><strong>150+ Technical Indicators</strong> - TA-Lib integration via sqa-tai</li>
|
|
12
|
+
<li><strong>13+ Trading Strategies</strong> - RSI, MACD, Bollinger Bands, and more</li>
|
|
13
|
+
<li><strong>Portfolio Management</strong> - Track positions, P&L, commissions</li>
|
|
14
|
+
<li><strong>Backtesting Framework</strong> - Comprehensive performance metrics</li>
|
|
15
|
+
<li><strong>Real-Time Streaming</strong> - Live price data with callbacks</li>
|
|
16
|
+
<li><strong>Strategy Generation</strong> - Discover patterns from profitable trades</li>
|
|
17
|
+
<li><strong>Genetic Programming</strong> - Evolve optimal parameters</li>
|
|
18
|
+
<li><strong>Risk Management</strong> - VaR, CVaR, position sizing</li>
|
|
19
|
+
<li><strong>Pattern Matching</strong> - Find similar historical patterns</li>
|
|
20
|
+
</ul>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
6
23
|
|
|
7
24
|
---
|
|
8
25
|
|
|
@@ -97,26 +114,7 @@ puts "Max Drawdown: #{results.max_drawdown}%"
|
|
|
97
114
|
|
|
98
115
|
## Architecture
|
|
99
116
|
|
|
100
|
-
|
|
101
|
-
graph TD
|
|
102
|
-
A[Stock Data] --> B[SQA::DataFrame]
|
|
103
|
-
B --> C[Technical Indicators]
|
|
104
|
-
C --> D[Trading Strategies]
|
|
105
|
-
D --> E{Strategy Type}
|
|
106
|
-
E -->|Simple| F[SMA/EMA/RSI]
|
|
107
|
-
E -->|Advanced| G[MACD/Bollinger]
|
|
108
|
-
E -->|Rule-Based| H[KBS Strategy]
|
|
109
|
-
D --> I[Portfolio Management]
|
|
110
|
-
I --> J[Backtesting]
|
|
111
|
-
J --> K[Performance Metrics]
|
|
112
|
-
|
|
113
|
-
L[Real-Time Data] --> M[SQA::Stream]
|
|
114
|
-
M --> D
|
|
115
|
-
|
|
116
|
-
N[Pattern Discovery] --> O[StrategyGenerator]
|
|
117
|
-
O --> P[Generated Strategies]
|
|
118
|
-
P --> D
|
|
119
|
-
```
|
|
117
|
+

|
|
120
118
|
|
|
121
119
|
## Getting Started
|
|
122
120
|
|
|
@@ -143,10 +141,15 @@ Ready to dive in? Check out our guides:
|
|
|
143
141
|
- [Data Sources](data-sources/index.md) - Working with data
|
|
144
142
|
- [Terms of Use](terms_of_use.md) - Important legal information
|
|
145
143
|
|
|
144
|
+
## Demo Application
|
|
145
|
+
|
|
146
|
+
Want to see SQA in action? Check out the **[sqa_demo-sinatra](https://github.com/MadBomber/sqa_demo-sinatra)** gem - a web-based demonstration application that provides a visual interface for exploring stock analysis, technical indicators, and trading strategies.
|
|
147
|
+
|
|
146
148
|
## Community & Support
|
|
147
149
|
|
|
148
150
|
- **GitHub**: [github.com/madbomber/sqa](https://github.com/madbomber/sqa)
|
|
149
151
|
- **RubyGems**: [rubygems.org/gems/sqa](https://rubygems.org/gems/sqa)
|
|
152
|
+
- **Demo App**: [sqa_demo-sinatra](https://github.com/MadBomber/sqa_demo-sinatra) - Web-based SQA demonstration
|
|
150
153
|
- **Issues**: Report bugs or request features on [GitHub Issues](https://github.com/madbomber/sqa/issues)
|
|
151
154
|
|
|
152
155
|
## License
|
data/docs/llms.txt
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# SQA - Simple Qualitative Analysis
|
|
2
|
+
|
|
3
|
+
> A powerful Ruby library for stock market technical analysis and trading strategy development
|
|
4
|
+
|
|
5
|
+
SQA (Simple Qualitative Analysis) is an educational Ruby library designed for stock market technical analysis and trading strategy development. Built with high-performance data structures and seamlessly integrated with TA-Lib, SQA provides a comprehensive toolkit for analyzing historical stock data, implementing trading strategies, and backtesting your ideas.
|
|
6
|
+
|
|
7
|
+
SQA is designed for educational purposes only. It should not be used for actual trading without extensive testing and professional financial advice. Trading stocks involves substantial risk of loss.
|
|
8
|
+
|
|
9
|
+
- Polars DataFrames: Rust-backed data structures providing 30x faster operations than pure Ruby - TA-Lib Integration: Access to 150+ battle-tested technical indicators via the sqa-tai gem - Efficient Algorithms: Optimized for large historical datasets
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
- [Index](https://madbomber.github.io/sqa/getting-started/index): Welcome to SQA! This guide will help you get up and running with stock market technical analysis in just a few minutes.
|
|
14
|
+
- [Installation](https://madbomber.github.io/sqa/getting-started/installation): This guide walks you through installing SQA and all its dependencies.
|
|
15
|
+
- [Quick Start](https://madbomber.github.io/sqa/getting-started/quick-start): Get up and running with SQA in just a few minutes!
|
|
16
|
+
|
|
17
|
+
## Core Concepts
|
|
18
|
+
|
|
19
|
+
- [Index](https://madbomber.github.io/sqa/concepts/index): Understanding the fundamental building blocks of SQA.
|
|
20
|
+
- [Dataframes](https://madbomber.github.io/sqa/data_frame): The SQA::DataFrame class is a high-performance wrapper around the Polars DataFrame library, specifically designed for time series financial data...
|
|
21
|
+
- [Technical Indicators](https://madbomber.github.io/sqa/indicators/index): SQA provides access to 150+ technical indicators via the sqa-tai gem, which wraps the industry-standard TA-Lib library.
|
|
22
|
+
- [Trading Strategies](https://madbomber.github.io/sqa/strategy): A strategy is a recipe that cooks all the indicators together to make a decision on a potential trade. The SQA::Strategy class provides the...
|
|
23
|
+
|
|
24
|
+
## Technical Indicators
|
|
25
|
+
|
|
26
|
+
- [Index](https://madbomber.github.io/sqa/indicators/index): SQA provides access to 150+ technical indicators via the sqa-tai gem, which wraps the industry-standard TA-Lib library.
|
|
27
|
+
- [Overview](https://madbomber.github.io/sqa/indicators): ## The Philosophy of Indicators
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Trading Strategies
|
|
32
|
+
|
|
33
|
+
- [Index](https://madbomber.github.io/sqa/strategies/index): Explore SQA's comprehensive suite of trading strategies.
|
|
34
|
+
|
|
35
|
+
### Built-in Strategies
|
|
36
|
+
|
|
37
|
+
- [Bollinger Bands Strategy](https://madbomber.github.io/sqa/strategies/bollinger-bands): The Bollinger Bands strategy uses volatility bands to identify oversold and overbought conditions. The strategy generates buy signals when price...
|
|
38
|
+
- [Rsi Strategy](https://madbomber.github.io/sqa/strategies/rsi): The Relative Strength Index (RSI) strategy identifies overbought and oversold conditions using momentum oscillators. It generates signals when RSI...
|
|
39
|
+
- [Macd Strategy](https://madbomber.github.io/sqa/strategies/macd): Moving Average Convergence Divergence (MACD) is a trend-following momentum indicator that shows the relationship between two moving averages.
|
|
40
|
+
- [Sma Strategy](https://madbomber.github.io/sqa/strategies/sma): The SMA strategy uses crossovers of short-term and long-term simple moving averages to identify trend changes and generate trading signals.
|
|
41
|
+
- [Ema Strategy](https://madbomber.github.io/sqa/strategies/ema): Similar to SMA but gives more weight to recent prices, making it more responsive to price changes.
|
|
42
|
+
- [Stochastic Strategy](https://madbomber.github.io/sqa/strategies/stochastic): Compares closing price to the price range over a period to identify overbought/oversold conditions and momentum changes.
|
|
43
|
+
- [Volume Breakout](https://madbomber.github.io/sqa/strategies/volume-breakout): Identifies price breakouts confirmed by high trading volume for stronger signal reliability.
|
|
44
|
+
- [Mean Reversion](https://madbomber.github.io/sqa/strategies/mean-reversion): Based on the theory that prices tend to return to their average over time. Buys when price is below average and sells when above.
|
|
45
|
+
- [Market Profile](https://madbomber.github.io/sqa/strategies/market-profile): Uses market profile analysis to identify support and resistance levels, generating signals when price reaches these key levels.
|
|
46
|
+
- [Consensus Strategy](https://madbomber.github.io/sqa/strategies/consensus): Aggregates signals from multiple strategies and makes trading decisions based on majority vote. Reduces risk of acting on single false signals.
|
|
47
|
+
|
|
48
|
+
### Advanced Strategies
|
|
49
|
+
|
|
50
|
+
- [Knowledge Based Strategy (kbs)](https://madbomber.github.io/sqa/strategies/kbs): Advanced rule-based trading system using RETE forward-chaining inference engine. Combines multiple indicators with custom logic rules.
|
|
51
|
+
- [Custom Strategies](https://madbomber.github.io/sqa/strategies/custom): Learn how to create your own trading strategies in the SQA framework.
|
|
52
|
+
|
|
53
|
+
## Advanced Features
|
|
54
|
+
|
|
55
|
+
- [Index](https://madbomber.github.io/sqa/advanced/index): Explore SQA's advanced capabilities for professional-grade analysis.
|
|
56
|
+
- [Portfolio Management](https://madbomber.github.io/sqa/advanced/portfolio): The Portfolio class tracks positions, calculates P&L, manages commissions, and monitors portfolio performance over time.
|
|
57
|
+
- [Backtesting](https://madbomber.github.io/sqa/advanced/backtesting): Simulate trading strategies on historical data to evaluate performance before risking real capital.
|
|
58
|
+
- [Strategy Generator](https://madbomber.github.io/sqa/advanced/strategy-generator): Reverse-engineer profitable trades to discover patterns and automatically generate executable trading strategies.
|
|
59
|
+
- [Genetic Programming](https://madbomber.github.io/sqa/genetic_programming): ### Overview of Genetic Programming (GP)
|
|
60
|
+
- [Real Time Streaming](https://madbomber.github.io/sqa/advanced/streaming): Process live price data with event callbacks and parallel strategy execution for real-time trading signals.
|
|
61
|
+
- [Fpop Analysis](https://madbomber.github.io/sqa/advanced/fpop): Calculate future returns, risk metrics, and direction classification to evaluate trading opportunities.
|
|
62
|
+
- [Risk Management](https://madbomber.github.io/sqa/advanced/risk-management): Comprehensive risk management tools including VaR, position sizing, and risk metrics.
|
|
63
|
+
- [Portfolio Optimizer](https://madbomber.github.io/sqa/advanced/portfolio-optimizer): Multi-objective portfolio optimization for optimal asset allocation and rebalancing.
|
|
64
|
+
- [Ensemble Strategies](https://madbomber.github.io/sqa/advanced/ensemble): Combine multiple strategies with voting and meta-learning.
|
|
65
|
+
- [Multi Timeframe Analysis](https://madbomber.github.io/sqa/advanced/multi-timeframe): Analyze multiple timeframes simultaneously for better trade timing.
|
|
66
|
+
- [Pattern Matcher](https://madbomber.github.io/sqa/advanced/pattern-matcher): Pattern recognition and similarity search for forecasting.
|
|
67
|
+
|
|
68
|
+
## AI & Machine Learning
|
|
69
|
+
|
|
70
|
+
- [Ai And Ml](https://madbomber.github.io/sqa/ai_and_ml): ## AI and ML in Trading -- Advancing Decision-Making
|
|
71
|
+
- [Mean Reversion](https://madbomber.github.io/sqa/mean_reversion): Determines if a stock exhibits mean reversion behavior based on a given price series.
|
|
72
|
+
- [Predict Next Value](https://madbomber.github.io/sqa/predict_next_value): As a stock quantitative analyst, having a predict next value method on a timeseries array of closing day stock price data would be extremely helpful....
|
|
73
|
+
- [Identify Wave Condition](https://madbomber.github.io/sqa/identify_wave_condition): The Elliott Wave Theory is a popular method used in stock technical analysis to predict future price movements in financial markets. It is based on...
|
|
74
|
+
- [Libsvm Format](https://madbomber.github.io/sqa/libsvm_file_format): This file format is used by rumale.
|
|
75
|
+
|
|
76
|
+
## API Reference
|
|
77
|
+
|
|
78
|
+
- [Index](https://madbomber.github.io/sqa/api/index): Complete API documentation for SQA classes and modules.
|
|
79
|
+
- [Dataframe Class](https://madbomber.github.io/sqa/api/dataframe): SQA::DataFrame is a high-performance wrapper around the Polars DataFrame library, specifically optimized for time series financial data manipulation....
|
|
80
|
+
|
|
81
|
+
## Data Sources
|
|
82
|
+
|
|
83
|
+
- [Index](https://madbomber.github.io/sqa/data-sources/index): SQA supports multiple data sources for historical stock price data.
|
|
84
|
+
|
|
85
|
+
## Resources
|
|
86
|
+
|
|
87
|
+
- [Tags](https://madbomber.github.io/sqa/tags): Browse documentation by topic.
|
|
88
|
+
- [Requirements](https://madbomber.github.io/sqa/requirements): ... otherwise know as what I want to do. Some people would call it a roadmap; but, where I'm going "we don't need no stinking roads!"
|
|
89
|
+
- [Terms Of Use](https://madbomber.github.io/sqa/terms_of_use): Some sections of these Terms of Use are aspirational. If found to be so, they shall not invalidate any other section which shall remain in full...
|
|
90
|
+
- [Trading Ideas](https://madbomber.github.io/sqa/i_gotta_an_idea): ... based upon my prior work with sports outcome predictions and sensor net architecture.
|
|
91
|
+
- [Factor Analysis](https://madbomber.github.io/sqa/factors_that_impact_price): ## Factors that Impact Price
|
|
92
|
+
|
|
93
|
+
### External Tools
|
|
94
|
+
|
|
95
|
+
- [Finviz](https://madbomber.github.io/sqa/finviz): The original finviz unofficial gem has been untouched for 3 years. I just forked it in the hope that I can bring it forward to current versions of...
|
|
96
|
+
- [Fx Pro Bit](https://madbomber.github.io/sqa/fx_pro_bit): FXProBot is a new trading software by Avenix Fzco, a major fintech firm located in Dubai that specializes in automated trading. This advanced robot...
|
|
97
|
+
- [Options Trading](https://madbomber.github.io/sqa/options): https://www.youtube.com/watch?v=A5w-dEgIU1M
|
|
98
|
+
|
|
99
|
+
## Contributing
|
|
100
|
+
|
|
101
|
+
- [Index](https://madbomber.github.io/sqa/contributing/index): Thank you for your interest in contributing to SQA!
|
|
102
|
+
|
|
103
|
+
## Optional
|
|
104
|
+
|
|
105
|
+
These resources provide supplementary information that may be skipped for shorter context:
|
|
106
|
+
|
|
107
|
+
- [Tags](https://madbomber.github.io/sqa/tags): Browse documentation by topic.
|
|
108
|
+
- [Requirements](https://madbomber.github.io/sqa/requirements): ... otherwise know as what I want to do. Some people would call it a roadmap; but, where I'm going "we don't need no stinking roads!"
|
|
109
|
+
- [Terms of Use](https://madbomber.github.io/sqa/terms_of_use): Some sections of these Terms of Use are aspirational. If found to be so, they shall not invalidate any other section which shall remain in full...
|
data/docs/strategies/kbs.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
Advanced rule-based trading system using RETE forward-chaining inference engine. Combines multiple indicators with custom logic rules.
|
|
5
|
+
Advanced rule-based trading system using RETE forward-chaining inference engine. Combines multiple indicators with custom logic rules using the `kbs` (knowledge-based system) ruby gem. A complete [documentation website for the `kbs` ruby gem is available.](https://madbomber.github.io/kbs)
|
|
6
6
|
|
|
7
7
|
## How It Works
|
|
8
8
|
|
|
@@ -29,6 +29,7 @@ end
|
|
|
29
29
|
## Default Rules
|
|
30
30
|
|
|
31
31
|
The KBS strategy includes 10 default rules:
|
|
32
|
+
|
|
32
33
|
1. Buy on RSI oversold in uptrend
|
|
33
34
|
2. Sell on RSI overbought in downtrend
|
|
34
35
|
3. Buy on bullish MACD crossover
|
|
@@ -71,10 +72,10 @@ strategy.add_rule :strong_buy do
|
|
|
71
72
|
without :position # Don't buy if already holding
|
|
72
73
|
|
|
73
74
|
perform do
|
|
74
|
-
kb.assert(:signal, {
|
|
75
|
-
action: :buy,
|
|
75
|
+
kb.assert(:signal, {
|
|
76
|
+
action: :buy,
|
|
76
77
|
confidence: :high,
|
|
77
|
-
reason: :triple_confirmation
|
|
78
|
+
reason: :triple_confirmation
|
|
78
79
|
})
|
|
79
80
|
end
|
|
80
81
|
end
|
|
@@ -100,18 +101,18 @@ Multiple rules can fire, with aggregate confidence determining final signal.
|
|
|
100
101
|
|
|
101
102
|
## Strengths
|
|
102
103
|
|
|
103
|
-
✅ Highly customizable
|
|
104
|
-
✅ Combines multiple indicators
|
|
105
|
-
✅ Confidence scoring
|
|
106
|
-
✅ Forward-chaining inference
|
|
107
|
-
✅ Can encode expert knowledge
|
|
104
|
+
- ✅ Highly customizable
|
|
105
|
+
- ✅ Combines multiple indicators
|
|
106
|
+
- ✅ Confidence scoring
|
|
107
|
+
- ✅ Forward-chaining inference
|
|
108
|
+
- ✅ Can encode expert knowledge
|
|
108
109
|
|
|
109
110
|
## Weaknesses
|
|
110
111
|
|
|
111
|
-
❌ Complex to configure
|
|
112
|
-
❌ Requires domain knowledge
|
|
113
|
-
❌ Can be slow with many rules
|
|
114
|
-
❌ Overfitting risk
|
|
112
|
+
- ❌ Complex to configure
|
|
113
|
+
- ❌ Requires domain knowledge
|
|
114
|
+
- ❌ Can be slow with many rules
|
|
115
|
+
- ❌ Overfitting risk
|
|
115
116
|
|
|
116
117
|
## Tips
|
|
117
118
|
|
|
@@ -124,6 +125,7 @@ Multiple rules can fire, with aggregate confidence determining final signal.
|
|
|
124
125
|
## Available Facts
|
|
125
126
|
|
|
126
127
|
The KBS strategy processes these fact types:
|
|
128
|
+
|
|
127
129
|
- `:rsi` - RSI indicator data
|
|
128
130
|
- `:macd` - MACD crossovers
|
|
129
131
|
- `:trend` - Price trend analysis
|
|
@@ -161,4 +163,3 @@ end
|
|
|
161
163
|
|
|
162
164
|
- [Strategy Generator](../advanced/strategy-generator.md) - Auto-generate rules
|
|
163
165
|
- [Genetic Programming](../genetic_programming.md) - Optimize rule parameters
|
|
164
|
-
|
data/docs/strategy.md
CHANGED
|
@@ -1,5 +1,383 @@
|
|
|
1
|
-
# Strategy
|
|
1
|
+
# Strategy Framework
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A comprehensive guide to SQA's trading strategy architecture.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
A strategy in SQA is a set of rules that analyze technical indicators and market data to generate trading signals. The `SQA::Strategy` class provides the framework for managing and executing multiple strategies.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## The Strategy Pattern
|
|
14
|
+
|
|
15
|
+
All SQA strategies follow a common interface:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
class SQA::Strategy::YourStrategy
|
|
19
|
+
def self.trade(vector)
|
|
20
|
+
# Analyze the vector (OpenStruct with indicator data)
|
|
21
|
+
# Return :buy, :sell, or :hold
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### The Vector
|
|
27
|
+
|
|
28
|
+
The vector is an `OpenStruct` containing all the data a strategy needs to make a decision:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
require 'ostruct'
|
|
32
|
+
|
|
33
|
+
vector = OpenStruct.new(
|
|
34
|
+
rsi: { trend: :over_sold, value: 28.5 },
|
|
35
|
+
macd: { crossover: :bullish, histogram: 0.5 },
|
|
36
|
+
prices: prices_array,
|
|
37
|
+
sma_20: sma_20.last,
|
|
38
|
+
sma_50: sma_50.last
|
|
39
|
+
)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Using the Strategy Framework
|
|
43
|
+
|
|
44
|
+
### Managing Multiple Strategies
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
# Create a strategy manager
|
|
48
|
+
strategy = SQA::Strategy.new
|
|
49
|
+
|
|
50
|
+
# Add strategies
|
|
51
|
+
strategy.add SQA::Strategy::RSI
|
|
52
|
+
strategy.add SQA::Strategy::MACD
|
|
53
|
+
strategy.add SQA::Strategy::BollingerBands
|
|
54
|
+
|
|
55
|
+
# Execute all strategies
|
|
56
|
+
signals = strategy.execute(vector)
|
|
57
|
+
# => [:buy, :hold, :sell]
|
|
58
|
+
|
|
59
|
+
# Count votes for consensus
|
|
60
|
+
buy_votes = signals.count(:buy)
|
|
61
|
+
sell_votes = signals.count(:sell)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Auto-Loading Strategies
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
# Load all built-in strategies
|
|
68
|
+
strategy = SQA::Strategy.new
|
|
69
|
+
strategy.auto_load
|
|
70
|
+
|
|
71
|
+
# Load specific strategies only
|
|
72
|
+
strategy.auto_load(only: [:rsi, :macd])
|
|
73
|
+
|
|
74
|
+
# Load all except certain strategies
|
|
75
|
+
strategy.auto_load(except: [:random, :common])
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Listing Available Strategies
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
strategy = SQA::Strategy.new
|
|
82
|
+
available = strategy.available
|
|
83
|
+
# => [SQA::Strategy::RSI, SQA::Strategy::MACD, ...]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Built-in Strategies
|
|
87
|
+
|
|
88
|
+
SQA includes 13+ built-in trading strategies:
|
|
89
|
+
|
|
90
|
+
### Trend-Following
|
|
91
|
+
|
|
92
|
+
| Strategy | Description | Best For |
|
|
93
|
+
|----------|-------------|----------|
|
|
94
|
+
| **SMA** | Simple Moving Average crossovers | Trending markets |
|
|
95
|
+
| **EMA** | Exponential Moving Average crossovers | Faster trend detection |
|
|
96
|
+
| **MACD** | Moving Average Convergence Divergence | Momentum + trend |
|
|
97
|
+
|
|
98
|
+
### Momentum
|
|
99
|
+
|
|
100
|
+
| Strategy | Description | Best For |
|
|
101
|
+
|----------|-------------|----------|
|
|
102
|
+
| **RSI** | Relative Strength Index (oversold/overbought) | Range-bound markets |
|
|
103
|
+
| **Stochastic** | Stochastic oscillator crossovers | Short-term reversals |
|
|
104
|
+
|
|
105
|
+
### Volatility
|
|
106
|
+
|
|
107
|
+
| Strategy | Description | Best For |
|
|
108
|
+
|----------|-------------|----------|
|
|
109
|
+
| **Bollinger Bands** | Price touching volatility bands | Volatile markets |
|
|
110
|
+
| **Volume Breakout** | High volume price breakouts | Breakout trading |
|
|
111
|
+
|
|
112
|
+
### Advanced
|
|
113
|
+
|
|
114
|
+
| Strategy | Description | Best For |
|
|
115
|
+
|----------|-------------|----------|
|
|
116
|
+
| **KBS** | Knowledge-Based System with RETE engine | Complex rule combinations |
|
|
117
|
+
| **Consensus** | Aggregates multiple strategy signals | Reducing noise |
|
|
118
|
+
| **Mean Reversion** | Statistical mean reversion | Range-bound markets |
|
|
119
|
+
|
|
120
|
+
## Creating Custom Strategies
|
|
121
|
+
|
|
122
|
+
### Basic Template
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
# lib/my_strategies/awesome_strategy.rb
|
|
126
|
+
|
|
127
|
+
class SQA::Strategy::AwesomeStrategy
|
|
128
|
+
def self.trade(vector)
|
|
129
|
+
# Your trading logic here
|
|
130
|
+
if buy_condition?(vector)
|
|
131
|
+
:buy
|
|
132
|
+
elsif sell_condition?(vector)
|
|
133
|
+
:sell
|
|
134
|
+
else
|
|
135
|
+
:hold
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
private
|
|
140
|
+
|
|
141
|
+
def self.buy_condition?(vector)
|
|
142
|
+
vector.rsi[:value] < 30 &&
|
|
143
|
+
vector.macd[:crossover] == :bullish
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def self.sell_condition?(vector)
|
|
147
|
+
vector.rsi[:value] > 70 &&
|
|
148
|
+
vector.macd[:crossover] == :bearish
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Using Your Strategy
|
|
154
|
+
|
|
155
|
+
```ruby
|
|
156
|
+
require_relative 'my_strategies/awesome_strategy'
|
|
157
|
+
|
|
158
|
+
# Execute directly
|
|
159
|
+
signal = SQA::Strategy::AwesomeStrategy.trade(vector)
|
|
160
|
+
|
|
161
|
+
# Or add to strategy manager
|
|
162
|
+
strategy = SQA::Strategy.new
|
|
163
|
+
strategy.add SQA::Strategy::AwesomeStrategy
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Strategy with Configuration
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
class SQA::Strategy::ConfigurableRSI
|
|
170
|
+
@oversold_threshold = 30
|
|
171
|
+
@overbought_threshold = 70
|
|
172
|
+
|
|
173
|
+
class << self
|
|
174
|
+
attr_accessor :oversold_threshold, :overbought_threshold
|
|
175
|
+
|
|
176
|
+
def trade(vector)
|
|
177
|
+
rsi_value = vector.rsi[:value] || vector.rsi
|
|
178
|
+
|
|
179
|
+
if rsi_value < oversold_threshold
|
|
180
|
+
:buy
|
|
181
|
+
elsif rsi_value > overbought_threshold
|
|
182
|
+
:sell
|
|
183
|
+
else
|
|
184
|
+
:hold
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Configure before using
|
|
191
|
+
SQA::Strategy::ConfigurableRSI.oversold_threshold = 25
|
|
192
|
+
SQA::Strategy::ConfigurableRSI.overbought_threshold = 75
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Combining Strategies
|
|
196
|
+
|
|
197
|
+
### Consensus Strategy
|
|
198
|
+
|
|
199
|
+
The built-in Consensus strategy aggregates signals from multiple strategies:
|
|
200
|
+
|
|
201
|
+
```ruby
|
|
202
|
+
# Simple majority vote
|
|
203
|
+
signals = strategy.execute(vector)
|
|
204
|
+
# => [:buy, :buy, :hold, :sell]
|
|
205
|
+
|
|
206
|
+
consensus = signals.group_by(&:itself)
|
|
207
|
+
.transform_values(&:count)
|
|
208
|
+
.max_by { |_, v| v }
|
|
209
|
+
.first
|
|
210
|
+
# => :buy (2 votes vs 1 each for hold/sell)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Weighted Voting
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
# Assign weights to strategies
|
|
217
|
+
weights = {
|
|
218
|
+
SQA::Strategy::RSI => 2.0, # RSI gets double weight
|
|
219
|
+
SQA::Strategy::MACD => 1.5, # MACD gets 1.5x weight
|
|
220
|
+
SQA::Strategy::SMA => 1.0 # SMA gets normal weight
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
# Calculate weighted consensus
|
|
224
|
+
weighted_votes = { buy: 0.0, sell: 0.0, hold: 0.0 }
|
|
225
|
+
signals.each_with_index do |signal, i|
|
|
226
|
+
weight = weights.values[i]
|
|
227
|
+
weighted_votes[signal] += weight
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
final_signal = weighted_votes.max_by { |_, v| v }.first
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Testing Strategies
|
|
234
|
+
|
|
235
|
+
### Unit Testing
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
# test/strategy/awesome_strategy_test.rb
|
|
239
|
+
require 'minitest/autorun'
|
|
240
|
+
require 'ostruct'
|
|
241
|
+
|
|
242
|
+
class AwesomeStrategyTest < Minitest::Test
|
|
243
|
+
def test_buy_signal_on_oversold
|
|
244
|
+
vector = OpenStruct.new(
|
|
245
|
+
rsi: { value: 25, trend: :over_sold },
|
|
246
|
+
macd: { crossover: :bullish }
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
assert_equal :buy, SQA::Strategy::AwesomeStrategy.trade(vector)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def test_sell_signal_on_overbought
|
|
253
|
+
vector = OpenStruct.new(
|
|
254
|
+
rsi: { value: 75, trend: :over_bought },
|
|
255
|
+
macd: { crossover: :bearish }
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
assert_equal :sell, SQA::Strategy::AwesomeStrategy.trade(vector)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Backtesting
|
|
264
|
+
|
|
265
|
+
```ruby
|
|
266
|
+
backtest = SQA::Backtest.new(
|
|
267
|
+
stock: stock,
|
|
268
|
+
strategy: SQA::Strategy::AwesomeStrategy,
|
|
269
|
+
initial_cash: 10_000
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
results = backtest.run
|
|
273
|
+
puts "Return: #{results.total_return}%"
|
|
274
|
+
puts "Sharpe: #{results.sharpe_ratio}"
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Strategy Internals
|
|
278
|
+
|
|
279
|
+
### How Strategies Process Data
|
|
280
|
+
|
|
281
|
+
1. **Data Preparation**: Raw price data is converted to indicators
|
|
282
|
+
2. **Vector Creation**: Indicators are packaged into an OpenStruct
|
|
283
|
+
3. **Strategy Execution**: Each strategy analyzes the vector
|
|
284
|
+
4. **Signal Generation**: Strategy returns `:buy`, `:sell`, or `:hold`
|
|
285
|
+
5. **Aggregation**: Signals can be combined for consensus
|
|
286
|
+
|
|
287
|
+
### Data Ordering
|
|
288
|
+
|
|
289
|
+
All indicator data in SQA follows **ascending chronological order** (oldest first):
|
|
290
|
+
|
|
291
|
+
```ruby
|
|
292
|
+
# prices[0] = oldest price
|
|
293
|
+
# prices[-1] = most recent price
|
|
294
|
+
|
|
295
|
+
prices = stock.df["adj_close_price"].to_a
|
|
296
|
+
rsi = SQAI.rsi(prices, period: 14)
|
|
297
|
+
|
|
298
|
+
# rsi.last is the most recent RSI value
|
|
299
|
+
current_rsi = rsi.last
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Best Practices
|
|
303
|
+
|
|
304
|
+
### 1. Keep Strategies Simple
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
# GOOD: Clear, single-purpose logic
|
|
308
|
+
def self.trade(vector)
|
|
309
|
+
vector.rsi[:value] < 30 ? :buy : :hold
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# BAD: Complex nested conditions
|
|
313
|
+
def self.trade(vector)
|
|
314
|
+
if vector.rsi[:value] < 30
|
|
315
|
+
if vector.macd[:histogram] > 0
|
|
316
|
+
if vector.volume > vector.avg_volume * 1.5
|
|
317
|
+
# ... more nesting ...
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### 2. Use Named Parameters in Vectors
|
|
325
|
+
|
|
326
|
+
```ruby
|
|
327
|
+
# GOOD: Self-documenting
|
|
328
|
+
vector = OpenStruct.new(
|
|
329
|
+
rsi_value: rsi.last,
|
|
330
|
+
rsi_trend: rsi.last < 30 ? :oversold : :neutral,
|
|
331
|
+
sma_20: sma_20.last,
|
|
332
|
+
sma_50: sma_50.last
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# BAD: Magic numbers
|
|
336
|
+
vector = OpenStruct.new(
|
|
337
|
+
val1: 28.5,
|
|
338
|
+
val2: 150.0,
|
|
339
|
+
val3: 148.0
|
|
340
|
+
)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### 3. Handle Edge Cases
|
|
344
|
+
|
|
345
|
+
```ruby
|
|
346
|
+
def self.trade(vector)
|
|
347
|
+
return :hold if vector.rsi.nil?
|
|
348
|
+
return :hold if vector.prices.empty?
|
|
349
|
+
|
|
350
|
+
# Main logic here
|
|
351
|
+
end
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### 4. Document Your Strategy
|
|
355
|
+
|
|
356
|
+
```ruby
|
|
357
|
+
# Dual Moving Average Crossover Strategy
|
|
358
|
+
#
|
|
359
|
+
# Generates buy signals when short MA crosses above long MA,
|
|
360
|
+
# sell signals when short MA crosses below long MA.
|
|
361
|
+
#
|
|
362
|
+
# Parameters:
|
|
363
|
+
# vector.sma_short - Short-term SMA (e.g., 20-day)
|
|
364
|
+
# vector.sma_long - Long-term SMA (e.g., 50-day)
|
|
365
|
+
#
|
|
366
|
+
# Returns:
|
|
367
|
+
# :buy - Short MA > Long MA (bullish crossover)
|
|
368
|
+
# :sell - Short MA < Long MA (bearish crossover)
|
|
369
|
+
# :hold - No clear signal
|
|
370
|
+
#
|
|
371
|
+
class SQA::Strategy::DualMA
|
|
372
|
+
def self.trade(vector)
|
|
373
|
+
# ...
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Related Documentation
|
|
379
|
+
|
|
380
|
+
- [Trading Strategies Reference](strategies/index.md) - Details on each built-in strategy
|
|
381
|
+
- [Custom Strategies](strategies/custom.md) - Guide to creating your own
|
|
382
|
+
- [Backtesting](advanced/backtesting.md) - Test strategies on historical data
|
|
383
|
+
- [Technical Indicators](indicators/index.md) - Calculate indicator values
|
data/docs/terms_of_use.md
CHANGED
|
@@ -32,7 +32,7 @@ Your affirmative act of using our Ruby Gem ("library") located at https://github
|
|
|
32
32
|
- [20. House rules](#20-house-rules)
|
|
33
33
|
- [21. Third Party Software](#21-third-party-software)
|
|
34
34
|
- [22. Scripts](#22-scripts)
|
|
35
|
-
- [23. Publications - No Recommendation or Advice Status](#23-publications
|
|
35
|
+
- [23. Publications - No Recommendation or Advice Status](#23-publications-no-recommendation-or-advice-status)
|
|
36
36
|
|
|
37
37
|
<!-- Tocer[finish]: Auto-generated, don't remove. -->
|
|
38
38
|
|
data/examples/README.md
CHANGED
|
@@ -335,6 +335,15 @@ Examples may create output files in `/tmp/`:
|
|
|
335
335
|
- `/tmp/sqa_evolution_history.csv` - GP evolution history
|
|
336
336
|
- `/tmp/sqa_backtest_results.csv` - Backtest results
|
|
337
337
|
|
|
338
|
+
## Web Demo Application
|
|
339
|
+
|
|
340
|
+
For a complete web-based demonstration of SQA's capabilities, see the **[sqa_demo-sinatra](https://github.com/MadBomber/sqa_demo-sinatra)** gem. This Sinatra application provides a visual interface for:
|
|
341
|
+
|
|
342
|
+
- Stock analysis dashboard
|
|
343
|
+
- Technical indicator visualization
|
|
344
|
+
- Strategy backtesting
|
|
345
|
+
- Portfolio management
|
|
346
|
+
|
|
338
347
|
## Next Steps
|
|
339
348
|
|
|
340
349
|
After running these examples:
|
|
@@ -344,6 +353,7 @@ After running these examples:
|
|
|
344
353
|
3. **Walk-Forward Validation**: Test on out-of-sample data
|
|
345
354
|
4. **Combine Techniques**: Use strategy generator + GP + KBS together
|
|
346
355
|
5. **Production Deployment**: Connect to real WebSocket data feeds
|
|
356
|
+
6. **Try the Web Demo**: Install [sqa_demo-sinatra](https://github.com/MadBomber/sqa_demo-sinatra) for a visual interface
|
|
347
357
|
|
|
348
358
|
## Educational Disclaimer
|
|
349
359
|
|