equity-aggregator 0.1.5__tar.gz → 0.1.7__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 (249) hide show
  1. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/.github/workflows/publish-build-release.yml +5 -1
  2. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/PKG-INFO +1 -1
  3. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/pyproject.toml +1 -1
  4. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/discovery_feeds/intrinio/test_intrinio.py +34 -22
  5. equity_aggregator-0.1.7/tests/live/adapters/data_sources/discovery_feeds/lseg/test_lseg.py +89 -0
  6. equity_aggregator-0.1.7/tests/live/adapters/data_sources/discovery_feeds/sec/test_sec.py +76 -0
  7. equity_aggregator-0.1.7/tests/live/adapters/data_sources/discovery_feeds/stock_analysis/test_stock_analysis.py +87 -0
  8. equity_aggregator-0.1.7/tests/live/adapters/data_sources/discovery_feeds/tradingview/test_tradingview.py +90 -0
  9. equity_aggregator-0.1.7/tests/live/adapters/data_sources/discovery_feeds/xetra/test_xetra.py +79 -0
  10. equity_aggregator-0.1.7/tests/live/adapters/data_sources/enrichment_feeds/gleif/test_gleif.py +81 -0
  11. equity_aggregator-0.1.7/tests/live/adapters/data_sources/enrichment_feeds/yfinance/test_yfinance.py +87 -0
  12. equity_aggregator-0.1.7/tests/live/adapters/data_sources/reference_lookup/__init__.py +1 -0
  13. equity_aggregator-0.1.7/tests/live/adapters/data_sources/reference_lookup/exchange_rate_api/__init__.py +1 -0
  14. equity_aggregator-0.1.7/tests/live/adapters/data_sources/reference_lookup/exchange_rate_api/test_exchange_rate_api.py +89 -0
  15. equity_aggregator-0.1.7/tests/live/adapters/data_sources/reference_lookup/openfigi/__init__.py +1 -0
  16. equity_aggregator-0.1.7/tests/live/adapters/data_sources/reference_lookup/openfigi/test_openfigi.py +76 -0
  17. equity_aggregator-0.1.7/tests/unit/adapters/data_sources/enrichment_feeds/gleif/__init__.py +1 -0
  18. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/uv.lock +1 -1
  19. equity_aggregator-0.1.5/tests/live/adapters/data_sources/discovery_feeds/lseg/test_lseg.py +0 -299
  20. equity_aggregator-0.1.5/tests/live/adapters/data_sources/discovery_feeds/sec/test_sec.py +0 -189
  21. equity_aggregator-0.1.5/tests/live/adapters/data_sources/discovery_feeds/stock_analysis/test_stock_analysis.py +0 -260
  22. equity_aggregator-0.1.5/tests/live/adapters/data_sources/discovery_feeds/tradingview/test_tradingview.py +0 -332
  23. equity_aggregator-0.1.5/tests/live/adapters/data_sources/discovery_feeds/xetra/test_xetra.py +0 -259
  24. equity_aggregator-0.1.5/tests/live/adapters/data_sources/enrichment_feeds/yfinance/test_yfinance.py +0 -247
  25. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/.dockerignore +0 -0
  26. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/.env_example +0 -0
  27. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/.github/workflows/publish-pypi.yml +0 -0
  28. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/.github/workflows/validate-push.yml +0 -0
  29. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/.gitignore +0 -0
  30. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/.python-version +0 -0
  31. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/Dockerfile +0 -0
  32. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/LICENCE.txt +0 -0
  33. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/README.md +0 -0
  34. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/docker-compose.yml +0 -0
  35. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/intrinio_equity.json +0 -0
  36. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/lseg_equities.json +0 -0
  37. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/sec_equity.json +0 -0
  38. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/stock_analysis_equity.json +0 -0
  39. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/tiprank_equity.json +0 -0
  40. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/tradingview_equities.json +0 -0
  41. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/xetra_equities.json +0 -0
  42. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/yfinance_quote_summary_equity.json +0 -0
  43. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/documentation/reference_data/yfinance_search_equity.json +0 -0
  44. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/examples/data_integrity_analysis.py +0 -0
  45. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/README.md +0 -0
  46. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/__init__.py +0 -0
  47. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/__init__.py +0 -0
  48. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/__init__.py +0 -0
  49. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/_utils/__init__.py +0 -0
  50. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/_utils/_client.py +0 -0
  51. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/_utils/_record_types.py +0 -0
  52. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/__init__.py +0 -0
  53. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/__init__.py +0 -0
  54. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/__init__.py +0 -0
  55. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/backoff.py +0 -0
  56. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/_utils/parser.py +0 -0
  57. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/intrinio.py +0 -0
  58. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/intrinio/session.py +0 -0
  59. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/__init__.py +0 -0
  60. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/__init__.py +0 -0
  61. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/backoff.py +0 -0
  62. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/_utils/parser.py +0 -0
  63. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/lseg.py +0 -0
  64. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/lseg/session.py +0 -0
  65. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/sec/__init__.py +0 -0
  66. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/sec/sec.py +0 -0
  67. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/stock_analysis/__init__.py +0 -0
  68. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/stock_analysis/stock_analysis.py +0 -0
  69. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/tradingview/__init__.py +0 -0
  70. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/tradingview/tradingview.py +0 -0
  71. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/xetra/__init__.py +0 -0
  72. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/discovery_feeds/xetra/xetra.py +0 -0
  73. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/__init__.py +0 -0
  74. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/__init__.py +0 -0
  75. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/api.py +0 -0
  76. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/download.py +0 -0
  77. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/gleif.py +0 -0
  78. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/gleif/parser.py +0 -0
  79. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/__init__.py +0 -0
  80. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/__init__.py +0 -0
  81. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/backoff.py +0 -0
  82. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/fuzzy.py +0 -0
  83. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/_utils/json.py +0 -0
  84. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/__init__.py +0 -0
  85. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/quote_summary.py +0 -0
  86. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/api/search.py +0 -0
  87. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/auth.py +0 -0
  88. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/config.py +0 -0
  89. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/ranking.py +0 -0
  90. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/session.py +0 -0
  91. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/transport.py +0 -0
  92. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/enrichment_feeds/yfinance/yfinance.py +0 -0
  93. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/reference_lookup/__init__.py +0 -0
  94. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/reference_lookup/exchange_rate_api.py +0 -0
  95. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/adapters/data_sources/reference_lookup/openfigi.py +0 -0
  96. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/cli/__init__.py +0 -0
  97. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/cli/config.py +0 -0
  98. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/cli/dispatcher.py +0 -0
  99. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/cli/main.py +0 -0
  100. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/cli/parser.py +0 -0
  101. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/cli/signals.py +0 -0
  102. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/__init__.py +0 -0
  103. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/_utils/__init__.py +0 -0
  104. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/_utils/_load_converter.py +0 -0
  105. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/_utils/_merge.py +0 -0
  106. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/_utils/_merge_config.py +0 -0
  107. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/_utils/_strategies.py +0 -0
  108. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/__init__.py +0 -0
  109. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/resolve.py +0 -0
  110. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/runner.py +0 -0
  111. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/seed.py +0 -0
  112. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/transforms/__init__.py +0 -0
  113. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/transforms/canonicalise.py +0 -0
  114. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/transforms/convert.py +0 -0
  115. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/transforms/enrich.py +0 -0
  116. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/transforms/group.py +0 -0
  117. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/transforms/identify.py +0 -0
  118. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/pipeline/transforms/parse.py +0 -0
  119. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/retrieval/__init__.py +0 -0
  120. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/domain/retrieval/retrieval.py +0 -0
  121. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/logging_config.py +0 -0
  122. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/__init__.py +0 -0
  123. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/canonical.py +0 -0
  124. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/__init__.py +0 -0
  125. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/feed_validators.py +0 -0
  126. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/gleif_feed_data.py +0 -0
  127. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/intrinio_feed_data.py +0 -0
  128. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/lseg_feed_data.py +0 -0
  129. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/sec_feed_data.py +0 -0
  130. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/stock_analysis_feed_data.py +0 -0
  131. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/tradingview_feed_data.py +0 -0
  132. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/xetra_feed_data.py +0 -0
  133. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/feeds/yfinance_feed_data.py +0 -0
  134. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/raw.py +0 -0
  135. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/types.py +0 -0
  136. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/schemas/validators.py +0 -0
  137. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/storage/__init__.py +0 -0
  138. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/storage/_utils.py +0 -0
  139. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/storage/cache.py +0 -0
  140. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/storage/data_store.py +0 -0
  141. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/storage/export.py +0 -0
  142. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/src/equity_aggregator/storage/metadata.py +0 -0
  143. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/README.md +0 -0
  144. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/__init__.py +0 -0
  145. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/conftest.py +0 -0
  146. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/__init__.py +0 -0
  147. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/__init__.py +0 -0
  148. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/__init__.py +0 -0
  149. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/discovery_feeds/__init__.py +0 -0
  150. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/discovery_feeds/intrinio/__init__.py +0 -0
  151. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/discovery_feeds/lseg/__init__.py +0 -0
  152. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/discovery_feeds/sec/__init__.py +0 -0
  153. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/discovery_feeds/stock_analysis/__init__.py +0 -0
  154. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/discovery_feeds/tradingview/__init__.py +0 -0
  155. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/discovery_feeds/xetra/__init__.py +0 -0
  156. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/enrichment_feeds/__init__.py +0 -0
  157. {equity_aggregator-0.1.5/tests/unit → equity_aggregator-0.1.7/tests/live}/adapters/data_sources/enrichment_feeds/gleif/__init__.py +0 -0
  158. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/live/adapters/data_sources/enrichment_feeds/yfinance/__init__.py +0 -0
  159. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/__init__.py +0 -0
  160. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/__init__.py +0 -0
  161. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/_utils/__init__.py +0 -0
  162. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/_utils/test_client.py +0 -0
  163. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/__init__.py +0 -0
  164. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/__init__.py +0 -0
  165. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/__init__.py +0 -0
  166. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/__init__.py +0 -0
  167. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/test_backoff.py +0 -0
  168. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/_utils/test_parser.py +0 -0
  169. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/test_intrinio.py +0 -0
  170. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/intrinio/test_session.py +0 -0
  171. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/lseg/__init__.py +0 -0
  172. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/__init__.py +0 -0
  173. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/test_backoff.py +0 -0
  174. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/lseg/_utils/test_parser.py +0 -0
  175. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/lseg/test_lseg.py +0 -0
  176. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/lseg/test_session.py +0 -0
  177. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/sec/__init__.py +0 -0
  178. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/sec/test_sec.py +0 -0
  179. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/stock_analysis/test_stock_analysis.py +0 -0
  180. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/tradingview/__init__.py +0 -0
  181. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/tradingview/test_tradingview.py +0 -0
  182. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/xetra/__init__.py +0 -0
  183. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/discovery_feeds/xetra/test_xetra.py +0 -0
  184. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/__init__.py +0 -0
  185. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/_helpers.py +0 -0
  186. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_api.py +0 -0
  187. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_download.py +0 -0
  188. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_gleif.py +0 -0
  189. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/gleif/test_parser.py +0 -0
  190. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/__init__.py +0 -0
  191. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_helpers.py +0 -0
  192. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/__init__.py +0 -0
  193. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/test_backoff.py +0 -0
  194. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/test_fuzzy.py +0 -0
  195. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/_utils/test_json.py +0 -0
  196. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api/__init__.py +0 -0
  197. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api/test_quote_summary.py +0 -0
  198. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/api/test_search.py +0 -0
  199. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_auth.py +0 -0
  200. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_config.py +0 -0
  201. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_ranking.py +0 -0
  202. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_session.py +0 -0
  203. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_transport.py +0 -0
  204. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/enrichment_feeds/yfinance/test_yfinance.py +0 -0
  205. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/reference_lookup/__init__.py +0 -0
  206. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/reference_lookup/test_exchange_rate_api.py +0 -0
  207. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/adapters/data_sources/reference_lookup/test_openfigi.py +0 -0
  208. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/cli/__init__.py +0 -0
  209. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/cli/test_config.py +0 -0
  210. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/cli/test_dispatcher.py +0 -0
  211. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/cli/test_main.py +0 -0
  212. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/cli/test_parser.py +0 -0
  213. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/__init__.py +0 -0
  214. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/_utils/__init__.py +0 -0
  215. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/_utils/test__merge.py +0 -0
  216. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/_utils/test__merge_config.py +0 -0
  217. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/_utils/test__strategies.py +0 -0
  218. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/_utils/test_load_converter.py +0 -0
  219. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/__init__.py +0 -0
  220. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/test_resolve.py +0 -0
  221. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/transforms/__init__.py +0 -0
  222. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/transforms/test_canonicalise.py +0 -0
  223. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/transforms/test_convert.py +0 -0
  224. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/transforms/test_enrich.py +0 -0
  225. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/transforms/test_group.py +0 -0
  226. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/transforms/test_identify.py +0 -0
  227. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/pipeline/transforms/test_parse.py +0 -0
  228. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/domain/retrieval/test_retrieval.py +0 -0
  229. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/__init__.py +0 -0
  230. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/__init__.py +0 -0
  231. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_feed_validators.py +0 -0
  232. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_gleif_feed_data.py +0 -0
  233. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_intrinio_feed_data.py +0 -0
  234. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_lseg_feed_data.py +0 -0
  235. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_sec_feed_data.py +0 -0
  236. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_stock_analysis_feed_data.py +0 -0
  237. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_tradingview_feed_data.py +0 -0
  238. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_xetra_feed_data.py +0 -0
  239. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/feeds/test_yfinance_feed_data.py +0 -0
  240. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/test_canonical.py +0 -0
  241. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/test_raw.py +0 -0
  242. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/test_types.py +0 -0
  243. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/schemas/test_validators.py +0 -0
  244. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/storage/__init__.py +0 -0
  245. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/storage/test__utils.py +0 -0
  246. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/storage/test_cache.py +0 -0
  247. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/storage/test_data_store.py +0 -0
  248. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/storage/test_export.py +0 -0
  249. {equity_aggregator-0.1.5 → equity_aggregator-0.1.7}/tests/unit/storage/test_metadata.py +0 -0
