quantwise 1.2.0 → 1.2.2

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 (362) hide show
  1. package/.claude/skills/README.md +80 -0
  2. package/.claude/skills/backtest-expert/SKILL.md +206 -0
  3. package/.claude/skills/backtest-expert/references/failed_tests.md +236 -0
  4. package/.claude/skills/backtest-expert/references/methodology.md +227 -0
  5. package/.claude/skills/breadth-chart-analyst/SKILL.md +583 -0
  6. package/.claude/skills/breadth-chart-analyst/assets/SP500_Breadth_Index_200MA_8MA.jpeg +0 -0
  7. package/.claude/skills/breadth-chart-analyst/assets/US_Stock_Market_Uptrend_Ratio.jpeg +0 -0
  8. package/.claude/skills/breadth-chart-analyst/assets/breadth_analysis_template.md +558 -0
  9. package/.claude/skills/breadth-chart-analyst/references/breadth_chart_methodology.md +590 -0
  10. package/.claude/skills/canslim-screener/SKILL.md +599 -0
  11. package/.claude/skills/canslim-screener/references/canslim_methodology.md +606 -0
  12. package/.claude/skills/canslim-screener/references/fmp_api_endpoints.md +707 -0
  13. package/.claude/skills/canslim-screener/references/interpretation_guide.md +516 -0
  14. package/.claude/skills/canslim-screener/references/scoring_system.md +597 -0
  15. package/.claude/skills/canslim-screener/scripts/calculators/earnings_calculator.py +343 -0
  16. package/.claude/skills/canslim-screener/scripts/calculators/growth_calculator.py +334 -0
  17. package/.claude/skills/canslim-screener/scripts/calculators/institutional_calculator.py +347 -0
  18. package/.claude/skills/canslim-screener/scripts/calculators/leadership_calculator.py +380 -0
  19. package/.claude/skills/canslim-screener/scripts/calculators/market_calculator.py +244 -0
  20. package/.claude/skills/canslim-screener/scripts/calculators/new_highs_calculator.py +194 -0
  21. package/.claude/skills/canslim-screener/scripts/calculators/supply_demand_calculator.py +221 -0
  22. package/.claude/skills/canslim-screener/scripts/finviz_stock_client.py +227 -0
  23. package/.claude/skills/canslim-screener/scripts/fmp_client.py +393 -0
  24. package/.claude/skills/canslim-screener/scripts/report_generator.py +405 -0
  25. package/.claude/skills/canslim-screener/scripts/scorer.py +625 -0
  26. package/.claude/skills/canslim-screener/scripts/screen_canslim.py +361 -0
  27. package/.claude/skills/canslim-screener/scripts/test_institutional_endpoint.py +109 -0
  28. package/.claude/skills/chart/SKILL.md +20 -0
  29. package/.claude/skills/dividend-growth-pullback-screener/SKILL.md +322 -0
  30. package/.claude/skills/dividend-growth-pullback-screener/references/dividend_growth_compounding.md +400 -0
  31. package/.claude/skills/dividend-growth-pullback-screener/references/fmp_api_guide.md +642 -0
  32. package/.claude/skills/dividend-growth-pullback-screener/references/rsi_oversold_strategy.md +333 -0
  33. package/.claude/skills/dividend-growth-pullback-screener/scripts/screen_dividend_growth_rsi.py +1155 -0
  34. package/.claude/skills/earnings-calendar/SKILL.md +721 -0
  35. package/.claude/skills/earnings-calendar/assets/earnings_report_template.md +102 -0
  36. package/.claude/skills/earnings-calendar/references/fmp_api_guide.md +590 -0
  37. package/.claude/skills/earnings-calendar/scripts/fetch_earnings_fmp.py +443 -0
  38. package/.claude/skills/earnings-calendar/scripts/generate_report.py +366 -0
  39. package/.claude/skills/economic-calendar-fetcher/SKILL.md +365 -0
  40. package/.claude/skills/economic-calendar-fetcher/references/fmp_api_documentation.md +345 -0
  41. package/.claude/skills/economic-calendar-fetcher/scripts/get_economic_calendar.py +267 -0
  42. package/.claude/skills/ftd-detector/SKILL.md +147 -0
  43. package/.claude/skills/ftd-detector/references/ftd_methodology.md +188 -0
  44. package/.claude/skills/ftd-detector/references/post_ftd_guide.md +185 -0
  45. package/.claude/skills/ftd-detector/scripts/fmp_client.py +158 -0
  46. package/.claude/skills/ftd-detector/scripts/ftd_detector.py +280 -0
  47. package/.claude/skills/ftd-detector/scripts/post_ftd_monitor.py +404 -0
  48. package/.claude/skills/ftd-detector/scripts/rally_tracker.py +508 -0
  49. package/.claude/skills/ftd-detector/scripts/report_generator.py +341 -0
  50. package/.claude/skills/ftd-detector/scripts/tests/conftest.py +9 -0
  51. package/.claude/skills/ftd-detector/scripts/tests/helpers.py +107 -0
  52. package/.claude/skills/ftd-detector/scripts/tests/test_post_ftd_monitor.py +311 -0
  53. package/.claude/skills/ftd-detector/scripts/tests/test_rally_tracker.py +302 -0
  54. package/.claude/skills/institutional-flow-tracker/README.md +362 -0
  55. package/.claude/skills/institutional-flow-tracker/SKILL.md +357 -0
  56. package/.claude/skills/institutional-flow-tracker/references/13f_filings_guide.md +383 -0
  57. package/.claude/skills/institutional-flow-tracker/references/institutional_investor_types.md +580 -0
  58. package/.claude/skills/institutional-flow-tracker/references/interpretation_framework.md +573 -0
  59. package/.claude/skills/institutional-flow-tracker/scripts/analyze_single_stock.py +457 -0
  60. package/.claude/skills/institutional-flow-tracker/scripts/track_institution_portfolio.py +108 -0
  61. package/.claude/skills/institutional-flow-tracker/scripts/track_institutional_flow.py +450 -0
  62. package/.claude/skills/macro-regime-detector/SKILL.md +86 -0
  63. package/.claude/skills/macro-regime-detector/references/historical_regimes.md +124 -0
  64. package/.claude/skills/macro-regime-detector/references/indicator_interpretation_guide.md +144 -0
  65. package/.claude/skills/macro-regime-detector/references/regime_detection_methodology.md +138 -0
  66. package/.claude/skills/macro-regime-detector/scripts/calculators/__init__.py +1 -0
  67. package/.claude/skills/macro-regime-detector/scripts/calculators/concentration_calculator.py +165 -0
  68. package/.claude/skills/macro-regime-detector/scripts/calculators/credit_conditions_calculator.py +124 -0
  69. package/.claude/skills/macro-regime-detector/scripts/calculators/equity_bond_calculator.py +198 -0
  70. package/.claude/skills/macro-regime-detector/scripts/calculators/sector_rotation_calculator.py +123 -0
  71. package/.claude/skills/macro-regime-detector/scripts/calculators/size_factor_calculator.py +131 -0
  72. package/.claude/skills/macro-regime-detector/scripts/calculators/utils.py +347 -0
  73. package/.claude/skills/macro-regime-detector/scripts/calculators/yield_curve_calculator.py +279 -0
  74. package/.claude/skills/macro-regime-detector/scripts/fmp_client.py +134 -0
  75. package/.claude/skills/macro-regime-detector/scripts/macro_regime_detector.py +278 -0
  76. package/.claude/skills/macro-regime-detector/scripts/report_generator.py +327 -0
  77. package/.claude/skills/macro-regime-detector/scripts/scorer.py +574 -0
  78. package/.claude/skills/macro-regime-detector/scripts/tests/conftest.py +9 -0
  79. package/.claude/skills/macro-regime-detector/scripts/tests/test_concentration.py +78 -0
  80. package/.claude/skills/macro-regime-detector/scripts/tests/test_credit_conditions.py +59 -0
  81. package/.claude/skills/macro-regime-detector/scripts/tests/test_equity_bond.py +74 -0
  82. package/.claude/skills/macro-regime-detector/scripts/tests/test_helpers.py +90 -0
  83. package/.claude/skills/macro-regime-detector/scripts/tests/test_scorer.py +439 -0
  84. package/.claude/skills/macro-regime-detector/scripts/tests/test_sector_rotation.py +78 -0
  85. package/.claude/skills/macro-regime-detector/scripts/tests/test_size_factor.py +59 -0
  86. package/.claude/skills/macro-regime-detector/scripts/tests/test_utils.py +126 -0
  87. package/.claude/skills/macro-regime-detector/scripts/tests/test_yield_curve.py +64 -0
  88. package/.claude/skills/market-breadth-analyzer/SKILL.md +121 -0
  89. package/.claude/skills/market-breadth-analyzer/references/breadth_analysis_methodology.md +168 -0
  90. package/.claude/skills/market-breadth-analyzer/scripts/calculators/__init__.py +1 -0
  91. package/.claude/skills/market-breadth-analyzer/scripts/calculators/bearish_signal_calculator.py +150 -0
  92. package/.claude/skills/market-breadth-analyzer/scripts/calculators/cycle_calculator.py +168 -0
  93. package/.claude/skills/market-breadth-analyzer/scripts/calculators/divergence_calculator.py +119 -0
  94. package/.claude/skills/market-breadth-analyzer/scripts/calculators/historical_context_calculator.py +120 -0
  95. package/.claude/skills/market-breadth-analyzer/scripts/calculators/ma_crossover_calculator.py +115 -0
  96. package/.claude/skills/market-breadth-analyzer/scripts/calculators/trend_level_calculator.py +103 -0
  97. package/.claude/skills/market-breadth-analyzer/scripts/csv_client.py +225 -0
  98. package/.claude/skills/market-breadth-analyzer/scripts/market_breadth_analyzer.py +307 -0
  99. package/.claude/skills/market-breadth-analyzer/scripts/report_generator.py +330 -0
  100. package/.claude/skills/market-breadth-analyzer/scripts/scorer.py +271 -0
  101. package/.claude/skills/market-environment-analysis/SKILL.md +139 -0
  102. package/.claude/skills/market-environment-analysis/references/analysis_patterns.md +124 -0
  103. package/.claude/skills/market-environment-analysis/references/indicators.md +99 -0
  104. package/.claude/skills/market-environment-analysis/scripts/market_utils.py +127 -0
  105. package/.claude/skills/market-news-analyst/SKILL.md +714 -0
  106. package/.claude/skills/market-news-analyst/references/corporate_news_impact.md +446 -0
  107. package/.claude/skills/market-news-analyst/references/geopolitical_commodity_correlations.md +499 -0
  108. package/.claude/skills/market-news-analyst/references/market_event_patterns.md +393 -0
  109. package/.claude/skills/market-news-analyst/references/trusted_news_sources.md +510 -0
  110. package/.claude/skills/market-top-detector/SKILL.md +159 -0
  111. package/.claude/skills/market-top-detector/references/distribution_day_guide.md +100 -0
  112. package/.claude/skills/market-top-detector/references/historical_tops.md +142 -0
  113. package/.claude/skills/market-top-detector/references/market_top_methodology.md +167 -0
  114. package/.claude/skills/market-top-detector/scripts/calculators/__init__.py +17 -0
  115. package/.claude/skills/market-top-detector/scripts/calculators/breadth_calculator.py +116 -0
  116. package/.claude/skills/market-top-detector/scripts/calculators/defensive_rotation_calculator.py +127 -0
  117. package/.claude/skills/market-top-detector/scripts/calculators/distribution_day_calculator.py +161 -0
  118. package/.claude/skills/market-top-detector/scripts/calculators/index_technical_calculator.py +254 -0
  119. package/.claude/skills/market-top-detector/scripts/calculators/leading_stock_calculator.py +198 -0
  120. package/.claude/skills/market-top-detector/scripts/calculators/sentiment_calculator.py +213 -0
  121. package/.claude/skills/market-top-detector/scripts/fmp_client.py +158 -0
  122. package/.claude/skills/market-top-detector/scripts/market_top_detector.py +349 -0
  123. package/.claude/skills/market-top-detector/scripts/report_generator.py +314 -0
  124. package/.claude/skills/market-top-detector/scripts/scorer.py +473 -0
  125. package/.claude/skills/market-top-detector/scripts/tests/conftest.py +9 -0
  126. package/.claude/skills/market-top-detector/scripts/tests/helpers.py +49 -0
  127. package/.claude/skills/market-top-detector/scripts/tests/test_breadth.py +62 -0
  128. package/.claude/skills/market-top-detector/scripts/tests/test_defensive_rotation.py +56 -0
  129. package/.claude/skills/market-top-detector/scripts/tests/test_distribution_day.py +92 -0
  130. package/.claude/skills/market-top-detector/scripts/tests/test_index_technical.py +73 -0
  131. package/.claude/skills/market-top-detector/scripts/tests/test_leading_stock.py +57 -0
  132. package/.claude/skills/market-top-detector/scripts/tests/test_scorer.py +180 -0
  133. package/.claude/skills/market-top-detector/scripts/tests/test_sentiment.py +64 -0
  134. package/.claude/skills/options-strategy-advisor/README.md +469 -0
  135. package/.claude/skills/options-strategy-advisor/SKILL.md +959 -0
  136. package/.claude/skills/options-strategy-advisor/scripts/black_scholes.py +495 -0
  137. package/.claude/skills/pair-trade-screener/README.md +389 -0
  138. package/.claude/skills/pair-trade-screener/SKILL.md +622 -0
  139. package/.claude/skills/pair-trade-screener/references/cointegration_guide.md +745 -0
  140. package/.claude/skills/pair-trade-screener/references/methodology.md +853 -0
  141. package/.claude/skills/pair-trade-screener/scripts/analyze_spread.py +394 -0
  142. package/.claude/skills/pair-trade-screener/scripts/find_pairs.py +535 -0
  143. package/.claude/skills/portfolio-manager/README.md +394 -0
  144. package/.claude/skills/portfolio-manager/SKILL.md +750 -0
  145. package/.claude/skills/portfolio-manager/references/alpaca-mcp-setup.md +367 -0
  146. package/.claude/skills/portfolio-manager/references/asset-allocation.md +502 -0
  147. package/.claude/skills/portfolio-manager/references/diversification-principles.md +553 -0
  148. package/.claude/skills/portfolio-manager/references/portfolio-risk-metrics.md +603 -0
  149. package/.claude/skills/portfolio-manager/references/position-evaluation.md +477 -0
  150. package/.claude/skills/portfolio-manager/references/rebalancing-strategies.md +715 -0
  151. package/.claude/skills/portfolio-manager/references/risk-profile-questionnaire.md +608 -0
  152. package/.claude/skills/portfolio-manager/references/target-allocations.md +558 -0
  153. package/.claude/skills/portfolio-manager/scripts/test_alpaca_connection.py +286 -0
  154. package/.claude/skills/scenario-analyzer/SKILL.md +317 -0
  155. package/.claude/skills/scenario-analyzer/references/headline_event_patterns.md +264 -0
  156. package/.claude/skills/scenario-analyzer/references/scenario_playbooks.md +320 -0
  157. package/.claude/skills/scenario-analyzer/references/sector_sensitivity_matrix.md +217 -0
  158. package/.claude/skills/sector-analyst/SKILL.md +206 -0
  159. package/.claude/skills/sector-analyst/assets/industory_performance_1.jpeg +0 -0
  160. package/.claude/skills/sector-analyst/assets/industory_performance_2.jpeg +0 -0
  161. package/.claude/skills/sector-analyst/assets/sector_performance.jpeg +0 -0
  162. package/.claude/skills/sector-analyst/references/sector_rotation.md +170 -0
  163. package/.claude/skills/stanley-druckenmiller-investment/SKILL.md +84 -0
  164. package/.claude/skills/stanley-druckenmiller-investment/references/case-studies.md +148 -0
  165. package/.claude/skills/stanley-druckenmiller-investment/references/investment-philosophy.md +80 -0
  166. package/.claude/skills/stanley-druckenmiller-investment/references/market-analysis-guide.md +146 -0
  167. package/.claude/skills/stock/NOTION_SETUP.md +33 -0
  168. package/.claude/skills/stock/SKILL.md +38 -0
  169. package/.claude/skills/technical-analyst/SKILL.md +238 -0
  170. package/.claude/skills/technical-analyst/assets/analysis_template.md +183 -0
  171. package/.claude/skills/technical-analyst/references/technical_analysis_framework.md +282 -0
  172. package/.claude/skills/theme-detector/SKILL.md +320 -0
  173. package/.claude/skills/theme-detector/assets/report_template.md +155 -0
  174. package/.claude/skills/theme-detector/references/cross_sector_themes.md +252 -0
  175. package/.claude/skills/theme-detector/references/finviz_industry_codes.md +403 -0
  176. package/.claude/skills/theme-detector/references/thematic_etf_catalog.md +333 -0
  177. package/.claude/skills/theme-detector/references/theme_detection_methodology.md +430 -0
  178. package/.claude/skills/theme-detector/scripts/calculators/__init__.py +1 -0
  179. package/.claude/skills/theme-detector/scripts/calculators/heat_calculator.py +123 -0
  180. package/.claude/skills/theme-detector/scripts/calculators/industry_ranker.py +98 -0
  181. package/.claude/skills/theme-detector/scripts/calculators/lifecycle_calculator.py +172 -0
  182. package/.claude/skills/theme-detector/scripts/calculators/theme_classifier.py +195 -0
  183. package/.claude/skills/theme-detector/scripts/calculators/theme_discoverer.py +280 -0
  184. package/.claude/skills/theme-detector/scripts/config_loader.py +142 -0
  185. package/.claude/skills/theme-detector/scripts/default_theme_config.py +254 -0
  186. package/.claude/skills/theme-detector/scripts/etf_scanner.py +609 -0
  187. package/.claude/skills/theme-detector/scripts/finviz_performance_client.py +131 -0
  188. package/.claude/skills/theme-detector/scripts/report_generator.py +490 -0
  189. package/.claude/skills/theme-detector/scripts/representative_stock_selector.py +673 -0
  190. package/.claude/skills/theme-detector/scripts/scorer.py +87 -0
  191. package/.claude/skills/theme-detector/scripts/tests/README.md +21 -0
  192. package/.claude/skills/theme-detector/scripts/tests/conftest.py +9 -0
  193. package/.claude/skills/theme-detector/scripts/tests/test_config_loader.py +239 -0
  194. package/.claude/skills/theme-detector/scripts/tests/test_etf_scanner.py +810 -0
  195. package/.claude/skills/theme-detector/scripts/tests/test_heat_calculator.py +245 -0
  196. package/.claude/skills/theme-detector/scripts/tests/test_industry_ranker.py +256 -0
  197. package/.claude/skills/theme-detector/scripts/tests/test_lifecycle_calculator.py +301 -0
  198. package/.claude/skills/theme-detector/scripts/tests/test_report_generator.py +624 -0
  199. package/.claude/skills/theme-detector/scripts/tests/test_representative_stock_selector.py +898 -0
  200. package/.claude/skills/theme-detector/scripts/tests/test_scorer.py +185 -0
  201. package/.claude/skills/theme-detector/scripts/tests/test_theme_classifier.py +534 -0
  202. package/.claude/skills/theme-detector/scripts/tests/test_theme_detector_e2e.py +467 -0
  203. package/.claude/skills/theme-detector/scripts/tests/test_theme_discoverer.py +458 -0
  204. package/.claude/skills/theme-detector/scripts/tests/test_uptrend_client.py +76 -0
  205. package/.claude/skills/theme-detector/scripts/theme_detector.py +815 -0
  206. package/.claude/skills/theme-detector/scripts/themes.yaml +168 -0
  207. package/.claude/skills/theme-detector/scripts/uptrend_client.py +241 -0
  208. package/.claude/skills/uptrend-analyzer/SKILL.md +108 -0
  209. package/.claude/skills/uptrend-analyzer/references/uptrend_methodology.md +215 -0
  210. package/.claude/skills/uptrend-analyzer/scripts/calculators/__init__.py +1 -0
  211. package/.claude/skills/uptrend-analyzer/scripts/calculators/historical_context_calculator.py +122 -0
  212. package/.claude/skills/uptrend-analyzer/scripts/calculators/market_breadth_calculator.py +145 -0
  213. package/.claude/skills/uptrend-analyzer/scripts/calculators/momentum_calculator.py +183 -0
  214. package/.claude/skills/uptrend-analyzer/scripts/calculators/sector_participation_calculator.py +204 -0
  215. package/.claude/skills/uptrend-analyzer/scripts/calculators/sector_rotation_calculator.py +218 -0
  216. package/.claude/skills/uptrend-analyzer/scripts/data_fetcher.py +236 -0
  217. package/.claude/skills/uptrend-analyzer/scripts/report_generator.py +329 -0
  218. package/.claude/skills/uptrend-analyzer/scripts/scorer.py +276 -0
  219. package/.claude/skills/uptrend-analyzer/scripts/uptrend_analyzer.py +219 -0
  220. package/.claude/skills/us-market-bubble-detector/CHANGELOG.md +118 -0
  221. package/.claude/skills/us-market-bubble-detector/SKILL.md +545 -0
  222. package/.claude/skills/us-market-bubble-detector/references/bubble_framework.md +335 -0
  223. package/.claude/skills/us-market-bubble-detector/references/historical_cases.md +327 -0
  224. package/.claude/skills/us-market-bubble-detector/references/implementation_guide.md +473 -0
  225. package/.claude/skills/us-market-bubble-detector/references/quick_reference.md +354 -0
  226. package/.claude/skills/us-market-bubble-detector/references/quick_reference_en.md +342 -0
  227. package/.claude/skills/us-market-bubble-detector/scripts/bubble_scorer.py +309 -0
  228. package/.claude/skills/us-stock-analysis/SKILL.md +294 -0
  229. package/.claude/skills/us-stock-analysis/references/financial-metrics.md +172 -0
  230. package/.claude/skills/us-stock-analysis/references/fundamental-analysis.md +129 -0
  231. package/.claude/skills/us-stock-analysis/references/report-template.md +207 -0
  232. package/.claude/skills/us-stock-analysis/references/technical-analysis.md +93 -0
  233. package/.claude/skills/value-dividend-screener/SKILL.md +562 -0
  234. package/.claude/skills/value-dividend-screener/references/fmp_api_guide.md +348 -0
  235. package/.claude/skills/value-dividend-screener/references/screening_methodology.md +315 -0
  236. package/.claude/skills/value-dividend-screener/scripts/screen_dividend_stocks.py +1138 -0
  237. package/.claude/skills/vcp-screener/SKILL.md +79 -0
  238. package/.claude/skills/vcp-screener/references/fmp_api_endpoints.md +45 -0
  239. package/.claude/skills/vcp-screener/references/scoring_system.md +154 -0
  240. package/.claude/skills/vcp-screener/references/vcp_methodology.md +124 -0
  241. package/.claude/skills/vcp-screener/scripts/calculators/__init__.py +1 -0
  242. package/.claude/skills/vcp-screener/scripts/calculators/pivot_proximity_calculator.py +139 -0
  243. package/.claude/skills/vcp-screener/scripts/calculators/relative_strength_calculator.py +161 -0
  244. package/.claude/skills/vcp-screener/scripts/calculators/trend_template_calculator.py +228 -0
  245. package/.claude/skills/vcp-screener/scripts/calculators/vcp_pattern_calculator.py +322 -0
  246. package/.claude/skills/vcp-screener/scripts/calculators/volume_pattern_calculator.py +121 -0
  247. package/.claude/skills/vcp-screener/scripts/fmp_client.py +162 -0
  248. package/.claude/skills/vcp-screener/scripts/report_generator.py +317 -0
  249. package/.claude/skills/vcp-screener/scripts/scorer.py +155 -0
  250. package/.claude/skills/vcp-screener/scripts/screen_vcp.py +536 -0
  251. package/.claude/skills/vcp-screener/scripts/tests/__init__.py +0 -0
  252. package/.claude/skills/vcp-screener/scripts/tests/conftest.py +9 -0
  253. package/.claude/skills/vcp-screener/scripts/tests/test_vcp_screener.py +834 -0
  254. package/.claude/skills/weekly-trade-strategy/.claude/agents/druckenmiller-strategy-planner.md +300 -0
  255. package/.claude/skills/weekly-trade-strategy/.claude/agents/market-news-analyzer.md +239 -0
  256. package/.claude/skills/weekly-trade-strategy/.claude/agents/technical-market-analyst.md +187 -0
  257. package/.claude/skills/weekly-trade-strategy/.claude/agents/us-market-analyst.md +218 -0
  258. package/.claude/skills/weekly-trade-strategy/.claude/agents/weekly-trade-blog-writer.md +318 -0
  259. package/.claude/skills/weekly-trade-strategy/.claude/skills/breadth-chart-analyst/SKILL.md +662 -0
  260. package/.claude/skills/weekly-trade-strategy/.claude/skills/breadth-chart-analyst/assets/SP500_Breadth_Index_200MA_8MA.jpeg +0 -0
  261. package/.claude/skills/weekly-trade-strategy/.claude/skills/breadth-chart-analyst/assets/US_Stock_Market_Uptrend_Ratio.jpeg +0 -0
  262. package/.claude/skills/weekly-trade-strategy/.claude/skills/breadth-chart-analyst/assets/breadth_analysis_template.md +558 -0
  263. package/.claude/skills/weekly-trade-strategy/.claude/skills/breadth-chart-analyst/references/breadth_chart_methodology.md +590 -0
  264. package/.claude/skills/weekly-trade-strategy/.claude/skills/earnings-calendar/SKILL.md +721 -0
  265. package/.claude/skills/weekly-trade-strategy/.claude/skills/earnings-calendar/assets/earnings_report_template.md +102 -0
  266. package/.claude/skills/weekly-trade-strategy/.claude/skills/earnings-calendar/earnings_calendar_2025-11-02.md +447 -0
  267. package/.claude/skills/weekly-trade-strategy/.claude/skills/earnings-calendar/references/fmp_api_guide.md +590 -0
  268. package/.claude/skills/weekly-trade-strategy/.claude/skills/earnings-calendar/scripts/fetch_earnings_fmp.py +443 -0
  269. package/.claude/skills/weekly-trade-strategy/.claude/skills/earnings-calendar/scripts/generate_report.py +366 -0
  270. package/.claude/skills/weekly-trade-strategy/.claude/skills/economic-calendar-fetcher/SKILL.md +365 -0
  271. package/.claude/skills/weekly-trade-strategy/.claude/skills/economic-calendar-fetcher/references/fmp_api_documentation.md +345 -0
  272. package/.claude/skills/weekly-trade-strategy/.claude/skills/economic-calendar-fetcher/scripts/get_economic_calendar.py +267 -0
  273. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-environment-analysis/SKILL.md +139 -0
  274. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-environment-analysis/references/analysis_patterns.md +124 -0
  275. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-environment-analysis/references/indicators.md +99 -0
  276. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-environment-analysis/scripts/market_utils.py +127 -0
  277. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-news-analyst/SKILL.md +714 -0
  278. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-news-analyst/references/corporate_news_impact.md +446 -0
  279. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-news-analyst/references/geopolitical_commodity_correlations.md +499 -0
  280. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-news-analyst/references/market_event_patterns.md +393 -0
  281. package/.claude/skills/weekly-trade-strategy/.claude/skills/market-news-analyst/references/trusted_news_sources.md +510 -0
  282. package/.claude/skills/weekly-trade-strategy/.claude/skills/sector-analyst/SKILL.md +206 -0
  283. package/.claude/skills/weekly-trade-strategy/.claude/skills/sector-analyst/assets/industory_performance_1.jpeg +0 -0
  284. package/.claude/skills/weekly-trade-strategy/.claude/skills/sector-analyst/assets/industory_performance_2.jpeg +0 -0
  285. package/.claude/skills/weekly-trade-strategy/.claude/skills/sector-analyst/assets/sector_performance.jpeg +0 -0
  286. package/.claude/skills/weekly-trade-strategy/.claude/skills/sector-analyst/references/sector_rotation.md +170 -0
  287. package/.claude/skills/weekly-trade-strategy/.claude/skills/stanley-druckenmiller-investment/SKILL.md +84 -0
  288. package/.claude/skills/weekly-trade-strategy/.claude/skills/stanley-druckenmiller-investment/references/case-studies.md +148 -0
  289. package/.claude/skills/weekly-trade-strategy/.claude/skills/stanley-druckenmiller-investment/references/investment-philosophy.md +80 -0
  290. package/.claude/skills/weekly-trade-strategy/.claude/skills/stanley-druckenmiller-investment/references/market-analysis-guide.md +146 -0
  291. package/.claude/skills/weekly-trade-strategy/.claude/skills/technical-analyst/SKILL.md +238 -0
  292. package/.claude/skills/weekly-trade-strategy/.claude/skills/technical-analyst/assets/analysis_template.md +183 -0
  293. package/.claude/skills/weekly-trade-strategy/.claude/skills/technical-analyst/references/technical_analysis_framework.md +282 -0
  294. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-market-bubble-detector/CHANGELOG.md +118 -0
  295. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-market-bubble-detector/SKILL.md +545 -0
  296. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-market-bubble-detector/references/bubble_framework.md +335 -0
  297. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-market-bubble-detector/references/historical_cases.md +327 -0
  298. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-market-bubble-detector/references/implementation_guide.md +473 -0
  299. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-market-bubble-detector/references/quick_reference.md +354 -0
  300. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-market-bubble-detector/references/quick_reference_en.md +342 -0
  301. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-market-bubble-detector/scripts/bubble_scorer.py +309 -0
  302. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-stock-analysis/SKILL.md +294 -0
  303. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-stock-analysis/references/financial-metrics.md +172 -0
  304. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-stock-analysis/references/fundamental-analysis.md +129 -0
  305. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-stock-analysis/references/report-template.md +207 -0
  306. package/.claude/skills/weekly-trade-strategy/.claude/skills/us-stock-analysis/references/technical-analysis.md +93 -0
  307. package/.claude/skills/weekly-trade-strategy/CLAUDE.md +454 -0
  308. package/.claude/skills/weekly-trade-strategy/README.md +287 -0
  309. package/.claude/skills/weekly-trade-strategy/blogs/.gitkeep +0 -0
  310. package/.claude/skills/weekly-trade-strategy/charts/.gitkeep +0 -0
  311. package/.claude/skills/weekly-trade-strategy/earnings_data.json +10054 -0
  312. package/.claude/skills/weekly-trade-strategy/skills/breadth-chart-analyst/SKILL.md +662 -0
  313. package/.claude/skills/weekly-trade-strategy/skills/breadth-chart-analyst/assets/SP500_Breadth_Index_200MA_8MA.jpeg +0 -0
  314. package/.claude/skills/weekly-trade-strategy/skills/breadth-chart-analyst/assets/US_Stock_Market_Uptrend_Ratio.jpeg +0 -0
  315. package/.claude/skills/weekly-trade-strategy/skills/breadth-chart-analyst/assets/breadth_analysis_template.md +558 -0
  316. package/.claude/skills/weekly-trade-strategy/skills/breadth-chart-analyst/references/breadth_chart_methodology.md +590 -0
  317. package/.claude/skills/weekly-trade-strategy/skills/earnings-calendar/SKILL.md +721 -0
  318. package/.claude/skills/weekly-trade-strategy/skills/earnings-calendar/assets/earnings_report_template.md +102 -0
  319. package/.claude/skills/weekly-trade-strategy/skills/earnings-calendar/earnings_calendar_2025-11-02.md +447 -0
  320. package/.claude/skills/weekly-trade-strategy/skills/earnings-calendar/references/fmp_api_guide.md +590 -0
  321. package/.claude/skills/weekly-trade-strategy/skills/earnings-calendar/scripts/fetch_earnings_fmp.py +443 -0
  322. package/.claude/skills/weekly-trade-strategy/skills/earnings-calendar/scripts/generate_report.py +366 -0
  323. package/.claude/skills/weekly-trade-strategy/skills/economic-calendar-fetcher/SKILL.md +365 -0
  324. package/.claude/skills/weekly-trade-strategy/skills/economic-calendar-fetcher/references/fmp_api_documentation.md +345 -0
  325. package/.claude/skills/weekly-trade-strategy/skills/economic-calendar-fetcher/scripts/get_economic_calendar.py +267 -0
  326. package/.claude/skills/weekly-trade-strategy/skills/market-environment-analysis/SKILL.md +139 -0
  327. package/.claude/skills/weekly-trade-strategy/skills/market-environment-analysis/references/analysis_patterns.md +124 -0
  328. package/.claude/skills/weekly-trade-strategy/skills/market-environment-analysis/references/indicators.md +99 -0
  329. package/.claude/skills/weekly-trade-strategy/skills/market-environment-analysis/scripts/market_utils.py +127 -0
  330. package/.claude/skills/weekly-trade-strategy/skills/market-news-analyst/SKILL.md +714 -0
  331. package/.claude/skills/weekly-trade-strategy/skills/market-news-analyst/references/corporate_news_impact.md +446 -0
  332. package/.claude/skills/weekly-trade-strategy/skills/market-news-analyst/references/geopolitical_commodity_correlations.md +499 -0
  333. package/.claude/skills/weekly-trade-strategy/skills/market-news-analyst/references/market_event_patterns.md +393 -0
  334. package/.claude/skills/weekly-trade-strategy/skills/market-news-analyst/references/trusted_news_sources.md +510 -0
  335. package/.claude/skills/weekly-trade-strategy/skills/sector-analyst/SKILL.md +206 -0
  336. package/.claude/skills/weekly-trade-strategy/skills/sector-analyst/assets/industory_performance_1.jpeg +0 -0
  337. package/.claude/skills/weekly-trade-strategy/skills/sector-analyst/assets/industory_performance_2.jpeg +0 -0
  338. package/.claude/skills/weekly-trade-strategy/skills/sector-analyst/assets/sector_performance.jpeg +0 -0
  339. package/.claude/skills/weekly-trade-strategy/skills/sector-analyst/references/sector_rotation.md +170 -0
  340. package/.claude/skills/weekly-trade-strategy/skills/stanley-druckenmiller-investment/SKILL.md +84 -0
  341. package/.claude/skills/weekly-trade-strategy/skills/stanley-druckenmiller-investment/references/case-studies.md +148 -0
  342. package/.claude/skills/weekly-trade-strategy/skills/stanley-druckenmiller-investment/references/investment-philosophy.md +80 -0
  343. package/.claude/skills/weekly-trade-strategy/skills/stanley-druckenmiller-investment/references/market-analysis-guide.md +146 -0
  344. package/.claude/skills/weekly-trade-strategy/skills/technical-analyst/SKILL.md +238 -0
  345. package/.claude/skills/weekly-trade-strategy/skills/technical-analyst/assets/analysis_template.md +183 -0
  346. package/.claude/skills/weekly-trade-strategy/skills/technical-analyst/references/technical_analysis_framework.md +282 -0
  347. package/.claude/skills/weekly-trade-strategy/skills/us-market-bubble-detector/CHANGELOG.md +118 -0
  348. package/.claude/skills/weekly-trade-strategy/skills/us-market-bubble-detector/SKILL.md +545 -0
  349. package/.claude/skills/weekly-trade-strategy/skills/us-market-bubble-detector/references/bubble_framework.md +335 -0
  350. package/.claude/skills/weekly-trade-strategy/skills/us-market-bubble-detector/references/historical_cases.md +327 -0
  351. package/.claude/skills/weekly-trade-strategy/skills/us-market-bubble-detector/references/implementation_guide.md +473 -0
  352. package/.claude/skills/weekly-trade-strategy/skills/us-market-bubble-detector/references/quick_reference.md +354 -0
  353. package/.claude/skills/weekly-trade-strategy/skills/us-market-bubble-detector/references/quick_reference_en.md +342 -0
  354. package/.claude/skills/weekly-trade-strategy/skills/us-market-bubble-detector/scripts/bubble_scorer.py +309 -0
  355. package/.claude/skills/weekly-trade-strategy/skills/us-stock-analysis/SKILL.md +294 -0
  356. package/.claude/skills/weekly-trade-strategy/skills/us-stock-analysis/references/financial-metrics.md +172 -0
  357. package/.claude/skills/weekly-trade-strategy/skills/us-stock-analysis/references/fundamental-analysis.md +129 -0
  358. package/.claude/skills/weekly-trade-strategy/skills/us-stock-analysis/references/report-template.md +207 -0
  359. package/.claude/skills/weekly-trade-strategy/skills/us-stock-analysis/references/technical-analysis.md +93 -0
  360. package/.mcp.json +3 -0
  361. package/cli.mjs +16 -16
  362. package/package.json +4 -2
