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