onefinance 0.1.0__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 (56) hide show
  1. onefinance-0.1.0/.gitignore +254 -0
  2. onefinance-0.1.0/.python-version +1 -0
  3. onefinance-0.1.0/LICENSE +21 -0
  4. onefinance-0.1.0/PKG-INFO +175 -0
  5. onefinance-0.1.0/README.md +146 -0
  6. onefinance-0.1.0/onefinance/__init__.py +74 -0
  7. onefinance-0.1.0/onefinance/audit/__init__.py +23 -0
  8. onefinance-0.1.0/onefinance/audit/log.py +325 -0
  9. onefinance-0.1.0/onefinance/audit/models.py +116 -0
  10. onefinance-0.1.0/onefinance/cache/__init__.py +11 -0
  11. onefinance-0.1.0/onefinance/cache/keys.py +62 -0
  12. onefinance-0.1.0/onefinance/cache/manager.py +363 -0
  13. onefinance-0.1.0/onefinance/cli/__init__.py +1 -0
  14. onefinance-0.1.0/onefinance/cli/__main__.py +4 -0
  15. onefinance-0.1.0/onefinance/cli/app.py +1131 -0
  16. onefinance-0.1.0/onefinance/cli/format.py +87 -0
  17. onefinance-0.1.0/onefinance/core/__init__.py +1 -0
  18. onefinance-0.1.0/onefinance/core/client.py +753 -0
  19. onefinance-0.1.0/onefinance/core/config.py +223 -0
  20. onefinance-0.1.0/onefinance/core/errors.py +174 -0
  21. onefinance-0.1.0/onefinance/core/models.py +378 -0
  22. onefinance-0.1.0/onefinance/core/router.py +409 -0
  23. onefinance-0.1.0/onefinance/indicators/__init__.py +16 -0
  24. onefinance-0.1.0/onefinance/indicators/core.py +284 -0
  25. onefinance-0.1.0/onefinance/providers/__init__.py +1 -0
  26. onefinance-0.1.0/onefinance/providers/_utils.py +23 -0
  27. onefinance-0.1.0/onefinance/providers/base.py +196 -0
  28. onefinance-0.1.0/onefinance/providers/finnhub.py +712 -0
  29. onefinance-0.1.0/onefinance/providers/fmp.py +885 -0
  30. onefinance-0.1.0/onefinance/providers/twelve_data.py +235 -0
  31. onefinance-0.1.0/onefinance/providers/yfinance_provider.py +513 -0
  32. onefinance-0.1.0/pyproject.toml +78 -0
  33. onefinance-0.1.0/tests/__init__.py +1 -0
  34. onefinance-0.1.0/tests/integration/__init__.py +1 -0
  35. onefinance-0.1.0/tests/integration/test_finnhub_live.py +75 -0
  36. onefinance-0.1.0/tests/integration/test_fmp_live.py +71 -0
  37. onefinance-0.1.0/tests/integration/test_twelve_data_live.py +50 -0
  38. onefinance-0.1.0/tests/unit/__init__.py +1 -0
  39. onefinance-0.1.0/tests/unit/test_audit.py +284 -0
  40. onefinance-0.1.0/tests/unit/test_base_provider.py +108 -0
  41. onefinance-0.1.0/tests/unit/test_cache.py +259 -0
  42. onefinance-0.1.0/tests/unit/test_cache_keys.py +64 -0
  43. onefinance-0.1.0/tests/unit/test_cli_app.py +427 -0
  44. onefinance-0.1.0/tests/unit/test_cli_format.py +95 -0
  45. onefinance-0.1.0/tests/unit/test_client.py +275 -0
  46. onefinance-0.1.0/tests/unit/test_config.py +239 -0
  47. onefinance-0.1.0/tests/unit/test_errors.py +91 -0
  48. onefinance-0.1.0/tests/unit/test_finnhub_provider.py +408 -0
  49. onefinance-0.1.0/tests/unit/test_fmp_provider.py +502 -0
  50. onefinance-0.1.0/tests/unit/test_indicators.py +343 -0
  51. onefinance-0.1.0/tests/unit/test_models.py +368 -0
  52. onefinance-0.1.0/tests/unit/test_provider_factory.py +114 -0
  53. onefinance-0.1.0/tests/unit/test_router.py +549 -0
  54. onefinance-0.1.0/tests/unit/test_twelve_data_provider.py +176 -0
  55. onefinance-0.1.0/tests/unit/test_yfinance_provider.py +260 -0
  56. onefinance-0.1.0/uv.lock +1255 -0
