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,100 @@
|
|
|
1
|
+
# Distribution Day Guide
|
|
2
|
+
|
|
3
|
+
## What is a Distribution Day?
|
|
4
|
+
|
|
5
|
+
A Distribution Day occurs when a major stock index (S&P 500 or NASDAQ Composite) declines by 0.2% or more on volume that is higher than the previous trading day. This pattern indicates institutional investors are selling stocks in volume - "distributing" their holdings.
|
|
6
|
+
|
|
7
|
+
William O'Neil introduced this concept in "How to Make Money in Stocks" as one of the most reliable signals that a market uptrend is under pressure.
|
|
8
|
+
|
|
9
|
+
## Precise Rules
|
|
10
|
+
|
|
11
|
+
### Distribution Day Criteria (BOTH must be met):
|
|
12
|
+
1. **Price decline >= 0.2%** from previous session's close
|
|
13
|
+
2. **Volume > previous day's volume** (even slightly higher counts)
|
|
14
|
+
|
|
15
|
+
### Stalling Day Criteria (BOTH must be met):
|
|
16
|
+
1. **Volume > previous day's volume** (institutional activity present)
|
|
17
|
+
2. **Price gain < 0.1%** (price fails to advance meaningfully despite volume)
|
|
18
|
+
3. Stalling days count as **0.5 distribution days** in the effective count
|
|
19
|
+
|
|
20
|
+
### 25-Day Expiration Rule:
|
|
21
|
+
- A distribution day automatically expires after **25 trading days** (approximately 5 weeks)
|
|
22
|
+
- Only the rolling 25-day window matters
|
|
23
|
+
- This prevents old distribution from affecting current assessment
|
|
24
|
+
|
|
25
|
+
### What Does NOT Count as Distribution:
|
|
26
|
+
- Index declines on lower volume (normal profit-taking)
|
|
27
|
+
- Large gap-up open followed by slight closing decline (still net positive day)
|
|
28
|
+
- Volume below average (lack of institutional participation)
|
|
29
|
+
|
|
30
|
+
## Counting and Interpretation
|
|
31
|
+
|
|
32
|
+
| Effective Count | Interpretation | Action |
|
|
33
|
+
|----------------|----------------|--------|
|
|
34
|
+
| 0-1 | Healthy market | Normal operations |
|
|
35
|
+
| 2-3 | Some selling but normal | Monitor closely |
|
|
36
|
+
| 4 | O'Neil's initial warning | Tighten stops |
|
|
37
|
+
| 5 | Significant distribution | Reduce exposure |
|
|
38
|
+
| 6+ | Heavy distribution | Protect capital aggressively |
|
|
39
|
+
|
|
40
|
+
**Effective Count Formula:**
|
|
41
|
+
```
|
|
42
|
+
Effective Count = Distribution Days + (0.5 × Stalling Days)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Dual-Index Approach
|
|
46
|
+
|
|
47
|
+
This tool monitors both the S&P 500 and NASDAQ (via QQQ). The higher effective count between the two indices is used for scoring, because:
|
|
48
|
+
|
|
49
|
+
1. Distribution can concentrate in one index before the other
|
|
50
|
+
2. NASDAQ often leads due to higher growth stock concentration
|
|
51
|
+
3. The worst signal from either index is the most conservative approach
|
|
52
|
+
|
|
53
|
+
## Common Patterns at Market Tops
|
|
54
|
+
|
|
55
|
+
### Classic Distribution Sequence (2022 Example):
|
|
56
|
+
1. Week 1: One distribution day (seems harmless)
|
|
57
|
+
2. Week 2: Two more distribution days
|
|
58
|
+
3. Week 3: One stalling day (selling into rallies)
|
|
59
|
+
4. Week 4: Two more distribution days (total: 5-6 effective)
|
|
60
|
+
5. Market breaks down shortly after
|
|
61
|
+
|
|
62
|
+
### False Alarm Pattern:
|
|
63
|
+
1. Two distribution days in quick succession
|
|
64
|
+
2. Market rallies strongly, erasing concerns
|
|
65
|
+
3. Distribution days expire without reaching critical mass
|
|
66
|
+
4. Uptrend continues
|
|
67
|
+
|
|
68
|
+
### Key Distinction:
|
|
69
|
+
The **clustering** of distribution days matters. Three distribution days in one week is more alarming than three spread over five weeks.
|
|
70
|
+
|
|
71
|
+
## Follow-Through Day (FTD)
|
|
72
|
+
|
|
73
|
+
The FTD is the counterpart to distribution days - it signals a potential new uptrend after a correction.
|
|
74
|
+
|
|
75
|
+
### FTD Rules:
|
|
76
|
+
1. **Rally Attempt:** Market makes its low and begins to rally (first up day)
|
|
77
|
+
2. **Counting:** Start counting from day 1 of the rally attempt
|
|
78
|
+
3. **FTD Occurs on Day 4-7:** A significant price gain (>1.5%) with volume higher than the previous day
|
|
79
|
+
4. **Confirmation:** The FTD should be on day 4 at the earliest (premature rallies on days 1-3 are unreliable)
|
|
80
|
+
|
|
81
|
+
### FTD Reliability:
|
|
82
|
+
- Not all FTDs lead to sustained uptrends (~25% fail)
|
|
83
|
+
- Multiple FTDs within a short period increase confidence
|
|
84
|
+
- FTDs work best when combined with improving breadth
|
|
85
|
+
- O'Neil: "I never try to buy at the bottom. I wait for the Follow-Through Day."
|
|
86
|
+
|
|
87
|
+
## Practical Tips
|
|
88
|
+
|
|
89
|
+
### When Monitoring Distribution:
|
|
90
|
+
1. Check distribution count DAILY during uncertain markets
|
|
91
|
+
2. Pay special attention when count reaches 3 (pre-warning)
|
|
92
|
+
3. At 4+, begin defensive actions regardless of other signals
|
|
93
|
+
4. Don't wait for 6+ to act - by then, significant damage may be done
|
|
94
|
+
|
|
95
|
+
### Common Mistakes:
|
|
96
|
+
1. **Ignoring stalling days:** They're subtle but significant
|
|
97
|
+
2. **Resetting count manually:** Trust the 25-day expiration rule
|
|
98
|
+
3. **Using wrong volume data:** Must compare day-to-day, not vs average
|
|
99
|
+
4. **Mixing indices:** Count separately for S&P 500 and NASDAQ
|
|
100
|
+
5. **Ignoring context:** 4 distribution days in a strong uptrend is different from 4 in a range-bound market
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# 历史市场顶部分析
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
通过6组件市场顶部检测框架对主要市场顶部进行分析。这些历史案例为评分系统提供校准数据。
|
|
6
|
+
|
|
7
|
+
## 2000年:互联网泡沫顶部(2000年3月)
|
|
8
|
+
|
|
9
|
+
### 时间线
|
|
10
|
+
- **S&P 500峰值:** 2000年3月24日(1,527.46)
|
|
11
|
+
- **NASDAQ峰值:** 2000年3月10日(5,048.62)
|
|
12
|
+
- **随后跌幅:** S&P -49%,NASDAQ在2.5年内-78%
|
|
13
|
+
|
|
14
|
+
### 各组件信号(估计分数)
|
|
15
|
+
|
|
16
|
+
| 组件 | 信号级别 | 估计分数 | 备注 |
|
|
17
|
+
|-----------|-------------|------------|-------|
|
|
18
|
+
| 派发日 | 非常高 | 90-100 | 2000年3月大量派发 |
|
|
19
|
+
| 领头股 | 危急 | 85-95 | 互联网股票比指数提前数周见顶 |
|
|
20
|
+
| 防御性轮动 | 强 | 70-80 | 价值/防御股数月来跑赢 |
|
|
21
|
+
| 广度 | 严重背离 | 80-90 | 涨跌线在1998年4月就已见顶 |
|
|
22
|
+
| 指数技术面 | 正在崩溃 | 70-80 | NASDAQ首先跌破50日均线 |
|
|
23
|
+
| 情绪 | 极端 | 90-100 | IPO狂热,"新范式"叙事 |
|
|
24
|
+
|
|
25
|
+
**估计综合评分:82-92(危急)**
|
|
26
|
+
|
|
27
|
+
### 关键教训
|
|
28
|
+
广度背离是最早的信号(比顶部早近2年)。派发日和领头股崩溃是最终确认信号。当所有6个组件都亮红灯时,下跌已经开始了。
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 2007年:金融危机顶部(2007年10月)
|
|
33
|
+
|
|
34
|
+
### 时间线
|
|
35
|
+
- **S&P 500峰值:** 2007年10月9日(1,565.15)
|
|
36
|
+
- **随后跌幅:** 17个月内-57%(2009年3月低点)
|
|
37
|
+
|
|
38
|
+
### 各组件信号(估计分数)
|
|
39
|
+
|
|
40
|
+
| 组件 | 信号级别 | 估计分数 | 备注 |
|
|
41
|
+
|-----------|-------------|------------|-------|
|
|
42
|
+
| 派发日 | 高 | 75-85 | 2007年9-10月出现多个派发集群 |
|
|
43
|
+
| 领头股 | 高 | 70-80 | 房屋建筑商(ITB)在2006年2月见顶,金融股(XLF)在2007年6月见顶 |
|
|
44
|
+
| 防御性轮动 | 中等 | 55-65 | 公用事业和医疗保健跑赢 |
|
|
45
|
+
| 广度 | 背离 | 60-70 | NYSE涨跌线在2007年7月见顶 |
|
|
46
|
+
| 指数技术面 | 走弱 | 50-60 | S&P仍接近高点但内部结构恶化 |
|
|
47
|
+
| 情绪 | 偏高 | 55-65 | VIX在2006-2007年长期处于极低水平(低于12) |
|
|
48
|
+
|
|
49
|
+
**估计综合评分:62-72(红色区域)**
|
|
50
|
+
|
|
51
|
+
### 关键教训
|
|
52
|
+
2007年的顶部是一个缓慢形成的过程。领先板块(金融/住房)比S&P 500提前12-18个月见顶。综合评分在到达"红色"之前会在"橙色"区域停留数月。这个顶部奖励的是逐步减少仓位,而非单一的二元判断。
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 2018年:第四季度抛售(2018年9-12月)
|
|
57
|
+
|
|
58
|
+
### 时间线
|
|
59
|
+
- **S&P 500峰值:** 2018年9月20日(2,930.75)
|
|
60
|
+
- **随后跌幅:** -20%(回调,非熊市)
|
|
61
|
+
- **恢复:** 2018年12月V形底部,2019年4月创新高
|
|
62
|
+
|
|
63
|
+
### 各组件信号(估计分数)
|
|
64
|
+
|
|
65
|
+
| 组件 | 信号级别 | 估计分数 | 备注 |
|
|
66
|
+
|-----------|-------------|------------|-------|
|
|
67
|
+
| 派发日 | 中等 | 55-65 | 10月期间派发日累积 |
|
|
68
|
+
| 领头股 | 中等 | 50-60 | FAANG股票在不同时间见顶(FB 7月,AMZN 9月) |
|
|
69
|
+
| 防御性轮动 | 中等 | 45-55 | 第三季度公用事业跑赢 |
|
|
70
|
+
| 广度 | 轻微背离 | 40-50 | 广度收窄但不极端 |
|
|
71
|
+
| 指数技术面 | 走弱 | 55-65 | 50日均线在12月下穿200日均线 |
|
|
72
|
+
| 情绪 | 混合 | 35-45 | VIX升高但不极端 |
|
|
73
|
+
|
|
74
|
+
**估计综合评分:47-57(橙色区域)**
|
|
75
|
+
|
|
76
|
+
### 关键教训
|
|
77
|
+
这是一个典型的"回调"案例(非熊市)。综合评分正确地处于橙色区域——足以建议获利了结但不需要全面防守姿态。快速的V形恢复证明了为什么综合评分在多个组件没有极端读数时不会进入"危急"级别。
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 2022年:美联储紧缩熊市(2022年1月)
|
|
82
|
+
|
|
83
|
+
### 时间线
|
|
84
|
+
- **S&P 500峰值:** 2022年1月3日(4,796.56)
|
|
85
|
+
- **NASDAQ峰值:** 2021年11月19日(16,057.44)
|
|
86
|
+
- **随后跌幅:** S&P -25%,NASDAQ -33%
|
|
87
|
+
|
|
88
|
+
### 各组件信号(2022年1月估计分数)
|
|
89
|
+
|
|
90
|
+
| 组件 | 信号级别 | 估计分数 | 备注 |
|
|
91
|
+
|-----------|-------------|------------|-------|
|
|
92
|
+
| 派发日 | 高 | 75-90 | 2021年12月底和2022年1月初大量派发 |
|
|
93
|
+
| 领头股 | 危急 | 80-90 | ARKK在2021年2月见顶(提前11个月),许多成长股较高点下跌超50% |
|
|
94
|
+
| 防御性轮动 | 强 | 65-75 | XLU、XLP强势跑赢 |
|
|
95
|
+
| 广度 | 严重背离 | 70-80 | NASDAQ新高/新低严重背离 |
|
|
96
|
+
| 指数技术面 | 正在破位 | 60-70 | NASDAQ跌破200日均线,S&P测试关键水平 |
|
|
97
|
+
| 情绪 | 偏高 | 50-60 | 保证金债务创历史新高,加密货币投机 |
|
|
98
|
+
|
|
99
|
+
**估计综合评分:68-78(红色区域)**
|
|
100
|
+
|
|
101
|
+
### 关键教训
|
|
102
|
+
ARKK(领头股代理指标)比S&P 500提前11个月见顶。这是教科书级的Minervini信号——领头股远在指数之前就已恶化。到2022年1月,综合评分已稳固处于红色区域,正确发出了积极获利了结的信号。2022年的案例验证了"领头股健康度"组件作为早期预警信号的有效性。
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 跨案例模式
|
|
107
|
+
|
|
108
|
+
### 所有顶部的共同点:
|
|
109
|
+
1. **派发日集中出现**(非分散)在下跌前的数周内
|
|
110
|
+
2. **领头股先于指数见顶**(提前数周到数月)
|
|
111
|
+
3. **广度与指数价格背离**(上涨变得越来越窄)
|
|
112
|
+
4. **防御性轮动**随着顶部形成而加速
|
|
113
|
+
|
|
114
|
+
### 差异之处:
|
|
115
|
+
1. **严重程度:** 从-20%回调(2018年)到NASDAQ -78%暴跌(2000年)不等
|
|
116
|
+
2. **速度:** 2018年快速下跌(3个月),2000-2002年缓慢下跌(2.5年)
|
|
117
|
+
3. **恢复时间:** 2018年4个月恢复,2000年NASDAQ用了7年
|
|
118
|
+
4. **广度背离时间:** 2000年有2年的背离,2022年有数月
|
|
119
|
+
|
|
120
|
+
### 评分校准:
|
|
121
|
+
- **橙色区域(41-60):** 可能发生回调(2018年类型,-10-20%)
|
|
122
|
+
- **红色区域(61-80):** 可能发生重大下跌(2007、2022年类型,-20-35%)
|
|
123
|
+
- **危急(81-100):** 极端泡沫顶部(2000年类型,-40%+)
|
|
124
|
+
|
|
125
|
+
### 重要提示:
|
|
126
|
+
历史校准并不完美。每个市场环境都是独特的。综合评分应作为投资决策的一个输入,而非确定性预测。市场可以在"警告"区域停留很长时间后才真正下跌。
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 模式:领头股作为早期预警
|
|
131
|
+
|
|
132
|
+
来自Monty文章:
|
|
133
|
+
> 在熊市的初期阶段,某些领头股表现得好像在抵抗下跌趋势,
|
|
134
|
+
> 给人以仍然可以上涨的印象。
|
|
135
|
+
|
|
136
|
+
这种模式出现在每一个历史顶部中:
|
|
137
|
+
- **2000年:** 蓝筹科技股(MSFT、INTC)在互联网股暴跌时仍然坚挺
|
|
138
|
+
- **2007年:** 能源板块上涨而金融股崩溃
|
|
139
|
+
- **2022年:** AAPL、MSFT相对稳定而ARKK成分股暴跌
|
|
140
|
+
- **当前类比:** 一些超大型股坚挺而成长/投机股恶化
|
|
141
|
+
|
|
142
|
+
这就是为什么组件2(领头股健康度)使用一篮子成长ETF而非仅S&P 500成分股——它能捕捉到指数掩盖的恶化信号。
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# 市场顶部检测方法论
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
本框架整合了三种经过验证的市场顶部检测方法,每种方法针对机构行为的不同方面,这些行为先于重大市场下跌(10-20%回调)出现。
|
|
6
|
+
|
|
7
|
+
## 三大支柱
|
|
8
|
+
|
|
9
|
+
### 支柱1:O'Neil - 派发日累积
|
|
10
|
+
|
|
11
|
+
**来源:** William O'Neil,《How to Make Money in Stocks》
|
|
12
|
+
|
|
13
|
+
**核心概念:** 机构投资者(共同基金、对冲基金、养老金)无法在一天内卖出其大额持仓。他们的卖出会形成一种独特的模式:指数在成交量高于前一日的情况下下跌。当这些"派发日"累积时,表明聪明资金正在系统性退出。
|
|
14
|
+
|
|
15
|
+
**派发日定义:**
|
|
16
|
+
- 指数较前一交易日收盘下跌 >= 0.2%
|
|
17
|
+
- 成交量高于前一交易日
|
|
18
|
+
- 两个条件必须同时满足
|
|
19
|
+
|
|
20
|
+
**停滞日定义:**
|
|
21
|
+
- 成交量较前一日增加
|
|
22
|
+
- 但价格涨幅极小(< 0.1%)
|
|
23
|
+
- 表明机构在上涨中卖出
|
|
24
|
+
- 按半权重计算(0.5个派发日)
|
|
25
|
+
|
|
26
|
+
**25日窗口:**
|
|
27
|
+
- 派发日在25个交易日后过期
|
|
28
|
+
- 只有滚动25日计数有意义
|
|
29
|
+
- 这可以防止旧事件扭曲当前评估
|
|
30
|
+
|
|
31
|
+
**O'Neil的警告阈值:**
|
|
32
|
+
- 25个交易日内4-5个派发日 = "市场承压"
|
|
33
|
+
- 6个以上派发日 = "派发沉重,保护资本"
|
|
34
|
+
- 结合停滞日综合判断
|
|
35
|
+
|
|
36
|
+
### 支柱2:Minervini - 领头股恶化
|
|
37
|
+
|
|
38
|
+
**来源:** Mark Minervini,《Trade Like a Stock Market Wizard》/《Think & Trade Like a Champion》
|
|
39
|
+
|
|
40
|
+
**核心概念:** 市场顶部不会突然出现。它们通过一个过程发展——领头股(前一轮上涨中最强的表现者)在主要指数之前开始崩溃。这是因为机构投资者首先卖出其最大的赢家以锁定利润。
|
|
41
|
+
|
|
42
|
+
**来自Monty文章的关键观察:**
|
|
43
|
+
> "在熊市的初期阶段,某些领头股表现得好像在抵抗下跌趋势,给人以仍然可以上涨的印象。"
|
|
44
|
+
|
|
45
|
+
**检测方法:**
|
|
46
|
+
使用一篮子成长/创新ETF作为市场领导力的代理指标:
|
|
47
|
+
- ARKK(创新)、WCLD(云计算)、IGV(软件)
|
|
48
|
+
- XBI(生物科技)、SOXX/SMH(半导体)
|
|
49
|
+
- KWEB(中国科技)、TAN(太阳能)
|
|
50
|
+
|
|
51
|
+
**每个ETF的恶化信号:**
|
|
52
|
+
1. 距52周高点的距离(>10% = 令人担忧,>25% = 熊市领域)
|
|
53
|
+
2. 价格低于50日移动平均线
|
|
54
|
+
3. 价格低于200日移动平均线
|
|
55
|
+
4. 形成更低高点的模式
|
|
56
|
+
|
|
57
|
+
**放大规则:** 当60%以上的领头ETF显示恶化时,信号放大1.3倍。这反映了领导层崩溃的系统性特征。
|
|
58
|
+
|
|
59
|
+
### 支柱3:Monty - 防御性板块轮动
|
|
60
|
+
|
|
61
|
+
**来源:** monty-trader.com "美国股市 判断股市顶部的方法及下跌阶段应做之事"
|
|
62
|
+
|
|
63
|
+
**核心概念:** 在市场顶部之前,资金从进攻性/成长性板块流向防御性/价值型板块。这种"轮动"发生的原因是机构投资者在维持股票配置的同时变得更加防御。这是一个关键的早期预警信号。
|
|
64
|
+
|
|
65
|
+
**防御性板块(避险资金):**
|
|
66
|
+
- XLU(公用事业)- 稳定现金流,类似债券
|
|
67
|
+
- XLP(必需消费品)- 抗衰退需求
|
|
68
|
+
- XLV(医疗保健)- 非可选支出
|
|
69
|
+
- VNQ(房地产)- 以收入为导向
|
|
70
|
+
|
|
71
|
+
**进攻性板块(成长/风险):**
|
|
72
|
+
- XLK(科技)- 依赖增长
|
|
73
|
+
- XLC(通信服务)- 对广告支出敏感
|
|
74
|
+
- XLY(可选消费)- 对经济敏感
|
|
75
|
+
- QQQ(NASDAQ 100)- 以科技为主的成长代理
|
|
76
|
+
|
|
77
|
+
**信号:** 当防御性板块在20日滚动期间跑赢进攻性板块时,资金正在防御性流动。相对表现差距达到+3%或以上是一个强烈的警告信号。
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 补充组件
|
|
82
|
+
|
|
83
|
+
### 组件4:市场广度背离
|
|
84
|
+
|
|
85
|
+
**概念:** 当指数创新高但参与的股票越来越少时,上涨正在收窄且变得脆弱。指数价格与市场广度之间的这种"背离"是经典的顶部信号。
|
|
86
|
+
|
|
87
|
+
**关键指标:** S&P 500中高于200日移动平均线的股票百分比。
|
|
88
|
+
- 健康市场:>70%的股票高于200日均线
|
|
89
|
+
- 警告区域:50-70%且指数接近高点
|
|
90
|
+
- 危急:<50%且指数处于高位
|
|
91
|
+
|
|
92
|
+
**重要细节:** 广度背离在指数接近52周高点(在-5%以内)时最有意义。如果指数已经大幅回调,广度疲弱是意料之中的,信息量较小。
|
|
93
|
+
|
|
94
|
+
### 组件5:指数技术状况
|
|
95
|
+
|
|
96
|
+
**移动平均线结构:**
|
|
97
|
+
- 健康:价格 > 21 EMA > 50 EMA > 200 SMA
|
|
98
|
+
- 恶化:上述任何关系出现反转
|
|
99
|
+
- 看空:价格低于所有主要移动平均线
|
|
100
|
+
|
|
101
|
+
**形态识别:**
|
|
102
|
+
- 反弹失败:价格反弹但未能超过近期峰值
|
|
103
|
+
- 更低的高点:连续的波动高点持续下降
|
|
104
|
+
- 放量跳空下跌:机构恐慌性抛售
|
|
105
|
+
|
|
106
|
+
### 组件6:情绪与投机
|
|
107
|
+
|
|
108
|
+
**VIX(恐慌指数):**
|
|
109
|
+
- <12:极度自满(警告)
|
|
110
|
+
- 12-16:低波动率(轻微警告)
|
|
111
|
+
- 16-20:正常
|
|
112
|
+
- >25:恐惧升高(顶部可能性较低,回调可能已在进行中)
|
|
113
|
+
|
|
114
|
+
**看跌/看涨比率:**
|
|
115
|
+
- <0.60:极端看涨期权买入(最大程度自满)
|
|
116
|
+
- 0.60-0.70:乐观情绪偏高
|
|
117
|
+
- 0.70-0.80:温和看多
|
|
118
|
+
- >0.80:健康的谨慎
|
|
119
|
+
|
|
120
|
+
**VIX期限结构:**
|
|
121
|
+
- 陡峭正价差:市场预期平静(自满信号)
|
|
122
|
+
- 反向价差:套保需求升高(存在恐惧)
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 跟进确认日(FTD)监控
|
|
127
|
+
|
|
128
|
+
O'Neil的底部确认概念,当综合评分 > 40时相关:
|
|
129
|
+
|
|
130
|
+
1. **反弹尝试日:** 下跌后指数首次收涨的日子
|
|
131
|
+
2. **开始计数:** 潜在新上升趋势的第1天
|
|
132
|
+
3. **跟进确认日:** 在反弹尝试的第4-7天,出现强劲涨幅(1.5%+)且成交量高于前一天
|
|
133
|
+
4. **重要性:** "最强劲的上升趋势通常以第4-7天的跟进确认日开始"
|
|
134
|
+
|
|
135
|
+
**虚假FTD比率:** 大约25%的FTD会失败。多个FTD增加置信度。
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 评分理念
|
|
140
|
+
|
|
141
|
+
### 为什么使用加权综合?
|
|
142
|
+
|
|
143
|
+
没有单一指标能完美预测市场顶部。每个支柱捕捉不同的维度:
|
|
144
|
+
- 派发日:机构卖出的直接衡量
|
|
145
|
+
- 领头股:市场领导层的质量
|
|
146
|
+
- 防御性轮动:机构仓位的转变
|
|
147
|
+
- 广度:市场参与的健康度
|
|
148
|
+
- 技术面:价格结构的完整性
|
|
149
|
+
- 情绪:心理极端值
|
|
150
|
+
|
|
151
|
+
### 权重依据
|
|
152
|
+
|
|
153
|
+
- **派发日(25%):** 最直接衡量机构行为
|
|
154
|
+
- **领头股(20%):** Minervini最有信心的信号
|
|
155
|
+
- **防御性轮动(15%):** Monty的关键差异化指标
|
|
156
|
+
- **广度(15%):** 经典的确认信号
|
|
157
|
+
- **技术面(15%):** 结构完整性检查
|
|
158
|
+
- **情绪(10%):** 背景和极端值(单独使用可靠性较低)
|
|
159
|
+
|
|
160
|
+
### 校准原则
|
|
161
|
+
|
|
162
|
+
评分的校准使得:
|
|
163
|
+
- "正常"健康市场评分为10-20
|
|
164
|
+
- "早期预警"市场评分为25-40
|
|
165
|
+
- 处于"顶部形成初期到中期"的市场评分为40-55
|
|
166
|
+
- 明确的顶部形成评分为60-80
|
|
167
|
+
- 已完成的顶部伴随破位评分为80+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Market Top Detector Calculator Modules"""
|
|
2
|
+
|
|
3
|
+
from .distribution_day_calculator import calculate_distribution_days
|
|
4
|
+
from .leading_stock_calculator import calculate_leading_stock_health
|
|
5
|
+
from .defensive_rotation_calculator import calculate_defensive_rotation
|
|
6
|
+
from .breadth_calculator import calculate_breadth_divergence
|
|
7
|
+
from .index_technical_calculator import calculate_index_technical
|
|
8
|
+
from .sentiment_calculator import calculate_sentiment
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
'calculate_distribution_days',
|
|
12
|
+
'calculate_leading_stock_health',
|
|
13
|
+
'calculate_defensive_rotation',
|
|
14
|
+
'calculate_breadth_divergence',
|
|
15
|
+
'calculate_index_technical',
|
|
16
|
+
'calculate_sentiment',
|
|
17
|
+
]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Component 4: Market Breadth Divergence (Weight: 15%)
|
|
4
|
+
|
|
5
|
+
Data source: CLI arguments (collected via WebSearch before script execution)
|
|
6
|
+
- breadth_200dma: % of S&P 500 stocks above 200DMA
|
|
7
|
+
- breadth_50dma: % of S&P 500 stocks above 50DMA
|
|
8
|
+
|
|
9
|
+
Scoring logic:
|
|
10
|
+
When index is near highs (within -5% of 52-week high):
|
|
11
|
+
200DMA_above < 40% -> 100 (Critical divergence)
|
|
12
|
+
200DMA_above < 50% -> 80
|
|
13
|
+
200DMA_above < 60% -> 60
|
|
14
|
+
200DMA_above < 70% -> 35
|
|
15
|
+
200DMA_above >= 70% -> 10
|
|
16
|
+
|
|
17
|
+
When index is NOT near highs (> -5%):
|
|
18
|
+
Score is halved (breadth divergence less meaningful when index is correcting)
|
|
19
|
+
|
|
20
|
+
50DMA breadth is used as a supplementary signal.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from typing import Dict, Optional
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def calculate_breadth_divergence(breadth_200dma: Optional[float],
|
|
27
|
+
breadth_50dma: Optional[float],
|
|
28
|
+
index_distance_from_high_pct: float) -> Dict:
|
|
29
|
+
"""
|
|
30
|
+
Calculate market breadth divergence score.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
breadth_200dma: % of S&P 500 stocks above 200DMA (0-100)
|
|
34
|
+
breadth_50dma: % of S&P 500 stocks above 50DMA (0-100)
|
|
35
|
+
index_distance_from_high_pct: S&P 500 distance from 52-week high (negative %)
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Dict with score (0-100), signal, details
|
|
39
|
+
"""
|
|
40
|
+
if breadth_200dma is None:
|
|
41
|
+
return {
|
|
42
|
+
"score": 50,
|
|
43
|
+
"signal": "NO DATA: Breadth data not provided (neutral default)",
|
|
44
|
+
"data_available": False,
|
|
45
|
+
"breadth_200dma": None,
|
|
46
|
+
"breadth_50dma": breadth_50dma,
|
|
47
|
+
"index_near_highs": False,
|
|
48
|
+
"divergence_detected": False,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
index_near_highs = index_distance_from_high_pct >= -5.0
|
|
52
|
+
|
|
53
|
+
# Primary score based on 200DMA breadth
|
|
54
|
+
raw_score = _score_200dma_breadth(breadth_200dma)
|
|
55
|
+
|
|
56
|
+
# Halve score if index is NOT near highs
|
|
57
|
+
if not index_near_highs:
|
|
58
|
+
raw_score = raw_score * 0.5
|
|
59
|
+
|
|
60
|
+
# 50DMA breadth supplementary adjustment
|
|
61
|
+
if breadth_50dma is not None:
|
|
62
|
+
if breadth_50dma < 30 and index_near_highs:
|
|
63
|
+
raw_score = min(100, raw_score + 10) # Extra warning
|
|
64
|
+
elif breadth_50dma > 70:
|
|
65
|
+
raw_score = max(0, raw_score - 5) # Slight relief
|
|
66
|
+
|
|
67
|
+
score = round(min(100, max(0, raw_score)))
|
|
68
|
+
|
|
69
|
+
# Detect divergence
|
|
70
|
+
divergence_detected = index_near_highs and breadth_200dma < 60
|
|
71
|
+
|
|
72
|
+
if score >= 80:
|
|
73
|
+
signal = "CRITICAL: Severe breadth divergence - index at highs but breadth collapsing"
|
|
74
|
+
elif score >= 60:
|
|
75
|
+
signal = "WARNING: Significant breadth divergence"
|
|
76
|
+
elif score >= 35:
|
|
77
|
+
signal = "CAUTION: Mild breadth weakness"
|
|
78
|
+
elif divergence_detected:
|
|
79
|
+
signal = "WATCH: Some breadth deterioration despite index strength"
|
|
80
|
+
else:
|
|
81
|
+
signal = "HEALTHY: Breadth supports index level"
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
"score": score,
|
|
85
|
+
"signal": signal,
|
|
86
|
+
"data_available": True,
|
|
87
|
+
"breadth_200dma": breadth_200dma,
|
|
88
|
+
"breadth_50dma": breadth_50dma,
|
|
89
|
+
"index_near_highs": index_near_highs,
|
|
90
|
+
"index_distance_from_high_pct": round(index_distance_from_high_pct, 1),
|
|
91
|
+
"divergence_detected": divergence_detected,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _score_200dma_breadth(breadth_200dma: float) -> int:
|
|
96
|
+
"""Score based on % of stocks above 200DMA.
|
|
97
|
+
|
|
98
|
+
Calibrated thresholds (linearly interpolated):
|
|
99
|
+
< 40% -> 100 (Critical divergence)
|
|
100
|
+
40-50% -> 100 to 55 (Severe)
|
|
101
|
+
50-60% -> 55 to 30 (Moderate)
|
|
102
|
+
60-70% -> 30 to 5 (Mild - still relatively healthy)
|
|
103
|
+
>= 70% -> 5 (Healthy breadth)
|
|
104
|
+
|
|
105
|
+
Calibration note: 62.26% should score ~24 (healthy/green signal)
|
|
106
|
+
"""
|
|
107
|
+
if breadth_200dma < 40:
|
|
108
|
+
return 100
|
|
109
|
+
elif breadth_200dma < 50:
|
|
110
|
+
return round(100 - (breadth_200dma - 40) / 10 * 45)
|
|
111
|
+
elif breadth_200dma < 60:
|
|
112
|
+
return round(55 - (breadth_200dma - 50) / 10 * 25)
|
|
113
|
+
elif breadth_200dma < 70:
|
|
114
|
+
return round(30 - (breadth_200dma - 60) / 10 * 25)
|
|
115
|
+
else:
|
|
116
|
+
return 5
|
package/.claude/skills/market-top-detector/scripts/calculators/defensive_rotation_calculator.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Component 3: Defensive Sector Rotation (Weight: 15%)
|
|
4
|
+
|
|
5
|
+
Compares defensive ETF performance vs offensive/growth ETF performance
|
|
6
|
+
over the trailing 20 trading days.
|
|
7
|
+
|
|
8
|
+
Defensive: XLU, XLP, XLV, VNQ
|
|
9
|
+
Offensive: XLK, XLC, XLY, QQQ
|
|
10
|
+
|
|
11
|
+
Scoring (defensive_return - offensive_return):
|
|
12
|
+
+5.0% or more -> 100 (Strong rotation into defensives)
|
|
13
|
+
+3.0% or more -> 80
|
|
14
|
+
+1.5% or more -> 60
|
|
15
|
+
+0.5% or more -> 40
|
|
16
|
+
+0.0% or more -> 20
|
|
17
|
+
Negative -> 0 (Growth leading = healthy)
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from typing import Dict, List
|
|
21
|
+
|
|
22
|
+
DEFENSIVE_ETFS = ["XLU", "XLP", "XLV", "VNQ"]
|
|
23
|
+
OFFENSIVE_ETFS = ["XLK", "XLC", "XLY", "QQQ"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def calculate_defensive_rotation(historical: Dict[str, List[Dict]],
|
|
27
|
+
lookback: int = 20) -> Dict:
|
|
28
|
+
"""
|
|
29
|
+
Calculate defensive vs offensive sector rotation score.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
historical: Dict of symbol -> list of daily OHLCV (most recent first)
|
|
33
|
+
lookback: Number of trading days to measure (default 20)
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Dict with score (0-100), relative_performance, details
|
|
37
|
+
"""
|
|
38
|
+
def _calc_return(symbol_hist: List[Dict], days: int) -> float:
|
|
39
|
+
if not symbol_hist or len(symbol_hist) < days + 1:
|
|
40
|
+
return None
|
|
41
|
+
recent = symbol_hist[0].get("close", symbol_hist[0].get("adjClose", 0))
|
|
42
|
+
past = symbol_hist[days].get("close", symbol_hist[days].get("adjClose", 0))
|
|
43
|
+
if past == 0:
|
|
44
|
+
return None
|
|
45
|
+
return (recent - past) / past * 100
|
|
46
|
+
|
|
47
|
+
# Calculate average returns for each group
|
|
48
|
+
def_returns = []
|
|
49
|
+
def_details = {}
|
|
50
|
+
for symbol in DEFENSIVE_ETFS:
|
|
51
|
+
hist = historical.get(symbol, [])
|
|
52
|
+
ret = _calc_return(hist, lookback)
|
|
53
|
+
if ret is not None:
|
|
54
|
+
def_returns.append(ret)
|
|
55
|
+
def_details[symbol] = round(ret, 2)
|
|
56
|
+
|
|
57
|
+
off_returns = []
|
|
58
|
+
off_details = {}
|
|
59
|
+
for symbol in OFFENSIVE_ETFS:
|
|
60
|
+
hist = historical.get(symbol, [])
|
|
61
|
+
ret = _calc_return(hist, lookback)
|
|
62
|
+
if ret is not None:
|
|
63
|
+
off_returns.append(ret)
|
|
64
|
+
off_details[symbol] = round(ret, 2)
|
|
65
|
+
|
|
66
|
+
if not def_returns or not off_returns:
|
|
67
|
+
return {
|
|
68
|
+
"score": 50,
|
|
69
|
+
"signal": "INSUFFICIENT DATA (neutral default)",
|
|
70
|
+
"data_available": False,
|
|
71
|
+
"relative_performance": 0,
|
|
72
|
+
"defensive_avg_return": 0,
|
|
73
|
+
"offensive_avg_return": 0,
|
|
74
|
+
"defensive_details": def_details,
|
|
75
|
+
"offensive_details": off_details,
|
|
76
|
+
"lookback_days": lookback,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
def_avg = sum(def_returns) / len(def_returns)
|
|
80
|
+
off_avg = sum(off_returns) / len(off_returns)
|
|
81
|
+
relative = def_avg - off_avg
|
|
82
|
+
|
|
83
|
+
score = _score_rotation(relative)
|
|
84
|
+
|
|
85
|
+
if score >= 80:
|
|
86
|
+
signal = "CRITICAL: Strong defensive rotation"
|
|
87
|
+
elif score >= 60:
|
|
88
|
+
signal = "WARNING: Defensive outperformance"
|
|
89
|
+
elif score >= 40:
|
|
90
|
+
signal = "CAUTION: Mild defensive rotation"
|
|
91
|
+
elif score >= 20:
|
|
92
|
+
signal = "MIXED: Slight defensive tilt"
|
|
93
|
+
else:
|
|
94
|
+
signal = "HEALTHY: Growth leading"
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
"score": score,
|
|
98
|
+
"signal": signal,
|
|
99
|
+
"data_available": True,
|
|
100
|
+
"relative_performance": round(relative, 2),
|
|
101
|
+
"defensive_avg_return": round(def_avg, 2),
|
|
102
|
+
"offensive_avg_return": round(off_avg, 2),
|
|
103
|
+
"defensive_details": def_details,
|
|
104
|
+
"offensive_details": off_details,
|
|
105
|
+
"lookback_days": lookback,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _score_rotation(relative: float) -> int:
|
|
110
|
+
"""Convert relative performance (defensive - offensive) to 0-100 score"""
|
|
111
|
+
if relative >= 5.0:
|
|
112
|
+
return 100
|
|
113
|
+
elif relative >= 3.0:
|
|
114
|
+
# Linear interpolation: 3.0 -> 80, 5.0 -> 100
|
|
115
|
+
return round(80 + (relative - 3.0) / 2.0 * 20)
|
|
116
|
+
elif relative >= 1.5:
|
|
117
|
+
return round(60 + (relative - 1.5) / 1.5 * 20)
|
|
118
|
+
elif relative >= 0.5:
|
|
119
|
+
return round(40 + (relative - 0.5) / 1.0 * 20)
|
|
120
|
+
elif relative >= 0.0:
|
|
121
|
+
return round(20 + relative / 0.5 * 20)
|
|
122
|
+
else:
|
|
123
|
+
# Negative: growth leading, healthy
|
|
124
|
+
# Scale from 0 to 20 as relative goes from -2.0 to 0
|
|
125
|
+
if relative >= -2.0:
|
|
126
|
+
return round(max(0, 20 + relative / 2.0 * 20))
|
|
127
|
+
return 0
|