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,745 @@
|
|
|
1
|
+
# Cointegration Testing Guide
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
1. [What is Cointegration?](#what-is-cointegration)
|
|
6
|
+
2. [Cointegration vs Correlation](#cointegration-vs-correlation)
|
|
7
|
+
3. [Augmented Dickey-Fuller (ADF) Test](#augmented-dickey-fuller-adf-test)
|
|
8
|
+
4. [Practical Implementation](#practical-implementation)
|
|
9
|
+
5. [Interpreting Results](#interpreting-results)
|
|
10
|
+
6. [Half-Life Estimation](#half-life-estimation)
|
|
11
|
+
7. [Testing for Structural Breaks](#testing-for-structural-breaks)
|
|
12
|
+
8. [Case Studies](#case-studies)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## What is Cointegration?
|
|
17
|
+
|
|
18
|
+
### Intuitive Explanation
|
|
19
|
+
|
|
20
|
+
Imagine two drunk people walking home from a bar. They're both stumbling randomly, but one person has a dog on a leash. The person and the dog may wander in different directions temporarily, but the leash keeps them together in the long run. They are "cointegrated."
|
|
21
|
+
|
|
22
|
+
**In finance:**
|
|
23
|
+
- Person A = Stock A price
|
|
24
|
+
- Person B (with dog) = Stock B price
|
|
25
|
+
- Leash = Economic relationship (sector, supply chain, competition)
|
|
26
|
+
|
|
27
|
+
While both stock prices are non-stationary (random walks), their **difference** (or spread) is stationary because the economic "leash" pulls them back together.
|
|
28
|
+
|
|
29
|
+
### Mathematical Definition
|
|
30
|
+
|
|
31
|
+
Two non-stationary time series **X(t)** and **Y(t)** are cointegrated if there exists a coefficient **β** such that:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Spread(t) = X(t) - β * Y(t)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
is stationary (mean-reverting).
|
|
38
|
+
|
|
39
|
+
**Key Components:**
|
|
40
|
+
- **X(t), Y(t)**: Non-stationary price series (random walks)
|
|
41
|
+
- **β**: Cointegration coefficient (hedge ratio)
|
|
42
|
+
- **Spread(t)**: Stationary series (mean-reverting)
|
|
43
|
+
|
|
44
|
+
### Why Cointegration Matters for Pair Trading
|
|
45
|
+
|
|
46
|
+
**Without Cointegration:**
|
|
47
|
+
- Prices can drift apart indefinitely
|
|
48
|
+
- No guarantee of mean reversion
|
|
49
|
+
- High risk of permanent losses
|
|
50
|
+
|
|
51
|
+
**With Cointegration:**
|
|
52
|
+
- Prices have long-term equilibrium
|
|
53
|
+
- Temporary deviations are predictable
|
|
54
|
+
- Mean reversion is statistically ensured
|
|
55
|
+
|
|
56
|
+
**Example:**
|
|
57
|
+
|
|
58
|
+
**Non-Cointegrated Pair:**
|
|
59
|
+
```
|
|
60
|
+
Stock A: Oil producer
|
|
61
|
+
Stock B: Tech company
|
|
62
|
+
Correlation: 0.75 (recent coincidence)
|
|
63
|
+
|
|
64
|
+
Result: No economic linkage → correlation breaks down → prices diverge forever
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Cointegrated Pair:**
|
|
68
|
+
```
|
|
69
|
+
Stock A: Exxon (XOM)
|
|
70
|
+
Stock B: Chevron (CVX)
|
|
71
|
+
Correlation: 0.92
|
|
72
|
+
Cointegration p-value: 0.008 (strong)
|
|
73
|
+
|
|
74
|
+
Result: Same sector, similar business → prices stay together → mean reversion reliable
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Cointegration vs Correlation
|
|
80
|
+
|
|
81
|
+
### Key Differences
|
|
82
|
+
|
|
83
|
+
| Aspect | Correlation | Cointegration |
|
|
84
|
+
|--------|-------------|---------------|
|
|
85
|
+
| **Measures** | Short-term returns co-movement | Long-term price level relationship |
|
|
86
|
+
| **Data** | First differences (returns) | Price levels |
|
|
87
|
+
| **Range** | -1 to +1 | p-value (0 to 1) |
|
|
88
|
+
| **Stationarity** | Assumes both series stationary | Allows non-stationary series |
|
|
89
|
+
| **Mean Reversion** | Does not imply | Guarantees (for spread) |
|
|
90
|
+
| **Stability** | Can be unstable | More stable |
|
|
91
|
+
|
|
92
|
+
### Why Correlation Alone is Insufficient
|
|
93
|
+
|
|
94
|
+
**Problem with Correlation:**
|
|
95
|
+
|
|
96
|
+
Two random walks can have high correlation **by chance** without any fundamental relationship.
|
|
97
|
+
|
|
98
|
+
**Example:**
|
|
99
|
+
```python
|
|
100
|
+
import numpy as np
|
|
101
|
+
|
|
102
|
+
# Generate two independent random walks
|
|
103
|
+
np.random.seed(42)
|
|
104
|
+
walk_A = np.cumsum(np.random.randn(252))
|
|
105
|
+
walk_B = np.cumsum(np.random.randn(252))
|
|
106
|
+
|
|
107
|
+
# Calculate correlation
|
|
108
|
+
correlation = np.corrcoef(walk_A, walk_B)[0, 1]
|
|
109
|
+
# Result: Might be 0.60-0.80 purely by chance!
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Key Point:**
|
|
113
|
+
- High correlation ≠ Mean reversion
|
|
114
|
+
- Need cointegration to ensure spread is stationary
|
|
115
|
+
|
|
116
|
+
### Combining Correlation and Cointegration
|
|
117
|
+
|
|
118
|
+
**Best Practice:**
|
|
119
|
+
|
|
120
|
+
Use both as filters:
|
|
121
|
+
1. **Correlation** (≥ 0.70): Quick screen for co-movement
|
|
122
|
+
2. **Cointegration** (p < 0.05): Rigorous test for mean reversion
|
|
123
|
+
|
|
124
|
+
**Decision Matrix:**
|
|
125
|
+
|
|
126
|
+
| Correlation | Cointegration | Trade? |
|
|
127
|
+
|-------------|---------------|--------|
|
|
128
|
+
| High (≥0.70) | Yes (p<0.05) | ✅ **YES** |
|
|
129
|
+
| High (≥0.70) | No (p>0.05) | ❌ **NO** |
|
|
130
|
+
| Low (<0.70) | Yes (p<0.05) | 🟡 **MAYBE** (unusual) |
|
|
131
|
+
| Low (<0.70) | No (p>0.05) | ❌ **NO** |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Augmented Dickey-Fuller (ADF) Test
|
|
136
|
+
|
|
137
|
+
### Purpose
|
|
138
|
+
|
|
139
|
+
The ADF test determines whether a time series has a **unit root** (non-stationary) or is stationary.
|
|
140
|
+
|
|
141
|
+
**Hypotheses:**
|
|
142
|
+
- **Null (H0)**: Series has unit root (non-stationary)
|
|
143
|
+
- **Alternative (H1)**: Series is stationary
|
|
144
|
+
|
|
145
|
+
**For pair trading:**
|
|
146
|
+
- Test the **spread** (not individual prices)
|
|
147
|
+
- Reject H0 → Spread is stationary → Pair is cointegrated
|
|
148
|
+
|
|
149
|
+
### Test Procedure
|
|
150
|
+
|
|
151
|
+
**Step 1: Calculate Spread**
|
|
152
|
+
```python
|
|
153
|
+
spread = price_A - (beta * price_B)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Step 2: Run ADF Test**
|
|
157
|
+
```python
|
|
158
|
+
from statsmodels.tsa.stattools import adfuller
|
|
159
|
+
|
|
160
|
+
result = adfuller(spread, maxlag=1, regression='c')
|
|
161
|
+
adf_statistic = result[0]
|
|
162
|
+
p_value = result[1]
|
|
163
|
+
critical_values = result[4]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Parameters:**
|
|
167
|
+
- `maxlag=1`: Number of lags (typically 1 for daily data)
|
|
168
|
+
- `regression='c'`: Include constant term (drift)
|
|
169
|
+
- Alternatives: `'ct'` (constant + trend), `'n'` (no constant)
|
|
170
|
+
|
|
171
|
+
**Step 3: Interpret Results**
|
|
172
|
+
```python
|
|
173
|
+
if p_value < 0.05:
|
|
174
|
+
print("Reject null → Spread is stationary → Cointegrated")
|
|
175
|
+
else:
|
|
176
|
+
print("Fail to reject null → Not cointegrated")
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### ADF Test Equation
|
|
180
|
+
|
|
181
|
+
The ADF test estimates:
|
|
182
|
+
```
|
|
183
|
+
ΔSpread(t) = α + β*Spread(t-1) + Σ(γ_i * ΔSpread(t-i)) + ε(t)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Where:
|
|
187
|
+
- ΔSpread(t) = Spread(t) - Spread(t-1) (first difference)
|
|
188
|
+
- β: Coefficient of interest (tests for unit root)
|
|
189
|
+
- α: Drift term
|
|
190
|
+
- Σ(γ_i * ΔSpread(t-i)): Lagged differences (capture serial correlation)
|
|
191
|
+
|
|
192
|
+
**Test Statistic:**
|
|
193
|
+
```
|
|
194
|
+
ADF = β / SE(β)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Decision Rule:**
|
|
198
|
+
- If ADF < Critical Value → Reject null (stationary)
|
|
199
|
+
- If p-value < 0.05 → Reject null (stationary)
|
|
200
|
+
|
|
201
|
+
### Critical Values
|
|
202
|
+
|
|
203
|
+
**Standard Critical Values (constant, no trend):**
|
|
204
|
+
|
|
205
|
+
| Significance Level | Critical Value |
|
|
206
|
+
|--------------------|----------------|
|
|
207
|
+
| 1% | -3.43 |
|
|
208
|
+
| 5% | -2.86 |
|
|
209
|
+
| 10% | -2.57 |
|
|
210
|
+
|
|
211
|
+
**Example:**
|
|
212
|
+
```
|
|
213
|
+
ADF Statistic: -3.75
|
|
214
|
+
Critical Value (5%): -2.86
|
|
215
|
+
|
|
216
|
+
Since -3.75 < -2.86 → Reject null → Stationary
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Practical Implementation
|
|
222
|
+
|
|
223
|
+
### Complete Python Example
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
import pandas as pd
|
|
227
|
+
import numpy as np
|
|
228
|
+
from statsmodels.tsa.stattools import adfuller
|
|
229
|
+
from scipy import stats
|
|
230
|
+
|
|
231
|
+
# Step 1: Load price data
|
|
232
|
+
prices_A = pd.Series([100, 102, 104, 103, 105, ...]) # Stock A
|
|
233
|
+
prices_B = pd.Series([50, 51, 52, 51.5, 52.5, ...]) # Stock B
|
|
234
|
+
|
|
235
|
+
# Step 2: Calculate beta (hedge ratio)
|
|
236
|
+
slope, intercept, r_value, p_value, std_err = stats.linregress(prices_B, prices_A)
|
|
237
|
+
beta = slope
|
|
238
|
+
|
|
239
|
+
print(f"Beta (hedge ratio): {beta:.4f}")
|
|
240
|
+
print(f"Correlation: {r_value:.4f}")
|
|
241
|
+
|
|
242
|
+
# Step 3: Calculate spread
|
|
243
|
+
spread = prices_A - (beta * prices_B)
|
|
244
|
+
|
|
245
|
+
# Step 4: Run ADF test
|
|
246
|
+
adf_result = adfuller(spread, maxlag=1, regression='c')
|
|
247
|
+
|
|
248
|
+
adf_statistic = adf_result[0]
|
|
249
|
+
p_value = adf_result[1]
|
|
250
|
+
critical_values = adf_result[4]
|
|
251
|
+
n_lags = adf_result[2]
|
|
252
|
+
|
|
253
|
+
# Step 5: Display results
|
|
254
|
+
print("\n=== Cointegration Test Results ===")
|
|
255
|
+
print(f"ADF Statistic: {adf_statistic:.4f}")
|
|
256
|
+
print(f"P-value: {p_value:.4f}")
|
|
257
|
+
print(f"Number of Lags: {n_lags}")
|
|
258
|
+
print(f"\nCritical Values:")
|
|
259
|
+
for key, value in critical_values.items():
|
|
260
|
+
print(f" {key}: {value:.4f}")
|
|
261
|
+
|
|
262
|
+
# Step 6: Interpret
|
|
263
|
+
if p_value < 0.01:
|
|
264
|
+
print("\n✅ STRONG Cointegration (p < 0.01)")
|
|
265
|
+
strength = "★★★"
|
|
266
|
+
elif p_value < 0.05:
|
|
267
|
+
print("\n✅ MODERATE Cointegration (p < 0.05)")
|
|
268
|
+
strength = "★★"
|
|
269
|
+
else:
|
|
270
|
+
print("\n❌ NOT Cointegrated (p > 0.05)")
|
|
271
|
+
strength = "☆"
|
|
272
|
+
|
|
273
|
+
# Step 7: Calculate half-life (if cointegrated)
|
|
274
|
+
if p_value < 0.05:
|
|
275
|
+
from statsmodels.tsa.ar_model import AutoReg
|
|
276
|
+
|
|
277
|
+
model = AutoReg(spread, lags=1)
|
|
278
|
+
result = model.fit()
|
|
279
|
+
phi = result.params[1]
|
|
280
|
+
|
|
281
|
+
half_life = -np.log(2) / np.log(phi)
|
|
282
|
+
print(f"\nHalf-Life: {half_life:.1f} days")
|
|
283
|
+
|
|
284
|
+
if half_life < 30:
|
|
285
|
+
print(" → Fast mean reversion (excellent)")
|
|
286
|
+
elif half_life < 60:
|
|
287
|
+
print(" → Moderate mean reversion (good)")
|
|
288
|
+
else:
|
|
289
|
+
print(" → Slow mean reversion (acceptable)")
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### FMP API Integration
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
import requests
|
|
296
|
+
import pandas as pd
|
|
297
|
+
|
|
298
|
+
def get_price_history(symbol, api_key, days=730):
|
|
299
|
+
"""Fetch historical prices from FMP API"""
|
|
300
|
+
url = f"https://financialmodelingprep.com/api/v3/historical-price-full/{symbol}?apikey={api_key}"
|
|
301
|
+
response = requests.get(url)
|
|
302
|
+
data = response.json()
|
|
303
|
+
|
|
304
|
+
# Extract historical prices
|
|
305
|
+
hist = data['historical'][:days]
|
|
306
|
+
hist = hist[::-1] # Reverse to chronological order
|
|
307
|
+
|
|
308
|
+
df = pd.DataFrame(hist)
|
|
309
|
+
df['date'] = pd.to_datetime(df['date'])
|
|
310
|
+
df = df.set_index('date')
|
|
311
|
+
|
|
312
|
+
return df['adjClose']
|
|
313
|
+
|
|
314
|
+
# Example usage
|
|
315
|
+
api_key = "YOUR_API_KEY"
|
|
316
|
+
prices_AAPL = get_price_history("AAPL", api_key)
|
|
317
|
+
prices_MSFT = get_price_history("MSFT", api_key)
|
|
318
|
+
|
|
319
|
+
# Align dates
|
|
320
|
+
common_dates = prices_AAPL.index.intersection(prices_MSFT.index)
|
|
321
|
+
prices_AAPL = prices_AAPL.loc[common_dates]
|
|
322
|
+
prices_MSFT = prices_MSFT.loc[common_dates]
|
|
323
|
+
|
|
324
|
+
# Test for cointegration
|
|
325
|
+
slope, intercept, r_value, p_value, std_err = stats.linregress(prices_MSFT, prices_AAPL)
|
|
326
|
+
beta = slope
|
|
327
|
+
spread = prices_AAPL - (beta * prices_MSFT)
|
|
328
|
+
|
|
329
|
+
adf_result = adfuller(spread, maxlag=1)
|
|
330
|
+
print(f"AAPL/MSFT Cointegration p-value: {adf_result[1]:.4f}")
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Interpreting Results
|
|
336
|
+
|
|
337
|
+
### P-Value Interpretation
|
|
338
|
+
|
|
339
|
+
**What p-value means:**
|
|
340
|
+
- Probability of observing test statistic if null hypothesis (unit root) is true
|
|
341
|
+
- Lower p-value = stronger evidence against null = stronger cointegration
|
|
342
|
+
|
|
343
|
+
**Guidelines:**
|
|
344
|
+
|
|
345
|
+
| P-Value Range | Interpretation | Confidence | Trade? |
|
|
346
|
+
|---------------|----------------|------------|--------|
|
|
347
|
+
| p < 0.01 | Very strong cointegration | 99% | ✅ **YES** (★★★) |
|
|
348
|
+
| p 0.01-0.03 | Strong cointegration | 97-99% | ✅ **YES** (★★★) |
|
|
349
|
+
| p 0.03-0.05 | Moderate cointegration | 95-97% | ✅ **YES** (★★) |
|
|
350
|
+
| p 0.05-0.10 | Weak evidence | 90-95% | 🟡 **MARGINAL** (★) |
|
|
351
|
+
| p > 0.10 | No cointegration | <90% | ❌ **NO** (☆) |
|
|
352
|
+
|
|
353
|
+
### ADF Statistic Interpretation
|
|
354
|
+
|
|
355
|
+
**More negative = stronger cointegration:**
|
|
356
|
+
|
|
357
|
+
```
|
|
358
|
+
ADF < -4.0: Very strong (★★★★)
|
|
359
|
+
ADF -3.5 to -4.0: Strong (★★★)
|
|
360
|
+
ADF -3.0 to -3.5: Moderate (★★)
|
|
361
|
+
ADF -2.5 to -3.0: Weak (★)
|
|
362
|
+
ADF > -2.5: Not cointegrated (☆)
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Example Rankings:**
|
|
366
|
+
|
|
367
|
+
```python
|
|
368
|
+
Pair A: ADF = -4.25, p = 0.002 → ★★★★ (Best)
|
|
369
|
+
Pair B: ADF = -3.65, p = 0.018 → ★★★ (Excellent)
|
|
370
|
+
Pair C: ADF = -2.95, p = 0.042 → ★★ (Good)
|
|
371
|
+
Pair D: ADF = -2.45, p = 0.125 → ☆ (Reject)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Common Mistakes
|
|
375
|
+
|
|
376
|
+
**Mistake 1: Testing Individual Prices**
|
|
377
|
+
```python
|
|
378
|
+
# WRONG: Testing if stock price is stationary
|
|
379
|
+
adf_result = adfuller(prices_A) # ❌ Will always fail (prices are random walks)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Correct:**
|
|
383
|
+
```python
|
|
384
|
+
# RIGHT: Test if SPREAD is stationary
|
|
385
|
+
spread = prices_A - (beta * prices_B)
|
|
386
|
+
adf_result = adfuller(spread) # ✅ Tests for cointegration
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**Mistake 2: Ignoring Lag Selection**
|
|
390
|
+
```python
|
|
391
|
+
# WRONG: Using too many lags (overfitting)
|
|
392
|
+
adf_result = adfuller(spread, maxlag=20) # ❌ Too complex
|
|
393
|
+
|
|
394
|
+
# RIGHT: Use simple lag structure
|
|
395
|
+
adf_result = adfuller(spread, maxlag=1) # ✅ Appropriate for daily data
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Mistake 3: Confusing Correlation with Cointegration**
|
|
399
|
+
```python
|
|
400
|
+
# WRONG: Assuming high correlation = cointegration
|
|
401
|
+
if correlation > 0.80:
|
|
402
|
+
trade_pair() # ❌ Not sufficient
|
|
403
|
+
|
|
404
|
+
# RIGHT: Test for cointegration explicitly
|
|
405
|
+
if correlation > 0.70 and cointegration_pvalue < 0.05:
|
|
406
|
+
trade_pair() # ✅ Both conditions required
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Half-Life Estimation
|
|
412
|
+
|
|
413
|
+
### What is Half-Life?
|
|
414
|
+
|
|
415
|
+
Half-life measures how quickly the spread mean-reverts. Specifically, it's the expected time for the spread to move halfway back to its mean.
|
|
416
|
+
|
|
417
|
+
**Example:**
|
|
418
|
+
```
|
|
419
|
+
Current spread: +2.0 (2 std devs above mean)
|
|
420
|
+
Half-life: 20 days
|
|
421
|
+
|
|
422
|
+
Expected spread after 20 days: +1.0 (halfway to mean)
|
|
423
|
+
Expected spread after 40 days: +0.5 (halfway from +1.0 to 0)
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### AR(1) Model Approach
|
|
427
|
+
|
|
428
|
+
Model spread as autoregressive process:
|
|
429
|
+
```
|
|
430
|
+
S(t) = α + φ * S(t-1) + ε(t)
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Where:
|
|
434
|
+
- φ: Autocorrelation coefficient (persistence)
|
|
435
|
+
- φ close to 1.0 → Slow mean reversion (long half-life)
|
|
436
|
+
- φ close to 0.0 → Fast mean reversion (short half-life)
|
|
437
|
+
|
|
438
|
+
**Half-Life Formula:**
|
|
439
|
+
```
|
|
440
|
+
Half-Life = -ln(2) / ln(φ)
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Python Implementation
|
|
444
|
+
|
|
445
|
+
```python
|
|
446
|
+
from statsmodels.tsa.ar_model import AutoReg
|
|
447
|
+
|
|
448
|
+
# Fit AR(1) model to spread
|
|
449
|
+
model = AutoReg(spread, lags=1)
|
|
450
|
+
result = model.fit()
|
|
451
|
+
|
|
452
|
+
# Extract autocorrelation coefficient
|
|
453
|
+
phi = result.params[1]
|
|
454
|
+
|
|
455
|
+
# Calculate half-life
|
|
456
|
+
half_life = -np.log(2) / np.log(phi)
|
|
457
|
+
|
|
458
|
+
print(f"Autocorrelation (φ): {phi:.4f}")
|
|
459
|
+
print(f"Half-Life: {half_life:.1f} days")
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Interpreting Half-Life
|
|
463
|
+
|
|
464
|
+
| Half-Life | Speed | Suitability | Holding Period |
|
|
465
|
+
|-----------|-------|-------------|----------------|
|
|
466
|
+
| < 10 days | Very fast | Day/swing trading | < 2 weeks |
|
|
467
|
+
| 10-30 days | Fast | Short-term pairs | 2-6 weeks |
|
|
468
|
+
| 30-60 days | Moderate | Standard pairs | 1-3 months |
|
|
469
|
+
| 60-90 days | Slow | Long-term pairs | 2-6 months |
|
|
470
|
+
| > 90 days | Very slow | Poor for trading | Avoid |
|
|
471
|
+
|
|
472
|
+
**Trading Implications:**
|
|
473
|
+
|
|
474
|
+
**Fast Half-Life (< 30 days):**
|
|
475
|
+
- ✅ Quick profits
|
|
476
|
+
- ✅ Lower holding risk
|
|
477
|
+
- ✅ Frequent opportunities
|
|
478
|
+
- ❌ Transaction costs matter more
|
|
479
|
+
|
|
480
|
+
**Slow Half-Life (> 60 days):**
|
|
481
|
+
- ✅ More stable relationships
|
|
482
|
+
- ❌ Capital tied up longer
|
|
483
|
+
- ❌ Fewer trading opportunities
|
|
484
|
+
- ❌ Higher holding risk (regime changes)
|
|
485
|
+
|
|
486
|
+
### Half-Life Stability
|
|
487
|
+
|
|
488
|
+
**Test half-life over multiple periods:**
|
|
489
|
+
```python
|
|
490
|
+
# Calculate rolling half-life
|
|
491
|
+
rolling_half_life = []
|
|
492
|
+
|
|
493
|
+
for i in range(252, len(spread)):
|
|
494
|
+
window = spread[i-252:i]
|
|
495
|
+
model = AutoReg(window, lags=1)
|
|
496
|
+
result = model.fit()
|
|
497
|
+
phi = result.params[1]
|
|
498
|
+
hl = -np.log(2) / np.log(phi)
|
|
499
|
+
rolling_half_life.append(hl)
|
|
500
|
+
|
|
501
|
+
# Check stability
|
|
502
|
+
std_hl = np.std(rolling_half_life)
|
|
503
|
+
mean_hl = np.mean(rolling_half_life)
|
|
504
|
+
cv = std_hl / mean_hl # Coefficient of variation
|
|
505
|
+
|
|
506
|
+
if cv < 0.30:
|
|
507
|
+
print("Half-life is STABLE (good)")
|
|
508
|
+
else:
|
|
509
|
+
print("Half-life is UNSTABLE (warning)")
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
## Testing for Structural Breaks
|
|
515
|
+
|
|
516
|
+
### Why Structural Breaks Matter
|
|
517
|
+
|
|
518
|
+
**Definition:**
|
|
519
|
+
- A structural break is a sudden, permanent change in the cointegration relationship
|
|
520
|
+
- Examples: Merger, spin-off, business model pivot, regulatory change
|
|
521
|
+
|
|
522
|
+
**Impact on Pair Trading:**
|
|
523
|
+
- Break in cointegration → Spread no longer mean-reverts
|
|
524
|
+
- Holding pair through break → Large losses
|
|
525
|
+
- Must detect breaks early and exit
|
|
526
|
+
|
|
527
|
+
### Chow Test
|
|
528
|
+
|
|
529
|
+
Tests for known breakpoint (e.g., specific corporate event date):
|
|
530
|
+
|
|
531
|
+
```python
|
|
532
|
+
from statsmodels.stats.diagnostic import breaks_cusumolsresid
|
|
533
|
+
|
|
534
|
+
# Fit OLS regression
|
|
535
|
+
from scipy import stats
|
|
536
|
+
slope, intercept = stats.linregress(prices_B, prices_A)[:2]
|
|
537
|
+
residuals = prices_A - (slope * prices_B + intercept)
|
|
538
|
+
|
|
539
|
+
# Test for structural breaks
|
|
540
|
+
stat, pvalue = breaks_cusumolsresid(residuals)
|
|
541
|
+
|
|
542
|
+
if pvalue < 0.05:
|
|
543
|
+
print("⚠️ STRUCTURAL BREAK DETECTED")
|
|
544
|
+
else:
|
|
545
|
+
print("✅ No structural break")
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Rolling Cointegration
|
|
549
|
+
|
|
550
|
+
**Monitor cointegration over time:**
|
|
551
|
+
```python
|
|
552
|
+
rolling_pvalues = []
|
|
553
|
+
|
|
554
|
+
for i in range(252, len(prices_A)):
|
|
555
|
+
window_A = prices_A[i-252:i]
|
|
556
|
+
window_B = prices_B[i-252:i]
|
|
557
|
+
|
|
558
|
+
slope, intercept = stats.linregress(window_B, window_A)[:2]
|
|
559
|
+
spread_window = window_A - (slope * window_B)
|
|
560
|
+
|
|
561
|
+
adf_result = adfuller(spread_window, maxlag=1)
|
|
562
|
+
pvalue = adf_result[1]
|
|
563
|
+
rolling_pvalues.append(pvalue)
|
|
564
|
+
|
|
565
|
+
# Plot rolling p-values
|
|
566
|
+
import matplotlib.pyplot as plt
|
|
567
|
+
plt.plot(rolling_pvalues)
|
|
568
|
+
plt.axhline(y=0.05, color='r', linestyle='--', label='Significance threshold')
|
|
569
|
+
plt.ylabel('P-Value')
|
|
570
|
+
plt.xlabel('Time')
|
|
571
|
+
plt.title('Rolling Cointegration P-Value')
|
|
572
|
+
plt.legend()
|
|
573
|
+
plt.show()
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
**Interpretation:**
|
|
577
|
+
- P-value stays below 0.05 → Cointegration stable ✅
|
|
578
|
+
- P-value crosses above 0.05 → Cointegration breaking down ⚠️
|
|
579
|
+
- P-value remains above 0.10 → Relationship broken ❌
|
|
580
|
+
|
|
581
|
+
### Early Warning System
|
|
582
|
+
|
|
583
|
+
**Exit conditions based on cointegration degradation:**
|
|
584
|
+
```python
|
|
585
|
+
# Calculate 90-day rolling cointegration p-value
|
|
586
|
+
recent_pvalue = calculate_rolling_cointegration(prices_A[-90:], prices_B[-90:])
|
|
587
|
+
|
|
588
|
+
if recent_pvalue > 0.10:
|
|
589
|
+
print("🚨 EXIT SIGNAL: Cointegration broken")
|
|
590
|
+
exit_pair()
|
|
591
|
+
elif recent_pvalue > 0.05:
|
|
592
|
+
print("⚠️ WARNING: Cointegration weakening")
|
|
593
|
+
reduce_position()
|
|
594
|
+
else:
|
|
595
|
+
print("✅ Cointegration healthy")
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
## Case Studies
|
|
601
|
+
|
|
602
|
+
### Case Study 1: XOM/CVX (Strong Cointegration)
|
|
603
|
+
|
|
604
|
+
**Background:**
|
|
605
|
+
- Exxon Mobil (XOM) and Chevron (CVX)
|
|
606
|
+
- Both: Large oil & gas companies
|
|
607
|
+
- Same sector, similar business models
|
|
608
|
+
|
|
609
|
+
**Analysis:**
|
|
610
|
+
```python
|
|
611
|
+
# 2-year data (2023-2025)
|
|
612
|
+
correlation: 0.94
|
|
613
|
+
beta: 1.08
|
|
614
|
+
adf_statistic: -4.25
|
|
615
|
+
p_value: 0.0008
|
|
616
|
+
half_life: 28 days
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
**Interpretation:**
|
|
620
|
+
- ✅ Very strong cointegration (p < 0.01)
|
|
621
|
+
- ✅ High correlation (0.94)
|
|
622
|
+
- ✅ Fast mean reversion (28 days)
|
|
623
|
+
- ✅ Economic linkage (same sector)
|
|
624
|
+
|
|
625
|
+
**Rating:** ★★★★ (Excellent pair)
|
|
626
|
+
|
|
627
|
+
**Trade Signal (Example):**
|
|
628
|
+
```
|
|
629
|
+
Current Z-Score: +2.3 (XOM expensive relative to CVX)
|
|
630
|
+
→ SHORT XOM, LONG CVX
|
|
631
|
+
Entry: Z > +2.0
|
|
632
|
+
Exit: Z < 0.0
|
|
633
|
+
Stop: Z > +3.0
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Case Study 2: JPM/BAC (Moderate Cointegration)
|
|
637
|
+
|
|
638
|
+
**Background:**
|
|
639
|
+
- JPMorgan Chase (JPM) and Bank of America (BAC)
|
|
640
|
+
- Both: Large banks
|
|
641
|
+
- Different focus areas (JPM more investment banking, BAC more retail)
|
|
642
|
+
|
|
643
|
+
**Analysis:**
|
|
644
|
+
```python
|
|
645
|
+
correlation: 0.85
|
|
646
|
+
beta: 1.35
|
|
647
|
+
adf_statistic: -3.12
|
|
648
|
+
p_value: 0.031
|
|
649
|
+
half_life: 42 days
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
**Interpretation:**
|
|
653
|
+
- ✅ Moderate cointegration (p = 0.031)
|
|
654
|
+
- ✅ Good correlation (0.85)
|
|
655
|
+
- ✅ Acceptable mean reversion (42 days)
|
|
656
|
+
- ⚠️ Different business mix (less perfect linkage)
|
|
657
|
+
|
|
658
|
+
**Rating:** ★★★ (Good pair)
|
|
659
|
+
|
|
660
|
+
### Case Study 3: AAPL/TSLA (No Cointegration)
|
|
661
|
+
|
|
662
|
+
**Background:**
|
|
663
|
+
- Apple (AAPL) and Tesla (TSLA)
|
|
664
|
+
- Both: High-growth tech stocks
|
|
665
|
+
- Different businesses (consumer electronics vs EVs)
|
|
666
|
+
|
|
667
|
+
**Analysis:**
|
|
668
|
+
```python
|
|
669
|
+
correlation: 0.72
|
|
670
|
+
beta: 0.88
|
|
671
|
+
adf_statistic: -2.15
|
|
672
|
+
p_value: 0.182
|
|
673
|
+
half_life: N/A (not stationary)
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
**Interpretation:**
|
|
677
|
+
- ❌ No cointegration (p = 0.182)
|
|
678
|
+
- ✅ Moderate correlation (0.72)
|
|
679
|
+
- ❌ No mean reversion
|
|
680
|
+
- ❌ Weak economic linkage
|
|
681
|
+
|
|
682
|
+
**Rating:** ☆ (Reject pair)
|
|
683
|
+
|
|
684
|
+
**Why correlation failed:**
|
|
685
|
+
- Both had high returns in 2023-2024 (growth stock rally)
|
|
686
|
+
- Correlation driven by macro factors (interest rates), not fundamental linkage
|
|
687
|
+
- Likely to diverge when market conditions change
|
|
688
|
+
|
|
689
|
+
### Case Study 4: Structural Break Example (GE)
|
|
690
|
+
|
|
691
|
+
**Background:**
|
|
692
|
+
- General Electric (GE) underwent major restructuring 2018-2021
|
|
693
|
+
- Spun off healthcare (GEHC) and energy divisions
|
|
694
|
+
|
|
695
|
+
**Analysis:**
|
|
696
|
+
```python
|
|
697
|
+
# Pre-spinoff (2018-2020): GE/UTX pair
|
|
698
|
+
correlation: 0.81
|
|
699
|
+
p_value: 0.025 (cointegrated)
|
|
700
|
+
|
|
701
|
+
# Post-spinoff (2021-2023): GE/UTX pair
|
|
702
|
+
correlation: 0.52
|
|
703
|
+
p_value: 0.235 (NOT cointegrated)
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
**Lesson:**
|
|
707
|
+
- Corporate actions can break cointegration
|
|
708
|
+
- Must monitor for structural breaks
|
|
709
|
+
- Exit pairs when cointegration deteriorates
|
|
710
|
+
|
|
711
|
+
---
|
|
712
|
+
|
|
713
|
+
## Summary Checklist
|
|
714
|
+
|
|
715
|
+
Before trading a pair, verify:
|
|
716
|
+
|
|
717
|
+
### Statistical Checklist
|
|
718
|
+
- [ ] Correlation ≥ 0.70 (preferably ≥ 0.80)
|
|
719
|
+
- [ ] Cointegration p-value < 0.05 (preferably < 0.03)
|
|
720
|
+
- [ ] ADF statistic < -3.0
|
|
721
|
+
- [ ] Half-life 20-60 days
|
|
722
|
+
- [ ] No structural breaks in recent 6 months
|
|
723
|
+
|
|
724
|
+
### Economic Checklist
|
|
725
|
+
- [ ] Same sector or supply chain relationship
|
|
726
|
+
- [ ] Similar business models
|
|
727
|
+
- [ ] No pending M&A or restructuring
|
|
728
|
+
- [ ] Similar market cap and liquidity
|
|
729
|
+
- [ ] Both stocks shortable (for short leg)
|
|
730
|
+
|
|
731
|
+
### Risk Checklist
|
|
732
|
+
- [ ] Transaction costs < expected profit
|
|
733
|
+
- [ ] Adequate liquidity (>1M avg volume)
|
|
734
|
+
- [ ] Position sized appropriately (10-15% max)
|
|
735
|
+
- [ ] Stop loss defined (Z > ±3.0)
|
|
736
|
+
- [ ] Maximum holding period set (90 days)
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
**Document Version**: 1.0
|
|
741
|
+
**Last Updated**: 2025-11-08
|
|
742
|
+
**References**:
|
|
743
|
+
- Engle & Granger (1987): "Co-Integration and Error Correction"
|
|
744
|
+
- Hamilton (1994): "Time Series Analysis" (Chapter 19)
|
|
745
|
+
- Tsay (2010): "Analysis of Financial Time Series" (Chapter 8)
|