@@ -0,0 +1,254 @@
1
+ # Created by https://www.toptal.com/developers/gitignore/api/vim,visualstudiocode,python,macos
2
+ # Edit at https://www.toptal.com/developers/gitignore?templates=vim,visualstudiocode,python,macos
3
+
4
+ ### macOS ###
5
+ # General
6
+ .DS_Store
7
+ .AppleDouble
8
+ .LSOverride
9
+
10
+ # Icon must end with two \r
11
+ Icon
12
+
13
+
14
+ # Thumbnails
15
+ ._*
16
+
17
+ # Files that might appear in the root of a volume
18
+ .DocumentRevisions-V100
19
+ .fseventsd
20
+ .Spotlight-V100
21
+ .TemporaryItems
22
+ .Trashes
23
+ .VolumeIcon.icns
24
+ .com.apple.timemachine.donotpresent
25
+
26
+ # Directories potentially created on remote AFP share
27
+ .AppleDB
28
+ .AppleDesktop
29
+ Network Trash Folder
30
+ Temporary Items
31
+ .apdisk
32
+
33
+ ### macOS Patch ###
34
+ # iCloud generated files
35
+ *.icloud
36
+
37
+ ### Python ###
38
+ # Byte-compiled / optimized / DLL files
39
+ __pycache__/
40
+ *.py[cod]
41
+ *$py.class
42
+
43
+ # C extensions
44
+ *.so
45
+
46
+ # Distribution / packaging
47
+ .Python
48
+ build/
49
+ develop-eggs/
50
+ dist/
51
+ downloads/
52
+ eggs/
53
+ .eggs/
54
+ lib/
55
+ lib64/
56
+ parts/
57
+ sdist/
58
+ var/
59
+ wheels/
60
+ share/python-wheels/
61
+ *.egg-info/
62
+ .installed.cfg
63
+ *.egg
64
+ MANIFEST
65
+
66
+ # PyInstaller
67
+ # Usually these files are written by a python script from a template
68
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
69
+ *.manifest
70
+ *.spec
71
+
72
+ # Installer logs
73
+ pip-log.txt
74
+ pip-delete-this-directory.txt
75
+
76
+ # Unit test / coverage reports
77
+ htmlcov/
78
+ .tox/
79
+ .nox/
80
+ .coverage
81
+ .coverage.*
82
+ .cache
83
+ nosetests.xml
84
+ coverage.xml
85
+ *.cover
86
+ *.py,cover
87
+ .hypothesis/
88
+ .pytest_cache/
89
+ cover/
90
+
91
+ # Translations
92
+ *.mo
93
+ *.pot
94
+
95
+ # Django stuff:
96
+ *.log
97
+ local_settings.py
98
+ db.sqlite3
99
+ db.sqlite3-journal
100
+
101
+ # Flask stuff:
102
+ instance/
103
+ .webassets-cache
104
+
105
+ # Scrapy stuff:
106
+ .scrapy
107
+
108
+ # Sphinx documentation
109
+ docs/_build/
110
+
111
+ # PyBuilder
112
+ .pybuilder/
113
+ target/
114
+
115
+ # Jupyter Notebook
116
+ .ipynb_checkpoints
117
+
118
+ # IPython
119
+ profile_default/
120
+ ipython_config.py
121
+
122
+ # pyenv
123
+ # For a library or package, you might want to ignore these files since the code is
124
+ # intended to run in multiple environments; otherwise, check them in:
125
+ # .python-version
126
+
127
+ # pipenv
128
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
129
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
130
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
131
+ # install all needed dependencies.
132
+ #Pipfile.lock
133
+
134
+ # poetry
135
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
136
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
137
+ # commonly ignored for libraries.
138
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
139
+ #poetry.lock
140
+
141
+ # pdm
142
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
143
+ #pdm.lock
144
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
145
+ # in version control.
146
+ # https://pdm.fming.dev/#use-with-ide
147
+ .pdm.toml
148
+
149
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
150
+ __pypackages__/
151
+
152
+ # Celery stuff
153
+ celerybeat-schedule
154
+ celerybeat.pid
155
+
156
+ # SageMath parsed files
157
+ *.sage.py
158
+
159
+ # Environments
160
+ .env
161
+ .venv
162
+ env/
163
+ venv/
164
+ ENV/
165
+ env.bak/
166
+ venv.bak/
167
+
168
+ # Spyder project settings
169
+ .spyderproject
170
+ .spyproject
171
+
172
+ # Rope project settings
173
+ .ropeproject
174
+
175
+ # mkdocs documentation
176
+ /site
177
+
178
+ # mypy
179
+ .mypy_cache/
180
+ .dmypy.json
181
+ dmypy.json
182
+
183
+ # Pyre type checker
184
+ .pyre/
185
+
186
+ # pytype static type analyzer
187
+ .pytype/
188
+
189
+ # Cython debug symbols
190
+ cython_debug/
191
+
192
+ # PyCharm
193
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
194
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
195
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
196
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
197
+ #.idea/
198
+
199
+ ### Python Patch ###
200
+ # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
201
+ poetry.toml
202
+
203
+ # ruff
204
+ .ruff_cache/
205
+
206
+ # LSP config files
207
+ pyrightconfig.json
208
+
209
+ ### Vim ###
210
+ # Swap
211
+ [._]*.s[a-v][a-z]
212
+ !*.svg # comment out if you don't need vector files
213
+ [._]*.sw[a-p]
214
+ [._]s[a-rt-v][a-z]
215
+ [._]ss[a-gi-z]
216
+ [._]sw[a-p]
217
+
218
+ # Session
219
+ Session.vim
220
+ Sessionx.vim
221
+
222
+ # Temporary
223
+ .netrwhist
224
+ *~
225
+ # Auto-generated tag files
226
+ tags
227
+ # Persistent undo
228
+ [._]*.un~
229
+
230
+ ### VisualStudioCode ###
231
+ .vscode/*
232
+ !.vscode/settings.json
233
+ !.vscode/tasks.json
234
+ !.vscode/launch.json
235
+ !.vscode/extensions.json
236
+ !.vscode/*.code-snippets
237
+
238
+ # Local History for Visual Studio Code
239
+ .history/
240
+
241
+ # Built Visual Studio Code Extensions
242
+ *.vsix
243
+
244
+ ### VisualStudioCode Patch ###
245
+ # Ignore all local history of files
246
+ .history
247
+ .ionide
248
+
249
+ # End of https://www.toptal.com/developers/gitignore/api/vim,visualstudiocode,python,macos
250
+
251
+ ### uv ###
252
+ # uv.lock is committed for reproducibility (do NOT ignore it)
253
+ # Build artifacts from `uv build`
254
+ dist/
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Syi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,175 @@
1
+ Metadata-Version: 2.4
2
+ Name: onefinance
3
+ Version: 0.1.0
4
+ Summary: One finance data client to rule them all — unified API across multiple financial data providers
5
+ Project-URL: Repository, https://github.com/yishanhe/one-finance-data
6
+ Author-email: Shanhe Yi <ysh@yishanhe.net>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Financial and Insurance Industry
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Office/Business :: Financial
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: diskcache>=5.6
21
+ Requires-Dist: httpx
22
+ Requires-Dist: pydantic>=2.0
23
+ Requires-Dist: pyyaml
24
+ Requires-Dist: yfinance
25
+ Provides-Extra: cli
26
+ Requires-Dist: rich; extra == 'cli'
27
+ Requires-Dist: typer>=0.12; extra == 'cli'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # one-finance-data
31
+
32
+ Unified financial data client for Python. Abstracts FMP, Finnhub, Twelve Data, and Yahoo Finance behind a single interface with transparent disk-based caching and a CLI designed for agents and automation.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ # Core library
38
+ pip install -e "."
39
+
40
+ # Core + CLI (ofclient)
41
+ pip install -e ".[cli]"
42
+
43
+ # Development
44
+ pip install -e ".[dev,cli]"
45
+ ```
46
+
47
+ ## Environment variables
48
+
49
+ | Variable | Provider | Required |
50
+ |---|---|---|
51
+ | `FMP_API_KEY` | Financial Modeling Prep | For FMPProvider |
52
+ | `FINNHUB_API_KEY` | Finnhub | For FinnhubProvider |
53
+ | `TWELVE_DATA_API_KEY` | Twelve Data | For TwelveDataProvider |
54
+
55
+ Providers whose key is unset are skipped automatically. `YFinanceProvider` (no key) is always available as a fallback.
56
+
57
+ ## Python usage
58
+
59
+ ```python
60
+ from onefinance.core.client import OneFinanceClient
61
+ from datetime import date
62
+
63
+ # Reads API keys from environment; builds all available providers automatically
64
+ with OneFinanceClient() as client:
65
+ # Price history — cached 30 days (historical) or 6 h (after market close)
66
+ bars = client.get_price_history("AAPL", date(2024, 1, 1), date(2024, 12, 31))
67
+
68
+ # Live quote — cached 30 seconds
69
+ quote = client.get_quote("AAPL")
70
+
71
+ # Company info — cached 30 days
72
+ info = client.get_info("AAPL")
73
+
74
+ # Financial statements
75
+ income = client.get_financials("AAPL", statement="income", period="annual")
76
+
77
+ # Ratios — use fresh=True to bypass the long-TTL cache
78
+ ratios = client.get_ratios("AAPL", period="annual", fresh=True)
79
+
80
+ # Earnings
81
+ earnings = client.get_earnings("AAPL")
82
+
83
+ # Insider trades
84
+ trades = client.get_insider_trades("AAPL")
85
+ ```
86
+
87
+ ### Per-call overrides
88
+
89
+ ```python
90
+ bars = client.get_price_history(
91
+ "AAPL",
92
+ date(2024, 1, 1), date(2024, 12, 31),
93
+ no_cache=True, # bypass cache
94
+ provider="finnhub", # force a specific provider
95
+ ttl=3600, # custom TTL in seconds
96
+ )
97
+ ```
98
+
99
+ ## CLI usage
100
+
101
+ ```bash
102
+ # Discover what's available
103
+ ofclient capabilities # machine-readable command manifest (JSON)
104
+ ofclient version # package + schema version
105
+
106
+ # Data commands (all output JSON by default)
107
+ ofclient price AAPL --range 1y
108
+ ofclient price AAPL --start 2024-01-01 --end 2024-12-31
109
+ ofclient quote AAPL
110
+ ofclient financials AAPL --statement income --period annual
111
+ ofclient info AAPL
112
+ ofclient insiders AAPL --since 2024-01-01
113
+ ofclient ratios AAPL --period annual --fresh
114
+ ofclient earnings AAPL
115
+
116
+ # Output formats
117
+ ofclient price AAPL --range 1m --format table
118
+ ofclient price AAPL --range 1m --format csv
119
+
120
+ # Dry-run: see cache key and whether a fetch would happen, without fetching
121
+ ofclient price AAPL --range 1y --dry-run
122
+
123
+ # Force a provider or bypass cache
124
+ ofclient quote AAPL --provider finnhub --no-cache
125
+
126
+ # Introspection
127
+ ofclient cache stats
128
+ ofclient providers status
129
+ ofclient config show
130
+ ofclient config init --output ./config.yaml
131
+ ```
132
+
133
+ ### Exit codes
134
+
135
+ | Code | Meaning |
136
+ |---|---|
137
+ | 0 | Success |
138
+ | 1 | Invalid argument (bad range, unknown statement, etc.) |
139
+ | 2 | Provider error or rate limit |
140
+ | 3 | Endpoint not supported by any configured provider |
141
+ | 4 | Configuration error (missing API key, bad config file) |
142
+
143
+ ### Environment overrides for CLI
144
+
145
+ | Variable | Effect |
146
+ |---|---|
147
+ | `OFCLIENT_OUTPUT` | Default output format (`json`, `table`, `csv`) |
148
+ | `OFCLIENT_NO_CACHE` | Set `1` to bypass cache on all calls |
149
+ | `OFCLIENT_DRY_RUN` | Set `1` to dry-run all calls |
150
+ | `OFCLIENT_CONFIG` | Path to config YAML file |
151
+
152
+ ## Provider coverage
153
+
154
+ | Endpoint | FMP | Finnhub | Twelve Data | YFinance |
155
+ |---|---|---|---|---|
156
+ | `get_price_history` | ✓ | ✓ | ✓ | ✓ |
157
+ | `get_quote` | ✓ | ✓ | ✓ | — |
158
+ | `get_info` | ✓ | ✓ | — | ✓ |
159
+ | `get_financials` | ✓ | ✓ | — | — |
160
+ | `get_ratios` | ✓ | ✓ | — | — |
161
+ | `get_earnings` | ✓ | ✓ | — | — |
162
+ | `get_insider_trades` | ✓ | ✓ | — | — |
163
+
164
+ ## Running tests
165
+
166
+ ```bash
167
+ # Unit tests only (no network)
168
+ python -m pytest tests/ -m "not integration"
169
+
170
+ # All tests including live API calls (requires API keys in env)
171
+ python -m pytest tests/ -m integration
172
+
173
+ # Single provider integration test
174
+ python -m pytest tests/integration/test_fmp_live.py -m integration -v
175
+ ```
@@ -0,0 +1,146 @@
1
+ # one-finance-data
2
+
3
+ Unified financial data client for Python. Abstracts FMP, Finnhub, Twelve Data, and Yahoo Finance behind a single interface with transparent disk-based caching and a CLI designed for agents and automation.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # Core library
9
+ pip install -e "."
10
+
11
+ # Core + CLI (ofclient)
12
+ pip install -e ".[cli]"
13
+
14
+ # Development
15
+ pip install -e ".[dev,cli]"
16
+ ```
17
+
18
+ ## Environment variables
19
+
20
+ | Variable | Provider | Required |
21
+ |---|---|---|
22
+ | `FMP_API_KEY` | Financial Modeling Prep | For FMPProvider |
23
+ | `FINNHUB_API_KEY` | Finnhub | For FinnhubProvider |
24
+ | `TWELVE_DATA_API_KEY` | Twelve Data | For TwelveDataProvider |
25
+
26
+ Providers whose key is unset are skipped automatically. `YFinanceProvider` (no key) is always available as a fallback.
27
+
28
+ ## Python usage
29
+
30
+ ```python
31
+ from onefinance.core.client import OneFinanceClient
32
+ from datetime import date
33
+
34
+ # Reads API keys from environment; builds all available providers automatically
35
+ with OneFinanceClient() as client:
36
+ # Price history — cached 30 days (historical) or 6 h (after market close)
37
+ bars = client.get_price_history("AAPL", date(2024, 1, 1), date(2024, 12, 31))
38
+
39
+ # Live quote — cached 30 seconds
40
+ quote = client.get_quote("AAPL")
41
+
42
+ # Company info — cached 30 days
43
+ info = client.get_info("AAPL")
44
+
45
+ # Financial statements
46
+ income = client.get_financials("AAPL", statement="income", period="annual")
47
+
48
+ # Ratios — use fresh=True to bypass the long-TTL cache
49
+ ratios = client.get_ratios("AAPL", period="annual", fresh=True)
50
+
51
+ # Earnings
52
+ earnings = client.get_earnings("AAPL")
53
+
54
+ # Insider trades
55
+ trades = client.get_insider_trades("AAPL")
56
+ ```
57
+
58
+ ### Per-call overrides
59
+
60
+ ```python
61
+ bars = client.get_price_history(
62
+ "AAPL",
63
+ date(2024, 1, 1), date(2024, 12, 31),
64
+ no_cache=True, # bypass cache
65
+ provider="finnhub", # force a specific provider
66
+ ttl=3600, # custom TTL in seconds
67
+ )
68
+ ```
69
+
70
+ ## CLI usage
71
+
72
+ ```bash
73
+ # Discover what's available
74
+ ofclient capabilities # machine-readable command manifest (JSON)
75
+ ofclient version # package + schema version
76
+
77
+ # Data commands (all output JSON by default)
78
+ ofclient price AAPL --range 1y
79
+ ofclient price AAPL --start 2024-01-01 --end 2024-12-31
80
+ ofclient quote AAPL
81
+ ofclient financials AAPL --statement income --period annual
82
+ ofclient info AAPL
83
+ ofclient insiders AAPL --since 2024-01-01
84
+ ofclient ratios AAPL --period annual --fresh
85
+ ofclient earnings AAPL
86
+
87
+ # Output formats
88
+ ofclient price AAPL --range 1m --format table
89
+ ofclient price AAPL --range 1m --format csv
90
+
91
+ # Dry-run: see cache key and whether a fetch would happen, without fetching
92
+ ofclient price AAPL --range 1y --dry-run
93
+
94
+ # Force a provider or bypass cache
95
+ ofclient quote AAPL --provider finnhub --no-cache
96
+
97
+ # Introspection
98
+ ofclient cache stats
99
+ ofclient providers status
100
+ ofclient config show
101
+ ofclient config init --output ./config.yaml
102
+ ```
103
+
104
+ ### Exit codes
105
+
106
+ | Code | Meaning |
107
+ |---|---|
108
+ | 0 | Success |
109
+ | 1 | Invalid argument (bad range, unknown statement, etc.) |
110
+ | 2 | Provider error or rate limit |
111
+ | 3 | Endpoint not supported by any configured provider |
112
+ | 4 | Configuration error (missing API key, bad config file) |
113
+
114
+ ### Environment overrides for CLI
115
+
116
+ | Variable | Effect |
117
+ |---|---|
118
+ | `OFCLIENT_OUTPUT` | Default output format (`json`, `table`, `csv`) |
119
+ | `OFCLIENT_NO_CACHE` | Set `1` to bypass cache on all calls |
120
+ | `OFCLIENT_DRY_RUN` | Set `1` to dry-run all calls |
121
+ | `OFCLIENT_CONFIG` | Path to config YAML file |
122
+
123
+ ## Provider coverage
124
+
125
+ | Endpoint | FMP | Finnhub | Twelve Data | YFinance |
126
+ |---|---|---|---|---|
127
+ | `get_price_history` | ✓ | ✓ | ✓ | ✓ |
128
+ | `get_quote` | ✓ | ✓ | ✓ | — |
129
+ | `get_info` | ✓ | ✓ | — | ✓ |
130
+ | `get_financials` | ✓ | ✓ | — | — |
131
+ | `get_ratios` | ✓ | ✓ | — | — |
132
+ | `get_earnings` | ✓ | ✓ | — | — |
133
+ | `get_insider_trades` | ✓ | ✓ | — | — |
134
+
135
+ ## Running tests
136
+
137
+ ```bash
138
+ # Unit tests only (no network)
139
+ python -m pytest tests/ -m "not integration"
140
+
141
+ # All tests including live API calls (requires API keys in env)
142
+ python -m pytest tests/ -m integration
143
+
144
+ # Single provider integration test
145
+ python -m pytest tests/integration/test_fmp_live.py -m integration -v
146
+ ```
@@ -0,0 +1,74 @@
1
+ """OneFinance — unified financial data API across multiple providers."""
2
+
3
+ from onefinance.core.client import OneFinanceClient
4
+ from onefinance.core.errors import (
5
+ AllProvidersFailedError,
6
+ FinanceError,
7
+ NotSupportedError,
8
+ ProviderError,
9
+ RateLimitError,
10
+ )
11
+ from onefinance.indicators import TechnicalIndicators, compute_indicators
12
+ from onefinance.core.models import (
13
+ AnalystData,
14
+ BalanceSheet,
15
+ CashFlow,
16
+ CompanyInfo,
17
+ CorporateAction,
18
+ Currency,
19
+ DCFValuation,
20
+ EarningsRecord,
21
+ FinancialRatios,
22
+ FinanceModel,
23
+ ForwardEstimates,
24
+ IncomeStatement,
25
+ InsiderTrade,
26
+ InstitutionalHolder,
27
+ NewsArticle,
28
+ OptionChain,
29
+ OptionContract,
30
+ PriceBar,
31
+ Quote,
32
+ ScreenerResult,
33
+ SectorInfo,
34
+ Symbol,
35
+ )
36
+
37
+ __all__ = [
38
+ # Client
39
+ "OneFinanceClient",
40
+ # Models
41
+ "AnalystData",
42
+ "FinanceModel",
43
+ "PriceBar",
44
+ "Quote",
45
+ "IncomeStatement",
46
+ "BalanceSheet",
47
+ "CashFlow",
48
+ "CompanyInfo",
49
+ "CorporateAction",
50
+ "DCFValuation",
51
+ "EarningsRecord",
52
+ "FinancialRatios",
53
+ "ForwardEstimates",
54
+ "InsiderTrade",
55
+ "InstitutionalHolder",
56
+ "NewsArticle",
57
+ "OptionChain",
58
+ "OptionContract",
59
+ "ScreenerResult",
60
+ "SectorInfo",
61
+ "Symbol",
62
+ "Currency",
63
+ # Errors
64
+ "FinanceError",
65
+ "ProviderError",
66
+ "NotSupportedError",
67
+ "RateLimitError",
68
+ "AllProvidersFailedError",
69
+ # Indicators
70
+ "TechnicalIndicators",
71
+ "compute_indicators",
72
+ ]
73
+
74
+ __version__ = "0.1.0"
@@ -0,0 +1,23 @@
1
+ """Audit log — structured tracing for every API invocation.
2
+
3
+ Records provider calls, cache hits, tier-walking decisions, and
4
+ errors so you can answer "which provider served this?" and
5
+ "how many FMP calls did I burn today?"
6
+
7
+ Usage::
8
+
9
+ from onefinance.audit import AuditLog, AuditEntry, AuditStats
10
+
11
+ log = AuditLog()
12
+ entries = log.query(provider="fmp", limit=10)
13
+ stats = log.stats()
14
+ """
15
+
16
+ from onefinance.audit.models import AuditEntry, AuditStats
17
+ from onefinance.audit.log import AuditLog
18
+
19
+ __all__ = [
20
+ "AuditEntry",
21
+ "AuditLog",
22
+ "AuditStats",
23
+ ]