financetoolkit 2.3.0__tar.gz → 2.3.2__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 (238) hide show
  1. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/.gitignore +193 -196
  2. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/PKG-INFO +5 -2
  3. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/cache_controller.py +68 -14
  4. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/policy_model.py +64 -6
  5. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/sqlite_model.py +96 -13
  6. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/currencies_model.py +15 -3
  7. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/discovery/discovery_controller.py +278 -51
  8. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/discovery/discovery_model.py +333 -37
  9. financetoolkit-2.3.2/financetoolkit/earnings_model.py +113 -0
  10. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/cointegration_model.py +19 -1
  11. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/diagnostics_model.py +3 -2
  12. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/econometrics_controller.py +102 -52
  13. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/regression_model.py +100 -4
  14. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/state_space_model.py +7 -0
  15. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/unitroot_model.py +12 -0
  16. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/bis_model.py +67 -0
  17. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/economics_controller.py +490 -83
  18. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/helpers.py +8 -3
  19. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/imf_model.py +13 -1
  20. financetoolkit-2.3.2/financetoolkit/economics/nyfed_model.py +120 -0
  21. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/etf/etf_controller.py +535 -57
  22. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/etf/etf_model.py +93 -0
  23. financetoolkit-2.3.2/financetoolkit/finra_model.py +311 -0
  24. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/bond_model.py +46 -6
  25. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/derivative_model.py +34 -17
  26. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fixedincome_controller.py +127 -6
  27. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fred_model.py +5 -1
  28. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/short_rate_model.py +10 -0
  29. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fmp_model.py +579 -29
  30. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fundamentals_model.py +50 -35
  31. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/helpers.py +127 -0
  32. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/historical_model.py +129 -41
  33. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/analytics_model.py +122 -19
  34. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/auth_model.py +344 -90
  35. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/coercion_model.py +37 -0
  36. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/config.yaml +75 -39
  37. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/diagnostics_model.py +17 -3
  38. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/formatting_model.py +27 -2
  39. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/inspection_controller.py +60 -29
  40. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcp_controller.py +26 -9
  41. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/.mcpbignore +0 -1
  42. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/README.md +7 -16
  43. financetoolkit-2.3.2/financetoolkit/mcp_server/mcpb/manifest.json +190 -0
  44. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/pyproject.toml +3 -3
  45. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/provider_model.py +174 -9
  46. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/registry_controller.py +551 -35
  47. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/series_model.py +15 -3
  48. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/setup_model.py +181 -103
  49. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/tools_model.py +32 -5
  50. financetoolkit-2.3.2/financetoolkit/models/damodaran_model.py +255 -0
  51. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/growth_model.py +88 -0
  52. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/intrinsic_model.py +173 -6
  53. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/models_controller.py +1090 -89
  54. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/quality_model.py +49 -0
  55. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/wacc_model.py +6 -6
  56. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/statistics.csv +2 -4
  57. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization_model.py +171 -62
  58. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/binomial_trees_model.py +15 -4
  59. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/black_scholes_model.py +26 -4
  60. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/exotics_model.py +6 -2
  61. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/greeks_model.py +3 -1
  62. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/helpers.py +3 -3
  63. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/options_controller.py +103 -60
  64. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/options_model.py +30 -10
  65. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/performance/performance_controller.py +929 -41
  66. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/performance/performance_model.py +710 -13
  67. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/attribution_model.py +23 -3
  68. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/config.yaml +4 -0
  69. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/construction_controller.py +225 -59
  70. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/helpers.py +53 -6
  71. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/optimization_model.py +265 -12
  72. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/overview_model.py +84 -17
  73. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/portfolio_controller.py +241 -37
  74. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/portfolio_model.py +63 -29
  75. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/helpers.py +7 -6
  76. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/ratios_controller.py +1043 -216
  77. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/cvar_model.py +8 -6
  78. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/garch_model.py +29 -1
  79. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/risk_controller.py +629 -37
  80. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/risk_model.py +326 -31
  81. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/var_model.py +3 -1
  82. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/breadth_model.py +64 -28
  83. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/momentum_model.py +23 -7
  84. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/overlap_model.py +23 -11
  85. financetoolkit-2.3.2/financetoolkit/technicals/pattern_model.py +579 -0
  86. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/technicals_controller.py +973 -249
  87. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/volatility_model.py +6 -3
  88. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/toolkit_controller.py +1358 -139
  89. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/error_model.py +18 -5
  90. financetoolkit-2.3.2/financetoolkit/utilities/factor_model.py +745 -0
  91. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/statistics_model.py +183 -25
  92. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/validation_model.py +22 -10
  93. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/yfinance_model.py +26 -12
  94. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/pyproject.toml +9 -4
  95. financetoolkit-2.3.0/financetoolkit/mcp_server/mcpb/build-mcpb.sh +0 -103
  96. financetoolkit-2.3.0/financetoolkit/mcp_server/mcpb/manifest.json +0 -186
  97. financetoolkit-2.3.0/financetoolkit/models/damodaran_model.py +0 -84
  98. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/LICENSE.txt +0 -0
  99. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/README.md +0 -0
  100. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/__init__.py +0 -0
  101. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/__init__.py +0 -0
  102. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/coverage_model.py +0 -0
  103. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/frame_model.py +0 -0
  104. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/request_model.py +0 -0
  105. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/serialization_model.py +0 -0
  106. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/ticker_model.py +0 -0
  107. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/discovery/__init__.py +0 -0
  108. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/__init__.py +0 -0
  109. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/causal_inference_model.py +0 -0
  110. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/causality_model.py +0 -0
  111. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/data_model.py +0 -0
  112. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/event_study_model.py +0 -0
  113. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/fama_macbeth_model.py +0 -0
  114. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/forecast_evaluation_model.py +0 -0
  115. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/hypothesis_testing_model.py +0 -0
  116. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/pairs_trading_model.py +0 -0
  117. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/panel_data_model.py +0 -0
  118. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/regime_model.py +0 -0
  119. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/specification_tests_model.py +0 -0
  120. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/time_series_model.py +0 -0
  121. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/__init__.py +0 -0
  122. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/bls_model.py +0 -0
  123. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/boe_model.py +0 -0
  124. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/boj_model.py +0 -0
  125. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/cboe_model.py +0 -0
  126. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/dnb_model.py +0 -0
  127. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/ecb_model.py +0 -0
  128. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/eex_model.py +0 -0
  129. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/esrb_model.py +0 -0
  130. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/eurostat_model.py +0 -0
  131. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/fmp_model.py +0 -0
  132. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/frb_model.py +0 -0
  133. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/fred_model.py +0 -0
  134. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/freddie_mac_model.py +0 -0
  135. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/gmdb_model.py +0 -0
  136. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/ibge_model.py +0 -0
  137. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/macrohistory_model.py +0 -0
  138. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/mof_model.py +0 -0
  139. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/nber_model.py +0 -0
  140. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/ngfs_model.py +0 -0
  141. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/oecd_model.py +0 -0
  142. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/ons_model.py +0 -0
  143. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/sbj_model.py +0 -0
  144. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/shiller_model.py +0 -0
  145. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/stoxx_model.py +0 -0
  146. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/treasury_model.py +0 -0
  147. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/yfinance_model.py +0 -0
  148. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/etf/__init__.py +0 -0
  149. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/__init__.py +0 -0
  150. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/boc_model.py +0 -0
  151. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/bundesbank_model.py +0 -0
  152. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/curve_model.py +0 -0
  153. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/ecb_model.py +0 -0
  154. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/eiopa_model.py +0 -0
  155. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/esma_model.py +0 -0
  156. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/euribor_model.py +0 -0
  157. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fed_model.py +0 -0
  158. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fiscaldata_model.py +0 -0
  159. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fmp_model.py +0 -0
  160. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/helpers.py +0 -0
  161. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/norgesbank_model.py +0 -0
  162. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/rba_model.py +0 -0
  163. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/riksbank_model.py +0 -0
  164. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/yieldcurve_model.py +0 -0
  165. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/__init__.py +0 -0
  166. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/__main__.py +0 -0
  167. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/LICENSE +0 -0
  168. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/finance_toolkit_icon.png +0 -0
  169. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/static/apple-touch-icon.png +0 -0
  170. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/static/favicon-32.png +0 -0
  171. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/static/favicon.ico +0 -0
  172. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/stats_page_model.py +0 -0
  173. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/__init__.py +0 -0
  174. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/altman_model.py +0 -0
  175. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/beneish_model.py +0 -0
  176. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/credit_model.py +0 -0
  177. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/dupont_model.py +0 -0
  178. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/enterprise_model.py +0 -0
  179. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/eva_model.py +0 -0
  180. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/fulmer_model.py +0 -0
  181. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/grover_model.py +0 -0
  182. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/helpers.py +0 -0
  183. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/ohlson_model.py +0 -0
  184. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/peers_model.py +0 -0
  185. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/piotroski_model.py +0 -0
  186. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/springate_model.py +0 -0
  187. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/zmijewski_model.py +0 -0
  188. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/balance.csv +0 -0
  189. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/balance_yf.csv +0 -0
  190. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/cash.csv +0 -0
  191. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/cash_yf.csv +0 -0
  192. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/income.csv +0 -0
  193. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/income_yf.csv +0 -0
  194. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/statistics_yf.csv +0 -0
  195. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/__init__.py +0 -0
  196. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/market_metrics_model.py +0 -0
  197. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/risk_neutral_density_model.py +0 -0
  198. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/svi_model.py +0 -0
  199. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/performance/__init__.py +0 -0
  200. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/performance/helpers.py +0 -0
  201. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/__init__.py +0 -0
  202. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/definition_model.py +0 -0
  203. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/example_datasets/example_portfolio.csv +0 -0
  204. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/example_datasets/example_portfolio.xlsx +0 -0
  205. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/all_weather.yaml +0 -0
  206. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/balanced_60_40.yaml +0 -0
  207. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/barbell.yaml +0 -0
  208. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/bogleheads_three_fund.yaml +0 -0
  209. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/buffett_90_10.yaml +0 -0
  210. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/conservative_income.yaml +0 -0
  211. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/global_60_40.yaml +0 -0
  212. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/global_equity_growth.yaml +0 -0
  213. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/golden_butterfly.yaml +0 -0
  214. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/permanent_portfolio.yaml +0 -0
  215. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/small_cap_value_tilt.yaml +0 -0
  216. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/target_date_glidepath.yaml +0 -0
  217. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/us_equity_sectors.yaml +0 -0
  218. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/py.typed +0 -0
  219. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/__init__.py +0 -0
  220. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/efficiency_model.py +0 -0
  221. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/liquidity_model.py +0 -0
  222. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/profitability_model.py +0 -0
  223. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/solvency_model.py +0 -0
  224. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/valuation_model.py +0 -0
  225. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/__init__.py +0 -0
  226. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/backtesting_model.py +0 -0
  227. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/copula_model.py +0 -0
  228. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/covar_model.py +0 -0
  229. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/evar_model.py +0 -0
  230. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/helpers.py +0 -0
  231. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/market_liquidity_model.py +0 -0
  232. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/realized_volatility_model.py +0 -0
  233. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/__init__.py +0 -0
  234. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/seasonality_model.py +0 -0
  235. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/dataframe_model.py +0 -0
  236. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/excel_model.py +0 -0
  237. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/logger_model.py +0 -0
  238. {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/requests_model.py +0 -0
@@ -1,197 +1,194 @@
1
- # Finance Toolkit Ignored Files
2
- *.csv
3
- *.xlsx
4
- *.xls
5
- *.ipynb
6
- cached/
7
- debugging.py
8
- .planning/
9
-
10
- # Finance Toolkit Example Datasets
11
- !financetoolkit/portfolio/example_datasets/*.xlsx
12
- !financetoolkit/portfolio/example_datasets/*.csv
13
-
14
- # Finance Toolkit Normalization Files
15
- !financetoolkit/normalization/*.csv
16
-
17
- # Finance Toolkit Tests
18
- !tests/datasets/*.xlsx
19
- !tests/*/csv/*/*.csv
20
- !tests/csv/*/*.csv
21
-
22
- # VS Code
23
- .agents
24
- .vscode/
25
- .claude/
26
- *.sh
27
-
28
- # Claude
29
- CLAUDE.md
30
-
31
- # Specific files for the MCP Bundle
32
- !financetoolkit/mcp_server/mcpb/build-mcpb.sh
33
-
34
- # Byte-compiled / optimized / DLL files
35
- __pycache__/
36
- *.py[cod]
37
- *$py.class
38
- .DS_Store
39
- .ipynb_checkpoints/
40
- .DS_Store
41
-
42
- # C extensions
43
- *.so
44
-
45
- # Distribution / packaging
46
- .Python
47
- build/
48
- develop-eggs/
49
- dist/
50
- downloads/
51
- eggs/
52
- .eggs/
53
- lib/
54
- lib64/
55
- parts/
56
- sdist/
57
- var/
58
- wheels/
59
- share/python-wheels/
60
- *.egg-info/
61
- .installed.cfg
62
- *.egg
63
- MANIFEST
64
-
65
- # PyInstaller
66
- # Usually these files are written by a python script from a template
67
- # before PyInstaller builds the exe, so as to inject date/other infos into it.
68
- *.manifest
69
- *.spec
70
-
71
- # Installer logs
72
- pip-log.txt
73
- pip-delete-this-directory.txt
74
-
75
- # Unit test / coverage reports
76
- htmlcov/
77
- .tox/
78
- .nox/
79
- .coverage
80
- .coverage.*
81
- .cache
82
- nosetests.xml
83
- coverage.xml
84
- *.cover
85
- *.py,cover
86
- .hypothesis/
87
- .pytest_cache/
88
- cover/
89
-
90
- # Translations
91
- *.mo
92
- *.pot
93
-
94
- # Django stuff:
95
- *.log
96
- local_settings.py
97
- db.sqlite3
98
- db.sqlite3-journal
99
-
100
- # Flask stuff:
101
- instance/
102
- .webassets-cache
103
-
104
- # Scrapy stuff:
105
- .scrapy
106
-
107
- # Sphinx documentation
108
- docs/_build/
109
-
110
- # PyBuilder
111
- .pybuilder/
112
- target/
113
-
114
- # Jupyter Notebook
115
- .ipynb_checkpoints
116
-
117
- # IPython
118
- profile_default/
119
- ipython_config.py
120
-
121
- # pyenv
122
- # For a library or package, you might want to ignore these files since the code is
123
- # intended to run in multiple environments; otherwise, check them in:
124
- # .python-version
125
-
126
- # pipenv
127
- # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
128
- # However, in case of collaboration, if having platform-specific dependencies or dependencies
129
- # having no cross-platform support, pipenv may install dependencies that don't work, or not
130
- # install all needed dependencies.
131
- #Pipfile.lock
132
-
133
- # poetry
134
- # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
135
- # This is especially recommended for binary packages to ensure reproducibility, and is more
136
- # commonly ignored for libraries.
137
- # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
138
- #poetry.lock
139
-
140
- # pdm
141
- # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
142
- #pdm.lock
143
- # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
144
- # in version control.
145
- # https://pdm.fming.dev/#use-with-ide
146
- .pdm.toml
147
-
148
- # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
149
- __pypackages__/
150
-
151
- # Celery stuff
152
- celerybeat-schedule
153
- celerybeat.pid
154
-
155
- # SageMath parsed files
156
- *.sage.py
157
-
158
- # Environments
159
- .env
160
- .venv
161
- env/
162
- venv/
163
- ENV/
164
- env.bak/
165
- venv.bak/
166
-
167
- # Spyder project settings
168
- .spyderproject
169
- .spyproject
170
-
171
- # Rope project settings
172
- .ropeproject
173
-
174
- # mkdocs documentation
175
- /site
176
-
177
- # mypy
178
- .mypy_cache/
179
- .dmypy.json
180
- dmypy.json
181
-
182
- # Pyre type checker
183
- .pyre/
184
-
185
- # pytype static type analyzer
186
- .pytype/
187
-
188
- # Cython debug symbols
189
- cython_debug/
190
-
191
- # PyCharm
192
- # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
193
- # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
194
- # and can be added to the global gitignore or merged into this file. For a more nuclear
195
- # option (not recommended) you can uncomment the following to ignore the entire idea folder.
196
- #.idea/
1
+ # Finance Toolkit Ignored Files
2
+ *.csv
3
+ *.xlsx
4
+ *.xls
5
+ *.ipynb
6
+ cached/
7
+ debugging.py
8
+ .planning/
9
+
10
+ # Finance Toolkit Example Datasets
11
+ !financetoolkit/portfolio/example_datasets/*.xlsx
12
+ !financetoolkit/portfolio/example_datasets/*.csv
13
+
14
+ # Finance Toolkit Normalization Files
15
+ !financetoolkit/normalization/*.csv
16
+
17
+ # Finance Toolkit Tests
18
+ !tests/datasets/*.xlsx
19
+ !tests/*/csv/*/*.csv
20
+ !tests/csv/*/*.csv
21
+
22
+ # VS Code
23
+ .agents
24
+ .vscode/
25
+ .claude/
26
+ *.sh
27
+
28
+ # Claude
29
+ CLAUDE.md
30
+
31
+ # Byte-compiled / optimized / DLL files
32
+ __pycache__/
33
+ *.py[cod]
34
+ *$py.class
35
+ .DS_Store
36
+ .ipynb_checkpoints/
37
+ .DS_Store
38
+
39
+ # C extensions
40
+ *.so
41
+
42
+ # Distribution / packaging
43
+ .Python
44
+ build/
45
+ develop-eggs/
46
+ dist/
47
+ downloads/
48
+ eggs/
49
+ .eggs/
50
+ lib/
51
+ lib64/
52
+ parts/
53
+ sdist/
54
+ var/
55
+ wheels/
56
+ share/python-wheels/
57
+ *.egg-info/
58
+ .installed.cfg
59
+ *.egg
60
+ MANIFEST
61
+
62
+ # PyInstaller
63
+ # Usually these files are written by a python script from a template
64
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
65
+ *.manifest
66
+ *.spec
67
+
68
+ # Installer logs
69
+ pip-log.txt
70
+ pip-delete-this-directory.txt
71
+
72
+ # Unit test / coverage reports
73
+ htmlcov/
74
+ .tox/
75
+ .nox/
76
+ .coverage
77
+ .coverage.*
78
+ .cache
79
+ nosetests.xml
80
+ coverage.xml
81
+ *.cover
82
+ *.py,cover
83
+ .hypothesis/
84
+ .pytest_cache/
85
+ cover/
86
+
87
+ # Translations
88
+ *.mo
89
+ *.pot
90
+
91
+ # Django stuff:
92
+ *.log
93
+ local_settings.py
94
+ db.sqlite3
95
+ db.sqlite3-journal
96
+
97
+ # Flask stuff:
98
+ instance/
99
+ .webassets-cache
100
+
101
+ # Scrapy stuff:
102
+ .scrapy
103
+
104
+ # Sphinx documentation
105
+ docs/_build/
106
+
107
+ # PyBuilder
108
+ .pybuilder/
109
+ target/
110
+
111
+ # Jupyter Notebook
112
+ .ipynb_checkpoints
113
+
114
+ # IPython
115
+ profile_default/
116
+ ipython_config.py
117
+
118
+ # pyenv
119
+ # For a library or package, you might want to ignore these files since the code is
120
+ # intended to run in multiple environments; otherwise, check them in:
121
+ # .python-version
122
+
123
+ # pipenv
124
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
125
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
126
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
127
+ # install all needed dependencies.
128
+ #Pipfile.lock
129
+
130
+ # poetry
131
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
132
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
133
+ # commonly ignored for libraries.
134
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
135
+ #poetry.lock
136
+
137
+ # pdm
138
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
139
+ #pdm.lock
140
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
141
+ # in version control.
142
+ # https://pdm.fming.dev/#use-with-ide
143
+ .pdm.toml
144
+
145
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
146
+ __pypackages__/
147
+
148
+ # Celery stuff
149
+ celerybeat-schedule
150
+ celerybeat.pid
151
+
152
+ # SageMath parsed files
153
+ *.sage.py
154
+
155
+ # Environments
156
+ .env
157
+ .venv
158
+ env/
159
+ venv/
160
+ ENV/
161
+ env.bak/
162
+ venv.bak/
163
+
164
+ # Spyder project settings
165
+ .spyderproject
166
+ .spyproject
167
+
168
+ # Rope project settings
169
+ .ropeproject
170
+
171
+ # mkdocs documentation
172
+ /site
173
+
174
+ # mypy
175
+ .mypy_cache/
176
+ .dmypy.json
177
+ dmypy.json
178
+
179
+ # Pyre type checker
180
+ .pyre/
181
+
182
+ # pytype static type analyzer
183
+ .pytype/
184
+
185
+ # Cython debug symbols
186
+ cython_debug/
187
+
188
+ # PyCharm
189
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
190
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
191
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
192
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
193
+ #.idea/
197
194
  articles/
@@ -1,7 +1,11 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: financetoolkit
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Transparent and Efficient Financial Analysis
5
+ Project-URL: Homepage, https://www.jeroenbouma.com/projects/financetoolkit
6
+ Project-URL: Documentation, https://www.jeroenbouma.com/projects/financetoolkit/docs
7
+ Project-URL: Repository, https://github.com/JerBouma/FinanceToolkit
8
+ Project-URL: Issues, https://github.com/JerBouma/FinanceToolkit/issues
5
9
  Author: Jeroen Bouma
6
10
  License: MIT
7
11
  License-File: LICENSE.txt
@@ -36,7 +40,6 @@ Requires-Dist: mcp[cli]<2,>=1.27.0; extra == 'mcp'
36
40
  Requires-Dist: python-dotenv>=1.0; extra == 'mcp'
37
41
  Requires-Dist: rich>=13.0; extra == 'mcp'
38
42
  Requires-Dist: statsmodels>=0.14; extra == 'mcp'
39
- Requires-Dist: tabulate>=0.9.0; extra == 'mcp'
40
43
  Description-Content-Type: text/markdown
41
44
 
42
45
  <!-- mcp-name: io.github.JerBouma/financetoolkit -->
@@ -29,6 +29,13 @@ DATABASE_FILE_NAME = "financetoolkit_cache.db"
29
29
  # Compacted into merged intervals past this many rows, to bound table growth.
30
30
  COVERAGE_COMPACTION_THRESHOLD = 16
31
31
 
32
+ # Point-in-time entries are kept at least this long after they were written, also past their
33
+ # time-to-live, since an expired entry still answers when its source cannot be reached.
34
+ STALE_ENTRY_RETENTION_SECONDS = 90 * policy_model.DAY
35
+
36
+ # How often the entries nobody asks for any more are removed.
37
+ EVICTION_INTERVAL_SECONDS = policy_model.DAY
38
+
32
39
  _CACHE_REGISTRY: dict[str, "Cache"] = {}
33
40
  _REGISTRY_LOCK = Lock()
34
41
 
@@ -103,7 +110,7 @@ def get_default_cache_location() -> Path:
103
110
  override = os.environ.get("FINANCE_TOOLKIT_CACHE_DB")
104
111
 
105
112
  if override:
106
- return Path(override).expanduser()
113
+ return Path(override).expanduser().absolute()
107
114
 
108
115
  if platform.system() == "Windows":
109
116
  base = Path(
@@ -113,7 +120,7 @@ def get_default_cache_location() -> Path:
113
120
  xdg_config_home = os.environ.get("XDG_CONFIG_HOME")
114
121
  base = Path(xdg_config_home) if xdg_config_home else Path.home() / ".config"
115
122
 
116
- return base / "financetoolkit" / DATABASE_FILE_NAME
123
+ return (base / "financetoolkit" / DATABASE_FILE_NAME).absolute()
117
124
 
118
125
 
119
126
  def resolve_cache_location(location: str | Path | None) -> Path:
@@ -133,7 +140,9 @@ def resolve_cache_location(location: str | Path | None) -> Path:
133
140
  if location is None:
134
141
  return get_default_cache_location()
135
142
 
136
- path = Path(location).expanduser()
143
+ # Absolute, so a relative folder keeps pointing at the same database after a change of
144
+ # working directory and caches opened from different directories are told apart.
145
+ path = Path(location).expanduser().absolute()
137
146
 
138
147
  if path.suffix in (".db", ".sqlite", ".sqlite3"):
139
148
  return path
@@ -283,6 +292,38 @@ class Cache:
283
292
  )
284
293
 
285
294
  self._warn_on_schema_mismatch()
295
+ self._remove_stale_entries()
296
+
297
+ def _remove_stale_entries(self) -> None:
298
+ """
299
+ Remove the point-in-time entries of every source that have not been refreshed for
300
+ longer than their time-to-live and the retention for unreachable sources, at most
301
+ once a day. The MCP server's responses are left to the server, which evicts them
302
+ on its own time-to-live.
303
+ """
304
+ try:
305
+ # A database of another schema version is left exactly as it is.
306
+ if (
307
+ self._backend is None
308
+ or self._backend.get_schema_version() != SCHEMA_VERSION
309
+ ):
310
+ return
311
+
312
+ evicted = self._backend.remove_stale_blobs(
313
+ lambda source, dataset: max(
314
+ policy_model.get_policy(source, dataset).ttl_seconds,
315
+ STALE_ENTRY_RETENTION_SECONDS,
316
+ ),
317
+ EVICTION_INTERVAL_SECONDS,
318
+ excluded_sources=frozenset({policy_model.MCP}),
319
+ )
320
+ except Exception as error: # pylint: disable=broad-except
321
+ # Eviction is housekeeping, so a failure here is not surfaced.
322
+ logger.debug("Could not evict stale cache entries: %s", error)
323
+ return
324
+
325
+ if evicted:
326
+ logger.debug("Removed %s stale cache entries.", evicted)
286
327
 
287
328
  def _warn_on_schema_mismatch(self) -> None:
288
329
  """
@@ -388,9 +429,9 @@ class Cache:
388
429
  start (str | date | None): Inclusive start of the requested range.
389
430
  end (str | date | None): Inclusive end of the requested range.
390
431
  parameters (dict[str, Any] | None): Parameters that change the data.
391
- date_axis (int): 0 when the index holds the dates, 1 when the columns do.
432
+ date_axis (int): 0 when the index holds the dates, 1 when the columns do. Defaults to 0.
392
433
  reference_date (date | None): The date the revision window is measured
393
- back from when the requested range has no end. Defaults to today;
434
+ back from when the requested range has no end or ends after it. Defaults to today;
394
435
  mainly useful for testing.
395
436
 
396
437
  Returns:
@@ -405,6 +446,10 @@ class Cache:
405
446
  coverage_model.normalize_date(start) if start else date(1900, 1, 1)
406
447
  )
407
448
  requested_end = coverage_model.normalize_date(end) if end else reference
449
+ # Nothing after today has been published yet, so a range that runs into the future is
450
+ # covered up to today and its revision window ends today, as an open range's does.
451
+ if requested_start <= reference < requested_end:
452
+ requested_end = reference
408
453
 
409
454
  if not self.serves(source):
410
455
  plan.missing = {
@@ -507,7 +552,7 @@ class Cache:
507
552
  start (str | date | None): Inclusive start of the range that was requested.
508
553
  end (str | date | None): Inclusive end of the range that was requested.
509
554
  parameters (dict[str, Any] | None): Parameters that change the data.
510
- date_axis (int): 0 when the index holds the dates, 1 when the columns do.
555
+ date_axis (int): 0 when the index holds the dates, 1 when the columns do. Defaults to 0.
511
556
  """
512
557
  if not self.serves(source):
513
558
  return
@@ -520,8 +565,10 @@ class Cache:
520
565
  if start
521
566
  else (bounds[0] if bounds else None)
522
567
  )