@@ -40,7 +40,11 @@ jobs:
40
40
 
41
41
  - name: Create .env file
42
42
  run: |
43
- printf '%b' "${{ secrets.EQUITY_AGGREGATOR_SECRETS }}" > .env
43
+ cat <<EOF > .env
44
+ EXCHANGE_RATE_API_KEY=${{ secrets.EXCHANGE_RATE_API_KEY }}
45
+ INTRINIO_API_KEY=${{ secrets.INTRINIO_API_KEY }}
46
+ OPENFIGI_API_KEY=${{ secrets.OPENFIGI_API_KEY }}
47
+ EOF
44
48
  chmod 600 .env
45
49
  test -s .env || { echo "::error ::empty .env"; exit 1; }
46
50
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: equity-aggregator
3
- Version: 0.1.5
3
+ Version: 0.1.7
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "equity-aggregator"
3
- version = "0.1.5"
3
+ version = "0.1.7"
4
4
  description = "Financial equity data aggregation toolkit"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -29,38 +29,28 @@ def _get_api_key() -> str:
29
29
  return os.getenv("INTRINIO_API_KEY", "")
30
30
 
31
31
 
32
- async def test_intrinio_endpoint_returns_ok() -> None:
32
+ @pytest.fixture(scope="module")
33
+ def intrinio_companies_response() -> httpx.Response:
33
34
  """
34
- ARRANGE: live Intrinio companies API endpoint
35
- ACT: send GET request
36
- ASSERT: returns HTTP 200
35
+ Fetch Intrinio companies API response once and share across all tests.
37
36
  """
