wbfdm 1.43.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 (351) 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 +277 -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/backends/dto.py +36 -0
  29. wbfdm/contrib/__init__.py +0 -0
  30. wbfdm/contrib/dsws/__init__.py +0 -0
  31. wbfdm/contrib/dsws/client.py +285 -0
  32. wbfdm/contrib/dsws/dataloaders/market_data.py +130 -0
  33. wbfdm/contrib/internal/__init__.py +0 -0
  34. wbfdm/contrib/internal/dataloaders/__init__.py +0 -0
  35. wbfdm/contrib/internal/dataloaders/market_data.py +87 -0
  36. wbfdm/contrib/metric/__init__.py +0 -0
  37. wbfdm/contrib/metric/admin/__init__.py +2 -0
  38. wbfdm/contrib/metric/admin/instruments.py +12 -0
  39. wbfdm/contrib/metric/admin/metrics.py +43 -0
  40. wbfdm/contrib/metric/apps.py +10 -0
  41. wbfdm/contrib/metric/backends/__init__.py +2 -0
  42. wbfdm/contrib/metric/backends/base.py +159 -0
  43. wbfdm/contrib/metric/backends/performances.py +265 -0
  44. wbfdm/contrib/metric/backends/statistics.py +182 -0
  45. wbfdm/contrib/metric/decorators.py +14 -0
  46. wbfdm/contrib/metric/dispatch.py +23 -0
  47. wbfdm/contrib/metric/dto.py +88 -0
  48. wbfdm/contrib/metric/exceptions.py +6 -0
  49. wbfdm/contrib/metric/factories.py +33 -0
  50. wbfdm/contrib/metric/filters.py +28 -0
  51. wbfdm/contrib/metric/migrations/0001_initial.py +88 -0
  52. wbfdm/contrib/metric/migrations/0002_remove_instrumentmetric_unique_instrument_metric_and_more.py +26 -0
  53. wbfdm/contrib/metric/migrations/__init__.py +0 -0
  54. wbfdm/contrib/metric/models.py +180 -0
  55. wbfdm/contrib/metric/orchestrators.py +94 -0
  56. wbfdm/contrib/metric/registry.py +80 -0
  57. wbfdm/contrib/metric/serializers.py +44 -0
  58. wbfdm/contrib/metric/tasks.py +27 -0
  59. wbfdm/contrib/metric/tests/__init__.py +0 -0
  60. wbfdm/contrib/metric/tests/backends/__init__.py +0 -0
  61. wbfdm/contrib/metric/tests/backends/test_performances.py +152 -0
  62. wbfdm/contrib/metric/tests/backends/test_statistics.py +48 -0
  63. wbfdm/contrib/metric/tests/conftest.py +92 -0
  64. wbfdm/contrib/metric/tests/test_dto.py +73 -0
  65. wbfdm/contrib/metric/tests/test_models.py +72 -0
  66. wbfdm/contrib/metric/tests/test_tasks.py +24 -0
  67. wbfdm/contrib/metric/tests/test_viewsets.py +79 -0
  68. wbfdm/contrib/metric/urls.py +19 -0
  69. wbfdm/contrib/metric/viewsets/__init__.py +1 -0
  70. wbfdm/contrib/metric/viewsets/configs/__init__.py +1 -0
  71. wbfdm/contrib/metric/viewsets/configs/display.py +92 -0
  72. wbfdm/contrib/metric/viewsets/configs/menus.py +11 -0
  73. wbfdm/contrib/metric/viewsets/configs/utils.py +137 -0
  74. wbfdm/contrib/metric/viewsets/mixins.py +248 -0
  75. wbfdm/contrib/metric/viewsets/viewsets.py +40 -0
  76. wbfdm/contrib/msci/__init__.py +0 -0
  77. wbfdm/contrib/msci/client.py +92 -0
  78. wbfdm/contrib/msci/dataloaders/__init__.py +0 -0
  79. wbfdm/contrib/msci/dataloaders/esg.py +87 -0
  80. wbfdm/contrib/msci/dataloaders/esg_controversies.py +81 -0
  81. wbfdm/contrib/msci/sync.py +58 -0
  82. wbfdm/contrib/msci/tests/__init__.py +0 -0
  83. wbfdm/contrib/msci/tests/conftest.py +1 -0
  84. wbfdm/contrib/msci/tests/test_client.py +70 -0
  85. wbfdm/contrib/qa/__init__.py +0 -0
  86. wbfdm/contrib/qa/apps.py +22 -0
  87. wbfdm/contrib/qa/database_routers.py +25 -0
  88. wbfdm/contrib/qa/dataloaders/__init__.py +0 -0
  89. wbfdm/contrib/qa/dataloaders/adjustments.py +56 -0
  90. wbfdm/contrib/qa/dataloaders/corporate_actions.py +59 -0
  91. wbfdm/contrib/qa/dataloaders/financials.py +83 -0
  92. wbfdm/contrib/qa/dataloaders/market_data.py +117 -0
  93. wbfdm/contrib/qa/dataloaders/officers.py +59 -0
  94. wbfdm/contrib/qa/dataloaders/reporting_dates.py +67 -0
  95. wbfdm/contrib/qa/dataloaders/statements.py +267 -0
  96. wbfdm/contrib/qa/jinja2/qa/sql/companies.sql +100 -0
  97. wbfdm/contrib/qa/jinja2/qa/sql/ibes/base_estimates.sql +33 -0
  98. wbfdm/contrib/qa/jinja2/qa/sql/ibes/calendarized.sql +37 -0
  99. wbfdm/contrib/qa/jinja2/qa/sql/ibes/complete.sql +9 -0
  100. wbfdm/contrib/qa/jinja2/qa/sql/ibes/estimates.sql +3 -0
  101. wbfdm/contrib/qa/jinja2/qa/sql/ibes/financials.sql +79 -0
  102. wbfdm/contrib/qa/jinja2/qa/sql/instruments.sql +100 -0
  103. wbfdm/contrib/qa/jinja2/qa/sql/quotes.sql +98 -0
  104. wbfdm/contrib/qa/sync/exchanges.py +70 -0
  105. wbfdm/contrib/qa/sync/instruments.py +94 -0
  106. wbfdm/contrib/qa/sync/utils.py +241 -0
  107. wbfdm/contrib/qa/tasks.py +0 -0
  108. wbfdm/dataloaders/__init__.py +0 -0
  109. wbfdm/dataloaders/cache.py +129 -0
  110. wbfdm/dataloaders/protocols.py +112 -0
  111. wbfdm/dataloaders/proxies.py +201 -0
  112. wbfdm/dataloaders/types.py +209 -0
  113. wbfdm/dynamic_preferences_registry.py +45 -0
  114. wbfdm/enums.py +657 -0
  115. wbfdm/factories/__init__.py +13 -0
  116. wbfdm/factories/classifications.py +56 -0
  117. wbfdm/factories/controversies.py +27 -0
  118. wbfdm/factories/exchanges.py +21 -0
  119. wbfdm/factories/instrument_list.py +22 -0
  120. wbfdm/factories/instrument_prices.py +79 -0
  121. wbfdm/factories/instruments.py +63 -0
  122. wbfdm/factories/instruments_relationships.py +31 -0
  123. wbfdm/factories/options.py +66 -0
  124. wbfdm/figures/__init__.py +1 -0
  125. wbfdm/figures/financials/__init__.py +1 -0
  126. wbfdm/figures/financials/financial_analysis_charts.py +469 -0
  127. wbfdm/figures/financials/financials_charts.py +711 -0
  128. wbfdm/filters/__init__.py +31 -0
  129. wbfdm/filters/classifications.py +100 -0
  130. wbfdm/filters/exchanges.py +22 -0
  131. wbfdm/filters/financials.py +95 -0
  132. wbfdm/filters/financials_analysis.py +119 -0
  133. wbfdm/filters/instrument_prices.py +112 -0
  134. wbfdm/filters/instruments.py +198 -0
  135. wbfdm/filters/utils.py +44 -0
  136. wbfdm/import_export/__init__.py +0 -0
  137. wbfdm/import_export/backends/__init__.py +0 -0
  138. wbfdm/import_export/backends/cbinsights/__init__.py +2 -0
  139. wbfdm/import_export/backends/cbinsights/deals.py +44 -0
  140. wbfdm/import_export/backends/cbinsights/equities.py +41 -0
  141. wbfdm/import_export/backends/cbinsights/mixin.py +15 -0
  142. wbfdm/import_export/backends/cbinsights/utils/__init__.py +0 -0
  143. wbfdm/import_export/backends/cbinsights/utils/classifications.py +4150 -0
  144. wbfdm/import_export/backends/cbinsights/utils/client.py +217 -0
  145. wbfdm/import_export/backends/refinitiv/__init__.py +5 -0
  146. wbfdm/import_export/backends/refinitiv/daily_fundamental.py +36 -0
  147. wbfdm/import_export/backends/refinitiv/fiscal_period.py +63 -0
  148. wbfdm/import_export/backends/refinitiv/forecast.py +178 -0
  149. wbfdm/import_export/backends/refinitiv/fundamental.py +103 -0
  150. wbfdm/import_export/backends/refinitiv/geographic_segment.py +32 -0
  151. wbfdm/import_export/backends/refinitiv/instrument.py +55 -0
  152. wbfdm/import_export/backends/refinitiv/instrument_price.py +77 -0
  153. wbfdm/import_export/backends/refinitiv/mixin.py +29 -0
  154. wbfdm/import_export/backends/refinitiv/utils/__init__.py +1 -0
  155. wbfdm/import_export/backends/refinitiv/utils/controller.py +182 -0
  156. wbfdm/import_export/handlers/__init__.py +0 -0
  157. wbfdm/import_export/handlers/instrument.py +253 -0
  158. wbfdm/import_export/handlers/instrument_list.py +101 -0
  159. wbfdm/import_export/handlers/instrument_price.py +71 -0
  160. wbfdm/import_export/handlers/option.py +54 -0
  161. wbfdm/import_export/handlers/private_equities.py +49 -0
  162. wbfdm/import_export/parsers/__init__.py +0 -0
  163. wbfdm/import_export/parsers/cbinsights/__init__.py +0 -0
  164. wbfdm/import_export/parsers/cbinsights/deals.py +39 -0
  165. wbfdm/import_export/parsers/cbinsights/equities.py +56 -0
  166. wbfdm/import_export/parsers/cbinsights/fundamentals.py +45 -0
  167. wbfdm/import_export/parsers/refinitiv/__init__.py +0 -0
  168. wbfdm/import_export/parsers/refinitiv/daily_fundamental.py +7 -0
  169. wbfdm/import_export/parsers/refinitiv/forecast.py +7 -0
  170. wbfdm/import_export/parsers/refinitiv/fundamental.py +9 -0
  171. wbfdm/import_export/parsers/refinitiv/geographic_segment.py +7 -0
  172. wbfdm/import_export/parsers/refinitiv/instrument.py +75 -0
  173. wbfdm/import_export/parsers/refinitiv/instrument_price.py +26 -0
  174. wbfdm/import_export/parsers/refinitiv/utils.py +96 -0
  175. wbfdm/import_export/resources/__init__.py +0 -0
  176. wbfdm/import_export/resources/classification.py +23 -0
  177. wbfdm/import_export/resources/instrument_prices.py +33 -0
  178. wbfdm/import_export/resources/instruments.py +176 -0
  179. wbfdm/jinja2.py +7 -0
  180. wbfdm/management/__init__.py +30 -0
  181. wbfdm/menu.py +11 -0
  182. wbfdm/migrations/0001_initial.py +71 -0
  183. wbfdm/migrations/0002_rename_statements_instrumentlookup_financials_and_more.py +144 -0
  184. wbfdm/migrations/0003_instrument_estimate_backend_and_more.py +34 -0
  185. wbfdm/migrations/0004_rename_financials_instrumentlookup_statements_and_more.py +86 -0
  186. wbfdm/migrations/0005_instrument_corporate_action_backend.py +29 -0
  187. wbfdm/migrations/0006_instrument_officer_backend.py +29 -0
  188. wbfdm/migrations/0007_instrument_country_instrument_currency_and_more.py +117 -0
  189. wbfdm/migrations/0008_controversy.py +75 -0
  190. wbfdm/migrations/0009_alter_controversy_flag_alter_controversy_initiated_and_more.py +85 -0
  191. wbfdm/migrations/0010_classification_classificationgroup_deal_exchange_and_more.py +1299 -0
  192. wbfdm/migrations/0011_delete_instrumentlookup_instrument_corporate_actions_and_more.py +169 -0
  193. wbfdm/migrations/0012_instrumentprice_created_instrumentprice_modified.py +564 -0
  194. wbfdm/migrations/0013_instrument_is_investable_universe_and_more.py +199 -0
  195. wbfdm/migrations/0014_alter_controversy_instrument.py +22 -0
  196. wbfdm/migrations/0015_instrument_instrument_investible_index.py +16 -0
  197. wbfdm/migrations/0016_instrumenttype_name_repr.py +18 -0
  198. wbfdm/migrations/0017_instrument_instrument_security_index.py +16 -0
  199. wbfdm/migrations/0018_instrument_instrument_level_index.py +20 -0
  200. wbfdm/migrations/0019_alter_controversy_source.py +17 -0
  201. wbfdm/migrations/0020_optionaggregate_option_and_more.py +249 -0
  202. wbfdm/migrations/0021_delete_instrumentdailystatistics.py +15 -0
  203. wbfdm/migrations/0022_instrument_cusip_option_open_interest_20d_and_more.py +91 -0
  204. wbfdm/migrations/0023_instrument_unique_ric_instrument_unique_rmc_and_more.py +53 -0
  205. wbfdm/migrations/0024_option_open_interest_10d_option_volume_10d_and_more.py +36 -0
  206. wbfdm/migrations/0025_instrument_is_primary_and_more.py +29 -0
  207. wbfdm/migrations/0026_instrument_is_cash_equivalent.py +30 -0
  208. wbfdm/migrations/0027_remove_instrument_unique_ric_and_more.py +100 -0
  209. wbfdm/migrations/0028_instrumentprice_annualized_daily_volatility.py +17 -0
  210. wbfdm/migrations/__init__.py +0 -0
  211. wbfdm/models/__init__.py +4 -0
  212. wbfdm/models/esg/__init__.py +1 -0
  213. wbfdm/models/esg/controversies.py +81 -0
  214. wbfdm/models/exchanges/__init__.py +1 -0
  215. wbfdm/models/exchanges/exchanges.py +223 -0
  216. wbfdm/models/fields.py +117 -0
  217. wbfdm/models/fk_fields.py +403 -0
  218. wbfdm/models/indicators.py +0 -0
  219. wbfdm/models/instruments/__init__.py +19 -0
  220. wbfdm/models/instruments/classifications.py +265 -0
  221. wbfdm/models/instruments/instrument_lists.py +120 -0
  222. wbfdm/models/instruments/instrument_prices.py +544 -0
  223. wbfdm/models/instruments/instrument_relationships.py +251 -0
  224. wbfdm/models/instruments/instrument_requests.py +196 -0
  225. wbfdm/models/instruments/instruments.py +991 -0
  226. wbfdm/models/instruments/llm/__init__.py +1 -0
  227. wbfdm/models/instruments/llm/create_instrument_news_relationships.py +78 -0
  228. wbfdm/models/instruments/mixin/__init__.py +0 -0
  229. wbfdm/models/instruments/mixin/financials_computed.py +804 -0
  230. wbfdm/models/instruments/mixin/financials_serializer_fields.py +1407 -0
  231. wbfdm/models/instruments/mixin/instruments.py +297 -0
  232. wbfdm/models/instruments/options.py +225 -0
  233. wbfdm/models/instruments/private_equities.py +59 -0
  234. wbfdm/models/instruments/querysets.py +73 -0
  235. wbfdm/models/instruments/utils.py +41 -0
  236. wbfdm/preferences.py +21 -0
  237. wbfdm/serializers/__init__.py +4 -0
  238. wbfdm/serializers/esg.py +36 -0
  239. wbfdm/serializers/exchanges.py +39 -0
  240. wbfdm/serializers/instruments/__init__.py +37 -0
  241. wbfdm/serializers/instruments/classifications.py +139 -0
  242. wbfdm/serializers/instruments/instrument_lists.py +61 -0
  243. wbfdm/serializers/instruments/instrument_prices.py +73 -0
  244. wbfdm/serializers/instruments/instrument_relationships.py +170 -0
  245. wbfdm/serializers/instruments/instrument_requests.py +61 -0
  246. wbfdm/serializers/instruments/instruments.py +274 -0
  247. wbfdm/serializers/instruments/mixins.py +104 -0
  248. wbfdm/serializers/officers.py +20 -0
  249. wbfdm/signals.py +7 -0
  250. wbfdm/sync/__init__.py +0 -0
  251. wbfdm/sync/abstract.py +31 -0
  252. wbfdm/sync/runner.py +22 -0
  253. wbfdm/tasks.py +69 -0
  254. wbfdm/tests/__init__.py +0 -0
  255. wbfdm/tests/analysis/__init__.py +0 -0
  256. wbfdm/tests/analysis/financial_analysis/__init__.py +0 -0
  257. wbfdm/tests/analysis/financial_analysis/test_statement_with_estimates.py +392 -0
  258. wbfdm/tests/analysis/financial_analysis/test_utils.py +322 -0
  259. wbfdm/tests/analysis/test_esg.py +159 -0
  260. wbfdm/tests/conftest.py +92 -0
  261. wbfdm/tests/dataloaders/__init__.py +0 -0
  262. wbfdm/tests/dataloaders/test_cache.py +73 -0
  263. wbfdm/tests/models/__init__.py +0 -0
  264. wbfdm/tests/models/test_classifications.py +99 -0
  265. wbfdm/tests/models/test_exchanges.py +7 -0
  266. wbfdm/tests/models/test_instrument_list.py +117 -0
  267. wbfdm/tests/models/test_instrument_prices.py +306 -0
  268. wbfdm/tests/models/test_instruments.py +202 -0
  269. wbfdm/tests/models/test_merge.py +99 -0
  270. wbfdm/tests/models/test_options.py +69 -0
  271. wbfdm/tests/test_tasks.py +6 -0
  272. wbfdm/tests/tests.py +10 -0
  273. wbfdm/urls.py +222 -0
  274. wbfdm/utils.py +54 -0
  275. wbfdm/viewsets/__init__.py +10 -0
  276. wbfdm/viewsets/configs/__init__.py +5 -0
  277. wbfdm/viewsets/configs/buttons/__init__.py +8 -0
  278. wbfdm/viewsets/configs/buttons/classifications.py +23 -0
  279. wbfdm/viewsets/configs/buttons/exchanges.py +9 -0
  280. wbfdm/viewsets/configs/buttons/instrument_prices.py +49 -0
  281. wbfdm/viewsets/configs/buttons/instruments.py +283 -0
  282. wbfdm/viewsets/configs/display/__init__.py +22 -0
  283. wbfdm/viewsets/configs/display/classifications.py +138 -0
  284. wbfdm/viewsets/configs/display/esg.py +75 -0
  285. wbfdm/viewsets/configs/display/exchanges.py +42 -0
  286. wbfdm/viewsets/configs/display/instrument_lists.py +137 -0
  287. wbfdm/viewsets/configs/display/instrument_prices.py +199 -0
  288. wbfdm/viewsets/configs/display/instrument_requests.py +116 -0
  289. wbfdm/viewsets/configs/display/instruments.py +340 -0
  290. wbfdm/viewsets/configs/display/instruments_relationships.py +65 -0
  291. wbfdm/viewsets/configs/display/monthly_performances.py +72 -0
  292. wbfdm/viewsets/configs/display/officers.py +16 -0
  293. wbfdm/viewsets/configs/display/prices.py +21 -0
  294. wbfdm/viewsets/configs/display/statement_with_estimates.py +101 -0
  295. wbfdm/viewsets/configs/display/statements.py +48 -0
  296. wbfdm/viewsets/configs/endpoints/__init__.py +41 -0
  297. wbfdm/viewsets/configs/endpoints/classifications.py +87 -0
  298. wbfdm/viewsets/configs/endpoints/esg.py +20 -0
  299. wbfdm/viewsets/configs/endpoints/exchanges.py +6 -0
  300. wbfdm/viewsets/configs/endpoints/financials_analysis.py +65 -0
  301. wbfdm/viewsets/configs/endpoints/instrument_lists.py +38 -0
  302. wbfdm/viewsets/configs/endpoints/instrument_prices.py +51 -0
  303. wbfdm/viewsets/configs/endpoints/instrument_requests.py +20 -0
  304. wbfdm/viewsets/configs/endpoints/instruments.py +13 -0
  305. wbfdm/viewsets/configs/endpoints/instruments_relationships.py +31 -0
  306. wbfdm/viewsets/configs/endpoints/statements.py +6 -0
  307. wbfdm/viewsets/configs/menus/__init__.py +9 -0
  308. wbfdm/viewsets/configs/menus/classifications.py +19 -0
  309. wbfdm/viewsets/configs/menus/exchanges.py +10 -0
  310. wbfdm/viewsets/configs/menus/instrument_lists.py +10 -0
  311. wbfdm/viewsets/configs/menus/instruments.py +20 -0
  312. wbfdm/viewsets/configs/menus/instruments_relationships.py +33 -0
  313. wbfdm/viewsets/configs/titles/__init__.py +42 -0
  314. wbfdm/viewsets/configs/titles/classifications.py +79 -0
  315. wbfdm/viewsets/configs/titles/esg.py +11 -0
  316. wbfdm/viewsets/configs/titles/exchanges.py +12 -0
  317. wbfdm/viewsets/configs/titles/financial_ratio_analysis.py +6 -0
  318. wbfdm/viewsets/configs/titles/financials_analysis.py +50 -0
  319. wbfdm/viewsets/configs/titles/instrument_prices.py +50 -0
  320. wbfdm/viewsets/configs/titles/instrument_requests.py +16 -0
  321. wbfdm/viewsets/configs/titles/instruments.py +31 -0
  322. wbfdm/viewsets/configs/titles/instruments_relationships.py +21 -0
  323. wbfdm/viewsets/configs/titles/market_data.py +13 -0
  324. wbfdm/viewsets/configs/titles/prices.py +15 -0
  325. wbfdm/viewsets/configs/titles/statement_with_estimates.py +10 -0
  326. wbfdm/viewsets/esg.py +72 -0
  327. wbfdm/viewsets/exchanges.py +63 -0
  328. wbfdm/viewsets/financial_analysis/__init__.py +3 -0
  329. wbfdm/viewsets/financial_analysis/financial_metric_analysis.py +85 -0
  330. wbfdm/viewsets/financial_analysis/financial_ratio_analysis.py +85 -0
  331. wbfdm/viewsets/financial_analysis/statement_with_estimates.py +145 -0
  332. wbfdm/viewsets/instruments/__init__.py +80 -0
  333. wbfdm/viewsets/instruments/classifications.py +279 -0
  334. wbfdm/viewsets/instruments/financials_analysis.py +614 -0
  335. wbfdm/viewsets/instruments/instrument_lists.py +77 -0
  336. wbfdm/viewsets/instruments/instrument_prices.py +542 -0
  337. wbfdm/viewsets/instruments/instrument_requests.py +51 -0
  338. wbfdm/viewsets/instruments/instruments.py +106 -0
  339. wbfdm/viewsets/instruments/instruments_relationships.py +235 -0
  340. wbfdm/viewsets/instruments/utils.py +27 -0
  341. wbfdm/viewsets/market_data.py +172 -0
  342. wbfdm/viewsets/mixins.py +9 -0
  343. wbfdm/viewsets/officers.py +27 -0
  344. wbfdm/viewsets/prices.py +62 -0
  345. wbfdm/viewsets/statements/__init__.py +1 -0
  346. wbfdm/viewsets/statements/statements.py +100 -0
  347. wbfdm/viewsets/technical_analysis/__init__.py +1 -0
  348. wbfdm/viewsets/technical_analysis/monthly_performances.py +93 -0
  349. wbfdm-1.43.1.dist-info/METADATA +15 -0
  350. wbfdm-1.43.1.dist-info/RECORD +351 -0
  351. wbfdm-1.43.1.dist-info/WHEEL +5 -0
