camel-ai 0.2.14__py3-none-any.whl → 0.2.16__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.

Potentially problematic release.


This version of camel-ai might be problematic. Click here for more details.

Files changed (69) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +362 -237
  3. camel/benchmarks/__init__.py +11 -1
  4. camel/benchmarks/apibank.py +560 -0
  5. camel/benchmarks/apibench.py +496 -0
  6. camel/benchmarks/gaia.py +2 -2
  7. camel/benchmarks/nexus.py +518 -0
  8. camel/datagen/__init__.py +21 -0
  9. camel/datagen/cotdatagen.py +448 -0
  10. camel/datagen/self_instruct/__init__.py +36 -0
  11. camel/datagen/self_instruct/filter/__init__.py +34 -0
  12. camel/datagen/self_instruct/filter/filter_function.py +216 -0
  13. camel/datagen/self_instruct/filter/filter_registry.py +56 -0
  14. camel/datagen/self_instruct/filter/instruction_filter.py +81 -0
  15. camel/datagen/self_instruct/self_instruct.py +393 -0
  16. camel/datagen/self_instruct/templates.py +384 -0
  17. camel/datahubs/huggingface.py +12 -2
  18. camel/datahubs/models.py +4 -2
  19. camel/embeddings/mistral_embedding.py +5 -1
  20. camel/embeddings/openai_compatible_embedding.py +6 -1
  21. camel/embeddings/openai_embedding.py +5 -1
  22. camel/interpreters/e2b_interpreter.py +5 -1
  23. camel/loaders/apify_reader.py +5 -1
  24. camel/loaders/chunkr_reader.py +5 -1
  25. camel/loaders/firecrawl_reader.py +0 -30
  26. camel/logger.py +11 -5
  27. camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +4 -1
  28. camel/models/anthropic_model.py +5 -1
  29. camel/models/azure_openai_model.py +1 -2
  30. camel/models/cohere_model.py +5 -1
  31. camel/models/deepseek_model.py +5 -1
  32. camel/models/gemini_model.py +5 -1
  33. camel/models/groq_model.py +5 -1
  34. camel/models/mistral_model.py +5 -1
  35. camel/models/nemotron_model.py +5 -1
  36. camel/models/nvidia_model.py +5 -1
  37. camel/models/openai_model.py +5 -1
  38. camel/models/qwen_model.py +5 -1
  39. camel/models/reka_model.py +5 -1
  40. camel/models/reward/nemotron_model.py +5 -1
  41. camel/models/samba_model.py +5 -1
  42. camel/models/togetherai_model.py +5 -1
  43. camel/models/yi_model.py +5 -1
  44. camel/models/zhipuai_model.py +5 -1
  45. camel/retrievers/auto_retriever.py +8 -0
  46. camel/retrievers/vector_retriever.py +6 -3
  47. camel/schemas/openai_converter.py +5 -1
  48. camel/societies/role_playing.py +4 -4
  49. camel/societies/workforce/workforce.py +2 -2
  50. camel/storages/graph_storages/nebula_graph.py +119 -27
  51. camel/storages/graph_storages/neo4j_graph.py +138 -0
  52. camel/toolkits/__init__.py +4 -0
  53. camel/toolkits/arxiv_toolkit.py +20 -3
  54. camel/toolkits/dappier_toolkit.py +196 -0
  55. camel/toolkits/function_tool.py +61 -61
  56. camel/toolkits/meshy_toolkit.py +5 -1
  57. camel/toolkits/notion_toolkit.py +1 -1
  58. camel/toolkits/openbb_toolkit.py +869 -0
  59. camel/toolkits/search_toolkit.py +91 -5
  60. camel/toolkits/stripe_toolkit.py +5 -1
  61. camel/toolkits/twitter_toolkit.py +24 -16
  62. camel/types/enums.py +7 -1
  63. camel/types/unified_model_type.py +5 -0
  64. camel/utils/__init__.py +4 -0
  65. camel/utils/commons.py +142 -20
  66. {camel_ai-0.2.14.dist-info → camel_ai-0.2.16.dist-info}/METADATA +17 -5
  67. {camel_ai-0.2.14.dist-info → camel_ai-0.2.16.dist-info}/RECORD +69 -55
  68. {camel_ai-0.2.14.dist-info → camel_ai-0.2.16.dist-info}/LICENSE +0 -0
  69. {camel_ai-0.2.14.dist-info → camel_ai-0.2.16.dist-info}/WHEEL +0 -0
