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,625 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ CANSLIM Composite Scoring Engine - Phase 1 MVP
4
+
5
+ Combines individual component scores (C, A, N, M) into weighted composite score.
6
+
7
+ Phase 1 MVP Weights:
8
+ - C (Current Earnings): 27%
9
+ - A (Annual Growth): 36%
10
+ - N (Newness): 27%
11
+ - M (Market Direction): 10%
12
+ Total: 100%
13
+
14
+ Interpretation Bands:
15
+ - 90-100: Exceptional+ (rare multi-bagger setup)
16
+ - 80-89: Exceptional (outstanding fundamentals)
17
+ - 70-79: Strong (solid across all components)
18
+ - 60-69: Above Average (meets thresholds)
19
+ - 50-59: Average (marginal)
20
+ - 40-49: Below Average (one or more weak)
21
+ - <40: Weak (fails CANSLIM criteria)
22
+ """
23
+
24
+ from typing import Dict
25
+
26
+
27
+ # Phase 1 MVP component weights (renormalized from original CANSLIM)
28
+ WEIGHTS_PHASE1 = {
29
+ "C": 0.27, # Current Earnings (original 15%, renormalized to 27%)
30
+ "A": 0.36, # Annual Growth (original 20%, renormalized to 36%)
31
+ "N": 0.27, # Newness (original 15%, renormalized to 27%)
32
+ "M": 0.10 # Market Direction (original 5%, renormalized to 10%)
33
+ }
34
+
35
+ # Phase 2 component weights (6 components, renormalized excluding L)
36
+ WEIGHTS_PHASE2 = {
37
+ "C": 0.19, # Current Earnings (15% / 0.80 = 0.1875 ≈ 0.19)
38
+ "A": 0.25, # Annual Growth (20% / 0.80 = 0.25)
39
+ "N": 0.19, # Newness (15% / 0.80 = 0.1875 ≈ 0.19)
40
+ "S": 0.19, # Supply/Demand (15% / 0.80 = 0.1875 ≈ 0.19)
41
+ "I": 0.13, # Institutional (10% / 0.80 = 0.125 ≈ 0.13)
42
+ "M": 0.06 # Market Direction (5% / 0.80 = 0.0625 ≈ 0.06)
43
+ }
44
+
45
+ # Phase 3 component weights (7 components, FULL CANSLIM - Original O'Neil weights)
46
+ WEIGHTS_PHASE3 = {
47
+ "C": 0.15, # Current Earnings - 15%
48
+ "A": 0.20, # Annual Growth - 20%
49
+ "N": 0.15, # Newness - 15%
50
+ "S": 0.15, # Supply/Demand - 15%
51
+ "L": 0.20, # Leadership/RS Rank - 20% (LARGEST component!)
52
+ "I": 0.10, # Institutional - 10%
53
+ "M": 0.05 # Market Direction - 5%
54
+ }
55
+
56
+
57
+ def calculate_composite_score(c_score: float,
58
+ a_score: float,
59
+ n_score: float,
60
+ m_score: float) -> Dict:
61
+ """
62
+ Calculate weighted composite CANSLIM score for Phase 1 MVP
63
+
64
+ Args:
65
+ c_score: Current Earnings component score (0-100)
66
+ a_score: Annual Growth component score (0-100)
67
+ n_score: Newness component score (0-100)
68
+ m_score: Market Direction component score (0-100)
69
+
70
+ Returns:
71
+ Dict with:
72
+ - composite_score: Weighted average (0-100)
73
+ - rating: "Exceptional+", "Exceptional", "Strong", etc.
74
+ - rating_description: What the rating means
75
+ - guidance: Recommended action
76
+ - weakest_component: Component with lowest score
77
+ - weakest_score: Score of weakest component
78
+
79
+ Example:
80
+ >>> result = calculate_composite_score(c_score=95, a_score=90, n_score=88, m_score=100)
81
+ >>> print(f"{result['composite_score']:.1f} - {result['rating']}")
82
+ 91.2 - Exceptional+
83
+ """
84
+ # Calculate weighted composite
85
+ composite = (
86
+ c_score * WEIGHTS_PHASE1["C"] +
87
+ a_score * WEIGHTS_PHASE1["A"] +
88
+ n_score * WEIGHTS_PHASE1["N"] +
89
+ m_score * WEIGHTS_PHASE1["M"]
90
+ )
91
+
92
+ # Identify weakest component
93
+ components = {"C": c_score, "A": a_score, "N": n_score, "M": m_score}
94
+ weakest_component = min(components, key=components.get)
95
+ weakest_score = components[weakest_component]
96
+
97
+ # Get rating and interpretation
98
+ rating_info = interpret_composite_score(composite)
99
+
100
+ return {
101
+ "composite_score": round(composite, 1),
102
+ "rating": rating_info["rating"],
103
+ "rating_description": rating_info["description"],
104
+ "guidance": rating_info["guidance"],
105
+ "weakest_component": weakest_component,
106
+ "weakest_score": weakest_score,
107
+ "component_scores": {
108
+ "C": c_score,
109
+ "A": a_score,
110
+ "N": n_score,
111
+ "M": m_score
112
+ }
113
+ }
114
+
115
+
116
+ def interpret_composite_score(composite: float) -> Dict:
117
+ """
118
+ Interpret composite score and provide rating/guidance
119
+
120
+ Args:
121
+ composite: Composite score (0-100)
122
+
123
+ Returns:
124
+ Dict with rating, description, guidance
125
+ """
126
+ if composite >= 90:
127
+ return {
128
+ "rating": "Exceptional+",
129
+ "description": "Rare multi-bagger setup - all components near-perfect",
130
+ "guidance": "Immediate buy, aggressive position sizing (15-20% of portfolio)"
131
+ }
132
+ elif composite >= 80:
133
+ return {
134
+ "rating": "Exceptional",
135
+ "description": "Outstanding fundamentals + strong momentum",
136
+ "guidance": "Strong buy, standard sizing (10-15% of portfolio)"
137
+ }
138
+ elif composite >= 70:
139
+ return {
140
+ "rating": "Strong",
141
+ "description": "Solid across all components, minor weaknesses",
142
+ "guidance": "Buy, standard sizing (8-12% of portfolio)"
143
+ }
144
+ elif composite >= 60:
145
+ return {
146
+ "rating": "Above Average",
147
+ "description": "Meets thresholds, one component weak",
148
+ "guidance": "Buy on pullback, conservative sizing (5-8% of portfolio)"
149
+ }
150
+ elif composite >= 50:
151
+ return {
152
+ "rating": "Average",
153
+ "description": "Marginal CANSLIM candidate",
154
+ "guidance": "Watchlist only, consider 3-5% if high conviction"
155
+ }
156
+ elif composite >= 40:
157
+ return {
158
+ "rating": "Below Average",
159
+ "description": "Fails one or more key thresholds",
160
+ "guidance": "Monitor, do not buy"
161
+ }
162
+ else:
163
+ return {
164
+ "rating": "Weak",
165
+ "description": "Does not meet CANSLIM criteria",
166
+ "guidance": "Avoid"
167
+ }
168
+
169
+
170
+ def check_minimum_thresholds(c_score: float,
171
+ a_score: float,
172
+ n_score: float,
173
+ m_score: float) -> Dict:
174
+ """
175
+ Check if stock meets minimum CANSLIM thresholds
176
+
177
+ Minimum thresholds for "buy" consideration:
178
+ - C >= 60 (18%+ quarterly EPS growth)
179
+ - A >= 50 (25%+ annual EPS CAGR)
180
+ - N >= 40 (within 25% of 52-week high)
181
+ - M >= 40 (market not in downtrend)
182
+
183
+ Args:
184
+ c_score, a_score, n_score, m_score: Component scores
185
+
186
+ Returns:
187
+ Dict with:
188
+ - passes_all: Boolean - True if all thresholds met
189
+ - failed_components: List of components below threshold
190
+ - recommendation: "buy", "watchlist", or "avoid"
191
+ """
192
+ thresholds = {"C": 60, "A": 50, "N": 40, "M": 40}
193
+ scores = {"C": c_score, "A": a_score, "N": n_score, "M": m_score}
194
+
195
+ failed = [comp for comp, threshold in thresholds.items()
196
+ if scores[comp] < threshold]
197
+
198
+ # Special case: M score = 0 (bear market) overrides everything
199
+ if m_score == 0:
200
+ return {
201
+ "passes_all": False,
202
+ "failed_components": ["M"],
203
+ "recommendation": "avoid",
204
+ "reason": "Bear market - M component = 0. Do NOT buy regardless of C, A, N scores."
205
+ }
206
+
207
+ if not failed:
208
+ return {
209
+ "passes_all": True,
210
+ "failed_components": [],
211
+ "recommendation": "buy",
212
+ "reason": "All minimum thresholds met"
213
+ }
214
+ elif len(failed) == 1:
215
+ return {
216
+ "passes_all": False,
217
+ "failed_components": failed,
218
+ "recommendation": "watchlist",
219
+ "reason": f"One component below threshold: {failed[0]}"
220
+ }
221
+ else:
222
+ return {
223
+ "passes_all": False,
224
+ "failed_components": failed,
225
+ "recommendation": "avoid",
226
+ "reason": f"Multiple components below threshold: {', '.join(failed)}"
227
+ }
228
+
229
+
230
+ def calculate_composite_score_phase2(c_score: float,
231
+ a_score: float,
232
+ n_score: float,
233
+ s_score: float,
234
+ i_score: float,
235
+ m_score: float) -> Dict:
236
+ """
237
+ Calculate weighted composite CANSLIM score for Phase 2 (6 components)
238
+
239
+ Args:
240
+ c_score: Current Earnings component score (0-100)
241
+ a_score: Annual Growth component score (0-100)
242
+ n_score: Newness component score (0-100)
243
+ s_score: Supply/Demand component score (0-100)
244
+ i_score: Institutional component score (0-100)
245
+ m_score: Market Direction component score (0-100)
246
+
247
+ Returns:
248
+ Dict with:
249
+ - composite_score: Weighted average (0-100)
250
+ - rating: "Exceptional+", "Exceptional", "Strong", etc.
251
+ - rating_description: What the rating means
252
+ - guidance: Recommended action
253
+ - weakest_component: Component with lowest score
254
+ - weakest_score: Score of weakest component
255
+
256
+ Example:
257
+ >>> result = calculate_composite_score_phase2(
258
+ ... c_score=95, a_score=90, n_score=88, s_score=85, i_score=92, m_score=100
259
+ ... )
260
+ >>> print(f"{result['composite_score']:.1f} - {result['rating']}")
261
+ 91.0 - Exceptional+
262
+ """
263
+ # Calculate weighted composite
264
+ composite = (
265
+ c_score * WEIGHTS_PHASE2["C"] +
266
+ a_score * WEIGHTS_PHASE2["A"] +
267
+ n_score * WEIGHTS_PHASE2["N"] +
268
+ s_score * WEIGHTS_PHASE2["S"] +
269
+ i_score * WEIGHTS_PHASE2["I"] +
270
+ m_score * WEIGHTS_PHASE2["M"]
271
+ )
272
+
273
+ # Identify weakest component
274
+ components = {
275
+ "C": c_score, "A": a_score, "N": n_score,
276
+ "S": s_score, "I": i_score, "M": m_score
277
+ }
278
+ weakest_component = min(components, key=components.get)
279
+ weakest_score = components[weakest_component]
280
+
281
+ # Get rating and interpretation
282
+ rating_info = interpret_composite_score(composite)
283
+
284
+ return {
285
+ "composite_score": round(composite, 1),
286
+ "rating": rating_info["rating"],
287
+ "rating_description": rating_info["description"],
288
+ "guidance": rating_info["guidance"],
289
+ "weakest_component": weakest_component,
290
+ "weakest_score": weakest_score,
291
+ "component_scores": {
292
+ "C": c_score,
293
+ "A": a_score,
294
+ "N": n_score,
295
+ "S": s_score,
296
+ "I": i_score,
297
+ "M": m_score
298
+ }
299
+ }
300
+
301
+
302
+ def check_minimum_thresholds_phase2(c_score: float,
303
+ a_score: float,
304
+ n_score: float,
305
+ s_score: float,
306
+ i_score: float,
307
+ m_score: float) -> Dict:
308
+ """
309
+ Check if stock meets minimum CANSLIM thresholds (Phase 2: 6 components)
310
+
311
+ Minimum thresholds for "buy" consideration:
312
+ - C >= 60 (18%+ quarterly EPS growth)
313
+ - A >= 50 (25%+ annual EPS CAGR)
314
+ - N >= 40 (within 25% of 52-week high)
315
+ - S >= 40 (accumulation pattern, ratio ≥ 1.0)
316
+ - I >= 40 (30+ holders or 20%+ ownership)
317
+ - M >= 40 (market not in downtrend)
318
+
319
+ Args:
320
+ c_score, a_score, n_score, s_score, i_score, m_score: Component scores
321
+
322
+ Returns:
323
+ Dict with:
324
+ - passes_all: Boolean - True if all thresholds met
325
+ - failed_components: List of components below threshold
326
+ - recommendation: "buy", "watchlist", or "avoid"
327
+ """
328
+ thresholds = {"C": 60, "A": 50, "N": 40, "S": 40, "I": 40, "M": 40}
329
+ scores = {
330
+ "C": c_score, "A": a_score, "N": n_score,
331
+ "S": s_score, "I": i_score, "M": m_score
332
+ }
333
+
334
+ failed = [comp for comp, threshold in thresholds.items()
335
+ if scores[comp] < threshold]
336
+
337
+ # Special case: M score = 0 (bear market) overrides everything
338
+ if m_score == 0:
339
+ return {
340
+ "passes_all": False,
341
+ "failed_components": ["M"],
342
+ "recommendation": "avoid",
343
+ "reason": "Bear market - M component = 0. Do NOT buy regardless of other scores."
344
+ }
345
+
346
+ if not failed:
347
+ return {
348
+ "passes_all": True,
349
+ "failed_components": [],
350
+ "recommendation": "buy",
351
+ "reason": "All minimum thresholds met"
352
+ }
353
+ elif len(failed) == 1:
354
+ return {
355
+ "passes_all": False,
356
+ "failed_components": failed,
357
+ "recommendation": "watchlist",
358
+ "reason": f"One component below threshold: {failed[0]}"
359
+ }
360
+ else:
361
+ return {
362
+ "passes_all": False,
363
+ "failed_components": failed,
364
+ "recommendation": "avoid",
365
+ "reason": f"Multiple components below threshold: {', '.join(failed)}"
366
+ }
367
+
368
+
369
+ def calculate_composite_score_phase3(c_score: float,
370
+ a_score: float,
371
+ n_score: float,
372
+ s_score: float,
373
+ l_score: float,
374
+ i_score: float,
375
+ m_score: float) -> Dict:
376
+ """
377
+ Calculate weighted composite CANSLIM score for Phase 3 (FULL 7 components)
378
+
379
+ This is the complete CANSLIM implementation with O'Neil's original weights.
380
+
381
+ Args:
382
+ c_score: Current Earnings component score (0-100)
383
+ a_score: Annual Growth component score (0-100)
384
+ n_score: Newness component score (0-100)
385
+ s_score: Supply/Demand component score (0-100)
386
+ l_score: Leadership/RS Rank component score (0-100)
387
+ i_score: Institutional component score (0-100)
388
+ m_score: Market Direction component score (0-100)
389
+
390
+ Returns:
391
+ Dict with:
392
+ - composite_score: Weighted average (0-100)
393
+ - rating: "Exceptional+", "Exceptional", "Strong", etc.
394
+ - rating_description: What the rating means
395
+ - guidance: Recommended action
396
+ - weakest_component: Component with lowest score
397
+ - weakest_score: Score of weakest component
398
+
399
+ Example:
400
+ >>> result = calculate_composite_score_phase3(
401
+ ... c_score=95, a_score=90, n_score=88, s_score=85,
402
+ ... l_score=92, i_score=80, m_score=100
403
+ ... )
404
+ >>> print(f"{result['composite_score']:.1f} - {result['rating']}")
405
+ 89.7 - Exceptional
406
+ """
407
+ # Calculate weighted composite using FULL CANSLIM weights
408
+ composite = (
409
+ c_score * WEIGHTS_PHASE3["C"] +
410
+ a_score * WEIGHTS_PHASE3["A"] +
411
+ n_score * WEIGHTS_PHASE3["N"] +
412
+ s_score * WEIGHTS_PHASE3["S"] +
413
+ l_score * WEIGHTS_PHASE3["L"] +
414
+ i_score * WEIGHTS_PHASE3["I"] +
415
+ m_score * WEIGHTS_PHASE3["M"]
416
+ )
417
+
418
+ # Identify weakest component
419
+ components = {
420
+ "C": c_score, "A": a_score, "N": n_score,
421
+ "S": s_score, "L": l_score, "I": i_score, "M": m_score
422
+ }
423
+ weakest_component = min(components, key=components.get)
424
+ weakest_score = components[weakest_component]
425
+
426
+ # Get rating and interpretation
427
+ rating_info = interpret_composite_score(composite)
428
+
429
+ return {
430
+ "composite_score": round(composite, 1),
431
+ "rating": rating_info["rating"],
432
+ "rating_description": rating_info["description"],
433
+ "guidance": rating_info["guidance"],
434
+ "weakest_component": weakest_component,
435
+ "weakest_score": weakest_score,
436
+ "component_scores": {
437
+ "C": c_score,
438
+ "A": a_score,
439
+ "N": n_score,
440
+ "S": s_score,
441
+ "L": l_score,
442
+ "I": i_score,
443
+ "M": m_score
444
+ }
445
+ }
446
+
447
+
448
+ def check_minimum_thresholds_phase3(c_score: float,
449
+ a_score: float,
450
+ n_score: float,
451
+ s_score: float,
452
+ l_score: float,
453
+ i_score: float,
454
+ m_score: float) -> Dict:
455
+ """
456
+ Check if stock meets minimum CANSLIM thresholds (Phase 3: FULL 7 components)
457
+
458
+ Minimum thresholds for "buy" consideration:
459
+ - C >= 60 (18%+ quarterly EPS growth)
460
+ - A >= 50 (25%+ annual EPS CAGR)
461
+ - N >= 40 (within 25% of 52-week high)
462
+ - S >= 40 (accumulation pattern, ratio >= 1.0)
463
+ - L >= 50 (RS Rank 60+, outperforming market)
464
+ - I >= 40 (30+ holders or 20%+ ownership)
465
+ - M >= 40 (market not in downtrend)
466
+
467
+ Args:
468
+ c_score, a_score, n_score, s_score, l_score, i_score, m_score: Component scores
469
+
470
+ Returns:
471
+ Dict with:
472
+ - passes_all: Boolean - True if all thresholds met
473
+ - failed_components: List of components below threshold
474
+ - recommendation: "buy", "watchlist", or "avoid"
475
+ """
476
+ thresholds = {
477
+ "C": 60, "A": 50, "N": 40,
478
+ "S": 40, "L": 50, "I": 40, "M": 40
479
+ }
480
+ scores = {
481
+ "C": c_score, "A": a_score, "N": n_score,
482
+ "S": s_score, "L": l_score, "I": i_score, "M": m_score
483
+ }
484
+
485
+ failed = [comp for comp, threshold in thresholds.items()
486
+ if scores[comp] < threshold]
487
+
488
+ # Special case: M score = 0 (bear market) overrides everything
489
+ if m_score == 0:
490
+ return {
491
+ "passes_all": False,
492
+ "failed_components": ["M"],
493
+ "recommendation": "avoid",
494
+ "reason": "Bear market - M component = 0. Do NOT buy regardless of other scores."
495
+ }
496
+
497
+ # Special case: L score < 40 (major laggard) - strong warning
498
+ if l_score < 40:
499
+ if "L" not in failed:
500
+ failed.append("L")
501
+ return {
502
+ "passes_all": False,
503
+ "failed_components": failed,
504
+ "recommendation": "avoid",
505
+ "reason": f"Stock significantly underperforming market (L={l_score}). CANSLIM requires market leaders."
506
+ }
507
+
508
+ if not failed:
509
+ return {
510
+ "passes_all": True,
511
+ "failed_components": [],
512
+ "recommendation": "buy",
513
+ "reason": "All 7 CANSLIM thresholds met - Full methodology validation"
514
+ }
515
+ elif len(failed) == 1:
516
+ return {
517
+ "passes_all": False,
518
+ "failed_components": failed,
519
+ "recommendation": "watchlist",
520
+ "reason": f"One component below threshold: {failed[0]}"
521
+ }
522
+ else:
523
+ return {
524
+ "passes_all": False,
525
+ "failed_components": failed,
526
+ "recommendation": "avoid",
527
+ "reason": f"Multiple components below threshold: {', '.join(failed)}"
528
+ }
529
+
530
+
531
+ def compare_to_full_canslim(phase1_score: float) -> Dict:
532
+ """
533
+ Estimate what Phase 1 MVP score would be with full 7-component CANSLIM
534
+
535
+ Phase 1 (4 components) represents 55% of full CANSLIM methodology.
536
+ This function estimates the equivalent full CANSLIM score.
537
+
538
+ Args:
539
+ phase1_score: Phase 1 composite score (0-100)
540
+
541
+ Returns:
542
+ Dict with:
543
+ - estimated_full_score: Estimated score with all 7 components (0-200 scale)
544
+ - equivalent_rating: Rating on full CANSLIM scale
545
+ - note: Explanation of estimation
546
+ """
547
+ # Phase 1 score 80+ typically indicates exceptional fundamentals
548
+ # In full CANSLIM, this would likely score 140-160+ (top tier)
549
+ if phase1_score >= 90:
550
+ estimated_range = "160-200"
551
+ equivalent_rating = "Exceptional"
552
+ elif phase1_score >= 80:
553
+ estimated_range = "140-159"
554
+ equivalent_rating = "Strong"
555
+ elif phase1_score >= 70:
556
+ estimated_range = "120-139"
557
+ equivalent_rating = "Above Average"
558
+ elif phase1_score >= 60:
559
+ estimated_range = "105-119"
560
+ equivalent_rating = "Average"
561
+ else:
562
+ estimated_range = "<105"
563
+ equivalent_rating = "Below Average"
564
+
565
+ return {
566
+ "phase1_score": phase1_score,
567
+ "estimated_full_range": estimated_range,
568
+ "equivalent_rating": equivalent_rating,
569
+ "note": ("Phase 1 implements 4 of 7 components (55% of methodology). "
570
+ "Full CANSLIM (Phases 2-3) will add S, L, I components.")
571
+ }
572
+
573
+
574
+ # Example usage and testing
575
+ if __name__ == "__main__":
576
+ print("Testing CANSLIM Scorer (Phase 1 MVP)...\n")
577
+
578
+ # Test 1: Exceptional stock (NVDA-like)
579
+ print("Test 1: Exceptional Stock (All Components Strong)")
580
+ result1 = calculate_composite_score(c_score=100, a_score=95, n_score=98, m_score=100)
581
+ print(f" Composite Score: {result1['composite_score']}/100")
582
+ print(f" Rating: {result1['rating']}")
583
+ print(f" Description: {result1['rating_description']}")
584
+ print(f" Guidance: {result1['guidance']}")
585
+ print(f" Weakest Component: {result1['weakest_component']} ({result1['weakest_score']})\n")
586
+
587
+ full1 = compare_to_full_canslim(result1['composite_score'])
588
+ print(f" Estimated Full CANSLIM Range: {full1['estimated_full_range']}\n")
589
+
590
+ # Test 2: Strong stock (META-like)
591
+ print("Test 2: Strong Stock (Most Components Good)")
592
+ result2 = calculate_composite_score(c_score=85, a_score=78, n_score=88, m_score=80)
593
+ print(f" Composite Score: {result2['composite_score']}/100")
594
+ print(f" Rating: {result2['rating']}")
595
+ print(f" Weakest Component: {result2['weakest_component']} ({result2['weakest_score']})\n")
596
+
597
+ # Test 3: Average stock (marginal)
598
+ print("Test 3: Average Stock (Meets Minimums)")
599
+ result3 = calculate_composite_score(c_score=60, a_score=55, n_score=65, m_score=60)
600
+ print(f" Composite Score: {result3['composite_score']}/100")
601
+ print(f" Rating: {result3['rating']}")
602
+ print(f" Guidance: {result3['guidance']}\n")
603
+
604
+ # Test 4: Bear market scenario (M=0)
605
+ print("Test 4: Bear Market Scenario (M=0 Override)")
606
+ result4 = calculate_composite_score(c_score=95, a_score=90, n_score=92, m_score=0)
607
+ print(f" Composite Score: {result4['composite_score']}/100")
608
+ print(f" Rating: {result4['rating']}")
609
+
610
+ threshold_check = check_minimum_thresholds(c_score=95, a_score=90, n_score=92, m_score=0)
611
+ print(f" Threshold Check: {threshold_check['recommendation']}")
612
+ print(f" Reason: {threshold_check['reason']}\n")
613
+
614
+ # Test 5: Minimum threshold checking
615
+ print("Test 5: Threshold Validation")
616
+ threshold_pass = check_minimum_thresholds(c_score=70, a_score=60, n_score=65, m_score=70)
617
+ print(f" All thresholds met: {threshold_pass['passes_all']}")
618
+ print(f" Recommendation: {threshold_pass['recommendation']}\n")
619
+
620
+ threshold_fail = check_minimum_thresholds(c_score=50, a_score=45, n_score=35, m_score=60)
621
+ print(f" All thresholds met: {threshold_fail['passes_all']}")
622
+ print(f" Failed components: {threshold_fail['failed_components']}")
623
+ print(f" Recommendation: {threshold_fail['recommendation']}")
624
+
625
+ print("\n✓ All tests completed")