@@ -0,0 +1,317 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ VCP Screener Report Generator
4
+
5
+ Generates JSON and Markdown reports for VCP screening results.
6
+
7
+ Outputs:
8
+ - JSON: Structured data for programmatic use
9
+ - Markdown: Human-readable ranked list with VCP pattern details
10
+ """
11
+
12
+ import json
13
+ from datetime import datetime
14
+ from typing import Dict, List, Optional
15
+
16
+
17
+ def generate_json_report(results: List[Dict], metadata: Dict, output_file: str,
18
+ all_results: Optional[List[Dict]] = None):
19
+ """Generate JSON report with screening results.
20
+
21
+ Args:
22
+ results: Top results to include in report detail
23
+ metadata: Screening metadata
24
+ output_file: Output file path
25
+ all_results: Full candidate list for summary stats (defaults to results)
26
+ """
27
+ report = {
28
+ "metadata": metadata,
29
+ "results": results,
30
+ "summary": _generate_summary(all_results if all_results is not None else results),
31
+ }
32
+
33
+ with open(output_file, 'w') as f:
34
+ json.dump(report, f, indent=2, default=str)
35
+
36
+ print(f" JSON report saved to: {output_file}")
37
+
38
+
39
+ def generate_markdown_report(results: List[Dict], metadata: Dict, output_file: str,
40
+ all_results: Optional[List[Dict]] = None):
41
+ """Generate Markdown report with VCP screening results.
42
+
43
+ Args:
44
+ results: Top results to include in report detail
45
+ metadata: Screening metadata
46
+ output_file: Output file path
47
+ all_results: Full candidate list for summary stats (defaults to results)
48
+ """
49
+ lines = []
50
+
51
+ # Header
52
+ lines.append("# VCP Screener Report - Minervini Volatility Contraction Pattern")
53
+ lines.append(f"**Generated:** {metadata.get('generated_at', 'N/A')}")
54
+ lines.append(f"**Universe:** {metadata.get('universe_description', 'S&P 500')}")
55
+ lines.append("")
56
+ lines.append("---")
57
+ lines.append("")
58
+
59
+ # Screening funnel
60
+ funnel = metadata.get("funnel", {})
61
+ lines.append("## Screening Funnel")
62
+ lines.append("")
63
+ lines.append(f"| Stage | Count |")
64
+ lines.append(f"|-------|-------|")
65
+ lines.append(f"| Universe | {funnel.get('universe', 'N/A')} |")
66
+ lines.append(f"| Pre-filter passed | {funnel.get('pre_filter_passed', 'N/A')} |")
67
+ lines.append(f"| Trend Template passed | {funnel.get('trend_template_passed', 'N/A')} |")
68
+ lines.append(f"| VCP candidates | {funnel.get('vcp_candidates', len(results))} |")
69
+ lines.append("")
70
+ lines.append("---")
71
+ lines.append("")
72
+
73
+ # Split results into entry_ready sections
74
+ section_a = [s for s in results if s.get("entry_ready", False)]
75
+ section_b = [s for s in results if not s.get("entry_ready", False)]
76
+
77
+ # Section A: Pre-Breakout Watchlist
78
+ lines.append("## Section A: Pre-Breakout Watchlist")
79
+ lines.append("")
80
+ if section_a:
81
+ for i, stock in enumerate(section_a, 1):
82
+ lines.extend(_format_stock_entry(i, stock))
83
+ else:
84
+ lines.append("No actionable pre-breakout candidates found.")
85
+ lines.append("")
86
+
87
+ # Section B: Extended / Quality VCP
88
+ lines.append("## Section B: Extended / Quality VCP")
89
+ lines.append("")
90
+ if section_b:
91
+ for i, stock in enumerate(section_b, 1):
92
+ lines.extend(_format_stock_entry(i, stock))
93
+ else:
94
+ lines.append("No extended VCP candidates.")
95
+ lines.append("")
96
+
97
+ # Summary statistics
98
+ lines.append("---")
99
+ lines.append("")
100
+ lines.append("## Summary Statistics")
101
+ summary_source = all_results if all_results is not None else results
102
+ summary = _generate_summary(summary_source)
103
+ lines.append(f"- **Total VCP Candidates:** {summary['total']}")
104
+ lines.append(f"- **Textbook VCP (90+):** {summary['textbook']}")
105
+ lines.append(f"- **Strong VCP (80-89):** {summary['strong']}")
106
+ lines.append(f"- **Good VCP (70-79):** {summary['good']}")
107
+ lines.append(f"- **Developing (60-69):** {summary['developing']}")
108
+ lines.append(f"- **Weak/No VCP (<60):** {summary['weak']}")
109
+ lines.append("")
110
+
111
+ # Sector distribution
112
+ sectors = {}
113
+ for stock in results:
114
+ s = stock.get("sector", "Unknown")
115
+ sectors[s] = sectors.get(s, 0) + 1
116
+
117
+ if sectors:
118
+ lines.append("### Sector Distribution")
119
+ lines.append("")
120
+ lines.append("| Sector | Count |")
121
+ lines.append("|--------|-------|")
122
+ for sector, count in sorted(sectors.items(), key=lambda x: -x[1]):
123
+ lines.append(f"| {sector} | {count} |")
124
+ lines.append("")
125
+
126
+ # API usage
127
+ api_stats = metadata.get("api_stats", {})
128
+ if api_stats:
129
+ lines.append("### API Usage")
130
+ lines.append(f"- **API Calls Made:** {api_stats.get('api_calls_made', 'N/A')}")
131
+ lines.append(f"- **Cache Entries:** {api_stats.get('cache_entries', 'N/A')}")
132
+ lines.append("")
133
+
134
+ # Methodology
135
+ lines.append("---")
136
+ lines.append("")
137
+ lines.append("## Methodology")
138
+ lines.append("")
139
+ lines.append("This screener implements Mark Minervini's Volatility Contraction Pattern (VCP):")
140
+ lines.append("")
141
+ lines.append("1. **Trend Template** (25%) - 7-point Stage 2 uptrend filter")
142
+ lines.append("2. **Contraction Quality** (25%) - VCP pattern with successive tighter corrections")
143
+ lines.append("3. **Volume Pattern** (20%) - Volume dry-up near pivot point")
144
+ lines.append("4. **Pivot Proximity** (15%) - Distance from breakout level")
145
+ lines.append("5. **Relative Strength** (15%) - Minervini-weighted RS vs S&P 500")
146
+ lines.append("")
147
+ lines.append("For detailed methodology, see `references/vcp_methodology.md`.")
148
+ lines.append("")
149
+
150
+ # Disclaimer
151
+ lines.append("---")
152
+ lines.append("")
153
+ lines.append("**Disclaimer:** This screener is for educational and informational purposes only. "
154
+ "Not investment advice. Always conduct your own research and consult a financial "
155
+ "advisor before making investment decisions. Past patterns do not guarantee future results.")
156
+ lines.append("")
157
+
158
+ with open(output_file, 'w') as f:
159
+ f.write('\n'.join(lines))
160
+
161
+ print(f" Markdown report saved to: {output_file}")
162
+
163
+
164
+ def _format_stock_entry(rank: int, stock: Dict) -> List[str]:
165
+ """Format a single stock entry for the Markdown report."""
166
+ lines = []
167
+
168
+ # Header with rating indicator
169
+ rating = stock.get("rating", "N/A")
170
+ valid_vcp = stock.get("valid_vcp", True)
171
+ indicator = _rating_indicator(stock.get("composite_score", 0), valid_vcp)
172
+ lines.append(f"### {rank}. {stock['symbol']} - {stock.get('company_name', 'N/A')} {indicator}")
173
+
174
+ # Basic info
175
+ price = stock.get("price", 0) or 0
176
+ mcap = stock.get("market_cap", 0) or 0
177
+ mcap_str = f"${mcap/1e9:.1f}B" if mcap >= 1e9 else (f"${mcap/1e6:.0f}M" if mcap > 0 else "N/A")
178
+ lines.append(f"**Price:** ${price:.2f} | **Market Cap:** {mcap_str} | "
179
+ f"**Sector:** {stock.get('sector', 'N/A')}")
180
+
181
+ # Composite score
182
+ lines.append(f"**VCP Score:** {stock.get('composite_score', 0):.1f}/100 ({rating})")
183
+ lines.append("")
184
+
185
+ # Component breakdown table
186
+ lines.append("| Component | Score | Details |")
187
+ lines.append("|-----------|-------|---------|")
188
+
189
+ # Trend Template
190
+ tt = stock.get("trend_template", {})
191
+ tt_score = tt.get("score", 0)
192
+ tt_pass = f"{tt.get('criteria_passed', 0)}/7 criteria"
193
+ ext_penalty = tt.get("extended_penalty", 0)
194
+ if ext_penalty < 0:
195
+ raw = tt.get("raw_score", tt_score)
196
+ tt_pass += f" (raw {raw:.0f}, ext {ext_penalty:+d})"
197
+ lines.append(f"| Trend Template | {tt_score:.0f}/100 | {tt_pass} |")
198
+
199
+ # Contraction Quality
200
+ vcp = stock.get("vcp_pattern", {})
201
+ vcp_score = vcp.get("score", 0)
202
+ num_c = vcp.get("num_contractions", 0)
203
+ contractions = vcp.get("contractions", [])
204
+ depths = ", ".join([f"{c['label']}={c['depth_pct']:.1f}%" for c in contractions[:4]])
205
+ lines.append(f"| Contraction Quality | {vcp_score:.0f}/100 | {num_c} contractions: {depths} |")
206
+
207
+ # Volume Pattern
208
+ vol = stock.get("volume_pattern", {})
209
+ vol_score = vol.get("score", 0)
210
+ dry_up = vol.get("dry_up_ratio")
211
+ dry_up_str = f"Dry-up: {dry_up:.2f}" if dry_up is not None else "N/A"
212
+ lines.append(f"| Volume Pattern | {vol_score:.0f}/100 | {dry_up_str} |")
213
+
214
+ # Pivot Proximity
215
+ piv = stock.get("pivot_proximity", {})
216
+ piv_score = piv.get("score", 0)
217
+ dist = piv.get("distance_from_pivot_pct")
218
+ status = piv.get("trade_status", "N/A")
219
+ dist_str = f"{dist:+.1f}% from pivot" if dist is not None else "N/A"
220
+ lines.append(f"| Pivot Proximity | {piv_score:.0f}/100 | {dist_str} ({status}) |")
221
+
222
+ # Relative Strength
223
+ rs = stock.get("relative_strength", {})
224
+ rs_score = rs.get("score", 0)
225
+ rs_rank = rs.get("rs_rank_estimate", "N/A")
226
+ weighted_rs = rs.get("weighted_rs")
227
+ rs_str = f"RS Rank ~{rs_rank}" + (f", Weighted RS: {weighted_rs:+.1f}%" if weighted_rs is not None else "")
228
+ lines.append(f"| Relative Strength | {rs_score:.0f}/100 | {rs_str} |")
229
+
230
+ lines.append("")
231
+
232
+ # Trade setup (distance-aware)
233
+ pivot_price = vcp.get("pivot_price")
234
+ stop_loss = piv.get("stop_loss_price")
235
+ risk_pct = piv.get("risk_pct")
236
+ dist = piv.get("distance_from_pivot_pct")
237
+
238
+ lines.append("**Trade Setup:**")
239
+
240
+ if dist is not None and dist > 10:
241
+ # Overextended: trade missed
242
+ lines.append(f"- Original pivot: ${pivot_price:.2f} (current price is +{dist:.1f}% above)"
243
+ if pivot_price else "- Pivot: N/A")
244
+ if risk_pct is not None:
245
+ lines.append(f"- TRADE MISSED: Entry at current level requires {risk_pct:.1f}% "
246
+ "stop distance — not a valid setup.")
247
+ else:
248
+ lines.append("- TRADE MISSED: Too far above pivot for a valid entry.")
249
+ lines.append("- Action: Wait for new base formation and a new pivot point.")
250
+ elif dist is not None and 5 < dist <= 10:
251
+ # Chase warning zone
252
+ lines.append(f"- Pivot: ${pivot_price:.2f}" if pivot_price else "- Pivot: N/A")
253
+ lines.append(f"- Stop-loss: ${stop_loss:.2f}" if stop_loss else "- Stop-loss: N/A")
254
+ lines.append(f"- Risk from current price: {risk_pct:.1f}%"
255
+ if risk_pct is not None else "- Risk: N/A")
256
+ lines.append(f"- WARNING: +{dist:.1f}% above pivot — consider waiting for pullback to pivot.")
257
+ else:
258
+ # Normal range (-8% to +5%) or below
259
+ lines.append(f"- Pivot: ${pivot_price:.2f}" if pivot_price else "- Pivot: N/A")
260
+ lines.append(f"- Stop-loss: ${stop_loss:.2f}" if stop_loss else "- Stop-loss: N/A")
261
+ lines.append(f"- Risk: {risk_pct:.1f}%" if risk_pct is not None else "- Risk: N/A")
262
+
263
+ guidance = stock.get('guidance', 'N/A')
264
+ trade_status = piv.get("trade_status", "")
265
+
266
+ if "EXTENDED" in trade_status or "OVEREXTENDED" in trade_status:
267
+ dist_val = piv.get("distance_from_pivot_pct", 0)
268
+ guidance += (f" | WARNING: Stock is +{dist_val:.1f}% above pivot - "
269
+ "Minervini advises against chasing >5% above pivot")
270
+
271
+ lines.append(f"- Guidance: {guidance}")
272
+ lines.append("")
273
+ lines.append("---")
274
+ lines.append("")
275
+
276
+ return lines
277
+
278
+
279
+ def _rating_indicator(score: float, valid_vcp: bool = True) -> str:
280
+ """Get indicator for rating."""
281
+ if not valid_vcp:
282
+ return "[PATTERN NOT CONFIRMED]"
283
+ if score >= 90:
284
+ return "[TEXTBOOK]"
285
+ elif score >= 80:
286
+ return "[STRONG]"
287
+ elif score >= 70:
288
+ return "[GOOD]"
289
+ elif score >= 60:
290
+ return "[DEVELOPING]"
291
+ else:
292
+ return ""
293
+
294
+
295
+ def _generate_summary(results: List[Dict]) -> Dict:
296
+ """Generate summary statistics based on rating (not raw composite_score).
297
+
298
+ Uses the ``rating`` field so that valid_vcp-capped stocks are counted
299
+ correctly (e.g. composite=72 but rating='Developing VCP' counts as
300
+ developing, not good).
301
+ """
302
+ total = len(results)
303
+ textbook = sum(1 for s in results if s.get("rating") == "Textbook VCP")
304
+ strong = sum(1 for s in results if s.get("rating") == "Strong VCP")
305
+ good = sum(1 for s in results if s.get("rating") == "Good VCP")
306
+ developing = sum(1 for s in results if s.get("rating") == "Developing VCP")
307
+ weak = sum(1 for s in results
308
+ if s.get("rating") in ("Weak VCP", "No VCP"))
309
+
310
+ return {
311
+ "total": total,
312
+ "textbook": textbook,
313
+ "strong": strong,
314
+ "good": good,
315
+ "developing": developing,
316
+ "weak": weak,
317
+ }
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ VCP Screener - 5-Component Composite Scoring Engine
4
+
5
+ Combines component scores into a weighted composite (0-100).
6
+
7
+ Component Weights:
8
+ 1. Trend Template: 25%
9
+ 2. Contraction Quality: 25%
10
+ 3. Volume Pattern: 20%
11
+ 4. Pivot Proximity: 15%
12
+ 5. Relative Strength: 15%
13
+ Total: 100%
14
+
15
+ Rating Bands:
16
+ 90-100: Textbook VCP - Buy at pivot, aggressive sizing
17
+ 80-89: Strong VCP - Buy at pivot, standard sizing
18
+ 70-79: Good VCP - Buy on volume confirmation
19
+ 60-69: Developing - Watchlist, wait for tighter pivot
20
+ 50-59: Weak VCP - Monitor only
21
+ <50: No VCP - Not a VCP setup
22
+ """
23
+
24
+ from typing import Dict
25
+
26
+
27
+ COMPONENT_WEIGHTS = {
28
+ "trend_template": 0.25,
29
+ "contraction_quality": 0.25,
30
+ "volume_pattern": 0.20,
31
+ "pivot_proximity": 0.15,
32
+ "relative_strength": 0.15,
33
+ }
34
+
35
+ COMPONENT_LABELS = {
36
+ "trend_template": "Trend Template (Stage 2)",
37
+ "contraction_quality": "Contraction Quality",
38
+ "volume_pattern": "Volume Pattern",
39
+ "pivot_proximity": "Pivot Proximity",
40
+ "relative_strength": "Relative Strength",
41
+ }
42
+
43
+
44
+ def calculate_composite_score(
45
+ trend_score: float,
46
+ contraction_score: float,
47
+ volume_score: float,
48
+ pivot_score: float,
49
+ rs_score: float,
50
+ valid_vcp: bool = True,
51
+ ) -> Dict:
52
+ """
53
+ Calculate weighted composite VCP score.
54
+
55
+ Args:
56
+ trend_score: Trend Template score (0-100)
57
+ contraction_score: VCP contraction quality score (0-100)
58
+ volume_score: Volume dry-up pattern score (0-100)
59
+ pivot_score: Pivot proximity score (0-100)
60
+ rs_score: Relative Strength score (0-100)
61
+ valid_vcp: Whether VCP pattern passed validation (contraction ratios)
62
+
63
+ Returns:
64
+ Dict with composite_score, rating, guidance, component breakdown
65
+ """
66
+ component_scores = {
67
+ "trend_template": trend_score,
68
+ "contraction_quality": contraction_score,
69
+ "volume_pattern": volume_score,
70
+ "pivot_proximity": pivot_score,
71
+ "relative_strength": rs_score,
72
+ }
73
+
74
+ # Calculate weighted composite
75
+ composite = 0.0
76
+ for key, weight in COMPONENT_WEIGHTS.items():
77
+ composite += component_scores[key] * weight
78
+
79
+ composite = round(composite, 1)
80
+
81
+ # Find weakest and strongest
82
+ weakest_key = min(component_scores, key=component_scores.get)
83
+ strongest_key = max(component_scores, key=component_scores.get)
84
+
85
+ # Rating
86
+ rating_info = _get_rating(composite)
87
+
88
+ # Override rating when VCP pattern is not validated (e.g. expanding contractions)
89
+ if not valid_vcp and composite >= 70:
90
+ rating_info = {
91
+ "rating": "Developing VCP",
92
+ "description": "VCP pattern not confirmed - contractions do not meet criteria",
93
+ "guidance": "Watchlist only - VCP pattern not validated, do not buy",
94
+ }
95
+
96
+ return {
97
+ "composite_score": composite,
98
+ "rating": rating_info["rating"],
99
+ "rating_description": rating_info["description"],
100
+ "guidance": rating_info["guidance"],
101
+ "valid_vcp": valid_vcp,
102
+ "weakest_component": COMPONENT_LABELS[weakest_key],
103
+ "weakest_score": component_scores[weakest_key],
104
+ "strongest_component": COMPONENT_LABELS[strongest_key],
105
+ "strongest_score": component_scores[strongest_key],
106
+ "component_breakdown": {
107
+ k: {
108
+ "score": component_scores[k],
109
+ "weight": w,
110
+ "weighted": round(component_scores[k] * w, 1),
111
+ "label": COMPONENT_LABELS[k],
112
+ }
113
+ for k, w in COMPONENT_WEIGHTS.items()
114
+ },
115
+ }
116
+
117
+
118
+ def _get_rating(composite: float) -> Dict:
119
+ """Map composite score to rating and guidance."""
120
+ if composite >= 90:
121
+ return {
122
+ "rating": "Textbook VCP",
123
+ "description": "Ideal VCP setup with all components aligned",
124
+ "guidance": "Buy at pivot, aggressive position sizing (1.5-2x normal)",
125
+ }
126
+ elif composite >= 80:
127
+ return {
128
+ "rating": "Strong VCP",
129
+ "description": "High-quality VCP with minor imperfections",
130
+ "guidance": "Buy at pivot, standard position sizing",
131
+ }
132
+ elif composite >= 70:
133
+ return {
134
+ "rating": "Good VCP",
135
+ "description": "Solid VCP pattern developing",
136
+ "guidance": "Buy on volume confirmation above pivot",
137
+ }
138
+ elif composite >= 60:
139
+ return {
140
+ "rating": "Developing VCP",
141
+ "description": "VCP forming but not yet actionable",
142
+ "guidance": "Watchlist - wait for tighter contraction near pivot",
143
+ }
144
+ elif composite >= 50:
145
+ return {
146
+ "rating": "Weak VCP",
147
+ "description": "Some VCP characteristics but incomplete",
148
+ "guidance": "Monitor only - pattern needs more development",
149
+ }
150
+ else:
151
+ return {
152
+ "rating": "No VCP",
153
+ "description": "Does not qualify as a VCP setup",
154
+ "guidance": "Not actionable as VCP",
155
+ }