wbfdm 1.54.22__tar.gz → 1.55.4__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.54.22 → wbfdm-1.55.4}/PKG-INFO +1 -1
- wbfdm-1.55.4/wbfdm/contrib/qa/dataloaders/fx_rates.py +49 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/market_data.py +29 -36
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/statements.py +9 -2
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/dataloaders/protocols.py +10 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/dataloaders/proxies.py +13 -1
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/dataloaders/types.py +6 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/instruments.py +2 -2
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/handlers/option.py +2 -2
- wbfdm-1.55.4/wbfdm/migrations/0032_alter_instrumentprice_outstanding_shares.py +18 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/instrument_prices.py +3 -1
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/mixin/financials_computed.py +0 -4
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/querysets.py +4 -5
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tasks.py +4 -2
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/test_instrument_prices.py +0 -14
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/instrument_prices.py +9 -9
- {wbfdm-1.54.22 → wbfdm-1.55.4}/.gitignore +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/pyproject.toml +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/esg.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/instrument_lists.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/instrument_requests.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/instruments_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/admin/options.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/esg/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/esg/enums.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/esg/esg_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/esg/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/change_point_detection.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/financial_metric_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/financial_ratio_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/financial_statistics_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/statement_with_estimates.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/technical_analysis/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/technical_analysis/technical_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/technical_analysis/traces.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/apps.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/backends/dto.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/dsws/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/dsws/client.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/dsws/dataloaders/market_data.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/internal/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/internal/dataloaders/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/internal/dataloaders/market_data.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/admin/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/admin/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/admin/metrics.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/apps.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/backends/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/backends/base.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/backends/performances.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/backends/statistics.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/backends/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/decorators.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/dispatch.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/dto.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/exceptions.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/factories.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/filters.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/migrations/0001_initial.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/migrations/0002_remove_instrumentmetric_unique_instrument_metric_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/migrations/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/models.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/orchestrators.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/registry.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/serializers.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tasks.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/backends/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/backends/test_performances.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/backends/test_statistics.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/conftest.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/test_dto.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/test_models.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/test_tasks.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/tests/test_viewsets.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/urls.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/viewsets/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/viewsets/configs/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/viewsets/configs/display.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/viewsets/configs/menus.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/viewsets/configs/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/viewsets/mixins.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/metric/viewsets/viewsets.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/client.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/dataloaders/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/dataloaders/esg.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/dataloaders/esg_controversies.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/sync.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/tests/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/tests/conftest.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/msci/tests/test_client.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/apps.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/database_routers.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/adjustments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/corporate_actions.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/financials.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/officers.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/reporting_dates.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/dataloaders/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/jinja2/qa/sql/companies.sql +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/base_estimates.sql +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/calendarized.sql +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/complete.sql +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/estimates.sql +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/jinja2/qa/sql/ibes/financials.sql +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/jinja2/qa/sql/instruments.sql +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/jinja2/qa/sql/quotes.sql +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/sync/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/sync/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/sync/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/contrib/qa/tasks.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/dataloaders/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/dataloaders/cache.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/dynamic_preferences_registry.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/enums.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/controversies.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/instrument_list.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/instruments_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/factories/options.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/figures/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/figures/financials/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/figures/financials/financial_analysis_charts.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/figures/financials/financials_charts.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/filters/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/filters/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/filters/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/filters/financials.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/filters/financials_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/filters/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/filters/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/filters/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/cbinsights/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/cbinsights/deals.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/cbinsights/equities.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/cbinsights/mixin.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/cbinsights/utils/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/cbinsights/utils/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/cbinsights/utils/client.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/daily_fundamental.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/fiscal_period.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/forecast.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/fundamental.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/geographic_segment.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/instrument.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/instrument_price.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/mixin.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/utils/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/backends/refinitiv/utils/controller.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/handlers/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/handlers/instrument.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/handlers/instrument_list.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/handlers/instrument_price.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/handlers/private_equities.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/cbinsights/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/cbinsights/deals.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/cbinsights/equities.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/cbinsights/fundamentals.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/refinitiv/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/refinitiv/daily_fundamental.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/refinitiv/forecast.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/refinitiv/fundamental.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/refinitiv/geographic_segment.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/refinitiv/instrument.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/refinitiv/instrument_price.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/parsers/refinitiv/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/resources/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/resources/classification.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/resources/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/import_export/resources/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/jinja2.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/locale/de/LC_MESSAGES/django.mo +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/locale/de/LC_MESSAGES/django.po +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/locale/en/LC_MESSAGES/django.mo +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/locale/en/LC_MESSAGES/django.po +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/locale/fr/LC_MESSAGES/django.mo +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/locale/fr/LC_MESSAGES/django.po +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/management/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0001_initial.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0002_rename_statements_instrumentlookup_financials_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0003_instrument_estimate_backend_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0004_rename_financials_instrumentlookup_statements_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0005_instrument_corporate_action_backend.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0006_instrument_officer_backend.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0007_instrument_country_instrument_currency_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0008_controversy.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0009_alter_controversy_flag_alter_controversy_initiated_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0010_classification_classificationgroup_deal_exchange_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0011_delete_instrumentlookup_instrument_corporate_actions_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0012_instrumentprice_created_instrumentprice_modified.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0013_instrument_is_investable_universe_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0014_alter_controversy_instrument.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0015_instrument_instrument_investible_index.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0016_instrumenttype_name_repr.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0017_instrument_instrument_security_index.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0018_instrument_instrument_level_index.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0019_alter_controversy_source.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0020_optionaggregate_option_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0021_delete_instrumentdailystatistics.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0022_instrument_cusip_option_open_interest_20d_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0023_instrument_unique_ric_instrument_unique_rmc_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0024_option_open_interest_10d_option_volume_10d_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0025_instrument_is_primary_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0026_instrument_is_cash_equivalent.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0027_remove_instrument_unique_ric_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0028_instrumentprice_annualized_daily_volatility.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0029_alter_instrumentprice_volume.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0030_alter_relatedinstrumentthroughmodel_related_type.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/0031_exchange_apply_round_lot_size_and_more.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/migrations/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/esg/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/esg/controversies.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/exchanges/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/exchanges/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/fields.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/fk_fields.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/indicators.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/instrument_lists.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/instrument_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/instrument_requests.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/llm/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/llm/create_instrument_news_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/mixin/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/mixin/financials_serializer_fields.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/mixin/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/options.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/private_equities.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/models/instruments/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/preferences.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/esg.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/instruments/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/instruments/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/instruments/instrument_lists.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/instruments/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/instruments/instrument_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/instruments/instrument_requests.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/instruments/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/instruments/mixins.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/serializers/officers.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/signals.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/sync/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/sync/abstract.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/sync/runner.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/analysis/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/analysis/financial_analysis/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/analysis/financial_analysis/test_statement_with_estimates.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/analysis/financial_analysis/test_utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/analysis/test_esg.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/conftest.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/dataloaders/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/dataloaders/test_cache.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/test_classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/test_exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/test_instrument_list.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/test_instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/test_merge.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/test_options.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/models/test_queryset.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/test_tasks.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/tests/tests.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/urls.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/buttons/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/buttons/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/buttons/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/buttons/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/buttons/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/esg.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/financial_summary.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/instrument_lists.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/instrument_requests.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/instruments_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/monthly_performances.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/officers.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/statement_with_estimates.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/display/statements.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/esg.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/financials_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/instrument_lists.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/instrument_requests.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/instruments_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/endpoints/statements.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/menus/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/menus/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/menus/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/menus/instrument_lists.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/menus/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/menus/instruments_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/esg.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/financial_ratio_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/financials_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/instrument_prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/instrument_requests.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/instruments_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/market_data.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/configs/titles/statement_with_estimates.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/esg.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/exchanges.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/financial_analysis/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/financial_analysis/financial_metric_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/financial_analysis/financial_ratio_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/financial_analysis/financial_summary.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/financial_analysis/statement_with_estimates.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/classifications.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/financials_analysis.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/instrument_lists.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/instrument_requests.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/instruments.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/instruments_relationships.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/instruments/utils.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/market_data.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/mixins.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/officers.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/prices.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/statements/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/statements/statements.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/viewsets/technical_analysis/__init__.py +0 -0
- {wbfdm-1.54.22 → wbfdm-1.55.4}/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.
|
|
3
|
+
Version: 1.55.4
|
|
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.*
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from datetime import date, timedelta
|
|
2
|
+
from typing import Iterator
|
|
3
|
+
|
|
4
|
+
import pypika as pk
|
|
5
|
+
from django.db import connections
|
|
6
|
+
from pypika import Case
|
|
7
|
+
from pypika import functions as fn
|
|
8
|
+
from pypika.enums import Order, SqlTypes
|
|
9
|
+
from wbcore.contrib.dataloader.dataloaders import Dataloader
|
|
10
|
+
from wbcore.contrib.dataloader.utils import dictfetchall
|
|
11
|
+
|
|
12
|
+
from wbfdm.dataloaders.protocols import FXRateProtocol
|
|
13
|
+
from wbfdm.dataloaders.types import FXRateDict
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DatastreamFXRatesDataloader(FXRateProtocol, Dataloader):
|
|
17
|
+
def fx_rates(
|
|
18
|
+
self,
|
|
19
|
+
from_date: date,
|
|
20
|
+
to_date: date,
|
|
21
|
+
target_currency: str,
|
|
22
|
+
) -> Iterator[FXRateDict]:
|
|
23
|
+
currencies = list(self.entities.values_list("currency__key", flat=True))
|
|
24
|
+
# Define tables
|
|
25
|
+
fx_rate = pk.Table("DS2FxRate")
|
|
26
|
+
fx_code = pk.Table("DS2FxCode")
|
|
27
|
+
|
|
28
|
+
# Base query to get data we always need unconditionally
|
|
29
|
+
query = (
|
|
30
|
+
pk.MSSQLQuery.from_(fx_rate)
|
|
31
|
+
# We join on _codes, which removes all instruments not in _codes - implicit where
|
|
32
|
+
.join(fx_code)
|
|
33
|
+
.on(fx_rate.ExRateIntCode == fx_code.ExRateIntCode)
|
|
34
|
+
.where((fx_rate.ExRateDate >= from_date) & (fx_rate.ExRateDate <= to_date + timedelta(days=1)))
|
|
35
|
+
.where(
|
|
36
|
+
(fx_code.ToCurrCode == target_currency)
|
|
37
|
+
& (fx_code.FromCurrCode.isin(currencies))
|
|
38
|
+
& (fx_code.RateTypeCode == "SPOT")
|
|
39
|
+
)
|
|
40
|
+
.orderby(fx_rate.ExRateDate, order=Order.desc)
|
|
41
|
+
.select(
|
|
42
|
+
fn.Cast(fx_rate.ExRateDate, SqlTypes.DATE).as_("fx_date"),
|
|
43
|
+
fn.Concat(fx_code.FromCurrCode, fx_code.ToCurrCode).as_("currency_pair"),
|
|
44
|
+
(Case().when(fx_code.FromCurrCode == target_currency, 1).else_(1 / fx_rate.midrate)).as_("fx_rate"),
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
with connections["qa"].cursor() as cursor:
|
|
48
|
+
cursor.execute(query.get_sql())
|
|
49
|
+
yield from dictfetchall(cursor, FXRateDict)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
1
2
|
from contextlib import suppress
|
|
2
3
|
from datetime import date
|
|
3
4
|
from enum import Enum
|
|
@@ -7,13 +8,14 @@ from typing import TYPE_CHECKING, Iterator
|
|
|
7
8
|
|
|
8
9
|
import pypika as pk
|
|
9
10
|
from django.db import ProgrammingError, connections
|
|
10
|
-
from pypika import
|
|
11
|
+
from pypika import Column, MSSQLQuery
|
|
11
12
|
from pypika import functions as fn
|
|
12
13
|
from pypika.enums import Order, SqlTypes
|
|
13
14
|
from pypika.terms import ValueWrapper
|
|
14
15
|
from wbcore.contrib.dataloader.dataloaders import Dataloader
|
|
15
16
|
from wbcore.contrib.dataloader.utils import dictfetchall
|
|
16
17
|
|
|
18
|
+
from wbfdm.contrib.qa.dataloaders.fx_rates import DatastreamFXRatesDataloader
|
|
17
19
|
from wbfdm.contrib.qa.dataloaders.utils import create_table
|
|
18
20
|
from wbfdm.dataloaders.protocols import MarketDataProtocol
|
|
19
21
|
from wbfdm.dataloaders.types import MarketDataDict
|
|
@@ -60,10 +62,19 @@ class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
|
60
62
|
Returns:
|
|
61
63
|
Iterator[MarketDataDict]: An iterator of dictionaries conforming to the DailyValuationDict.
|
|
62
64
|
"""
|
|
63
|
-
|
|
64
65
|
lookup = {
|
|
65
66
|
f"{k[0]},{k[1]}": v for k, v in self.entities.values_list("dl_parameters__market_data__parameters", "id")
|
|
66
67
|
}
|
|
68
|
+
fx_rates = defaultdict(dict)
|
|
69
|
+
if target_currency:
|
|
70
|
+
if exact_date:
|
|
71
|
+
from_date = exact_date
|
|
72
|
+
to_date = exact_date
|
|
73
|
+
if from_date and to_date:
|
|
74
|
+
for fx_rate in DatastreamFXRatesDataloader(self.entities).fx_rates(
|
|
75
|
+
from_date, to_date, target_currency
|
|
76
|
+
):
|
|
77
|
+
fx_rates[fx_rate["currency_pair"]][fx_rate["fx_date"]] = fx_rate["fx_rate"]
|
|
67
78
|
|
|
68
79
|
# Define tables
|
|
69
80
|
pricing = pk.Table("vw_DS2Pricing")
|
|
@@ -90,33 +101,7 @@ class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
|
90
101
|
.orderby(pricing.MarketDate, order=Order.desc)
|
|
91
102
|
)
|
|
92
103
|
|
|
93
|
-
|
|
94
|
-
# otherwise we just set the currency to whatever the currency is from the instrument
|
|
95
|
-
fx_rate = None
|
|
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")
|
|
100
|
-
query = (
|
|
101
|
-
query.select(
|
|
102
|
-
(Case().when(pricing.Currency == target_currency, 1).else_(1 / fx_rate.midrate)).as_("fx_rate")
|
|
103
|
-
)
|
|
104
|
-
# Join FX code table matching currencies and ensuring SPOT rate type
|
|
105
|
-
.left_join(fx_code)
|
|
106
|
-
.on(
|
|
107
|
-
(fx_code.FromCurrCode == pricing.Currency)
|
|
108
|
-
& (fx_code.ToCurrCode == target_currency)
|
|
109
|
-
& (fx_code.RateTypeCode == "SPOT")
|
|
110
|
-
)
|
|
111
|
-
# Join FX rate table matching internal code and date
|
|
112
|
-
.left_join(fx_rate)
|
|
113
|
-
.on((fx_rate.ExRateIntCode == fx_code.ExRateIntCode) & (fx_rate.ExRateDate == pricing.MarketDate))
|
|
114
|
-
# We filter out rows which do not have a proper fx rate (we exclude same currency conversions)
|
|
115
|
-
.where((Case().when(pricing.Currency == target_currency, 1).else_(fx_rate.midrate).isnotnull()))
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
else:
|
|
119
|
-
query = query.select(pricing.Currency.as_("currency"))
|
|
104
|
+
query = query.select(pricing.Currency.as_("currency"))
|
|
120
105
|
|
|
121
106
|
# if market cap or shares outstanding are required we need to join with an additional table
|
|
122
107
|
if MarketData.MARKET_CAPITALIZATION in values or MarketData.SHARES_OUTSTANDING in values:
|
|
@@ -130,9 +115,6 @@ class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
|
130
115
|
)
|
|
131
116
|
|
|
132
117
|
value = pricing_2.Close_
|
|
133
|
-
if fx_rate and apply_fx_rate:
|
|
134
|
-
value /= Case().when(pricing_2.Currency == target_currency, 1).else_(fx_rate.midrate)
|
|
135
|
-
|
|
136
118
|
query = query.select(value.as_("undadjusted_close"))
|
|
137
119
|
query = query.select(
|
|
138
120
|
MSSQLQuery.from_(num_shares)
|
|
@@ -148,9 +130,6 @@ class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
|
148
130
|
):
|
|
149
131
|
ds2_value = DS2MarketData[market_data.name].value
|
|
150
132
|
value = getattr(pricing, ds2_value)
|
|
151
|
-
if fx_rate and apply_fx_rate and market_data is not MarketData.SHARES_OUTSTANDING:
|
|
152
|
-
value /= Case().when(pricing.Currency == target_currency, 1).else_(fx_rate.midrate)
|
|
153
|
-
|
|
154
133
|
query = query.select(value.as_(market_data.value))
|
|
155
134
|
|
|
156
135
|
# Add conditional where clauses
|
|
@@ -189,7 +168,21 @@ class DatastreamMarketDataDataloader(MarketDataProtocol, Dataloader):
|
|
|
189
168
|
|
|
190
169
|
if MarketData.SHARES_OUTSTANDING in values:
|
|
191
170
|
row["outstanding_shares"] = (row["market_capitalization"] / row["close"]) if row["close"] else None
|
|
192
|
-
|
|
171
|
+
if target_currency:
|
|
172
|
+
try:
|
|
173
|
+
if target_currency == row["currency"]:
|
|
174
|
+
fx_rate = 1.0
|
|
175
|
+
else:
|
|
176
|
+
fx_rate = fx_rates[f'{row["currency"]}{target_currency}'][row["valuation_date"]] or 1.0
|
|
177
|
+
if apply_fx_rate:
|
|
178
|
+
for e in MarketData:
|
|
179
|
+
if e != MarketData.SHARES_OUTSTANDING and e.value in row and row[e.value]:
|
|
180
|
+
row[e.value] = row[e.value] * fx_rate
|
|
181
|
+
row["currency"] = target_currency
|
|
182
|
+
row["fx_rate"] = fx_rate
|
|
183
|
+
except KeyError:
|
|
184
|
+
# if we don't find the fx rate but we asked for it, we invalid that row and do not return it
|
|
185
|
+
continue
|
|
193
186
|
yield row
|
|
194
187
|
|
|
195
188
|
cursor.execute(MSSQLQuery.drop_table(mapping).get_sql())
|
|
@@ -239,6 +239,10 @@ class RKDStatementsDataloader(StatementsProtocol, Dataloader):
|
|
|
239
239
|
) -> Iterator[StatementDataDict]:
|
|
240
240
|
lookup = {k: v for k, v in self.entities.values_list("dl_parameters__statements__parameters", "id")}
|
|
241
241
|
sql = reported_sql if data_type is DataType.REPORTED else standardized_sql
|
|
242
|
+
if not financials:
|
|
243
|
+
financials = []
|
|
244
|
+
external_codes = [RKDFinancial[fin.name].value for fin in financials if fin.name in RKDFinancial.__members__]
|
|
245
|
+
|
|
242
246
|
query, bind_params = JinjaSql(param_style="format").prepare_query(
|
|
243
247
|
sql,
|
|
244
248
|
{
|
|
@@ -249,7 +253,7 @@ class RKDStatementsDataloader(StatementsProtocol, Dataloader):
|
|
|
249
253
|
"from_date": from_date,
|
|
250
254
|
"to_date": to_date,
|
|
251
255
|
"period_type": period_type.value,
|
|
252
|
-
"external_codes":
|
|
256
|
+
"external_codes": external_codes,
|
|
253
257
|
},
|
|
254
258
|
)
|
|
255
259
|
with connections["qa"].cursor() as cursor:
|
|
@@ -264,5 +268,8 @@ class RKDStatementsDataloader(StatementsProtocol, Dataloader):
|
|
|
264
268
|
row["year"] = int(row["year"] or row["period_end_date"].year)
|
|
265
269
|
row["instrument_id"] = lookup[row["external_identifier"]]
|
|
266
270
|
if financials:
|
|
267
|
-
|
|
271
|
+
try:
|
|
272
|
+
row["financial"] = Financial[RKDFinancial(row["external_code"]).name].value
|
|
273
|
+
except (ValueError, KeyError):
|
|
274
|
+
continue
|
|
268
275
|
yield row
|
|
@@ -7,6 +7,7 @@ from wbfdm.dataloaders.types import (
|
|
|
7
7
|
ESGControversyDataDict,
|
|
8
8
|
ESGDataDict,
|
|
9
9
|
FinancialDataDict,
|
|
10
|
+
FXRateDict,
|
|
10
11
|
MarketDataDict,
|
|
11
12
|
OfficerDataDict,
|
|
12
13
|
ReportDateDataDict,
|
|
@@ -36,6 +37,15 @@ class AdjustmentsProtocol(Protocol):
|
|
|
36
37
|
) -> Iterator[AdjustmentDataDict]: ...
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
class FXRateProtocol(Protocol):
|
|
41
|
+
def fx_rates(
|
|
42
|
+
self,
|
|
43
|
+
from_date: date,
|
|
44
|
+
to_date: date,
|
|
45
|
+
target_currency: str,
|
|
46
|
+
) -> Iterator[FXRateDict]: ...
|
|
47
|
+
|
|
48
|
+
|
|
39
49
|
class MarketDataProtocol(Protocol):
|
|
40
50
|
def market_data(
|
|
41
51
|
self,
|
|
@@ -9,6 +9,7 @@ from wbfdm.dataloaders.protocols import (
|
|
|
9
9
|
ESGControversyProtocol,
|
|
10
10
|
ESGProtocol,
|
|
11
11
|
FinancialsProtocol,
|
|
12
|
+
FXRateProtocol,
|
|
12
13
|
MarketDataProtocol,
|
|
13
14
|
OfficersProtocol,
|
|
14
15
|
ReportDateProtocol,
|
|
@@ -20,6 +21,7 @@ from wbfdm.dataloaders.types import (
|
|
|
20
21
|
ESGControversyDataDict,
|
|
21
22
|
ESGDataDict,
|
|
22
23
|
FinancialDataDict,
|
|
24
|
+
FXRateDict,
|
|
23
25
|
MarketDataDict,
|
|
24
26
|
OfficerDataDict,
|
|
25
27
|
ReportDateDataDict,
|
|
@@ -53,7 +55,8 @@ def _market_data_row_parser(row):
|
|
|
53
55
|
|
|
54
56
|
class InstrumentDataloaderProxy(
|
|
55
57
|
DataloaderProxy[
|
|
56
|
-
|
|
58
|
+
FXRateProtocol
|
|
59
|
+
| AdjustmentsProtocol
|
|
57
60
|
| MarketDataProtocol
|
|
58
61
|
| CorporateActionsProtocol
|
|
59
62
|
| OfficersProtocol
|
|
@@ -68,6 +71,15 @@ class InstrumentDataloaderProxy(
|
|
|
68
71
|
for dl in self.iterate_dataloaders("reporting_dates"):
|
|
69
72
|
yield from dl.reporting_dates(only_next=only_next)
|
|
70
73
|
|
|
74
|
+
def fx_rates(
|
|
75
|
+
self,
|
|
76
|
+
from_date: date,
|
|
77
|
+
to_date: date,
|
|
78
|
+
target_currency: str,
|
|
79
|
+
) -> Iterator[FXRateDict]:
|
|
80
|
+
for dl in self.iterate_dataloaders("fx_rates"):
|
|
81
|
+
yield from dl.fx_rates(from_date, to_date, target_currency)
|
|
82
|
+
|
|
71
83
|
def adjustments(self, from_date: date | None = None, to_date: date | None = None) -> Iterator[AdjustmentDataDict]:
|
|
72
84
|
for dl in self.iterate_dataloaders("adjustments"):
|
|
73
85
|
yield from dl.adjustments(from_date=from_date, to_date=to_date)
|
|
@@ -26,6 +26,12 @@ class BaseDict(TypedDict):
|
|
|
26
26
|
currency: NotRequired[str]
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
class FXRateDict(TypedDict):
|
|
30
|
+
currency_pair: str
|
|
31
|
+
fx_date: date
|
|
32
|
+
fx_rate: float
|
|
33
|
+
|
|
34
|
+
|
|
29
35
|
class MarketDataDict(BaseDict):
|
|
30
36
|
"""
|
|
31
37
|
Represents a dictionary for daily valuation data.
|
|
@@ -21,7 +21,7 @@ class InstrumentFactory(factory.django.DjangoModelFactory):
|
|
|
21
21
|
instrument_type = factory.SubFactory(InstrumentTypeFactory)
|
|
22
22
|
inception_date = factory.Faker("past_date")
|
|
23
23
|
delisted_date = None
|
|
24
|
-
currency = factory.SubFactory("wbcore.contrib.currency.factories.
|
|
24
|
+
currency = factory.SubFactory("wbcore.contrib.currency.factories.CurrencyUSDFactory")
|
|
25
25
|
country = factory.SubFactory("wbcore.contrib.geography.factories.CountryFactory")
|
|
26
26
|
exchange = factory.SubFactory("wbfdm.factories.exchanges.ExchangeFactory")
|
|
27
27
|
|
|
@@ -54,7 +54,7 @@ class InstrumentFactory(factory.django.DjangoModelFactory):
|
|
|
54
54
|
|
|
55
55
|
class CashFactory(factory.django.DjangoModelFactory):
|
|
56
56
|
is_cash = True
|
|
57
|
-
currency = factory.SubFactory("wbcore.contrib.currency.factories.
|
|
57
|
+
currency = factory.SubFactory("wbcore.contrib.currency.factories.CurrencyUSDFactory")
|
|
58
58
|
name = factory.LazyAttribute(lambda o: o.currency.title)
|
|
59
59
|
instrument_type = factory.LazyAttribute(
|
|
60
60
|
lambda o: InstrumentType.objects.get_or_create(key="cash", defaults={"name": "Cash", "short_name": "Cash"})[0]
|
|
@@ -26,7 +26,7 @@ class OptionAggregateImportHandler(ImportExportHandler):
|
|
|
26
26
|
|
|
27
27
|
def _get_instance(self, data: Dict[str, Any], history: Optional[models.QuerySet] = None, **kwargs) -> models.Model:
|
|
28
28
|
with suppress(ObjectDoesNotExist):
|
|
29
|
-
return self.model.objects.
|
|
29
|
+
return self.model.objects.get(instrument=data["instrument"], date=data["date"], type=data["type"])
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
class OptionImportHandler(ImportExportHandler):
|
|
@@ -46,7 +46,7 @@ class OptionImportHandler(ImportExportHandler):
|
|
|
46
46
|
|
|
47
47
|
def _get_instance(self, data: Dict[str, Any], history: Optional[models.QuerySet] = None, **kwargs) -> models.Model:
|
|
48
48
|
with suppress(ObjectDoesNotExist):
|
|
49
|
-
return self.model.objects.
|
|
49
|
+
return self.model.objects.get(
|
|
50
50
|
instrument=data["instrument"],
|
|
51
51
|
contract_identifier=data["contract_identifier"],
|
|
52
52
|
date=data["date"],
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.0.14 on 2025-08-27 07:59
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('wbfdm', '0031_exchange_apply_round_lot_size_and_more'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='instrumentprice',
|
|
15
|
+
name='outstanding_shares',
|
|
16
|
+
field=models.DecimalField(blank=True, decimal_places=4, help_text='The amount of outstanding share for this instrument', max_digits=16, null=True, verbose_name='Outstanding Shares'),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -195,9 +195,11 @@ class InstrumentPrice(
|
|
|
195
195
|
verbose_name="Value (Gross)",
|
|
196
196
|
) # TODO: I think we need to remove this field that is not really used here.
|
|
197
197
|
|
|
198
|
-
outstanding_shares =
|
|
198
|
+
outstanding_shares = models.DecimalField(
|
|
199
199
|
decimal_places=4,
|
|
200
200
|
max_digits=16,
|
|
201
|
+
blank=True,
|
|
202
|
+
null=True,
|
|
201
203
|
verbose_name="Outstanding Shares",
|
|
202
204
|
help_text="The amount of outstanding share for this instrument",
|
|
203
205
|
)
|
|
@@ -697,10 +697,6 @@ import pandas as pd
|
|
|
697
697
|
#
|
|
698
698
|
#
|
|
699
699
|
class InstrumentPriceComputedMixin:
|
|
700
|
-
def _compute_outstanding_shares(self):
|
|
701
|
-
if self.outstanding_shares is None and (previous_price := self.previous_price):
|
|
702
|
-
return previous_price.outstanding_shares
|
|
703
|
-
|
|
704
700
|
def _compute_outstanding_shares_consolidated(self):
|
|
705
701
|
if self.outstanding_shares_consolidated is None and self.outstanding_shares is not None:
|
|
706
702
|
return self.outstanding_shares
|
|
@@ -200,7 +200,7 @@ class InstrumentQuerySet(QuerySet):
|
|
|
200
200
|
padded_from_date = from_date - timedelta(days=15)
|
|
201
201
|
padded_to_date = to_date + timedelta(days=3)
|
|
202
202
|
logger.info(
|
|
203
|
-
f"Loading returns from {from_date:%Y-%m-%d} (padded to {padded_from_date:%Y-%m-%d}) to {to_date:%Y-%m-%d} (padded to {padded_to_date:%Y-%m-%d})"
|
|
203
|
+
f"Loading returns from {from_date:%Y-%m-%d} (padded to {padded_from_date:%Y-%m-%d}) to {to_date:%Y-%m-%d} (padded to {padded_to_date:%Y-%m-%d}) for {self.count()} instruments"
|
|
204
204
|
)
|
|
205
205
|
|
|
206
206
|
if use_dl:
|
|
@@ -248,13 +248,12 @@ class InstrumentQuerySet(QuerySet):
|
|
|
248
248
|
(df.index <= pd.Timestamp(to_date)) & (df.index >= pd.Timestamp(from_date))
|
|
249
249
|
] # ensure the returned df corresponds to requested date range
|
|
250
250
|
prices_df = df["close"]
|
|
251
|
-
|
|
252
251
|
if "fx_rate" in df.columns:
|
|
253
252
|
fx_rate_df = df["fx_rate"].fillna(1.0)
|
|
254
253
|
else:
|
|
255
254
|
fx_rate_df = pd.DataFrame(np.ones(prices_df.shape), index=prices_df.index, columns=prices_df.columns)
|
|
256
255
|
returns = prices_to_returns(fx_rate_df * prices_df, drop_inceptions_nan=False, fill_nan=True)
|
|
257
|
-
return {
|
|
258
|
-
|
|
259
|
-
)
|
|
256
|
+
return {
|
|
257
|
+
ts.date(): row for ts, row in prices_df.replace([np.nan], None).to_dict("index").items()
|
|
258
|
+
}, returns.replace([np.inf, -np.inf, np.nan], 0)
|
|
260
259
|
return {}, pd.DataFrame()
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
from contextlib import suppress
|
|
1
2
|
from datetime import date, timedelta
|
|
2
3
|
|
|
3
4
|
from celery import shared_task
|
|
4
5
|
from django.db import transaction
|
|
5
|
-
from django.db.models import Q
|
|
6
|
+
from django.db.models import ProtectedError, Q
|
|
6
7
|
from pandas.tseries.offsets import BDay
|
|
7
8
|
from tqdm import tqdm
|
|
8
9
|
|
|
@@ -89,7 +90,8 @@ def full_synchronization_as_task():
|
|
|
89
90
|
(Q(name="") & Q(name_repr="")) | (Q(source__in=["qa-ds2-security", "qa-ds2-quote"]) & Q(parent__isnull=True))
|
|
90
91
|
)
|
|
91
92
|
for instrument in qs:
|
|
92
|
-
|
|
93
|
+
with suppress(ProtectedError):
|
|
94
|
+
instrument.delete()
|
|
93
95
|
initialize_exchanges()
|
|
94
96
|
initialize_instruments()
|
|
95
97
|
with transaction.atomic():
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
from datetime import date
|
|
2
|
-
from decimal import Decimal
|
|
3
2
|
|
|
4
3
|
import pandas as pd
|
|
5
4
|
import pytest
|
|
6
5
|
from faker import Faker
|
|
7
|
-
from pandas.tseries.offsets import BDay
|
|
8
6
|
from wbcore.models import DynamicDecimalField, DynamicFloatField
|
|
9
7
|
|
|
10
8
|
from wbfdm.models import Instrument, InstrumentPrice, RelatedInstrumentThroughModel
|
|
@@ -168,18 +166,6 @@ class TestInstrumentPriceModel:
|
|
|
168
166
|
assert isinstance(instrument_price._meta.get_field("gross_value"), DynamicDecimalField)
|
|
169
167
|
assert instrument_price.gross_value == instrument_price.net_value
|
|
170
168
|
|
|
171
|
-
@pytest.mark.parametrize("instrument_price__outstanding_shares", [Decimal(10)])
|
|
172
|
-
def test_compute_outstanding_shares(self, instrument_price, instrument_price_factory):
|
|
173
|
-
next_price = instrument_price_factory.create(
|
|
174
|
-
instrument=instrument_price.instrument,
|
|
175
|
-
date=instrument_price.date + BDay(1),
|
|
176
|
-
outstanding_shares=None,
|
|
177
|
-
calculated=instrument_price.calculated,
|
|
178
|
-
)
|
|
179
|
-
assert hasattr(instrument_price, "_compute_outstanding_shares")
|
|
180
|
-
assert isinstance(instrument_price._meta.get_field("outstanding_shares"), DynamicDecimalField)
|
|
181
|
-
assert next_price.outstanding_shares == instrument_price.outstanding_shares
|
|
182
|
-
|
|
183
169
|
@pytest.mark.parametrize("instrument_price__volume_50d", [None])
|
|
184
170
|
def test_compute_volume_50d(self, instrument_price, instrument_price_factory):
|
|
185
171
|
assert hasattr(instrument_price, "_compute_volume_50d")
|
|
@@ -174,22 +174,22 @@ class InstrumentPriceInstrumentStatisticsChartView(InstrumentMixin, viewsets.Cha
|
|
|
174
174
|
|
|
175
175
|
if self.instrument.related_instruments.count() > 0:
|
|
176
176
|
reference = self.instrument.related_instruments.first().name_repr
|
|
177
|
-
risk = self.instrument.primary_risk_instrument.name_repr
|
|
178
177
|
df = pd.DataFrame(queryset.values("date", "sharpe_ratio", "correlation", "beta")).replace(
|
|
179
178
|
[np.inf, -np.inf], np.nan
|
|
180
179
|
)
|
|
181
180
|
|
|
182
181
|
if not df.empty:
|
|
183
182
|
df = df.set_index("date").sort_index().dropna()
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
183
|
+
if risk_instrument := self.instrument.primary_risk_instrument:
|
|
184
|
+
fig.add_trace(
|
|
185
|
+
go.Scatter(
|
|
186
|
+
x=df.index,
|
|
187
|
+
y=df.sharpe_ratio,
|
|
188
|
+
mode="lines",
|
|
189
|
+
name=f"Sharpe Ratio ({risk_instrument.name_repr})",
|
|
190
|
+
hovertemplate=get_hovertemplate_timeserie(currency=""),
|
|
191
|
+
)
|
|
191
192
|
)
|
|
192
|
-
)
|
|
193
193
|
fig.add_trace(
|
|
194
194
|
go.Scatter(
|
|
195
195
|
x=df.index,
|
|
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
|
{wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/financial_metric_analysis.py
RENAMED
|
File without changes
|
{wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/financial_ratio_analysis.py
RENAMED
|
File without changes
|
{wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/financial_statistics_analysis.py
RENAMED
|
File without changes
|
{wbfdm-1.54.22 → wbfdm-1.55.4}/wbfdm/analysis/financial_analysis/statement_with_estimates.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
|