sqa 0.0.32 → 0.0.38

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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +154 -1
  3. data/README.md +4 -0
  4. data/Rakefile +52 -10
  5. data/docs/advanced/index.md +1 -13
  6. data/docs/api/index.md +547 -61
  7. data/docs/api-reference/alphavantageapi.md +1057 -0
  8. data/docs/api-reference/apierror.md +31 -0
  9. data/docs/api-reference/index.md +221 -0
  10. data/docs/api-reference/notimplemented.md +27 -0
  11. data/docs/api-reference/sqa.md +267 -0
  12. data/docs/api-reference/sqa_backtest.md +171 -0
  13. data/docs/api-reference/sqa_backtest_results.md +530 -0
  14. data/docs/api-reference/sqa_badparametererror.md +13 -0
  15. data/docs/api-reference/sqa_config.md +538 -0
  16. data/docs/api-reference/sqa_configurationerror.md +13 -0
  17. data/docs/api-reference/sqa_datafetcherror.md +56 -0
  18. data/docs/api-reference/sqa_dataframe.md +779 -0
  19. data/docs/api-reference/sqa_dataframe_alphavantage.md +30 -0
  20. data/docs/api-reference/sqa_dataframe_data.md +325 -0
  21. data/docs/api-reference/sqa_dataframe_yahoofinance.md +25 -0
  22. data/docs/api-reference/sqa_ensemble.md +413 -0
  23. data/docs/api-reference/sqa_fpop.md +211 -0
  24. data/docs/api-reference/sqa_geneticprogram.md +325 -0
  25. data/docs/api-reference/sqa_geneticprogram_individual.md +114 -0
  26. data/docs/api-reference/sqa_marketregime.md +212 -0
  27. data/docs/api-reference/sqa_multitimeframe.md +227 -0
  28. data/docs/api-reference/sqa_patternmatcher.md +195 -0
  29. data/docs/api-reference/sqa_pluginmanager.md +55 -0
  30. data/docs/api-reference/sqa_portfolio.md +512 -0
  31. data/docs/api-reference/sqa_portfolio_position.md +220 -0
  32. data/docs/api-reference/sqa_portfolio_trade.md +332 -0
  33. data/docs/api-reference/sqa_portfoliooptimizer.md +248 -0
  34. data/docs/api-reference/sqa_riskmanager.md +388 -0
  35. data/docs/api-reference/sqa_seasonalanalyzer.md +121 -0
  36. data/docs/api-reference/sqa_sectoranalyzer.md +163 -0
  37. data/docs/api-reference/sqa_stock.md +661 -0
  38. data/docs/api-reference/sqa_strategy.md +178 -0
  39. data/docs/api-reference/sqa_strategy_bollingerbands.md +26 -0
  40. data/docs/api-reference/sqa_strategy_common.md +29 -0
  41. data/docs/api-reference/sqa_strategy_consensus.md +129 -0
  42. data/docs/api-reference/sqa_strategy_ema.md +41 -0
  43. data/docs/api-reference/sqa_strategy_kbs.md +154 -0
  44. data/docs/api-reference/sqa_strategy_macd.md +26 -0
  45. data/docs/api-reference/sqa_strategy_mp.md +41 -0
  46. data/docs/api-reference/sqa_strategy_mr.md +41 -0
  47. data/docs/api-reference/sqa_strategy_random.md +41 -0
  48. data/docs/api-reference/sqa_strategy_rsi.md +41 -0
  49. data/docs/api-reference/sqa_strategy_sma.md +41 -0
  50. data/docs/api-reference/sqa_strategy_stochastic.md +26 -0
  51. data/docs/api-reference/sqa_strategy_volumebreakout.md +26 -0
  52. data/docs/api-reference/sqa_strategygenerator.md +298 -0
  53. data/docs/api-reference/sqa_strategygenerator_pattern.md +264 -0
  54. data/docs/api-reference/sqa_strategygenerator_patterncontext.md +326 -0
  55. data/docs/api-reference/sqa_strategygenerator_profitablepoint.md +424 -0
  56. data/docs/api-reference/sqa_stream.md +256 -0
  57. data/docs/api-reference/sqa_ticker.md +175 -0
  58. data/docs/api-reference/string.md +135 -0
  59. data/docs/assets/images/advanced-workflow.svg +89 -0
  60. data/docs/assets/images/architecture.svg +107 -0
  61. data/docs/assets/images/data-flow.svg +138 -0
  62. data/docs/assets/images/getting-started-workflow.svg +88 -0
  63. data/docs/assets/images/strategy-flow.svg +78 -0
  64. data/docs/assets/images/system-architecture.svg +150 -0
  65. data/docs/concepts/index.md +292 -19
  66. data/docs/file_formats.md +250 -0
  67. data/docs/getting-started/index.md +1 -14
  68. data/docs/index.md +26 -23
  69. data/docs/llms.txt +109 -0
  70. data/docs/strategies/kbs.md +15 -14
  71. data/docs/strategy.md +381 -3
  72. data/docs/terms_of_use.md +1 -1
  73. data/examples/README.md +10 -0
  74. data/lib/api/alpha_vantage_api.rb +3 -7
  75. data/lib/sqa/backtest.rb +32 -0
  76. data/lib/sqa/config.rb +109 -28
  77. data/lib/sqa/data_frame/data.rb +13 -1
  78. data/lib/sqa/data_frame.rb +193 -26
  79. data/lib/sqa/errors.rb +79 -17
  80. data/lib/sqa/init.rb +70 -15
  81. data/lib/sqa/pattern_matcher.rb +4 -4
  82. data/lib/sqa/portfolio.rb +55 -1
  83. data/lib/sqa/sector_analyzer.rb +3 -11
  84. data/lib/sqa/stock.rb +180 -15
  85. data/lib/sqa/strategy.rb +62 -4
  86. data/lib/sqa/ticker.rb +106 -48
  87. data/lib/sqa/version.rb +1 -1
  88. data/lib/sqa.rb +4 -4
  89. data/mkdocs.yml +69 -81
  90. metadata +89 -21
  91. data/docs/README.md +0 -43
  92. data/examples/sinatra_app/Gemfile +0 -42
  93. data/examples/sinatra_app/Gemfile.lock +0 -268
  94. data/examples/sinatra_app/QUICKSTART.md +0 -169
  95. data/examples/sinatra_app/README.md +0 -471
  96. data/examples/sinatra_app/RUNNING_WITHOUT_TALIB.md +0 -90
  97. data/examples/sinatra_app/TROUBLESHOOTING.md +0 -95
  98. data/examples/sinatra_app/app.rb +0 -404
  99. data/examples/sinatra_app/config.ru +0 -5
  100. data/examples/sinatra_app/public/css/style.css +0 -723
  101. data/examples/sinatra_app/public/debug_macd.html +0 -82
  102. data/examples/sinatra_app/public/js/app.js +0 -107
  103. data/examples/sinatra_app/start.sh +0 -53
  104. data/examples/sinatra_app/views/analyze.erb +0 -306
  105. data/examples/sinatra_app/views/backtest.erb +0 -325
  106. data/examples/sinatra_app/views/dashboard.erb +0 -831
  107. data/examples/sinatra_app/views/error.erb +0 -58
  108. data/examples/sinatra_app/views/index.erb +0 -118
  109. data/examples/sinatra_app/views/layout.erb +0 -61
  110. data/examples/sinatra_app/views/portfolio.erb +0 -43
