fmp-data 0.0.0__py3-none-any.whl
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.
- fmp_data/__init__.py +138 -0
- fmp_data/alternative/__init__.py +34 -0
- fmp_data/alternative/client.py +150 -0
- fmp_data/alternative/endpoints.py +533 -0
- fmp_data/alternative/mapping.py +737 -0
- fmp_data/alternative/models.py +296 -0
- fmp_data/alternative/schema.py +165 -0
- fmp_data/base.py +316 -0
- fmp_data/client.py +269 -0
- fmp_data/company/__init__.py +40 -0
- fmp_data/company/client.py +238 -0
- fmp_data/company/endpoints.py +711 -0
- fmp_data/company/hints.py +77 -0
- fmp_data/company/mapping.py +1361 -0
- fmp_data/company/models.py +543 -0
- fmp_data/company/schema.py +132 -0
- fmp_data/config.py +207 -0
- fmp_data/economics/__init__.py +16 -0
- fmp_data/economics/client.py +52 -0
- fmp_data/economics/endpoints.py +164 -0
- fmp_data/economics/mapping.py +641 -0
- fmp_data/economics/models.py +75 -0
- fmp_data/economics/schema.py +91 -0
- fmp_data/exceptions.py +54 -0
- fmp_data/fundamental/__init__.py +40 -0
- fmp_data/fundamental/client.py +87 -0
- fmp_data/fundamental/endpoints.py +403 -0
- fmp_data/fundamental/mapping.py +867 -0
- fmp_data/fundamental/models.py +913 -0
- fmp_data/fundamental/schema.py +40 -0
- fmp_data/institutional/__init__.py +26 -0
- fmp_data/institutional/client.py +141 -0
- fmp_data/institutional/endpoints.py +321 -0
- fmp_data/institutional/mapping.py +749 -0
- fmp_data/institutional/models.py +301 -0
- fmp_data/institutional/schema.py +99 -0
- fmp_data/intelligence/__init__.py +58 -0
- fmp_data/intelligence/client.py +331 -0
- fmp_data/intelligence/endpoints.py +788 -0
- fmp_data/intelligence/mapping.py +1677 -0
- fmp_data/intelligence/models.py +707 -0
- fmp_data/intelligence/schema.py +57 -0
- fmp_data/investment/__init__.py +24 -0
- fmp_data/investment/client.py +104 -0
- fmp_data/investment/endpoints.py +241 -0
- fmp_data/investment/mapping.py +658 -0
- fmp_data/investment/models.py +220 -0
- fmp_data/investment/schema.py +106 -0
- fmp_data/lc/__init__.py +256 -0
- fmp_data/lc/config.py +88 -0
- fmp_data/lc/embedding.py +140 -0
- fmp_data/lc/hints.py +66 -0
- fmp_data/lc/mapping.py +107 -0
- fmp_data/lc/models.py +98 -0
- fmp_data/lc/registry.py +693 -0
- fmp_data/lc/utils.py +35 -0
- fmp_data/lc/validation.py +267 -0
- fmp_data/lc/vector_store.py +592 -0
- fmp_data/logger.py +358 -0
- fmp_data/market/__init__.py +18 -0
- fmp_data/market/client.py +106 -0
- fmp_data/market/endpoints.py +358 -0
- fmp_data/market/hints.py +22 -0
- fmp_data/market/mapping.py +854 -0
- fmp_data/market/models.py +310 -0
- fmp_data/market/schema.py +186 -0
- fmp_data/mcp/__init__.py +0 -0
- fmp_data/mcp/server.py +101 -0
- fmp_data/mcp/tool_loader.py +74 -0
- fmp_data/mcp/tools_manifest.py +17 -0
- fmp_data/models.py +265 -0
- fmp_data/rate_limit.py +136 -0
- fmp_data/schema.py +158 -0
- fmp_data/technical/__init__.py +28 -0
- fmp_data/technical/client.py +214 -0
- fmp_data/technical/endpoints.py +102 -0
- fmp_data/technical/mapping.py +452 -0
- fmp_data/technical/models.py +87 -0
- fmp_data/technical/schema.py +261 -0
- fmp_data-0.0.0.dist-info/METADATA +732 -0
- fmp_data-0.0.0.dist-info/RECORD +84 -0
- fmp_data-0.0.0.dist-info/WHEEL +4 -0
- fmp_data-0.0.0.dist-info/entry_points.txt +10 -0
- fmp_data-0.0.0.dist-info/licenses/LICENSE +21 -0
fmp_data/__init__.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""
|
|
2
|
+
fmp-data top-level package
|
|
3
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
4
|
+
|
|
5
|
+
Core usage:
|
|
6
|
+
|
|
7
|
+
import fmp_data as fmp
|
|
8
|
+
client = fmp.FMPDataClient(...)
|
|
9
|
+
|
|
10
|
+
Optional LangChain / FAISS helpers are exposed lazily and raise
|
|
11
|
+
ImportError with guidance if the extra is not installed.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import importlib.util as _importlib_util
|
|
17
|
+
import types as _types
|
|
18
|
+
import warnings as _warnings
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
from fmp_data.client import FMPDataClient
|
|
22
|
+
from fmp_data.config import (
|
|
23
|
+
ClientConfig,
|
|
24
|
+
LoggingConfig,
|
|
25
|
+
LogHandlerConfig,
|
|
26
|
+
RateLimitConfig,
|
|
27
|
+
)
|
|
28
|
+
from fmp_data.exceptions import (
|
|
29
|
+
AuthenticationError,
|
|
30
|
+
ConfigError,
|
|
31
|
+
FMPError,
|
|
32
|
+
RateLimitError,
|
|
33
|
+
ValidationError,
|
|
34
|
+
)
|
|
35
|
+
from fmp_data.logger import FMPLogger
|
|
36
|
+
|
|
37
|
+
__version__ = "0.0.0"
|
|
38
|
+
|
|
39
|
+
# --------------------------------------------------------------------------- #
|
|
40
|
+
# Public re-exports guaranteed to work without optional dependencies
|
|
41
|
+
# --------------------------------------------------------------------------- #
|
|
42
|
+
__all__ = [
|
|
43
|
+
"FMPDataClient",
|
|
44
|
+
"ClientConfig",
|
|
45
|
+
"LoggingConfig",
|
|
46
|
+
"LogHandlerConfig",
|
|
47
|
+
"RateLimitConfig",
|
|
48
|
+
"FMPError",
|
|
49
|
+
"FMPLogger",
|
|
50
|
+
"RateLimitError",
|
|
51
|
+
"AuthenticationError",
|
|
52
|
+
"ValidationError",
|
|
53
|
+
"ConfigError",
|
|
54
|
+
"logger",
|
|
55
|
+
"is_langchain_available",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
logger = FMPLogger()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# --------------------------------------------------------------------------- #
|
|
62
|
+
# Helper: detect whether LangChain core stack is available
|
|
63
|
+
# --------------------------------------------------------------------------- #
|
|
64
|
+
def is_langchain_available() -> bool:
|
|
65
|
+
"""
|
|
66
|
+
Return ``True`` if the optional *langchain* extra is installed.
|
|
67
|
+
|
|
68
|
+
We check for ``langchain_core`` because it is imported by every
|
|
69
|
+
sub-module that fmp-data’s LC helpers rely on.
|
|
70
|
+
"""
|
|
71
|
+
return _importlib_util.find_spec("langchain_core") is not None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# --------------------------------------------------------------------------- #
|
|
75
|
+
# Lazy import machinery for optional vector-store helpers
|
|
76
|
+
# --------------------------------------------------------------------------- #
|
|
77
|
+
def _lazy_import_vector_store() -> _types.ModuleType:
|
|
78
|
+
"""
|
|
79
|
+
Import fmp_data.lc only when a LC-specific symbol is first accessed.
|
|
80
|
+
Raises ImportError with installation hint if LangChain (or FAISS) is missing.
|
|
81
|
+
"""
|
|
82
|
+
if not is_langchain_available():
|
|
83
|
+
raise ImportError(
|
|
84
|
+
"Optional LangChain features are not installed. "
|
|
85
|
+
"Run: pip install 'fmp-data[langchain]'"
|
|
86
|
+
) from None
|
|
87
|
+
|
|
88
|
+
# Import inside the function to keep top-level import cheap.
|
|
89
|
+
from fmp_data import lc as _lc # noqa: WPS433 (allow internal import)
|
|
90
|
+
|
|
91
|
+
# Check FAISS at runtime to give a clearer error than module not found.
|
|
92
|
+
if _importlib_util.find_spec("faiss") is None:
|
|
93
|
+
raise ImportError(
|
|
94
|
+
"FAISS is required for vector-store helpers. "
|
|
95
|
+
"Run: pip install 'fmp-data[langchain]'"
|
|
96
|
+
) from None
|
|
97
|
+
|
|
98
|
+
return _lc
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# Map attribute names to callables that will supply them on demand.
|
|
102
|
+
# Keys must match what you later append to __all__.
|
|
103
|
+
_lazy_attrs = {
|
|
104
|
+
"EndpointVectorStore": lambda: _lazy_import_vector_store().EndpointVectorStore,
|
|
105
|
+
"EndpointSemantics": lambda: _lazy_import_vector_store().EndpointSemantics,
|
|
106
|
+
"SemanticCategory": lambda: _lazy_import_vector_store().SemanticCategory,
|
|
107
|
+
"create_vector_store": lambda: _lazy_import_vector_store().create_vector_store,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# extend __all__ so IDEs still see the names when LC is installed
|
|
111
|
+
__all__.extend(_lazy_attrs.keys())
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def __getattr__(name: str) -> Any: # pragma: no cover
|
|
115
|
+
"""
|
|
116
|
+
PEP 562 hook: resolve optional symbols at first access.
|
|
117
|
+
|
|
118
|
+
If *name* is one of the LC helpers, call the associated factory,
|
|
119
|
+
cache the result in the module dict, and return it.
|
|
120
|
+
"""
|
|
121
|
+
if name in _lazy_attrs:
|
|
122
|
+
value = _lazy_attrs[name]()
|
|
123
|
+
globals()[name] = value # cache so subsequent access is fast
|
|
124
|
+
return value
|
|
125
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# --------------------------------------------------------------------------- #
|
|
129
|
+
# Warn immediately if user tried to import LC helpers without extras
|
|
130
|
+
# --------------------------------------------------------------------------- #
|
|
131
|
+
if not is_langchain_available():
|
|
132
|
+
_warnings.filterwarnings("once", category=ImportWarning)
|
|
133
|
+
_warnings.warn(
|
|
134
|
+
"LangChain extras not installed; vector-store helpers will be unavailable "
|
|
135
|
+
"until you run: pip install 'fmp-data[langchain]'",
|
|
136
|
+
ImportWarning,
|
|
137
|
+
stacklevel=2,
|
|
138
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# fmp_data/alternative/__init__.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from fmp_data.alternative.client import AlternativeMarketsClient
|
|
5
|
+
from fmp_data.alternative.models import (
|
|
6
|
+
Commodity,
|
|
7
|
+
CommodityHistoricalPrice,
|
|
8
|
+
CommodityIntradayPrice,
|
|
9
|
+
CommodityQuote,
|
|
10
|
+
CryptoHistoricalPrice,
|
|
11
|
+
CryptoIntradayPrice,
|
|
12
|
+
CryptoPair,
|
|
13
|
+
CryptoQuote,
|
|
14
|
+
ForexHistoricalPrice,
|
|
15
|
+
ForexIntradayPrice,
|
|
16
|
+
ForexPair,
|
|
17
|
+
ForexQuote,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"AlternativeMarketsClient",
|
|
22
|
+
"CryptoPair",
|
|
23
|
+
"CryptoQuote",
|
|
24
|
+
"CryptoHistoricalPrice",
|
|
25
|
+
"CryptoIntradayPrice",
|
|
26
|
+
"ForexPair",
|
|
27
|
+
"ForexQuote",
|
|
28
|
+
"ForexHistoricalPrice",
|
|
29
|
+
"ForexIntradayPrice",
|
|
30
|
+
"Commodity",
|
|
31
|
+
"CommodityQuote",
|
|
32
|
+
"CommodityHistoricalPrice",
|
|
33
|
+
"CommodityIntradayPrice",
|
|
34
|
+
]
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# fmp_data/alternative/client.py
|
|
2
|
+
from datetime import date
|
|
3
|
+
from typing import TypeVar, cast
|
|
4
|
+
|
|
5
|
+
from fmp_data.alternative.endpoints import (
|
|
6
|
+
COMMODITIES_LIST,
|
|
7
|
+
COMMODITIES_QUOTES,
|
|
8
|
+
COMMODITY_HISTORICAL,
|
|
9
|
+
COMMODITY_INTRADAY,
|
|
10
|
+
COMMODITY_QUOTE,
|
|
11
|
+
CRYPTO_HISTORICAL,
|
|
12
|
+
CRYPTO_INTRADAY,
|
|
13
|
+
CRYPTO_LIST,
|
|
14
|
+
CRYPTO_QUOTE,
|
|
15
|
+
CRYPTO_QUOTES,
|
|
16
|
+
FOREX_HISTORICAL,
|
|
17
|
+
FOREX_INTRADAY,
|
|
18
|
+
FOREX_LIST,
|
|
19
|
+
FOREX_QUOTE,
|
|
20
|
+
FOREX_QUOTES,
|
|
21
|
+
)
|
|
22
|
+
from fmp_data.alternative.models import (
|
|
23
|
+
Commodity,
|
|
24
|
+
CommodityIntradayPrice,
|
|
25
|
+
CommodityPriceHistory,
|
|
26
|
+
CommodityQuote,
|
|
27
|
+
CryptoHistoricalData,
|
|
28
|
+
CryptoIntradayPrice,
|
|
29
|
+
CryptoPair,
|
|
30
|
+
CryptoQuote,
|
|
31
|
+
ForexIntradayPrice,
|
|
32
|
+
ForexPair,
|
|
33
|
+
ForexPriceHistory,
|
|
34
|
+
ForexQuote,
|
|
35
|
+
)
|
|
36
|
+
from fmp_data.base import EndpointGroup
|
|
37
|
+
|
|
38
|
+
T = TypeVar("T")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AlternativeMarketsClient(EndpointGroup):
|
|
42
|
+
"""Client for alternative markets endpoints"""
|
|
43
|
+
|
|
44
|
+
# Cryptocurrency methods
|
|
45
|
+
def get_crypto_list(self) -> list[CryptoPair]:
|
|
46
|
+
"""Get list of available cryptocurrencies"""
|
|
47
|
+
return self.client.request(CRYPTO_LIST)
|
|
48
|
+
|
|
49
|
+
def get_crypto_quotes(self) -> list[CryptoQuote]:
|
|
50
|
+
"""Get cryptocurrency quotes"""
|
|
51
|
+
return self.client.request(CRYPTO_QUOTES)
|
|
52
|
+
|
|
53
|
+
def get_crypto_quote(self, symbol: str) -> CryptoQuote:
|
|
54
|
+
"""Get cryptocurrency quote"""
|
|
55
|
+
result = self.client.request(CRYPTO_QUOTE, symbol=symbol)
|
|
56
|
+
return cast(CryptoQuote, result[0] if isinstance(result, list) else result)
|
|
57
|
+
|
|
58
|
+
def get_crypto_historical(
|
|
59
|
+
self,
|
|
60
|
+
symbol: str,
|
|
61
|
+
start_date: date | None = None,
|
|
62
|
+
end_date: date | None = None,
|
|
63
|
+
) -> CryptoHistoricalData:
|
|
64
|
+
"""Get cryptocurrency historical prices"""
|
|
65
|
+
params = {"symbol": symbol}
|
|
66
|
+
if start_date:
|
|
67
|
+
params["from"] = start_date.strftime("%Y-%m-%d")
|
|
68
|
+
if end_date:
|
|
69
|
+
params["to"] = end_date.strftime("%Y-%m-%d")
|
|
70
|
+
|
|
71
|
+
result = self.client.request(CRYPTO_HISTORICAL, **params)
|
|
72
|
+
return cast(CryptoHistoricalData, result)
|
|
73
|
+
|
|
74
|
+
def get_crypto_intraday(
|
|
75
|
+
self, symbol: str, interval: str = "5min"
|
|
76
|
+
) -> list[CryptoIntradayPrice]:
|
|
77
|
+
"""Get cryptocurrency intraday prices"""
|
|
78
|
+
return self.client.request(CRYPTO_INTRADAY, symbol=symbol, interval=interval)
|
|
79
|
+
|
|
80
|
+
# Forex methods
|
|
81
|
+
def get_forex_list(self) -> list[ForexPair]:
|
|
82
|
+
"""Get list of available forex pairs"""
|
|
83
|
+
return self.client.request(FOREX_LIST)
|
|
84
|
+
|
|
85
|
+
def get_forex_quotes(self) -> list[ForexQuote]:
|
|
86
|
+
"""Get forex quotes"""
|
|
87
|
+
return self.client.request(FOREX_QUOTES)
|
|
88
|
+
|
|
89
|
+
def get_forex_quote(self, symbol: str) -> ForexQuote:
|
|
90
|
+
"""Get forex quote"""
|
|
91
|
+
result = self.client.request(FOREX_QUOTE, symbol=symbol)
|
|
92
|
+
return cast(ForexQuote, result[0] if isinstance(result, list) else result)
|
|
93
|
+
|
|
94
|
+
def get_forex_historical(
|
|
95
|
+
self,
|
|
96
|
+
symbol: str,
|
|
97
|
+
start_date: date | None = None,
|
|
98
|
+
end_date: date | None = None,
|
|
99
|
+
) -> ForexPriceHistory:
|
|
100
|
+
"""Get forex historical prices"""
|
|
101
|
+
params = {"symbol": symbol}
|
|
102
|
+
if start_date:
|
|
103
|
+
params["from"] = start_date.strftime("%Y-%m-%d")
|
|
104
|
+
if end_date:
|
|
105
|
+
params["to"] = end_date.strftime("%Y-%m-%d")
|
|
106
|
+
|
|
107
|
+
result = self.client.request(FOREX_HISTORICAL, **params)
|
|
108
|
+
return cast(ForexPriceHistory, result)
|
|
109
|
+
|
|
110
|
+
def get_forex_intraday(
|
|
111
|
+
self, symbol: str, interval: str = "5min"
|
|
112
|
+
) -> list[ForexIntradayPrice]:
|
|
113
|
+
"""Get forex intraday prices"""
|
|
114
|
+
return self.client.request(FOREX_INTRADAY, symbol=symbol, interval=interval)
|
|
115
|
+
|
|
116
|
+
# Commodities methods
|
|
117
|
+
def get_commodities_list(self) -> list[Commodity]:
|
|
118
|
+
"""Get list of available commodities"""
|
|
119
|
+
return self.client.request(COMMODITIES_LIST)
|
|
120
|
+
|
|
121
|
+
def get_commodities_quotes(self) -> list[CommodityQuote]:
|
|
122
|
+
"""Get commodities quotes"""
|
|
123
|
+
return self.client.request(COMMODITIES_QUOTES)
|
|
124
|
+
|
|
125
|
+
def get_commodity_quote(self, symbol: str) -> CommodityQuote:
|
|
126
|
+
"""Get commodity quote"""
|
|
127
|
+
result = self.client.request(COMMODITY_QUOTE, symbol=symbol)
|
|
128
|
+
return cast(CommodityQuote, result[0] if isinstance(result, list) else result)
|
|
129
|
+
|
|
130
|
+
def get_commodity_historical(
|
|
131
|
+
self,
|
|
132
|
+
symbol: str,
|
|
133
|
+
start_date: date | None = None,
|
|
134
|
+
end_date: date | None = None,
|
|
135
|
+
) -> CommodityPriceHistory:
|
|
136
|
+
"""Get commodity historical prices"""
|
|
137
|
+
params = {"symbol": symbol}
|
|
138
|
+
if start_date:
|
|
139
|
+
params["from"] = start_date.strftime("%Y-%m-%d")
|
|
140
|
+
if end_date:
|
|
141
|
+
params["to"] = end_date.strftime("%Y-%m-%d")
|
|
142
|
+
|
|
143
|
+
result = self.client.request(COMMODITY_HISTORICAL, **params)
|
|
144
|
+
return cast(CommodityPriceHistory, result)
|
|
145
|
+
|
|
146
|
+
def get_commodity_intraday(
|
|
147
|
+
self, symbol: str, interval: str = "5min"
|
|
148
|
+
) -> list[CommodityIntradayPrice]:
|
|
149
|
+
"""Get commodity intraday prices"""
|
|
150
|
+
return self.client.request(COMMODITY_INTRADAY, symbol=symbol, interval=interval)
|