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,535 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Pair Trade Screener - Find Cointegrated Stock Pairs
4
+
5
+ This script screens for statistically significant pair trading opportunities by:
6
+ 1. Fetching historical price data from FMP API
7
+ 2. Calculating pairwise correlations
8
+ 3. Testing for cointegration (ADF test)
9
+ 4. Estimating half-life of mean reversion
10
+ 5. Ranking pairs by statistical strength
11
+
12
+ Usage:
13
+ # Sector-based screening
14
+ python find_pairs.py --sector Technology --min-correlation 0.70
15
+
16
+ # Custom stock list
17
+ python find_pairs.py --symbols AAPL,MSFT,GOOGL,META --min-correlation 0.75
18
+
19
+ # Full options
20
+ python find_pairs.py \\
21
+ --sector Financials \\
22
+ --min-correlation 0.70 \\
23
+ --min-market-cap 2000000000 \\
24
+ --lookback-days 730 \\
25
+ --output pairs_analysis.json \\
26
+ --api-key YOUR_KEY
27
+
28
+ Requirements:
29
+ pip install pandas numpy scipy statsmodels requests
30
+
31
+ Author: Claude Trading Skills
32
+ Version: 1.0
33
+ """
34
+
35
+ import argparse
36
+ import json
37
+ import os
38
+ import sys
39
+ import time
40
+ from datetime import datetime, timedelta
41
+ from itertools import combinations
42
+
43
+ import numpy as np
44
+ import pandas as pd
45
+ import requests
46
+ from scipy import stats
47
+ from statsmodels.tsa.ar_model import AutoReg
48
+ from statsmodels.tsa.stattools import adfuller
49
+
50
+
51
+ # =============================================================================
52
+ # FMP API Functions
53
+ # =============================================================================
54
+
55
+ def get_api_key(args_api_key):
56
+ """Get API key from args or environment variable"""
57
+ if args_api_key:
58
+ return args_api_key
59
+ api_key = os.environ.get('FMP_API_KEY')
60
+ if not api_key:
61
+ print("ERROR: FMP_API_KEY not found. Set environment variable or use --api-key")
62
+ sys.exit(1)
63
+ return api_key
64
+
65
+
66
+ def fetch_sector_stocks(sector, api_key, min_market_cap=2_000_000_000):
67
+ """Fetch stocks in a sector from FMP API"""
68
+ print(f"\n[1/5] Fetching {sector} sector stocks from FMP API...")
69
+
70
+ # Use stock screener to get sector stocks
71
+ url = f"https://financialmodelingprep.com/api/v3/stock-screener"
72
+ params = {
73
+ 'sector': sector,
74
+ 'marketCapMoreThan': min_market_cap,
75
+ 'limit': 1000,
76
+ 'apikey': api_key
77
+ }
78
+
79
+ try:
80
+ response = requests.get(url, params=params, timeout=30)
81
+ response.raise_for_status()
82
+ data = response.json()
83
+
84
+ if not data:
85
+ print(f"ERROR: No stocks found in {sector} sector with market cap > ${min_market_cap:,}")
86
+ sys.exit(1)
87
+
88
+ # Extract symbols and basic info
89
+ stocks = []
90
+ for item in data:
91
+ if item.get('isActivelyTrading', True):
92
+ stocks.append({
93
+ 'symbol': item['symbol'],
94
+ 'name': item.get('companyName', ''),
95
+ 'marketCap': item.get('marketCap', 0),
96
+ 'sector': item.get('sector', sector),
97
+ 'exchange': item.get('exchangeShortName', '')
98
+ })
99
+
100
+ print(f" → Found {len(stocks)} stocks in {sector} sector")
101
+ return stocks
102
+
103
+ except requests.exceptions.RequestException as e:
104
+ print(f"ERROR: Failed to fetch sector stocks: {e}")
105
+ sys.exit(1)
106
+
107
+
108
+ def fetch_historical_prices(symbol, api_key, lookback_days=730):
109
+ """Fetch historical adjusted close prices for a symbol"""
110
+ url = f"https://financialmodelingprep.com/api/v3/historical-price-full/{symbol}"
111
+ params = {'apikey': api_key}
112
+
113
+ try:
114
+ response = requests.get(url, params=params, timeout=30)
115
+ response.raise_for_status()
116
+ data = response.json()
117
+
118
+ if 'historical' not in data:
119
+ return None
120
+
121
+ # Extract historical prices
122
+ historical = data['historical'][:lookback_days]
123
+ historical = historical[::-1] # Reverse to chronological order
124
+
125
+ # Convert to pandas Series
126
+ prices = pd.Series(
127
+ [item['adjClose'] for item in historical],
128
+ index=[pd.to_datetime(item['date']) for item in historical],
129
+ name=symbol
130
+ )
131
+
132
+ return prices
133
+
134
+ except requests.exceptions.RequestException:
135
+ return None
136
+
137
+
138
+ def fetch_price_data_batch(symbols, api_key, lookback_days=730):
139
+ """Fetch historical prices for multiple symbols"""
140
+ print(f"\n[2/5] Fetching {lookback_days} days of price data for {len(symbols)} stocks...")
141
+
142
+ price_data = {}
143
+ failed_symbols = []
144
+
145
+ for i, symbol in enumerate(symbols, 1):
146
+ print(f" [{i}/{len(symbols)}] Fetching {symbol}...", end='', flush=True)
147
+
148
+ prices = fetch_historical_prices(symbol, api_key, lookback_days)
149
+
150
+ if prices is not None and len(prices) >= 250: # Require at least 250 days
151
+ price_data[symbol] = prices
152
+ print(f" ✓ ({len(prices)} days)")
153
+ else:
154
+ failed_symbols.append(symbol)
155
+ print(" ✗ (insufficient data)")
156
+
157
+ # Rate limiting
158
+ time.sleep(0.3)
159
+
160
+ print(f"\n → Successfully fetched {len(price_data)} stocks")
161
+ if failed_symbols:
162
+ print(f" → Failed: {', '.join(failed_symbols)}")
163
+
164
+ return price_data
165
+
166
+
167
+ # =============================================================================
168
+ # Statistical Analysis Functions
169
+ # =============================================================================
170
+
171
+ def calculate_correlation(prices_a, prices_b):
172
+ """Calculate Pearson correlation coefficient"""
173
+ # Align dates
174
+ common_dates = prices_a.index.intersection(prices_b.index)
175
+ if len(common_dates) < 100:
176
+ return None
177
+
178
+ aligned_a = prices_a.loc[common_dates]
179
+ aligned_b = prices_b.loc[common_dates]
180
+
181
+ correlation = aligned_a.corr(aligned_b)
182
+ return correlation
183
+
184
+
185
+ def calculate_beta(prices_a, prices_b):
186
+ """Calculate hedge ratio (beta) using OLS regression"""
187
+ # Align dates
188
+ common_dates = prices_a.index.intersection(prices_b.index)
189
+ aligned_a = prices_a.loc[common_dates]
190
+ aligned_b = prices_b.loc[common_dates]
191
+
192
+ # Linear regression: A = alpha + beta * B
193
+ slope, intercept, r_value, p_value, std_err = stats.linregress(aligned_b, aligned_a)
194
+
195
+ return {
196
+ 'beta': slope,
197
+ 'intercept': intercept,
198
+ 'r_squared': r_value ** 2
199
+ }
200
+
201
+
202
+ def test_cointegration(prices_a, prices_b, beta):
203
+ """Test for cointegration using Augmented Dickey-Fuller test"""
204
+ # Align dates
205
+ common_dates = prices_a.index.intersection(prices_b.index)
206
+ aligned_a = prices_a.loc[common_dates]
207
+ aligned_b = prices_b.loc[common_dates]
208
+
209
+ # Calculate spread
210
+ spread = aligned_a - (beta * aligned_b)
211
+
212
+ # ADF test
213
+ try:
214
+ result = adfuller(spread, maxlag=1, regression='c')
215
+ adf_statistic = result[0]
216
+ p_value = result[1]
217
+ critical_values = result[4]
218
+
219
+ return {
220
+ 'adf_statistic': adf_statistic,
221
+ 'p_value': p_value,
222
+ 'critical_value_1pct': critical_values['1%'],
223
+ 'critical_value_5pct': critical_values['5%'],
224
+ 'critical_value_10pct': critical_values['10%'],
225
+ 'is_cointegrated': p_value < 0.05,
226
+ 'spread': spread
227
+ }
228
+ except Exception as e:
229
+ return None
230
+
231
+
232
+ def calculate_half_life(spread):
233
+ """Estimate mean reversion half-life using AR(1) model"""
234
+ try:
235
+ # Fit AR(1) model
236
+ model = AutoReg(spread.dropna(), lags=1)
237
+ result = model.fit()
238
+
239
+ # Extract autocorrelation coefficient
240
+ phi = result.params[1]
241
+
242
+ # Calculate half-life
243
+ if phi >= 1.0 or phi <= 0:
244
+ return None # No mean reversion
245
+
246
+ half_life = -np.log(2) / np.log(phi)
247
+
248
+ return half_life
249
+
250
+ except Exception:
251
+ return None
252
+
253
+
254
+ def calculate_current_zscore(spread, window=90):
255
+ """Calculate current z-score of spread"""
256
+ if len(spread) < window:
257
+ window = len(spread)
258
+
259
+ mean = spread[-window:].mean()
260
+ std = spread[-window:].std()
261
+
262
+ if std == 0:
263
+ return None
264
+
265
+ current_spread = spread.iloc[-1]
266
+ zscore = (current_spread - mean) / std
267
+
268
+ return zscore
269
+
270
+
271
+ # =============================================================================
272
+ # Pair Analysis
273
+ # =============================================================================
274
+
275
+ def analyze_pair(symbol_a, symbol_b, prices_a, prices_b, min_correlation=0.70):
276
+ """Analyze a single pair for cointegration"""
277
+
278
+ # Step 1: Calculate correlation
279
+ correlation = calculate_correlation(prices_a, prices_b)
280
+ if correlation is None or correlation < min_correlation:
281
+ return None
282
+
283
+ # Step 2: Calculate beta (hedge ratio)
284
+ beta_result = calculate_beta(prices_a, prices_b)
285
+ beta = beta_result['beta']
286
+
287
+ # Step 3: Test for cointegration
288
+ coint_result = test_cointegration(prices_a, prices_b, beta)
289
+ if coint_result is None:
290
+ return None
291
+
292
+ # Step 4: Calculate half-life (if cointegrated)
293
+ half_life = None
294
+ if coint_result['is_cointegrated']:
295
+ half_life = calculate_half_life(coint_result['spread'])
296
+
297
+ # Step 5: Calculate current z-score
298
+ current_zscore = calculate_current_zscore(coint_result['spread'])
299
+
300
+ # Step 6: Determine trade signal
301
+ signal = 'NONE'
302
+ if current_zscore is not None:
303
+ if current_zscore > 2.0:
304
+ signal = 'SHORT' # Short A, Long B
305
+ elif current_zscore < -2.0:
306
+ signal = 'LONG' # Long A, Short B
307
+
308
+ # Step 7: Determine strength rating
309
+ strength = '☆'
310
+ if coint_result['p_value'] < 0.01:
311
+ strength = '★★★'
312
+ elif coint_result['p_value'] < 0.05:
313
+ strength = '★★'
314
+
315
+ return {
316
+ 'pair': f"{symbol_a}/{symbol_b}",
317
+ 'stock_a': symbol_a,
318
+ 'stock_b': symbol_b,
319
+ 'correlation': round(correlation, 4),
320
+ 'beta': round(beta, 4),
321
+ 'cointegration_pvalue': round(coint_result['p_value'], 4),
322
+ 'adf_statistic': round(coint_result['adf_statistic'], 4),
323
+ 'critical_value_5pct': round(coint_result['critical_value_5pct'], 4),
324
+ 'is_cointegrated': coint_result['is_cointegrated'],
325
+ 'half_life_days': round(half_life, 1) if half_life else None,
326
+ 'current_zscore': round(current_zscore, 2) if current_zscore else None,
327
+ 'signal': signal,
328
+ 'strength': strength,
329
+ 'timestamp': datetime.now().isoformat()
330
+ }
331
+
332
+
333
+ def screen_all_pairs(price_data, min_correlation=0.70):
334
+ """Screen all possible pairs from price data"""
335
+ print(f"\n[3/5] Calculating correlations and testing pairs...")
336
+
337
+ symbols = list(price_data.keys())
338
+ total_pairs = len(list(combinations(symbols, 2)))
339
+
340
+ print(f" → Total possible pairs: {total_pairs}")
341
+ print(f" → Minimum correlation: {min_correlation}")
342
+
343
+ pairs_analyzed = 0
344
+ cointegrated_pairs = []
345
+
346
+ # Analyze all combinations
347
+ for symbol_a, symbol_b in combinations(symbols, 2):
348
+ pairs_analyzed += 1
349
+
350
+ if pairs_analyzed % 10 == 0 or pairs_analyzed == total_pairs:
351
+ print(f" [{pairs_analyzed}/{total_pairs}] pairs analyzed...", end='\r', flush=True)
352
+
353
+ result = analyze_pair(
354
+ symbol_a, symbol_b,
355
+ price_data[symbol_a],
356
+ price_data[symbol_b],
357
+ min_correlation
358
+ )
359
+
360
+ if result and result['is_cointegrated']:
361
+ cointegrated_pairs.append(result)
362
+
363
+ print(f"\n → Found {len(cointegrated_pairs)} cointegrated pairs")
364
+
365
+ return cointegrated_pairs
366
+
367
+
368
+ def rank_pairs(pairs):
369
+ """Rank pairs by statistical strength"""
370
+ print(f"\n[4/5] Ranking pairs by statistical strength...")
371
+
372
+ # Sort by p-value (ascending) and then by absolute z-score (descending)
373
+ ranked = sorted(
374
+ pairs,
375
+ key=lambda x: (x['cointegration_pvalue'], -abs(x['current_zscore'] or 0))
376
+ )
377
+
378
+ print(f" → Top 10 pairs:")
379
+ for i, pair in enumerate(ranked[:10], 1):
380
+ print(f" {i}. {pair['pair']} "
381
+ f"(p={pair['cointegration_pvalue']:.4f}, "
382
+ f"z={pair['current_zscore']:.2f}, "
383
+ f"{pair['strength']})")
384
+
385
+ return ranked
386
+
387
+
388
+ # =============================================================================
389
+ # Output
390
+ # =============================================================================
391
+
392
+ def save_results(pairs, output_file):
393
+ """Save results to JSON file"""
394
+ print(f"\n[5/5] Saving results to {output_file}...")
395
+
396
+ output_data = {
397
+ 'metadata': {
398
+ 'generated_at': datetime.now().isoformat(),
399
+ 'total_pairs': len(pairs),
400
+ 'cointegrated_pairs': sum(1 for p in pairs if p['is_cointegrated']),
401
+ 'active_signals': sum(1 for p in pairs if p['signal'] != 'NONE')
402
+ },
403
+ 'pairs': pairs
404
+ }
405
+
406
+ with open(output_file, 'w') as f:
407
+ json.dump(output_data, f, indent=2)
408
+
409
+ print(f" → Saved {len(pairs)} pairs to {output_file}")
410
+ print(f" → Cointegrated pairs: {output_data['metadata']['cointegrated_pairs']}")
411
+ print(f" → Active signals: {output_data['metadata']['active_signals']}")
412
+
413
+
414
+ def print_summary(pairs):
415
+ """Print summary to console"""
416
+ print("\n" + "="*70)
417
+ print("PAIR TRADING SCREEN SUMMARY")
418
+ print("="*70)
419
+
420
+ cointegrated = [p for p in pairs if p['is_cointegrated']]
421
+ with_signals = [p for p in cointegrated if p['signal'] != 'NONE']
422
+
423
+ print(f"\nTotal pairs analyzed: {len(pairs)}")
424
+ print(f"Cointegrated pairs: {len(cointegrated)}")
425
+ print(f"Pairs with trade signals: {len(with_signals)}")
426
+
427
+ if with_signals:
428
+ print(f"\n{'='*70}")
429
+ print("ACTIVE TRADE SIGNALS")
430
+ print("="*70)
431
+
432
+ for pair in with_signals[:10]:
433
+ print(f"\nPair: {pair['pair']}")
434
+ print(f" Signal: {pair['signal']}")
435
+ print(f" Z-Score: {pair['current_zscore']:.2f}")
436
+ print(f" Correlation: {pair['correlation']:.4f}")
437
+ print(f" P-Value: {pair['cointegration_pvalue']:.4f}")
438
+ print(f" Half-Life: {pair['half_life_days']:.1f} days" if pair['half_life_days'] else " Half-Life: N/A")
439
+ print(f" Strength: {pair['strength']}")
440
+
441
+ print(f"\n{'='*70}\n")
442
+
443
+
444
+ # =============================================================================
445
+ # Main
446
+ # =============================================================================
447
+
448
+ def main():
449
+ parser = argparse.ArgumentParser(
450
+ description='Screen for cointegrated stock pairs suitable for pair trading',
451
+ formatter_class=argparse.RawDescriptionHelpFormatter,
452
+ epilog="""
453
+ Examples:
454
+ # Screen Technology sector
455
+ python find_pairs.py --sector Technology
456
+
457
+ # Custom stock list
458
+ python find_pairs.py --symbols AAPL,MSFT,GOOGL,META
459
+
460
+ # Adjust parameters
461
+ python find_pairs.py --sector Financials --min-correlation 0.75 --lookback-days 365
462
+ """
463
+ )
464
+
465
+ parser.add_argument('--sector', type=str,
466
+ help='Sector to screen (Technology, Financials, Healthcare, etc.)')
467
+ parser.add_argument('--symbols', type=str,
468
+ help='Comma-separated list of stock symbols (alternative to --sector)')
469
+ parser.add_argument('--min-correlation', type=float, default=0.70,
470
+ help='Minimum correlation threshold (default: 0.70)')
471
+ parser.add_argument('--min-market-cap', type=float, default=2_000_000_000,
472
+ help='Minimum market cap filter in dollars (default: $2B)')
473
+ parser.add_argument('--lookback-days', type=int, default=730,
474
+ help='Historical data lookback period in days (default: 730)')
475
+ parser.add_argument('--output', type=str, default='pair_analysis.json',
476
+ help='Output JSON file (default: pair_analysis.json)')
477
+ parser.add_argument('--api-key', type=str,
478
+ help='FMP API key (or set FMP_API_KEY env variable)')
479
+
480
+ args = parser.parse_args()
481
+
482
+ # Validate inputs
483
+ if not args.sector and not args.symbols:
484
+ parser.error("Either --sector or --symbols must be provided")
485
+
486
+ if args.sector and args.symbols:
487
+ parser.error("Provide either --sector or --symbols, not both")
488
+
489
+ # Get API key
490
+ api_key = get_api_key(args.api_key)
491
+
492
+ print("\n" + "="*70)
493
+ print("PAIR TRADE SCREENER")
494
+ print("="*70)
495
+ print(f"Configuration:")
496
+ print(f" Min Correlation: {args.min_correlation}")
497
+ print(f" Lookback Days: {args.lookback_days}")
498
+ print(f" Min Market Cap: ${args.min_market_cap:,.0f}")
499
+
500
+ # Get list of stocks to analyze
501
+ if args.sector:
502
+ stocks = fetch_sector_stocks(args.sector, api_key, args.min_market_cap)
503
+ symbols = [s['symbol'] for s in stocks]
504
+ else:
505
+ symbols = [s.strip().upper() for s in args.symbols.split(',')]
506
+
507
+ # Fetch price data
508
+ price_data = fetch_price_data_batch(symbols, api_key, args.lookback_days)
509
+
510
+ if len(price_data) < 2:
511
+ print("\nERROR: Need at least 2 stocks with valid data")
512
+ sys.exit(1)
513
+
514
+ # Screen all pairs
515
+ pairs = screen_all_pairs(price_data, args.min_correlation)
516
+
517
+ if not pairs:
518
+ print("\nNo cointegrated pairs found. Try:")
519
+ print(" - Lowering --min-correlation threshold")
520
+ print(" - Expanding stock universe (--sector or --symbols)")
521
+ print(" - Increasing --lookback-days")
522
+ sys.exit(0)
523
+
524
+ # Rank pairs
525
+ ranked_pairs = rank_pairs(pairs)
526
+
527
+ # Save results
528
+ save_results(ranked_pairs, args.output)
529
+
530
+ # Print summary
531
+ print_summary(ranked_pairs)
532
+
533
+
534
+ if __name__ == '__main__':
535
+ main()