wbfdm 1.55.9__tar.gz → 1.55.10rc0__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.55.9 → wbfdm-1.55.10rc0}/PKG-INFO +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/dsws/client.py +3 -3
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/dsws/dataloaders/market_data.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/internal/dataloaders/market_data.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/backends/base.py +2 -2
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/backends/statistics.py +2 -2
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/exceptions.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/models.py +6 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/orchestrators.py +4 -4
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/viewsets/mixins.py +6 -6
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/client.py +3 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/database_routers.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/adjustments.py +2 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/corporate_actions.py +2 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/market_data.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/officers.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/sync/utils.py +4 -2
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/dataloaders/protocols.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/figures/financials/financial_analysis_charts.py +2 -8
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/filters/instruments.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/cbinsights/utils/client.py +8 -8
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/utils/controller.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/handlers/instrument.py +2 -2
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/cbinsights/equities.py +2 -3
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/jinja2.py +2 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/esg/controversies.py +3 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/fields.py +2 -2
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/fk_fields.py +3 -3
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/instrument_relationships.py +3 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/instruments.py +6 -6
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/mixin/instruments.py +2 -2
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/options.py +6 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/private_equities.py +3 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/analysis/financial_analysis/test_statement_with_estimates.py +0 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/instruments_relationships.py +3 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/instrument_prices.py +2 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/esg.py +2 -2
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/financial_analysis/financial_metric_analysis.py +2 -2
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/financial_analysis/financial_ratio_analysis.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/financial_analysis/financial_summary.py +6 -6
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/financials_analysis.py +8 -11
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/market_data.py +1 -1
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/.gitignore +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/pyproject.toml +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/esg.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/instrument_lists.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/instrument_requests.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/instruments_relationships.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/admin/options.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/esg/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/esg/enums.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/esg/esg_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/esg/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/financial_analysis/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/financial_analysis/change_point_detection.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/financial_analysis/financial_metric_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/financial_analysis/financial_ratio_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/financial_analysis/financial_statistics_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/financial_analysis/statement_with_estimates.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/financial_analysis/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/technical_analysis/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/technical_analysis/technical_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/technical_analysis/traces.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/analysis/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/apps.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/backends/dto.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/dsws/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/internal/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/internal/dataloaders/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/admin/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/admin/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/admin/metrics.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/apps.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/backends/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/backends/performances.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/backends/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/decorators.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/dispatch.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/dto.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/factories.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/filters.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/migrations/0001_initial.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/migrations/0002_remove_instrumentmetric_unique_instrument_metric_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/migrations/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/registry.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/serializers.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/signals.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tasks.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/backends/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/backends/test_performances.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/backends/test_statistics.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/conftest.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/test_dto.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/test_models.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/test_tasks.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/tests/test_viewsets.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/urls.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/viewsets/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/viewsets/configs/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/viewsets/configs/display.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/viewsets/configs/menus.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/viewsets/configs/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/metric/viewsets/viewsets.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/dataloaders/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/dataloaders/esg.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/dataloaders/esg_controversies.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/sync.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/tests/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/tests/conftest.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/msci/tests/test_client.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/apps.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/financials.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/fx_rates.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/reporting_dates.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/statements.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/dataloaders/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/jinja2/qa/sql/companies.sql +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/base_estimates.sql +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/calendarized.sql +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/complete.sql +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/estimates.sql +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/financials.sql +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/jinja2/qa/sql/instruments.sql +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/jinja2/qa/sql/quotes.sql +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/sync/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/sync/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/contrib/qa/tasks.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/dataloaders/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/dataloaders/cache.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/dataloaders/proxies.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/dataloaders/types.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/dynamic_preferences_registry.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/enums.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/controversies.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/instrument_list.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/instruments_relationships.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/factories/options.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/figures/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/figures/financials/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/figures/financials/financials_charts.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/filters/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/filters/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/filters/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/filters/financials.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/filters/financials_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/filters/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/filters/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/cbinsights/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/cbinsights/deals.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/cbinsights/equities.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/cbinsights/mixin.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/cbinsights/utils/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/cbinsights/utils/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/daily_fundamental.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/fiscal_period.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/forecast.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/fundamental.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/geographic_segment.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/instrument.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/instrument_price.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/mixin.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/utils/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/handlers/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/handlers/instrument_list.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/handlers/instrument_price.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/handlers/option.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/handlers/private_equities.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/cbinsights/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/cbinsights/deals.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/cbinsights/fundamentals.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/refinitiv/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/refinitiv/daily_fundamental.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/refinitiv/forecast.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/refinitiv/fundamental.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/refinitiv/geographic_segment.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/refinitiv/instrument.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/refinitiv/instrument_price.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/parsers/refinitiv/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/resources/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/resources/classification.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/resources/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/resources/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/locale/de/LC_MESSAGES/django.mo +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/locale/de/LC_MESSAGES/django.po +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/locale/en/LC_MESSAGES/django.mo +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/locale/en/LC_MESSAGES/django.po +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/locale/fr/LC_MESSAGES/django.mo +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/locale/fr/LC_MESSAGES/django.po +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/management/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0001_initial.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0002_rename_statements_instrumentlookup_financials_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0003_instrument_estimate_backend_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0004_rename_financials_instrumentlookup_statements_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0005_instrument_corporate_action_backend.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0006_instrument_officer_backend.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0007_instrument_country_instrument_currency_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0008_controversy.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0009_alter_controversy_flag_alter_controversy_initiated_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0010_classification_classificationgroup_deal_exchange_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0011_delete_instrumentlookup_instrument_corporate_actions_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0012_instrumentprice_created_instrumentprice_modified.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0013_instrument_is_investable_universe_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0014_alter_controversy_instrument.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0015_instrument_instrument_investible_index.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0016_instrumenttype_name_repr.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0017_instrument_instrument_security_index.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0018_instrument_instrument_level_index.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0019_alter_controversy_source.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0020_optionaggregate_option_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0021_delete_instrumentdailystatistics.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0022_instrument_cusip_option_open_interest_20d_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0023_instrument_unique_ric_instrument_unique_rmc_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0024_option_open_interest_10d_option_volume_10d_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0025_instrument_is_primary_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0026_instrument_is_cash_equivalent.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0027_remove_instrument_unique_ric_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0028_instrumentprice_annualized_daily_volatility.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0029_alter_instrumentprice_volume.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0030_alter_relatedinstrumentthroughmodel_related_type.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0031_exchange_apply_round_lot_size_and_more.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0032_alter_instrumentprice_outstanding_shares.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/0033_alter_controversy_review.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/migrations/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/esg/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/exchanges/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/exchanges/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/indicators.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/instrument_lists.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/instrument_requests.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/llm/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/llm/create_instrument_news_relationships.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/mixin/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/mixin/financials_computed.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/mixin/financials_serializer_fields.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/querysets.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/models/instruments/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/preferences.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/esg.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/instruments/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/instruments/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/instruments/instrument_lists.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/instruments/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/instruments/instrument_relationships.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/instruments/instrument_requests.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/instruments/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/instruments/mixins.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/serializers/officers.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/signals.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/sync/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/sync/abstract.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/sync/runner.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tasks.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/analysis/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/analysis/financial_analysis/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/analysis/financial_analysis/test_utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/analysis/test_esg.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/conftest.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/dataloaders/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/dataloaders/test_cache.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/test_classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/test_exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/test_instrument_list.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/test_instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/test_instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/test_merge.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/test_options.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/models/test_queryset.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/test_tasks.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/tests/tests.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/urls.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/buttons/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/buttons/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/buttons/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/buttons/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/buttons/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/esg.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/financial_summary.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/instrument_lists.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/instrument_requests.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/monthly_performances.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/officers.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/statement_with_estimates.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/statements.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/esg.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/financials_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/instrument_lists.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/instrument_requests.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/instruments_relationships.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/endpoints/statements.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/menus/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/menus/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/menus/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/menus/instrument_lists.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/menus/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/menus/instruments_relationships.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/esg.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/financial_ratio_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/financials_analysis.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/instrument_requests.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/instruments_relationships.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/market_data.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/titles/statement_with_estimates.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/exchanges.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/financial_analysis/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/financial_analysis/statement_with_estimates.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/classifications.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/instrument_lists.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/instrument_prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/instrument_requests.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/instruments.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/instruments_relationships.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/instruments/utils.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/mixins.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/officers.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/prices.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/statements/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/statements/statements.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/technical_analysis/__init__.py +0 -0
- {wbfdm-1.55.9 → wbfdm-1.55.10rc0}/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.55.
|
|
3
|
+
Version: 1.55.10rc0
|
|
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,7 +3,7 @@ import re
|
|
|
3
3
|
from datetime import date, datetime
|
|
4
4
|
from typing import Generator, List, Optional
|
|
5
5
|
|
|
6
|
-
import DatastreamPy as dsweb
|
|
6
|
+
import DatastreamPy as dsweb # noqa
|
|
7
7
|
import numpy as np
|
|
8
8
|
import pandas as pd
|
|
9
9
|
import pytz
|
|
@@ -13,7 +13,7 @@ from wbcore.contrib.currency.models import Currency, CurrencyFXRates
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class CachedTokenDataClient(dsweb.DataClient):
|
|
16
|
-
def _get_token(self, isProxy=False):
|
|
16
|
+
def _get_token(self, isProxy=False): # noqa
|
|
17
17
|
if (token := cache.get("dsws_token")) and (token_expiry := cache.get("dsws_token_expiry")):
|
|
18
18
|
self.token = token
|
|
19
19
|
self.tokenExpiry = timezone.make_aware(datetime.fromtimestamp(token_expiry), timezone=pytz.UTC)
|
|
@@ -102,7 +102,7 @@ class Client:
|
|
|
102
102
|
if len(requests_data) > self.MAXIMUM_REQUESTS_PER_BUNDLE:
|
|
103
103
|
raise ValueError(f"number of request exceed {self.MAXIMUM_REQUESTS_PER_BUNDLE}")
|
|
104
104
|
# Construct the requests bundle
|
|
105
|
-
for request_tickers,
|
|
105
|
+
for request_tickers, _ in requests_data:
|
|
106
106
|
# Convert a list of string into a valid string
|
|
107
107
|
converted_ticker = ",".join(request_tickers)
|
|
108
108
|
if "start" in extra_client_kwargs or "end" in extra_client_kwargs:
|
|
@@ -30,7 +30,7 @@ FIELD_MAP = {
|
|
|
30
30
|
class DSWSMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
31
31
|
def market_data(
|
|
32
32
|
self,
|
|
33
|
-
values: list[MarketData] =
|
|
33
|
+
values: list[MarketData] | None = None,
|
|
34
34
|
from_date: date | None = None,
|
|
35
35
|
to_date: date | None = None,
|
|
36
36
|
exact_date: date | None = None,
|
|
@@ -36,7 +36,7 @@ def _cast_decimal_to_float(value: float | Decimal) -> float:
|
|
|
36
36
|
class MarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
37
37
|
def market_data(
|
|
38
38
|
self,
|
|
39
|
-
values: list[MarketData] =
|
|
39
|
+
values: list[MarketData] | None = None,
|
|
40
40
|
from_date: date | None = None,
|
|
41
41
|
to_date: date | None = None,
|
|
42
42
|
exact_date: date | None = None,
|
|
@@ -13,7 +13,7 @@ from wbcore.contrib.currency.models import CurrencyFXRates
|
|
|
13
13
|
from wbfdm.models import Instrument, InstrumentPrice
|
|
14
14
|
|
|
15
15
|
from ..dto import Metric, MetricField, MetricKey
|
|
16
|
-
from ..exceptions import
|
|
16
|
+
from ..exceptions import MetricInvalidParameterError
|
|
17
17
|
from .utils import get_today
|
|
18
18
|
|
|
19
19
|
T = TypeVar("T", bound=Model)
|
|
@@ -94,7 +94,7 @@ class InstrumentMetricBaseBackend(AbstractBackend[Instrument]):
|
|
|
94
94
|
[val_date, (get_today() - pd.tseries.offsets.BDay(1)).date()]
|
|
95
95
|
) # ensure that value date is at least lower than today (otherwise, we might compute performance for intraday, which we do not want yet
|
|
96
96
|
else:
|
|
97
|
-
raise
|
|
97
|
+
raise MetricInvalidParameterError()
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
class BaseDataloader:
|
|
@@ -11,7 +11,7 @@ from wbfdm.models import Instrument, InstrumentPrice
|
|
|
11
11
|
|
|
12
12
|
from ..decorators import register
|
|
13
13
|
from ..dto import Metric, MetricField, MetricKey
|
|
14
|
-
from ..exceptions import
|
|
14
|
+
from ..exceptions import MetricInvalidParameterError
|
|
15
15
|
from .base import BaseDataloader, InstrumentMetricBaseBackend
|
|
16
16
|
|
|
17
17
|
STATISTICS_METRIC = MetricKey(
|
|
@@ -207,7 +207,7 @@ class InstrumentFinancialStatisticsMetricBackend(InstrumentMetricBaseBackend):
|
|
|
207
207
|
elif self.val_date:
|
|
208
208
|
with suppress(InstrumentPrice.DoesNotExist):
|
|
209
209
|
return instrument.valuations.filter(date__lte=self.val_date).latest("date").date
|
|
210
|
-
raise
|
|
210
|
+
raise MetricInvalidParameterError()
|
|
211
211
|
|
|
212
212
|
|
|
213
213
|
@register(move_first=True)
|
|
@@ -48,6 +48,12 @@ class InstrumentMetric(models.Model):
|
|
|
48
48
|
self.basket_repr = str(self.basket)
|
|
49
49
|
super().save(*args, **kwargs)
|
|
50
50
|
|
|
51
|
+
def __str__(self) -> str:
|
|
52
|
+
repr = f"{self.basket} - {self.key}"
|
|
53
|
+
if self.date:
|
|
54
|
+
repr += f"({self.date})"
|
|
55
|
+
return repr
|
|
56
|
+
|
|
51
57
|
@classmethod
|
|
52
58
|
def update_or_create_from_metric(cls, metric: Metric, parent_instrument_metric: Self | None = None):
|
|
53
59
|
"""
|
|
@@ -8,7 +8,7 @@ from tqdm import tqdm
|
|
|
8
8
|
|
|
9
9
|
from .backends.base import AbstractBackend
|
|
10
10
|
from .dto import Metric
|
|
11
|
-
from .exceptions import
|
|
11
|
+
from .exceptions import MetricInvalidParameterError
|
|
12
12
|
from .models import InstrumentMetric
|
|
13
13
|
from .registry import backend_registry
|
|
14
14
|
|
|
@@ -73,9 +73,9 @@ class MetricOrchestrator:
|
|
|
73
73
|
if debug:
|
|
74
74
|
# if debug mode is enabled, we wrap the parameters list into a tqdm generator
|
|
75
75
|
parameters = tqdm(parameters)
|
|
76
|
-
for
|
|
77
|
-
with suppress(
|
|
78
|
-
yield from
|
|
76
|
+
for param in parameters:
|
|
77
|
+
with suppress(MetricInvalidParameterError):
|
|
78
|
+
yield from param[0].compute_metrics(param[1])
|
|
79
79
|
|
|
80
80
|
def process(self, debug: bool = False):
|
|
81
81
|
"""
|
|
@@ -185,19 +185,19 @@ class InstrumentMetricMixin(_Base):
|
|
|
185
185
|
serializer_class = self.get_serializer_class()
|
|
186
186
|
kwargs.setdefault("context", self.get_serializer_context())
|
|
187
187
|
|
|
188
|
-
|
|
189
|
-
fields = list(getattr(
|
|
190
|
-
read_only_fields = list(getattr(
|
|
188
|
+
base_meta = serializer_class.Meta
|
|
189
|
+
fields = list(getattr(base_meta, "fields", ()))
|
|
190
|
+
read_only_fields = list(getattr(base_meta, "read_only_fields", ()))
|
|
191
191
|
for extra_field in self._metric_serializer_fields.keys():
|
|
192
192
|
fields.append(extra_field)
|
|
193
193
|
read_only_fields.append(extra_field)
|
|
194
194
|
|
|
195
|
-
|
|
195
|
+
meta = type(str("Meta"), (base_meta,), {"fields": fields, "read_only_fields": read_only_fields})
|
|
196
196
|
new_class = type(
|
|
197
197
|
serializer_class.__name__,
|
|
198
198
|
(serializer_class,),
|
|
199
199
|
{
|
|
200
|
-
"Meta":
|
|
200
|
+
"Meta": meta,
|
|
201
201
|
**self._metric_serializer_fields,
|
|
202
202
|
"SERIALIZER_CLASS_FOR_REMOTE_ADDITIONAL_RESOURCES": serializer_class,
|
|
203
203
|
},
|
|
@@ -233,7 +233,7 @@ class InstrumentMetricMixin(_Base):
|
|
|
233
233
|
# for all the missings keys (not present in the aggregates already), we compute the aggregatation based on the aggregate function given by the MetricField class
|
|
234
234
|
missing_aggregate_map = {}
|
|
235
235
|
for metric_key in self.metric_keys:
|
|
236
|
-
for field_key
|
|
236
|
+
for field_key in metric_key.subfields_filter_map.keys():
|
|
237
237
|
if field_key in self._metric_serializer_fields.keys() and field_key not in aggregates:
|
|
238
238
|
missing_aggregate_map[field_key] = metric_key.subfields_map[field_key]
|
|
239
239
|
missing_aggregate = queryset.aggregate(
|
|
@@ -38,6 +38,7 @@ class MSCIClient:
|
|
|
38
38
|
"grant_type": "client_credentials",
|
|
39
39
|
"audience": "https://esg/data",
|
|
40
40
|
},
|
|
41
|
+
timeout=10,
|
|
41
42
|
)
|
|
42
43
|
if resp.status_code == requests.codes.ok:
|
|
43
44
|
with suppress(KeyError, requests.exceptions.JSONDecodeError):
|
|
@@ -58,6 +59,7 @@ class MSCIClient:
|
|
|
58
59
|
"factor_name_list": factors,
|
|
59
60
|
},
|
|
60
61
|
headers={"AUTHORIZATION": f"Bearer {self.oauth_token}"},
|
|
62
|
+
timeout=10,
|
|
61
63
|
)
|
|
62
64
|
if response.ok:
|
|
63
65
|
for row in response.json().get("result", {}).get("issuers", []):
|
|
@@ -78,6 +80,7 @@ class MSCIClient:
|
|
|
78
80
|
"offset": offset,
|
|
79
81
|
},
|
|
80
82
|
headers={"AUTHORIZATION": f"Bearer {self.oauth_token}"},
|
|
83
|
+
timeout=10,
|
|
81
84
|
)
|
|
82
85
|
|
|
83
86
|
if not response.ok:
|
|
@@ -57,7 +57,8 @@ class DatastreamAdjustmentsDataloader(AdjustmentsProtocol, Dataloader):
|
|
|
57
57
|
pk.MSSQLQuery.create_table(infocode).columns(pk.Column("infocode", SqlTypes.INTEGER)).get_sql()
|
|
58
58
|
)
|
|
59
59
|
for batch in batched(lookup.keys(), 1000):
|
|
60
|
-
|
|
60
|
+
placeholders = ",".join(map(lambda x: f"({x})", batch))
|
|
61
|
+
cursor.execute("insert into #ds2infocode values %s;", (placeholders,))
|
|
61
62
|
|
|
62
63
|
cursor.execute(query.get_sql())
|
|
63
64
|
|
|
@@ -58,7 +58,8 @@ class DatastreamCorporateActionsDataloader(CorporateActionsProtocol, Dataloader)
|
|
|
58
58
|
pk.MSSQLQuery.create_table(infocode).columns(pk.Column("infocode", SqlTypes.INTEGER)).get_sql()
|
|
59
59
|
)
|
|
60
60
|
for batch in batched(lookup.keys(), 1000):
|
|
61
|
-
|
|
61
|
+
placeholders = ",".join(map(lambda x: f"({x})", batch))
|
|
62
|
+
cursor.execute("insert into #ds2infocode values %s;", (placeholders,))
|
|
62
63
|
|
|
63
64
|
cursor.execute(query.get_sql())
|
|
64
65
|
for row in dictfetchall(cursor, CorporateActionDataDict):
|
|
@@ -41,7 +41,7 @@ class DS2MarketData(Enum):
|
|
|
41
41
|
class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
42
42
|
def market_data(
|
|
43
43
|
self,
|
|
44
|
-
values: list[MarketData] =
|
|
44
|
+
values: list[MarketData] | None = None,
|
|
45
45
|
from_date: date | None = None,
|
|
46
46
|
to_date: date | None = None,
|
|
47
47
|
exact_date: date | None = None,
|
|
@@ -60,7 +60,7 @@ class RKDOfficersDataloader(OfficersProtocol, Dataloader):
|
|
|
60
60
|
)
|
|
61
61
|
for batch in batched(lookup.keys(), 1000):
|
|
62
62
|
placeholders = ",".join(map(lambda x: f"('{x}')", batch))
|
|
63
|
-
cursor.execute(
|
|
63
|
+
cursor.execute("insert into #rkd_codes values %s;", (placeholders,))
|
|
64
64
|
|
|
65
65
|
cursor.execute(query.get_sql())
|
|
66
66
|
|
|
@@ -290,14 +290,16 @@ def trigger_partial_update(
|
|
|
290
290
|
else:
|
|
291
291
|
with connections["qa"].cursor() as cursor:
|
|
292
292
|
cursor.execute(
|
|
293
|
-
|
|
293
|
+
"SELECT MAX(last_user_update) FROM sys.dm_db_index_usage_stats WHERE OBJECT_NAME(object_id) = %S'",
|
|
294
|
+
(table_change_name,),
|
|
294
295
|
)
|
|
295
296
|
max_last_updated_qa = (
|
|
296
297
|
pytz.timezone(settings.TIME_ZONE).localize(result[0]) if (result := cursor.fetchone()) else None
|
|
297
298
|
)
|
|
298
299
|
if max_last_updated_qa and max_last_updated_qa > max_last_updated:
|
|
299
300
|
for _, security_id in cursor.execute(
|
|
300
|
-
|
|
301
|
+
"SELECT UpdateFlag_, %s FROM %s",
|
|
302
|
+
(id_field, table_change_name),
|
|
301
303
|
).fetchall():
|
|
302
304
|
try:
|
|
303
305
|
update_or_create_item(security_id)
|
|
@@ -49,7 +49,7 @@ class FXRateProtocol(Protocol):
|
|
|
49
49
|
class MarketDataProtocol(Protocol):
|
|
50
50
|
def market_data(
|
|
51
51
|
self,
|
|
52
|
-
values: list[MarketData] =
|
|
52
|
+
values: list[MarketData] | None = None,
|
|
53
53
|
from_date: date | None = None,
|
|
54
54
|
to_date: date | None = None,
|
|
55
55
|
exact_date: date | None = None,
|
|
@@ -115,13 +115,7 @@ class FinancialAnalysisGenerator:
|
|
|
115
115
|
self.instruments_repr_map = {i.id: i.name_repr for i in self.instruments}
|
|
116
116
|
self.currency_map = {i.id: i.currency.id for i in self.instruments}
|
|
117
117
|
|
|
118
|
-
def build_df(
|
|
119
|
-
self,
|
|
120
|
-
instrument_prices_field_names: list[str] = [],
|
|
121
|
-
fundamental_field_names: list[str] = [],
|
|
122
|
-
forecast_field_names: list[str] = [],
|
|
123
|
-
daily_fundamental_field_names: list[str] = [],
|
|
124
|
-
):
|
|
118
|
+
def build_df(self, **kwargs):
|
|
125
119
|
"""
|
|
126
120
|
Used to returns a df with all the variables passed in four separate lists
|
|
127
121
|
|
|
@@ -239,7 +233,7 @@ class FinancialAnalysisGenerator:
|
|
|
239
233
|
@staticmethod
|
|
240
234
|
def clean_data(
|
|
241
235
|
df: pd.DataFrame,
|
|
242
|
-
var_list: list[str]
|
|
236
|
+
var_list: list[str],
|
|
243
237
|
drop_negative=True,
|
|
244
238
|
q_low: float = 0.05,
|
|
245
239
|
q_high: float = 0.95,
|
|
@@ -138,7 +138,7 @@ class InstrumentFilterSet(TagFilterMixin, InstrumentFavoriteGroupFilterSet):
|
|
|
138
138
|
if "parent" in data:
|
|
139
139
|
data.pop("classifications", None) # remove classifications in case we are navigating the tree
|
|
140
140
|
data.pop("level", None)
|
|
141
|
-
super().__init__(data=data,
|
|
141
|
+
super().__init__(*args, data=data, **kwargs)
|
|
142
142
|
|
|
143
143
|
class Meta:
|
|
144
144
|
model = Instrument
|
|
@@ -7,11 +7,11 @@ from celery import shared_task
|
|
|
7
7
|
from tqdm import tqdm
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class
|
|
10
|
+
class RateLimitError(Exception):
|
|
11
11
|
pass
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class
|
|
14
|
+
class CreditLimitError(Exception):
|
|
15
15
|
pass
|
|
16
16
|
|
|
17
17
|
|
|
@@ -38,17 +38,18 @@ class Client:
|
|
|
38
38
|
url,
|
|
39
39
|
params={**params, **{"nextPageToken": next_page_token}} if next_page_token else params,
|
|
40
40
|
headers={"authorization": self.jwt_header_value},
|
|
41
|
+
timeout=10,
|
|
41
42
|
)
|
|
42
43
|
if resp.status_code != 200:
|
|
43
44
|
if resp.status_code == 429:
|
|
44
|
-
raise
|
|
45
|
+
raise RateLimitError()
|
|
45
46
|
raise requests.ConnectionError(
|
|
46
47
|
f"unexpected error from api\nstatus_code: {resp.status_code}\nerror: {resp.text}"
|
|
47
48
|
)
|
|
48
49
|
|
|
49
50
|
if credits_remaining_str := resp.headers.get("x-cbinsights-credits-remaining", None):
|
|
50
51
|
if int(credits_remaining_str) <= 0:
|
|
51
|
-
raise
|
|
52
|
+
raise CreditLimitError()
|
|
52
53
|
|
|
53
54
|
return resp.json()
|
|
54
55
|
|
|
@@ -72,11 +73,11 @@ class Client:
|
|
|
72
73
|
resp = self._request(data_url, params=params, next_page_token=next_page_token)
|
|
73
74
|
yield resp
|
|
74
75
|
next_page_token = resp["nextPageToken"]
|
|
75
|
-
except
|
|
76
|
+
except RateLimitError:
|
|
76
77
|
time.sleep(self.rate_limit_sleep)
|
|
77
78
|
retry += 1
|
|
78
79
|
if retry >= 5:
|
|
79
|
-
raise
|
|
80
|
+
raise RateLimitError()
|
|
80
81
|
|
|
81
82
|
def _chunk_paginated_request(self, data_url, org_ids, extra_params, endpoint, debug: bool = False):
|
|
82
83
|
data = []
|
|
@@ -96,8 +97,7 @@ class Client:
|
|
|
96
97
|
auth_url = "https://api.cbinsights.com/v1/authorize"
|
|
97
98
|
|
|
98
99
|
auth_resp = requests.get(
|
|
99
|
-
auth_url,
|
|
100
|
-
params={"clientId": self.client_id, "clientSecret": self.client_secret},
|
|
100
|
+
auth_url, params={"clientId": self.client_id, "clientSecret": self.client_secret}, timeout=10
|
|
101
101
|
)
|
|
102
102
|
|
|
103
103
|
if auth_resp.status_code != 200:
|
{wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/import_export/backends/refinitiv/utils/controller.py
RENAMED
|
@@ -61,7 +61,7 @@ class Controller:
|
|
|
61
61
|
instrument_ric: str = None,
|
|
62
62
|
instrument_isin: str = None,
|
|
63
63
|
instrument_mnemonic: str = None,
|
|
64
|
-
perm_id_symbols:
|
|
64
|
+
perm_id_symbols: tuple[str, ...] = ("QPID", "IPID"),
|
|
65
65
|
) -> str | None:
|
|
66
66
|
def _process_ticker(ticker):
|
|
67
67
|
if not (df := self.client.get_static_df(tickers=[ticker], fields=perm_id_symbols)).empty:
|
|
@@ -237,8 +237,8 @@ class InstrumentImportHandler(ImportExportHandler):
|
|
|
237
237
|
if instrument_id := data.pop("id", None):
|
|
238
238
|
try:
|
|
239
239
|
return self.model.objects.get(id=instrument_id)
|
|
240
|
-
except self.model.DoesNotExist:
|
|
241
|
-
raise DeserializationError("Instrument id does not match an existing instrument")
|
|
240
|
+
except self.model.DoesNotExist as e:
|
|
241
|
+
raise DeserializationError("Instrument id does not match an existing instrument") from e
|
|
242
242
|
else:
|
|
243
243
|
return self.instrument_lookup.lookup(only_security=only_security, **data)
|
|
244
244
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from contextlib import suppress
|
|
2
3
|
|
|
3
4
|
from wbcore.contrib.geography.models import Geography
|
|
4
5
|
|
|
@@ -44,14 +45,12 @@ def parse(import_source):
|
|
|
44
45
|
d["headquarter_address"] = f"{street}, {postal_code} {city_name}"
|
|
45
46
|
|
|
46
47
|
if sector_id := summary.get("sectorId", None):
|
|
47
|
-
|
|
48
|
+
with suppress(Exception):
|
|
48
49
|
code_aggregated = f"{int(sector_id):03}"
|
|
49
50
|
if industry_id := summary.get("industryId", None):
|
|
50
51
|
code_aggregated += f"{int(industry_id):03}"
|
|
51
52
|
if subindustry_id := summary.get("subindustryId", None):
|
|
52
53
|
code_aggregated += f"{int(subindustry_id):03}"
|
|
53
|
-
except Exception:
|
|
54
|
-
pass
|
|
55
54
|
d["classifications"] = [{"code_aggregated": code_aggregated, "group": cbinsight_group.id}]
|
|
56
55
|
data.append(d)
|
|
57
56
|
return {"data": data}
|
|
@@ -3,5 +3,6 @@ from jinjasql import JinjaSql # type: ignore
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
def get_environment(**options):
|
|
6
|
-
|
|
6
|
+
# we except only SQL template, so we need to not escape special characters (possible XSS attack for HTML template)
|
|
7
|
+
env = Environment(**options) # noqa: S701
|
|
7
8
|
return JinjaSql(env=env, param_style="format").env
|
|
@@ -56,6 +56,9 @@ class Controversy(models.Model):
|
|
|
56
56
|
review = models.DateField(verbose_name="Reviewed", null=True, blank=True)
|
|
57
57
|
initiated = models.DateField(verbose_name="initiated", null=True, blank=True)
|
|
58
58
|
|
|
59
|
+
def __str__(self) -> str:
|
|
60
|
+
return f"{self.headline} ({self.instrument})"
|
|
61
|
+
|
|
59
62
|
@classmethod
|
|
60
63
|
def dict_to_model(cls, controversy: dict[str, Any], instrument) -> Self:
|
|
61
64
|
return Controversy(
|
|
@@ -23,7 +23,7 @@ class CompositeKey(models.AutoField):
|
|
|
23
23
|
def __init__(self, columns: list[str], db_column_ref: str | None = None, *args, **kwargs):
|
|
24
24
|
self.columns = columns
|
|
25
25
|
self.db_column_ref = db_column_ref
|
|
26
|
-
super().__init__(primary_key=True,
|
|
26
|
+
super().__init__(*args, primary_key=True, **kwargs)
|
|
27
27
|
|
|
28
28
|
def contribute_to_class(self, cls, name, private_only=False):
|
|
29
29
|
self.set_attributes_from_name(name)
|
|
@@ -108,7 +108,7 @@ class Exact(models.Lookup):
|
|
|
108
108
|
|
|
109
109
|
lookups = [
|
|
110
110
|
lookup_class(field.get_col(self.lhs.alias), self.rhs[column])
|
|
111
|
-
for lookup_class, field, column in zip(lookup_classes, fields, self.lhs.field.columns)
|
|
111
|
+
for lookup_class, field, column in zip(lookup_classes, fields, self.lhs.field.columns, strict=False)
|
|
112
112
|
]
|
|
113
113
|
|
|
114
114
|
value_constraint = WhereNode()
|
|
@@ -93,7 +93,7 @@ class CompositeForeignKey(ForeignObject):
|
|
|
93
93
|
kwargs["on_delete"] = self.override_on_delete(kwargs["on_delete"])
|
|
94
94
|
|
|
95
95
|
kwargs["to_fields"], kwargs["from_fields"] = zip(
|
|
96
|
-
*((k, v.value) for k, v in self._raw_fields.items() if v.is_local_field)
|
|
96
|
+
*((k, v.value) for k, v in self._raw_fields.items() if v.is_local_field), strict=False
|
|
97
97
|
)
|
|
98
98
|
super().__init__(to, **kwargs)
|
|
99
99
|
|
|
@@ -220,7 +220,7 @@ class CompositeForeignKey(ForeignObject):
|
|
|
220
220
|
|
|
221
221
|
def _check_nullifequal_fields_exists(self):
|
|
222
222
|
res = []
|
|
223
|
-
for field_name,
|
|
223
|
+
for field_name, _ in self.null_if_equal:
|
|
224
224
|
try:
|
|
225
225
|
self.model._meta.get_field(field_name)
|
|
226
226
|
except FieldDoesNotExist:
|
|
@@ -269,7 +269,7 @@ class CompositeForeignKey(ForeignObject):
|
|
|
269
269
|
|
|
270
270
|
return OrderedDict(
|
|
271
271
|
(k, (v if isinstance(v, CompositePart) else LocalFieldValue(v)))
|
|
272
|
-
for k, v in (to_fields.items() if isinstance(to_fields, dict) else zip(to_fields, to_fields))
|
|
272
|
+
for k, v in (to_fields.items() if isinstance(to_fields, dict) else zip(to_fields, to_fields, strict=False))
|
|
273
273
|
)
|
|
274
274
|
|
|
275
275
|
def db_type(self, connection):
|
|
@@ -162,6 +162,9 @@ class RelatedInstrumentThroughModel(models.Model):
|
|
|
162
162
|
class Meta:
|
|
163
163
|
unique_together = ("instrument", "related_instrument", "is_primary", "related_type")
|
|
164
164
|
|
|
165
|
+
def __str__(self) -> str:
|
|
166
|
+
return f"{self.instrument} - {self.related_instrument} ({self.related_type})"
|
|
167
|
+
|
|
165
168
|
def save(self, *args, **kwargs):
|
|
166
169
|
qs = RelatedInstrumentThroughModel.objects.filter(
|
|
167
170
|
instrument=self.instrument, related_type=self.related_type, is_primary=True
|
|
@@ -205,38 +205,38 @@ class InstrumentType(models.Model):
|
|
|
205
205
|
|
|
206
206
|
@classmethod
|
|
207
207
|
@property
|
|
208
|
-
def PRODUCT(cls):
|
|
208
|
+
def PRODUCT(cls): # noqa
|
|
209
209
|
return InstrumentType.objects.get_or_create(
|
|
210
210
|
key="product", defaults={"name": "Product", "short_name": "Product"}
|
|
211
211
|
)[0]
|
|
212
212
|
|
|
213
213
|
@classmethod
|
|
214
214
|
@property
|
|
215
|
-
def EQUITY(cls):
|
|
215
|
+
def EQUITY(cls): # noqa
|
|
216
216
|
return InstrumentType.objects.get_or_create(key="equity", defaults={"name": "equity", "short_name": "equity"})[
|
|
217
217
|
0
|
|
218
218
|
]
|
|
219
219
|
|
|
220
220
|
@classmethod
|
|
221
221
|
@property
|
|
222
|
-
def INDEX(cls):
|
|
222
|
+
def INDEX(cls): # noqa
|
|
223
223
|
return InstrumentType.objects.get_or_create(key="index", defaults={"name": "Index", "short_name": "Index"})[0]
|
|
224
224
|
|
|
225
225
|
@classmethod
|
|
226
226
|
@property
|
|
227
|
-
def CASH(cls):
|
|
227
|
+
def CASH(cls): # noqa
|
|
228
228
|
return InstrumentType.objects.get_or_create(key="cash", defaults={"name": "Cash", "short_name": "Cash"})[0]
|
|
229
229
|
|
|
230
230
|
@classmethod
|
|
231
231
|
@property
|
|
232
|
-
def CASHEQUIVALENT(cls):
|
|
232
|
+
def CASHEQUIVALENT(cls): # noqa
|
|
233
233
|
return InstrumentType.objects.get_or_create(
|
|
234
234
|
key="cash_equivalent", defaults={"name": "Cash Equivalents", "short_name": "Cash Equivalents"}
|
|
235
235
|
)[0]
|
|
236
236
|
|
|
237
237
|
@classmethod
|
|
238
238
|
@property
|
|
239
|
-
def PRODUCT_GROUP(cls):
|
|
239
|
+
def PRODUCT_GROUP(cls): # noqa
|
|
240
240
|
return InstrumentType.objects.get_or_create(
|
|
241
241
|
key="product_group", defaults={"name": "Product Group", "short_name": "Product Group"}
|
|
242
242
|
)[0]
|
|
@@ -63,7 +63,7 @@ class InstrumentPMSMixin:
|
|
|
63
63
|
market_capitalization=price.market_capitalization,
|
|
64
64
|
outstanding_shares=float(price.outstanding_shares) if price.outstanding_shares else None,
|
|
65
65
|
)
|
|
66
|
-
except InstrumentPrice.DoesNotExist:
|
|
66
|
+
except InstrumentPrice.DoesNotExist as e:
|
|
67
67
|
prices = sorted(
|
|
68
68
|
self.get_prices(from_date=(val_date - BDay(price_date_timedelta)).date(), to_date=val_date),
|
|
69
69
|
key=lambda x: x["valuation_date"],
|
|
@@ -87,7 +87,7 @@ class InstrumentPMSMixin:
|
|
|
87
87
|
market_capitalization=p.get("market_capitalization", None),
|
|
88
88
|
outstanding_shares=p.get("outstanding_shares", None),
|
|
89
89
|
)
|
|
90
|
-
raise ValueError("Not price was found")
|
|
90
|
+
raise ValueError("Not price was found") from e
|
|
91
91
|
|
|
92
92
|
# Instrument Prices Utility Functions
|
|
93
93
|
@classmethod
|
|
@@ -143,6 +143,9 @@ class OptionAggregate(BaseOptionAbstractModel):
|
|
|
143
143
|
),
|
|
144
144
|
]
|
|
145
145
|
|
|
146
|
+
def __str__(self) -> str:
|
|
147
|
+
return f"{self.instrument} - {self.date} - {self.type}"
|
|
148
|
+
|
|
146
149
|
|
|
147
150
|
class Option(BaseOptionAbstractModel):
|
|
148
151
|
import_export_handler_class = OptionImportHandler
|
|
@@ -224,3 +227,6 @@ class Option(BaseOptionAbstractModel):
|
|
|
224
227
|
fields=["type"],
|
|
225
228
|
),
|
|
226
229
|
]
|
|
230
|
+
|
|
231
|
+
def __str__(self):
|
|
232
|
+
return f"{self.contract_identifier} - {self.date} - {self.type}"
|
{wbfdm-1.55.9 → wbfdm-1.55.10rc0}/wbfdm/viewsets/configs/display/instruments_relationships.py
RENAMED
|
@@ -52,7 +52,9 @@ class ClassifiedInstrumentDisplayConfig(DisplayViewConfig):
|
|
|
52
52
|
if group := self.view.classification_group:
|
|
53
53
|
fields = [dp.Field(key="instrument", label="Instrument")]
|
|
54
54
|
level_representations = group.get_levels_representation()
|
|
55
|
-
for key, label in zip(
|
|
55
|
+
for key, label in zip(
|
|
56
|
+
reversed(group.get_fields_names(sep="_")), reversed(level_representations[1:]), strict=False
|
|
57
|
+
):
|
|
56
58
|
fields.append(
|
|
57
59
|
dp.Field(key=f"classification_{key}", label=label),
|
|
58
60
|
)
|
|
@@ -31,7 +31,8 @@ class MonthlyPerformancesInstrumentTitleConfig(TitleViewConfig):
|
|
|
31
31
|
|
|
32
32
|
class InstrumentTitleConfigMixin(TitleViewConfig):
|
|
33
33
|
def get_list_title(self):
|
|
34
|
-
|
|
34
|
+
if not self.message:
|
|
35
|
+
raise AssertionError("No message has been set")
|
|
35
36
|
instrument = Instrument.objects.get(id=self.view.kwargs["instrument_id"])
|
|
36
37
|
return f"{self.message} {str(instrument)}"
|
|
37
38
|
|
|
@@ -66,8 +66,8 @@ class InstrumentESGPAIViewSet(InstrumentMixin, ExportPandasAPIViewSet):
|
|
|
66
66
|
def get_dataframe(self, request, queryset, **kwargs):
|
|
67
67
|
df = pd.DataFrame(queryset.dl.esg(values=list(ESG))).reset_index()
|
|
68
68
|
if not df.empty:
|
|
69
|
-
|
|
69
|
+
esg_mapping = ESG.mapping()
|
|
70
70
|
df[["section", "asi", "metric", "factor"]] = pd.DataFrame(
|
|
71
|
-
df.factor_code.map(
|
|
71
|
+
df.factor_code.map(esg_mapping).tolist(), index=df.index
|
|
72
72
|
)
|
|
73
73
|
return df
|