@@ -0,0 +1,80 @@
1
+ from django.conf import settings
2
+ from wbcore.utils.importlib import import_from_dotted_path
3
+ from .instruments import (
4
+ InstrumentModelViewSet,
5
+ InstrumentRepresentationViewSet,
6
+ InstrumentTypeRepresentationViewSet,
7
+ ChildrenInstrumentModelViewSet,
8
+ )
9
+ from .instrument_prices import (
10
+ InstrumentPriceModelViewSet,
11
+ InstrumentPriceInstrumentModelViewSet,
12
+ InstrumentPriceInstrumentStatisticsChartView,
13
+ FinancialStatisticsInstrumentPandasView,
14
+ InstrumentPriceInstrumentDistributionReturnsChartView,
15
+ BestAndWorstReturnsInstrumentPandasView,
16
+ )
17
+
18
+ from .classifications import (
19
+ ClassificationClassificationGroupModelViewSet,
20
+ ClassificationGroupModelViewSet,
21
+ ClassificationGroupRepresentationViewSet,
22
+ ClassificationIcicleChartView,
23
+ ClassificationInstrumentThroughInstrumentModelViewSet,
24
+ ClassificationRepresentationViewSet,
25
+ ClassificationTreeChartView,
26
+ InstrumentClassificationThroughInstrumentModelViewSet,
27
+ InstrumentClassificationThroughModelViewSet,
28
+ )
29
+ from .financials_analysis import (
30
+ CashFlowAnalysisInstrumentBarChartViewSet,
31
+ CashFlowAnalysisInstrumentTableViewSet,
32
+ EarningsInstrumentChartViewSet,
33
+ FinancialsGraphInstrumentChartViewSet,
34
+ NetDebtAndEbitdaInstrumentChartViewSet,
35
+ ProfitabilityRatiosInstrumentChartViewSet,
36
+ SummaryTableInstrumentChartViewSet,
37
+ ValuationRatiosChartView,
38
+ )
39
+ from .instrument_lists import (
40
+ InstrumentListModelViewSet,
41
+ InstrumentListRepresentationModelViewSet,
42
+ InstrumentListThroughModelViewSet,
43
+ InstrumentListThroughModelInstrumentListViewSet,
44
+ InstrumentListThroughModelInstrumentViewSet,
45
+ )
46
+
47
+ from .instrument_requests import (
48
+ InstrumentRequestModelViewSet,
49
+ InstrumentRequestRepresentationViewSet,
50
+ )
51
+ from .instruments_relationships import (
52
+ InstrumentClassificationRelatedInstrumentModelViewSet,
53
+ InstrumentClassificationRelatedInstrumentRepresentationViewSet,
54
+ InstrumentFavoriteGroupModelViewSet,
55
+ InstrumentFavoriteGroupRepresentationViewSet,
56
+ RelatedInstrumentThroughInstrumentModelViewSet,
57
+ )
58
+
59
+
60
+ ClassificationModelViewSet = import_from_dotted_path(
61
+ getattr(
62
+ settings,
63
+ "DEFAULT_CLASSIFICATION_MODEL_VIEWSET",
64
+ "wbfdm.viewsets.instruments.classifications.ClassificationModelViewSet",
65
+ )
66
+ )
67
+ ChildClassificationParentClassificationModelViewSet = import_from_dotted_path(
68
+ getattr(
69
+ settings,
70
+ "DEFAULT_PARENT_CLASSIFICATION_MODEL_VIEWSET",
71
+ "wbfdm.viewsets.instruments.classifications.ChildClassificationParentClassificationModelViewSet",
72
+ )
73
+ )
74
+ ClassifiedInstrumentModelViewSet = import_from_dotted_path(
75
+ getattr(
76
+ settings,
77
+ "DEFAULT_CLASSIFICATION_INSTRUMENT_MODEL_VIEWSET",
78
+ "wbfdm.viewsets.instruments.instruments_relationships.ClassifiedInstrumentModelViewSet",
79
+ )
80
+ )
@@ -0,0 +1,279 @@
1
+ import pandas as pd
2
+ import plotly.express as px
3
+ import plotly.graph_objects as go
4
+ from django.db.models import Count, Value
5
+ from django.db.models.expressions import OuterRef, Subquery
6
+ from django.db.models.functions import Coalesce
7
+ from django.shortcuts import get_object_or_404
8
+ from django.utils.functional import cached_property
9
+ from reversion.views import RevisionMixin
10
+ from wbcore import viewsets
11
+ from wbcore.cache.decorators import cache_table
12
+ from wbcore.filters import DjangoFilterBackend
13
+ from wbcore.permissions.permissions import InternalUserPermissionMixin
14
+ from wbcore.utils.date import get_next_day_timedelta
15
+ from wbfdm.filters import (
16
+ ClassificationFilter,
17
+ ClassificationTreeChartFilter,
18
+ InstrumentClassificationThroughModelViewFilterSet,
19
+ )
20
+ from wbfdm.models import (
21
+ Classification,
22
+ ClassificationGroup,
23
+ InstrumentClassificationThroughModel,
24
+ )
25
+ from wbfdm.serializers import (
26
+ ClassificationGroupModelSerializer,
27
+ ClassificationGroupRepresentationSerializer,
28
+ ClassificationModelSerializer,
29
+ ClassificationRepresentationSerializer,
30
+ InstrumentClassificationThroughModelSerializer,
31
+ )
32
+ from wbfdm.viewsets.configs import (
33
+ ChildClassificationParentClassificationTitleConfig,
34
+ ClassificationButtonConfig,
35
+ ClassificationClassificationGroupEndpointConfig,
36
+ ClassificationClassificationGroupTitleConfig,
37
+ ClassificationDisplayConfig,
38
+ ClassificationEndpointConfig,
39
+ ClassificationGroupButtonConfig,
40
+ ClassificationGroupDisplayConfig,
41
+ ClassificationGroupTitleConfig,
42
+ ClassificationIcicleChartEndpointConfig,
43
+ ClassificationIcicleChartTitleConfig,
44
+ ClassificationInstrumentThroughInstrumentModelEndpointConfig,
45
+ ClassificationParentClassificationEndpointConfig,
46
+ ClassificationTitleConfig,
47
+ ClassificationTreeChartEndpointConfig,
48
+ ClassificationTreeChartTitleConfig,
49
+ InstrumentClassificationThroughDisplayConfig,
50
+ InstrumentClassificationThroughEndpointConfig,
51
+ InstrumentClassificationThroughInstrumentModelEndpointConfig,
52
+ InstrumentClassificationThroughTitleConfig,
53
+ )
54
+
55
+ from ..mixins import InstrumentMixin
56
+
57
+
58
+ class ClassificationRepresentationViewSet(InternalUserPermissionMixin, viewsets.RepresentationViewSet):
59
+ IDENTIFIER = "wbfdm:classification"
60
+ queryset = Classification.objects.all()
61
+ serializer_class = ClassificationRepresentationSerializer
62
+
63
+ filterset_class = ClassificationFilter
64
+ ordering_fields = ["code_aggregated"]
65
+ ordering = ["code_aggregated"]
66
+ search_fields = ["code_aggregated", "name"]
67
+
68
+
69
+ class ClassificationGroupRepresentationViewSet(InternalUserPermissionMixin, viewsets.RepresentationViewSet):
70
+ IDENTIFIER = "wbfdm:classificationgrouprepresentation"
71
+ queryset = ClassificationGroup.objects.all()
72
+ serializer_class = ClassificationGroupRepresentationSerializer
73
+
74
+ filterset_fields = {"is_primary": ["exact"], "max_depth": ["gte", "exact", "lte"]}
75
+ ordering_fields = ["name"]
76
+ ordering = ["name"]
77
+ search_fields = ["name"]
78
+
79
+
80
+ class ClassificationModelViewSet(InternalUserPermissionMixin, RevisionMixin, viewsets.ModelViewSet):
81
+ IDENTIFIER = "wbfdm:classification"
82
+
83
+ queryset = Classification.objects.select_related("parent", "group")
84
+ serializer_class = ClassificationModelSerializer
85
+ filterset_class = ClassificationFilter
86
+
87
+ ordering_fields = (
88
+ "name",
89
+ "code_aggregated",
90
+ "level_representation",
91
+ )
92
+ ordering = ("level_representation", "name")
93
+ search_fields = ("name", "group__name", "parent__name", "code_aggregated")
94
+
95
+ endpoint_config_class = ClassificationEndpointConfig
96
+ display_config_class = ClassificationDisplayConfig
97
+ title_config_class = ClassificationTitleConfig
98
+ button_config_class = ClassificationButtonConfig
99
+
100
+
101
+ class ClassificationClassificationGroupModelViewSet(ClassificationModelViewSet):
102
+ endpoint_config_class = ClassificationClassificationGroupEndpointConfig
103
+ title_config_class = ClassificationClassificationGroupTitleConfig
104
+
105
+ def get_queryset(self):
106
+ return super().get_queryset().filter(group=self.kwargs["group_id"], level=0)
107
+
108
+
109
+ class ChildClassificationParentClassificationModelViewSet(ClassificationModelViewSet):
110
+ endpoint_config_class = ClassificationParentClassificationEndpointConfig
111
+ title_config_class = ChildClassificationParentClassificationTitleConfig
112
+
113
+ def get_queryset(self):
114
+ parent = Classification.objects.get(id=self.kwargs["parent_id"])
115
+ return super().get_queryset().filter(parent=self.kwargs["parent_id"], level=parent.level + 1)
116
+
117
+
118
+ class ClassificationGroupModelViewSet(InternalUserPermissionMixin, RevisionMixin, viewsets.ModelViewSet):
119
+ IDENTIFIER = "wbfdm:classificationgroup"
120
+
121
+ queryset = ClassificationGroup.objects.all()
122
+ serializer_class = ClassificationGroupModelSerializer
123
+ filterset_fields = {"is_primary": ["exact"], "max_depth": ["gte", "exact", "lte"]}
124
+ ordering_fields = ("name",)
125
+ ordering = ("name",)
126
+ search_fields = ("name",)
127
+
128
+ display_config_class = ClassificationGroupDisplayConfig
129
+ title_config_class = ClassificationGroupTitleConfig
130
+ button_config_class = ClassificationGroupButtonConfig
131
+
132
+
133
+ class AbstractClassificationChartView(viewsets.ChartViewSet):
134
+ filter_backends = (DjangoFilterBackend,)
135
+ queryset = Classification.objects.all()
136
+ filterset_class = ClassificationTreeChartFilter
137
+
138
+ @cached_property
139
+ def aggregation_type(self) -> str:
140
+ return self.request.GET.get("aggregation_type", "classification_count")
141
+
142
+ @cached_property
143
+ def classification_group(self) -> ClassificationGroup:
144
+ return ClassificationGroup.objects.get(id=self.kwargs["group_id"])
145
+
146
+ @cached_property
147
+ def top_level(self) -> int:
148
+ top_level = 0
149
+ if top_classification_id := self.request.GET.get("top_classification", None):
150
+ top_level = Classification.objects.get(id=top_classification_id).level
151
+ return top_level
152
+
153
+ def get_df(self, queryset) -> tuple[pd.DataFrame, list[str]]:
154
+ _range = self.classification_group.max_depth + 1 - self.top_level
155
+ df = pd.DataFrame(columns=[self.aggregation_type])
156
+ level_representation = []
157
+ if queryset.exists():
158
+ df = pd.DataFrame(
159
+ queryset.values(*[f"{'parent__' * height}name" for height in range(_range)], self.aggregation_type)
160
+ ).fillna(0)
161
+
162
+ level_representation = self.classification_group.get_levels_representation()[:_range]
163
+ df.columns = [*level_representation, self.aggregation_type]
164
+ return df, level_representation
165
+
166
+ def get_queryset(self):
167
+ return (
168
+ super()
169
+ .get_queryset()
170
+ .filter(height=0, group=self.classification_group)
171
+ .annotate(
172
+ instrument_count=Coalesce(
173
+ Subquery(
174
+ InstrumentClassificationThroughModel.objects.filter(classification=OuterRef("pk"))
175
+ .values("classification")
176
+ .annotate(c=Count("classification"))
177
+ .values("c")[:1]
178
+ ),
179
+ 0,
180
+ ),
181
+ classification_count=Value(1),
182
+ )
183
+ )
184
+
185
+ def get_plotly(self, queryset):
186
+ return go.Figure()
187
+
188
+
189
+ @cache_table(
190
+ timeout=get_next_day_timedelta(),
191
+ key_prefix=lambda view: f"{view.classification_group.id}_{view.aggregation_type}_{view.top_level}",
192
+ periodic_caching=True,
193
+ periodic_caching_view_kwargs=lambda: [
194
+ {"group_id": group_id} for group_id in ClassificationGroup.objects.values_list("id", flat=True)
195
+ ],
196
+ periodic_caching_get_parameters=[
197
+ {"aggregation_type": "classification_count"},
198
+ {"aggregation_type": "instrument_count"},
199
+ ],
200
+ )
201
+ class ClassificationTreeChartView(AbstractClassificationChartView):
202
+ IDENTIFIER = "wbfdm:classificationgroup-tree"
203
+ title_config_class = ClassificationTreeChartTitleConfig
204
+ endpoint_config_class = ClassificationTreeChartEndpointConfig
205
+
206
+ def get_plotly(self, queryset):
207
+ df, level_representation = self.get_df(queryset)
208
+ fig = px.treemap(df, path=[*level_representation[::-1]], values=self.aggregation_type, branchvalues="total")
209
+ fig.update_traces(root_color="lightgrey", hovertemplate=f"{self.aggregation_type}: %{{value}}")
210
+ fig.update_layout(margin=dict(t=25, l=25, r=25, b=25))
211
+ return fig
212
+
213
+
214
+ @cache_table(
215
+ timeout=get_next_day_timedelta(),
216
+ key_prefix=lambda view: f"{view.classification_group.id}_{view.aggregation_type}_{view.top_level}",
217
+ periodic_caching=True,
218
+ periodic_caching_view_kwargs=lambda: [
219
+ {"group_id": group_id} for group_id in ClassificationGroup.objects.values_list("id", flat=True)
220
+ ],
221
+ periodic_caching_get_parameters=[
222
+ {"aggregation_type": "classification_count"},
223
+ {"aggregation_type": "instrument_count"},
224
+ ],
225
+ )
226
+ class ClassificationIcicleChartView(AbstractClassificationChartView):
227
+ IDENTIFIER = "wbfdm:classificationgroup-iciclechart"
228
+ title_config_class = ClassificationIcicleChartTitleConfig
229
+ endpoint_config_class = ClassificationIcicleChartEndpointConfig
230
+
231
+ def get_plotly(self, queryset):
232
+ df, level_representation = self.get_df(queryset)
233
+ fig = px.icicle(df, path=[*level_representation[::-1]], values=self.aggregation_type)
234
+ fig.update_traces(
235
+ root_color="lightgrey", tiling=dict(orientation="v"), hovertemplate=f"{self.aggregation_type}: %{{value}}"
236
+ )
237
+ fig.update_layout(margin=dict(t=25, l=25, r=25, b=25))
238
+ return fig
239
+
240
+
241
+ class InstrumentClassificationThroughModelViewSet(InternalUserPermissionMixin, viewsets.ModelViewSet):
242
+ serializer_class = InstrumentClassificationThroughModelSerializer
243
+ queryset = InstrumentClassificationThroughModel.objects.select_related(
244
+ "instrument",
245
+ "classification",
246
+ ).prefetch_related("related_instruments", "tags")
247
+ search_fields = ("classification__name", "classification__code_aggregated")
248
+ ordering_fields = ordering = ["classification__name"]
249
+
250
+ filterset_class = InstrumentClassificationThroughModelViewFilterSet
251
+ display_config_class = InstrumentClassificationThroughDisplayConfig
252
+ endpoint_config_class = InstrumentClassificationThroughEndpointConfig
253
+ title_config_class = InstrumentClassificationThroughTitleConfig
254
+
255
+
256
+ class InstrumentClassificationThroughInstrumentModelViewSet(
257
+ InstrumentMixin, InstrumentClassificationThroughModelViewSet
258
+ ):
259
+ endpoint_config_class = InstrumentClassificationThroughInstrumentModelEndpointConfig
260
+ search_fields = ["classification__computed_str"]
261
+ ordering_fields = ordering = ["classification__computed_str"]
262
+
263
+ def get_queryset(self):
264
+ return super().get_queryset().filter(instrument__in=self.instrument.get_family())
265
+
266
+
267
+ class ClassificationInstrumentThroughInstrumentModelViewSet(InstrumentClassificationThroughModelViewSet):
268
+ search_fields = ["instrument__computed_str"]
269
+ ordering_fields = ordering = ["instrument__computed_str"]
270
+
271
+ endpoint_config_class = ClassificationInstrumentThroughInstrumentModelEndpointConfig
272
+
273
+ def get_queryset(self):
274
+ classification = get_object_or_404(Classification, id=self.kwargs["classification_id"])
275
+ return (
276
+ super()
277
+ .get_queryset()
278
+ .filter(classification__in=classification.get_descendants(include_self=True).values("id"))
279
+ )