@@ -0,0 +1,88 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 450" width="1400" height="450">
2
+ <defs>
3
+ <style>
4
+ .box { stroke: #ffffff; stroke-width: 3; }
5
+ .text { fill: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 15px; font-weight: 600; text-anchor: middle; }
6
+ .small-text { fill: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 13px; font-weight: 500; text-anchor: middle; }
7
+ .arrow { stroke: #ffffff; stroke-width: 2.5; fill: none; marker-end: url(#arrowhead); }
8
+ .diamond { stroke: #ffffff; stroke-width: 3; }
9
+ .label { fill: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 14px; font-weight: 500; }
10
+ </style>
11
+ <marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
12
+ <polygon points="0 0, 10 3, 0 6" fill="#ffffff" />
13
+ </marker>
14
+ </defs>
15
+
16
+ <!-- Install SQA -->
17
+ <rect x="30" y="180" width="150" height="70" rx="8" class="box" fill="#2E86DE"/>
18
+ <text x="105" y="210" class="text">Install</text>
19
+ <text x="105" y="230" class="text">SQA</text>
20
+
21
+ <!-- Configure API Keys -->
22
+ <rect x="220" y="180" width="150" height="70" rx="8" class="box" fill="#3867D6"/>
23
+ <text x="295" y="210" class="text">Configure</text>
24
+ <text x="295" y="230" class="text">API Keys</text>
25
+
26
+ <!-- Load Stock Data -->
27
+ <rect x="410" y="180" width="150" height="70" rx="8" class="box" fill="#10AC84"/>
28
+ <text x="485" y="210" class="text">Load Stock</text>
29
+ <text x="485" y="230" class="text">Data</text>
30
+
31
+ <!-- Calculate Indicators -->
32
+ <rect x="600" y="180" width="150" height="70" rx="8" class="box" fill="#EE5A6F"/>
33
+ <text x="675" y="210" class="text">Calculate</text>
34
+ <text x="675" y="230" class="text">Indicators</text>
35
+
36
+ <!-- Apply Strategies -->
37
+ <rect x="790" y="180" width="150" height="70" rx="8" class="box" fill="#F368E0"/>
38
+ <text x="865" y="210" class="text">Apply</text>
39
+ <text x="865" y="230" class="text">Strategies</text>
40
+
41
+ <!-- Analysis Type Diamond -->
42
+ <g transform="translate(1030, 215)">
43
+ <polygon points="0,-50 70,0 0,50 -70,0" class="diamond" fill="#FD79A8"/>
44
+ <text x="0" y="-5" class="small-text">Analysis</text>
45
+ <text x="0" y="12" class="small-text">Type</text>
46
+ </g>
47
+
48
+ <!-- Run Backtest -->
49
+ <rect x="1155" y="50" width="150" height="70" rx="8" class="box" fill="#FF9F43"/>
50
+ <text x="1230" y="80" class="text">Run</text>
51
+ <text x="1230" y="100" class="text">Backtest</text>
52
+
53
+ <!-- Stream Real-Time -->
54
+ <rect x="1155" y="180" width="150" height="70" rx="8" class="box" fill="#FFA502"/>
55
+ <text x="1230" y="210" class="text">Stream</text>
56
+ <text x="1230" y="230" class="text">Real-Time</text>
57
+
58
+ <!-- Explore in Console -->
59
+ <rect x="1155" y="310" width="150" height="70" rx="8" class="box" fill="#FF6348"/>
60
+ <text x="1230" y="333" class="text">Explore in</text>
61
+ <text x="1230" y="353" class="text">Console</text>
62
+
63
+ <!-- Review Results -->
64
+ <rect x="1155" y="420" width="150" height="50" rx="8" class="box" fill="#26DE81"/>
65
+ <text x="1230" y="450" class="text">Review Results</text>
66
+
67
+ <!-- Arrows - Main flow -->
68
+ <path d="M 180 215 L 220 215" class="arrow"/>
69
+ <path d="M 370 215 L 410 215" class="arrow"/>
70
+ <path d="M 560 215 L 600 215" class="arrow"/>
71
+ <path d="M 750 215 L 790 215" class="arrow"/>
72
+ <path d="M 940 215 L 960 215" class="arrow"/>
73
+
74
+ <!-- Arrows from diamond -->
75
+ <path d="M 1030 165 L 1030 85 L 1155 85" class="arrow"/>
76
+ <path d="M 1100 215 L 1155 215" class="arrow"/>
77
+ <path d="M 1030 265 L 1030 345 L 1155 345" class="arrow"/>
78
+
79
+ <!-- Arrows to Review Results -->
80
+ <path d="M 1230 120 L 1230 420" class="arrow"/>
81
+ <path d="M 1230 250 L 1230 420" class="arrow"/>
82
+ <path d="M 1230 380 L 1230 420" class="arrow"/>
83
+
84
+ <!-- Labels on decision paths -->
85
+ <text x="1090" y="115" class="label">Backtest</text>
86
+ <text x="1120" y="210" class="label">Live</text>
87
+ <text x="1090" y="305" class="label">Research</text>
88
+ </svg>
@@ -0,0 +1,78 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 650" width="800" height="650">
2
+ <defs>
3
+ <style>
4
+ .box { stroke: #ffffff; stroke-width: 3; }
5
+ .text { fill: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 16px; font-weight: 600; text-anchor: middle; }
6
+ .arrow { stroke: #ffffff; stroke-width: 2.5; fill: none; marker-end: url(#arrowhead); }
7
+ .diamond { stroke: #ffffff; stroke-width: 3; }
8
+ .label { fill: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 14px; font-weight: 500; }
9
+ </style>
10
+ <marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
11
+ <polygon points="0 0, 10 3, 0 6" fill="#ffffff" />
12
+ </marker>
13
+ </defs>
14
+
15
+ <!-- Price Data -->
16
+ <rect x="300" y="30" width="200" height="70" rx="8" class="box" fill="#2E86DE"/>
17
+ <text x="400" y="70" class="text">Price Data</text>
18
+
19
+ <!-- Technical Indicators -->
20
+ <rect x="300" y="150" width="200" height="70" rx="8" class="box" fill="#EE5A6F"/>
21
+ <text x="400" y="182" class="text">Technical</text>
22
+ <text x="400" y="202" class="text">Indicators</text>
23
+
24
+ <!-- Strategy Vector -->
25
+ <rect x="300" y="270" width="200" height="70" rx="8" class="box" fill="#10AC84"/>
26
+ <text x="400" y="302" class="text">Strategy</text>
27
+ <text x="400" y="322" class="text">Vector</text>
28
+
29
+ <!-- Trading Strategy -->
30
+ <rect x="300" y="390" width="200" height="70" rx="8" class="box" fill="#F368E0"/>
31
+ <text x="400" y="422" class="text">Trading</text>
32
+ <text x="400" y="442" class="text">Strategy</text>
33
+
34
+ <!-- Signal Diamond -->
35
+ <g transform="translate(400, 540)">
36
+ <polygon points="0,-50 70,0 0,50 -70,0" class="diamond" fill="#FD79A8"/>
37
+ <text x="0" y="5" class="text">Signal</text>
38
+ </g>
39
+
40
+ <!-- Buy Action -->
41
+ <rect x="50" y="580" width="150" height="60" rx="8" class="box" fill="#26DE81"/>
42
+ <text x="125" y="615" class="text">Buy Action</text>
43
+
44
+ <!-- Sell Action -->
45
+ <rect x="325" y="580" width="150" height="60" rx="8" class="box" fill="#FC5C65"/>
46
+ <text x="400" y="615" class="text">Sell Action</text>
47
+
48
+ <!-- No Action (Hold) -->
49
+ <rect x="600" y="580" width="150" height="60" rx="8" class="box" fill="#FED330"/>
50
+ <text x="675" y="615" class="text">No Action</text>
51
+
52
+ <!-- Arrows -->
53
+ <!-- Price Data to Technical Indicators -->
54
+ <path d="M 400 100 L 400 150" class="arrow"/>
55
+
56
+ <!-- Technical Indicators to Strategy Vector -->
57
+ <path d="M 400 220 L 400 270" class="arrow"/>
58
+
59
+ <!-- Strategy Vector to Trading Strategy -->
60
+ <path d="M 400 340 L 400 390" class="arrow"/>
61
+
62
+ <!-- Trading Strategy to Signal -->
63
+ <path d="M 400 460 L 400 490" class="arrow"/>
64
+
65
+ <!-- Signal to Buy -->
66
+ <path d="M 330 540 L 200 580" class="arrow"/>
67
+
68
+ <!-- Signal to Sell -->
69
+ <path d="M 400 590 L 400 580" class="arrow"/>
70
+
71
+ <!-- Signal to Hold -->
72
+ <path d="M 470 540 L 600 580" class="arrow"/>
73
+
74
+ <!-- Labels on arrows to actions -->
75
+ <text x="260" y="565" class="label">:buy</text>
76
+ <text x="400" y="575" class="label">:sell</text>
77
+ <text x="535" y="565" class="label">:hold</text>
78
+ </svg>
@@ -0,0 +1,150 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 900" width="1200" height="900">
2
+ <defs>
3
+ <style>
4
+ .box { stroke: #ffffff; stroke-width: 3; }
5
+ .text { fill: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 15px; font-weight: 600; text-anchor: middle; }
6
+ .small-text { fill: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 13px; font-weight: 500; text-anchor: middle; }
7
+ .arrow { stroke: #ffffff; stroke-width: 2.5; fill: none; marker-end: url(#arrowhead); }
8
+ .layer-box { stroke: #ffffff; stroke-width: 2; fill: none; stroke-dasharray: 5,5; opacity: 0.6; }
9
+ .layer-title { fill: #ffffff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 18px; font-weight: 700; }
10
+ .diamond { stroke: #ffffff; stroke-width: 3; }
11
+ </style>
12
+ <marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
13
+ <polygon points="0 0, 10 3, 0 6" fill="#ffffff" />
14
+ </marker>
15
+ </defs>
16
+
17
+ <!-- Data Layer -->
18
+ <rect x="20" y="20" width="1160" height="140" rx="8" class="layer-box"/>
19
+ <text x="40" y="45" class="layer-title">Data Layer</text>
20
+
21
+ <rect x="80" y="70" width="200" height="60" rx="8" class="box" fill="#2E86DE"/>
22
+ <text x="180" y="97" class="text">Alpha Vantage</text>
23
+ <text x="180" y="115" class="text">API</text>
24
+
25
+ <rect x="350" y="70" width="200" height="60" rx="8" class="box" fill="#3867D6"/>
26
+ <text x="450" y="97" class="text">Yahoo</text>
27
+ <text x="450" y="115" class="text">Finance</text>
28
+
29
+ <rect x="620" y="70" width="200" height="60" rx="8" class="box" fill="#4B7BEC"/>
30
+ <text x="720" y="105" class="text">CSV Files</text>
31
+
32
+ <rect x="880" y="70" width="200" height="60" rx="8" class="box" fill="#5352ED"/>
33
+ <text x="980" y="105" class="text">Raw Data</text>
34
+
35
+ <!-- Core Layer -->
36
+ <rect x="20" y="180" width="1160" height="160" rx="8" class="layer-box"/>
37
+ <text x="40" y="205" class="layer-title">Core Layer</text>
38
+
39
+ <rect x="150" y="230" width="180" height="60" rx="8" class="box" fill="#10AC84"/>
40
+ <text x="240" y="265" class="text">SQA::Stock</text>
41
+
42
+ <rect x="400" y="230" width="200" height="60" rx="8" class="box" fill="#1DD1A1"/>
43
+ <text x="500" y="265" class="text">SQA::DataFrame</text>
44
+
45
+ <rect x="670" y="230" width="240" height="60" rx="8" class="box" fill="#00D2D3"/>
46
+ <text x="790" y="257" class="text">SQA::DataFrame</text>
47
+ <text x="790" y="275" class="text">::Data</text>
48
+
49
+ <rect x="980" y="230" width="180" height="60" rx="8" class="box" fill="#01A3A4"/>
50
+ <text x="1070" y="257" class="text">Price/Volume</text>
51
+ <text x="1070" y="275" class="text">Arrays</text>
52
+
53
+ <!-- Analysis Layer -->
54
+ <rect x="20" y="360" width="1160" height="140" rx="8" class="layer-box"/>
55
+ <text x="40" y="385" class="layer-title">Analysis Layer</text>
56
+
57
+ <rect x="350" y="410" width="240" height="60" rx="8" class="box" fill="#EE5A6F"/>
58
+ <text x="470" y="437" class="text">SQAI/TAI</text>
59
+ <text x="470" y="455" class="text">Indicators</text>
60
+
61
+ <rect x="680" y="410" width="200" height="60" rx="8" class="box" fill="#FF6B6B"/>
62
+ <text x="780" y="437" class="text">Technical</text>
63
+ <text x="780" y="455" class="text">Values</text>
64
+
65
+ <!-- Strategy Layer -->
66
+ <rect x="20" y="520" width="1160" height="220" rx="8" class="layer-box"/>
67
+ <text x="40" y="545" class="layer-title">Strategy Layer</text>
68
+
69
+ <rect x="80" y="570" width="200" height="60" rx="8" class="box" fill="#F368E0"/>
70
+ <text x="180" y="597" class="text">Strategy</text>
71
+ <text x="180" y="615" class="text">Vector</text>
72
+
73
+ <rect x="360" y="570" width="200" height="60" rx="8" class="box" fill="#E056FD"/>
74
+ <text x="460" y="597" class="text">Trading</text>
75
+ <text x="460" y="615" class="text">Strategies</text>
76
+
77
+ <!-- Diamond for Signal -->
78
+ <g transform="translate(720, 600)">
79
+ <polygon points="0,-40 60,0 0,40 -60,0" class="diamond" fill="#FD79A8"/>
80
+ <text x="0" y="5" class="text">Signal</text>
81
+ </g>
82
+
83
+ <rect x="860" y="570" width="120" height="60" rx="8" class="box" fill="#26DE81"/>
84
+ <text x="920" y="605" class="text">Buy</text>
85
+
86
+ <rect x="860" y="650" width="120" height="60" rx="8" class="box" fill="#FC5C65"/>
87
+ <text x="920" y="685" class="text">Sell</text>
88
+
89
+ <rect x="1010" y="610" width="120" height="60" rx="8" class="box" fill="#FED330"/>
90
+ <text x="1070" y="645" class="text">Hold</text>
91
+
92
+ <!-- Execution Layer -->
93
+ <rect x="20" y="760" width="1160" height="120" rx="8" class="layer-box"/>
94
+ <text x="40" y="785" class="layer-title">Execution Layer</text>
95
+
96
+ <rect x="250" y="805" width="180" height="60" rx="8" class="box" fill="#FF9F43"/>
97
+ <text x="340" y="840" class="text">Portfolio</text>
98
+
99
+ <rect x="510" y="805" width="180" height="60" rx="8" class="box" fill="#FFA502"/>
100
+ <text x="600" y="840" class="text">Backtest</text>
101
+
102
+ <rect x="770" y="805" width="200" height="60" rx="8" class="box" fill="#FF6348"/>
103
+ <text x="870" y="832" class="text">Performance</text>
104
+ <text x="870" y="850" class="text">Metrics</text>
105
+
106
+ <!-- Arrows -->
107
+ <!-- Data Layer -->
108
+ <path d="M 180 130 L 980 130 L 980 70" class="arrow"/>
109
+ <path d="M 450 130 L 980 130" class="arrow" stroke-dasharray="5,5"/>
110
+ <path d="M 720 130 L 980 130" class="arrow" stroke-dasharray="5,5"/>
111
+
112
+ <!-- To Core Layer -->
113
+ <path d="M 980 130 L 980 180 L 240 180 L 240 230" class="arrow"/>
114
+
115
+ <!-- Core Layer connections -->
116
+ <path d="M 330 260 L 400 260" class="arrow"/>
117
+ <path d="M 600 260 L 670 260" class="arrow"/>
118
+ <path d="M 910 260 L 980 260" class="arrow"/>
119
+
120
+ <!-- To Analysis Layer -->
121
+ <path d="M 1070 290 L 1070 340 L 470 340 L 470 410" class="arrow"/>
122
+
123
+ <!-- Analysis Layer -->
124
+ <path d="M 590 440 L 680 440" class="arrow"/>
125
+
126
+ <!-- To Strategy Layer -->
127
+ <path d="M 780 470 L 780 500 L 180 500 L 180 570" class="arrow"/>
128
+
129
+ <!-- Strategy Layer -->
130
+ <path d="M 280 600 L 360 600" class="arrow"/>
131
+ <path d="M 560 600 L 660 600" class="arrow"/>
132
+ <path d="M 780 600 L 860 600" class="arrow"/>
133
+ <path d="M 760 640 L 860 680" class="arrow"/>
134
+ <path d="M 780 600 L 860 600 L 1010 640" class="arrow"/>
135
+
136
+ <!-- To Execution Layer -->
137
+ <path d="M 460 630 L 460 760 L 340 760 L 340 805" class="arrow"/>
138
+
139
+ <!-- Execution Layer -->
140
+ <path d="M 430 835 L 510 835" class="arrow"/>
141
+ <path d="M 690 835 L 770 835" class="arrow"/>
142
+
143
+ <!-- Labels -->
144
+ <text x="510" y="125" class="small-text">Fetch</text>
145
+ <text x="665" y="125" class="small-text">Scrape</text>
146
+ <text x="815" y="125" class="small-text">Import</text>
147
+ <text x="345" y="255" class="small-text">Contains</text>
148
+ <text x="635" y="255" class="small-text">Metadata</text>
149
+ <text x="525" y="435" class="small-text">Calculate</text>
150
+ </svg>
@@ -4,29 +4,259 @@ Understanding the fundamental building blocks of SQA.
4
4
 
5
5
  ## Overview
6
6
 
7
- SQA is built around several key concepts that work together to provide a comprehensive stock analysis framework:
7
+ SQA is built around several key concepts that work together to provide a comprehensive stock analysis framework. This page explains the architecture and how all the pieces fit together.
8
8
 
9
- - **Stock Objects** - Represent individual stocks with historical data
10
- - **DataFrames** - High-performance time series data structures
11
- - **Technical Indicators** - Mathematical calculations on price/volume data
12
- - **Trading Strategies** - Rules for generating buy/sell/hold signals
13
- - **Portfolio Management** - Track positions and calculate P&L
14
- - **Backtesting** - Simulate strategies on historical data
9
+ ## System Architecture
15
10
 
16
- ## Architecture Diagram
11
+ ![System Architecture](../assets/images/system-architecture.svg)
17
12
 
18
- ```mermaid
19
- graph TB
20
- A[Data Source] -->|Fetch| B[Stock Object]
21
- B -->|Contains| C[DataFrame]
22
- C -->|Calculate| D[Technical Indicators]
23
- D -->|Feed| E[Trading Strategies]
24
- E -->|Generate| F[Trading Signals]
25
- F -->|Execute| G[Portfolio]
26
- G -->|Track| H[Trades & P/L]
13
+ ## Key Components
14
+
15
+ ### 1. Stock Object (`SQA::Stock`)
16
+
17
+ The primary domain object representing a stock with all its associated data.
18
+
19
+ **Responsibilities:**
20
+ - Load and cache historical price data
21
+ - Fetch company overview information
22
+ - Manage data persistence (JSON metadata + CSV prices)
23
+ - Provide access to DataFrame for analysis
24
+
25
+ **Example:**
26
+ ```ruby
27
+ stock = SQA::Stock.new(ticker: 'AAPL')
28
+
29
+ # Access data
30
+ stock.ticker # => "aapl"
31
+ stock.name # => "Apple Inc"
32
+ stock.exchange # => "NASDAQ"
33
+ stock.df # => SQA::DataFrame with price/volume
34
+ stock.overview # => Hash with company details
35
+ ```
36
+
37
+ ### 2. DataFrame (`SQA::DataFrame`)
38
+
39
+ High-performance wrapper around Polars for time series data manipulation.
40
+
41
+ **Key Features:**
42
+ - Rust-backed Polars engine (30x faster than pure Ruby)
43
+ - Columnar operations for efficiency
44
+ - CSV/JSON import/export
45
+ - Method delegation to Polars
46
+
47
+ **Standard Columns:**
48
+ | Column | Description |
49
+ |--------|-------------|
50
+ | `timestamp` | Date of trading day |
51
+ | `open_price` | Opening price |
52
+ | `high_price` | Highest price |
53
+ | `low_price` | Lowest price |
54
+ | `close_price` | Closing price |
55
+ | `adj_close_price` | Split/dividend adjusted price |
56
+ | `volume` | Trading volume |
57
+
58
+ **Example:**
59
+ ```ruby
60
+ df = stock.df
61
+
62
+ # Column operations
63
+ prices = df["adj_close_price"].to_a
64
+ volumes = df["volume"].to_a
65
+
66
+ # Statistics (via Polars)
67
+ df.data["close_price"].mean
68
+ df.data["volume"].sum
69
+ ```
70
+
71
+ ### 3. Technical Indicators (`SQAI` / `SQA::TAI`)
72
+
73
+ 150+ technical indicators provided by the `sqa-tai` gem, which wraps TA-Lib.
74
+
75
+ **Categories:**
76
+ - **Overlap Studies**: SMA, EMA, Bollinger Bands
77
+ - **Momentum**: RSI, MACD, Stochastic
78
+ - **Volume**: OBV, AD, ADOSC
79
+ - **Volatility**: ATR, NATR, True Range
80
+ - **Cycle**: Hilbert Transform indicators
81
+ - **Pattern**: Candlestick pattern recognition
82
+
83
+ **Example:**
84
+ ```ruby
85
+ prices = stock.df["adj_close_price"].to_a
86
+
87
+ # Single-value indicators
88
+ sma = SQAI.sma(prices, period: 20)
89
+ rsi = SQAI.rsi(prices, period: 14)
90
+
91
+ # Multi-value indicators
92
+ macd, signal, histogram = SQAI.macd(prices)
93
+ upper, middle, lower = SQAI.bbands(prices, period: 20)
94
+ ```
95
+
96
+ ### 4. Trading Strategies (`SQA::Strategy`)
97
+
98
+ Framework for creating and executing trading rules.
99
+
100
+ **Interface:**
101
+ ```ruby
102
+ # All strategies implement this interface
103
+ class SQA::Strategy::MyStrategy
104
+ def self.trade(vector)
105
+ # Returns :buy, :sell, or :hold
106
+ end
107
+ end
108
+ ```
109
+
110
+ **Built-in Strategies:**
111
+ - RSI, MACD, SMA, EMA
112
+ - Bollinger Bands, Stochastic
113
+ - Volume Breakout, Mean Reversion
114
+ - KBS (Knowledge-Based System)
115
+ - Consensus (aggregates multiple strategies)
116
+
117
+ **Example:**
118
+ ```ruby
119
+ require 'ostruct'
120
+
121
+ vector = OpenStruct.new(
122
+ rsi: { trend: :over_sold, value: 28 },
123
+ prices: prices
124
+ )
125
+
126
+ signal = SQA::Strategy::RSI.trade(vector)
127
+ # => :buy
128
+ ```
129
+
130
+ ### 5. Portfolio (`SQA::Portfolio`)
131
+
132
+ Track positions, calculate P&L, and manage trades.
133
+
134
+ **Features:**
135
+ - Position tracking (shares per ticker)
136
+ - Commission handling
137
+ - Realized/unrealized P&L
138
+ - Trade history
139
+
140
+ **Example:**
141
+ ```ruby
142
+ portfolio = SQA::Portfolio.new(initial_cash: 10_000, commission: 1.0)
143
+ portfolio.buy('AAPL', shares: 10, price: 150.0)
144
+ portfolio.sell('AAPL', shares: 5, price: 160.0)
145
+
146
+ portfolio.cash # Remaining cash
147
+ portfolio.positions # Current holdings
148
+ portfolio.trades # Trade history
149
+ ```
150
+
151
+ ### 6. Backtesting (`SQA::Backtest`)
152
+
153
+ Simulate strategies on historical data.
154
+
155
+ **Metrics Generated:**
156
+ - Total return, annualized return
157
+ - Sharpe ratio, Sortino ratio
158
+ - Maximum drawdown
159
+ - Win rate, profit factor
160
+ - Number of trades
161
+
162
+ **Example:**
163
+ ```ruby
164
+ backtest = SQA::Backtest.new(
165
+ stock: stock,
166
+ strategy: SQA::Strategy::RSI,
167
+ initial_cash: 10_000
168
+ )
169
+
170
+ results = backtest.run
171
+ puts "Return: #{results.total_return}%"
172
+ puts "Sharpe: #{results.sharpe_ratio}"
173
+ ```
174
+
175
+ ## Data Flow
176
+
177
+ Understanding how data flows through SQA:
178
+
179
+ ![Data Flow](../assets/images/data-flow.svg)
180
+
181
+ ## Data Ordering Convention
182
+
183
+ **Critical**: TA-Lib requires data in **ascending chronological order** (oldest first).
184
+
185
+ ```ruby
186
+ # Correct order
187
+ prices = [100, 102, 105, 103, 108] # oldest → newest
188
+ # ^ ^
189
+ # index 0 index -1
190
+
191
+ # Access latest value
192
+ current_price = prices.last # or prices[-1]
193
+
194
+ # Calculate indicator
195
+ rsi = SQAI.rsi(prices, period: 14)
196
+ current_rsi = rsi.last # Most recent RSI value
197
+ ```
198
+
199
+ ## Configuration
200
+
201
+ SQA uses a hierarchical configuration system:
202
+
203
+ ```
204
+ 1. Default values (lowest priority)
205
+ 2. Environment variables (SQA_* prefix)
206
+ 3. Config file (~/.sqa.yml)
207
+ 4. Runtime settings (highest priority)
208
+ ```
209
+
210
+ **Key Settings:**
211
+ ```yaml
212
+ # ~/.sqa.yml
213
+ data_dir: ~/sqa_data
214
+ log_level: info
215
+ debug: false
216
+ verbose: false
217
+ lazy_update: false
218
+ ```
219
+
220
+ **Environment Variables:**
221
+ ```bash
222
+ export AV_API_KEY="your_alpha_vantage_key"
223
+ export SQA_DATA_DIR="~/my_data"
224
+ export SQA_DEBUG=true
225
+ ```
226
+
227
+ ## File Storage
228
+
229
+ SQA stores data in the configured data directory (default: `~/sqa_data`):
230
+
231
+ ```
232
+ ~/sqa_data/
233
+ ├── aapl.csv # Price/volume data
234
+ ├── aapl.json # Stock metadata
235
+ ├── msft.csv
236
+ ├── msft.json
237
+ └── dumbstockapi-*.csv # Ticker validation data
238
+ ```
239
+
240
+ ## Module Structure
27
241
 
28
- E -->|Test| I[Backtest]
29
- I -->|Evaluate| J[Performance Metrics]
242
+ ```
243
+ SQA
244
+ ├── Stock # Primary domain object
245
+ ├── DataFrame # Time series data wrapper
246
+ │ ├── Data # Stock metadata class
247
+ │ ├── AlphaVantage # Alpha Vantage adapter
248
+ │ └── YahooFinance # Yahoo Finance adapter
249
+ ├── Strategy # Strategy framework
250
+ │ ├── RSI # RSI strategy
251
+ │ ├── MACD # MACD strategy
252
+ │ ├── BollingerBands # Bollinger Bands strategy
253
+ │ ├── KBS # Knowledge-based system
254
+ │ └── ... # Other strategies
255
+ ├── Portfolio # Position tracking
256
+ ├── Backtest # Historical simulation
257
+ ├── Config # Configuration management
258
+ ├── Ticker # Symbol validation
259
+ └── FPOP # Future Period analysis
30
260
  ```
31
261
 
32
262
  ## Learn More
@@ -57,4 +287,47 @@ graph TB
57
287
 
58
288
  [:octicons-arrow-right-24: Strategies](../strategy.md)
59
289
 
290
+ - :material-briefcase:{ .lg .middle } __Portfolio__
291
+
292
+ ---
293
+
294
+ Track positions, P&L, and trade history
295
+
296
+ [:octicons-arrow-right-24: Portfolio](../advanced/portfolio.md)
297
+
298
+ - :material-chart-timeline:{ .lg .middle } __Backtesting__
299
+
300
+ ---
301
+
302
+ Test strategies on historical data
303
+
304
+ [:octicons-arrow-right-24: Backtesting](../advanced/backtesting.md)
305
+
306
+ - :material-cog:{ .lg .middle } __Configuration__
307
+
308
+ ---
309
+
310
+ Set up data directories and API keys
311
+
312
+ [:octicons-arrow-right-24: Installation](../getting-started/installation.md)
313
+
60
314
  </div>
315
+
316
+ ## Design Principles
317
+
318
+ ### 1. Plugin Architecture
319
+ Strategies are pluggable modules that follow a common interface. Add new strategies without modifying core code.
320
+
321
+ ### 2. Data Source Abstraction
322
+ Multiple data providers (Alpha Vantage, Yahoo Finance, CSV) share a common interface. Easy to add new sources.
323
+
324
+ ### 3. Performance First
325
+ Polars DataFrame operations are vectorized and Rust-backed. Avoid Ruby loops over data.
326
+
327
+ ### 4. Educational Focus
328
+ Clear documentation, transparent algorithms, and honest risk disclaimers.
329
+
330
+ ### 5. Separation of Concerns
331
+ - Data fetching is separate from analysis
332
+ - Indicators are separate from strategies
333
+ - Strategies are separate from execution