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,347 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
I Component - Institutional Sponsorship Calculator (Full Implementation)
|
|
4
|
+
|
|
5
|
+
Calculates CANSLIM 'I' component score based on institutional holder count and ownership percentage.
|
|
6
|
+
|
|
7
|
+
O'Neil's Rule: "You need some of the big boys on your side. Look for stocks with increasing
|
|
8
|
+
institutional sponsorship, but not too much. The sweet spot is 50-100 institutional holders
|
|
9
|
+
with 30-60% ownership."
|
|
10
|
+
|
|
11
|
+
Key Principles:
|
|
12
|
+
- 50-100 holders: Enough interest, not overcrowded
|
|
13
|
+
- 30-60% ownership: Strong backing without lock-up
|
|
14
|
+
- <30%: Underowned (potential upside, but may lack institutional support)
|
|
15
|
+
- >80%: Overcrowded (no buying power left, vulnerable to selling)
|
|
16
|
+
- Superinvestors (Berkshire, Baupost, etc.): Quality signal
|
|
17
|
+
|
|
18
|
+
Scoring:
|
|
19
|
+
- 100 points: 50-100 holders + 30-60% ownership (O'Neil's sweet spot)
|
|
20
|
+
- 90 points: Superinvestor present + good holder count
|
|
21
|
+
- 80 points: 30-50 holders + 20-40% ownership OR 100-150 holders + 40-70% ownership
|
|
22
|
+
- 60 points: Acceptable but suboptimal ranges
|
|
23
|
+
- 40 points: <20% or >80% ownership
|
|
24
|
+
- 20 points: <10% or >90% ownership
|
|
25
|
+
- 0 points: Institutional data unavailable or extreme ranges
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from typing import Dict, List, Optional
|
|
29
|
+
import sys
|
|
30
|
+
import os
|
|
31
|
+
|
|
32
|
+
# Optional: Import Finviz client for fallback data (requires finviz library)
|
|
33
|
+
try:
|
|
34
|
+
# Add parent directory to path to import finviz_stock_client
|
|
35
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
|
36
|
+
from finviz_stock_client import FinvizStockClient
|
|
37
|
+
FINVIZ_AVAILABLE = True
|
|
38
|
+
except ImportError:
|
|
39
|
+
FINVIZ_AVAILABLE = False
|
|
40
|
+
print("INFO: finviz library not available. Install with 'pip install finviz' for improved institutional data.", file=sys.stderr)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# List of superinvestors (legendary value investors whose presence signals quality)
|
|
44
|
+
SUPERINVESTORS = [
|
|
45
|
+
"BERKSHIRE HATHAWAY",
|
|
46
|
+
"BAUPOST GROUP",
|
|
47
|
+
"PERSHING SQUARE",
|
|
48
|
+
"GREENLIGHT CAPITAL",
|
|
49
|
+
"THIRD POINT",
|
|
50
|
+
"APPALOOSA MANAGEMENT",
|
|
51
|
+
"VIKING GLOBAL",
|
|
52
|
+
"SCION ASSET MANAGEMENT", # Michael Burry
|
|
53
|
+
"BRIDGEWATER ASSOCIATES", # Ray Dalio
|
|
54
|
+
"RENAISSANCE TECHNOLOGIES"
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def calculate_institutional_sponsorship(
|
|
59
|
+
institutional_holders: List[Dict],
|
|
60
|
+
profile: Optional[Dict] = None,
|
|
61
|
+
symbol: Optional[str] = None,
|
|
62
|
+
use_finviz_fallback: bool = True
|
|
63
|
+
) -> Dict:
|
|
64
|
+
"""
|
|
65
|
+
Calculate institutional sponsorship score (Full Implementation with Finviz fallback)
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
institutional_holders: List of institutional holders from FMP API
|
|
69
|
+
Each entry: {"holder": str, "shares": int, "dateReported": str, "change": int}
|
|
70
|
+
profile: Company profile dict (optional, for shares outstanding)
|
|
71
|
+
symbol: Stock ticker symbol (optional, required for Finviz fallback)
|
|
72
|
+
use_finviz_fallback: If True, use Finviz data when FMP ownership % unavailable (default: True)
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Dict with:
|
|
76
|
+
- score: 0-100 points
|
|
77
|
+
- num_holders: Number of institutional holders
|
|
78
|
+
- ownership_pct: Institutional ownership percentage
|
|
79
|
+
- superinvestor_present: True if superinvestor detected
|
|
80
|
+
- superinvestors: List of superinvestors holding the stock
|
|
81
|
+
- total_shares_held: Total shares held by institutions
|
|
82
|
+
- shares_outstanding: Total shares outstanding (from profile)
|
|
83
|
+
- interpretation: Human-readable interpretation
|
|
84
|
+
- quality_warning: Warning if data quality issues
|
|
85
|
+
- error: Error message if calculation failed
|
|
86
|
+
|
|
87
|
+
Example:
|
|
88
|
+
>>> holders = client.get_institutional_holders("NVDA")
|
|
89
|
+
>>> profile = client.get_profile("NVDA")[0]
|
|
90
|
+
>>> result = calculate_institutional_sponsorship(holders, profile)
|
|
91
|
+
>>> print(f"I Score: {result['score']}, Holders: {result['num_holders']}, Ownership: {result['ownership_pct']:.1f}%")
|
|
92
|
+
"""
|
|
93
|
+
# Validate input
|
|
94
|
+
if not institutional_holders:
|
|
95
|
+
return {
|
|
96
|
+
"score": 0,
|
|
97
|
+
"error": "No institutional holder data available",
|
|
98
|
+
"num_holders": 0,
|
|
99
|
+
"ownership_pct": None,
|
|
100
|
+
"superinvestor_present": False,
|
|
101
|
+
"superinvestors": [],
|
|
102
|
+
"total_shares_held": None,
|
|
103
|
+
"shares_outstanding": None,
|
|
104
|
+
"interpretation": "Data unavailable"
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Count institutional holders
|
|
108
|
+
num_holders = len(institutional_holders)
|
|
109
|
+
|
|
110
|
+
# Check for superinvestors
|
|
111
|
+
superinvestors_found = []
|
|
112
|
+
for holder_entry in institutional_holders:
|
|
113
|
+
holder_name = holder_entry.get("holder", "").upper()
|
|
114
|
+
for superinvestor in SUPERINVESTORS:
|
|
115
|
+
if superinvestor in holder_name:
|
|
116
|
+
superinvestors_found.append(holder_entry.get("holder"))
|
|
117
|
+
break
|
|
118
|
+
|
|
119
|
+
superinvestor_present = len(superinvestors_found) > 0
|
|
120
|
+
|
|
121
|
+
# Calculate total shares held by institutions
|
|
122
|
+
total_shares_held = sum(
|
|
123
|
+
holder.get("shares", 0) for holder in institutional_holders
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Calculate ownership percentage (requires shares outstanding from profile)
|
|
127
|
+
ownership_pct = None
|
|
128
|
+
shares_outstanding = None
|
|
129
|
+
quality_warning = None
|
|
130
|
+
data_source = "FMP" # Track data source
|
|
131
|
+
|
|
132
|
+
if profile:
|
|
133
|
+
# Try to get shares outstanding (different field names possible)
|
|
134
|
+
shares_outstanding = profile.get("sharesOutstanding")
|
|
135
|
+
|
|
136
|
+
# Fallback: calculate from market cap and price
|
|
137
|
+
if not shares_outstanding:
|
|
138
|
+
market_cap = profile.get("marketCap")
|
|
139
|
+
price = profile.get("price")
|
|
140
|
+
if market_cap and price and price > 0:
|
|
141
|
+
shares_outstanding = market_cap / price
|
|
142
|
+
|
|
143
|
+
if shares_outstanding and shares_outstanding > 0:
|
|
144
|
+
ownership_pct = (total_shares_held / shares_outstanding) * 100
|
|
145
|
+
else:
|
|
146
|
+
quality_warning = "Shares outstanding unavailable from FMP."
|
|
147
|
+
else:
|
|
148
|
+
quality_warning = "Company profile not provided."
|
|
149
|
+
|
|
150
|
+
# Finviz fallback: If ownership % still unavailable, try Finviz
|
|
151
|
+
if ownership_pct is None and use_finviz_fallback and FINVIZ_AVAILABLE and symbol:
|
|
152
|
+
try:
|
|
153
|
+
finviz_client = FinvizStockClient(rate_limit_seconds=1.0)
|
|
154
|
+
finviz_data = finviz_client.get_institutional_ownership(symbol)
|
|
155
|
+
|
|
156
|
+
if finviz_data and finviz_data.get('inst_own_pct') is not None:
|
|
157
|
+
ownership_pct = finviz_data['inst_own_pct']
|
|
158
|
+
data_source = "Finviz"
|
|
159
|
+
quality_warning = f"Using Finviz institutional ownership data ({ownership_pct:.1f}%) - FMP shares outstanding unavailable."
|
|
160
|
+
print(f"✅ Using Finviz institutional ownership for {symbol}: {ownership_pct:.1f}%", file=sys.stderr)
|
|
161
|
+
else:
|
|
162
|
+
quality_warning += " Finviz fallback also unavailable. Score reduced by 50%."
|
|
163
|
+
except Exception as e:
|
|
164
|
+
print(f"WARNING: Finviz fallback failed for {symbol}: {e}", file=sys.stderr)
|
|
165
|
+
quality_warning += " Finviz fallback failed. Score reduced by 50%."
|
|
166
|
+
|
|
167
|
+
# Final warning if ownership % still unavailable
|
|
168
|
+
if ownership_pct is None:
|
|
169
|
+
if not quality_warning:
|
|
170
|
+
quality_warning = "Ownership % unavailable from all sources. Score reduced by 50%."
|
|
171
|
+
else:
|
|
172
|
+
quality_warning += " Score reduced by 50%."
|
|
173
|
+
|
|
174
|
+
# Score institutional sponsorship
|
|
175
|
+
score = score_institutional_sponsorship(
|
|
176
|
+
num_holders, ownership_pct, superinvestor_present, quality_warning
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Generate interpretation
|
|
180
|
+
interpretation = interpret_institutional_sponsorship(
|
|
181
|
+
num_holders, ownership_pct, superinvestor_present, superinvestors_found
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
"score": score,
|
|
186
|
+
"num_holders": num_holders,
|
|
187
|
+
"ownership_pct": ownership_pct,
|
|
188
|
+
"superinvestor_present": superinvestor_present,
|
|
189
|
+
"superinvestors": superinvestors_found,
|
|
190
|
+
"total_shares_held": total_shares_held,
|
|
191
|
+
"shares_outstanding": shares_outstanding,
|
|
192
|
+
"interpretation": interpretation,
|
|
193
|
+
"quality_warning": quality_warning,
|
|
194
|
+
"data_source": data_source # "FMP" or "Finviz"
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def score_institutional_sponsorship(
|
|
199
|
+
num_holders: int,
|
|
200
|
+
ownership_pct: Optional[float],
|
|
201
|
+
superinvestor_present: bool,
|
|
202
|
+
quality_warning: Optional[str]
|
|
203
|
+
) -> int:
|
|
204
|
+
"""
|
|
205
|
+
Score institutional sponsorship based on O'Neil's criteria
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
num_holders: Number of institutional holders
|
|
209
|
+
ownership_pct: Institutional ownership percentage (None if unavailable)
|
|
210
|
+
superinvestor_present: True if superinvestor detected
|
|
211
|
+
quality_warning: Data quality warning
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
int: Score from 0-100
|
|
215
|
+
"""
|
|
216
|
+
# If ownership % unavailable, score on holder count only (reduced scale)
|
|
217
|
+
if ownership_pct is None:
|
|
218
|
+
if num_holders >= 50 and num_holders <= 100:
|
|
219
|
+
base_score = 50 # Half of ideal score
|
|
220
|
+
elif num_holders >= 30 and num_holders < 50:
|
|
221
|
+
base_score = 40
|
|
222
|
+
elif num_holders > 100 and num_holders <= 150:
|
|
223
|
+
base_score = 35
|
|
224
|
+
elif num_holders > 150:
|
|
225
|
+
base_score = 20
|
|
226
|
+
else:
|
|
227
|
+
base_score = 10
|
|
228
|
+
|
|
229
|
+
# Superinvestor bonus (even without ownership %)
|
|
230
|
+
if superinvestor_present:
|
|
231
|
+
base_score += 15
|
|
232
|
+
|
|
233
|
+
return min(base_score, 70) # Cap at 70 when ownership % unavailable
|
|
234
|
+
|
|
235
|
+
# Full scoring with ownership %
|
|
236
|
+
base_score = 0
|
|
237
|
+
|
|
238
|
+
# O'Neil's Sweet Spot: 50-100 holders + 30-60% ownership
|
|
239
|
+
if 50 <= num_holders <= 100 and 30 <= ownership_pct <= 60:
|
|
240
|
+
base_score = 100
|
|
241
|
+
# Superinvestor present + good holder count
|
|
242
|
+
elif superinvestor_present and 30 <= num_holders <= 150:
|
|
243
|
+
base_score = 90
|
|
244
|
+
# Good ranges (slightly outside sweet spot)
|
|
245
|
+
elif (30 <= num_holders < 50 and 20 <= ownership_pct <= 40) or \
|
|
246
|
+
(100 < num_holders <= 150 and 40 <= ownership_pct <= 70):
|
|
247
|
+
base_score = 80
|
|
248
|
+
# Acceptable ranges
|
|
249
|
+
elif (20 <= num_holders < 30 and 20 <= ownership_pct <= 50) or \
|
|
250
|
+
(50 <= num_holders <= 150 and 20 <= ownership_pct <= 70):
|
|
251
|
+
base_score = 60
|
|
252
|
+
# Suboptimal ownership
|
|
253
|
+
elif ownership_pct < 20 or ownership_pct > 80:
|
|
254
|
+
base_score = 40
|
|
255
|
+
# Extreme ownership
|
|
256
|
+
elif ownership_pct < 10 or ownership_pct > 90:
|
|
257
|
+
base_score = 20
|
|
258
|
+
else:
|
|
259
|
+
base_score = 50 # Default for other combinations
|
|
260
|
+
|
|
261
|
+
# Superinvestor bonus
|
|
262
|
+
if superinvestor_present and base_score < 100:
|
|
263
|
+
base_score = min(base_score + 10, 100)
|
|
264
|
+
|
|
265
|
+
return base_score
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def interpret_institutional_sponsorship(
|
|
269
|
+
num_holders: int,
|
|
270
|
+
ownership_pct: Optional[float],
|
|
271
|
+
superinvestor_present: bool,
|
|
272
|
+
superinvestors: List[str]
|
|
273
|
+
) -> str:
|
|
274
|
+
"""
|
|
275
|
+
Generate human-readable interpretation
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
num_holders: Number of institutional holders
|
|
279
|
+
ownership_pct: Institutional ownership percentage
|
|
280
|
+
superinvestor_present: True if superinvestor detected
|
|
281
|
+
superinvestors: List of superinvestor names
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
str: Interpretation string
|
|
285
|
+
"""
|
|
286
|
+
# Holder count assessment
|
|
287
|
+
if 50 <= num_holders <= 100:
|
|
288
|
+
holder_msg = f"{num_holders} holders (O'Neil's sweet spot)"
|
|
289
|
+
elif 30 <= num_holders < 50:
|
|
290
|
+
holder_msg = f"{num_holders} holders (good, but could grow)"
|
|
291
|
+
elif num_holders > 100 and num_holders <= 150:
|
|
292
|
+
holder_msg = f"{num_holders} holders (getting crowded)"
|
|
293
|
+
elif num_holders > 150:
|
|
294
|
+
holder_msg = f"{num_holders} holders (overcrowded)"
|
|
295
|
+
else:
|
|
296
|
+
holder_msg = f"{num_holders} holders (underowned)"
|
|
297
|
+
|
|
298
|
+
# Ownership assessment
|
|
299
|
+
if ownership_pct is None:
|
|
300
|
+
ownership_msg = "ownership % unavailable"
|
|
301
|
+
elif 30 <= ownership_pct <= 60:
|
|
302
|
+
ownership_msg = f"{ownership_pct:.1f}% ownership (ideal range)"
|
|
303
|
+
elif 20 <= ownership_pct < 30 or 60 < ownership_pct <= 80:
|
|
304
|
+
ownership_msg = f"{ownership_pct:.1f}% ownership (acceptable)"
|
|
305
|
+
elif ownership_pct < 20:
|
|
306
|
+
ownership_msg = f"{ownership_pct:.1f}% ownership (underowned, potential upside)"
|
|
307
|
+
else:
|
|
308
|
+
ownership_msg = f"{ownership_pct:.1f}% ownership (overcrowded, vulnerable)"
|
|
309
|
+
|
|
310
|
+
# Superinvestor note
|
|
311
|
+
if superinvestor_present:
|
|
312
|
+
superinvestor_names = ", ".join(superinvestors[:2]) # Show first 2
|
|
313
|
+
if len(superinvestors) > 2:
|
|
314
|
+
superinvestor_names += f" +{len(superinvestors)-2} more"
|
|
315
|
+
superinvestor_msg = f" ⭐ Superinvestors: {superinvestor_names}"
|
|
316
|
+
else:
|
|
317
|
+
superinvestor_msg = ""
|
|
318
|
+
|
|
319
|
+
return f"{holder_msg}, {ownership_msg}.{superinvestor_msg}"
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
# Example usage
|
|
323
|
+
if __name__ == "__main__":
|
|
324
|
+
# Test with sample data
|
|
325
|
+
sample_holders = [
|
|
326
|
+
{"holder": "Vanguard Group Inc", "shares": 1000000000, "dateReported": "2024-09-30", "change": 5000000},
|
|
327
|
+
{"holder": "BERKSHIRE HATHAWAY INC", "shares": 500000000, "dateReported": "2024-09-30", "change": 0},
|
|
328
|
+
] + [
|
|
329
|
+
{"holder": f"Institution {i}", "shares": 10000000, "dateReported": "2024-09-30", "change": 0}
|
|
330
|
+
for i in range(3, 75) # Total 74 holders
|
|
331
|
+
]
|
|
332
|
+
|
|
333
|
+
sample_profile = {
|
|
334
|
+
"symbol": "TEST",
|
|
335
|
+
"sharesOutstanding": 5000000000,
|
|
336
|
+
"price": 150.0
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
result = calculate_institutional_sponsorship(sample_holders, sample_profile)
|
|
340
|
+
|
|
341
|
+
print("I Component Test Results:")
|
|
342
|
+
print(f" Score: {result['score']}/100")
|
|
343
|
+
print(f" Holders: {result['num_holders']}")
|
|
344
|
+
print(f" Ownership: {result['ownership_pct']:.1f}%")
|
|
345
|
+
print(f" Superinvestor: {result['superinvestor_present']}")
|
|
346
|
+
print(f" Superinvestors: {result['superinvestors']}")
|
|
347
|
+
print(f" Interpretation: {result['interpretation']}")
|