equity-aggregator 0.1.1__tar.gz → 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/.env_example +1 -1
  2. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/.github/workflows/publish-build-release.yml +19 -1
  3. equity_aggregator-0.1.4/.github/workflows/publish-pypi.yml +103 -0
  4. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/.github/workflows/validate-push.yml +1 -1
  5. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/PKG-INFO +205 -115
  6. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/README.md +204 -107
  7. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/docker-compose.yml +5 -2
  8. equity_aggregator-0.1.4/documentation/reference_data/lseg_equities.json +482 -0
  9. equity_aggregator-0.1.4/documentation/reference_data/sec_equity.json +60862 -0
  10. equity_aggregator-0.1.4/documentation/reference_data/tradingview_equities.json +24005 -0
  11. equity_aggregator-0.1.4/documentation/reference_data/yfinance_quote_summary_equity.json +15383 -0
  12. equity_aggregator-0.1.4/documentation/reference_data/yfinance_search_equity.json +309 -0
  13. equity_aggregator-0.1.4/examples/data_integrity_analysis.py +1812 -0
  14. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/pyproject.toml +5 -4
  15. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/README.md +40 -36
  16. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/__init__.py +13 -7
  17. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/__init__.py +4 -6
  18. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/_utils/_client.py +1 -1
  19. {equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/authoritative_feeds → equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/_utils}/_record_types.py +1 -1
  20. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/__init__.py +17 -0
  21. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/__init__.py +7 -0
  22. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/__init__.py +10 -0
  23. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/backoff.py +33 -0
  24. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/parser.py +107 -0
  25. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/intrinio.py +305 -0
  26. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/session.py +197 -0
  27. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/__init__.py +7 -0
  28. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/__init__.py +9 -0
  29. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/backoff.py +33 -0
  30. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/parser.py +120 -0
  31. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/lseg.py +239 -0
  32. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/session.py +162 -0
  33. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/sec/__init__.py +7 -0
  34. {equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/authoritative_feeds → equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/sec}/sec.py +4 -5
  35. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/stock_analysis/__init__.py +7 -0
  36. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/stock_analysis/stock_analysis.py +150 -0
  37. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/tradingview/__init__.py +5 -0
  38. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/tradingview/tradingview.py +275 -0
  39. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/xetra/__init__.py +7 -0
  40. {equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/authoritative_feeds → equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/discovery_feeds/xetra}/xetra.py +9 -12
  41. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/__init__.py +10 -0
  42. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/__init__.py +5 -0
  43. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/api.py +71 -0
  44. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/download.py +109 -0
  45. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/gleif.py +195 -0
  46. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/parser.py +75 -0
  47. {equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/enrichment_feeds → equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance}/__init__.py +1 -1
  48. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/__init__.py +11 -0
  49. {equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/utils → equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils}/backoff.py +1 -1
  50. {equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/utils → equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils}/fuzzy.py +28 -26
  51. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/json.py +36 -0
  52. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/__init__.py +1 -1
  53. equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/summary.py → equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/quote_summary.py +44 -30
  54. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/search.py +10 -5
  55. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/auth.py +130 -0
  56. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/config.py +3 -3
  57. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/ranking.py +97 -0
  58. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/session.py +243 -0
  59. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/transport.py +191 -0
  60. equity_aggregator-0.1.4/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/yfinance.py +413 -0
  61. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/reference_lookup/exchange_rate_api.py +6 -13
  62. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/reference_lookup/openfigi.py +23 -7
  63. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/cli/dispatcher.py +11 -8
  64. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/cli/main.py +14 -5
  65. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/cli/parser.py +1 -1
  66. equity_aggregator-0.1.4/src/equity_aggregator/cli/signals.py +32 -0
  67. equity_aggregator-0.1.4/src/equity_aggregator/domain/_utils/__init__.py +6 -0
  68. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/_utils/_load_converter.py +30 -21
  69. equity_aggregator-0.1.4/src/equity_aggregator/domain/_utils/_merge.py +312 -0
  70. equity_aggregator-0.1.4/src/equity_aggregator/domain/_utils/_merge_config.py +205 -0
  71. equity_aggregator-0.1.4/src/equity_aggregator/domain/_utils/_strategies.py +180 -0
  72. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/resolve.py +17 -11
  73. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/runner.py +4 -4
  74. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/seed.py +5 -1
  75. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/transforms/__init__.py +2 -2
  76. equity_aggregator-0.1.4/src/equity_aggregator/domain/pipeline/transforms/enrich.py +467 -0
  77. equity_aggregator-0.1.4/src/equity_aggregator/domain/pipeline/transforms/group.py +48 -0
  78. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/logging_config.py +4 -1
  79. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/__init__.py +11 -5
  80. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/canonical.py +11 -6
  81. equity_aggregator-0.1.4/src/equity_aggregator/schemas/feeds/__init__.py +23 -0
  82. equity_aggregator-0.1.4/src/equity_aggregator/schemas/feeds/gleif_feed_data.py +35 -0
  83. equity_aggregator-0.1.4/src/equity_aggregator/schemas/feeds/intrinio_feed_data.py +142 -0
  84. equity_aggregator-0.1.1/src/equity_aggregator/schemas/feeds/lse_feed_data.py → equity_aggregator-0.1.4/src/equity_aggregator/schemas/feeds/lseg_feed_data.py +85 -52
  85. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/feeds/sec_feed_data.py +36 -6
  86. equity_aggregator-0.1.4/src/equity_aggregator/schemas/feeds/stock_analysis_feed_data.py +107 -0
  87. equity_aggregator-0.1.4/src/equity_aggregator/schemas/feeds/tradingview_feed_data.py +144 -0
  88. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/feeds/xetra_feed_data.py +1 -1
  89. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/feeds/yfinance_feed_data.py +47 -35
  90. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/raw.py +5 -3
  91. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/types.py +7 -0
  92. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/validators.py +81 -27
  93. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/storage/data_store.py +5 -3
  94. equity_aggregator-0.1.4/tests/live/adapters/__init__.py +1 -0
  95. equity_aggregator-0.1.4/tests/live/adapters/data_sources/__init__.py +1 -0
  96. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/__init__.py +1 -0
  97. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/intrinio/__init__.py +1 -0
  98. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/intrinio/test_intrinio.py +73 -0
  99. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/lseg/__init__.py +1 -0
  100. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/lseg/test_lseg.py +299 -0
  101. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/sec/__init__.py +1 -0
  102. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/sec/test_sec.py +189 -0
  103. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/stock_analysis/__init__.py +1 -0
  104. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/stock_analysis/test_stock_analysis.py +260 -0
  105. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/tradingview/__init__.py +1 -0
  106. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/tradingview/test_tradingview.py +332 -0
  107. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/xetra/__init__.py +1 -0
  108. equity_aggregator-0.1.4/tests/live/adapters/data_sources/discovery_feeds/xetra/test_xetra.py +259 -0
  109. equity_aggregator-0.1.4/tests/live/adapters/data_sources/enrichment_feeds/__init__.py +1 -0
  110. equity_aggregator-0.1.4/tests/live/adapters/data_sources/enrichment_feeds/yfinance/__init__.py +1 -0
  111. equity_aggregator-0.1.4/tests/live/adapters/data_sources/enrichment_feeds/yfinance/test_yfinance.py +247 -0
  112. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/__init__.py +13 -0
  113. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/intrinio/__init__.py +1 -0
  114. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/__init__.py +1 -0
  115. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/test_backoff.py +66 -0
  116. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/test_parser.py +213 -0
  117. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/intrinio/test_intrinio.py +573 -0
  118. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/intrinio/test_session.py +409 -0
  119. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/lseg/__init__.py +1 -0
  120. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/__init__.py +1 -0
  121. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/test_backoff.py +66 -0
  122. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/test_parser.py +395 -0
  123. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/lseg/test_lseg.py +567 -0
  124. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/lseg/test_session.py +338 -0
  125. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/sec/__init__.py +1 -0
  126. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/authoritative_feeds → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/sec}/test_sec.py +11 -15
  127. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/stock_analysis/test_stock_analysis.py +394 -0
  128. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/tradingview/__init__.py +1 -0
  129. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/tradingview/test_tradingview.py +625 -0
  130. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/xetra/__init__.py +1 -0
  131. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/authoritative_feeds → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds/xetra}/test_xetra.py +2 -2
  132. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/gleif/__init__.py +1 -0
  133. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/gleif/_helpers.py +22 -0
  134. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_api.py +215 -0
  135. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_download.py +245 -0
  136. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_gleif.py +598 -0
  137. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_parser.py +310 -0
  138. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_test_utils → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils}/test_backoff.py +2 -2
  139. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_test_utils → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils}/test_fuzzy.py +18 -18
  140. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/test_json.py +107 -0
  141. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api/test_quote_summary.py +202 -0
  142. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_test_api → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api}/test_search.py +14 -45
  143. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_auth.py +321 -0
  144. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_config.py +9 -4
  145. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_ranking.py +200 -0
  146. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_session.py +494 -0
  147. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_transport.py +384 -0
  148. equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_yfinance.py +968 -0
  149. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/adapters/data_sources/reference_lookup/test_exchange_rate_api.py +2 -2
  150. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/adapters/data_sources/reference_lookup/test_openfigi.py +3 -3
  151. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/cli/test_dispatcher.py +47 -24
  152. equity_aggregator-0.1.4/tests/unit/cli/test_main.py +304 -0
  153. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/domain/_utils/test__merge.py +330 -12
  154. equity_aggregator-0.1.4/tests/unit/domain/_utils/test__merge_config.py +319 -0
  155. equity_aggregator-0.1.4/tests/unit/domain/_utils/test__strategies.py +294 -0
  156. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/domain/_utils/test_load_converter.py +149 -7
  157. equity_aggregator-0.1.4/tests/unit/domain/pipeline/transforms/test_convert.py +277 -0
  158. equity_aggregator-0.1.4/tests/unit/domain/pipeline/transforms/test_enrich.py +842 -0
  159. equity_aggregator-0.1.4/tests/unit/domain/pipeline/transforms/test_group.py +98 -0
  160. equity_aggregator-0.1.4/tests/unit/domain/pipeline/transforms/test_parse.py +270 -0
  161. equity_aggregator-0.1.4/tests/unit/schemas/feeds/test_gleif_feed_data.py +180 -0
  162. equity_aggregator-0.1.4/tests/unit/schemas/feeds/test_intrinio_feed_data.py +504 -0
  163. equity_aggregator-0.1.1/tests/unit/schemas/feeds/test_lse_feed_data.py → equity_aggregator-0.1.4/tests/unit/schemas/feeds/test_lseg_feed_data.py +43 -76
  164. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/schemas/feeds/test_sec_feed_data.py +26 -4
  165. equity_aggregator-0.1.4/tests/unit/schemas/feeds/test_stock_analysis_feed_data.py +444 -0
  166. equity_aggregator-0.1.4/tests/unit/schemas/feeds/test_tradingview_feed_data.py +569 -0
  167. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/schemas/test_raw.py +66 -4
  168. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/schemas/test_validators.py +209 -4
  169. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/uv.lock +71 -68
  170. equity_aggregator-0.1.1/.claude/settings.local.json +0 -9
  171. equity_aggregator-0.1.1/documentation/reference_data/capedge_equity.json +0 -80
  172. equity_aggregator-0.1.1/documentation/reference_data/euronext_equities.json +0 -8661
  173. equity_aggregator-0.1.1/documentation/reference_data/lse_equities.json +0 -13226
  174. equity_aggregator-0.1.1/documentation/reference_data/yfinance_equity.json +0 -6357
  175. equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/authoritative_feeds/__init__.py +0 -13
  176. equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/authoritative_feeds/euronext.py +0 -420
  177. equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/authoritative_feeds/lse.py +0 -352
  178. equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/__init__.py +0 -5
  179. equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/feed.py +0 -350
  180. equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/session.py +0 -376
  181. equity_aggregator-0.1.1/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/utils/__init__.py +0 -9
  182. equity_aggregator-0.1.1/src/equity_aggregator/domain/_utils/__init__.py +0 -6
  183. equity_aggregator-0.1.1/src/equity_aggregator/domain/_utils/_merge.py +0 -459
  184. equity_aggregator-0.1.1/src/equity_aggregator/domain/pipeline/transforms/deduplicate.py +0 -54
  185. equity_aggregator-0.1.1/src/equity_aggregator/domain/pipeline/transforms/enrich.py +0 -424
  186. equity_aggregator-0.1.1/src/equity_aggregator/schemas/feeds/__init__.py +0 -17
  187. equity_aggregator-0.1.1/src/equity_aggregator/schemas/feeds/euronext_feed_data.py +0 -59
  188. equity_aggregator-0.1.1/tests/live/test_exchanges.py +0 -126
  189. equity_aggregator-0.1.1/tests/unit/adapters/data_sources/authoritative_feeds/test_euronext.py +0 -640
  190. equity_aggregator-0.1.1/tests/unit/adapters/data_sources/authoritative_feeds/test_lse.py +0 -386
  191. equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_test_api/test_summary.py +0 -245
  192. equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_feed.py +0 -604
  193. equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_session.py +0 -277
  194. equity_aggregator-0.1.1/tests/unit/cli/test_main.py +0 -222
  195. equity_aggregator-0.1.1/tests/unit/domain/pipeline/test_runner.py +0 -85
  196. equity_aggregator-0.1.1/tests/unit/domain/pipeline/test_seed.py +0 -18
  197. equity_aggregator-0.1.1/tests/unit/domain/pipeline/transforms/test_convert.py +0 -132
  198. equity_aggregator-0.1.1/tests/unit/domain/pipeline/transforms/test_deduplicate.py +0 -78
  199. equity_aggregator-0.1.1/tests/unit/domain/pipeline/transforms/test_enrich.py +0 -712
  200. equity_aggregator-0.1.1/tests/unit/domain/pipeline/transforms/test_parse.py +0 -431
  201. equity_aggregator-0.1.1/tests/unit/schemas/feeds/test_euronext_feed_data.py +0 -282
  202. equity_aggregator-0.1.1/tests/unit/storage/__init__.py +0 -0
  203. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/.dockerignore +0 -0
  204. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/.gitignore +0 -0
  205. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/.python-version +0 -0
  206. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/Dockerfile +0 -0
  207. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/LICENCE.txt +0 -0
  208. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/documentation/reference_data/intrinio_equity.json +0 -0
  209. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/documentation/reference_data/stock_analysis_equity.json +0 -0
  210. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/documentation/reference_data/tiprank_equity.json +0 -0
  211. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/documentation/reference_data/xetra_equities.json +0 -0
  212. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/__init__.py +0 -0
  213. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/_utils/__init__.py +0 -0
  214. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/adapters/data_sources/reference_lookup/__init__.py +0 -0
  215. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/cli/__init__.py +0 -0
  216. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/cli/config.py +0 -0
  217. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/__init__.py +0 -0
  218. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/__init__.py +0 -0
  219. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/transforms/canonicalise.py +1 -1
  220. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/transforms/convert.py +0 -0
  221. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/transforms/identify.py +0 -0
  222. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/pipeline/transforms/parse.py +0 -0
  223. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/retrieval/__init__.py +0 -0
  224. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/domain/retrieval/retrieval.py +0 -0
  225. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/schemas/feeds/feed_validators.py +0 -0
  226. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/storage/__init__.py +0 -0
  227. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/storage/_utils.py +0 -0
  228. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/storage/cache.py +0 -0
  229. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/storage/export.py +0 -0
  230. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/src/equity_aggregator/storage/metadata.py +0 -0
  231. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/README.md +0 -0
  232. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/__init__.py +0 -0
  233. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/conftest.py +0 -0
  234. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/live/__init__.py +0 -0
  235. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/__init__.py +0 -0
  236. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/adapters/__init__.py +0 -0
  237. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/adapters/_utils/__init__.py +0 -0
  238. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/adapters/_utils/test_client.py +0 -0
  239. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/discovery_feeds}/__init__.py +0 -0
  240. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/authoritative_feeds → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds}/__init__.py +0 -0
  241. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance}/__init__.py +0 -0
  242. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_helpers.py +0 -0
  243. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils}/__init__.py +0 -0
  244. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_test_api → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api}/__init__.py +0 -0
  245. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_test_utils → equity_aggregator-0.1.4/tests/unit/adapters/data_sources/reference_lookup}/__init__.py +0 -0
  246. {equity_aggregator-0.1.1/tests/unit/adapters/data_sources/reference_lookup → equity_aggregator-0.1.4/tests/unit/cli}/__init__.py +0 -0
  247. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/cli/test_config.py +0 -0
  248. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/cli/test_parser.py +0 -0
  249. {equity_aggregator-0.1.1/tests/unit/cli → equity_aggregator-0.1.4/tests/unit/domain}/__init__.py +0 -0
  250. {equity_aggregator-0.1.1/tests/unit/domain → equity_aggregator-0.1.4/tests/unit/domain/_utils}/__init__.py +0 -0
  251. {equity_aggregator-0.1.1/tests/unit/domain/_utils → equity_aggregator-0.1.4/tests/unit/domain/pipeline}/__init__.py +0 -0
  252. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/domain/pipeline/test_resolve.py +0 -0
  253. {equity_aggregator-0.1.1/tests/unit/domain/pipeline → equity_aggregator-0.1.4/tests/unit/domain/pipeline/transforms}/__init__.py +0 -0
  254. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/domain/pipeline/transforms/test_canonicalise.py +0 -0
  255. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/domain/pipeline/transforms/test_identify.py +0 -0
  256. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/domain/retrieval/test_retrieval.py +0 -0
  257. {equity_aggregator-0.1.1/tests/unit/domain/pipeline/transforms → equity_aggregator-0.1.4/tests/unit/schemas}/__init__.py +0 -0
  258. {equity_aggregator-0.1.1/tests/unit/schemas → equity_aggregator-0.1.4/tests/unit/schemas/feeds}/__init__.py +0 -0
  259. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/schemas/feeds/test_feed_validators.py +0 -0
  260. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/schemas/feeds/test_xetra_feed_data.py +0 -0
  261. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/schemas/feeds/test_yfinance_feed_data.py +0 -0
  262. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/schemas/test_canonical.py +0 -0
  263. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/schemas/test_types.py +0 -0
  264. {equity_aggregator-0.1.1/tests/unit/schemas/feeds → equity_aggregator-0.1.4/tests/unit/storage}/__init__.py +0 -0
  265. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/storage/test__utils.py +0 -0
  266. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/storage/test_cache.py +0 -0
  267. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/storage/test_data_store.py +0 -0
  268. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/storage/test_export.py +0 -0
  269. {equity_aggregator-0.1.1 → equity_aggregator-0.1.4}/tests/unit/storage/test_metadata.py +0 -0
