financetoolkit 2.3.0__tar.gz → 2.3.1__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.1}/PKG-INFO +5 -2
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/cache_controller.py +64 -14
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/policy_model.py +3 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/sqlite_model.py +96 -13
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/currencies_model.py +15 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/discovery/discovery_controller.py +39 -29
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/discovery/discovery_model.py +164 -32
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/cointegration_model.py +19 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/diagnostics_model.py +3 -2
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/econometrics_controller.py +102 -52
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/regression_model.py +100 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/state_space_model.py +7 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/unitroot_model.py +12 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/economics_controller.py +84 -83
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/helpers.py +8 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/imf_model.py +13 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/etf/etf_controller.py +93 -57
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/bond_model.py +46 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/derivative_model.py +34 -17
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/fixedincome_controller.py +13 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/fred_model.py +5 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/short_rate_model.py +10 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fmp_model.py +148 -29
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fundamentals_model.py +50 -35
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/helpers.py +127 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/historical_model.py +113 -41
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/analytics_model.py +122 -19
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/auth_model.py +344 -90
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/coercion_model.py +37 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/config.yaml +25 -11
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/diagnostics_model.py +17 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/formatting_model.py +16 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/inspection_controller.py +60 -29
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/mcp_controller.py +16 -2
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/mcpb/manifest.json +10 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/mcpb/pyproject.toml +3 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/provider_model.py +174 -9
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/registry_controller.py +391 -19
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/series_model.py +15 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/setup_model.py +78 -35
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/tools_model.py +16 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/models_controller.py +144 -63
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/wacc_model.py +6 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization/statistics.csv +2 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization_model.py +171 -62
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/binomial_trees_model.py +15 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/black_scholes_model.py +26 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/exotics_model.py +6 -2
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/greeks_model.py +3 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/helpers.py +3 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/options_controller.py +103 -60
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/options_model.py +30 -10
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/performance/performance_controller.py +76 -35
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/performance/performance_model.py +50 -13
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/attribution_model.py +23 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/config.yaml +4 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/construction_controller.py +76 -21
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/helpers.py +53 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/optimization_model.py +84 -10
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/overview_model.py +84 -17
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/portfolio_controller.py +241 -37
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/portfolio_model.py +63 -29
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/ratios/helpers.py +7 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/ratios/ratios_controller.py +250 -117
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/cvar_model.py +8 -6
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/garch_model.py +29 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/risk_controller.py +77 -36
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/risk_model.py +116 -31
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/var_model.py +3 -1
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/technicals/breadth_model.py +64 -28
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/technicals/momentum_model.py +23 -7
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/technicals/overlap_model.py +23 -11
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/technicals/technicals_controller.py +219 -238
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/technicals/volatility_model.py +6 -3
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/toolkit_controller.py +411 -107
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/utilities/error_model.py +18 -5
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/utilities/statistics_model.py +88 -23
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/utilities/validation_model.py +22 -10
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/yfinance_model.py +4 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/pyproject.toml +9 -4
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/.gitignore +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/LICENSE.txt +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/README.md +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/coverage_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/frame_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/request_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/serialization_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/cache/ticker_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/discovery/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/causal_inference_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/causality_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/data_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/event_study_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/fama_macbeth_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/forecast_evaluation_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/hypothesis_testing_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/pairs_trading_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/panel_data_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/regime_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/specification_tests_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/econometrics/time_series_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/bis_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/bls_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/boe_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/boj_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/cboe_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/dnb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/ecb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/eex_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/esrb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/eurostat_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/fmp_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/frb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/fred_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/freddie_mac_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/gmdb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/ibge_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/macrohistory_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/mof_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/nber_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/ngfs_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/oecd_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/ons_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/sbj_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/shiller_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/stoxx_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/treasury_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/economics/yfinance_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/etf/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/etf/etf_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/boc_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/bundesbank_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/curve_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/ecb_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/eiopa_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/esma_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/euribor_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/fed_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/fiscaldata_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/fmp_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/helpers.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/norgesbank_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/rba_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/riksbank_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/fixedincome/yieldcurve_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/__main__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/mcpb/.mcpbignore +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/mcpb/LICENSE +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/mcpb/README.md +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/mcpb/build-mcpb.sh +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/mcpb/finance_toolkit_icon.png +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/static/apple-touch-icon.png +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/static/favicon-32.png +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/static/favicon.ico +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/mcp_server/stats_page_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/altman_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/beneish_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/credit_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/damodaran_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/dupont_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/enterprise_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/eva_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/fulmer_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/grover_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/growth_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/helpers.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/intrinsic_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/ohlson_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/peers_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/piotroski_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/quality_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/springate_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/models/zmijewski_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization/balance.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization/balance_yf.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization/cash.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization/cash_yf.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization/income.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization/income_yf.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/normalization/statistics_yf.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/market_metrics_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/risk_neutral_density_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/options/svi_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/performance/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/performance/helpers.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/definition_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/example_datasets/example_portfolio.csv +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/example_datasets/example_portfolio.xlsx +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/all_weather.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/balanced_60_40.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/barbell.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/bogleheads_three_fund.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/buffett_90_10.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/conservative_income.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/global_60_40.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/global_equity_growth.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/golden_butterfly.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/permanent_portfolio.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/small_cap_value_tilt.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/target_date_glidepath.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/portfolio/presets/us_equity_sectors.yaml +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/py.typed +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/ratios/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/ratios/efficiency_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/ratios/liquidity_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/ratios/profitability_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/ratios/solvency_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/ratios/valuation_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/backtesting_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/copula_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/covar_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/evar_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/helpers.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/market_liquidity_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/risk/realized_volatility_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/technicals/__init__.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/technicals/seasonality_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/utilities/dataframe_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/utilities/excel_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/utilities/logger_model.py +0 -0
- {financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/utilities/requests_model.py +0 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: financetoolkit
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
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,8 @@ class Cache:
|
|
|
534
581
|
coverage_start = min(coverage_start, bounds[0])
|
|
535
582
|
coverage_end = max(coverage_end, bounds[1])
|
|
536
583
|
|
|
537
|
-
|
|
584
|
+
if coverage_start <= coverage_end:
|
|
585
|
+
coverage = (coverage_start, coverage_end)
|
|
538
586
|
|
|
539
587
|
def merge_payload(existing_payload: bytes | None) -> bytes:
|
|
540
588
|
"""
|
|
@@ -813,7 +861,7 @@ def get_cache(
|
|
|
813
861
|
location (str | Path | None): Directory or database file to use. None
|
|
814
862
|
selects the shared default location.
|
|
815
863
|
enabled (bool): When False a disabled cache is returned, which misses on
|
|
816
|
-
every read and ignores every write.
|
|
864
|
+
every read and ignores every write. Defaults to True.
|
|
817
865
|
excluded_sources (frozenset[str] | set[str] | None): Sources this cache never
|
|
818
866
|
reads or writes, see Cache. Defaults to None.
|
|
819
867
|
|
|
@@ -829,12 +877,14 @@ def get_cache(
|
|
|
829
877
|
registry_key = f"{resolved}|{','.join(sorted(excluded))}"
|
|
830
878
|
|
|
831
879
|
with _REGISTRY_LOCK:
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
)
|
|
880
|
+
cache = _CACHE_REGISTRY.get(registry_key)
|
|
881
|
+
if cache is not None:
|
|
882
|
+
return cache
|
|
836
883
|
|
|
837
|
-
|
|
884
|
+
# 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
|
|
885
|
+
cache = Cache(location=location, enabled=True, excluded_sources=excluded)
|
|
886
|
+
with _REGISTRY_LOCK:
|
|
887
|
+
return _CACHE_REGISTRY.setdefault(registry_key, cache)
|
|
838
888
|
|
|
839
889
|
|
|
840
890
|
def reset_cache_registry() -> None:
|
|
@@ -47,9 +47,9 @@ DE_NEDERLANDSCHE_BANK = "DeNederlandscheBank"
|
|
|
47
47
|
EUROPEAN_SYSTEMIC_RISK_BOARD = "ESRB"
|
|
48
48
|
DAMODARAN = "Damodaran"
|
|
49
49
|
|
|
50
|
-
# The market risk premium is published per country, so it is one cache entry.
|
|
51
|
-
#
|
|
52
|
-
#
|
|
50
|
+
# The market risk premium is published per country, so it is one cache entry. The name
|
|
51
|
+
# marks the premiums as decimals, so an entry holding percentages under another name is
|
|
52
|
+
# never read back as decimals.
|
|
53
53
|
MARKET_RISK_PREMIUM_ENTITY = "global_decimals"
|
|
54
54
|
|
|
55
55
|
|
|
@@ -20,6 +20,10 @@ SCHEMA_VERSION = 1
|
|
|
20
20
|
# How long a writer waits for another process to release the write lock.
|
|
21
21
|
BUSY_TIMEOUT_SECONDS = 30
|
|
22
22
|
|
|
23
|
+
# A database up to this size is compacted after an eviction freed most of it; a larger one
|
|
24
|
+
# would hold every other process off the cache for too long while it is rewritten.
|
|
25
|
+
VACUUM_MAXIMUM_BYTES = 256 * 1024 * 1024
|
|
26
|
+
|
|
23
27
|
# Three tables; source and dataset stay plain columns so clearing can be scoped.
|
|
24
28
|
SCHEMA_STATEMENTS = (
|
|
25
29
|
"""
|
|
@@ -130,10 +134,15 @@ class SQLiteBackend:
|
|
|
130
134
|
the block, so that every statement inside it commits or rolls back
|
|
131
135
|
as one unit. False opens a plain read connection.
|
|
132
136
|
|
|
137
|
+
Only writers take the instance lock, so the threads of one process queue for the
|
|
138
|
+
write lock here instead of each waiting out SQLite's busy timeout. Readers never
|
|
139
|
+
take it: under write-ahead logging they read alongside a writer, also while that
|
|
140
|
+
writer waits for another process to release the database.
|
|
141
|
+
|
|
133
142
|
Yields:
|
|
134
|
-
sqlite3.Connection: An open connection guarded by the instance lock.
|
|
143
|
+
sqlite3.Connection: An open connection, guarded by the instance lock when writing.
|
|
135
144
|
"""
|
|
136
|
-
with self._lock:
|
|
145
|
+
with self._lock if write else contextlib.nullcontext():
|
|
137
146
|
connection = sqlite3.connect(
|
|
138
147
|
self._database_location,
|
|
139
148
|
timeout=BUSY_TIMEOUT_SECONDS,
|
|
@@ -277,8 +286,8 @@ class SQLiteBackend:
|
|
|
277
286
|
|
|
278
287
|
Reading the coverage and the payload over three separate connections lets
|
|
279
288
|
a concurrent writer commit in between, so the planner could see coverage
|
|
280
|
-
that does not describe the payload it read.
|
|
281
|
-
consistent view of both.
|
|
289
|
+
that does not describe the payload it read. One read transaction on a single
|
|
290
|
+
connection gives one consistent view of both.
|
|
282
291
|
|
|
283
292
|
Args:
|
|
284
293
|
key (str): The dataset key.
|
|
@@ -292,15 +301,20 @@ class SQLiteBackend:
|
|
|
292
301
|
stored payload (None when nothing is cached).
|
|
293
302
|
"""
|
|
294
303
|
with self._connect() as connection:
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
(
|
|
303
|
-
|
|
304
|
+
# One read transaction, so both SELECTs see the same snapshot; in autocommit mode each would take its own. # noqa: E501
|
|
305
|
+
connection.execute("BEGIN")
|
|
306
|
+
try:
|
|
307
|
+
ever_rows = connection.execute(
|
|
308
|
+
"SELECT start_date, end_date, fetched_at FROM coverage "
|
|
309
|
+
"WHERE key = ? AND entity = ?",
|
|
310
|
+
(key, entity),
|
|
311
|
+
).fetchall()
|
|
312
|
+
payload_row = connection.execute(
|
|
313
|
+
"SELECT payload FROM series WHERE key = ? AND entity = ?",
|
|
314
|
+
(key, entity),
|
|
315
|
+
).fetchone()
|
|
316
|
+
finally:
|
|
317
|
+
connection.execute("COMMIT")
|
|
304
318
|
|
|
305
319
|
ever_covered = [
|
|
306
320
|
(normalize_date(start), normalize_date(end)) for start, end, _ in ever_rows
|
|
@@ -671,6 +685,75 @@ class SQLiteBackend:
|
|
|
671
685
|
|
|
672
686
|
return deleted
|
|
673
687
|
|
|
688
|
+
def remove_stale_blobs(
|
|
689
|
+
self,
|
|
690
|
+
maximum_age: Callable[[str, str], float],
|
|
691
|
+
interval: float,
|
|
692
|
+
excluded_sources: frozenset[str] = frozenset(),
|
|
693
|
+
) -> int:
|
|
694
|
+
"""
|
|
695
|
+
Delete the point-in-time entries of every source that have not been refreshed for
|
|
696
|
+
longer than their dataset allows, at most once per interval.
|
|
697
|
+
|
|
698
|
+
An entry that is read again is refreshed by its next fetch, so only entries nobody
|
|
699
|
+
asks for any more pile up. The time of the last run is kept in the database, so
|
|
700
|
+
every process sharing it runs this once per interval in total. When the deletes
|
|
701
|
+
free more than half of a small database, it is compacted as well.
|
|
702
|
+
|
|
703
|
+
Args:
|
|
704
|
+
maximum_age (Callable[[str, str], float]): The age in seconds after which an
|
|
705
|
+
entry of a source and dataset is removed.
|
|
706
|
+
interval (float): The minimum number of seconds between two runs.
|
|
707
|
+
excluded_sources (frozenset[str]): Sources that evict their own entries.
|
|
708
|
+
|
|
709
|
+
Returns:
|
|
710
|
+
int: The number of entries deleted, 0 when the interval has not passed.
|
|
711
|
+
"""
|
|
712
|
+
now = time.time()
|
|
713
|
+
deleted = 0
|
|
714
|
+
|
|
715
|
+
with self._connect(write=True) as connection:
|
|
716
|
+
row = connection.execute(
|
|
717
|
+
"SELECT value FROM meta WHERE name = ?", ("last_blob_eviction",)
|
|
718
|
+
).fetchone()
|
|
719
|
+
|
|
720
|
+
if row is not None and now - float(row[0]) < interval:
|
|
721
|
+
return 0
|
|
722
|
+
|
|
723
|
+
connection.execute(
|
|
724
|
+
"INSERT OR REPLACE INTO meta (name, value) VALUES (?, ?)",
|
|
725
|
+
("last_blob_eviction", str(now)),
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
scopes = connection.execute(
|
|
729
|
+
"SELECT DISTINCT source, dataset FROM blobs"
|
|
730
|
+
).fetchall()
|
|
731
|
+
|
|
732
|
+
for source, dataset in scopes:
|
|
733
|
+
if source in excluded_sources:
|
|
734
|
+
continue
|
|
735
|
+
|
|
736
|
+
deleted += connection.execute(
|
|
737
|
+
"DELETE FROM blobs WHERE source = ? AND dataset = ? AND updated_at < ?",
|
|
738
|
+
(source, dataset, now - maximum_age(source, dataset)),
|
|
739
|
+
).rowcount
|
|
740
|
+
|
|
741
|
+
page_count = connection.execute("PRAGMA page_count").fetchone()[0]
|
|
742
|
+
free_pages = connection.execute("PRAGMA freelist_count").fetchone()[0]
|
|
743
|
+
|
|
744
|
+
database_path = Path(self._database_location)
|
|
745
|
+
if (
|
|
746
|
+
deleted
|
|
747
|
+
and free_pages * 2 > page_count
|
|
748
|
+
and database_path.exists()
|
|
749
|
+
and database_path.stat().st_size <= VACUUM_MAXIMUM_BYTES
|
|
750
|
+
):
|
|
751
|
+
# VACUUM cannot run inside a transaction, so it takes a plain connection.
|
|
752
|
+
with self._lock, self._connect() as connection:
|
|
753
|
+
connection.execute("VACUUM")
|
|
754
|
+
|
|
755
|
+
return deleted
|
|
756
|
+
|
|
674
757
|
def clear_all(self) -> int:
|
|
675
758
|
"""
|
|
676
759
|
Remove every cached entry regardless of age.
|
|
@@ -190,6 +190,12 @@ CURRENCY_CODES: frozenset[str] = frozenset(
|
|
|
190
190
|
) # codespell:ignore zar
|
|
191
191
|
|
|
192
192
|
|
|
193
|
+
# How old the last published rate may be on a period end before the period has no rate.
|
|
194
|
+
# Sparse or exotic pairs can go a few weeks without a quote, so only a rate older than a
|
|
195
|
+
# month marks a series that ended before the period did.
|
|
196
|
+
STALE_RATE_DAYS = pd.Timedelta(days=31)
|
|
197
|
+
|
|
198
|
+
|
|
193
199
|
def is_currency_pair(ticker: str) -> bool:
|
|
194
200
|
"""
|
|
195
201
|
Returns whether a ticker is a forex pair: six letters, optionally followed by "=X" as
|
|
@@ -474,11 +480,17 @@ def get_statement_exchange_rates(
|
|
|
474
480
|
]
|
|
475
481
|
else:
|
|
476
482
|
dates = end_dates if rate == "closing" else start_dates
|
|
477
|
-
# The last published rate on or before each date
|
|
483
|
+
# The last published rate on or before each date, unless that rate is more than
|
|
484
|
+
# a month old: a period ending after the rates do has no rate yet.
|
|
478
485
|
positions = currency_rates.index.searchsorted(dates, side="right") - 1
|
|
479
486
|
values = [
|
|
480
|
-
|
|
481
|
-
|
|
487
|
+
(
|
|
488
|
+
currency_rates.iloc[position]
|
|
489
|
+
if position >= 0
|
|
490
|
+
and date - currency_rates.index[position] <= STALE_RATE_DAYS
|
|
491
|
+
else float("nan")
|
|
492
|
+
)
|
|
493
|
+
for position, date in zip(positions, dates, strict=True)
|
|
482
494
|
]
|
|
483
495
|
|
|
484
496
|
rates[ticker] = pd.Series(values, index=end_dates.index, dtype="float64")
|
{financetoolkit-2.3.0 → financetoolkit-2.3.1}/financetoolkit/discovery/discovery_controller.py
RENAMED
|
@@ -214,14 +214,14 @@ class Discovery:
|
|
|
214
214
|
self,
|
|
215
215
|
market_cap_higher: int | None = None,
|
|
216
216
|
market_cap_lower: int | None = None,
|
|
217
|
-
price_higher:
|
|
218
|
-
price_lower:
|
|
219
|
-
beta_higher:
|
|
220
|
-
beta_lower:
|
|
217
|
+
price_higher: float | None = None,
|
|
218
|
+
price_lower: float | None = None,
|
|
219
|
+
beta_higher: float | None = None,
|
|
220
|
+
beta_lower: float | None = None,
|
|
221
221
|
volume_higher: int | None = None,
|
|
222
222
|
volume_lower: int | None = None,
|
|
223
|
-
dividend_higher:
|
|
224
|
-
dividend_lower:
|
|
223
|
+
dividend_higher: float | None = None,
|
|
224
|
+
dividend_lower: float | None = None,
|
|
225
225
|
sector: str | None = None,
|
|
226
226
|
industry: str | None = None,
|
|
227
227
|
country: str | None = None,
|
|
@@ -250,22 +250,32 @@ class Discovery:
|
|
|
250
250
|
|
|
251
251
|
Args:
|
|
252
252
|
market_cap_higher (int): The minimum market capitalization of the stock in US dollars
|
|
253
|
-
(not in millions), e.g. 1_000_000_000 for $1 billion.
|
|
253
|
+
(not in millions), e.g. 1_000_000_000 for $1 billion. Defaults to None, which applies no filter.
|
|
254
254
|
market_cap_lower (int): The maximum market capitalization of the stock in US dollars.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
255
|
+
The screener returns the largest companies first, so this bound is only sent to it
|
|
256
|
+
when the currency of the listings is known: with an exchange, or with a country and
|
|
257
|
+
primary_only. Otherwise it is applied to the companies returned. Defaults to None,
|
|
258
|
+
which applies no filter.
|
|
259
|
+
price_higher (float | None): The minimum price of the stock. Defaults to None, which applies no filter.
|
|
260
|
+
price_lower (float | None): The maximum price of the stock. Defaults to None, which applies no filter.
|
|
261
|
+
beta_higher (float | None): The minimum beta of the stock. Defaults to None, which applies no filter.
|
|
262
|
+
beta_lower (float | None): The maximum beta of the stock. Defaults to None, which applies no filter.
|
|
263
|
+
volume_higher (int): The minimum volume of the stock, in shares traded. Defaults to None, which applies no
|
|
264
|
+
filter.
|
|
265
|
+
volume_lower (int): The maximum volume of the stock. Defaults to None, which applies no filter.
|
|
266
|
+
dividend_higher (float | None): The minimum dividend of the stock, as an amount per share
|
|
267
|
+
over the last annual period rather than as a yield. Defaults to None, which applies no filter.
|
|
268
|
+
dividend_lower (float | None): The maximum dividend of the stock. Defaults to None, which applies no filter.
|
|
269
|
+
sector (str | None): The sector to restrict the screen to, e.g. "Energy". Defaults to None, which applies no
|
|
270
|
+
filter.
|
|
271
|
+
industry (str | None): The industry to restrict the screen to, e.g. "Biotechnology". Defaults to None, which
|
|
272
|
+
applies no filter.
|
|
273
|
+
country (str | None): The country to restrict the screen to, as a two-letter code ("US")
|
|
274
|
+
or a name ("United States"). Defaults to None, which applies no filter.
|
|
275
|
+
exchange (str | None): The exchange code to restrict the screen to, e.g. "NASDAQ". Defaults to None, which
|
|
276
|
+
applies no filter.
|
|
277
|
+
is_etf (bool | None): Whether to restrict the screen to ETFs or to exclude them. Defaults to None, which
|
|
278
|
+
applies no filter.
|
|
269
279
|
limit (int): The maximum number of companies to return. Defaults to 1000.
|
|
270
280
|
primary_only (bool): Whether to keep only the home listing of each company (on an
|
|
271
281
|
exchange in its own country, the most traded one among several) rather than
|
|
@@ -1666,8 +1676,8 @@ class Discovery:
|
|
|
1666
1676
|
Also known as: sector performance snapshot, sector performance history, sector trend.
|
|
1667
1677
|
|
|
1668
1678
|
Args:
|
|
1669
|
-
date (str, optional): The date to retrieve a snapshot for, e.g. "2024-02-01".
|
|
1670
|
-
sector (str, optional): The sector to retrieve the history for, e.g. "Energy".
|
|
1679
|
+
date (str, optional): The date to retrieve a snapshot for, e.g. "2024-02-01". Defaults to None.
|
|
1680
|
+
sector (str, optional): The sector to retrieve the history for, e.g. "Energy". Defaults to None.
|
|
1671
1681
|
start_date (str, optional): The start of the history of one sector. Defaults to a year
|
|
1672
1682
|
ago.
|
|
1673
1683
|
end_date (str, optional): The end of the history of one sector. Defaults to today.
|
|
@@ -1735,8 +1745,8 @@ class Discovery:
|
|
|
1735
1745
|
Also known as: industry performance snapshot, industry performance history, industry trend.
|
|
1736
1746
|
|
|
1737
1747
|
Args:
|
|
1738
|
-
date (str, optional): The date to retrieve a snapshot for, e.g. "2024-02-01".
|
|
1739
|
-
industry (str, optional): The industry to retrieve the history for, e.g. "Biotechnology".
|
|
1748
|
+
date (str, optional): The date to retrieve a snapshot for, e.g. "2024-02-01". Defaults to None.
|
|
1749
|
+
industry (str, optional): The industry to retrieve the history for, e.g. "Biotechnology". Defaults to None.
|
|
1740
1750
|
start_date (str, optional): The start of the history of one industry. Defaults to a year
|
|
1741
1751
|
ago.
|
|
1742
1752
|
end_date (str, optional): The end of the history of one industry. Defaults to today.
|
|
@@ -1803,8 +1813,8 @@ class Discovery:
|
|
|
1803
1813
|
Also known as: sector P/E snapshot, sector P/E history, sector valuation trend.
|
|
1804
1814
|
|
|
1805
1815
|
Args:
|
|
1806
|
-
date (str, optional): The date to retrieve a snapshot for, e.g. "2024-02-01".
|
|
1807
|
-
sector (str, optional): The sector to retrieve the history for, e.g. "Energy".
|
|
1816
|
+
date (str, optional): The date to retrieve a snapshot for, e.g. "2024-02-01". Defaults to None.
|
|
1817
|
+
sector (str, optional): The sector to retrieve the history for, e.g. "Energy". Defaults to None.
|
|
1808
1818
|
start_date (str, optional): The start of the history of one sector. Defaults to a year
|
|
1809
1819
|
ago.
|
|
1810
1820
|
end_date (str, optional): The end of the history of one sector. Defaults to today.
|
|
@@ -1872,8 +1882,8 @@ class Discovery:
|
|
|
1872
1882
|
Also known as: industry P/E snapshot, industry P/E history, industry valuation trend.
|
|
1873
1883
|
|
|
1874
1884
|
Args:
|
|
1875
|
-
date (str, optional): The date to retrieve a snapshot for, e.g. "2024-02-01".
|
|
1876
|
-
industry (str, optional): The industry to retrieve the history for, e.g. "Biotechnology".
|
|
1885
|
+
date (str, optional): The date to retrieve a snapshot for, e.g. "2024-02-01". Defaults to None.
|
|
1886
|
+
industry (str, optional): The industry to retrieve the history for, e.g. "Biotechnology". Defaults to None.
|
|
1877
1887
|
start_date (str, optional): The start of the history of one industry. Defaults to a year
|
|
1878
1888
|
ago.
|
|
1879
1889
|
end_date (str, optional): The end of the history of one industry. Defaults to today.
|