568
+ # A request that runs into the future holds what was published up to today; claiming the
569
+ # future as well would never ask for those days once they have passed.
523
570
  coverage_end = (
524
- coverage_model.normalize_date(end)
571
+ min(coverage_model.normalize_date(end), date.today()) # noqa: DTZ011
525
572
  if end
526
573
  else (bounds[1] if bounds else None)
527
574
  )
@@ -534,7 +581,12 @@ class Cache:
534
581
  coverage_start = min(coverage_start, bounds[0])
535
582
  coverage_end = max(coverage_end, bounds[1])
536
583
 
537
- coverage = (coverage_start, coverage_end)
584
+ # A bar of a session that has not closed is a snapshot: the day stays uncovered, so the next call asks for it again. # noqa: E501
585
+ if policy_model.get_policy(source, dataset).settles_at_close:
586
+ coverage_end = min(coverage_end, policy_model.get_last_closed_session())
587
+
588
+ if coverage_start <= coverage_end:
589
+ coverage = (coverage_start, coverage_end)
538
590
 
539
591
  def merge_payload(existing_payload: bytes | None) -> bytes:
540
592
  """
@@ -813,7 +865,7 @@ def get_cache(
813
865
  location (str | Path | None): Directory or database file to use. None
814
866
  selects the shared default location.
815
867
  enabled (bool): When False a disabled cache is returned, which misses on
816
- every read and ignores every write.
868
+ every read and ignores every write. Defaults to True.
817
869
  excluded_sources (frozenset[str] | set[str] | None): Sources this cache never
818
870
  reads or writes, see Cache. Defaults to None.
819
871
 
@@ -829,12 +881,14 @@ def get_cache(
829
881
  registry_key = f"{resolved}|{','.join(sorted(excluded))}"
830
882
 
831
883
  with _REGISTRY_LOCK:
832
- if registry_key not in _CACHE_REGISTRY:
833
- _CACHE_REGISTRY[registry_key] = Cache(
834
- location=location, enabled=True, excluded_sources=excluded
835
- )
884
+ cache = _CACHE_REGISTRY.get(registry_key)
885
+ if cache is not None:
886
+ return cache
836
887
 
837
- return _CACHE_REGISTRY[registry_key]
888
+ # Opened outside the lock: opening evicts stale entries once a day, which can wait for another process's write lock, and that would hold up every other caller meanwhile. When two threads open the same location at once, the first instance registered is kept. # noqa: E501
889
+ cache = Cache(location=location, enabled=True, excluded_sources=excluded)
890
+ with _REGISTRY_LOCK:
891
+ return _CACHE_REGISTRY.setdefault(registry_key, cache)
838
892
 
839
893
 
840
894
  def reset_cache_registry() -> None: