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,804 @@
1
+ from datetime import date
2
+
3
+ import pandas as pd
4
+
5
+
6
+ #
7
+ #
8
+ # class FundamentalComputedMixin:
9
+ # def _compute_revenue_growth(self) -> float:
10
+ # if (
11
+ # self.revenue is not None
12
+ # and (last_fundamental := self.last_fundamental)
13
+ # and (last_revenue := last_fundamental.revenue)
14
+ # ):
15
+ # return self.revenue / last_revenue - 1
16
+ #
17
+ # def _compute_gross_profit(self) -> float:
18
+ # if self.revenue is not None and self.cost_of_good_sold is not None:
19
+ # return self.revenue - self.cost_of_good_sold
20
+ #
21
+ # def _compute_gross_profit_margin(self) -> float:
22
+ # if (
23
+ # self.gross_profit is not None
24
+ # and self.revenue
25
+ # and self.deprecation_and_amortization_to_sales_ratio is not None
26
+ # ):
27
+ # return (self.gross_profit / self.revenue) + self.deprecation_and_amortization_to_sales_ratio
28
+ #
29
+ # def _compute_ebitda_margin(self) -> float:
30
+ # if self.ebitda is not None and self.revenue:
31
+ # return self.ebitda / self.revenue
32
+ #
33
+ # def _compute_ebit_margin(self) -> float:
34
+ # if self.ebit is not None and self.revenue:
35
+ # return self.ebit / self.revenue
36
+ #
37
+ # def _compute_net_profit_margin(self) -> float:
38
+ # if self.net_profit is not None and self.revenue:
39
+ # return self.net_profit / self.revenue
40
+ #
41
+ # def _compute_cost_of_good_sold(self) -> float:
42
+ # if self.cost_of_good_sold_without_depreciation is not None and self.deprecation_and_amortization is not None:
43
+ # return self.cost_of_good_sold_without_depreciation + self.deprecation_and_amortization
44
+ #
45
+ # def _compute_eps_growth(self) -> float:
46
+ # if self.eps is not None and (last_fundamental := self.last_fundamental) and (last_eps := last_fundamental.eps):
47
+ # return self.eps / last_eps - 1
48
+ #
49
+ # def _compute_sga_to_sales_ratio(self) -> float:
50
+ # if self.sga is not None and self.revenue:
51
+ # return self.sga / self.revenue
52
+ #
53
+ # def _compute_interest_expense_to_sales_ratio(self) -> float:
54
+ # if self.interest_expense is not None and self.revenue:
55
+ # return self.interest_expense / self.revenue
56
+ #
57
+ # def _compute_deprecation_and_amortization_to_sales_ratio(self) -> float:
58
+ # if self.deprecation_and_amortization is not None and self.revenue:
59
+ # return self.deprecation_and_amortization / self.revenue
60
+ #
61
+ # def _compute_free_cash(self) -> float:
62
+ # if self.cash_from_operation is not None and self.capital_expenditures is not None:
63
+ # return self.cash_from_operation - self.capital_expenditures
64
+ #
65
+ # def _compute_free_cash_flow(self):
66
+ # if (
67
+ # self.free_cash is not None
68
+ # and (price := self.last_price)
69
+ # and (outstanding_shares_consolidated := price.outstanding_shares_consolidated)
70
+ # ):
71
+ # return self.free_cash / float(outstanding_shares_consolidated)
72
+ #
73
+ # def _compute_free_cash_flow_growth(self) -> float:
74
+ # if (
75
+ # self.free_cash_flow is not None
76
+ # and (last_fundamental := self.last_fundamental)
77
+ # and (last_free_cash_flow := last_fundamental.free_cash_flow)
78
+ # ):
79
+ # return self.free_cash_flow / last_free_cash_flow - 1
80
+ #
81
+ # def _compute_free_cash_flow_to_sales_ratio(self) -> float:
82
+ # if self.free_cash_flow is not None and self.revenue:
83
+ # return self.free_cash_flow / self.revenue
84
+ #
85
+ # def _compute_book_value_per_share(self) -> float:
86
+ # if self.total_assets is not None and self.total_debt is not None:
87
+ # if (
88
+ # yearly_valuations := self.instrument.valuations.exclude(outstanding_shares_consolidated=0).filter(
89
+ # date__year=self.year,
90
+ # date__lte=self.date_range.upper,
91
+ # outstanding_shares__isnull=False,
92
+ # )
93
+ # ).exists() and (
94
+ # last_outstanding_shares := yearly_valuations.latest("date").outstanding_shares_consolidated
95
+ # ):
96
+ # return (self.total_assets - self.total_debt) / float(last_outstanding_shares)
97
+ #
98
+ # def _compute_net_change_in_cash(self) -> float:
99
+ # if (
100
+ # self.cash_from_operation is not None
101
+ # and self.investment_cash is not None
102
+ # and self.financing_cash is not None
103
+ # ):
104
+ # return self.cash_from_operation - self.investment_cash + self.financing_cash
105
+ #
106
+ # def _compute_employee_count_growth(self) -> float:
107
+ # if self.employee_count is not None and (previous := self.last_fundamental) and previous.employee_count:
108
+ # return self.employee_count / previous.employee_count - 1
109
+ #
110
+ # def _compute_capex_to_sales(self) -> float:
111
+ # if self.capital_expenditures is not None and self.revenue:
112
+ # return self.capital_expenditures / self.revenue
113
+ #
114
+ # def _compute_net_debt_to_ebitda_ratio(self) -> float:
115
+ # if self.net_debt is not None and self.ebitda:
116
+ # return self.net_debt / self.ebitda
117
+ #
118
+ # def _compute_burn_rate(self) -> float:
119
+ # if self.net_change_in_cash is not None:
120
+ # return min(self.net_change_in_cash / 12, 0)
121
+ #
122
+ # def _compute_operating_burn_rate(self) -> float:
123
+ # if self.cash_from_operation is not None:
124
+ # return min(self.cash_from_operation / 12, 0)
125
+ #
126
+ # def _compute_free_cash_burn_rate(self) -> float:
127
+ # if self.free_cash is not None:
128
+ # return min(self.free_cash / 12, 0)
129
+ #
130
+ # def _compute_cash_reserve_to_burn_rate_ratio(self) -> float:
131
+ # if self.cash_and_short_term_investments is not None and self.burn_rate:
132
+ # return abs(self.cash_and_short_term_investments / self.burn_rate / 12)
133
+ #
134
+ # def _compute_cash_reserve_to_operating_burn_rate_ratio(self) -> float:
135
+ # if self.cash_and_short_term_investments is not None and self.operating_burn_rate:
136
+ # return abs(self.cash_and_short_term_investments / self.operating_burn_rate / 12)
137
+ #
138
+ # def _compute_cash_reserve_to_free_cash_burn_rate_ratio(self) -> float:
139
+ # if self.cash_and_short_term_investments is not None and self.free_cash_burn_rate:
140
+ # return abs(self.cash_and_short_term_investments / self.free_cash_burn_rate / 12)
141
+ #
142
+ # def _compute_working_capital_to_burn_rate_ratio(self) -> float:
143
+ # if self.working_capital is not None and self.burn_rate:
144
+ # if self.working_capital <= 0:
145
+ # return None
146
+ # return abs(self.working_capital / self.burn_rate / 12)
147
+ #
148
+ # def _compute_working_capital_to_operating_burn_rate_ratio(self) -> float:
149
+ # if self.working_capital is not None and self.operating_burn_rate:
150
+ # if self.working_capital <= 0:
151
+ # return None
152
+ # return abs(self.working_capital / self.operating_burn_rate / 12)
153
+ #
154
+ # def _compute_working_capital_to_free_cash_burn_rate_ratio(self) -> float:
155
+ # if self.working_capital is not None and self.free_cash_burn_rate:
156
+ # if self.working_capital <= 0:
157
+ # return None
158
+ # return abs(self.working_capital / self.free_cash_burn_rate / 12)
159
+ #
160
+ # def _compute_current_ratio(self) -> float:
161
+ # if self.current_assets is not None and self.current_liabilities:
162
+ # return self.current_assets / self.current_liabilities
163
+ #
164
+ # def _compute_cash_and_short_term_investments_to_current_assets_ratio(self) -> float:
165
+ # if self.cash_and_short_term_investments is not None and self.current_assets:
166
+ # return self.cash_and_short_term_investments / self.current_assets
167
+ #
168
+ # def _compute_rd_to_sales_ratio(self) -> float:
169
+ # if self.cost_research_development is not None and self.revenue:
170
+ # return self.cost_research_development / self.revenue
171
+ #
172
+ # def _compute_interest_coverage_ratio(self) -> float:
173
+ # if self.ebit is not None and self.interest_expense:
174
+ # return self.ebit / self.interest_expense
175
+ #
176
+ # def _compute_return_on_equity(self) -> float:
177
+ # if (
178
+ # (previous := self.last_fundamental)
179
+ # and self.net_profit is not None
180
+ # and self.shareholder_equity is not None
181
+ # and (previous_shareholder := previous.shareholder_equity) is not None
182
+ # ):
183
+ # avg_shareholder = (self.shareholder_equity + previous_shareholder) / 2
184
+ # if avg_shareholder:
185
+ # return self.net_profit / avg_shareholder
186
+ #
187
+ # def _compute_return_on_assets(self) -> float:
188
+ # if (
189
+ # (previous := self.last_fundamental)
190
+ # and self.net_profit is not None
191
+ # and self.total_assets is not None
192
+ # and (previous_total_assets := previous.total_assets) is not None
193
+ # ):
194
+ # avg_total_assets = (self.total_assets + previous_total_assets) / 2
195
+ # if avg_total_assets:
196
+ # return self.net_profit / avg_total_assets
197
+ #
198
+ # def _compute_return_on_capital_employed(self) -> float:
199
+ # if (
200
+ # self.ebit is not None
201
+ # and self.total_assets
202
+ # and self.current_liabilities
203
+ # and (diff := self.total_assets - self.current_liabilities)
204
+ # ):
205
+ # return self.ebit / diff
206
+ #
207
+ # def _compute_return_on_invested_capital(self) -> float:
208
+ # if (
209
+ # self.ebit is not None
210
+ # and self.company_tax_rate is not None
211
+ # and self.shareholder_equity is not None
212
+ # and self.total_liabilities is not None
213
+ # and self.cash_and_cash_equivalents is not None
214
+ # and (previous := self.last_fundamental)
215
+ # ):
216
+ # if (
217
+ # previous.shareholder_equity is not None
218
+ # and previous.total_liabilities is not None
219
+ # and previous.cash_and_cash_equivalents is not None
220
+ # ):
221
+ # divisor = (
222
+ # self.shareholder_equity
223
+ # + self.total_liabilities
224
+ # - self.cash_and_cash_equivalents
225
+ # + previous.shareholder_equity
226
+ # + previous.total_liabilities
227
+ # - previous.cash_and_cash_equivalents
228
+ # ) / 2
229
+ # if divisor:
230
+ # return self.ebit * (1 - self.company_tax_rate) / divisor
231
+ #
232
+ # def _compute_revenue_to_employee_ratio(self) -> float:
233
+ # if self.revenue is not None and self.employee_count:
234
+ # return self.revenue / self.employee_count
235
+ #
236
+ #
237
+ # class GeographicSegmentComputedMixin:
238
+ # def _compute_value_growth(self) -> float:
239
+ # if self.value is not None and (previous_segment := self.last_geographic_segment) and previous_segment.value:
240
+ # return self.value / previous_segment.value - 1
241
+ #
242
+ #
243
+ # class ForecastComputedMixin:
244
+ # def _compute_revenue_growth_y1(self) -> float:
245
+ # if (fundamental := self.yearly_fundamental) and self.revenue_y1 is not None and fundamental.revenue:
246
+ # return self.revenue_y1 / fundamental.revenue - 1
247
+ #
248
+ # def _compute_revenue_growth_y2(self) -> float:
249
+ # if self.revenue_y2 is not None and self.revenue_y1:
250
+ # return self.revenue_y2 / self.revenue_y1 - 1
251
+ #
252
+ # def _compute_revenue_growth_y3(self) -> float:
253
+ # if self.revenue_y3 is not None and self.revenue_y2:
254
+ # return self.revenue_y3 / self.revenue_y2 - 1
255
+ #
256
+ # def _compute_revenue_growth_y4(self) -> float:
257
+ # if self.revenue_y4 is not None and self.revenue_y3:
258
+ # return self.revenue_y4 / self.revenue_y3 - 1
259
+ #
260
+ # def _compute_revenue_growth_y5(self) -> float:
261
+ # if self.revenue_y5 is not None and self.revenue_y4:
262
+ # return self.revenue_y5 / self.revenue_y4 - 1
263
+ #
264
+ # def _compute_deprecation_and_amortization_y1(self):
265
+ # if self.ebitda_margin_y1 is not None and self.ebit_margin_y1 is not None:
266
+ # return self.ebitda_margin_y1 - self.ebit_margin_y1
267
+ #
268
+ # def _compute_deprecation_and_amortization_y2(self):
269
+ # if self.ebitda_margin_y2 is not None and self.ebit_margin_y2 is not None:
270
+ # return self.ebitda_margin_y2 - self.ebit_margin_y2
271
+ #
272
+ # def _compute_deprecation_and_amortization_y3(self):
273
+ # if self.ebitda_margin_y3 is not None and self.ebit_margin_y3 is not None:
274
+ # return self.ebitda_margin_y3 - self.ebit_margin_y3
275
+ #
276
+ # def _compute_deprecation_and_amortization_y4(self):
277
+ # if self.ebitda_margin_y4 is not None and self.ebit_margin_y4 is not None:
278
+ # return self.ebitda_margin_y4 - self.ebit_margin_y4
279
+ #
280
+ # def _compute_deprecation_and_amortization_y5(self):
281
+ # if self.ebitda_margin_y5 is not None and self.ebit_margin_y5 is not None:
282
+ # return self.ebitda_margin_y5 - self.ebit_margin_y5
283
+ #
284
+ # def _compute_gross_profit_margin_y1(self):
285
+ # if (
286
+ # self.gross_profit_margin_without_depreciation_y1 is not None
287
+ # and self.deprecation_and_amortization_y1 is not None
288
+ # ):
289
+ # return self.gross_profit_margin_without_depreciation_y1 + self.deprecation_and_amortization_y1
290
+ #
291
+ # def _compute_gross_profit_margin_y2(self):
292
+ # if (
293
+ # self.gross_profit_margin_without_depreciation_y2 is not None
294
+ # and self.deprecation_and_amortization_y2 is not None
295
+ # ):
296
+ # return self.gross_profit_margin_without_depreciation_y2 + self.deprecation_and_amortization_y2
297
+ #
298
+ # def _compute_gross_profit_margin_y3(self):
299
+ # if (
300
+ # self.gross_profit_margin_without_depreciation_y3 is not None
301
+ # and self.deprecation_and_amortization_y3 is not None
302
+ # ):
303
+ # return self.gross_profit_margin_without_depreciation_y3 + self.deprecation_and_amortization_y3
304
+ #
305
+ # def _compute_gross_profit_margin_y4(self):
306
+ # if (
307
+ # self.gross_profit_margin_without_depreciation_y4 is not None
308
+ # and self.deprecation_and_amortization_y4 is not None
309
+ # ):
310
+ # return self.gross_profit_margin_without_depreciation_y4 + self.deprecation_and_amortization_y4
311
+ #
312
+ # def _compute_gross_profit_margin_y5(self):
313
+ # if (
314
+ # self.gross_profit_margin_without_depreciation_y5 is not None
315
+ # and self.deprecation_and_amortization_y5 is not None
316
+ # ):
317
+ # return self.gross_profit_margin_without_depreciation_y5 + self.deprecation_and_amortization_y5
318
+ #
319
+ # def _compute_gross_profit_y1(self):
320
+ # if self.gross_profit_margin_y1 is not None and self.revenue_y1 is not None:
321
+ # return self.gross_profit_margin_y1 * self.revenue_y1
322
+ #
323
+ # def _compute_gross_profit_y2(self):
324
+ # if self.gross_profit_margin_y2 is not None and self.revenue_y2 is not None:
325
+ # return self.gross_profit_margin_y2 * self.revenue_y2
326
+ #
327
+ # def _compute_gross_profit_y3(self):
328
+ # if self.gross_profit_margin_y3 is not None and self.revenue_y3 is not None:
329
+ # return self.gross_profit_margin_y3 * self.revenue_y3
330
+ #
331
+ # def _compute_gross_profit_y4(self):
332
+ # if self.gross_profit_margin_y4 is not None and self.revenue_y4 is not None:
333
+ # return self.gross_profit_margin_y4 * self.revenue_y4
334
+ #
335
+ # def _compute_gross_profit_y5(self):
336
+ # if self.gross_profit_margin_y5 is not None and self.revenue_y5 is not None:
337
+ # return self.gross_profit_margin_y5 * self.revenue_y5
338
+ #
339
+ # def _compute_net_profit_margin_y1(self) -> float:
340
+ # if self.reported_net_profit_y1 is not None and self.revenue_y1:
341
+ # return self.reported_net_profit_y1 / self.revenue_y1
342
+ #
343
+ # def _compute_net_profit_margin_y2(self) -> float:
344
+ # if self.reported_net_profit_y2 is not None and self.revenue_y2:
345
+ # return self.reported_net_profit_y2 / self.revenue_y2
346
+ #
347
+ # def _compute_net_profit_margin_y3(self) -> float:
348
+ # if self.reported_net_profit_y3 is not None and self.revenue_y3:
349
+ # return self.reported_net_profit_y3 / self.revenue_y3
350
+ #
351
+ # def _compute_net_profit_margin_y4(self) -> float:
352
+ # if self.reported_net_profit_y4 is not None and self.revenue_y4:
353
+ # return self.reported_net_profit_y4 / self.revenue_y4
354
+ #
355
+ # def _compute_net_profit_margin_y5(self) -> float:
356
+ # if self.reported_net_profit_y5 is not None and self.revenue_y5:
357
+ # return self.reported_net_profit_y5 / self.revenue_y5
358
+ #
359
+ # def _compute_ebitda_margin_y1(self) -> float:
360
+ # if self.ebitda_y1 is not None and self.revenue_y1:
361
+ # return self.ebitda_y1 / self.revenue_y1
362
+ #
363
+ # def _compute_ebitda_margin_y2(self) -> float:
364
+ # if self.ebitda_y2 is not None and self.revenue_y2:
365
+ # return self.ebitda_y2 / self.revenue_y2
366
+ #
367
+ # def _compute_ebitda_margin_y3(self) -> float:
368
+ # if self.ebitda_y3 is not None and self.revenue_y3:
369
+ # return self.ebitda_y3 / self.revenue_y3
370
+ #
371
+ # def _compute_ebitda_margin_y4(self) -> float:
372
+ # if self.ebitda_y4 is not None and self.revenue_y4:
373
+ # return self.ebitda_y4 / self.revenue_y4
374
+ #
375
+ # def _compute_ebitda_margin_y5(self) -> float:
376
+ # if self.ebitda_y5 is not None and self.revenue_y5:
377
+ # return self.ebitda_y5 / self.revenue_y5
378
+ #
379
+ # def _compute_ebit_margin_y1(self) -> float:
380
+ # if self.ebit_y1 is not None and self.revenue_y1:
381
+ # return self.ebit_y1 / self.revenue_y1
382
+ #
383
+ # def _compute_ebit_margin_y2(self) -> float:
384
+ # if self.ebit_y2 is not None and self.revenue_y2:
385
+ # return self.ebit_y2 / self.revenue_y2
386
+ #
387
+ # def _compute_ebit_margin_y3(self) -> float:
388
+ # if self.ebit_y3 is not None and self.revenue_y3:
389
+ # return self.ebit_y3 / self.revenue_y3
390
+ #
391
+ # def _compute_ebit_margin_y4(self) -> float:
392
+ # if self.ebit_y4 is not None and self.revenue_y4:
393
+ # return self.ebit_y4 / self.revenue_y4
394
+ #
395
+ # def _compute_ebit_margin_y5(self) -> float:
396
+ # if self.ebit_y5 is not None and self.revenue_y5:
397
+ # return self.ebit_y5 / self.revenue_y5
398
+ #
399
+ # def _compute_eps_y1(self):
400
+ # if self.reported_net_profit_y1 is not None and self.shares:
401
+ # return self.reported_net_profit_y1 / self.shares
402
+ #
403
+ # def _compute_eps_y2(self):
404
+ # if self.reported_net_profit_y2 is not None and self.shares:
405
+ # return self.reported_net_profit_y2 / self.shares
406
+ #
407
+ # def _compute_eps_y3(self):
408
+ # if self.reported_net_profit_y3 is not None and self.shares:
409
+ # return self.reported_net_profit_y3 / self.shares
410
+ #
411
+ # def _compute_eps_y4(self):
412
+ # if self.reported_net_profit_y4 is not None and self.shares:
413
+ # return self.reported_net_profit_y4 / self.shares
414
+ #
415
+ # def _compute_eps_y5(self):
416
+ # if self.reported_net_profit_y5 is not None and self.shares:
417
+ # return self.reported_net_profit_y5 / self.shares
418
+ #
419
+ # def _compute_eps_growth_y1(self) -> float:
420
+ # if (fundamental := self.yearly_fundamental) and self.eps_y1 is not None and fundamental.eps:
421
+ # return self.eps_y1 / fundamental.eps - 1
422
+ #
423
+ # def _compute_eps_growth_y2(self) -> float:
424
+ # if self.eps_y2 is not None and self.eps_y1:
425
+ # return self.eps_y2 / self.eps_y1 - 1
426
+ #
427
+ # def _compute_eps_growth_y3(self) -> float:
428
+ # if self.eps_y3 is not None and self.eps_y2:
429
+ # return self.eps_y3 / self.eps_y2 - 1
430
+ #
431
+ # def _compute_eps_growth_y4(self) -> float:
432
+ # if self.eps_y4 is not None and self.eps_y3:
433
+ # return self.eps_y4 / self.eps_y3 - 1
434
+ #
435
+ # def _compute_eps_growth_y5(self) -> float:
436
+ # if self.eps_y5 is not None and self.eps_y4:
437
+ # return self.eps_y5 / self.eps_y4 - 1
438
+ #
439
+ # def _compute_net_debt_to_ebitda_ratio_y1(self) -> float:
440
+ # if self.net_debt_y1 is not None and self.ebitda_y1:
441
+ # return self.net_debt_y1 / self.ebitda_y1
442
+ #
443
+ # def _compute_net_debt_to_ebitda_ratio_y2(self) -> float:
444
+ # if self.net_debt_y2 is not None and self.ebitda_y2:
445
+ # return self.net_debt_y2 / self.ebitda_y2
446
+ #
447
+ # def _compute_net_debt_to_ebitda_ratio_y3(self) -> float:
448
+ # if self.net_debt_y3 is not None and self.ebitda_y3:
449
+ # return self.net_debt_y3 / self.ebitda_y3
450
+ #
451
+ # def _compute_net_debt_to_ebitda_ratio_y4(self) -> float:
452
+ # if self.net_debt_y4 is not None and self.ebitda_y4:
453
+ # return self.net_debt_y4 / self.ebitda_y4
454
+ #
455
+ # def _compute_net_debt_to_ebitda_ratio_y5(self) -> float:
456
+ # if self.net_debt_y5 is not None and self.ebitda_y5:
457
+ # return self.net_debt_y5 / self.ebitda_y5
458
+ #
459
+ # def _compute_free_cash_flow_growth_y1(self) -> float:
460
+ # if (
461
+ # (daily_fundamental := self.daily_fundamental)
462
+ # and self.free_cash_flow_y1 is not None
463
+ # and daily_fundamental.free_cash_flow
464
+ # ):
465
+ # return self.free_cash_flow_y1 / daily_fundamental.free_cash_flow - 1
466
+ #
467
+ # def _compute_free_cash_flow_growth_y2(self) -> float:
468
+ # if self.free_cash_flow_y2 is not None and self.free_cash_flow_y1:
469
+ # return self.free_cash_flow_y2 / self.free_cash_flow_y1 - 1
470
+ #
471
+ # def _compute_free_cash_flow_growth_y3(self) -> float:
472
+ # if self.free_cash_flow_y3 is not None and self.free_cash_flow_y2:
473
+ # return self.free_cash_flow_y3 / self.free_cash_flow_y2 - 1
474
+ #
475
+ # def _compute_free_cash_flow_growth_y4(self) -> float:
476
+ # if self.free_cash_flow_y4 is not None and self.free_cash_flow_y3:
477
+ # return self.free_cash_flow_y4 / self.free_cash_flow_y3 - 1
478
+ #
479
+ # def _compute_free_cash_flow_growth_y5(self) -> float:
480
+ # if self.free_cash_flow_y5 is not None and self.free_cash_flow_y4:
481
+ # return self.free_cash_flow_y5 / self.free_cash_flow_y4 - 1
482
+ #
483
+ # def _compute_free_cash_flow_to_sales_ratio_y1(self) -> float:
484
+ # if self.free_cash_flow_y1 is not None and self.revenue_y1:
485
+ # return self.free_cash_flow_y1 / self.revenue_y1
486
+ #
487
+ # def _compute_free_cash_flow_to_sales_ratio_y2(self) -> float:
488
+ # if self.free_cash_flow_y2 is not None and self.revenue_y2:
489
+ # return self.free_cash_flow_y2 / self.revenue_y2
490
+ #
491
+ # def _compute_free_cash_flow_to_sales_ratio_y3(self) -> float:
492
+ # if self.free_cash_flow_y3 is not None and self.revenue_y3:
493
+ # return self.free_cash_flow_y3 / self.revenue_y3
494
+ #
495
+ # def _compute_free_cash_flow_to_sales_ratio_y4(self) -> float:
496
+ # if self.free_cash_flow_y4 is not None and self.revenue_y4:
497
+ # return self.free_cash_flow_y4 / self.revenue_y4
498
+ #
499
+ # def _compute_free_cash_flow_to_sales_ratio_y5(self) -> float:
500
+ # if self.free_cash_flow_y5 is not None and self.revenue_y5:
501
+ # return self.free_cash_flow_y5 / self.revenue_y5
502
+ #
503
+ # def _compute_capex_to_sales_y1(self) -> float:
504
+ # if self.capital_expenditures_y1 is not None and self.revenue_y1:
505
+ # return self.capital_expenditures_y1 / self.revenue_y1
506
+ #
507
+ # def _compute_capex_to_sales_y2(self) -> float:
508
+ # if self.capital_expenditures_y2 is not None and self.revenue_y2:
509
+ # return self.capital_expenditures_y2 / self.revenue_y2
510
+ #
511
+ # def _compute_capex_to_sales_y3(self) -> float:
512
+ # if self.capital_expenditures_y3 is not None and self.revenue_y3:
513
+ # return self.capital_expenditures_y3 / self.revenue_y3
514
+ #
515
+ # def _compute_capex_to_sales_y4(self) -> float:
516
+ # if self.capital_expenditures_y4 is not None and self.revenue_y4:
517
+ # return self.capital_expenditures_y4 / self.revenue_y4
518
+ #
519
+ # def _compute_capex_to_sales_y5(self) -> float:
520
+ # if self.capital_expenditures_y5 is not None and self.revenue_y5:
521
+ # return self.capital_expenditures_y5 / self.revenue_y5
522
+ #
523
+ # def __compute_return_on_equity(self, year: int) -> float:
524
+ # if (
525
+ # (net_profit := getattr(self, f"reported_net_profit_y{year}")) is not None
526
+ # and (previous := self.yearly_fundamental)
527
+ # and previous.net_profit is not None
528
+ # and previous.shareholder_equity
529
+ # ):
530
+ # return net_profit / previous.shareholder_equity
531
+ #
532
+ # def _compute_return_on_equity_y1(self):
533
+ # return self.__compute_return_on_equity(1)
534
+ #
535
+ # def _compute_return_on_equity_y2(self):
536
+ # return self.__compute_return_on_equity(2)
537
+ #
538
+ # def _compute_return_on_equity_y3(self):
539
+ # return self.__compute_return_on_equity(3)
540
+ #
541
+ # def _compute_return_on_equity_y4(self):
542
+ # return self.__compute_return_on_equity(4)
543
+ #
544
+ # def _compute_return_on_equity_y5(self):
545
+ # return self.__compute_return_on_equity(5)
546
+ #
547
+ # def __compute_return_on_assets(self, year: int) -> float:
548
+ # if (
549
+ # (net_profit := getattr(self, f"reported_net_profit_y{year}")) is not None
550
+ # and (previous := self.yearly_fundamental)
551
+ # and previous.net_profit is not None
552
+ # and previous.total_assets
553
+ # ):
554
+ # return net_profit / previous.total_assets
555
+ #
556
+ # def _compute_return_on_assets_y1(self):
557
+ # return self.__compute_return_on_assets(1)
558
+ #
559
+ # def _compute_return_on_assets_y2(self):
560
+ # return self.__compute_return_on_assets(2)
561
+ #
562
+ # def _compute_return_on_assets_y3(self):
563
+ # return self.__compute_return_on_assets(3)
564
+ #
565
+ # def _compute_return_on_assets_y4(self):
566
+ # return self.__compute_return_on_assets(4)
567
+ #
568
+ # def _compute_return_on_assets_y5(self):
569
+ # return self.__compute_return_on_assets(5)
570
+ #
571
+ # def __compute_return_on_capital_employed(self, year: int) -> float:
572
+ # if (
573
+ # (previous := self.yearly_fundamental)
574
+ # and (ebit := getattr(self, f"ebit_y{year}")) is not None
575
+ # and previous.total_assets
576
+ # and previous.current_liabilities
577
+ # and (diff := previous.total_assets - previous.current_liabilities)
578
+ # ):
579
+ # return ebit / diff
580
+ #
581
+ # def _compute_return_on_capital_employed_y1(self):
582
+ # return self.__compute_return_on_capital_employed(1)
583
+ #
584
+ # def _compute_return_on_capital_employed_y2(self):
585
+ # return self.__compute_return_on_capital_employed(2)
586
+ #
587
+ # def _compute_return_on_capital_employed_y3(self):
588
+ # return self.__compute_return_on_capital_employed(3)
589
+ #
590
+ # def _compute_return_on_capital_employed_y4(self):
591
+ # return self.__compute_return_on_capital_employed(4)
592
+ #
593
+ # def _compute_return_on_capital_employed_y5(self):
594
+ # return self.__compute_return_on_capital_employed(5)
595
+ #
596
+ # def __compute_return_on_invested_capital(self, year: int) -> float:
597
+ # if (
598
+ # (previous := self.yearly_fundamental)
599
+ # and (ebit := getattr(self, f"ebit_y{year}")) is not None
600
+ # and previous.company_tax_rate is not None
601
+ # and previous.shareholder_equity is not None
602
+ # and previous.total_liabilities is not None
603
+ # and previous.cash_and_cash_equivalents is not None
604
+ # ):
605
+ # divisor = previous.shareholder_equity + previous.total_liabilities - previous.cash_and_cash_equivalents
606
+ # if divisor:
607
+ # return ebit * (1 - previous.company_tax_rate) / divisor
608
+ #
609
+ # def _compute_return_on_invested_capital_y1(self):
610
+ # return self.__compute_return_on_invested_capital(1)
611
+ #
612
+ # def _compute_return_on_invested_capital_y2(self):
613
+ # return self.__compute_return_on_invested_capital(2)
614
+ #
615
+ # def _compute_return_on_invested_capital_y3(self):
616
+ # return self.__compute_return_on_invested_capital(3)
617
+ #
618
+ # def _compute_return_on_invested_capital_y4(self):
619
+ # return self.__compute_return_on_invested_capital(4)
620
+ #
621
+ # def _compute_return_on_invested_capital_y5(self):
622
+ # return self.__compute_return_on_invested_capital(5)
623
+ #
624
+ # def __compute_interest_coverage_ratio(self, year: int) -> float:
625
+ # if (
626
+ # (previous := self.yearly_fundamental)
627
+ # and (ebit := getattr(self, f"ebit_y{year}")) is not None
628
+ # and previous.interest_expense
629
+ # ):
630
+ # return ebit / previous.interest_expense
631
+ #
632
+ # def _compute_interest_coverage_ratio_y1(self):
633
+ # return self.__compute_interest_coverage_ratio(1)
634
+ #
635
+ # def _compute_interest_coverage_ratio_y2(self):
636
+ # return self.__compute_interest_coverage_ratio(2)
637
+ #
638
+ # def _compute_interest_coverage_ratio_y3(self):
639
+ # return self.__compute_interest_coverage_ratio(3)
640
+ #
641
+ # def _compute_interest_coverage_ratio_y4(self):
642
+ # return self.__compute_interest_coverage_ratio(4)
643
+ #
644
+ # def _compute_interest_coverage_ratio_y5(self):
645
+ # return self.__compute_interest_coverage_ratio(5)
646
+ #
647
+ #
648
+ # class DailyFundamentalComputedMixin:
649
+ # def _compute_free_cash_flow_ttm_growth(self) -> float:
650
+ # if (
651
+ # self.free_cash_flow is not None
652
+ # and (last_ttl_daily_fundamental := self.last_ttl_daily_fundamental)
653
+ # and (last_free_cash_flow := last_ttl_daily_fundamental.free_cash_flow)
654
+ # ):
655
+ # return self.free_cash_flow / last_free_cash_flow - 1
656
+ #
657
+ # def _compute_free_cash_flow(self) -> float:
658
+ # if (
659
+ # self.free_cash is not None
660
+ # and (price := self.price)
661
+ # and (outstanding_shares_consolidated := price.outstanding_shares_consolidated)
662
+ # ):
663
+ # return self.free_cash / float(outstanding_shares_consolidated)
664
+ #
665
+ # def _compute_revenue_growth_3y_cagr(self) -> float:
666
+ # if (
667
+ # (forecast := self.forecast)
668
+ # and (fundamental := self.yearly_fundamental)
669
+ # and (revenue_y3 := forecast.revenue_y3) is not None
670
+ # and fundamental.revenue
671
+ # ):
672
+ # if (den := revenue_y3 / fundamental.revenue) >= 0:
673
+ # return math.pow(den, 1 / 3) - 1
674
+ #
675
+ # def _compute_eps_3y_cagr(self) -> float:
676
+ # if (
677
+ # (forecast := self.forecast)
678
+ # and (fundamental := self.yearly_fundamental)
679
+ # and (eps_3y := forecast.eps_y3) is not None
680
+ # and fundamental.eps
681
+ # ):
682
+ # if (den := eps_3y / fundamental.eps) >= 0:
683
+ # return math.pow(den, 1 / 3) - 1
684
+ #
685
+ # def _compute_free_cash_flow_3y_cagr(self) -> float:
686
+ # if (
687
+ # (forecast := self.forecast)
688
+ # and (fundamental := self.yearly_fundamental)
689
+ # and (fcf_3y := forecast.free_cash_flow_y3) is not None
690
+ # and fundamental.free_cash_flow
691
+ # ):
692
+ # if (den := fcf_3y / fundamental.free_cash_flow) >= 0:
693
+ # return math.pow(den, 1 / 3) - 1
694
+ #
695
+ # def _compute_eps_ttm(self):
696
+ # pass
697
+ #
698
+ #
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
+ def _compute_outstanding_shares_consolidated(self):
705
+ if self.outstanding_shares_consolidated is None and self.outstanding_shares is not None:
706
+ return self.outstanding_shares
707
+
708
+ def _compute_gross_value(self):
709
+ if self.net_value is not None and self.gross_value is None:
710
+ return self.net_value
711
+
712
+ def _compute_volume_50d(self):
713
+ volumes = list(
714
+ filter(
715
+ None,
716
+ self.instrument.valuations.filter(date__lte=self.date)
717
+ .order_by("-date")
718
+ .values_list("volume", flat=True)[:50],
719
+ )
720
+ )
721
+ if len(volumes) > 0:
722
+ return sum(volumes) / len(volumes)
723
+ return 0.0
724
+
725
+ def _compute_volume_200d(self):
726
+ volumes = list(
727
+ filter(
728
+ None,
729
+ self.instrument.valuations.filter(date__lte=self.date)
730
+ .order_by("-date")
731
+ .values_list("volume", flat=True)[:200],
732
+ )
733
+ )
734
+ if len(volumes) > 0:
735
+ return sum(volumes) / len(volumes)
736
+ return 0.0
737
+
738
+ def _compute_performance_1d(self):
739
+ try:
740
+ last_price = self.instrument.prices.get(
741
+ calculated=self.calculated, date=(self.date - pd.tseries.offsets.BDay(1)).date()
742
+ )
743
+ if self.net_value is not None and last_price.net_value:
744
+ return self.net_value / last_price.net_value - 1
745
+ except self.DoesNotExist:
746
+ pass
747
+
748
+ def _compute_performance_7d(self):
749
+ try:
750
+ last_price = self.instrument.prices.get(
751
+ calculated=self.calculated, date=(self.date - pd.tseries.offsets.BDay(7)).date()
752
+ )
753
+ if self.net_value is not None and last_price.net_value:
754
+ return self.net_value / last_price.net_value - 1
755
+ except self.DoesNotExist:
756
+ pass
757
+
758
+ def _compute_performance_30d(self):
759
+ try:
760
+ last_price = self.instrument.prices.get(
761
+ calculated=self.calculated, date=(self.date - pd.tseries.offsets.BDay(30)).date()
762
+ )
763
+ if self.net_value is not None and last_price.net_value:
764
+ return self.net_value / last_price.net_value - 1
765
+ except self.DoesNotExist:
766
+ pass
767
+
768
+ def _compute_performance_90d(self):
769
+ try:
770
+ last_price = self.instrument.prices.get(
771
+ calculated=self.calculated, date=(self.date - pd.tseries.offsets.BDay(90)).date()
772
+ )
773
+ if self.net_value is not None and last_price.net_value:
774
+ return self.net_value / last_price.net_value - 1
775
+ except self.DoesNotExist:
776
+ pass
777
+
778
+ def _compute_performance_365d(self):
779
+ try:
780
+ last_price = self.instrument.prices.get(
781
+ calculated=self.calculated, date=(self.date - pd.tseries.offsets.BDay(365)).date()
782
+ )
783
+ if self.net_value is not None and last_price.net_value:
784
+ return self.net_value / last_price.net_value - 1
785
+ except self.DoesNotExist:
786
+ pass
787
+
788
+ def _compute_performance_ytd(self):
789
+ try:
790
+ last_price = self.instrument.prices.get(
791
+ calculated=self.calculated, date=(date(self.date.year, 1, 1) - pd.tseries.offsets.BDay(0)).date()
792
+ )
793
+ if self.net_value is not None and last_price.net_value:
794
+ return self.net_value / last_price.net_value - 1
795
+ except self.DoesNotExist:
796
+ pass
797
+
798
+ def _compute_performance_inception(self):
799
+ try:
800
+ last_price = self.instrument.prices.get(calculated=self.calculated, date=self.instrument.inception_date)
801
+ if self.net_value is not None and last_price.net_value:
802
+ return self.net_value / last_price.net_value - 1
803
+ except self.DoesNotExist:
804
+ pass