38
37
  params = {"api_key": _get_api_key(), "page_size": "10"}
38
+ with httpx.Client() as client:
39
+ return client.get(_INTRINIO_COMPANIES_URL, params=params)
39
40
 
40
- async with httpx.AsyncClient() as client:
41
- response = await client.get(_INTRINIO_COMPANIES_URL, params=params)
42
-
43
- assert response.status_code == _HTTP_OK
44
41
 
45
-
46
- async def test_intrinio_record_validates_against_schema() -> None:
42
+ @pytest.fixture(scope="module")
43
+ def intrinio_security_record(intrinio_companies_response: httpx.Response) -> dict:
47
44
  """
48
- ARRANGE: security record from live Intrinio API response
49
- ACT: validate with IntrinioFeedData schema
50
- ASSERT: no ValidationError raised
45
+ Fetch a security record from Intrinio for schema validation.
51
46
  """
52
- params = {"api_key": _get_api_key(), "page_size": "10"}
53
-
54
- async with httpx.AsyncClient() as client:
55
- response = await client.get(_INTRINIO_COMPANIES_URL, params=params)
56
-
57
- records, _ = parse_companies_response(response.json())
47
+ records, _ = parse_companies_response(intrinio_companies_response.json())
58
48
  first_company = records[0]
59
49
  ticker = first_company["company_ticker"]