@@ -15,7 +15,7 @@ CACHE_TTL_MINUTES=1440
15
15
  # Optional database storage location (defaults to system log directory)
16
16
  DATA_STORE_DIR=
17
17
 
18
- # authoritative and enrichment feed api keys
18
+ # discovery and enrichment feed api keys
19
19
  EXCHANGE_RATE_API_KEY=
20
20
  OPENFIGI_API_KEY=
21
21
  INTRINIO_API_KEY=
@@ -44,6 +44,11 @@ jobs:
44
44
  chmod 600 .env
45
45
  test -s .env || { echo "::error ::empty .env"; exit 1; }
46
46
 
47
+ - name: Run live sanity tests
48
+ env:
49
+ UV_ENV_FILE: ".env"
50
+ run: uv run pytest -m live -v
51
+
47
52
  - name: Run Equity Aggregator
48
53
  env:
49
54
  UV_ENV_FILE: ".env"
@@ -55,6 +60,19 @@ jobs:
55
60
  uv run equity-aggregator --verbose seed
56
61
  uv run equity-aggregator export --output-dir ./data/data_store
57
62
 
63
+ - name: Get latest log file
64
+ id: latest_log
65
+ run: |
66
+ LATEST_LOG=$(ls -t data/logs/equity_aggregator_*.log | head -1)
67
+ echo "latest_log=$LATEST_LOG" >> $GITHUB_OUTPUT
68
+
69
+ - name: Delete existing release
70
+ run: |
71
+ gh release delete latest-build-release --yes || true
72
+ git push --delete origin latest-build-release || true
73
+ env:
74
+ GH_TOKEN: ${{ github.token }}
75
+
58
76
  - name: Publish Latest Canonical Equities Release
59
77
  uses: softprops/action-gh-release@v2
60
78
  with:
@@ -66,4 +84,4 @@ jobs:
66
84
  generate_release_notes: false
67
85
  files: |
68
86
  data/data_store/canonical_equities.jsonl.gz
69
- data/logs/equity_aggregator_*.log
87
+ ${{ steps.latest_log.outputs.latest_log }}
@@ -0,0 +1,103 @@
1
+ name: publish-pypi
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows: ["validate-push"]
6
+ types:
7
+ - completed
8
+ branches: [master]
9
+
10
+ permissions:
11
+ contents: write
12
+
13
+ concurrency:
14
+ group: publish-pypi
15
+ cancel-in-progress: false
16
+
17
+ jobs:
18
+ check:
19
+ runs-on: ubuntu-latest
20
+ if: >
21
+ github.event.workflow_run.conclusion == 'success' &&
22
+ github.actor != 'github-actions[bot]'
23
+ outputs:
24
+ should_publish: ${{ steps.check_commit.outputs.should_publish }}
25
+ steps:
26
+ - name: Checkout repository
27
+ uses: actions/checkout@v4
28
+ with:
29
+ fetch-depth: 1
30
+
31
+ - name: Check if last commit is version bump
32
+ id: check_commit
33
+ run: |
34
+ LAST_COMMIT_MSG=$(git log -1 --pretty=%B)
35
+ if [[ "$LAST_COMMIT_MSG" == *"chore: bump version"* ]]; then
36
+ echo "should_publish=false" >> $GITHUB_OUTPUT
37
+ else
38
+ echo "should_publish=true" >> $GITHUB_OUTPUT
39
+ fi
40
+
41
+ publish:
42
+ needs: check
43
+ if: needs.check.outputs.should_publish == 'true'
44
+ runs-on: ubuntu-latest
45
+ env:
46
+ UV_SYSTEM_PYTHON: 1
47
+ steps:
48
+ - name: Checkout repository
49
+ uses: actions/checkout@v4
50
+ with:
51
+ fetch-depth: 0
52
+ token: ${{ secrets.EQUITY_AGGREGATOR }}
53
+
54
+ - name: Set up Python
55
+ uses: actions/setup-python@v5
56
+ with:
57
+ python-version-file: ".python-version"
58
+
59
+ - name: Install uv (with cache)
60
+ uses: astral-sh/setup-uv@v6
61
+ with:
62
+ version: "latest"
63
+ enable-cache: true
64
+ cache-dependency-glob: |
65
+ **/pyproject.toml
66
+ **/uv.lock
67
+
68
+ - name: Sync environment
69
+ run: uv sync --locked
70
+
71
+ - name: Bump patch version
72
+ id: bump_version
73
+ run: |
74
+ CURRENT_VERSION=$(sed -n '3p' pyproject.toml | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
75
+ IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
76
+ NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
77
+ sed -i "3s/.*/version = \"$NEW_VERSION\"/" pyproject.toml
78
+ echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
79
+
80
+ - name: Configure git
81
+ run: |
82
+ git config user.name "github-actions[bot]"
83
+ git config user.email "github-actions[bot]@users.noreply.github.com"
84
+
85
+ - name: Commit and tag version bump
86
+ run: |
87
+ git add pyproject.toml
88
+ git commit -m "chore: bump version to ${{ steps.bump_version.outputs.new_version }} [skip ci]"
89
+ git tag "v${{ steps.bump_version.outputs.new_version }}"
90
+
91
+ - name: Push changes
92
+ run: |
93
+ git push origin master
94
+ git push origin "v${{ steps.bump_version.outputs.new_version }}"
95
+
96
+ - name: Build package
97
+ run: uv build
98
+
99
+ - name: Publish to PyPI
100
+ uses: pypa/gh-action-pypi-publish@release/v1
101
+ with:
102
+ password: ${{ secrets.PYPI }}
103
+ attestations: false
@@ -60,7 +60,7 @@ jobs:
60
60
  if: success()
61
61
  uses: schneegans/dynamic-badges-action@v1.7.0
62
62
  with:
63
- auth: ${{ secrets.GIST_SECRET }}
63
+ auth: ${{ secrets.GIST_AUTH }}
64
64
  gistID: ce6ce2d7e3c247c34aba66dedcd7ede3
65
65
  filename: coverage-badge.json
66
66
  label: Coverage
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: equity-aggregator
3
- Version: 0.1.1
3
+ Version: 0.1.4
4
4
  Summary: Financial equity data aggregation toolkit
5
5
  Project-URL: Homepage, https://github.com/gregorykelleher/equity-aggregator
6
6
  Project-URL: Repository, https://github.com/gregorykelleher/equity-aggregator
@@ -18,13 +18,6 @@ Requires-Dist: openfigipy>=0.1.6
18
18
  Requires-Dist: platformdirs>=4.0.0
19
19
  Requires-Dist: pydantic>=2.11.3
20
20
  Requires-Dist: rapidfuzz>=3.13.0
21
- Provides-Extra: dev
22
- Requires-Dist: pytest-asyncio>=1.0.0; extra == 'dev'
23
- Requires-Dist: pytest-cov>=6.2.0; extra == 'dev'
24
- Requires-Dist: pytest-env>=1.1.5; extra == 'dev'
25
- Requires-Dist: pytest-timeout>=2.4.0; extra == 'dev'
26
- Requires-Dist: pytest>=8.3.5; extra == 'dev'
27
- Requires-Dist: ruff>=0.8.0; extra == 'dev'
28
21
  Description-Content-Type: text/markdown
29
22
 
30
23
  # Equity Aggregator
@@ -34,20 +27,34 @@ Description-Content-Type: text/markdown
34
27
  [![Licence](https://img.shields.io/badge/license-MIT-green)](LICENCE.txt)
35
28
  [![Validation Status](https://img.shields.io/github/actions/workflow/status/gregorykelleher/equity-aggregator/validate-push.yml?branch=master&label=build)](https://github.com/gregorykelleher/equity-aggregator/actions/workflows/validate-push.yml)
36
29
  [![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/gregorykelleher/ce6ce2d7e3c247c34aba66dedcd7ede3/raw/coverage-badge.json)](https://github.com/gregorykelleher/equity-aggregator/actions/workflows/validate-push.yml)
37
- [![CodeFactor](https://www.codefactor.io/repository/github/gregorykelleher/equity-aggregator/badge/master)](https://www.codefactor.io/repository/github/gregorykelleher/equity-aggregator/overview/master)
38
30
 
39
31
  ## Description
40
32
 
41
- Equity Aggregator is a financial data tool that collects and normalises raw equity data from authoritative sources (Euronext, LSE, SEC, XETRA), before enriching it with third-party market vendor data to produce a unified canonical dataset of unique equities.
33
+ Equity Aggregator is a financial data tool that collects and normalises raw equity data from discovery sources (Intrinio, LSEG, SEC, XETRA, Stock Analysis, TradingView), before enriching it with third-party market vendor data from enrichment feeds (Yahoo Finance and Global LEI Foundation) to produce a unified canonical dataset of unique equities.
42
34
 
43
- Altogether, this tool makes it possible to retrieve up-to-date information on over 9,500+ equities from ten countries worldwide:
35
+ Altogether, this tool makes it possible to retrieve up-to-date information on over 15,000+ equities from countries worldwide.
44
36
 
45
- | Source | Country | Description |
37
+ ### Discovery Feeds
38
+
39
+ Discovery feeds provide raw equity data from primary market sources:
40
+
41
+ | Source | Coverage | Description |
46
42
  |----------|---------|-------------|
47
- | 🇪🇺&nbsp;Euronext | Europe | Pan-European stock exchange operating in Netherlands, France, Belgium, Portugal, Ireland, and Norway |
48
- | 🇬🇧 LSE | United Kingdom | London Stock Exchange |
49
- | 🇺🇸 SEC | United States | Securities and Exchange Commission |
50
- | 🇩🇪 XETRA | Germany | Deutsche Börse electronic trading platform |
43
+ | 🇺🇸 Intrinio | United States | Intrinio - US-listed equities |
44
+ | 🇬🇧 LSEG | International | London Stock Exchange Group - Global equities |
45
+ | 🇺🇸 SEC | United States | Securities and Exchange Commission - US-listed equities |
46
+ | 🇺🇸 Stock Analysis | United States | Stock Analysis - Global equities |
47
+ | 🇺🇸 TradingView | United States | TradingView - US-listed equities |
48
+ | 🇩🇪 XETRA | Germany | Deutsche Börse electronic trading platform - Global listed equities |
49
+
50
+ ### Enrichment Feeds
51
+
52
+ Enrichment feeds provide supplementary data to enhance the canonical equity dataset:
53
+
54
+ | Source | Description |
55
+ |--------|-------------|
56
+ | Yahoo Finance | Market data, financial metrics, and equity metadata |
57
+ | GLEIF | Legal Entity Identifier (LEI) lookups via the Global LEI Foundation |
51
58
 
52
59
  ## What kind of Equity Data is available?
53
60
 
@@ -58,10 +65,11 @@ Equity Aggregator provides a comprehensive profile for each equity in its canoni
58
65
  |-------|-------------|
59
66
  | **name** | Full company name |
60
67
  | **symbol** | Trading symbol |
61
- | **share class figi** | Authoritative OpenFIGI identifier |
68
+ | **share class figi** | Definitive OpenFIGI identifier |
62
69
  | **isin** | International Securities Identification Number |
63
70
  | **cusip** | CUSIP identifier |
64
71
  | **cik** | Central Index Key for SEC filings |
72
+ | **lei** | Legal Entity Identifier (ISO 17442) |
65
73
 
66
74
  ### Financial Metrics
67
75
  | Category | Fields |
@@ -79,7 +87,7 @@ Equity Aggregator provides a comprehensive profile for each equity in its canoni
79
87
  | **Classification** | `industry`, `sector`, `analyst_rating` |
80
88
 
81
89
  > [!NOTE]
82
- > The OpenFIGI Share Class FIGI is the only definitive unique identifier for each equity in this dataset. While other identifiers like ISIN, CUSIP, and CIK are also collected, they may not be universally available across all global markets or may have inconsistencies in formatting and coverage.
90
+ > The OpenFIGI Share Class FIGI is the only definitive unique identifier for each equity in this dataset. While other identifiers like ISIN, CUSIP, CIK and LEI are also collected, they may not be universally available across all global markets or may have inconsistencies in formatting and coverage.
83
91
  >
84
92
  > OpenFIGI provides standardised, globally unique identifiers that work consistently across all equity markets and exchanges, hence its selection for Equity Aggregator.
85
93
 
@@ -93,91 +101,9 @@ Equity Aggregator is available to download via `pip` as the `equity-aggregator`
93
101
  pip install equity-aggregator
94
102
  ```
95
103
 
96
- ### CLI Usage
97
-
98
- Once installed, Equity Aggregator provides a comprehensive command-line interface for managing equity data operations. The CLI offers three main commands:
99
-
100
- - **seed** - Aggregate and populate the local database with fresh equity data
101
- - **export** - Export the local canonical equity database to compressed JSONL format
102
- - **download** - Download the latest canonical equity data from remote repository
103
-
104
- Run `equity-aggregator --help` for more information:
105
-
106
- ```bash
107
- usage: equity-aggregator [-h] [-v] [-d] [-q] {seed,export,download} ...
108
-
109
- aggregate, download, and export canonical equity data
110
-
111
- options:
112
- -h, --help show this help message and exit
113
- -v, --verbose enable verbose logging (INFO level)
114
- -d, --debug enable debug logging (DEBUG level)
115
- -q, --quiet quiet mode - only show warnings and errors
116
-
117
- commands:
118
- Available operations
119
-
120
- {seed,export,download}
121
- seed aggregate enriched canonical equity data sourced from data feeds
122
- export export local canonical equity data to compressed JSONL format
123
- download download latest canonical equity data from remote repository
124
-
125
- Use 'equity-aggregator <command> --help' for help
126
- ```
127
-
128
- #### Download Command
129
-
130
- The `download` command retrieves the latest pre-processed canonical equity dataset from GitHub Releases, eliminating the need to run the full aggregation pipeline via `seed` locally. This command:
131
-
132
- - Downloads compressed equity data (`canonical_equities.jsonl.gz`) from the latest nightly build
133
- - Automatically rebuilds the database locally from the downloaded data
134
- - Provides access to 9,500+ equities with immediate effect
135
-
136
- > [!TIP]
137
- > **Optional: Increase Rate Limits**
138
- >
139
- > Set `GITHUB_TOKEN` to increase download limits from 60/hour to 5,000/hour:
140
- > ```bash
141
- > export GITHUB_TOKEN="your_personal_access_token_here"
142
- > ```
143
- > Create a token at [GitHub Settings](https://github.com/settings/tokens) - no special scopes needed. Recommended for frequent downloads or CI/CD pipelines.
144
-
145
- #### Export Command
146
-
147
- The `export` command extracts canonical equity data from the local database and exports it as compressed JSONL (JSON Lines) format. It reads all canonical equities from the local database and exports the data to `canonical_equities.jsonl.gz` in the specified output directory.
148
-
149
- This creates a portable, standardised dataset suitable for analysis, sharing, or backup while preserving all equity metadata and financial metrics in structured JSON format.
150
-
151
- ```bash
152
- # Export aggregated data to compressed JSON in specified directory
153
- equity-aggregator export --output-dir ~/Downloads
154
- equity-aggregator export --output-dir /path/to/export/location
155
- ```
156
-
157
- #### Seed Command
158
-
159
- The `seed` command executes the complete equity aggregation pipeline, collecting raw data from authoritative sources (Euronext, LSE, SEC, XETRA), enriching it with market data from enrichment feeds, and storing the processed results in the local database. This command runs the full transformation pipeline to create a fresh canonical equity dataset.
160
-
161
- This command requires that the following API keys are set prior:
162
-
163
- ```bash
164
- export EXCHANGE_RATE_API_KEY="your_key_here"
165
- export OPENFIGI_API_KEY="your_key_here"
166
- ```
167
-
168
- ```bash
169
- # Run the main aggregation pipeline (requires API keys)
170
- equity-aggregator seed
171
- ```
104
+ ### Python API
172
105
 
173
- > [!IMPORTANT]
174
- > Note that the `seed` command processes thousands of equities and is intentionally rate-limited to respect external API constraints. A full run typically takes 90 minutes depending on network conditions and API response times.
175
- >
176
- > This is mitigated by the automated nightly CI pipeline that runs `seed` and publishes the latest canonical equity dataset. Users can download this pre-built data using `equity-aggregator download` instead of running the full aggregation pipeline locally.
177
-
178
- ### Python API Integration
179
-
180
- Beyond the CLI, Equity Aggregator also exposes a focused public API that enables seamless integration opportunities. The API automatically detects and downloads the latest canonical equity dataset from remote sources when needed, ensuring users always work with up-to-date data.
106
+ Equity Aggregator exposes a focused public API that enables seamless integration opportunities. The API automatically detects and downloads the latest canonical equity dataset from remote sources when needed, ensuring users always work with up-to-date data.
181
107
 
182
108
  #### Retrieving All Equities
183
109
 
@@ -197,7 +123,7 @@ for equity in equities[:3]: # Show first 3
197
123
 
198
124
  **Example Output:**
199
125
  ```
200
- Retrieved 9547 canonical equities
126
+ Retrieved 10000 canonical equities
201
127
  AAPL: APPLE INC
202
128
  MSFT: MICROSOFT CORP
203
129
  GOOGL: ALPHABET INC
@@ -260,6 +186,88 @@ Market Cap: 3500000000000
260
186
  > [!NOTE]
261
187
  > Both functions work independently - `retrieve_canonical_equity()` automatically downloads data if needed, so there's no requirement to call `retrieve_canonical_equities()` first.
262
188
 
189
+ ### CLI Usage
190
+
191
+ Once installed, Equity Aggregator provides a comprehensive command-line interface for managing equity data operations. The CLI offers three main commands:
192
+
193
+ - **seed** - Aggregate and populate the local database with fresh equity data
194
+ - **export** - Export the local canonical equity database to compressed JSONL format
195
+ - **download** - Download the latest canonical equity data from remote repository
196
+
197
+ Run `equity-aggregator --help` for more information:
198
+
199
+ ```bash
200
+ usage: equity-aggregator [-h] [-v] [-d] [-q] {seed,export,download} ...
201
+
202
+ aggregate, download, and export canonical equity data
203
+
204
+ options:
205
+ -h, --help show this help message and exit
206
+ -v, --verbose enable verbose logging (INFO level)
207
+ -d, --debug enable debug logging (DEBUG level)
208
+ -q, --quiet quiet mode - only show warnings and errors
209
+
210
+ commands:
211
+ Available operations
212
+
213
+ {seed,export,download}
214
+ seed aggregate enriched canonical equity data sourced from data feeds
215
+ export export local canonical equity data to compressed JSONL format
216
+ download download latest canonical equity data from remote repository
217
+
218
+ Use 'equity-aggregator <command> --help' for help
219
+ ```
220
+
221
+ #### Download Command
222
+
223
+ The `download` command retrieves the latest pre-processed canonical equity dataset from GitHub Releases, eliminating the need to run the full aggregation pipeline via `seed` locally. This command:
224
+
225
+ - Downloads compressed equity data (`canonical_equities.jsonl.gz`) from the latest nightly build
226
+ - Automatically rebuilds the database locally from the downloaded data
227
+ - Provides access to 15,000+ equities with immediate effect
228
+
229
+ > [!TIP]
230
+ > **Optional: Increase Rate Limits**
231
+ >
232
+ > Set `GITHUB_TOKEN` to increase download limits from 60/hour to 5,000/hour:
233
+ > ```bash
234
+ > export GITHUB_TOKEN="your_personal_access_token_here"
235
+ > ```
236
+ > Create a token at [GitHub Settings](https://github.com/settings/tokens) - no special scopes needed. Recommended for frequent downloads or CI/CD pipelines.
237
+
238
+ #### Export Command
239
+
240
+ The `export` command extracts canonical equity data from the local database and exports it as compressed JSONL (JSON Lines) format. It reads all canonical equities from the local database and exports the data to `canonical_equities.jsonl.gz` in the specified output directory.
241
+
242
+ This creates a portable, standardised dataset suitable for analysis, sharing, or backup while preserving all equity metadata and financial metrics in structured JSON format.
243
+
244
+ ```bash
245
+ # Export aggregated data to compressed JSON in specified directory
246
+ equity-aggregator export --output-dir ~/Downloads
247
+ equity-aggregator export --output-dir /path/to/export/location
248
+ ```
249
+
250
+ #### Seed Command
251
+
252
+ The `seed` command executes the complete equity aggregation pipeline, collecting raw data from discovery sources (LSEG, SEC, XETRA, Stock Analysis, TradingView), enriching it with market data from enrichment feeds, and storing the processed results in the local database. This command runs the full transformation pipeline to create a fresh canonical equity dataset.
253
+
254
+ This command requires that the following API keys are set prior:
255
+
256
+ ```bash
257
+ export EXCHANGE_RATE_API_KEY="your_key_here"
258
+ export OPENFIGI_API_KEY="your_key_here"
259
+ ```
260
+
261
+ ```bash
262
+ # Run the main aggregation pipeline (requires API keys)
263
+ equity-aggregator seed
264
+ ```
265
+
266
+ > [!IMPORTANT]
267
+ > Note that the `seed` command processes thousands of equities and is intentionally rate-limited to respect external API constraints. A full run typically takes 60 minutes depending on network conditions and API response times.
268
+ >
269
+ > This is mitigated by the automated nightly CI pipeline that runs `seed` and publishes the latest canonical equity dataset. Users can download this pre-built data using `equity-aggregator download` instead of running the full aggregation pipeline locally.
270
+
263
271
  ### Data Storage
264
272
 
265
273
  Equity Aggregator automatically stores its database (i.e. `data_store.db`) in system-appropriate locations using platform-specific directories:
@@ -339,9 +347,9 @@ cp .env_example .env
339
347
 
340
348
  #### Optional Keys:
341
349
 
342
- - `INTRINIO_API_KEY` - For additional data enrichment
350
+ - `INTRINIO_API_KEY` - For Intrinio discovery feed
343
351
  - Retrieve from: [Intrinio](https://intrinio.com/)
344
- - Provides supplementary equity enrichment data
352
+ - Provides US equity data with comprehensive quote information
345
353
 
346
354
  - `GITHUB_TOKEN` - For increased GitHub API rate limits
347
355
  - Retrieve from: [GitHub Settings](https://github.com/settings/tokens)
@@ -440,7 +448,7 @@ docker compose exec equity-aggregator bash
440
448
  ```
441
449
 
442
450
  > [!NOTE]
443
- > The Docker container mounts the `data/` directory as a volume for persistent database storage.
451
+ > The Docker setup uses named volumes for persistent database storage and automatically handles all directory creation and permissions.
444
452
 
445
453
  ## Architecture
446
454
 
@@ -455,8 +463,8 @@ equity-aggregator/
455
463
  │ ├── domain/pipeline/ # Core aggregation pipeline
456
464
  │ │ └── transforms/ # Transformation stages
457
465
  │ ├── adapters/data_sources/ # External data integrations
458
- │ │ ├── authoritative_feeds/ # Primary sources (Euronext, LSE, SEC, XETRA)
459
- │ │ └── enrichment_feeds/ # Yahoo Finance integration
466
+ │ │ ├── discovery_feeds/ # Primary sources (Intrinio, LSEG, SEC, Stock Analysis, TradingView, XETRA)
467
+ │ │ └── enrichment_feeds/ # Enrichment feed integrations (Yahoo Finance)
460
468
  │ ├── schemas/ # Data validation and types
461
469
  │ └── storage/ # Database operations
462
470
  ├── data/ # Database and cache
@@ -465,15 +473,29 @@ equity-aggregator/
465
473
  └── pyproject.toml # Project metadata and dependencies
466
474
  ```
467
475
 
476
+ ### Project Dependencies (Production)
477
+
478
+ The dependency listing is intentionally minimal, relying only on the following core packages:
479
+
480
+ | Dependency | Use case |
481
+ |------------|----------|
482
+ | pydantic | Type-safe models and validation for data |
483
+ | rapidfuzz | Fast fuzzy matching to reconcile data sourced by multiple data feeds |
484
+ | httpx | HTTP client with HTTP/2 support for data feed retrieval |
485
+ | openfigipy | OpenFIGI integration that anchors equities to a definitive identifier |
486
+ | platformdirs | Consistent storage paths for caches, logs, and data stores on every OS |
487
+
488
+ Keeping such a small set of dependencies reduces upgrade risk and maintenance costs, whilst still providing all the functionality required for comprehensive equity data aggregation and processing.
489
+
468
490
  ### Data Transformation Pipeline
469
491
 
470
492
  The aggregation pipeline consists of six sequential transformation stages, each with a specific responsibility:
471
493
 
472
- 1. **Parse**: Extract and validate raw equity data from authorative feed data
494
+ 1. **Parse**: Extract and validate raw equity data from discovery feed data
473
495
  2. **Convert**: Normalise currency values to USD reference currency using live exchange rates
474
- 3. **Identify**: Attach authoritative identification metadata (i.e. Share Class FIGI) via OpenFIGI API integration
475
- 4. **Deduplicate**: Merge duplicate equity records predicated on Share Class FIGI
476
- 5. **Enrich**: Supplement core data with additional market metrics sourced from enrichment feeds
496
+ 3. **Identify**: Attach definitive identification metadata (i.e. Share Class FIGI) via OpenFIGI
497
+ 4. **Group**: Group equities by Share Class FIGI, preserving all discovery feed sources
498
+ 5. **Enrich**: Fetch enrichment data and perform single comprehensive merge of all sources (discovery + enrichment)
477
499
  6. **Canonicalise**: Transform enriched data into the final canonical equity schema
478
500
 
479
501
  ### Clean Architecture Layers
@@ -485,16 +507,86 @@ The codebase adheres to clean architecture principles with distinct layers:
485
507
  - **Infrastructure Layer** (`storage/`, `cli/`): Handles system concerns, regarding database operations and command-line tooling
486
508
  - **Schema Layer** (`schemas/`): Defines data contracts and validation rules using Pydantic models for type safety
487
509
 
510
+ ### Test Suites
511
+
512
+ The project maintains two distinct test suites, each serving a specific purpose in the testing strategy:
513
+
514
+ #### Unit Tests (`-m unit`)
515
+
516
+ Unit tests provide comprehensive coverage of all internal application logic. These tests are fully isolated and do not make any external network calls, ensuring fast and deterministic execution. The suite contains over 1,000 test cases and executes in under 30 seconds, enforcing a **minimum coverage threshold of 99%** with the goal of maintaining **100% coverage** across all source code.
517
+
518
+ Unit tests follow strict conventions:
519
+ - **AAA Pattern**: All tests are structured using the Arrange-Act-Assert pattern for clarity and consistency
520
+ - **Single Assertion**: Each test case contains exactly one assertion, ensuring focused and maintainable tests
521
+ - **No Mocking**: Monkey-patching and Python mocking techniques (e.g. `monkeypatch`, `unittest.mock`) are strictly forbidden, promoting testable design through dependency injection and explicit interfaces
522
+
523
+ #### Live Tests (`-m live`)
524
+
525
+ Live tests serve as **sanity tests** that validate external API endpoints are available and responding correctly. These tests hit real external services to verify that:
526
+ - Discovery and enrichment feed endpoints are accessible
527
+ - API response schemas match expected Pydantic models
528
+ - Authentication and rate limiting are functioning as expected
529
+
530
+ Live tests act as an early warning system, catching upstream API changes or outages before they impact the main aggregation pipeline.
531
+
532
+ #### Continuous Integration
533
+
534
+ Both test suites are executed as part of the GitHub Actions CI pipeline:
535
+
536
+ - **[validate-push.yml](.github/workflows/validate-push.yml)**: Runs unit tests with coverage enforcement on every push to master, ensuring code quality and the 99% coverage threshold are maintained
537
+ - **[publish-build-release.yml](.github/workflows/publish-build-release.yml)**: Runs live sanity tests before executing the nightly aggregation pipeline, validating that all external APIs are operational before publishing a new release
538
+
539
+ ## Limitations
540
+
541
+ ### Data Depth and Scope
542
+
543
+ - Equity Aggregator is intrinsically bound by the quality and coverage of its upstream discovery and enrichment feeds. Data retrieved and processed by Equity Aggregator reflects the quality and scope inherited from these data sources.
544
+
545
+ - Normalisation, outlier detection, coherency validation checks and other statistical techniques catch most upstream issues, yet occasional gaps or data aberrations can persist and should be handled defensively by downstream consumers.
546
+
547
+ ### Venue-Specific Financial Metrics and Secondary Listings
548
+
549
+ - Certain equities may be sourced solely from secondary listings (e.g. OTC Markets or cross-listings) rather than their primary exchange. This occurs when the primary venue's data is unavailable from equity-aggregator's data sources.
550
+
551
+ - Company-level metrics such as `market_cap`, `shares_outstanding`, `revenue`, and valuation ratios remain accurate regardless of sourcing venue, as they reflect the underlying company rather than the trading venue.
552
+
553
+ - However, venue-specific metrics, particularly `market_volume` reflect trading activity only on the captured venues, not _total_ market-wide volume. An equity showing low volume may simply indicate minimal OTC activity despite substantial trading on its primary exchange.
554
+
555
+ - Attention should therefore be paid to the `mics` field, indicating which Market Identifier Codes are represented in the data (i.e. whether it's the equity's primary exchange MIC or a secondary listing).
556
+
557
+ ### Data Update Cadence
558
+
559
+ - Equity Aggregator publishes nightly batch snapshots and does not aim to serve as a real-time market data service. The primary objective of Equity Aggregator is to provide equity identification metadata with limited financial metrics for fundamental analysis.
560
+
561
+ - Downstream services should therefore treat Equity Aggregator as a discovery catalogue, using its authoritative identifiers to discover equities and then poll specialised market data providers for time-sensitive pricing metrics.
562
+
563
+ - Delivering real-time quotes directly through Equity Aggregator would be infeasible because the upstream data sources enforce strict rate limits and the pipeline is network-bound; attempting live polling would exhaust quotas quickly and degrade reliability for all consumers.
564
+
565
+ ### Single Identifier Authority
566
+
567
+ - Share Class FIGI remains the authoritative identifier because OpenFIGI supplies globally unique, deduplicated mappings across discovery feeds. Other identifiers such as ISIN, CUSIP, CIK or LEI depend on regional registries, are frequently absent for specific markets, and are prone to formatting discrepancies, so they should be treated as supplementary identifiers only.
568
+
569
+ ### Performance
570
+
571
+ - The end-to-end aggregation pipeline is network-bound and respects vendor rate limits, meaning a full `seed` run can take close to an hour in steady-state conditions. This is mitigated by comprehensive caching used throughout the application, as well as the automated nightly CI pipeline that publishes the latest canonical equity dataset, made available via `download`.
572
+
573
+ ### External Service Reliance
574
+
575
+ - As the entirety of Equity Aggregator is built around the use of third-party APIs for discovery, enrichment, as well as other services, its robustness is fundamentally fragile. Upstream outages, schema shifts, bot protection revocations, API churn and rate-limit policy changes can easily degrade the pipeline without warning, with remediation often relying on vendor response times outside of the project's remit.
576
+
577
+ - As this is an inherent architectural constraint, the only viable response centres on providing robust mitigation controls. Monitoring, retry strategies and graceful degradation paths lessen the impact; they cannot eliminate the dependency risk entirely.
578
+
488
579
  ## Disclaimer
489
580
 
490
581
  > [!IMPORTANT]
491
582
  > **Important Legal Notice**
492
583
  >
493
- > This software aggregates data from various third-party sources including Yahoo Finance, Euronext, London Stock Exchange, SEC, and XETRA. Equity Aggregator is **not** affiliated, endorsed, or vetted by any of these organisations.
584
+ > This software aggregates data from various third-party sources including Intrinio, Yahoo Finance, LSEG trading platform, SEC, Stock Analysis, and XETRA. Equity Aggregator is **not** affiliated, endorsed, or vetted by any of these organisations.
494
585
  >
495
586
  > **Data Sources and Terms:**
496
587
  >
497
588
  > - **Yahoo Finance**: This tool uses Yahoo's publicly available APIs. Refer to [Yahoo!'s terms of use](https://policies.yahoo.com/us/en/yahoo/terms/product-atos/apiforydn/index.htm) for details on your rights to use the actual data downloaded. Yahoo! finance API is intended for personal use only.
589
+ > - **Intrinio**: This tool requires a valid Intrinio subscription and API key. Refer to [Intrinio's terms of use](https://about.intrinio.com/terms) for permitted usage, rate limits, and redistribution policies.
498
590
  > - **Market Data**: All market data is obtained from publicly available sources and is intended for research and educational purposes only.
499
591
  >
500
592
  > **Usage Responsibility:**
@@ -505,5 +597,3 @@ The codebase adheres to clean architecture principles with distinct layers:
505
597
  > - Users should independently verify any data before making financial decisions
506
598
  >
507
599
  > **Commercial Use:** Users intending commercial use should review and comply with the terms of service of all underlying data providers.
508
-
509
-