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.
- onefinance-0.1.0/.gitignore +254 -0
- onefinance-0.1.0/.python-version +1 -0
- onefinance-0.1.0/LICENSE +21 -0
- onefinance-0.1.0/PKG-INFO +175 -0
- onefinance-0.1.0/README.md +146 -0
- onefinance-0.1.0/onefinance/__init__.py +74 -0
- onefinance-0.1.0/onefinance/audit/__init__.py +23 -0
- onefinance-0.1.0/onefinance/audit/log.py +325 -0
- onefinance-0.1.0/onefinance/audit/models.py +116 -0
- onefinance-0.1.0/onefinance/cache/__init__.py +11 -0
- onefinance-0.1.0/onefinance/cache/keys.py +62 -0
- onefinance-0.1.0/onefinance/cache/manager.py +363 -0
- onefinance-0.1.0/onefinance/cli/__init__.py +1 -0
- onefinance-0.1.0/onefinance/cli/__main__.py +4 -0
- onefinance-0.1.0/onefinance/cli/app.py +1131 -0
- onefinance-0.1.0/onefinance/cli/format.py +87 -0
- onefinance-0.1.0/onefinance/core/__init__.py +1 -0
- onefinance-0.1.0/onefinance/core/client.py +753 -0
- onefinance-0.1.0/onefinance/core/config.py +223 -0
- onefinance-0.1.0/onefinance/core/errors.py +174 -0
- onefinance-0.1.0/onefinance/core/models.py +378 -0
- onefinance-0.1.0/onefinance/core/router.py +409 -0
- onefinance-0.1.0/onefinance/indicators/__init__.py +16 -0
- onefinance-0.1.0/onefinance/indicators/core.py +284 -0
- onefinance-0.1.0/onefinance/providers/__init__.py +1 -0
- onefinance-0.1.0/onefinance/providers/_utils.py +23 -0
- onefinance-0.1.0/onefinance/providers/base.py +196 -0
- onefinance-0.1.0/onefinance/providers/finnhub.py +712 -0
- onefinance-0.1.0/onefinance/providers/fmp.py +885 -0
- onefinance-0.1.0/onefinance/providers/twelve_data.py +235 -0
- onefinance-0.1.0/onefinance/providers/yfinance_provider.py +513 -0
- onefinance-0.1.0/pyproject.toml +78 -0
- onefinance-0.1.0/tests/__init__.py +1 -0
- onefinance-0.1.0/tests/integration/__init__.py +1 -0
- onefinance-0.1.0/tests/integration/test_finnhub_live.py +75 -0
- onefinance-0.1.0/tests/integration/test_fmp_live.py +71 -0
- onefinance-0.1.0/tests/integration/test_twelve_data_live.py +50 -0
- onefinance-0.1.0/tests/unit/__init__.py +1 -0
- onefinance-0.1.0/tests/unit/test_audit.py +284 -0
- onefinance-0.1.0/tests/unit/test_base_provider.py +108 -0
- onefinance-0.1.0/tests/unit/test_cache.py +259 -0
- onefinance-0.1.0/tests/unit/test_cache_keys.py +64 -0
- onefinance-0.1.0/tests/unit/test_cli_app.py +427 -0
- onefinance-0.1.0/tests/unit/test_cli_format.py +95 -0
- onefinance-0.1.0/tests/unit/test_client.py +275 -0
- onefinance-0.1.0/tests/unit/test_config.py +239 -0
- onefinance-0.1.0/tests/unit/test_errors.py +91 -0
- onefinance-0.1.0/tests/unit/test_finnhub_provider.py +408 -0
- onefinance-0.1.0/tests/unit/test_fmp_provider.py +502 -0
- onefinance-0.1.0/tests/unit/test_indicators.py +343 -0
- onefinance-0.1.0/tests/unit/test_models.py +368 -0
- onefinance-0.1.0/tests/unit/test_provider_factory.py +114 -0
- onefinance-0.1.0/tests/unit/test_router.py +549 -0
- onefinance-0.1.0/tests/unit/test_twelve_data_provider.py +176 -0
- onefinance-0.1.0/tests/unit/test_yfinance_provider.py +260 -0
- 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
|
onefinance-0.1.0/LICENSE
ADDED
|
@@ -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
|
+
]
|