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.
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/.gitignore +193 -196
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/PKG-INFO +5 -2
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/cache_controller.py +68 -14
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/policy_model.py +64 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/sqlite_model.py +96 -13
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/currencies_model.py +15 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/discovery/discovery_controller.py +278 -51
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/discovery/discovery_model.py +333 -37
- financetoolkit-2.3.2/financetoolkit/earnings_model.py +113 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/cointegration_model.py +19 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/diagnostics_model.py +3 -2
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/econometrics_controller.py +102 -52
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/regression_model.py +100 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/state_space_model.py +7 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/unitroot_model.py +12 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/bis_model.py +67 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/economics_controller.py +490 -83
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/helpers.py +8 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/imf_model.py +13 -1
- financetoolkit-2.3.2/financetoolkit/economics/nyfed_model.py +120 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/etf/etf_controller.py +535 -57
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/etf/etf_model.py +93 -0
- financetoolkit-2.3.2/financetoolkit/finra_model.py +311 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/bond_model.py +46 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/derivative_model.py +34 -17
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fixedincome_controller.py +127 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fred_model.py +5 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/short_rate_model.py +10 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fmp_model.py +579 -29
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fundamentals_model.py +50 -35
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/helpers.py +127 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/historical_model.py +129 -41
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/analytics_model.py +122 -19
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/auth_model.py +344 -90
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/coercion_model.py +37 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/config.yaml +75 -39
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/diagnostics_model.py +17 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/formatting_model.py +27 -2
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/inspection_controller.py +60 -29
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcp_controller.py +26 -9
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/.mcpbignore +0 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/README.md +7 -16
- financetoolkit-2.3.2/financetoolkit/mcp_server/mcpb/manifest.json +190 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/pyproject.toml +3 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/provider_model.py +174 -9
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/registry_controller.py +551 -35
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/series_model.py +15 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/setup_model.py +181 -103
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/tools_model.py +32 -5
- financetoolkit-2.3.2/financetoolkit/models/damodaran_model.py +255 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/growth_model.py +88 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/intrinsic_model.py +173 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/models_controller.py +1090 -89
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/quality_model.py +49 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/wacc_model.py +6 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/statistics.csv +2 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization_model.py +171 -62
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/binomial_trees_model.py +15 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/black_scholes_model.py +26 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/exotics_model.py +6 -2
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/greeks_model.py +3 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/helpers.py +3 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/options_controller.py +103 -60
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/options_model.py +30 -10
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/performance/performance_controller.py +929 -41
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/performance/performance_model.py +710 -13
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/attribution_model.py +23 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/config.yaml +4 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/construction_controller.py +225 -59
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/helpers.py +53 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/optimization_model.py +265 -12
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/overview_model.py +84 -17
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/portfolio_controller.py +241 -37
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/portfolio_model.py +63 -29
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/helpers.py +7 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/ratios_controller.py +1043 -216
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/cvar_model.py +8 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/garch_model.py +29 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/risk_controller.py +629 -37
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/risk_model.py +326 -31
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/var_model.py +3 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/breadth_model.py +64 -28
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/momentum_model.py +23 -7
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/overlap_model.py +23 -11
- financetoolkit-2.3.2/financetoolkit/technicals/pattern_model.py +579 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/technicals_controller.py +973 -249
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/volatility_model.py +6 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/toolkit_controller.py +1358 -139
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/error_model.py +18 -5
- financetoolkit-2.3.2/financetoolkit/utilities/factor_model.py +745 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/statistics_model.py +183 -25
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/validation_model.py +22 -10
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/yfinance_model.py +26 -12
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/pyproject.toml +9 -4
- financetoolkit-2.3.0/financetoolkit/mcp_server/mcpb/build-mcpb.sh +0 -103
- financetoolkit-2.3.0/financetoolkit/mcp_server/mcpb/manifest.json +0 -186
- financetoolkit-2.3.0/financetoolkit/models/damodaran_model.py +0 -84
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/LICENSE.txt +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/README.md +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/coverage_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/frame_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/request_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/serialization_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/cache/ticker_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/discovery/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/causal_inference_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/causality_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/data_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/event_study_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/fama_macbeth_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/forecast_evaluation_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/hypothesis_testing_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/pairs_trading_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/panel_data_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/regime_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/specification_tests_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/econometrics/time_series_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/bls_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/boe_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/boj_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/cboe_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/dnb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/ecb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/eex_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/esrb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/eurostat_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/fmp_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/frb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/fred_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/freddie_mac_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/gmdb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/ibge_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/macrohistory_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/mof_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/nber_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/ngfs_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/oecd_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/ons_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/sbj_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/shiller_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/stoxx_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/treasury_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/economics/yfinance_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/etf/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/boc_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/bundesbank_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/curve_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/ecb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/eiopa_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/esma_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/euribor_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fed_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fiscaldata_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/fmp_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/helpers.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/norgesbank_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/rba_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/riksbank_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/fixedincome/yieldcurve_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/__main__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/LICENSE +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/mcpb/finance_toolkit_icon.png +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/static/apple-touch-icon.png +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/static/favicon-32.png +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/static/favicon.ico +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/mcp_server/stats_page_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/altman_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/beneish_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/credit_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/dupont_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/enterprise_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/eva_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/fulmer_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/grover_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/helpers.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/ohlson_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/peers_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/piotroski_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/springate_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/models/zmijewski_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/balance.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/balance_yf.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/cash.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/cash_yf.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/income.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/income_yf.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/normalization/statistics_yf.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/market_metrics_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/risk_neutral_density_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/options/svi_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/performance/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/performance/helpers.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/definition_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/example_datasets/example_portfolio.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/example_datasets/example_portfolio.xlsx +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/all_weather.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/balanced_60_40.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/barbell.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/bogleheads_three_fund.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/buffett_90_10.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/conservative_income.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/global_60_40.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/global_equity_growth.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/golden_butterfly.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/permanent_portfolio.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/small_cap_value_tilt.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/target_date_glidepath.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/portfolio/presets/us_equity_sectors.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/py.typed +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/efficiency_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/liquidity_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/profitability_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/solvency_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/ratios/valuation_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/backtesting_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/copula_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/covar_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/evar_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/helpers.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/market_liquidity_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/risk/realized_volatility_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/technicals/seasonality_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/dataframe_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/excel_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.2}/financetoolkit/utilities/logger_model.py +0 -0
- {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
|
-
#
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
.
|
|
78
|
-
.
|
|
79
|
-
.
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
*.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
.
|
|
103
|
-
|
|
104
|
-
#
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
#
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
#
|
|
122
|
-
|
|
123
|
-
#
|
|
124
|
-
# .
|
|
125
|
-
|
|
126
|
-
# pipenv
|
|
127
|
-
#
|
|
128
|
-
#
|
|
129
|
-
|
|
130
|
-
#
|
|
131
|
-
#Pipfile.lock
|
|
132
|
-
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
# pdm
|
|
141
|
-
#
|
|
142
|
-
#pdm.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
#
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
#
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
env/
|
|
162
|
-
venv/
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
.
|
|
170
|
-
|
|
171
|
-
#
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
#
|
|
175
|
-
/
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
#
|
|
183
|
-
.
|
|
184
|
-
|
|
185
|
-
#
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
#
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
#
|
|
192
|
-
#
|
|
193
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
)
|
|
884
|
+
cache = _CACHE_REGISTRY.get(registry_key)
|
|
885
|
+
if cache is not None:
|
|
886
|
+
return cache
|
|
836
887
|
|
|
837
|
-
|
|
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:
|