wbfdm 1.46.4__tar.gz → 1.46.6__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.
Potentially problematic release.
This version of wbfdm might be problematic. Click here for more details.
- {wbfdm-1.46.4 → wbfdm-1.46.6}/PKG-INFO +1 -1
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/dataloaders/market_data.py +47 -44
- wbfdm-1.46.6/wbfdm/contrib/qa/dataloaders/utils.py +68 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/sync/utils.py +14 -5
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/dataloaders/protocols.py +1 -1
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/filters/classifications.py +2 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/filters/instruments.py +2 -9
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/filters/utils.py +10 -1
- wbfdm-1.46.6/wbfdm/migrations/0030_alter_relatedinstrumentthroughmodel_related_type.py +18 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/instrument_relationships.py +1 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tasks.py +2 -2
- wbfdm-1.46.4/wbfdm/contrib/qa/dataloaders/utils.py +0 -22
- {wbfdm-1.46.4 → wbfdm-1.46.6}/.gitignore +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/pyproject.toml +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/esg.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/instrument_lists.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/instrument_requests.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/instruments_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/admin/options.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/esg/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/esg/enums.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/esg/esg_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/esg/utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/financial_analysis/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/financial_analysis/financial_metric_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/financial_analysis/financial_ratio_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/financial_analysis/financial_statistics_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/financial_analysis/statement_with_estimates.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/financial_analysis/utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/technical_analysis/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/technical_analysis/technical_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/technical_analysis/traces.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/apps.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/backends/dto.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/dsws/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/dsws/client.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/dsws/dataloaders/market_data.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/internal/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/internal/dataloaders/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/internal/dataloaders/market_data.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/admin/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/admin/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/admin/metrics.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/apps.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/backends/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/backends/base.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/backends/performances.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/backends/statistics.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/decorators.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/dispatch.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/dto.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/exceptions.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/factories.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/filters.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/migrations/0001_initial.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/migrations/0002_remove_instrumentmetric_unique_instrument_metric_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/migrations/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/models.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/orchestrators.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/registry.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/serializers.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tasks.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/backends/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/backends/test_performances.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/backends/test_statistics.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/conftest.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/test_dto.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/test_models.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/test_tasks.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/tests/test_viewsets.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/urls.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/viewsets/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/viewsets/configs/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/viewsets/configs/display.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/viewsets/configs/menus.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/viewsets/configs/utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/viewsets/mixins.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/metric/viewsets/viewsets.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/client.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/dataloaders/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/dataloaders/esg.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/dataloaders/esg_controversies.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/sync.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/tests/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/tests/conftest.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/msci/tests/test_client.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/apps.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/database_routers.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/dataloaders/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/dataloaders/adjustments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/dataloaders/corporate_actions.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/dataloaders/financials.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/dataloaders/officers.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/dataloaders/reporting_dates.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/dataloaders/statements.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/jinja2/qa/sql/companies.sql +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/base_estimates.sql +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/calendarized.sql +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/complete.sql +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/estimates.sql +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/financials.sql +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/jinja2/qa/sql/instruments.sql +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/jinja2/qa/sql/quotes.sql +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/sync/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/sync/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/contrib/qa/tasks.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/dataloaders/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/dataloaders/cache.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/dataloaders/proxies.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/dataloaders/types.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/dynamic_preferences_registry.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/enums.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/controversies.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/instrument_list.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/instruments_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/factories/options.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/figures/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/figures/financials/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/figures/financials/financial_analysis_charts.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/figures/financials/financials_charts.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/filters/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/filters/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/filters/financials.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/filters/financials_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/filters/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/cbinsights/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/cbinsights/deals.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/cbinsights/equities.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/cbinsights/mixin.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/cbinsights/utils/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/cbinsights/utils/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/cbinsights/utils/client.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/daily_fundamental.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/fiscal_period.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/forecast.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/fundamental.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/geographic_segment.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/instrument.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/instrument_price.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/mixin.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/utils/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/backends/refinitiv/utils/controller.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/handlers/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/handlers/instrument.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/handlers/instrument_list.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/handlers/instrument_price.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/handlers/option.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/handlers/private_equities.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/cbinsights/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/cbinsights/deals.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/cbinsights/equities.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/cbinsights/fundamentals.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/refinitiv/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/refinitiv/daily_fundamental.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/refinitiv/forecast.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/refinitiv/fundamental.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/refinitiv/geographic_segment.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/refinitiv/instrument.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/refinitiv/instrument_price.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/parsers/refinitiv/utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/resources/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/resources/classification.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/resources/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/import_export/resources/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/jinja2.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/management/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/menu.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0001_initial.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0002_rename_statements_instrumentlookup_financials_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0003_instrument_estimate_backend_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0004_rename_financials_instrumentlookup_statements_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0005_instrument_corporate_action_backend.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0006_instrument_officer_backend.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0007_instrument_country_instrument_currency_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0008_controversy.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0009_alter_controversy_flag_alter_controversy_initiated_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0010_classification_classificationgroup_deal_exchange_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0011_delete_instrumentlookup_instrument_corporate_actions_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0012_instrumentprice_created_instrumentprice_modified.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0013_instrument_is_investable_universe_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0014_alter_controversy_instrument.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0015_instrument_instrument_investible_index.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0016_instrumenttype_name_repr.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0017_instrument_instrument_security_index.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0018_instrument_instrument_level_index.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0019_alter_controversy_source.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0020_optionaggregate_option_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0021_delete_instrumentdailystatistics.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0022_instrument_cusip_option_open_interest_20d_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0023_instrument_unique_ric_instrument_unique_rmc_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0024_option_open_interest_10d_option_volume_10d_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0025_instrument_is_primary_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0026_instrument_is_cash_equivalent.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0027_remove_instrument_unique_ric_and_more.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0028_instrumentprice_annualized_daily_volatility.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/0029_alter_instrumentprice_volume.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/migrations/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/esg/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/esg/controversies.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/exchanges/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/exchanges/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/fields.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/fk_fields.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/indicators.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/instrument_lists.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/instrument_requests.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/llm/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/llm/create_instrument_news_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/mixin/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/mixin/financials_computed.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/mixin/financials_serializer_fields.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/mixin/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/options.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/private_equities.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/querysets.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/models/instruments/utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/preferences.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/esg.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/instruments/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/instruments/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/instruments/instrument_lists.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/instruments/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/instruments/instrument_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/instruments/instrument_requests.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/instruments/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/instruments/mixins.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/serializers/officers.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/signals.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/sync/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/sync/abstract.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/sync/runner.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/analysis/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/analysis/financial_analysis/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/analysis/financial_analysis/test_statement_with_estimates.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/analysis/financial_analysis/test_utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/analysis/test_esg.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/conftest.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/dataloaders/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/dataloaders/test_cache.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/models/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/models/test_classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/models/test_exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/models/test_instrument_list.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/models/test_instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/models/test_instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/models/test_merge.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/models/test_options.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/test_tasks.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/tests/tests.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/urls.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/buttons/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/buttons/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/buttons/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/buttons/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/buttons/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/esg.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/financial_summary.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/instrument_lists.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/instrument_requests.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/instruments_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/monthly_performances.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/officers.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/statement_with_estimates.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/display/statements.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/esg.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/financials_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/instrument_lists.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/instrument_requests.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/instruments_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/endpoints/statements.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/menus/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/menus/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/menus/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/menus/instrument_lists.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/menus/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/menus/instruments_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/esg.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/financial_ratio_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/financials_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/instrument_requests.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/instruments_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/market_data.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/configs/titles/statement_with_estimates.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/esg.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/exchanges.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/financial_analysis/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/financial_analysis/financial_metric_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/financial_analysis/financial_ratio_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/financial_analysis/financial_summary.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/financial_analysis/statement_with_estimates.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/classifications.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/financials_analysis.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/instrument_lists.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/instrument_prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/instrument_requests.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/instruments.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/instruments_relationships.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/instruments/utils.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/market_data.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/mixins.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/officers.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/prices.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/statements/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/statements/statements.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/technical_analysis/__init__.py +0 -0
- {wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/viewsets/technical_analysis/monthly_performances.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wbfdm
|
|
3
|
-
Version: 1.46.
|
|
3
|
+
Version: 1.46.6
|
|
4
4
|
Summary: The workbench module ensures rapid access to diverse financial data (market, fundamental, forecasts, ESG), with features for storing instruments, classifying them, and conducting financial analysis.
|
|
5
5
|
Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
|
|
6
6
|
Requires-Dist: roman==4.*
|
|
@@ -3,11 +3,11 @@ from datetime import date
|
|
|
3
3
|
from enum import Enum
|
|
4
4
|
from functools import reduce
|
|
5
5
|
from itertools import batched
|
|
6
|
-
from typing import Iterator
|
|
6
|
+
from typing import TYPE_CHECKING, Iterator
|
|
7
7
|
|
|
8
8
|
import pypika as pk
|
|
9
9
|
from django.db import ProgrammingError, connections
|
|
10
|
-
from pypika import Column, MSSQLQuery
|
|
10
|
+
from pypika import Case, Column, MSSQLQuery
|
|
11
11
|
from pypika import functions as fn
|
|
12
12
|
from pypika.enums import Order, SqlTypes
|
|
13
13
|
from pypika.terms import LiteralValue, ValueWrapper
|
|
@@ -19,24 +19,27 @@ from wbfdm.dataloaders.protocols import MarketDataProtocol
|
|
|
19
19
|
from wbfdm.dataloaders.types import MarketDataDict
|
|
20
20
|
from wbfdm.enums import Frequency, MarketData
|
|
21
21
|
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
pass
|
|
24
|
+
|
|
22
25
|
|
|
23
26
|
class DS2MarketData(Enum):
|
|
24
|
-
OPEN =
|
|
25
|
-
CLOSE =
|
|
26
|
-
HIGH =
|
|
27
|
-
LOW =
|
|
28
|
-
BID =
|
|
29
|
-
ASK =
|
|
30
|
-
VWAP =
|
|
31
|
-
VOLUME =
|
|
32
|
-
MARKET_CAPITALIZATION =
|
|
33
|
-
SHARES_OUTSTANDING =
|
|
27
|
+
OPEN = "Open_"
|
|
28
|
+
CLOSE = "Close_"
|
|
29
|
+
HIGH = "High"
|
|
30
|
+
LOW = "Low"
|
|
31
|
+
BID = "Bid"
|
|
32
|
+
ASK = "Ask"
|
|
33
|
+
VWAP = "VWAP"
|
|
34
|
+
VOLUME = "Volume"
|
|
35
|
+
MARKET_CAPITALIZATION = "MktCap"
|
|
36
|
+
SHARES_OUTSTANDING = "NumShrs"
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
37
40
|
def market_data(
|
|
38
41
|
self,
|
|
39
|
-
values: list[MarketData]
|
|
42
|
+
values: list[MarketData] = [MarketData.CLOSE],
|
|
40
43
|
from_date: date | None = None,
|
|
41
44
|
to_date: date | None = None,
|
|
42
45
|
exact_date: date | None = None,
|
|
@@ -60,17 +63,10 @@ class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
|
60
63
|
lookup = {
|
|
61
64
|
f"{k[0]},{k[1]}": v for k, v in self.entities.values_list("dl_parameters__market_data__parameters", "id")
|
|
62
65
|
}
|
|
63
|
-
value_mapping = [(DS2MarketData[x.name].value, x.value) for x in values or []]
|
|
64
66
|
|
|
65
67
|
# Define tables
|
|
66
68
|
pricing = pk.Table("vw_DS2Pricing")
|
|
67
|
-
market_val = pk.Table("
|
|
68
|
-
fx_code = pk.Table("DS2FxCode")
|
|
69
|
-
fx = pk.Table("DS2FxRate")
|
|
70
|
-
|
|
71
|
-
quotes = pk.Table("DS2CtryQtInfo")
|
|
72
|
-
securities = pk.Table("DS2Security")
|
|
73
|
-
securities2 = pk.Table("DS2Security", alias="securities2")
|
|
69
|
+
market_val = pk.Table("vw_DS2MktCap")
|
|
74
70
|
|
|
75
71
|
mapping, create_mapping_table = create_table(
|
|
76
72
|
"#ds2infoexchcode", Column("InfoCode", SqlTypes.INTEGER), Column("ExchIntCode", SqlTypes.INTEGER)
|
|
@@ -87,14 +83,6 @@ class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
|
87
83
|
fn.Cast(pricing.MarketDate, SqlTypes.DATE).as_("valuation_date"),
|
|
88
84
|
ValueWrapper("qa-ds2").as_("source"),
|
|
89
85
|
)
|
|
90
|
-
.join(quotes)
|
|
91
|
-
.on_field("InfoCode")
|
|
92
|
-
.join(securities)
|
|
93
|
-
.on(quotes.DsSecCode == securities.DsSecCode)
|
|
94
|
-
.join(securities2)
|
|
95
|
-
.on((securities2.DsCmpyCode == securities.DsCmpyCode) & securities2.IsMajorSec == "Y")
|
|
96
|
-
.left_join(market_val)
|
|
97
|
-
.on((securities2.PrimQtInfoCode == market_val.InfoCode) & (pricing.MarketDate == market_val.ValDate))
|
|
98
86
|
# We join on _codes, which removes all instruments not in _codes - implicit where
|
|
99
87
|
.join(mapping)
|
|
100
88
|
.on((pricing.InfoCode == mapping.InfoCode) & (pricing.ExchIntCode == mapping.ExchIntCode))
|
|
@@ -102,31 +90,46 @@ class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
|
102
90
|
.orderby(pricing.MarketDate, order=Order.desc)
|
|
103
91
|
)
|
|
104
92
|
|
|
105
|
-
#
|
|
93
|
+
# if a target currency is required, we join on the fx tables and set the currency to the desired one
|
|
94
|
+
# otherwise we just set the currency to whatever the currency is from the instrument
|
|
95
|
+
fx_rate = None
|
|
106
96
|
if target_currency:
|
|
97
|
+
query = query.select(ValueWrapper(target_currency).as_("currency"))
|
|
98
|
+
fx_code = pk.Table("DS2FxCode")
|
|
99
|
+
fx_rate = pk.Table("DS2FxRate")
|
|
107
100
|
query = (
|
|
108
|
-
query
|
|
109
|
-
|
|
110
|
-
*[
|
|
111
|
-
(LiteralValue(value[0][0]) * fn.Coalesce(fx.midrate, 1) * value[0][1]).as_(value[1])
|
|
112
|
-
for value in value_mapping
|
|
113
|
-
],
|
|
114
|
-
)
|
|
101
|
+
query
|
|
102
|
+
# Join FX code table matching currencies and ensuring SPOT rate type
|
|
115
103
|
.left_join(fx_code)
|
|
116
104
|
.on(
|
|
117
|
-
(fx_code.FromCurrCode ==
|
|
118
|
-
& (fx_code.ToCurrCode ==
|
|
105
|
+
(fx_code.FromCurrCode == pricing.Currency)
|
|
106
|
+
& (fx_code.ToCurrCode == target_currency)
|
|
119
107
|
& (fx_code.RateTypeCode == "SPOT")
|
|
120
108
|
)
|
|
121
|
-
|
|
122
|
-
.
|
|
109
|
+
# Join FX rate table matching internal code and date
|
|
110
|
+
.left_join(fx_rate)
|
|
111
|
+
.on((fx_rate.ExRateIntCode == fx_code.ExRateIntCode) & (fx_rate.ExRateDate == pricing.MarketDate))
|
|
112
|
+
# We filter out rows which do not have a proper fx rate (we exclude same currency conversions)
|
|
113
|
+
.where((Case().when(pricing.Currency == target_currency, 1).else_(fx_rate.midrate).isnotnull()))
|
|
123
114
|
)
|
|
115
|
+
|
|
124
116
|
else:
|
|
125
|
-
query = query.select(
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
query = query.select(pricing.Currency.as_("currency"))
|
|
118
|
+
|
|
119
|
+
# if market cap or shares outstanding are required we need to join with an additional table
|
|
120
|
+
if MarketData.MARKET_CAPITALIZATION in values or MarketData.SHARES_OUTSTANDING in values:
|
|
121
|
+
query = query.join(market_val).on(
|
|
122
|
+
(pricing.InfoCode == market_val.InfoCode) & (pricing.MarketDate == market_val.MarketDate)
|
|
128
123
|
)
|
|
129
124
|
|
|
125
|
+
for market_data in values:
|
|
126
|
+
ds2_value = DS2MarketData[market_data.name].value
|
|
127
|
+
value = LiteralValue(ds2_value)
|
|
128
|
+
if fx_rate and market_data is not MarketData.SHARES_OUTSTANDING:
|
|
129
|
+
value /= Case().when(pricing.Currency == target_currency, 1).else_(fx_rate.midrate)
|
|
130
|
+
|
|
131
|
+
query = query.select(value.as_(market_data.value))
|
|
132
|
+
|
|
130
133
|
# Add conditional where clauses
|
|
131
134
|
if from_date:
|
|
132
135
|
query = query.where(pricing.MarketDate >= from_date)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from pypika import Case, Column, Criterion, Field, MSSQLQuery, Table
|
|
4
|
+
from pypika.terms import ValueWrapper
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from pypika.queries import CreateQueryBuilder, QueryBuilder
|
|
8
|
+
from pypika.terms import Term
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def compile_source(source: str) -> "Term":
|
|
12
|
+
return ValueWrapper(source).as_("source")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
SOURCE_DS2 = compile_source("qa-ds2")
|
|
16
|
+
SOURCE_RKD = compile_source("qa-rkd")
|
|
17
|
+
SOURCE_IBES = compile_source("qa-ibes")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def create_table(tablename: "str", *columns: "Column") -> tuple[Table, "CreateQueryBuilder"]:
|
|
21
|
+
table = Table(tablename)
|
|
22
|
+
return table, MSSQLQuery.create_table(table).columns(*columns)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_currency_fx_rate(
|
|
26
|
+
query: "QueryBuilder", alias_prefix: str, from_ccy: str | Field, to_ccy: str | Field, fx_date: str | Criterion
|
|
27
|
+
) -> tuple["QueryBuilder", Criterion]:
|
|
28
|
+
"""Gets the currency exchange rate with fallback to 1 if rate not found.
|
|
29
|
+
|
|
30
|
+
Extends a query with FX table joins to retrieve currency conversion rates. Uses left joins
|
|
31
|
+
and provides a default rate of 1 when no conversion rate exists, effectively making the
|
|
32
|
+
conversion neutral in such cases.
|
|
33
|
+
|
|
34
|
+
Warning:
|
|
35
|
+
The alias_prefix must be unique across the entire query chain. Reusing the same
|
|
36
|
+
prefix in multiple calls will cause table alias conflicts, leading to incorrect
|
|
37
|
+
results or SQL errors. Each call to this function should use a distinct prefix.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
query (QueryBuilder): Base query to extend with FX-related joins
|
|
41
|
+
alias_prefix (str): Prefix for table aliases to prevent naming conflicts in joins.
|
|
42
|
+
Must be unique across the entire query chain.
|
|
43
|
+
from_ccy (str | pk.Field): Source currency code or Field to convert from
|
|
44
|
+
to_ccy (str | pk.Field): Target currency code or Field to convert to
|
|
45
|
+
fx_date (Any): Date for which to get the exchange rate
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
tuple[QueryBuilder, pk.Criterion]: A tuple containing:
|
|
49
|
+
- Modified query with FX table joins
|
|
50
|
+
- Coalesced midrate (defaults to 1 if no rate found)
|
|
51
|
+
"""
|
|
52
|
+
# Create aliased FX tables to avoid naming conflicts in complex queries
|
|
53
|
+
fx_code = Table("DS2FxCode", alias=f"{alias_prefix}DS2FxCode")
|
|
54
|
+
fx_rate = Table("DS2FxRate", alias=f"{alias_prefix}DS2FxRate")
|
|
55
|
+
# Build query with FX table joins
|
|
56
|
+
query = (
|
|
57
|
+
query
|
|
58
|
+
# Join FX code table matching currencies and ensuring SPOT rate type
|
|
59
|
+
.left_join(fx_code)
|
|
60
|
+
.on((fx_code.FromCurrCode == from_ccy) & (fx_code.ToCurrCode == to_ccy) & (fx_code.RateTypeCode == "SPOT"))
|
|
61
|
+
# Join FX rate table matching internal code and date
|
|
62
|
+
.left_join(fx_rate)
|
|
63
|
+
.on((fx_rate.ExRateIntCode == fx_code.ExRateIntCode) & (fx_rate.ExRateDate == fx_date))
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Return query and coalesced rate (falls back to 1 if no rate found)
|
|
67
|
+
fx = Case().when(from_ccy == to_ccy, 1).else_(fx_rate.midrate)
|
|
68
|
+
return (query, fx)
|
|
@@ -114,7 +114,19 @@ def convert_data(data, parent_source: str | None = None) -> dict:
|
|
|
114
114
|
def get_instrument_from_data(data, parent_source: str | None = None) -> Instrument | None:
|
|
115
115
|
if len(data.keys()) == 0:
|
|
116
116
|
return None
|
|
117
|
-
|
|
117
|
+
|
|
118
|
+
defaults = convert_data(data, parent_source)
|
|
119
|
+
try:
|
|
120
|
+
instrument = Instrument.objects.get(source=defaults["source"], source_id=defaults["source_id"])
|
|
121
|
+
instrument.dl_parameters.update(
|
|
122
|
+
defaults.pop("dl_parameters")
|
|
123
|
+
) # we need to update the existing dl parameters to not override its existing value
|
|
124
|
+
for k, v in defaults.items():
|
|
125
|
+
setattr(instrument, k, v)
|
|
126
|
+
|
|
127
|
+
except Instrument.DoesNotExist:
|
|
128
|
+
instrument = Instrument(**defaults)
|
|
129
|
+
|
|
118
130
|
instrument.pre_save()
|
|
119
131
|
instrument.computed_str = instrument.compute_str()
|
|
120
132
|
if (
|
|
@@ -198,10 +210,7 @@ def update_or_create_item(
|
|
|
198
210
|
source_id=external_id,
|
|
199
211
|
defaults=defaults,
|
|
200
212
|
)
|
|
201
|
-
|
|
202
|
-
for key, value in dl_parameters.items():
|
|
203
|
-
instrument.dl_parameters[key] = value
|
|
204
|
-
|
|
213
|
+
instrument.dl_parameters.update(dl_parameters)
|
|
205
214
|
instrument.save()
|
|
206
215
|
|
|
207
216
|
return instrument
|
|
@@ -39,7 +39,7 @@ class AdjustmentsProtocol(Protocol):
|
|
|
39
39
|
class MarketDataProtocol(Protocol):
|
|
40
40
|
def market_data(
|
|
41
41
|
self,
|
|
42
|
-
values: list[MarketData]
|
|
42
|
+
values: list[MarketData] = [MarketData.CLOSE],
|
|
43
43
|
from_date: date | None = None,
|
|
44
44
|
to_date: date | None = None,
|
|
45
45
|
exact_date: date | None = None,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from wbcore import filters as wb_filters
|
|
2
2
|
|
|
3
|
+
from wbfdm.filters.utils import _get_default_classification_group_id
|
|
3
4
|
from wbfdm.models import (
|
|
4
5
|
Classification,
|
|
5
6
|
ClassificationGroup,
|
|
@@ -88,6 +89,7 @@ class InstrumentClassificationThroughModelViewFilterSet(wb_filters.FilterSet):
|
|
|
88
89
|
endpoint=ClassificationGroup.get_representation_endpoint(),
|
|
89
90
|
value_key=ClassificationGroup.get_representation_value_key(),
|
|
90
91
|
label_key=ClassificationGroup.get_representation_label_key(),
|
|
92
|
+
default=_get_default_classification_group_id,
|
|
91
93
|
)
|
|
92
94
|
|
|
93
95
|
class Meta:
|
|
@@ -5,7 +5,7 @@ from psycopg.types.range import DateRange
|
|
|
5
5
|
from wbcore import filters as wb_filters
|
|
6
6
|
from wbcore.contrib.tags.filters import TagFilterMixin
|
|
7
7
|
|
|
8
|
-
from wbfdm.filters.utils import get_earliest_date, get_latest_date
|
|
8
|
+
from wbfdm.filters.utils import _get_default_classification_group_id, get_earliest_date, get_latest_date
|
|
9
9
|
from wbfdm.models.instruments import (
|
|
10
10
|
ClassificationGroup,
|
|
11
11
|
Instrument,
|
|
@@ -13,7 +13,6 @@ from wbfdm.models.instruments import (
|
|
|
13
13
|
InstrumentFavoriteGroup,
|
|
14
14
|
)
|
|
15
15
|
from wbfdm.models.instruments.classifications import Classification
|
|
16
|
-
from wbfdm.preferences import get_default_classification_group
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
def get_default_favorite_group(field, request, view):
|
|
@@ -156,12 +155,6 @@ class InstrumentFilterSet(TagFilterMixin, InstrumentFavoriteGroupFilterSet):
|
|
|
156
155
|
hidden_fields = ["id__in", "is_managed", "is_security", "level"]
|
|
157
156
|
|
|
158
157
|
|
|
159
|
-
def _get_default_classification_group_id(*args, **kwargs):
|
|
160
|
-
if group := get_default_classification_group():
|
|
161
|
-
return group.id
|
|
162
|
-
return None
|
|
163
|
-
|
|
164
|
-
|
|
165
158
|
class BaseClassifiedInstrumentFilterSet(TagFilterMixin, wb_filters.FilterSet):
|
|
166
159
|
classification_group = wb_filters.ModelChoiceFilter(
|
|
167
160
|
label="Classification Group",
|
|
@@ -169,7 +162,7 @@ class BaseClassifiedInstrumentFilterSet(TagFilterMixin, wb_filters.FilterSet):
|
|
|
169
162
|
endpoint=ClassificationGroup.get_representation_endpoint(),
|
|
170
163
|
value_key=ClassificationGroup.get_representation_value_key(),
|
|
171
164
|
label_key=ClassificationGroup.get_representation_label_key(),
|
|
172
|
-
default=_get_default_classification_group_id
|
|
165
|
+
default=_get_default_classification_group_id,
|
|
173
166
|
method="fake_filter",
|
|
174
167
|
required=True,
|
|
175
168
|
)
|
|
@@ -4,7 +4,16 @@ from pandas.tseries.offsets import BDay, BMonthBegin, BMonthEnd
|
|
|
4
4
|
from psycopg.types.range import DateRange
|
|
5
5
|
from wbcore.utils.date import current_quarter_date_start
|
|
6
6
|
|
|
7
|
-
from wbfdm.models import Instrument
|
|
7
|
+
from wbfdm.models import Classification, Instrument
|
|
8
|
+
from wbfdm.preferences import get_default_classification_group
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _get_default_classification_group_id(field, request, view, **kwargs):
|
|
12
|
+
if classification_id := view.kwargs.get("classification_id", None):
|
|
13
|
+
return Classification.objects.get(id=classification_id).group.id
|
|
14
|
+
if group := get_default_classification_group():
|
|
15
|
+
return group.id
|
|
16
|
+
return None
|
|
8
17
|
|
|
9
18
|
|
|
10
19
|
def get_earliest_date(field, request, view):
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.0.12 on 2025-02-20 14:48
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('wbfdm', '0029_alter_instrumentprice_volume'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='relatedinstrumentthroughmodel',
|
|
15
|
+
name='related_type',
|
|
16
|
+
field=models.CharField(choices=[('BENCHMARK', 'Benchmark'), ('PEER', 'Peer'), ('RISK_INSTRUMENT', 'Risk Instrument'), ('TRACKER', 'Tracker')], default='BENCHMARK', max_length=32),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -140,6 +140,7 @@ class RelatedInstrumentThroughModel(models.Model):
|
|
|
140
140
|
BENCHMARK = "BENCHMARK", "Benchmark"
|
|
141
141
|
PEER = "PEER", "Peer"
|
|
142
142
|
RISK_INSTRUMENT = "RISK_INSTRUMENT", "Risk Instrument"
|
|
143
|
+
TRACKER = "TRACKER", "Tracker"
|
|
143
144
|
|
|
144
145
|
instrument = models.ForeignKey(
|
|
145
146
|
"wbfdm.Instrument",
|
|
@@ -55,8 +55,8 @@ def update_of_investable_universe_data(
|
|
|
55
55
|
for instrument in tqdm(instruments, total=instruments.count()):
|
|
56
56
|
try:
|
|
57
57
|
prices.extend(list(instrument.get_price_objects(start=start, end=end, clear=clear)))
|
|
58
|
-
except
|
|
59
|
-
print(f"Connection error while processing instrument {instrument}") # noqa
|
|
58
|
+
except Exception as e:
|
|
59
|
+
print(f"Connection error while processing instrument {instrument}: {str(e)}") # noqa
|
|
60
60
|
Instrument.bulk_save_instrument_prices(prices)
|
|
61
61
|
investable_universe_updated.send(sender=Instrument, end_date=end)
|
|
62
62
|
if with_background_tasks:
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING
|
|
2
|
-
|
|
3
|
-
from pypika import Column, MSSQLQuery, Table
|
|
4
|
-
from pypika.terms import ValueWrapper
|
|
5
|
-
|
|
6
|
-
if TYPE_CHECKING:
|
|
7
|
-
from pypika.queries import CreateQueryBuilder
|
|
8
|
-
from pypika.terms import Term
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def compile_source(source: str) -> "Term":
|
|
12
|
-
return ValueWrapper(source).as_("source")
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
SOURCE_DS2 = compile_source("qa-ds2")
|
|
16
|
-
SOURCE_RKD = compile_source("qa-rkd")
|
|
17
|
-
SOURCE_IBES = compile_source("qa-ibes")
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def create_table(tablename: "str", *columns: "Column") -> tuple[Table, "CreateQueryBuilder"]:
|
|
21
|
-
table = Table(tablename)
|
|
22
|
-
return table, MSSQLQuery.create_table(table).columns(*columns)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/financial_analysis/financial_metric_analysis.py
RENAMED
|
File without changes
|
|
File without changes
|
{wbfdm-1.46.4 → wbfdm-1.46.6}/wbfdm/analysis/financial_analysis/financial_statistics_analysis.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|