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.
Files changed (84) hide show
  1. fmp_data/__init__.py +138 -0
  2. fmp_data/alternative/__init__.py +34 -0
  3. fmp_data/alternative/client.py +150 -0
  4. fmp_data/alternative/endpoints.py +533 -0
  5. fmp_data/alternative/mapping.py +737 -0
  6. fmp_data/alternative/models.py +296 -0
  7. fmp_data/alternative/schema.py +165 -0
  8. fmp_data/base.py +316 -0
  9. fmp_data/client.py +269 -0
  10. fmp_data/company/__init__.py +40 -0
  11. fmp_data/company/client.py +238 -0
  12. fmp_data/company/endpoints.py +711 -0
  13. fmp_data/company/hints.py +77 -0
  14. fmp_data/company/mapping.py +1361 -0
  15. fmp_data/company/models.py +543 -0
  16. fmp_data/company/schema.py +132 -0
  17. fmp_data/config.py +207 -0
  18. fmp_data/economics/__init__.py +16 -0
  19. fmp_data/economics/client.py +52 -0
  20. fmp_data/economics/endpoints.py +164 -0
  21. fmp_data/economics/mapping.py +641 -0
  22. fmp_data/economics/models.py +75 -0
  23. fmp_data/economics/schema.py +91 -0
  24. fmp_data/exceptions.py +54 -0
  25. fmp_data/fundamental/__init__.py +40 -0
  26. fmp_data/fundamental/client.py +87 -0
  27. fmp_data/fundamental/endpoints.py +403 -0
  28. fmp_data/fundamental/mapping.py +867 -0
  29. fmp_data/fundamental/models.py +913 -0
  30. fmp_data/fundamental/schema.py +40 -0
  31. fmp_data/institutional/__init__.py +26 -0
  32. fmp_data/institutional/client.py +141 -0
  33. fmp_data/institutional/endpoints.py +321 -0
  34. fmp_data/institutional/mapping.py +749 -0
  35. fmp_data/institutional/models.py +301 -0
  36. fmp_data/institutional/schema.py +99 -0
  37. fmp_data/intelligence/__init__.py +58 -0
  38. fmp_data/intelligence/client.py +331 -0
  39. fmp_data/intelligence/endpoints.py +788 -0
  40. fmp_data/intelligence/mapping.py +1677 -0
  41. fmp_data/intelligence/models.py +707 -0
  42. fmp_data/intelligence/schema.py +57 -0
  43. fmp_data/investment/__init__.py +24 -0
  44. fmp_data/investment/client.py +104 -0
  45. fmp_data/investment/endpoints.py +241 -0
  46. fmp_data/investment/mapping.py +658 -0
  47. fmp_data/investment/models.py +220 -0
  48. fmp_data/investment/schema.py +106 -0
  49. fmp_data/lc/__init__.py +256 -0
  50. fmp_data/lc/config.py +88 -0
  51. fmp_data/lc/embedding.py +140 -0
  52. fmp_data/lc/hints.py +66 -0
  53. fmp_data/lc/mapping.py +107 -0
  54. fmp_data/lc/models.py +98 -0
  55. fmp_data/lc/registry.py +693 -0
  56. fmp_data/lc/utils.py +35 -0
  57. fmp_data/lc/validation.py +267 -0
  58. fmp_data/lc/vector_store.py +592 -0
  59. fmp_data/logger.py +358 -0
  60. fmp_data/market/__init__.py +18 -0
  61. fmp_data/market/client.py +106 -0
  62. fmp_data/market/endpoints.py +358 -0
  63. fmp_data/market/hints.py +22 -0
  64. fmp_data/market/mapping.py +854 -0
  65. fmp_data/market/models.py +310 -0
  66. fmp_data/market/schema.py +186 -0
  67. fmp_data/mcp/__init__.py +0 -0
  68. fmp_data/mcp/server.py +101 -0
  69. fmp_data/mcp/tool_loader.py +74 -0
  70. fmp_data/mcp/tools_manifest.py +17 -0
  71. fmp_data/models.py +265 -0
  72. fmp_data/rate_limit.py +136 -0
  73. fmp_data/schema.py +158 -0
  74. fmp_data/technical/__init__.py +28 -0
  75. fmp_data/technical/client.py +214 -0
  76. fmp_data/technical/endpoints.py +102 -0
  77. fmp_data/technical/mapping.py +452 -0
  78. fmp_data/technical/models.py +87 -0
  79. fmp_data/technical/schema.py +261 -0
  80. fmp_data-0.0.0.dist-info/METADATA +732 -0
  81. fmp_data-0.0.0.dist-info/RECORD +84 -0
  82. fmp_data-0.0.0.dist-info/WHEEL +4 -0
  83. fmp_data-0.0.0.dist-info/entry_points.txt +10 -0
  84. 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)