wbfdm 2.2.1__py2.py3-none-any.whl

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.

Files changed (337) hide show
  1. wbfdm/__init__.py +2 -0
  2. wbfdm/admin/__init__.py +42 -0
  3. wbfdm/admin/classifications.py +39 -0
  4. wbfdm/admin/esg.py +23 -0
  5. wbfdm/admin/exchanges.py +53 -0
  6. wbfdm/admin/instrument_lists.py +23 -0
  7. wbfdm/admin/instrument_prices.py +62 -0
  8. wbfdm/admin/instrument_requests.py +33 -0
  9. wbfdm/admin/instruments.py +117 -0
  10. wbfdm/admin/instruments_relationships.py +25 -0
  11. wbfdm/admin/options.py +101 -0
  12. wbfdm/analysis/__init__.py +2 -0
  13. wbfdm/analysis/esg/__init__.py +0 -0
  14. wbfdm/analysis/esg/enums.py +82 -0
  15. wbfdm/analysis/esg/esg_analysis.py +217 -0
  16. wbfdm/analysis/esg/utils.py +13 -0
  17. wbfdm/analysis/financial_analysis/__init__.py +1 -0
  18. wbfdm/analysis/financial_analysis/financial_metric_analysis.py +88 -0
  19. wbfdm/analysis/financial_analysis/financial_ratio_analysis.py +125 -0
  20. wbfdm/analysis/financial_analysis/financial_statistics_analysis.py +271 -0
  21. wbfdm/analysis/financial_analysis/statement_with_estimates.py +558 -0
  22. wbfdm/analysis/financial_analysis/utils.py +316 -0
  23. wbfdm/analysis/technical_analysis/__init__.py +1 -0
  24. wbfdm/analysis/technical_analysis/technical_analysis.py +138 -0
  25. wbfdm/analysis/technical_analysis/traces.py +165 -0
  26. wbfdm/analysis/utils.py +32 -0
  27. wbfdm/apps.py +14 -0
  28. wbfdm/contrib/__init__.py +0 -0
  29. wbfdm/contrib/dsws/__init__.py +0 -0
  30. wbfdm/contrib/dsws/client.py +285 -0
  31. wbfdm/contrib/internal/__init__.py +0 -0
  32. wbfdm/contrib/internal/dataloaders/__init__.py +0 -0
  33. wbfdm/contrib/internal/dataloaders/market_data.py +87 -0
  34. wbfdm/contrib/metric/__init__.py +0 -0
  35. wbfdm/contrib/metric/admin/__init__.py +2 -0
  36. wbfdm/contrib/metric/admin/instruments.py +12 -0
  37. wbfdm/contrib/metric/admin/metrics.py +43 -0
  38. wbfdm/contrib/metric/apps.py +10 -0
  39. wbfdm/contrib/metric/backends/__init__.py +2 -0
  40. wbfdm/contrib/metric/backends/base.py +159 -0
  41. wbfdm/contrib/metric/backends/performances.py +265 -0
  42. wbfdm/contrib/metric/backends/statistics.py +182 -0
  43. wbfdm/contrib/metric/decorators.py +14 -0
  44. wbfdm/contrib/metric/dispatch.py +23 -0
  45. wbfdm/contrib/metric/dto.py +88 -0
  46. wbfdm/contrib/metric/exceptions.py +6 -0
  47. wbfdm/contrib/metric/factories.py +33 -0
  48. wbfdm/contrib/metric/filters.py +28 -0
  49. wbfdm/contrib/metric/migrations/0001_initial.py +88 -0
  50. wbfdm/contrib/metric/migrations/0002_remove_instrumentmetric_unique_instrument_metric_and_more.py +26 -0
  51. wbfdm/contrib/metric/migrations/__init__.py +0 -0
  52. wbfdm/contrib/metric/models.py +180 -0
  53. wbfdm/contrib/metric/orchestrators.py +94 -0
  54. wbfdm/contrib/metric/registry.py +80 -0
  55. wbfdm/contrib/metric/serializers.py +44 -0
  56. wbfdm/contrib/metric/tasks.py +27 -0
  57. wbfdm/contrib/metric/tests/__init__.py +0 -0
  58. wbfdm/contrib/metric/tests/backends/__init__.py +0 -0
  59. wbfdm/contrib/metric/tests/backends/test_performances.py +152 -0
  60. wbfdm/contrib/metric/tests/backends/test_statistics.py +48 -0
  61. wbfdm/contrib/metric/tests/conftest.py +92 -0
  62. wbfdm/contrib/metric/tests/test_dto.py +73 -0
  63. wbfdm/contrib/metric/tests/test_models.py +72 -0
  64. wbfdm/contrib/metric/tests/test_tasks.py +24 -0
  65. wbfdm/contrib/metric/tests/test_viewsets.py +79 -0
  66. wbfdm/contrib/metric/urls.py +19 -0
  67. wbfdm/contrib/metric/viewsets/__init__.py +1 -0
  68. wbfdm/contrib/metric/viewsets/configs/__init__.py +1 -0
  69. wbfdm/contrib/metric/viewsets/configs/display.py +92 -0
  70. wbfdm/contrib/metric/viewsets/configs/menus.py +11 -0
  71. wbfdm/contrib/metric/viewsets/configs/utils.py +137 -0
  72. wbfdm/contrib/metric/viewsets/mixins.py +245 -0
  73. wbfdm/contrib/metric/viewsets/viewsets.py +40 -0
  74. wbfdm/contrib/msci/__init__.py +0 -0
  75. wbfdm/contrib/msci/client.py +92 -0
  76. wbfdm/contrib/msci/dataloaders/__init__.py +0 -0
  77. wbfdm/contrib/msci/dataloaders/esg.py +87 -0
  78. wbfdm/contrib/msci/dataloaders/esg_controversies.py +81 -0
  79. wbfdm/contrib/msci/sync.py +58 -0
  80. wbfdm/contrib/msci/tests/__init__.py +0 -0
  81. wbfdm/contrib/msci/tests/conftest.py +1 -0
  82. wbfdm/contrib/msci/tests/test_client.py +70 -0
  83. wbfdm/contrib/qa/__init__.py +0 -0
  84. wbfdm/contrib/qa/apps.py +22 -0
  85. wbfdm/contrib/qa/database_routers.py +25 -0
  86. wbfdm/contrib/qa/dataloaders/__init__.py +0 -0
  87. wbfdm/contrib/qa/dataloaders/adjustments.py +56 -0
  88. wbfdm/contrib/qa/dataloaders/corporate_actions.py +59 -0
  89. wbfdm/contrib/qa/dataloaders/financials.py +83 -0
  90. wbfdm/contrib/qa/dataloaders/market_data.py +117 -0
  91. wbfdm/contrib/qa/dataloaders/officers.py +59 -0
  92. wbfdm/contrib/qa/dataloaders/reporting_dates.py +67 -0
  93. wbfdm/contrib/qa/dataloaders/statements.py +267 -0
  94. wbfdm/contrib/qa/tasks.py +0 -0
  95. wbfdm/dataloaders/__init__.py +0 -0
  96. wbfdm/dataloaders/cache.py +129 -0
  97. wbfdm/dataloaders/protocols.py +112 -0
  98. wbfdm/dataloaders/proxies.py +201 -0
  99. wbfdm/dataloaders/types.py +209 -0
  100. wbfdm/dynamic_preferences_registry.py +45 -0
  101. wbfdm/enums.py +657 -0
  102. wbfdm/factories/__init__.py +13 -0
  103. wbfdm/factories/classifications.py +56 -0
  104. wbfdm/factories/controversies.py +27 -0
  105. wbfdm/factories/exchanges.py +21 -0
  106. wbfdm/factories/instrument_list.py +22 -0
  107. wbfdm/factories/instrument_prices.py +79 -0
  108. wbfdm/factories/instruments.py +63 -0
  109. wbfdm/factories/instruments_relationships.py +31 -0
  110. wbfdm/factories/options.py +66 -0
  111. wbfdm/figures/__init__.py +1 -0
  112. wbfdm/figures/financials/__init__.py +1 -0
  113. wbfdm/figures/financials/financial_analysis_charts.py +469 -0
  114. wbfdm/figures/financials/financials_charts.py +711 -0
  115. wbfdm/filters/__init__.py +31 -0
  116. wbfdm/filters/classifications.py +100 -0
  117. wbfdm/filters/exchanges.py +22 -0
  118. wbfdm/filters/financials.py +95 -0
  119. wbfdm/filters/financials_analysis.py +119 -0
  120. wbfdm/filters/instrument_prices.py +112 -0
  121. wbfdm/filters/instruments.py +198 -0
  122. wbfdm/filters/utils.py +44 -0
  123. wbfdm/import_export/__init__.py +0 -0
  124. wbfdm/import_export/backends/__init__.py +0 -0
  125. wbfdm/import_export/backends/cbinsights/__init__.py +2 -0
  126. wbfdm/import_export/backends/cbinsights/deals.py +44 -0
  127. wbfdm/import_export/backends/cbinsights/equities.py +41 -0
  128. wbfdm/import_export/backends/cbinsights/mixin.py +15 -0
  129. wbfdm/import_export/backends/cbinsights/utils/__init__.py +0 -0
  130. wbfdm/import_export/backends/cbinsights/utils/classifications.py +4150 -0
  131. wbfdm/import_export/backends/cbinsights/utils/client.py +217 -0
  132. wbfdm/import_export/backends/refinitiv/__init__.py +5 -0
  133. wbfdm/import_export/backends/refinitiv/daily_fundamental.py +36 -0
  134. wbfdm/import_export/backends/refinitiv/fiscal_period.py +63 -0
  135. wbfdm/import_export/backends/refinitiv/forecast.py +178 -0
  136. wbfdm/import_export/backends/refinitiv/fundamental.py +103 -0
  137. wbfdm/import_export/backends/refinitiv/geographic_segment.py +32 -0
  138. wbfdm/import_export/backends/refinitiv/instrument.py +55 -0
  139. wbfdm/import_export/backends/refinitiv/instrument_price.py +77 -0
  140. wbfdm/import_export/backends/refinitiv/mixin.py +29 -0
  141. wbfdm/import_export/backends/refinitiv/utils/__init__.py +1 -0
  142. wbfdm/import_export/backends/refinitiv/utils/controller.py +182 -0
  143. wbfdm/import_export/handlers/__init__.py +0 -0
  144. wbfdm/import_export/handlers/instrument.py +253 -0
  145. wbfdm/import_export/handlers/instrument_list.py +101 -0
  146. wbfdm/import_export/handlers/instrument_price.py +71 -0
  147. wbfdm/import_export/handlers/option.py +54 -0
  148. wbfdm/import_export/handlers/private_equities.py +49 -0
  149. wbfdm/import_export/parsers/__init__.py +0 -0
  150. wbfdm/import_export/parsers/cbinsights/__init__.py +0 -0
  151. wbfdm/import_export/parsers/cbinsights/deals.py +39 -0
  152. wbfdm/import_export/parsers/cbinsights/equities.py +56 -0
  153. wbfdm/import_export/parsers/cbinsights/fundamentals.py +45 -0
  154. wbfdm/import_export/parsers/refinitiv/__init__.py +0 -0
  155. wbfdm/import_export/parsers/refinitiv/daily_fundamental.py +7 -0
  156. wbfdm/import_export/parsers/refinitiv/forecast.py +7 -0
  157. wbfdm/import_export/parsers/refinitiv/fundamental.py +9 -0
  158. wbfdm/import_export/parsers/refinitiv/geographic_segment.py +7 -0
  159. wbfdm/import_export/parsers/refinitiv/instrument.py +75 -0
  160. wbfdm/import_export/parsers/refinitiv/instrument_price.py +26 -0
  161. wbfdm/import_export/parsers/refinitiv/utils.py +96 -0
  162. wbfdm/import_export/resources/__init__.py +0 -0
  163. wbfdm/import_export/resources/classification.py +23 -0
  164. wbfdm/import_export/resources/instrument_prices.py +33 -0
  165. wbfdm/import_export/resources/instruments.py +176 -0
  166. wbfdm/jinja2.py +7 -0
  167. wbfdm/management/__init__.py +30 -0
  168. wbfdm/menu.py +11 -0
  169. wbfdm/migrations/0001_initial.py +71 -0
  170. wbfdm/migrations/0002_rename_statements_instrumentlookup_financials_and_more.py +144 -0
  171. wbfdm/migrations/0003_instrument_estimate_backend_and_more.py +34 -0
  172. wbfdm/migrations/0004_rename_financials_instrumentlookup_statements_and_more.py +86 -0
  173. wbfdm/migrations/0005_instrument_corporate_action_backend.py +29 -0
  174. wbfdm/migrations/0006_instrument_officer_backend.py +29 -0
  175. wbfdm/migrations/0007_instrument_country_instrument_currency_and_more.py +117 -0
  176. wbfdm/migrations/0008_controversy.py +75 -0
  177. wbfdm/migrations/0009_alter_controversy_flag_alter_controversy_initiated_and_more.py +85 -0
  178. wbfdm/migrations/0010_classification_classificationgroup_deal_exchange_and_more.py +1299 -0
  179. wbfdm/migrations/0011_delete_instrumentlookup_instrument_corporate_actions_and_more.py +169 -0
  180. wbfdm/migrations/0012_instrumentprice_created_instrumentprice_modified.py +564 -0
  181. wbfdm/migrations/0013_instrument_is_investable_universe_and_more.py +199 -0
  182. wbfdm/migrations/0014_alter_controversy_instrument.py +22 -0
  183. wbfdm/migrations/0015_instrument_instrument_investible_index.py +16 -0
  184. wbfdm/migrations/0016_instrumenttype_name_repr.py +18 -0
  185. wbfdm/migrations/0017_instrument_instrument_security_index.py +16 -0
  186. wbfdm/migrations/0018_instrument_instrument_level_index.py +20 -0
  187. wbfdm/migrations/0019_alter_controversy_source.py +17 -0
  188. wbfdm/migrations/0020_optionaggregate_option_and_more.py +249 -0
  189. wbfdm/migrations/0021_delete_instrumentdailystatistics.py +15 -0
  190. wbfdm/migrations/0022_instrument_cusip_option_open_interest_20d_and_more.py +91 -0
  191. wbfdm/migrations/0023_instrument_unique_ric_instrument_unique_rmc_and_more.py +53 -0
  192. wbfdm/migrations/0024_option_open_interest_10d_option_volume_10d_and_more.py +36 -0
  193. wbfdm/migrations/0025_instrument_is_primary_and_more.py +29 -0
  194. wbfdm/migrations/0026_instrument_is_cash_equivalent.py +30 -0
  195. wbfdm/migrations/0027_remove_instrument_unique_ric_and_more.py +100 -0
  196. wbfdm/migrations/__init__.py +0 -0
  197. wbfdm/models/__init__.py +4 -0
  198. wbfdm/models/esg/__init__.py +1 -0
  199. wbfdm/models/esg/controversies.py +81 -0
  200. wbfdm/models/exchanges/__init__.py +1 -0
  201. wbfdm/models/exchanges/exchanges.py +223 -0
  202. wbfdm/models/fields.py +117 -0
  203. wbfdm/models/fk_fields.py +403 -0
  204. wbfdm/models/indicators.py +0 -0
  205. wbfdm/models/instruments/__init__.py +19 -0
  206. wbfdm/models/instruments/classifications.py +265 -0
  207. wbfdm/models/instruments/instrument_lists.py +120 -0
  208. wbfdm/models/instruments/instrument_prices.py +540 -0
  209. wbfdm/models/instruments/instrument_relationships.py +251 -0
  210. wbfdm/models/instruments/instrument_requests.py +196 -0
  211. wbfdm/models/instruments/instruments.py +991 -0
  212. wbfdm/models/instruments/llm/__init__.py +1 -0
  213. wbfdm/models/instruments/llm/create_instrument_news_relationships.py +78 -0
  214. wbfdm/models/instruments/mixin/__init__.py +0 -0
  215. wbfdm/models/instruments/mixin/financials_computed.py +804 -0
  216. wbfdm/models/instruments/mixin/financials_serializer_fields.py +1407 -0
  217. wbfdm/models/instruments/mixin/instruments.py +294 -0
  218. wbfdm/models/instruments/options.py +225 -0
  219. wbfdm/models/instruments/private_equities.py +59 -0
  220. wbfdm/models/instruments/querysets.py +73 -0
  221. wbfdm/models/instruments/utils.py +41 -0
  222. wbfdm/preferences.py +21 -0
  223. wbfdm/serializers/__init__.py +4 -0
  224. wbfdm/serializers/esg.py +36 -0
  225. wbfdm/serializers/exchanges.py +39 -0
  226. wbfdm/serializers/instruments/__init__.py +37 -0
  227. wbfdm/serializers/instruments/classifications.py +139 -0
  228. wbfdm/serializers/instruments/instrument_lists.py +61 -0
  229. wbfdm/serializers/instruments/instrument_prices.py +73 -0
  230. wbfdm/serializers/instruments/instrument_relationships.py +170 -0
  231. wbfdm/serializers/instruments/instrument_requests.py +61 -0
  232. wbfdm/serializers/instruments/instruments.py +274 -0
  233. wbfdm/serializers/instruments/mixins.py +104 -0
  234. wbfdm/serializers/officers.py +20 -0
  235. wbfdm/signals.py +7 -0
  236. wbfdm/sync/__init__.py +0 -0
  237. wbfdm/sync/abstract.py +31 -0
  238. wbfdm/sync/runner.py +22 -0
  239. wbfdm/tasks.py +69 -0
  240. wbfdm/tests/__init__.py +0 -0
  241. wbfdm/tests/analysis/__init__.py +0 -0
  242. wbfdm/tests/analysis/financial_analysis/__init__.py +0 -0
  243. wbfdm/tests/analysis/financial_analysis/test_statement_with_estimates.py +392 -0
  244. wbfdm/tests/analysis/financial_analysis/test_utils.py +322 -0
  245. wbfdm/tests/analysis/test_esg.py +159 -0
  246. wbfdm/tests/conftest.py +92 -0
  247. wbfdm/tests/dataloaders/__init__.py +0 -0
  248. wbfdm/tests/dataloaders/test_cache.py +73 -0
  249. wbfdm/tests/models/__init__.py +0 -0
  250. wbfdm/tests/models/test_classifications.py +99 -0
  251. wbfdm/tests/models/test_exchanges.py +7 -0
  252. wbfdm/tests/models/test_instrument_list.py +117 -0
  253. wbfdm/tests/models/test_instrument_prices.py +306 -0
  254. wbfdm/tests/models/test_instruments.py +202 -0
  255. wbfdm/tests/models/test_merge.py +99 -0
  256. wbfdm/tests/models/test_options.py +69 -0
  257. wbfdm/tests/test_tasks.py +6 -0
  258. wbfdm/tests/tests.py +10 -0
  259. wbfdm/urls.py +222 -0
  260. wbfdm/utils.py +54 -0
  261. wbfdm/viewsets/__init__.py +10 -0
  262. wbfdm/viewsets/configs/__init__.py +5 -0
  263. wbfdm/viewsets/configs/buttons/__init__.py +8 -0
  264. wbfdm/viewsets/configs/buttons/classifications.py +23 -0
  265. wbfdm/viewsets/configs/buttons/exchanges.py +9 -0
  266. wbfdm/viewsets/configs/buttons/instrument_prices.py +49 -0
  267. wbfdm/viewsets/configs/buttons/instruments.py +283 -0
  268. wbfdm/viewsets/configs/display/__init__.py +22 -0
  269. wbfdm/viewsets/configs/display/classifications.py +138 -0
  270. wbfdm/viewsets/configs/display/esg.py +75 -0
  271. wbfdm/viewsets/configs/display/exchanges.py +42 -0
  272. wbfdm/viewsets/configs/display/instrument_lists.py +137 -0
  273. wbfdm/viewsets/configs/display/instrument_prices.py +199 -0
  274. wbfdm/viewsets/configs/display/instrument_requests.py +116 -0
  275. wbfdm/viewsets/configs/display/instruments.py +618 -0
  276. wbfdm/viewsets/configs/display/instruments_relationships.py +65 -0
  277. wbfdm/viewsets/configs/display/monthly_performances.py +72 -0
  278. wbfdm/viewsets/configs/display/officers.py +16 -0
  279. wbfdm/viewsets/configs/display/prices.py +21 -0
  280. wbfdm/viewsets/configs/display/statement_with_estimates.py +101 -0
  281. wbfdm/viewsets/configs/display/statements.py +48 -0
  282. wbfdm/viewsets/configs/endpoints/__init__.py +41 -0
  283. wbfdm/viewsets/configs/endpoints/classifications.py +87 -0
  284. wbfdm/viewsets/configs/endpoints/esg.py +20 -0
  285. wbfdm/viewsets/configs/endpoints/exchanges.py +6 -0
  286. wbfdm/viewsets/configs/endpoints/financials_analysis.py +65 -0
  287. wbfdm/viewsets/configs/endpoints/instrument_lists.py +38 -0
  288. wbfdm/viewsets/configs/endpoints/instrument_prices.py +51 -0
  289. wbfdm/viewsets/configs/endpoints/instrument_requests.py +20 -0
  290. wbfdm/viewsets/configs/endpoints/instruments.py +13 -0
  291. wbfdm/viewsets/configs/endpoints/instruments_relationships.py +31 -0
  292. wbfdm/viewsets/configs/endpoints/statements.py +6 -0
  293. wbfdm/viewsets/configs/menus/__init__.py +9 -0
  294. wbfdm/viewsets/configs/menus/classifications.py +19 -0
  295. wbfdm/viewsets/configs/menus/exchanges.py +10 -0
  296. wbfdm/viewsets/configs/menus/instrument_lists.py +10 -0
  297. wbfdm/viewsets/configs/menus/instruments.py +20 -0
  298. wbfdm/viewsets/configs/menus/instruments_relationships.py +33 -0
  299. wbfdm/viewsets/configs/titles/__init__.py +42 -0
  300. wbfdm/viewsets/configs/titles/classifications.py +79 -0
  301. wbfdm/viewsets/configs/titles/esg.py +11 -0
  302. wbfdm/viewsets/configs/titles/exchanges.py +12 -0
  303. wbfdm/viewsets/configs/titles/financial_ratio_analysis.py +6 -0
  304. wbfdm/viewsets/configs/titles/financials_analysis.py +50 -0
  305. wbfdm/viewsets/configs/titles/instrument_prices.py +50 -0
  306. wbfdm/viewsets/configs/titles/instrument_requests.py +16 -0
  307. wbfdm/viewsets/configs/titles/instruments.py +31 -0
  308. wbfdm/viewsets/configs/titles/instruments_relationships.py +21 -0
  309. wbfdm/viewsets/configs/titles/market_data.py +13 -0
  310. wbfdm/viewsets/configs/titles/prices.py +15 -0
  311. wbfdm/viewsets/configs/titles/statement_with_estimates.py +10 -0
  312. wbfdm/viewsets/esg.py +72 -0
  313. wbfdm/viewsets/exchanges.py +63 -0
  314. wbfdm/viewsets/financial_analysis/__init__.py +3 -0
  315. wbfdm/viewsets/financial_analysis/financial_metric_analysis.py +85 -0
  316. wbfdm/viewsets/financial_analysis/financial_ratio_analysis.py +85 -0
  317. wbfdm/viewsets/financial_analysis/statement_with_estimates.py +145 -0
  318. wbfdm/viewsets/instruments/__init__.py +80 -0
  319. wbfdm/viewsets/instruments/classifications.py +279 -0
  320. wbfdm/viewsets/instruments/financials_analysis.py +614 -0
  321. wbfdm/viewsets/instruments/instrument_lists.py +77 -0
  322. wbfdm/viewsets/instruments/instrument_prices.py +542 -0
  323. wbfdm/viewsets/instruments/instrument_requests.py +51 -0
  324. wbfdm/viewsets/instruments/instruments.py +106 -0
  325. wbfdm/viewsets/instruments/instruments_relationships.py +235 -0
  326. wbfdm/viewsets/instruments/utils.py +27 -0
  327. wbfdm/viewsets/market_data.py +172 -0
  328. wbfdm/viewsets/mixins.py +9 -0
  329. wbfdm/viewsets/officers.py +27 -0
  330. wbfdm/viewsets/prices.py +62 -0
  331. wbfdm/viewsets/statements/__init__.py +1 -0
  332. wbfdm/viewsets/statements/statements.py +100 -0
  333. wbfdm/viewsets/technical_analysis/__init__.py +1 -0
  334. wbfdm/viewsets/technical_analysis/monthly_performances.py +93 -0
  335. wbfdm-2.2.1.dist-info/METADATA +15 -0
  336. wbfdm-2.2.1.dist-info/RECORD +337 -0
  337. wbfdm-2.2.1.dist-info/WHEEL +5 -0