@@ -0,0 +1,869 @@
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
+
15
+ import logging
16
+ from typing import List, Literal, Optional
17
+
18
+ from camel.toolkits.base import BaseToolkit
19
+ from camel.toolkits.function_tool import FunctionTool
20
+ from camel.utils import api_keys_required, dependencies_required
21
+
22
+
23
+ class OpenBBToolkit(BaseToolkit):
24
+ r"""A toolkit for accessing financial data and analysis through OpenBB
25
+ Platform.
26
+
27
+ This toolkit provides methods for retrieving and analyzing financial market
28
+ data, including stocks, ETFs, cryptocurrencies, economic indicators, and
29
+ more through the OpenBB Platform SDK. For credential configuration, please
30
+ refer to the OpenBB documentation
31
+ https://my.openbb.co/app/platform/credentials .
32
+ """
33
+
34
+ @dependencies_required("openbb")
35
+ @api_keys_required(
36
+ [
37
+ (None, "OPENBB_TOKEN"),
38
+ ]
39
+ )
40
+ def __init__(self) -> None:
41
+ r"""Initialize the OpenBBToolkit.
42
+
43
+ This method sets up the OpenBB client and initializes the OpenBB
44
+ Hub account system.
45
+ """
46
+ import os
47
+
48
+ from openbb import obb
49
+
50
+ self.client = obb
51
+ # Initialize OpenBB Hub account with access token
52
+ token = os.getenv("OPENBB_TOKEN")
53
+ self.client.account.login(pat=token) # type: ignore[union-attr]
54
+
55
+ def _handle_api_error(
56
+ self,
57
+ error: Exception,
58
+ operation: str,
59
+ log_level: str = "warning",
60
+ **format_args,
61
+ ) -> List:
62
+ r"""Handle API operation errors consistently.
63
+
64
+ Args:
65
+ error (Exception): The caught exception.
66
+ operation (str): Description of the failed operation
67
+ (e.g., "get_historical_data").
68
+ log_level (str): Logging level to use ("warning" or "error").
69
+ format_args: Additional format arguments for the error message .
70
+
71
+ Returns:
72
+ List: List with error message.
73
+ """
74
+ logger = logging.getLogger(__name__)
75
+ log_func = getattr(logger, log_level)
76
+
77
+ error_msg = f"Failed to {operation}"
78
+ if format_args:
79
+ error_msg += ": " + ", ".join(
80
+ f"{k}={v}" for k, v in format_args.items()
81
+ )
82
+ error_msg += f". Error: {error!s}"
83
+
84
+ log_func(error_msg)
85
+ return [error_msg]
86
+
87
+ def search_equity(
88
+ self,
89
+ query: str,
90
+ provider: Literal["intrinio", "sec"] = "sec",
91
+ ) -> List:
92
+ r"""Search for equity symbols and company information.
93
+
94
+ For SEC provider, an empty query ("") returns the complete list of
95
+ companies sorted by market cap.
96
+
97
+ Args:
98
+ query (str): Search query (company name or symbol), use "" for
99
+ complete SEC list.
100
+ provider (Literal["intrinio", "sec"]): Data provider. Available
101
+ options:
102
+ - sec: SEC EDGAR Database (sorted by market cap)
103
+ - intrinio: Intrinio Financial Data
104
+
105
+ Returns:
106
+ List: Search results.
107
+ """
108
+ try:
109
+ data = self.client.equity.search(query, provider=provider) # type: ignore[union-attr]
110
+
111
+ return data.results
112
+
113
+ except Exception as e:
114
+ return self._handle_api_error(
115
+ error=e,
116
+ operation="search equity",
117
+ log_level="warning",
118
+ query=query,
119
+ provider=provider,
120
+ )
121
+
122
+ def search_institution(self, query: str) -> List:
123
+ r"""Search for financial institutions in SEC database.
124
+
125
+ Args:
126
+ query (str): Institution name to search (e.g., "Berkshire
127
+ Hathaway").
128
+
129
+ Returns:
130
+ List: Institution search results.
131
+ """
132
+ try:
133
+ data = self.client.regulators.sec.institutions_search(query) # type: ignore[union-attr]
134
+
135
+ return data.results
136
+
137
+ except Exception as e:
138
+ return self._handle_api_error(
139
+ error=e,
140
+ operation="search institution",
141
+ log_level="warning",
142
+ query=query,
143
+ )
144
+
145
+ def search_filings(
146
+ self,
147
+ symbol: str,
148
+ provider: Literal["fmp", "intrinio", "sec"] = "sec",
149
+ form_type: Optional[str] = None,
150
+ ) -> List:
151
+ r"""Search for SEC filings by CIK or ticker symbol.
152
+
153
+ Args:
154
+ symbol (str): Symbol to get data for (e.g., "MAXD").
155
+ provider (Literal["fmp", "intrinio", "sec"]): Data provider.
156
+ (default: :obj:`sec`)
157
+ form_type (Optional[str]): Filter by form type. Check the data
158
+ provider for available types. Multiple comma separated items
159
+ allowed for provider(s): sec. (default: :obj:`None`)
160
+
161
+ Returns:
162
+ List: Filing search results.
163
+ """
164
+ try:
165
+ data = self.client.equity.fundamental.filings( # type: ignore[union-attr]
166
+ symbol=symbol,
167
+ form_type=form_type,
168
+ provider=provider,
169
+ )
170
+
171
+ return data.results
172
+
173
+ except Exception as e:
174
+ return self._handle_api_error(
175
+ error=e,
176
+ operation="search filings",
177
+ log_level="warning",
178
+ symbol=symbol,
179
+ form_type=form_type,
180
+ provider=provider,
181
+ )
182
+
183
+ def search_etf(
184
+ self,
185
+ query: str,
186
+ provider: Literal["fmp", "intrinio"] = "fmp",
187
+ ) -> List:
188
+ r"""Search for ETF information.
189
+
190
+ Args:
191
+ query (str): Search query (ETF name or symbol).
192
+ provider (Literal["fmp", "intrinio"]): Data provider. (default:
193
+ :obj:`fmp`)
194
+
195
+ Returns:
196
+ List: ETF search results.
197
+ """
198
+ try:
199
+ data = self.client.etf.search(query, provider=provider) # type: ignore[union-attr]
200
+ return data.results
201
+
202
+ except Exception as e:
203
+ return self._handle_api_error(
204
+ error=e,
205
+ operation="search ETF",
206
+ log_level="warning",
207
+ query=query,
208
+ provider=provider,
209
+ )
210
+
211
+ def screen_market(
212
+ self,
213
+ provider: Literal["fmp", "yfinance"] = "fmp",
214
+ country: Optional[str] = None,
215
+ exchange: Optional[str] = None,
216
+ sector: Optional[str] = None,
217
+ industry: Optional[str] = None,
218
+ mktcap_min: Optional[float] = None,
219
+ mktcap_max: Optional[float] = None,
220
+ beta_min: Optional[float] = None,
221
+ beta_max: Optional[float] = None,
222
+ ) -> List:
223
+ r"""Screen stocks based on market and fundamental criteria.
224
+
225
+ Args:
226
+ provider (Literal["fmp", "yfinance"]): Data provider.
227
+ (default: :obj:`fmp`)
228
+ country (Optional[str]): Two-letter ISO country code (e.g., 'US',
229
+ 'IN', 'CN'). (default: :obj:`None`)
230
+ exchange(Optional[str]) : Stock exchange code (e.g., 'NYSE',
231
+ 'AMEX', 'NSE'). (default: :obj:`None`)
232
+ sector (Optional[str]): Market sector (e.g., 'Financial Services',
233
+ 'Healthcare). (default: :obj:`None`)
234
+ industry (Optional[str]): Industry within sector (e.g.,
235
+ 'Banks—Regional','Drug Manufacturers'). (default: :obj:`None`)
236
+ mktcap_min (Optional[float]): Minimum market cap in USD.
237
+ (default: :obj:`None`)
238
+ mktcap_max (Optional[float]): Maximum market cap in USD.
239
+ (default: :obj:`None`)
240
+ beta_min (Optional[float]): Minimum beta value.
241
+ (default: :obj:`None`)
242
+ beta_max (Optional[float]): Maximum beta value.
243
+ (default: :obj:`None`)
244
+
245
+ Returns:
246
+ List: Screened stocks.
247
+ """
248
+ try:
249
+ params = {
250
+ k: v
251
+ for k, v in {
252
+ 'country': country,
253
+ 'exchange': exchange,
254
+ 'sector': sector,
255
+ 'industry': industry,
256
+ 'mktcap_min': mktcap_min,
257
+ 'mktcap_max': mktcap_max,
258
+ 'beta_min': beta_min,
259
+ 'beta_max': beta_max,
260
+ }.items()
261
+ if v is not None
262
+ }
263
+
264
+ data = self.client.equity.screener(provider=provider, **params) # type: ignore[union-attr]
265
+
266
+ return data.results
267
+
268
+ except Exception as e:
269
+ return self._handle_api_error(
270
+ error=e,
271
+ operation="screen market",
272
+ log_level="warning",
273
+ provider=provider,
274
+ )
275
+
276
+ def get_available_indices(
277
+ self,
278
+ provider: Literal['fmp', 'yfinance'] = 'fmp',
279
+ ) -> List:
280
+ r"""Get list of available market indices.
281
+
282
+ Args:
283
+ provider (Literal["fmp", "yfinance"]): Data provider.
284
+ (default: :obj:`fmp`)
285
+
286
+ Returns:
287
+ List: Available indices.
288
+ """
289
+ try:
290
+ data = self.client.index.available(provider=provider) # type: ignore[union-attr]
291
+
292
+ return data.results
293
+
294
+ except Exception as e:
295
+ return self._handle_api_error(
296
+ error=e,
297
+ operation="get available indices",
298
+ log_level="warning",
299
+ provider=provider,
300
+ )
301
+
302
+ def get_stock_quote(
303
+ self,
304
+ symbol: str,
305
+ provider: Literal['fmp', 'intrinio', 'yfinance'] = "fmp",
306
+ ) -> List:
307
+ r"""Get current stock quote for a given symbol.
308
+
309
+ Args:
310
+ symbol (str): Stock symbol (e.g., 'AAPL' for Apple Inc.)
311
+ provider (Literal["fmp", "intrinio", "yfinance"]): Data source.
312
+ (default: :obj:`fmp`)
313
+
314
+ Returns:
315
+ List: Stock quote data in requested format
316
+ """
317
+ try:
318
+ data = self.client.equity.price.quote( # type: ignore[union-attr]
319
+ symbol=symbol, provider=provider
320
+ )
321
+
322
+ return data.results
323
+
324
+ except Exception as e:
325
+ return self._handle_api_error(
326
+ error=e,
327
+ operation="get stock quote",
328
+ log_level="error",
329
+ symbol=symbol,
330
+ )
331
+
332
+ def get_historical_data(
333
+ self,
334
+ symbol: str,
335
+ provider: Literal['fmp', 'polygon', 'tiingo', 'yfinance'] = "fmp",
336
+ asset_type: Literal[
337
+ "equity",
338
+ "currency",
339
+ "crypto",
340
+ ] = "equity",
341
+ start_date: Optional[str] = None,
342
+ end_date: Optional[str] = None,
343
+ interval: Literal["1m", "5m", "15m", "30m", "1h", "4h", "1d"] = "1d",
344
+ ) -> List:
345
+ r"""Retrieves historical market data from OpenBB Platform providers.
346
+
347
+ Args:
348
+ symbol (str): Stock symbol (e.g., 'AAPL' for Apple Inc.).
349
+ provider (Literal["fmp", "polygon", "tiingo", "yfinance"]): Data
350
+ source. (default: :obj:`fmp`)
351
+ asset_type (Literal["equity", "currency", "crypto"]): Asset type.
352
+ (default: :obj:`equity`)
353
+ start_date: Start date in YYYY-MM-DD format. If None, uses
354
+ provider's default lookback. (default: :obj:`None`)
355
+ end_date: End date in YYYY-MM-DD format. If None, uses current
356
+ date. (default: :obj:`None`)
357
+ interval: Data frequency/timeframe. (default: :obj:`1d`)
358
+
359
+ Returns:
360
+ List: Historical market data.
361
+ """
362
+ try:
363
+ if asset_type == "currency":
364
+ response = self.client.currency.price.historical( # type: ignore[union-attr]
365
+ symbol=symbol,
366
+ start_date=start_date,
367
+ end_date=end_date,
368
+ interval=interval,
369
+ provider=provider,
370
+ )
371
+ elif asset_type == "crypto":
372
+ response = self.client.crypto.price.historical( # type: ignore[union-attr]
373
+ symbol=symbol,
374
+ start_date=start_date,
375
+ end_date=end_date,
376
+ interval=interval,
377
+ provider=provider,
378
+ )
379
+ else: # equity
380
+ response = self.client.equity.price.historical( # type: ignore[union-attr]
381
+ symbol=symbol,
382
+ start_date=start_date,
383
+ end_date=end_date,
384
+ interval=interval,
385
+ provider=provider,
386
+ )
387
+
388
+ return response.results
389
+ except Exception as e:
390
+ return self._handle_api_error(
391
+ error=e,
392
+ operation="get historical data",
393
+ log_level="error",
394
+ symbol=symbol,
395
+ )
396
+
397
+ def get_market_data(
398
+ self,
399
+ category: Literal["gainers", "losers", "active"] = "active",
400
+ ) -> List:
401
+ r"""Get market movers data.
402
+
403
+ Args:
404
+ category(Literal["gainers", "losers", "active"]): Type of market
405
+ data. Must be 'gainers', 'losers', or 'active'. (default:
406
+ :obj:`active`)
407
+
408
+ Returns:
409
+ List: Market movers data.
410
+ """
411
+ try:
412
+ if category == "gainers":
413
+ response = self.client.equity.discovery.gainers() # type: ignore[union-attr]
414
+ elif category == "losers":
415
+ response = self.client.equity.discovery.losers() # type: ignore[union-attr]
416
+ else: # active
417
+ response = self.client.equity.discovery.active() # type: ignore[union-attr]
418
+
419
+ return response.results
420
+
421
+ except Exception as e:
422
+ return self._handle_api_error(
423
+ error=e,
424
+ operation="get market data",
425
+ log_level="error",
426
+ category=category,
427
+ )
428
+
429
+ def get_earnings_calendar(
430
+ self,
431
+ start_date: Optional[str] = None,
432
+ end_date: Optional[str] = None,
433
+ ) -> List:
434
+ r"""Get company earnings calendar with filtering and sorting options.
435
+
436
+ Args:
437
+ start_date (Optional[str]): Start date in YYYY-MM-DD format.
438
+ (default: :obj:`None`)
439
+ end_date (Optional[str]): End date in YYYY-MM-DD format. (default:
440
+ :obj:`None`)
441
+
442
+ Returns:
443
+ List: Earnings calendar.
444
+ """
445
+ try:
446
+ response = self.client.equity.calendar.earnings( # type: ignore[union-attr]
447
+ start_date=start_date, end_date=end_date
448
+ )
449
+
450
+ return response.results
451
+
452
+ except Exception as e:
453
+ return self._handle_api_error(
454
+ error=e,
455
+ operation="get earnings calendar",
456
+ log_level="warning",
457
+ )
458
+
459
+ def get_dividend_calendar(
460
+ self,
461
+ start_date: Optional[str] = None,
462
+ end_date: Optional[str] = None,
463
+ ) -> List:
464
+ r"""Get dividend calendar with optional yield calculations.
465
+
466
+ Args:
467
+ start_date (Optional[str]): Start date in YYYY-MM-DD format.
468
+ (default: :obj:`None`)
469
+ end_date (Optional[str]): End date in YYYY-MM-DD format. (default:
470
+ :obj:`None`)
471
+
472
+ Returns:
473
+ List: Dividend calendar.
474
+ """
475
+ try:
476
+ response = self.client.equity.calendar.dividend( # type: ignore[union-attr]
477
+ start_date=start_date, end_date=end_date
478
+ )
479
+
480
+ return response.results
481
+
482
+ except Exception as e:
483
+ return self._handle_api_error(
484
+ error=e,
485
+ operation="get dividend calendar",
486
+ log_level="warning",
487
+ )
488
+
489
+ def get_ipo_calendar(
490
+ self,
491
+ start_date: Optional[str] = None,
492
+ end_date: Optional[str] = None,
493
+ ) -> List:
494
+ r"""Get IPO/SPO calendar with comprehensive filtering options.
495
+
496
+ Args:
497
+ start_date (Optional[str]): Start date in YYYY-MM-DD format.
498
+ (default: :obj:`None`)
499
+ end_date (Optional[str]): End date in YYYY-MM-DD format. (default:
500
+ :obj:`None`)
501
+
502
+ Returns:
503
+ List: IPO/SPO calendar.
504
+ """
505
+ try:
506
+ response = self.client.equity.calendar.ipo( # type: ignore[union-attr]
507
+ start_date=start_date, end_date=end_date
508
+ )
509
+
510
+ return response.results
511
+
512
+ except Exception as e:
513
+ return self._handle_api_error(
514
+ error=e,
515
+ operation="get IPO calendar",
516
+ log_level="warning",
517
+ )
518
+
519
+ def get_available_indicators(
520
+ self,
521
+ provider: Literal["econdb", "imf"] = "econdb",
522
+ ) -> List:
523
+ r"""Get list of available economic indicators.
524
+
525
+ Args:
526
+ provider (Literal["econdb", "imf"]): Data provider.
527
+ (default: :obj:`econdb`)
528
+
529
+ Returns:
530
+ List: Available indicators.
531
+ """
532
+ try:
533
+ response = self.client.economy.available_indicators( # type: ignore[union-attr]
534
+ provider=provider
535
+ )
536
+
537
+ return response.results
538
+
539
+ except Exception as e:
540
+ return self._handle_api_error(
541
+ error=e,
542
+ operation="get available indicators",
543
+ log_level="warning",
544
+ provider=provider,
545
+ )
546
+
547
+ def get_indicator_data(
548
+ self,
549
+ symbol: str,
550
+ country: str,
551
+ provider: Literal["econdb", "imf"] = "econdb",
552
+ ) -> List:
553
+ r"""Get detailed metadata for an economic indicator.
554
+
555
+ Args:
556
+ symbol (str): Stock symbol (e.g., 'AAPL' for Apple Inc.).
557
+ country (str): Country code (e.g., 'US' for United States).
558
+ provider (Literal["econdb", "imf"]): Data provider. (default:
559
+ :obj:`econdb`)
560
+
561
+ Returns:
562
+ List: Indicator data.
563
+ """
564
+ try:
565
+ response = self.client.economy.indicators( # type: ignore[union-attr]
566
+ country=country, provider=provider, symbol=symbol
567
+ )
568
+ return response.results
569
+
570
+ except Exception as e:
571
+ return self._handle_api_error(
572
+ error=e,
573
+ operation="get indicator data",
574
+ log_level="warning",
575
+ symbol=symbol,
576
+ country=country,
577
+ provider=provider,
578
+ )
579
+
580
+ def get_financial_metrics(
581
+ self,
582
+ symbol: str,
583
+ provider: Literal['fmp', 'intrinio', 'yfinance'] = "fmp",
584
+ period: Literal["annual", "quarter"] = "annual",
585
+ limit: int = 5,
586
+ ) -> List:
587
+ r"""Get company financial metrics and ratios.
588
+
589
+ Args:
590
+ symbol (str): Stock symbol (e.g., 'AAPL' for Apple Inc.).
591
+ provider (Literal["fmp", "intrinio", "yfinance"]): Data source.
592
+ (default: :obj:`fmp`)
593
+ period (Literal["annual", "quarter"]): Reporting period, "annual":
594
+ Annual metrics, "quarter": Quarterly metrics. (default:
595
+ :obj:`annual`)
596
+ limit (int): Number of periods to return. (default: :obj:`5`)
597
+
598
+ Returns:
599
+ List: Financial metric.
600
+ """
601
+ try:
602
+ response = self.client.equity.fundamental.metrics( # type: ignore[union-attr]
603
+ symbol=symbol, period=period, provider=provider, limit=limit
604
+ )
605
+
606
+ return response.results
607
+
608
+ except Exception as e:
609
+ return self._handle_api_error(
610
+ error=e,
611
+ operation="get financial metrics",
612
+ log_level="warning",
613
+ symbol=symbol,
614
+ provider=provider,
615
+ )
616
+
617
+ def get_company_profile(
618
+ self,
619
+ symbol: str,
620
+ provider: Literal["fmp", "intrinio", "yfinance"] = "fmp",
621
+ ) -> List:
622
+ r"""Get company profile information.
623
+
624
+ Args:
625
+ symbol (str): Stock symbol (e.g., 'AAPL' for Apple Inc.).
626
+ provider (Literal["fmp", "intrinio", "yfinance"]): Data provider.
627
+ (default: :obj:`fmp`)
628
+
629
+ Returns:
630
+ List: Company profile.
631
+ """
632
+ try:
633
+ response = self.client.equity.profile( # type: ignore[union-attr]
634
+ symbol=symbol, provider=provider
635
+ )
636
+
637
+ return response.results
638
+
639
+ except Exception as e:
640
+ return self._handle_api_error(
641
+ error=e,
642
+ operation="get company profile",
643
+ log_level="warning",
644
+ symbol=symbol,
645
+ provider=provider,
646
+ )
647
+
648
+ def get_financial_statement(
649
+ self,
650
+ symbol: str,
651
+ provider: Literal["fmp", "intrinio", "polygon", "yfinance"] = "fmp",
652
+ statement_type: Literal["balance", "income", "cash"] = "balance",
653
+ period: Literal["annual", "quarter"] = "annual",
654
+ limit: int = 5,
655
+ ) -> List:
656
+ r"""Get company financial statements.
657
+
658
+ Access balance sheet, income statement, or cash flow statement data.
659
+ Data availability and field names vary by provider and company type.
660
+
661
+ Args:
662
+ symbol (str): Stock symbol (e.g., 'AAPL' for Apple Inc.).
663
+ provider (Literal["fmp", "intrinio", "polygon", "yfinance"]): Data
664
+ provider. (default: :obj:`fmp`)
665
+ statement_type (Literal["balance", "income", "cash"]): Type of
666
+ financial statement, "balance": Balance sheet, "income":
667
+ Income statement, "cash": Cash flow statement. (default:
668
+ :obj:`balance`)
669
+ period (Literal["annual", "quarter"]): Reporting period, "annual":
670
+ Annual reports, "quarter": Quarterly reports. (default:
671
+ :obj:`annual`)
672
+ limit (int): Number of periods to return. (default: :obj:`5`)
673
+
674
+ Returns:
675
+ List: Financial statement data.
676
+ """
677
+ try:
678
+ # Map statement type to client endpoint
679
+ endpoint_map = {
680
+ "balance": self.client.equity.fundamental.balance, # type: ignore[union-attr]
681
+ "income": self.client.equity.fundamental.income, # type: ignore[union-attr]
682
+ "cash": self.client.equity.fundamental.cash, # type: ignore[union-attr]
683
+ }
684
+
685
+ endpoint = endpoint_map.get(statement_type)
686
+ if not endpoint:
687
+ raise ValueError(f"Invalid statement_type: {statement_type}")
688
+
689
+ response = endpoint(
690
+ symbol=symbol, period=period, provider=provider, limit=limit
691
+ )
692
+
693
+ return response.results
694
+
695
+ except Exception as e:
696
+ return self._handle_api_error(
697
+ error=e,
698
+ operation="get financial statement",
699
+ log_level="warning",
700
+ symbol=symbol,
701
+ provider=provider,
702
+ )
703
+
704
+ def get_financial_attributes(
705
+ self,
706
+ symbol: str,
707
+ tag: str,
708
+ frequency: Literal[
709
+ "daily", "weekly", "monthly", "quarterly", "yearly"
710
+ ] = "yearly",
711
+ ) -> List:
712
+ r"""Get historical values for a specific financial attribute.
713
+
714
+ Args:
715
+ symbol (str): Stock symbol (e.g., 'AAPL' for Apple Inc.).
716
+ tag (str): Financial attribute tag (use
717
+ search_financial_attributes to find tags).
718
+ frequency (Literal["daily", "weekly", "monthly", "quarterly",
719
+ "yearly"]): Data frequency, "daily", "weekly", "monthly",
720
+ "quarterly", "yearly". (default: :obj:`yearly`)
721
+
722
+ Returns:
723
+ List: Historical values.
724
+ """
725
+ try:
726
+ response = self.client.equity.fundamental.historical_attributes( # type: ignore[union-attr]
727
+ symbol=symbol, tag=tag, frequency=frequency
728
+ )
729
+
730
+ return response.results
731
+
732
+ except Exception as e:
733
+ return self._handle_api_error(
734
+ error=e,
735
+ operation="get financial attribute",
736
+ log_level="warning",
737
+ symbol=symbol,
738
+ tag=tag,
739
+ )
740
+
741
+ def search_financial_attributes(
742
+ self,
743
+ query: str,
744
+ ) -> List:
745
+ r"""Search for available financial attributes/tags.
746
+
747
+ Args:
748
+ query (str): Search term (e.g., "marketcap", "revenue", "assets").
749
+
750
+ Returns:
751
+ List: Matching attributes.
752
+ """
753
+ try:
754
+ response = self.client.equity.fundamental.search_attributes( # type: ignore[union-attr]
755
+ query=query
756
+ )
757
+
758
+ return response.results
759
+
760
+ except Exception as e:
761
+ return self._handle_api_error(
762
+ error=e,
763
+ operation="search financial attributes",
764
+ log_level="warning",
765
+ query=query,
766
+ )
767
+
768
+ def get_economic_calendar(
769
+ self,
770
+ provider: Literal["fmp", "tradingeconomics"] = "fmp",
771
+ start_date: Optional[str] = None,
772
+ end_date: Optional[str] = None,
773
+ ) -> List:
774
+ r"""Get economic calendar events.
775
+
776
+ Args:
777
+ provider (Literal["fmp", "tradingeconomics"]): Data provider.
778
+ (default: :obj:`fmp`)
779
+ start_date (Optional[str]): Start date in YYYY-MM-DD format.
780
+ (default: :obj:`None`)
781
+ end_date (Optional[str]): End date in YYYY-MM-DD format. (default:
782
+ :obj:`None`)
783
+
784
+ Returns:
785
+ List: Economic calendar.
786
+ """
787
+ try:
788
+ response = self.client.economy.calendar( # type: ignore[union-attr]
789
+ start_date=start_date, end_date=end_date, provider=provider
790
+ )
791
+
792
+ return response.results
793
+
794
+ except Exception as e:
795
+ return self._handle_api_error(
796
+ error=e,
797
+ operation="get economic calendar",
798
+ log_level="warning",
799
+ provider=provider,
800
+ )
801
+
802
+ def get_tools(self) -> List[FunctionTool]:
803
+ r"""Returns a list of available OpenBB financial tools.
804
+
805
+ Returns:
806
+ List[FunctionTool]: List of available tools.
807
+ """
808
+ return [
809
+ FunctionTool(
810
+ func=self.search_equity,
811
+ ),
812
+ FunctionTool(
813
+ func=self.search_etf,
814
+ ),
815
+ FunctionTool(
816
+ func=self.search_institution,
817
+ ),
818
+ FunctionTool(
819
+ func=self.search_filings,
820
+ ),
821
+ FunctionTool(
822
+ func=self.screen_market,
823
+ ),
824
+ FunctionTool(
825
+ func=self.get_available_indices,
826
+ ),
827
+ FunctionTool(
828
+ func=self.get_stock_quote,
829
+ ),
830
+ FunctionTool(
831
+ func=self.get_historical_data,
832
+ ),
833
+ FunctionTool(
834
+ func=self.get_market_data,
835
+ ),
836
+ FunctionTool(
837
+ func=self.get_earnings_calendar,
838
+ ),
839
+ FunctionTool(
840
+ func=self.get_dividend_calendar,
841
+ ),
842
+ FunctionTool(
843
+ func=self.get_ipo_calendar,
844
+ ),
845
+ FunctionTool(
846
+ func=self.get_available_indicators,
847
+ ),
848
+ FunctionTool(
849
+ func=self.get_indicator_data,
850
+ ),
851
+ FunctionTool(
852
+ func=self.get_financial_metrics,
853
+ ),
854
+ FunctionTool(
855
+ func=self.get_company_profile,
856
+ ),
857
+ FunctionTool(
858
+ func=self.get_financial_statement,
859
+ ),
860
+ FunctionTool(
861
+ func=self.get_financial_attributes,
862
+ ),
863
+ FunctionTool(
864
+ func=self.search_financial_attributes,
865
+ ),
866
+ FunctionTool(
867
+ func=self.get_economic_calendar,
868
+ ),
869
+ ]