60
50
  securities_url = f"{_INTRINIO_COMPANIES_URL}/{ticker}/securities"
61
51
 
62
- async with httpx.AsyncClient() as client:
63
- securities_response = await client.get(
52
+ with httpx.Client() as client:
53
+ securities_response = client.get(
64
54
  securities_url,
65
55
  params={"api_key": _get_api_key()},
66
56
  )
@@ -70,4 +60,26 @@ async def test_intrinio_record_validates_against_schema() -> None:
70
60
  if not security_records:
71
61
  pytest.skip("No securities found for first company")
72
62
 
73
- assert IntrinioFeedData.model_validate(security_records[0])
63
+ return security_records[0]
64
+
65
+
66
+ def test_intrinio_endpoint_returns_ok(
67
+ intrinio_companies_response: httpx.Response,
68
+ ) -> None:
69
+ """
70
+ ARRANGE: live Intrinio companies API endpoint
71
+ ACT: send GET request
72
+ ASSERT: returns HTTP 200
73
+ """
74
+ assert intrinio_companies_response.status_code == _HTTP_OK
75
+
76
+
77
+ def test_intrinio_record_validates_against_schema(
78
+ intrinio_security_record: dict,
79
+ ) -> None:
80
+ """
81
+ ARRANGE: security record from live Intrinio API response
82
+ ACT: validate with IntrinioFeedData schema
83
+ ASSERT: no ValidationError raised
84
+ """
85
+ assert IntrinioFeedData.model_validate(intrinio_security_record)
@@ -0,0 +1,89 @@
1
+ # lseg/test_lseg.py
2
+
3
+ import httpx
4
+ import pytest
5
+ from pydantic import ValidationError
6
+
7
+ from equity_aggregator.adapters.data_sources.discovery_feeds.lseg._utils import (
8
+ parse_response,
9
+ )
10
+ from equity_aggregator.adapters.data_sources.discovery_feeds.lseg.lseg import (
11
+ _HEADERS,
12
+ _LSEG_BASE_PARAMS,
13
+ _LSEG_PATH,
14
+ _LSEG_SEARCH_URL,
15
+ )
16
+ from equity_aggregator.schemas.feeds import LsegFeedData
17
+
18
+ pytestmark = pytest.mark.live
19
+
20
+ _HTTP_OK = 200
21
+ _TIMEOUT = httpx.Timeout(connect=10.0, read=60.0, write=10.0, pool=None)
22
+
23
+
24
+ @pytest.fixture(scope="module")
25
+ def lseg_response() -> httpx.Response:
26
+ """
27
+ Fetch LSEG API response once and share across all tests in this module.
28
+ """
29
+ with httpx.Client(headers=_HEADERS, timeout=_TIMEOUT) as client:
30
+ return client.get(
31
+ _LSEG_SEARCH_URL,
32
+ params={
33
+ "path": _LSEG_PATH,
34
+ "parameters": f"{_LSEG_BASE_PARAMS}&page=0",
35
+ },
36
+ )
37
+
38
+
39
+ def test_lseg_endpoint_returns_ok(lseg_response: httpx.Response) -> None:
40
+ """
41
+ ARRANGE: live LSEG API endpoint
42
+ ACT: send GET request
43
+ ASSERT: returns HTTP 200
44
+ """
45
+ assert lseg_response.status_code == _HTTP_OK
46
+
47
+
48
+ def test_lseg_response_contains_components_key(lseg_response: httpx.Response) -> None:
49
+ """
50
+ ARRANGE: live LSEG API response
51
+ ACT: parse JSON payload
52
+ ASSERT: contains 'components' key
53
+ """
54
+ payload = lseg_response.json()
55
+
56
+ assert "components" in payload
57
+
58
+
59
+ def test_lseg_response_parses_to_non_empty_records(
60
+ lseg_response: httpx.Response,
61
+ ) -> None:
62
+ """
63
+ ARRANGE: live LSEG API response
64
+ ACT: parse response using parse_response
65
+ ASSERT: returns non-empty list of records
66
+ """
67
+ payload = lseg_response.json()
68
+ records, _ = parse_response(payload)
69
+
70
+ assert isinstance(records, list) and len(records) > 0
71
+
72
+
73
+ def test_lseg_record_validates_against_schema(lseg_response: httpx.Response) -> None:
74
+ """
75
+ ARRANGE: first record from live LSEG API response
76
+ ACT: validate with LsegFeedData schema
77
+ ASSERT: no ValidationError raised
78
+ """
79
+ payload = lseg_response.json()
80
+ records, _ = parse_response(payload)
81
+ first_record = records[0]
82
+
83
+ try:
84
+ LsegFeedData.model_validate(first_record)
85
+ validated = True
86
+ except ValidationError:
87
+ validated = False
88
+
89
+ assert validated
@@ -0,0 +1,76 @@
1
+ # sec/test_sec.py
2
+
3
+ import httpx
4
+ import pytest
5
+ from pydantic import ValidationError
6
+
7
+ from equity_aggregator.adapters.data_sources.discovery_feeds.sec.sec import (
8
+ _HEADERS,
9
+ _SEC_SEARCH_URL,
10
+ _parse_row,
11
+ )
12
+ from equity_aggregator.schemas.feeds import SecFeedData
13
+
14
+ pytestmark = pytest.mark.live
15
+
16
+ _HTTP_OK = 200
17
+
18
+
19
+ @pytest.fixture(scope="module")
20
+ def sec_response() -> httpx.Response:
21
+ """
22
+ Fetch SEC API response once and share across all tests in this module.
23
+ """
24
+ with httpx.Client(headers=_HEADERS) as client:
25
+ return client.get(_SEC_SEARCH_URL)
26
+
27
+
28
+ def test_sec_endpoint_returns_ok(sec_response: httpx.Response) -> None:
29
+ """
30
+ ARRANGE: live SEC API endpoint
31
+ ACT: send GET request
32
+ ASSERT: returns HTTP 200
33
+ """
34
+ assert sec_response.status_code == _HTTP_OK
35
+
36
+
37
+ def test_sec_response_contains_data_key(sec_response: httpx.Response) -> None:
38
+ """
39
+ ARRANGE: live SEC API response
40
+ ACT: parse JSON payload
41
+ ASSERT: contains 'data' key
42
+ """
43
+ payload = sec_response.json()
44
+
45
+ assert "data" in payload
46
+
47
+
48
+ def test_sec_response_data_is_non_empty_list(sec_response: httpx.Response) -> None:
49
+ """
50
+ ARRANGE: live SEC API response
51
+ ACT: extract 'data' field
52
+ ASSERT: is a non-empty list
53
+ """
54
+ payload = sec_response.json()
55
+ data = payload.get("data", [])
56
+
57
+ assert isinstance(data, list) and len(data) > 0
58
+
59
+
60
+ def test_sec_record_validates_against_schema(sec_response: httpx.Response) -> None:
61
+ """
62
+ ARRANGE: first row from live SEC API response, parsed into record
63
+ ACT: validate with SecFeedData schema
64
+ ASSERT: no ValidationError raised
65
+ """
66
+ payload = sec_response.json()
67
+ first_row = payload["data"][0]
68
+ record = _parse_row(first_row)
69
+
70
+ try:
71
+ SecFeedData.model_validate(record)
72
+ validated = True
73
+ except ValidationError:
74
+ validated = False
75
+
76
+ assert validated
@@ -0,0 +1,87 @@
1
+ # stock_analysis/test_stock_analysis.py
2
+
3
+ import httpx
4
+ import pytest
5
+ from pydantic import ValidationError
6
+
7
+ from equity_aggregator.adapters.data_sources.discovery_feeds.stock_analysis import (
8
+ stock_analysis,
9
+ )
10
+ from equity_aggregator.schemas.feeds import StockAnalysisFeedData
11
+
12
+ pytestmark = pytest.mark.live
13
+
14
+ _HTTP_OK = 200
15
+
16
+
17
+ @pytest.fixture(scope="module")
18
+ def stock_analysis_response() -> httpx.Response:
19
+ """
20
+ Fetch Stock Analysis API response once and share across all tests in this module.
21
+ """
22
+ with httpx.Client() as client:
23
+ return client.get(
24
+ stock_analysis._STOCK_ANALYSIS_SEARCH_URL,
25
+ params=stock_analysis._PARAMS,
26
+ )
27
+
28
+
29
+ def test_stock_analysis_endpoint_returns_ok(
30
+ stock_analysis_response: httpx.Response,
31
+ ) -> None:
32
+ """
33
+ ARRANGE: live Stock Analysis screener API endpoint
34
+ ACT: send GET request
35
+ ASSERT: returns HTTP 200
36
+ """
37
+ assert stock_analysis_response.status_code == _HTTP_OK
38
+
39
+
40
+ def test_stock_analysis_response_contains_data_key(
41
+ stock_analysis_response: httpx.Response,
42
+ ) -> None:
43
+ """
44
+ ARRANGE: live Stock Analysis API response
45
+ ACT: parse JSON payload
46
+ ASSERT: contains 'data' key
47
+ """
48
+ payload = stock_analysis_response.json()
49
+
50
+ assert "data" in payload
51
+
52
+
53
+ def test_stock_analysis_response_data_is_non_empty_list(
54
+ stock_analysis_response: httpx.Response,
55
+ ) -> None:
56
+ """
57
+ ARRANGE: live Stock Analysis API response
58
+ ACT: extract nested data array
59
+ ASSERT: is a non-empty list
60
+ """
61
+ payload = stock_analysis_response.json()
62
+ data_wrapper = payload.get("data", {})
63
+ records = data_wrapper.get("data", [])
64
+
65
+ assert isinstance(records, list) and len(records) > 0
66
+
67
+
68
+ def test_stock_analysis_record_validates_against_schema(
69
+ stock_analysis_response: httpx.Response,
70
+ ) -> None:
71
+ """
72
+ ARRANGE: first record from live Stock Analysis API response
73
+ ACT: validate with StockAnalysisFeedData schema
74
+ ASSERT: no ValidationError raised
75
+ """
76
+ payload = stock_analysis_response.json()
77
+ data_wrapper = payload.get("data", {})
78
+ records = data_wrapper.get("data", [])
79
+ first_record = records[0]
80
+
81
+ try:
82
+ StockAnalysisFeedData.model_validate(first_record)
83
+ validated = True
84
+ except ValidationError:
85
+ validated = False
86
+
87
+ assert validated
@@ -0,0 +1,90 @@
1
+ # tradingview/test_tradingview.py
2
+
3
+ import httpx
4
+ import pytest
5
+ from pydantic import ValidationError
6
+
7
+ from equity_aggregator.adapters.data_sources.discovery_feeds.tradingview import (
8
+ tradingview,
9
+ )
10
+ from equity_aggregator.schemas.feeds import TradingViewFeedData
11
+
12
+ pytestmark = pytest.mark.live
13
+
14
+ _HTTP_OK = 200
15
+
16
+
17
+ def _build_request_body(start: int = 0, end: int = tradingview._PAGE_SIZE) -> dict:
18
+ """
19
+ Build request body with pagination range.
20
+ """
21
+ return {**tradingview._REQUEST_BODY_TEMPLATE, "range": [start, end]}
22
+
23
+
24
+ @pytest.fixture(scope="module")
25
+ def tradingview_response() -> httpx.Response:
26
+ """
27
+ Fetch TradingView API response once and share across all tests in this module.
28
+ """
29
+ with httpx.Client() as client:
30
+ return client.post(
31
+ tradingview._TRADINGVIEW_SCAN_URL,
32
+ json=_build_request_body(),
33
+ )
34
+
35
+
36
+ def test_tradingview_endpoint_returns_ok(tradingview_response: httpx.Response) -> None:
37
+ """
38
+ ARRANGE: live TradingView scanner API endpoint
39
+ ACT: send POST request
40
+ ASSERT: returns HTTP 200
41
+ """
42
+ assert tradingview_response.status_code == _HTTP_OK
43
+
44
+
45
+ def test_tradingview_response_contains_data_key(
46
+ tradingview_response: httpx.Response,
47
+ ) -> None:
48
+ """
49
+ ARRANGE: live TradingView API response
50
+ ACT: parse JSON payload
51
+ ASSERT: contains 'data' key
52
+ """
53
+ payload = tradingview_response.json()
54
+
55
+ assert "data" in payload
56
+
57
+
58
+ def test_tradingview_response_data_is_non_empty_list(
59
+ tradingview_response: httpx.Response,
60
+ ) -> None:
61
+ """
62
+ ARRANGE: live TradingView API response
63
+ ACT: extract 'data' field
64
+ ASSERT: is a non-empty list
65
+ """
66
+ payload = tradingview_response.json()
67
+ data = payload.get("data", [])
68
+
69
+ assert isinstance(data, list) and len(data) > 0
70
+
71
+
72
+ def test_tradingview_record_validates_against_schema(
73
+ tradingview_response: httpx.Response,
74
+ ) -> None:
75
+ """
76
+ ARRANGE: first parsed record from live TradingView API response
77
+ ACT: validate with TradingViewFeedData schema
78
+ ASSERT: no ValidationError raised
79
+ """
80
+ payload = tradingview_response.json()
81
+ first_row = payload["data"][0]
82
+ record = tradingview._parse_row(first_row)
83
+
84
+ try:
85
+ TradingViewFeedData.model_validate(record)
86
+ validated = True
87
+ except ValidationError:
88
+ validated = False
89
+
90
+ assert validated
@@ -0,0 +1,79 @@
1
+ # xetra/test_xetra.py
2
+
3
+ import httpx
4
+ import pytest
5
+ from pydantic import ValidationError
6
+
7
+ from equity_aggregator.adapters.data_sources.discovery_feeds.xetra.xetra import (
8
+ _HEADERS,
9
+ _XETRA_SEARCH_URL,
10
+ _build_payload,
11
+ _extract_records,
12
+ )
13
+ from equity_aggregator.schemas.feeds import XetraFeedData
14
+
15
+ pytestmark = pytest.mark.live
16
+
17
+ _HTTP_OK = 200
18
+
19
+
20
+ @pytest.fixture(scope="module")
21
+ def xetra_response() -> httpx.Response:
22
+ """
23
+ Fetch XETRA API response once and share across all tests in this module.
24
+ """
25
+ with httpx.Client(headers=_HEADERS) as client:
26
+ return client.post(_XETRA_SEARCH_URL, json=_build_payload(offset=0))
27
+
28
+
29
+ def test_xetra_endpoint_returns_ok(xetra_response: httpx.Response) -> None:
30
+ """
31
+ ARRANGE: live XETRA API endpoint
32
+ ACT: send POST request
33
+ ASSERT: returns HTTP 200
34
+ """
35
+ assert xetra_response.status_code == _HTTP_OK
36
+
37
+
38
+ def test_xetra_response_contains_data_key(xetra_response: httpx.Response) -> None:
39
+ """
40
+ ARRANGE: live XETRA API response
41
+ ACT: parse JSON payload
42
+ ASSERT: contains 'data' key
43
+ """
44
+ payload = xetra_response.json()
45
+
46
+ assert "data" in payload
47
+
48
+
49
+ def test_xetra_response_data_is_non_empty_list(xetra_response: httpx.Response) -> None:
50
+ """
51
+ ARRANGE: live XETRA API response
52
+ ACT: extract 'data' field
53
+ ASSERT: is a non-empty list
54
+ """
55
+ payload = xetra_response.json()
56
+ data = payload.get("data", [])
57
+
58
+ assert isinstance(data, list) and len(data) > 0
59
+
60
+
61
+ def test_xetra_extracted_record_validates_against_schema(
62
+ xetra_response: httpx.Response,
63
+ ) -> None:
64
+ """
65
+ ARRANGE: first extracted record from live XETRA API response
66
+ ACT: validate with XetraFeedData schema
67
+ ASSERT: no ValidationError raised
68
+ """
69
+ payload = xetra_response.json()
70
+ records = _extract_records(payload)
71
+ first_record = records[0]
72
+
73
+ try:
74
+ XetraFeedData.model_validate(first_record)
75
+ validated = True
76
+ except ValidationError:
77
+ validated = False
78
+
79
+ assert validated
@@ -0,0 +1,81 @@
1
+ # gleif/test_gleif.py
2
+
3
+ import httpx
4
+ import pytest
5
+
6
+ from equity_aggregator.adapters.data_sources.enrichment_feeds.gleif.api import (
7
+ GLEIF_ISIN_LEI_URL,
8
+ )
9
+
10
+ pytestmark = pytest.mark.live
11
+
12
+ _HTTP_OK = 200
13
+
14
+
15
+ @pytest.fixture(scope="module")
16
+ def gleif_response() -> httpx.Response:
17
+ """
18
+ Fetch GLEIF API response once and share across all tests in this module.
19
+ """
20
+ with httpx.Client() as client:
21
+ return client.get(GLEIF_ISIN_LEI_URL)
22
+
23
+
24
+ def test_gleif_api_endpoint_returns_ok(gleif_response: httpx.Response) -> None:
25
+ """
26
+ ARRANGE: live GLEIF ISIN-LEI mapping API endpoint
27
+ ACT: send GET request
28
+ ASSERT: returns HTTP 200
29
+ """
30
+ assert gleif_response.status_code == _HTTP_OK
31
+
32
+
33
+ def test_gleif_api_response_contains_data_key(gleif_response: httpx.Response) -> None:
34
+ """
35
+ ARRANGE: live GLEIF API response
36
+ ACT: parse JSON payload
37
+ ASSERT: contains 'data' key
38
+ """
39
+ payload = gleif_response.json()
40
+
41
+ assert "data" in payload
42
+
43
+
44
+ def test_gleif_api_response_data_contains_attributes(
45
+ gleif_response: httpx.Response,
46
+ ) -> None:
47
+ """
48
+ ARRANGE: live GLEIF API response
49
+ ACT: extract 'data' field
50
+ ASSERT: contains 'attributes' key
51
+ """
52
+ payload = gleif_response.json()
53
+ data = payload.get("data", {})
54
+
55
+ assert "attributes" in data
56
+
57
+
58
+ def test_gleif_api_response_contains_download_link(
59
+ gleif_response: httpx.Response,
60
+ ) -> None:
61
+ """
62
+ ARRANGE: live GLEIF API response
63
+ ACT: extract attributes from response
64
+ ASSERT: contains 'downloadLink' key
65
+ """
66
+ payload = gleif_response.json()
67
+ attrs = payload.get("data", {}).get("attributes", {})
68
+
69
+ assert "downloadLink" in attrs
70
+
71
+
72
+ def test_gleif_api_download_link_is_valid_url(gleif_response: httpx.Response) -> None:
73
+ """
74
+ ARRANGE: live GLEIF API response
75
+ ACT: extract download link
76
+ ASSERT: is a non-empty string starting with https
77
+ """
78
+ payload = gleif_response.json()
79
+ download_link = payload.get("data", {}).get("attributes", {}).get("downloadLink")
80
+
81
+ assert isinstance(download_link, str) and download_link.startswith("https://")