@@ -0,0 +1,61 @@
1
+ from wbcore import serializers as wb_serializers
2
+ from wbcore.contrib.directory.serializers import PersonRepresentationSerializer
3
+ from wbfdm.models.instruments import InstrumentRequest
4
+
5
+ from .instruments import InstrumentModelSerializer, InstrumentRepresentationSerializer
6
+
7
+
8
+ class InstrumentRequestRepresentationSerializer(wb_serializers.RepresentationSerializer):
9
+ _detail = wb_serializers.HyperlinkField(reverse_name="wbfdm:instrumentrequest-detail")
10
+
11
+ class Meta:
12
+ model = InstrumentRequest
13
+ fields = ("id", "status", "_detail")
14
+
15
+
16
+ class InstrumentRequestModelSerializer(wb_serializers.ModelSerializer):
17
+ _requester = PersonRepresentationSerializer(source="requester")
18
+ _handler = PersonRepresentationSerializer(source="handler")
19
+ _created_instrument = InstrumentRepresentationSerializer(source="created_instrument")
20
+ notes = wb_serializers.CharField(required=False)
21
+
22
+ def validate(self, data):
23
+ if (not self.instance or not self.instance.requester) and (request := self.context.get("request")):
24
+ data["requester"] = request.user.profile
25
+ return super().validate(data)
26
+
27
+ class Meta:
28
+ model = InstrumentRequest
29
+ fields = (
30
+ "id",
31
+ "status",
32
+ "requester",
33
+ "_requester",
34
+ "_handler",
35
+ "handler",
36
+ "_created_instrument",
37
+ "created_instrument",
38
+ "notes",
39
+ "created",
40
+ "_additional_resources",
41
+ )
42
+ flatten_fields = {
43
+ "instrument_data": wb_serializers.JSONTableField(
44
+ serializer_class=InstrumentModelSerializer,
45
+ required=False,
46
+ flatten_field_names=[
47
+ "name",
48
+ "name_repr",
49
+ "instrument_type",
50
+ "refinitiv_identifier_code",
51
+ "refinitiv_mnemonic_code",
52
+ "isin",
53
+ "ticker",
54
+ "is_cash",
55
+ "currency",
56
+ "country",
57
+ "tags",
58
+ "classifications",
59
+ ],
60
+ )
61
+ }
@@ -0,0 +1,274 @@
1
+ from typing import TYPE_CHECKING, Type
2
+
3
+ from django.contrib.auth import get_user_model
4
+ from rest_framework.reverse import reverse
5
+ from wbcore import serializers
6
+ from wbcore.contrib.currency.models import Currency
7
+ from wbcore.contrib.currency.serializers import CurrencyRepresentationSerializer
8
+ from wbcore.contrib.geography.models import Geography
9
+ from wbcore.contrib.geography.serializers import CountryRepresentationSerializer
10
+ from wbcore.contrib.tags.serializers import TagRepresentationSerializer
11
+ from wbfdm.models import Instrument, InstrumentType
12
+
13
+ from ..exchanges import ExchangeRepresentationSerializer
14
+ from .classifications import ClassificationRepresentationSerializer
15
+ from .mixins import InstrumentAdditionalResourcesMixin
16
+
17
+ if TYPE_CHECKING:
18
+ User = Type[get_user_model()]
19
+
20
+
21
+ class InstrumentTypeRepresentationSerializer(serializers.RepresentationSerializer):
22
+ class Meta:
23
+ model = InstrumentType
24
+ fields = ("id", "name", "key")
25
+
26
+
27
+ class InstrumentRepresentationSerializer(serializers.RepresentationSerializer):
28
+ _detail = serializers.HyperlinkField(reverse_name="wbfdm:instrument-detail")
29
+
30
+ def get_filter_params(self, request):
31
+ filter_params = {}
32
+ if (view := request.parser_context.get("view", None)) and (
33
+ classification_id := view.kwargs.get("classification_id", None)
34
+ ):
35
+ filter_params["classifications_neq"] = classification_id
36
+
37
+ return filter_params
38
+
39
+ class Meta:
40
+ model = Instrument
41
+ fields = ("id", "name", "ticker", "isin", "computed_str", "_detail")
42
+
43
+
44
+ class ClassifiableInstrumentRepresentationSerializer(InstrumentRepresentationSerializer):
45
+ def get_filter_params(self, request):
46
+ filter_params = super().get_filter_params(request)
47
+ filter_params["instrument_type__is_classifiable"] = True
48
+ filter_params["level"] = 0
49
+ return filter_params
50
+
51
+
52
+ class SecurityRepresentationSerializer(InstrumentRepresentationSerializer):
53
+ def get_filter_params(self, request):
54
+ filter_params = super().get_filter_params(request)
55
+ filter_params["is_security"] = True
56
+ return filter_params
57
+
58
+
59
+ class InvestableUniverseRepresentationSerializer(InstrumentRepresentationSerializer):
60
+ def get_filter_params(self, request):
61
+ filter_params = super().get_filter_params(request)
62
+ filter_params["is_investable_universe"] = True
63
+ return filter_params
64
+
65
+
66
+ class InvestableInstrumentRepresentationSerializer(InstrumentRepresentationSerializer):
67
+ def get_filter_params(self, request):
68
+ filter_params = super().get_filter_params(request)
69
+ filter_params["is_investable"] = True
70
+ return filter_params
71
+
72
+
73
+ class PrimaryInvestableInstrumentRepresentationSerializer(InvestableInstrumentRepresentationSerializer):
74
+ def get_filter_params(self, request):
75
+ filter_params = super().get_filter_params(request)
76
+ filter_params["is_primary"] = True
77
+ return filter_params
78
+
79
+
80
+ class ManagedInstrumentRepresentationSerializer(InstrumentRepresentationSerializer):
81
+ def get_filter_params(self, request):
82
+ filter_params = super().get_filter_params(request)
83
+ filter_params["is_managed"] = True
84
+ return filter_params
85
+
86
+
87
+ class EquityRepresentationSerializer(InstrumentRepresentationSerializer):
88
+ def get_filter_params(self, request):
89
+ filter_params = super().get_filter_params(request)
90
+ filter_params["investment_type__key"] = "equity"
91
+ return filter_params
92
+
93
+
94
+ class ProductRepresentationSerializer(InstrumentRepresentationSerializer):
95
+ def get_filter_params(self, request):
96
+ filter_params = super().get_filter_params(request)
97
+ filter_params["investment_type__key"] = "product"
98
+ return filter_params
99
+
100
+
101
+ class InstrumentModelListSerializer(
102
+ serializers.ModelSerializer,
103
+ ):
104
+ _currency = CurrencyRepresentationSerializer(source="currency")
105
+ currency = serializers.PrimaryKeyRelatedField(queryset=Currency.objects.all())
106
+ currency_symbol = serializers.CharField(read_only=True)
107
+ _exchange = ExchangeRepresentationSerializer(source="exchange")
108
+ country = serializers.PrimaryKeyRelatedField(queryset=Geography.countries.all())
109
+ _country = CountryRepresentationSerializer(source="country")
110
+ instrument_type = serializers.PrimaryKeyRelatedField(queryset=InstrumentType.objects.all())
111
+ _instrument_type = InstrumentTypeRepresentationSerializer(source="instrument_type")
112
+ _tags = TagRepresentationSerializer(many=True, source="tags")
113
+
114
+ _classifications = ClassificationRepresentationSerializer(
115
+ source="classifications", many=True, label_key="{{ name }}"
116
+ )
117
+ _parent = InstrumentRepresentationSerializer(source="parent")
118
+ is_active = serializers.BooleanField(default=True, read_only=True)
119
+ is_cash = serializers.BooleanField(default=False, read_only=True)
120
+ _group_key = serializers.CharField(read_only=True)
121
+
122
+ class Meta:
123
+ model = Instrument
124
+ read_only_fields = (
125
+ "name",
126
+ "exchange",
127
+ "computed_str",
128
+ "instrument_type",
129
+ "old_isins",
130
+ "inception_date",
131
+ "delisted_date",
132
+ "country",
133
+ "isin",
134
+ "refinitiv_identifier_code",
135
+ "ticker",
136
+ "is_active",
137
+ "parent",
138
+ "is_primary",
139
+ "is_investable_universe",
140
+ "is_security",
141
+ "is_managed",
142
+ )
143
+
144
+ fields = (
145
+ "id",
146
+ "name",
147
+ "name_repr",
148
+ "description",
149
+ "instrument_type",
150
+ "_instrument_type",
151
+ "inception_date",
152
+ "delisted_date",
153
+ "country",
154
+ "_country",
155
+ "currency",
156
+ "_currency",
157
+ "currency_symbol",
158
+ "isin",
159
+ "refinitiv_identifier_code",
160
+ "ticker",
161
+ "_classifications",
162
+ "classifications",
163
+ "_tags",
164
+ "tags",
165
+ "is_active",
166
+ "is_cash",
167
+ "_parent",
168
+ "parent",
169
+ "_additional_resources",
170
+ "_buttons",
171
+ "_group_key",
172
+ "exchange",
173
+ "_exchange",
174
+ "is_primary",
175
+ "is_investable_universe",
176
+ "is_security",
177
+ "is_managed",
178
+ )
179
+
180
+
181
+ class InstrumentModelSerializer(InstrumentAdditionalResourcesMixin, InstrumentModelListSerializer):
182
+ _related_instruments = SecurityRepresentationSerializer(source="related_instruments", many=True)
183
+
184
+ @serializers.register_resource()
185
+ def load_resources(self, instance, request, user, **kwargs):
186
+ res = {
187
+ "prices": reverse("wbfdm:prices-list", args=[instance.id], request=request),
188
+ "financial-statistics": reverse(
189
+ "wbfdm:instrument-financialstatistics-list", args=[instance.id], request=request
190
+ ),
191
+ }
192
+ if not instance.is_managed:
193
+ res.update(
194
+ {
195
+ "swe-income-statement": reverse(
196
+ "wbfdm:statementwithestimates-list", args=[instance.id, "income"], request=request
197
+ ),
198
+ "swe-balance-sheet": reverse(
199
+ "wbfdm:statementwithestimates-list", args=[instance.id, "balancesheet"], request=request
200
+ ),
201
+ "swe-cashflow-statement": reverse(
202
+ "wbfdm:statementwithestimates-list", args=[instance.id, "cashflow"], request=request
203
+ ),
204
+ "swe-ratios": reverse(
205
+ "wbfdm:statementwithestimates-list", args=[instance.id, "ratios"], request=request
206
+ ),
207
+ "swe-margins": reverse(
208
+ "wbfdm:statementwithestimates-list", args=[instance.id, "margins"], request=request
209
+ ),
210
+ "swe-summary": reverse(
211
+ "wbfdm:statementwithestimates-list", args=[instance.id, "summary"], request=request
212
+ ),
213
+ "swe-cashflow-ratios": reverse(
214
+ "wbfdm:statementwithestimates-list", args=[instance.id, "cashflow-ratios"], request=request
215
+ ),
216
+ "swe-asset-turnover-ratios": reverse(
217
+ "wbfdm:statementwithestimates-list",
218
+ args=[instance.id, "asset-turnover-ratios"],
219
+ request=request,
220
+ ),
221
+ "swe-credit": reverse(
222
+ "wbfdm:statementwithestimates-list", args=[instance.id, "credit"], request=request
223
+ ),
224
+ "swe-long-term-solvency": reverse(
225
+ "wbfdm:statementwithestimates-list", args=[instance.id, "long-term-solvency"], request=request
226
+ ),
227
+ "swe-short-term-liquidity": reverse(
228
+ "wbfdm:statementwithestimates-list",
229
+ args=[instance.id, "short-term-liquidity"],
230
+ request=request,
231
+ ),
232
+ "valuation_ratios-new": reverse(
233
+ "wbfdm:valuation_ratios-list", args=[instance.id], request=request
234
+ ),
235
+ "income-statement": reverse(
236
+ "wbfdm:statement-list", args=[instance.id, "income-statement"], request=request
237
+ ),
238
+ "balance-sheet": reverse(
239
+ "wbfdm:statement-list", args=[instance.id, "balance-sheet"], request=request
240
+ ),
241
+ "cash-flow-statement": reverse(
242
+ "wbfdm:statement-list", args=[instance.id, "cash-flow-statement"], request=request
243
+ ),
244
+ "officers": reverse(viewname="wbfdm:officers-list", args=[instance.id], request=request),
245
+ "controversies": reverse(viewname="wbfdm:controversies-list", args=[instance.id], request=request),
246
+ "pai": reverse(viewname="wbfdm:pai-list", args=[instance.id], request=request),
247
+ }
248
+ )
249
+ return res
250
+
251
+ @serializers.register_only_instance_resource()
252
+ def register_children(self, instance, request, user, **kwargs):
253
+ return {"children": reverse("wbfdm:instrument-children-list", args=[instance.id], request=request)}
254
+
255
+ @serializers.register_resource()
256
+ def register_market_data(self, instance, request, user, **kwargs):
257
+ return {
258
+ "market_data": reverse("wbfdm:market_data-list", args=[instance.id], request=request),
259
+ "cumulativereturn": f'{reverse("wbfdm:market_data-list", args=[instance.id], request=request)}?chart_type=ret',
260
+ "drawdown": f'{reverse("wbfdm:market_data-list", args=[instance.id], request=request)}?chart_type=drawdown',
261
+ "performance_summary": reverse("wbfdm:performance_summary-list", args=[instance.id], request=request),
262
+ "monthly_performances": reverse("wbfdm:monthly_performances-list", args=[instance.id], request=request),
263
+ }
264
+
265
+ class Meta(InstrumentModelListSerializer.Meta):
266
+ fields = InstrumentModelListSerializer.Meta.fields + (
267
+ "refinitiv_mnemonic_code",
268
+ "identifier",
269
+ "base_color",
270
+ "old_isins",
271
+ "is_cash",
272
+ "related_instruments",
273
+ "_related_instruments",
274
+ )
@@ -0,0 +1,104 @@
1
+ from rest_framework.reverse import reverse
2
+ from wbcore import serializers as wb_serializers
3
+
4
+
5
+ class InstrumentAdditionalResourcesMixin:
6
+ @wb_serializers.register_only_instance_resource()
7
+ def instrument_resources(self, instance, request, user, **kwargs):
8
+ additional_resources = dict()
9
+
10
+ if instance.prices.exists():
11
+ additional_resources["instrumentpricestatisticchart"] = reverse(
12
+ "wbfdm:instrument-pricestatisticchart-list",
13
+ args=[instance.id],
14
+ request=request,
15
+ )
16
+ additional_resources["instrumentprices"] = reverse(
17
+ "wbfdm:instrument-price-list",
18
+ args=[instance.id],
19
+ request=request,
20
+ )
21
+
22
+ additional_resources["distributionreturnschart"] = reverse(
23
+ "wbfdm:instrument-distributionreturnschart-list",
24
+ args=[instance.id],
25
+ request=request,
26
+ )
27
+ additional_resources["bestandworstreturns"] = reverse(
28
+ "wbfdm:instrument-bestandworstreturns-list",
29
+ args=[instance.id],
30
+ request=request,
31
+ )
32
+ additional_resources[
33
+ "price_and_volume"
34
+ ] = f'{reverse("wbfdm:market_data-list", args=[instance.id], request=request)}?chart_type=close&indicators=sma_50,sma_100&volume=true'
35
+
36
+ additional_resources["classifications_list"] = reverse(
37
+ "wbfdm:instrument-classification-list",
38
+ args=[instance.get_root().id],
39
+ request=request,
40
+ )
41
+ additional_resources["instrument_lists"] = reverse(
42
+ "wbfdm:instrument-instrumentlistthrough-list", args=[instance.id], request=request
43
+ )
44
+
45
+ return additional_resources
46
+
47
+ @wb_serializers.register_only_instance_resource()
48
+ def related_instruments(self, instance, request, user, **kwargs):
49
+ return {
50
+ "related_instruments": reverse(
51
+ "wbfdm:instrument-relatedinstrument-list", args=[instance.id], request=request
52
+ )
53
+ }
54
+
55
+ # @wb_serializers.register_only_instance_resource()
56
+ # def deprecated_financial_resources(self, instance, request, user, **kwargs):
57
+ # additional_resources = dict()
58
+ # additional_resources["summary_table"] = reverse(
59
+ # "wbfdm:instrument-summarytablechart-list",
60
+ # args=[instance.id],
61
+ # request=request,
62
+ # )
63
+ # additional_resources["financials_graph"] = reverse(
64
+ # "wbfdm:instrument-financialsgraphchart-list",
65
+ # args=[instance.id],
66
+ # request=request,
67
+ # )
68
+ # additional_resources["profitability_ratios"] = reverse(
69
+ # "wbfdm:instrument-profitabilityratioschart-list",
70
+ # args=[instance.id],
71
+ # request=request,
72
+ # )
73
+ # additional_resources["cash_flow_analysis_table"] = reverse(
74
+ # "wbfdm:instrument-cashflowanalysistablechart-list",
75
+ # args=[instance.id],
76
+ # request=request,
77
+ # )
78
+ # additional_resources["cash_flow_analysis_chart"] = reverse(
79
+ # "wbfdm:instrument-cashflowanalysisbarchart-list",
80
+ # args=[instance.id],
81
+ # request=request,
82
+ # )
83
+ # additional_resources["net_debt_and_ebitda_chart"] = reverse(
84
+ # "wbfdm:instrument-netdebtandebitdachart-list",
85
+ # args=[instance.id],
86
+ # request=request,
87
+ # )
88
+ # earnings_base_url = reverse(
89
+ # "wbfdm:instrument-earningschart-list",
90
+ # args=[instance.id],
91
+ # request=request,
92
+ # )
93
+ # additional_resources["earnings_chart"] = earnings_base_url
94
+ # additional_resources["earnings_chart_ttm"] = f"{earnings_base_url}?period=TTM"
95
+ # additional_resources["earnings_chart_ntm"] = f"{earnings_base_url}?period=FTM"
96
+ # valuation_ratios_base_url = reverse(
97
+ # "wbfdm:instrument-valuationratios-list",
98
+ # args=[instance.id],
99
+ # request=request,
100
+ # )
101
+ # additional_resources["valuation_ratios-old"] = valuation_ratios_base_url
102
+ # additional_resources["valuation_ratios_ranges"] = f"{valuation_ratios_base_url}?ranges=true"
103
+ # additional_resources["valuation_ratios_related"] = f"{valuation_ratios_base_url}?vs_related=true"
104
+ # return additional_resources
@@ -0,0 +1,20 @@
1
+ from wbcore import serializers
2
+
3
+
4
+ class OfficerSerializer(serializers.Serializer):
5
+ id = serializers.PrimaryKeyCharField()
6
+ position = serializers.CharField()
7
+ name = serializers.CharField()
8
+ age = serializers.IntegerField()
9
+ sex = serializers.CharField()
10
+ start = serializers.DateField()
11
+
12
+ class Meta:
13
+ fields = (
14
+ "id",
15
+ "position",
16
+ "name",
17
+ "age",
18
+ "sex",
19
+ "start",
20
+ )
wbfdm/signals.py ADDED
@@ -0,0 +1,7 @@
1
+ from django.db.models.signals import ModelSignal
2
+
3
+ # this signal is triggered by the investable universe manager in order to gather what instrument are considered within the investable universe.
4
+ add_instrument_to_investable_universe = ModelSignal(use_caching=False)
5
+
6
+ # this signal is triggered whenever prices are stored in the system and action needs to be considered
7
+ instrument_price_imported = ModelSignal(use_caching=False)
wbfdm/sync/__init__.py ADDED
File without changes
wbfdm/sync/abstract.py ADDED
@@ -0,0 +1,31 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Generic, TypeVar
3
+
4
+ T = TypeVar("T")
5
+
6
+
7
+ class Sync(Generic[T], ABC):
8
+ @abstractmethod
9
+ def update(self):
10
+ """Updates all items"""
11
+ ...
12
+
13
+ @abstractmethod
14
+ def update_or_create_item(self, external_id: int) -> T:
15
+ """Updates or creates a single item from an external id and returns it"""
16
+ ...
17
+
18
+ @abstractmethod
19
+ def update_item(self, item: T) -> T:
20
+ """Updates a single item and returns it"""
21
+ ...
22
+
23
+ @abstractmethod
24
+ def get_item(self, external_id: int) -> dict:
25
+ """Retrieves a dictionairy representation of the item"""
26
+ ...
27
+
28
+ @abstractmethod
29
+ def trigger_partial_update(self):
30
+ """Figures out if an update is necessary and then tries to update the entire database in the most efficiant way"""
31
+ ...
wbfdm/sync/runner.py ADDED
@@ -0,0 +1,22 @@
1
+ from django.conf import settings
2
+ from django.utils.module_loading import import_string
3
+
4
+
5
+ def initialize_instruments():
6
+ for sync in map(import_string, getattr(settings, "INSTRUMENT_SYNC", [])):
7
+ sync().update()
8
+
9
+
10
+ def initialize_exchanges():
11
+ for sync in map(import_string, getattr(settings, "EXCHANGE_SYNC", [])):
12
+ sync().update()
13
+
14
+
15
+ def synchronize_instruments():
16
+ for sync in map(import_string, getattr(settings, "INSTRUMENT_SYNC", [])):
17
+ sync().trigger_partial_update()
18
+
19
+
20
+ def synchronize_exchanges():
21
+ for sync in map(import_string, getattr(settings, "EXCHANGE_SYNC", [])):
22
+ sync().trigger_partial_update()
wbfdm/tasks.py ADDED
@@ -0,0 +1,69 @@
1
+ from datetime import date
2
+
3
+ from celery import shared_task
4
+ from django.db import transaction
5
+ from django.db.models import Q
6
+ from pandas.tseries.offsets import BDay
7
+ from tqdm import tqdm
8
+ from wbfdm.models import Instrument
9
+ from wbfdm.sync.runner import ( # noqa: F401
10
+ initialize_exchanges,
11
+ initialize_instruments,
12
+ synchronize_exchanges,
13
+ synchronize_instruments,
14
+ )
15
+
16
+
17
+ @shared_task(queue="portfolio")
18
+ def update_of_investable_universe_data(start: date | None = None, end: date | None = None, clear: bool = False):
19
+ """
20
+ Update the investable universe data on a daily basis.
21
+
22
+ Parameters:
23
+ - start (date | None): The start date for updating data. If None, defaults to three business days before 'end'.
24
+ - end (date | None): The end date for updating data. If None, defaults to the current date.
25
+
26
+ Notes:
27
+ - The function resets the investable universe by marking all instruments as not in the investable universe.
28
+ - It then updates all instruments marked as part of the investable universe.
29
+ - If 'end' is not provided, it defaults to the current date.
30
+ - If 'start' is not provided, it defaults to three business days before 'end'.
31
+
32
+ Returns:
33
+ None
34
+ """
35
+ if not end:
36
+ end = (
37
+ date.today() - BDay(1)
38
+ ).date() # we don't import today price in case the dataloader returns duplicates (e.g. DSWS)
39
+ if not start:
40
+ start = (end - BDay(3)).date() # override three last day by default
41
+
42
+ Instrument.investable_universe.update(
43
+ is_investable_universe=True
44
+ ) # ensure all the investable universe is marked as such
45
+
46
+ instruments = Instrument.active_objects.filter(is_investable_universe=True, delisted_date__isnull=True).exclude(
47
+ Q(is_managed=True)
48
+ | Q(dl_parameters__market_data__path="wbfdm.contrib.internal.dataloaders.market_data.MarketDataDataloader")
49
+ ) # we exclude product and index managed to avoid circular import
50
+ for instrument in tqdm(instruments, total=instruments.count()):
51
+ instrument.import_prices(start=start, end=end, clear=clear)
52
+
53
+
54
+ @shared_task(queue="portfolio")
55
+ def synchronize_instruments_as_task():
56
+ synchronize_instruments()
57
+
58
+
59
+ @shared_task(queue="portfolio")
60
+ def synchronize_exchanges_as_task():
61
+ synchronize_exchanges()
62
+
63
+
64
+ @shared_task(queue="portfolio")
65
+ def full_synchronization_as_task():
66
+ initialize_exchanges()
67
+ initialize_instruments()
68
+ with transaction.atomic():
69
+ Instrument.objects.rebuild() # rebuild MPTT tree
File without changes
File without changes
File without changes