equity-aggregator 0.1.7__tar.gz → 1.0.0__tar.gz
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.
- equity_aggregator-1.0.0/.claude/settings.local.json +25 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/PKG-INFO +1 -1
- equity_aggregator-1.0.0/debug_yfinance.py +473 -0
- equity_aggregator-1.0.0/examples/data_integrity_analysis/__init__.py +24 -0
- equity_aggregator-1.0.0/examples/data_integrity_analysis/__main__.py +6 -0
- equity_aggregator-0.1.7/examples/data_integrity_analysis.py → equity_aggregator-1.0.0/examples/data_integrity_analysis/analyzers.py +18 -408
- equity_aggregator-1.0.0/examples/data_integrity_analysis/formatters.py +224 -0
- equity_aggregator-1.0.0/examples/data_integrity_analysis/main.py +102 -0
- equity_aggregator-1.0.0/examples/data_integrity_analysis/models.py +60 -0
- equity_aggregator-1.0.0/examples/data_integrity_analysis/rendering.py +73 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/pyproject.toml +1 -1
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/uv.lock +1 -1
- equity_aggregator-0.1.7/documentation/reference_data/tiprank_equity.json +0 -474
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/.dockerignore +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/.env_example +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/.github/workflows/publish-build-release.yml +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/.github/workflows/publish-pypi.yml +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/.github/workflows/validate-push.yml +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/.gitignore +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/.python-version +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/Dockerfile +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/LICENCE.txt +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/README.md +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/docker-compose.yml +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/documentation/reference_data/intrinio_equity.json +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/documentation/reference_data/lseg_equities.json +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/documentation/reference_data/sec_equity.json +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/documentation/reference_data/stock_analysis_equity.json +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/documentation/reference_data/tradingview_equities.json +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/documentation/reference_data/xetra_equities.json +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/documentation/reference_data/yfinance_quote_summary_equity.json +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/documentation/reference_data/yfinance_search_equity.json +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/README.md +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/_utils/_client.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/_utils/_record_types.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/backoff.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/parser.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/intrinio.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/session.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/backoff.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/parser.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/lseg.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/session.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/sec/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/sec/sec.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/stock_analysis/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/stock_analysis/stock_analysis.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/tradingview/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/tradingview/tradingview.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/xetra/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/discovery_feeds/xetra/xetra.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/api.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/download.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/gleif.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/parser.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/backoff.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/fuzzy.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/json.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/quote_summary.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/search.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/auth.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/config.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/ranking.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/session.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/transport.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/yfinance.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/reference_lookup/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/reference_lookup/exchange_rate_api.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/adapters/data_sources/reference_lookup/openfigi.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/cli/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/cli/config.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/cli/dispatcher.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/cli/main.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/cli/parser.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/cli/signals.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/_utils/_load_converter.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/_utils/_merge.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/_utils/_merge_config.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/_utils/_strategies.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/resolve.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/runner.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/seed.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/transforms/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/transforms/canonicalise.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/transforms/convert.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/transforms/enrich.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/transforms/group.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/transforms/identify.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/pipeline/transforms/parse.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/retrieval/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/domain/retrieval/retrieval.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/logging_config.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/canonical.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/feed_validators.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/gleif_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/intrinio_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/lseg_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/sec_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/stock_analysis_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/tradingview_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/xetra_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/feeds/yfinance_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/raw.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/types.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/schemas/validators.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/storage/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/storage/_utils.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/storage/cache.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/storage/data_store.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/storage/export.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/src/equity_aggregator/storage/metadata.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/README.md +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/conftest.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/intrinio/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/intrinio/test_intrinio.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/lseg/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/lseg/test_lseg.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/sec/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/sec/test_sec.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/stock_analysis/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/stock_analysis/test_stock_analysis.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/tradingview/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/tradingview/test_tradingview.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/xetra/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/discovery_feeds/xetra/test_xetra.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/enrichment_feeds/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/enrichment_feeds/gleif/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/enrichment_feeds/gleif/test_gleif.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/enrichment_feeds/yfinance/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/enrichment_feeds/yfinance/test_yfinance.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/reference_lookup/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/reference_lookup/exchange_rate_api/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/reference_lookup/exchange_rate_api/test_exchange_rate_api.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/reference_lookup/openfigi/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/live/adapters/data_sources/reference_lookup/openfigi/test_openfigi.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/_utils/test_client.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/test_backoff.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/test_parser.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/test_intrinio.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/test_session.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/lseg/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/test_backoff.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/test_parser.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/lseg/test_lseg.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/lseg/test_session.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/sec/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/sec/test_sec.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/stock_analysis/test_stock_analysis.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/tradingview/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/tradingview/test_tradingview.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/xetra/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/discovery_feeds/xetra/test_xetra.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/_helpers.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_api.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_download.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_gleif.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_parser.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_helpers.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/test_backoff.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/test_fuzzy.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/test_json.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api/test_quote_summary.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api/test_search.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_auth.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_config.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_ranking.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_session.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_transport.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_yfinance.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/reference_lookup/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/reference_lookup/test_exchange_rate_api.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/adapters/data_sources/reference_lookup/test_openfigi.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/cli/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/cli/test_config.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/cli/test_dispatcher.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/cli/test_main.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/cli/test_parser.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/_utils/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/_utils/test__merge.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/_utils/test__merge_config.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/_utils/test__strategies.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/_utils/test_load_converter.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/test_resolve.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/transforms/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/transforms/test_canonicalise.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/transforms/test_convert.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/transforms/test_enrich.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/transforms/test_group.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/transforms/test_identify.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/pipeline/transforms/test_parse.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/domain/retrieval/test_retrieval.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_feed_validators.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_gleif_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_intrinio_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_lseg_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_sec_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_stock_analysis_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_tradingview_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_xetra_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/feeds/test_yfinance_feed_data.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/test_canonical.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/test_raw.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/test_types.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/schemas/test_validators.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/storage/__init__.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/storage/test__utils.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/storage/test_cache.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/storage/test_data_store.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/storage/test_export.py +0 -0
- {equity_aggregator-0.1.7 → equity_aggregator-1.0.0}/tests/unit/storage/test_metadata.py +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(uv run pytest:*)",
|
|
5
|
+
"Bash(uv run:*)",
|
|
6
|
+
"Bash(tree:*)",
|
|
7
|
+
"Bash(find:*)",
|
|
8
|
+
"Bash(sqlite3:*)",
|
|
9
|
+
"Bash(xargs basename:*)",
|
|
10
|
+
"Bash(xargs cat:*)",
|
|
11
|
+
"Bash(cat:*)",
|
|
12
|
+
"WebFetch(domain:docs.intrinio.com)",
|
|
13
|
+
"WebFetch(domain:mapping.gleif.org)",
|
|
14
|
+
"WebSearch",
|
|
15
|
+
"WebFetch(domain:www.gleif.org)",
|
|
16
|
+
"Bash(python3 -m py_compile src/equity_aggregator/**/*.py)",
|
|
17
|
+
"Bash(python3 -m pytest:*)",
|
|
18
|
+
"Bash(wc:*)",
|
|
19
|
+
"Bash(grep:*)",
|
|
20
|
+
"Bash(git -C /Users/gregory.kelleher/Documents/equity-aggregator log --oneline -10)"
|
|
21
|
+
],
|
|
22
|
+
"deny": [],
|
|
23
|
+
"ask": []
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: equity-aggregator
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Financial equity data aggregation toolkit
|
|
5
5
|
Project-URL: Homepage, https://github.com/gregorykelleher/equity-aggregator
|
|
6
6
|
Project-URL: Repository, https://github.com/gregorykelleher/equity-aggregator
|
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Debug script to investigate Yahoo Finance API responses for specific tickers.
|
|
4
|
+
|
|
5
|
+
This script tests the YFinance endpoints:
|
|
6
|
+
1. search_url - Search for ticker/company name
|
|
7
|
+
2. quote_summary_url - Detailed quote data endpoint
|
|
8
|
+
3. Validation - Test Pydantic validation and show failures
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
uv run python debug_yfinance.py BKSC
|
|
12
|
+
uv run python debug_yfinance.py AAPL
|
|
13
|
+
uv run python debug_yfinance.py CMC
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import json
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
from pydantic import ValidationError
|
|
21
|
+
|
|
22
|
+
from equity_aggregator.adapters.data_sources.enrichment_feeds.yfinance.api.quote_summary import (
|
|
23
|
+
_get_quote_summary_fallback,
|
|
24
|
+
get_quote_summary,
|
|
25
|
+
)
|
|
26
|
+
from equity_aggregator.adapters.data_sources.enrichment_feeds.yfinance.config import (
|
|
27
|
+
FeedConfig,
|
|
28
|
+
)
|
|
29
|
+
from equity_aggregator.adapters.data_sources.enrichment_feeds.yfinance.session import (
|
|
30
|
+
YFSession,
|
|
31
|
+
)
|
|
32
|
+
from equity_aggregator.schemas.feeds.yfinance_feed_data import YFinanceFeedData
|
|
33
|
+
from equity_aggregator.schemas.raw import RawEquity
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def debug_ticker(
|
|
37
|
+
ticker: str, query: str | None = None, isin: str | None = None, export: bool = False
|
|
38
|
+
) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Debug Yahoo Finance API endpoints for a specific ticker.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
ticker: The ticker symbol to query (e.g., "BKSC", "AAPL")
|
|
44
|
+
query: Optional search query (defaults to ticker if not provided)
|
|
45
|
+
isin: Optional ISIN to test identifier-based lookup flow
|
|
46
|
+
export: Whether to export raw API responses to JSON files
|
|
47
|
+
"""
|
|
48
|
+
query = query or ticker
|
|
49
|
+
|
|
50
|
+
config = FeedConfig()
|
|
51
|
+
|
|
52
|
+
print("=" * 80)
|
|
53
|
+
print(f"DEBUGGING TICKER: {ticker}")
|
|
54
|
+
print(f"SEARCH QUERY: {query}")
|
|
55
|
+
if isin:
|
|
56
|
+
print(f"ISIN: {isin}")
|
|
57
|
+
print("=" * 80)
|
|
58
|
+
print()
|
|
59
|
+
|
|
60
|
+
session = YFSession(config)
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
# ===================================================================
|
|
64
|
+
# TEST 1: Search URL
|
|
65
|
+
# ===================================================================
|
|
66
|
+
print("📍 TEST 1: SEARCH URL")
|
|
67
|
+
print(f" URL: {config.search_url}")
|
|
68
|
+
print(f" Query: {query}")
|
|
69
|
+
print("-" * 80)
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
search_response = await session.get(
|
|
73
|
+
config.search_url,
|
|
74
|
+
params={"q": query},
|
|
75
|
+
)
|
|
76
|
+
print(f" ✓ Status Code: {search_response.status_code}")
|
|
77
|
+
|
|
78
|
+
search_data = search_response.json()
|
|
79
|
+
|
|
80
|
+
# Export search data if requested
|
|
81
|
+
if export:
|
|
82
|
+
import os
|
|
83
|
+
|
|
84
|
+
export_path = "documentation/reference_data/yfinance_search_equity.json"
|
|
85
|
+
os.makedirs(os.path.dirname(export_path), exist_ok=True)
|
|
86
|
+
with open(export_path, "w") as f:
|
|
87
|
+
json.dump(search_data, f, indent=2)
|
|
88
|
+
print(f" ✓ Exported to {export_path}")
|
|
89
|
+
quotes = search_data.get("quotes", [])
|
|
90
|
+
print(f" ✓ Found {len(quotes)} results")
|
|
91
|
+
|
|
92
|
+
if quotes:
|
|
93
|
+
print("\n Results:")
|
|
94
|
+
for i, quote in enumerate(quotes[:5], 1): # Show first 5
|
|
95
|
+
symbol = quote.get("symbol", "N/A")
|
|
96
|
+
name = quote.get("longName") or quote.get("shortName", "N/A")
|
|
97
|
+
quote_type = quote.get("quoteType", "N/A")
|
|
98
|
+
exchange = quote.get("exchange", "N/A")
|
|
99
|
+
print(f" {i}. {symbol} - {name}")
|
|
100
|
+
print(f" Type: {quote_type}, Exchange: {exchange}")
|
|
101
|
+
else:
|
|
102
|
+
print(" ⚠ No results found")
|
|
103
|
+
|
|
104
|
+
except Exception as e:
|
|
105
|
+
print(f" ✗ ERROR: {e}")
|
|
106
|
+
|
|
107
|
+
print()
|
|
108
|
+
|
|
109
|
+
# ===================================================================
|
|
110
|
+
# TEST 2: Quote Summary URL (Primary)
|
|
111
|
+
# ===================================================================
|
|
112
|
+
print("📍 TEST 2: QUOTE SUMMARY URL (PRIMARY)")
|
|
113
|
+
print(f" URL: {config.quote_summary_primary_url}{ticker}")
|
|
114
|
+
print(f" Modules: {len(config.modules)} modules requested")
|
|
115
|
+
print("-" * 80)
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
summary_url = config.quote_summary_primary_url + ticker
|
|
119
|
+
# Add 30-second timeout to prevent hanging
|
|
120
|
+
summary_response = await asyncio.wait_for(
|
|
121
|
+
session.get(
|
|
122
|
+
summary_url,
|
|
123
|
+
params={
|
|
124
|
+
"modules": ",".join(config.modules),
|
|
125
|
+
"corsDomain": "finance.yahoo.com",
|
|
126
|
+
"formatted": "false",
|
|
127
|
+
"symbol": ticker,
|
|
128
|
+
"lang": "en-US",
|
|
129
|
+
"region": "US",
|
|
130
|
+
},
|
|
131
|
+
),
|
|
132
|
+
timeout=30.0,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
print(f" ✓ Status Code: {summary_response.status_code}")
|
|
136
|
+
print(
|
|
137
|
+
f" ✓ Content-Type: {summary_response.headers.get('content-type', 'N/A')}"
|
|
138
|
+
)
|
|
139
|
+
print(f" ✓ Content-Length: {len(summary_response.content)} bytes")
|
|
140
|
+
|
|
141
|
+
if summary_response.status_code == 200:
|
|
142
|
+
summary_data = summary_response.json()
|
|
143
|
+
|
|
144
|
+
# Export quote summary data if requested
|
|
145
|
+
if export:
|
|
146
|
+
import os
|
|
147
|
+
|
|
148
|
+
export_path = "documentation/reference_data/yfinance_quote_summary_equity.json"
|
|
149
|
+
os.makedirs(os.path.dirname(export_path), exist_ok=True)
|
|
150
|
+
with open(export_path, "w") as f:
|
|
151
|
+
json.dump(summary_data, f, indent=2)
|
|
152
|
+
print(f" ✓ Exported to {export_path}")
|
|
153
|
+
|
|
154
|
+
result = summary_data.get("quoteSummary", {}).get("result", [])
|
|
155
|
+
error = summary_data.get("quoteSummary", {}).get("error")
|
|
156
|
+
|
|
157
|
+
if error:
|
|
158
|
+
print(f" ✗ API Error: {error}")
|
|
159
|
+
elif result:
|
|
160
|
+
print(f" ✓ Data received for {len(result)} ticker(s)")
|
|
161
|
+
|
|
162
|
+
# Show available modules
|
|
163
|
+
modules_present = list(result[0].keys())
|
|
164
|
+
print(
|
|
165
|
+
f" ✓ Available modules ({len(modules_present)}): {', '.join(modules_present)}"
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# Flatten all module data to get total field count
|
|
169
|
+
all_fields = {}
|
|
170
|
+
for module_name in modules_present:
|
|
171
|
+
module_data = result[0].get(module_name)
|
|
172
|
+
if isinstance(module_data, dict):
|
|
173
|
+
all_fields.update(module_data)
|
|
174
|
+
|
|
175
|
+
print(f" ✓ Total flattened fields: {len(all_fields)}")
|
|
176
|
+
print(f"\n All fields from quote_summary_url:")
|
|
177
|
+
for field_name in sorted(all_fields.keys()):
|
|
178
|
+
value = all_fields[field_name]
|
|
179
|
+
# Truncate long values
|
|
180
|
+
if isinstance(value, (dict, list)):
|
|
181
|
+
value_str = str(type(value).__name__)
|
|
182
|
+
else:
|
|
183
|
+
value_str = str(value)[:50]
|
|
184
|
+
print(f" {field_name}: {value_str}")
|
|
185
|
+
else:
|
|
186
|
+
print(" ⚠ Empty result array")
|
|
187
|
+
print(
|
|
188
|
+
f" Raw response: {json.dumps(summary_data, indent=2)[:500]}..."
|
|
189
|
+
)
|
|
190
|
+
else:
|
|
191
|
+
print(f" ✗ Non-200 status code")
|
|
192
|
+
print(f" Response preview: {summary_response.text[:500]}...")
|
|
193
|
+
|
|
194
|
+
except Exception as e:
|
|
195
|
+
print(f" ✗ ERROR: {e}")
|
|
196
|
+
|
|
197
|
+
print()
|
|
198
|
+
|
|
199
|
+
# ===================================================================
|
|
200
|
+
# TEST 3: Quote Summary Fallback URL
|
|
201
|
+
# ===================================================================
|
|
202
|
+
print("📍 TEST 3: QUOTE SUMMARY FALLBACK URL")
|
|
203
|
+
print(f" URL: {config.quote_summary_fallback_url}")
|
|
204
|
+
print(f" Ticker: {ticker}")
|
|
205
|
+
print("-" * 80)
|
|
206
|
+
|
|
207
|
+
try:
|
|
208
|
+
fallback_data = await _get_quote_summary_fallback(session, ticker)
|
|
209
|
+
|
|
210
|
+
if fallback_data:
|
|
211
|
+
print(f" ✓ Data received for ticker")
|
|
212
|
+
print(f" ✓ Total fields: {len(fallback_data)}")
|
|
213
|
+
|
|
214
|
+
print(f"\n All fields from quote_summary_fallback_url:")
|
|
215
|
+
for field_name in sorted(fallback_data.keys()):
|
|
216
|
+
value = fallback_data[field_name]
|
|
217
|
+
# Truncate long values
|
|
218
|
+
if isinstance(value, (dict, list)):
|
|
219
|
+
value_str = str(type(value).__name__)
|
|
220
|
+
else:
|
|
221
|
+
value_str = str(value)[:50]
|
|
222
|
+
print(f" {field_name}: {value_str}")
|
|
223
|
+
|
|
224
|
+
# Compare with primary endpoint
|
|
225
|
+
print(f"\n 📊 FIELD COMPARISON:")
|
|
226
|
+
print(f" Primary endpoint would have returned flattened module data")
|
|
227
|
+
print(
|
|
228
|
+
f" Fallback endpoint returns {len(fallback_data)} direct fields"
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
except Exception as e:
|
|
232
|
+
print(f" ✗ ERROR: {e}")
|
|
233
|
+
|
|
234
|
+
print()
|
|
235
|
+
|
|
236
|
+
# ===================================================================
|
|
237
|
+
# TEST 3.5: ISIN-based Lookup (Pipeline Simulation)
|
|
238
|
+
# ===================================================================
|
|
239
|
+
if isin:
|
|
240
|
+
print("📍 TEST 3.5: ISIN-BASED LOOKUP (PIPELINE SIMULATION)")
|
|
241
|
+
print(
|
|
242
|
+
" Simulating actual pipeline flow: search by ISIN → get symbol → fetch data"
|
|
243
|
+
)
|
|
244
|
+
print("-" * 80)
|
|
245
|
+
|
|
246
|
+
try:
|
|
247
|
+
# Search for the ISIN
|
|
248
|
+
isin_search_response = await session.get(
|
|
249
|
+
config.search_url,
|
|
250
|
+
params={"q": isin},
|
|
251
|
+
)
|
|
252
|
+
isin_search_data = isin_search_response.json()
|
|
253
|
+
isin_quotes = isin_search_data.get("quotes", [])
|
|
254
|
+
|
|
255
|
+
# Filter for EQUITY type only (like search_quotes does)
|
|
256
|
+
isin_equities = [
|
|
257
|
+
q for q in isin_quotes if q.get("quoteType") == "EQUITY"
|
|
258
|
+
]
|
|
259
|
+
|
|
260
|
+
print(f" ✓ Searched for ISIN: {isin}")
|
|
261
|
+
print(f" ✓ Found {len(isin_equities)} EQUITY results")
|
|
262
|
+
|
|
263
|
+
if isin_equities:
|
|
264
|
+
print("\n ISIN Search Results:")
|
|
265
|
+
for i, quote in enumerate(isin_equities, 1):
|
|
266
|
+
symbol = quote.get("symbol", "N/A")
|
|
267
|
+
name = quote.get("longname") or quote.get("shortname", "N/A")
|
|
268
|
+
exchange = quote.get("exchange", "N/A")
|
|
269
|
+
print(f" {i}. {symbol} ({exchange}) - {name}")
|
|
270
|
+
|
|
271
|
+
# Pick the first equity (simplified - pipeline does fuzzy matching)
|
|
272
|
+
chosen_symbol = isin_equities[0].get("symbol")
|
|
273
|
+
print(f"\n → Pipeline would fetch data for: {chosen_symbol}")
|
|
274
|
+
|
|
275
|
+
# Now fetch quote summary for this symbol
|
|
276
|
+
print(f"\n Fetching quote summary for {chosen_symbol}...")
|
|
277
|
+
isin_raw_data = await get_quote_summary(session, chosen_symbol)
|
|
278
|
+
|
|
279
|
+
if isin_raw_data:
|
|
280
|
+
print(f" ✓ Data fetched: {len(isin_raw_data)} fields")
|
|
281
|
+
|
|
282
|
+
# Validate this data
|
|
283
|
+
print(f"\n Validating data from ISIN-based lookup...")
|
|
284
|
+
try:
|
|
285
|
+
yf_data = YFinanceFeedData.model_validate(isin_raw_data)
|
|
286
|
+
coerced = yf_data.model_dump()
|
|
287
|
+
_ = RawEquity.model_validate(coerced)
|
|
288
|
+
print(f" ✓ Validation PASSED for {chosen_symbol}")
|
|
289
|
+
except ValidationError as ve:
|
|
290
|
+
print(f" ✗ Validation FAILED for {chosen_symbol}")
|
|
291
|
+
print(
|
|
292
|
+
f"\n ⚠️ THIS IS THE ACTUAL VALIDATION FAILURE IN THE PIPELINE!"
|
|
293
|
+
)
|
|
294
|
+
print(f"\n Failed fields ({len(ve.errors())}):")
|
|
295
|
+
for err in ve.errors():
|
|
296
|
+
field_name = err["loc"][0] if err["loc"] else "unknown"
|
|
297
|
+
error_msg = err["msg"]
|
|
298
|
+
|
|
299
|
+
# Try to get value from either stage
|
|
300
|
+
if field_name in coerced:
|
|
301
|
+
raw_value = coerced.get(field_name)
|
|
302
|
+
else:
|
|
303
|
+
raw_value = isin_raw_data.get(field_name)
|
|
304
|
+
|
|
305
|
+
print(f"\n ❌ Field: {field_name}")
|
|
306
|
+
print(f" Error: {error_msg}")
|
|
307
|
+
print(f" Raw value: {raw_value!r}")
|
|
308
|
+
print(
|
|
309
|
+
f" Value type: {type(raw_value).__name__}"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
# Show related fields
|
|
313
|
+
if field_name in ["revenue", "revenue_per_share"]:
|
|
314
|
+
print(f" Related fields:")
|
|
315
|
+
for related in ["totalRevenue", "revenuePerShare"]:
|
|
316
|
+
if related in isin_raw_data:
|
|
317
|
+
print(
|
|
318
|
+
f" {related}: {isin_raw_data[related]!r}"
|
|
319
|
+
)
|
|
320
|
+
elif field_name == "trailing_pe":
|
|
321
|
+
print(f" Related fields:")
|
|
322
|
+
for related in ["trailingPE", "forwardPE"]:
|
|
323
|
+
if related in isin_raw_data:
|
|
324
|
+
print(
|
|
325
|
+
f" {related}: {isin_raw_data[related]!r}"
|
|
326
|
+
)
|
|
327
|
+
else:
|
|
328
|
+
print(" ⚠ No EQUITY results found for ISIN")
|
|
329
|
+
|
|
330
|
+
except Exception as e:
|
|
331
|
+
print(f" ✗ ERROR: {e}")
|
|
332
|
+
import traceback
|
|
333
|
+
|
|
334
|
+
traceback.print_exc()
|
|
335
|
+
|
|
336
|
+
print()
|
|
337
|
+
|
|
338
|
+
# ===================================================================
|
|
339
|
+
# TEST 4: Validation Testing
|
|
340
|
+
# ===================================================================
|
|
341
|
+
print("📍 TEST 4: VALIDATION TESTING (Direct Symbol Lookup)")
|
|
342
|
+
print(" Testing Pydantic validation against YFinanceFeedData schema")
|
|
343
|
+
print("-" * 80)
|
|
344
|
+
|
|
345
|
+
try:
|
|
346
|
+
# Fetch raw data using the quote_summary function
|
|
347
|
+
raw_data = await get_quote_summary(session, ticker)
|
|
348
|
+
|
|
349
|
+
if not raw_data:
|
|
350
|
+
print(" ⚠ No data returned from get_quote_summary()")
|
|
351
|
+
else:
|
|
352
|
+
print(f" ✓ Raw data fetched: {len(raw_data)} fields")
|
|
353
|
+
|
|
354
|
+
# Step 1: Try validating with YFinanceFeedData
|
|
355
|
+
print("\n Step 1: Validating with YFinanceFeedData model...")
|
|
356
|
+
try:
|
|
357
|
+
yf_data = YFinanceFeedData.model_validate(raw_data)
|
|
358
|
+
print(" ✓ YFinanceFeedData validation PASSED")
|
|
359
|
+
|
|
360
|
+
# Step 2: Try converting to RawEquity
|
|
361
|
+
print("\n Step 2: Converting to RawEquity model...")
|
|
362
|
+
try:
|
|
363
|
+
coerced = yf_data.model_dump()
|
|
364
|
+
_ = RawEquity.model_validate(coerced)
|
|
365
|
+
print(" ✓ RawEquity validation PASSED")
|
|
366
|
+
print(f" ✓ All validation successful for ticker {ticker}")
|
|
367
|
+
|
|
368
|
+
except ValidationError as ve:
|
|
369
|
+
print(" ✗ RawEquity validation FAILED")
|
|
370
|
+
print(f"\n Failed fields ({len(ve.errors())}):")
|
|
371
|
+
for err in ve.errors():
|
|
372
|
+
field_name = err["loc"][0] if err["loc"] else "unknown"
|
|
373
|
+
error_type = err["type"]
|
|
374
|
+
error_msg = err["msg"]
|
|
375
|
+
|
|
376
|
+
# Get the actual raw value that failed
|
|
377
|
+
raw_value = coerced.get(field_name, "<not found>")
|
|
378
|
+
|
|
379
|
+
print(f"\n ❌ Field: {field_name}")
|
|
380
|
+
print(f" Error: {error_msg}")
|
|
381
|
+
print(f" Type: {error_type}")
|
|
382
|
+
print(f" Raw value: {raw_value!r}")
|
|
383
|
+
print(f" Value type: {type(raw_value).__name__}")
|
|
384
|
+
|
|
385
|
+
except ValidationError as ve:
|
|
386
|
+
print(" ✗ YFinanceFeedData validation FAILED")
|
|
387
|
+
print(f"\n Failed fields ({len(ve.errors())}):")
|
|
388
|
+
for err in ve.errors():
|
|
389
|
+
field_name = err["loc"][0] if err["loc"] else "unknown"
|
|
390
|
+
error_type = err["type"]
|
|
391
|
+
error_msg = err["msg"]
|
|
392
|
+
|
|
393
|
+
# Get the actual raw value that failed
|
|
394
|
+
raw_value = raw_data.get(field_name, "<not found>")
|
|
395
|
+
|
|
396
|
+
print(f"\n ❌ Field: {field_name}")
|
|
397
|
+
print(f" Error: {error_msg}")
|
|
398
|
+
print(f" Type: {error_type}")
|
|
399
|
+
print(f" Raw value: {raw_value!r}")
|
|
400
|
+
print(f" Value type: {type(raw_value).__name__}")
|
|
401
|
+
|
|
402
|
+
# Show context: what other related fields look like
|
|
403
|
+
if field_name in ["revenue", "revenue_per_share"]:
|
|
404
|
+
print(f" Related fields:")
|
|
405
|
+
for related in [
|
|
406
|
+
"totalRevenue",
|
|
407
|
+
"revenuePerShare",
|
|
408
|
+
"revenue",
|
|
409
|
+
"revenue_per_share",
|
|
410
|
+
]:
|
|
411
|
+
if related in raw_data:
|
|
412
|
+
print(
|
|
413
|
+
f" {related}: {raw_data[related]!r}"
|
|
414
|
+
)
|
|
415
|
+
elif field_name == "trailing_pe":
|
|
416
|
+
print(f" Related fields:")
|
|
417
|
+
for related in ["trailingPE", "trailing_pe", "forwardPE"]:
|
|
418
|
+
if related in raw_data:
|
|
419
|
+
print(
|
|
420
|
+
f" {related}: {raw_data[related]!r}"
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
except Exception as e:
|
|
424
|
+
print(f" ✗ ERROR: {e}")
|
|
425
|
+
import traceback
|
|
426
|
+
|
|
427
|
+
traceback.print_exc()
|
|
428
|
+
|
|
429
|
+
print()
|
|
430
|
+
print("=" * 80)
|
|
431
|
+
print("DEBUG COMPLETE")
|
|
432
|
+
print("=" * 80)
|
|
433
|
+
|
|
434
|
+
finally:
|
|
435
|
+
await session.aclose()
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
async def main() -> None:
|
|
439
|
+
"""Main entry point for the debug script."""
|
|
440
|
+
if len(sys.argv) < 2:
|
|
441
|
+
print(
|
|
442
|
+
"Usage: uv run python debug_yfinance.py TICKER [QUERY] [--isin ISIN] [--export]"
|
|
443
|
+
)
|
|
444
|
+
print("\nExamples:")
|
|
445
|
+
print(" uv run python debug_yfinance.py BKSC")
|
|
446
|
+
print(" uv run python debug_yfinance.py AIT --isin GG00BB0RDB98")
|
|
447
|
+
print(" uv run python debug_yfinance.py CMC --isin GB00BL6NGV24")
|
|
448
|
+
print(" uv run python debug_yfinance.py AAPL --export")
|
|
449
|
+
sys.exit(1)
|
|
450
|
+
|
|
451
|
+
ticker = sys.argv[1].upper()
|
|
452
|
+
query = None
|
|
453
|
+
isin = None
|
|
454
|
+
export = False
|
|
455
|
+
|
|
456
|
+
# Parse optional arguments
|
|
457
|
+
i = 2
|
|
458
|
+
while i < len(sys.argv):
|
|
459
|
+
if sys.argv[i] == "--isin" and i + 1 < len(sys.argv):
|
|
460
|
+
isin = sys.argv[i + 1]
|
|
461
|
+
i += 2
|
|
462
|
+
elif sys.argv[i] == "--export":
|
|
463
|
+
export = True
|
|
464
|
+
i += 1
|
|
465
|
+
else:
|
|
466
|
+
query = sys.argv[i]
|
|
467
|
+
i += 1
|
|
468
|
+
|
|
469
|
+
await debug_ticker(ticker, query, isin, export)
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
if __name__ == "__main__":
|
|
473
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# data_integrity_analysis/__init__.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Data Integrity Analysis package for Equity Aggregator.
|
|
5
|
+
|
|
6
|
+
This package provides comprehensive data quality analysis for canonical equity
|
|
7
|
+
records, examining financial outliers, temporal anomalies, data consistency,
|
|
8
|
+
identifier quality, and completeness metrics.
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
python -m examples.data_integrity_analysis
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .main import main, run_analysis
|
|
15
|
+
from .models import AnalysisSettings, Finding, SectionReport, default_settings
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"AnalysisSettings",
|
|
19
|
+
"Finding",
|
|
20
|
+
"SectionReport",
|
|
21
|
+
"default_settings",
|
|
22
|
+
"main",
|
|
23
|
+
"run_analysis",
|
|
24
|
+
]
|