CatPtain commited on
Commit
7f82fb5
·
verified ·
1 Parent(s): 12c00ae

Upload 5 files

Browse files
openbb_platform/CONTRIBUTING.md ADDED
@@ -0,0 +1,891 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Contributing to the OpenBB Platform
3
+
4
+ <!-- markdownlint-disable MD033 MD024 -->
5
+
6
+ - [Contributing to the OpenBB Platform](#contributing-to-the-openbb-platform)
7
+ - [Introduction](#introduction)
8
+ - [Quick look into the OpenBB Platform](#quick-look-into-the-openbb-platform)
9
+ - [What is the Standardization Framework?](#what-is-the-standardization-framework)
10
+ - [Standardization Caveats](#standardization-caveats)
11
+ - [Standard QueryParams Example](#standard-queryparams-example)
12
+ - [Standard Data Example](#standard-data-example)
13
+ - [What is an extension?](#what-is-an-extension)
14
+ - [Types of extensions](#types-of-extensions)
15
+ - [Dependency Management](#dependency-management)
16
+ - [High-Level Overview](#high-level-overview)
17
+ - [Core Dependency Management](#core-dependency-management)
18
+ - [Installation](#installation)
19
+ - [Using Poetry](#using-poetry)
20
+ - [Core and Extensions](#core-and-extensions)
21
+ - [Installation](#installation-1)
22
+ - [Dependency Management with Poetry](#dependency-management-with-poetry)
23
+ - [Developer Guidelines](#developer-guidelines)
24
+ - [Expectations for Developers](#expectations-for-developers)
25
+ - [How to build OpenBB extensions?](#how-to-build-openbb-extensions)
26
+ - [Building Extensions: Best Practices](#building-extensions-best-practices)
27
+ - [How to add a new data point?](#how-to-add-a-new-data-point)
28
+ - [Identify which type of data you want to add](#identify-which-type-of-data-you-want-to-add)
29
+ - [Check if the standard model exists](#check-if-the-standard-model-exists)
30
+ - [Create Query Parameters model](#create-query-parameters-model)
31
+ - [Create Data Output model](#create-data-output-model)
32
+ - [Build the Fetcher](#build-the-fetcher)
33
+ - [Make the provider visible](#make-the-provider-visible)
34
+ - [How to add custom data sources?](#how-to-add-custom-data-sources)
35
+ - [OpenBB Platform commands](#openbb-platform-commands)
36
+ - [Architectural considerations](#architectural-considerations)
37
+ - [Important classes](#important-classes)
38
+ - [Import statements](#import-statements)
39
+ - [The TET pattern](#the-tet-pattern)
40
+ - [Error](#errors)
41
+ - [Data processing commands](#data-processing-commands)
42
+ - [Python Interface](#python-interface)
43
+ - [API Interface](#api-interface)
44
+ - [Contributor Guidelines](#contributor-guidelines)
45
+ - [Expectations for Contributors](#expectations-for-contributors)
46
+ - [Quality Assurance](#quality-assurance)
47
+ - [Unit tests](#unit-tests)
48
+ - [Integration tests](#integration-tests)
49
+ - [Import time](#import-time)
50
+ - [Sharing your extension](#sharing-your-extension)
51
+ - [Publish your extension to PyPI](#publish-your-extension-to-pypi)
52
+ - [Setup](#setup)
53
+ - [Release](#release)
54
+ - [Publish](#publish)
55
+ - [Manage extensions](#manage-extensions)
56
+ - [Add an extension as a dependency](#add-an-extension-as-a-dependency)
57
+ - [Write code and commit](#write-code-and-commit)
58
+ - [How to create a PR?](#how-to-create-a-pr)
59
+ - [Branch Naming Conventions](#branch-naming-conventions)
60
+
61
+ ## Introduction
62
+
63
+ This document provides guidelines for contributing to the OpenBB Platform.
64
+ Throughout this document, we will be differentiating between two types of contributors: Developers and Contributors.
65
+
66
+ 1. **Developers**: Those who are building new features or extensions for the OpenBB Platform or leveraging the OpenBB Platform.
67
+ 2. **Contributors**: Those who contribute to the existing codebase, by opening a [Pull Request](#getting_started-create-a-pr) thus giving back to the community.
68
+
69
+ **Why is this distinction important?**
70
+
71
+ The OpenBB Platform is designed as a foundation for further development. We anticipate a wide range of creative use cases for it. Some use cases may be highly specific or detail-oriented, solving particular problems that may not necessarily fit within the OpenBB Platform Github repository. This is entirely acceptable and even encouraged. This document provides a comprehensive guide on how to build your own extensions, add new data points, and more.
72
+
73
+ The **Developer** role, as defined in this document, can be thought of as the foundational role. Developers are those who use the OpenBB Platform as is or build upon it.
74
+
75
+ Conversely, the **Contributor** role refers to those who enhance the OpenBB Platform codebase (either by directly adding to the OpenBB Platform or by extending the [extension repository](/openbb_platform/extensions/)). Contributors are willing to go the extra mile, spending additional time on quality assurance, testing, or collaborating with the OpenBB development team to ensure adherence to standards, thereby giving back to the community.
76
+
77
+ ### Quick look into the OpenBB Platform
78
+
79
+ The OpenBB Platform is built by the Open-Source community and is characterized by its core and extensions. The core handles data integration and standardization, while the extensions enable customization and advanced functionalities. The OpenBB Platform is designed to be used both from a Python interface and a REST API.
80
+
81
+ The REST API is built on top of FastAPI and can be started by running the following command from the root:
82
+
83
+ ```bash
84
+ uvicorn openbb_platform.core.openbb_core.api.rest_api:app --host 0.0.0.0 --port 8000 --reload
85
+ ```
86
+
87
+ The Python interfaces we provide to users is the `openbb` python package.
88
+
89
+ The code you will find in this package is generated from a script and it is just a wrapper around the `openbb-core` and any installed extensions.
90
+
91
+ When the user runs `import openbb`, `from openbb import obb` or other variants, the script that generates the packaged code is triggered. It detects if there are new extensions installed in the environment and rebuilds the packaged code accordingly. If new extensions are not found, it just uses the current packaged version.
92
+
93
+ When you are developing chances are you want to manually trigger the package rebuild.
94
+
95
+ You can do that with:
96
+
97
+ ```python
98
+ python -c "import openbb; openbb.build()"
99
+ ```
100
+
101
+ The Python interface can be imported with:
102
+
103
+ ```python
104
+ from openbb import obb
105
+ ```
106
+
107
+ This document will take you through two types of contributions:
108
+
109
+ 1. Building a custom extension
110
+ 2. Contributing directly to the OpenBB Platform
111
+
112
+ Before moving forward, please take a look at the high-level view of the OpenBB Platform architecture. We will go over each bit in this document.
113
+
114
+ <picture>
115
+ <source media="(prefers-color-scheme: dark)" srcset="https://github.com/OpenBB-finance/OpenBB/assets/74266147/c9a5a92a-28b6-4257-aefc-deaebe635c6a">
116
+ <img alt="OpenBB Platform High-Level Architecture" src="https://github.com/OpenBB-finance/OpenBB/assets/74266147/c9a5a92a-28b6-4257-aefc-deaebe635c6a">
117
+ </picture>
118
+
119
+ #### What is the Standardization Framework?
120
+
121
+ The Standardization Framework is a set of tools and guidelines that enable the user to query and obtain data in a consistent way across multiple providers.
122
+
123
+ Each data model should inherit from a [standard data](core/openbb_core/provider/standard_models) model that is already defined inside the OpenBB Platform. All standard models are created and maintained by the OpenBB team.
124
+
125
+ Usage of these models will unlock a set of perks that are only available to standardized data, namely:
126
+
127
+ - Can query and output data in a standardized way.
128
+ - Can expect extensions that follow standardization to work out-of-the-box.
129
+ - Can expect transparently defined schemas for the data that is returned by the API.
130
+ - Can expect consistent data types and validation.
131
+ - Will work seamlessly with other providers that use the same standard model.
132
+
133
+ The standard models are defined under the `/OpenBB/openbb_platform/core/openbb_core/provider/standard_models` directory.
134
+
135
+ They define the [`QueryParams`](core/openbb_core/provider/abstract/query_params.py) and [`Data`](core/openbb_core/provider/abstract/data.py) models, which are used to query and output data. They are pydantic and you can leverage all the pydantic features such as validators.
136
+
137
+ ##### Standardization Caveats
138
+
139
+ The standardization framework is a very powerful tool, but it has some caveats that you should be aware of:
140
+
141
+ - We standardize fields that are shared between two or more providers. If there is a third provider that doesn't share the same fields, we will declare it as an `Optional` field.
142
+ - When mapping the column names from a provider-specific model to the standard model, the CamelCase to snake_case conversion is done automatically. If the column names are not the same, you'll need to manually map them. (e.g. `o` -> `open`)
143
+ - The standard models are created and maintained by the OpenBB team. If you want to add a new field to a standard model, you'll need to open a PR to the OpenBB Platform.
144
+
145
+ ##### Standard QueryParams Example
146
+
147
+ ```python
148
+ class EquityHistoricalQueryParams(QueryParams):
149
+ """Equity Historical end of day Query."""
150
+ symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", ""))
151
+ start_date: Optional[date] = Field(
152
+ description=QUERY_DESCRIPTIONS.get("start_date", ""), default=None
153
+ )
154
+ end_date: Optional[date] = Field(
155
+ description=QUERY_DESCRIPTIONS.get("end_date", ""), default=None
156
+ )
157
+ ```
158
+
159
+ The `QueryParams` is an abstract class that just tells us that we are dealing with query parameters
160
+
161
+ The OpenBB Platform dynamically knows where the standard models begin in the inheritance tree, so you don't need to worry about it.
162
+
163
+ ##### Standard Data Example
164
+
165
+ ```python
166
+ class EquityHistoricalData(Data):
167
+ """Equity Historical end of day price Data."""
168
+
169
+ date: datetime = Field(description=DATA_DESCRIPTIONS.get("date", ""))
170
+ open: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("open", ""))
171
+ high: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("high", ""))
172
+ low: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("low", ""))
173
+ close: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("close", ""))
174
+ volume: float = Field(description=DATA_DESCRIPTIONS.get("volume", ""))
175
+ vwap: Optional[PositiveFloat] = Field(description=DATA_DESCRIPTIONS.get("vwap", ""), default=None)
176
+ ```
177
+
178
+ The `Data` class is an abstract class that tells us the expected output data. Here we can see a `vwap` field that is `Optional`. This is because not all providers share this field while it is shared between two or more providers.
179
+
180
+ #### What is an extension?
181
+
182
+ An extension adds functionality to the OpenBB Platform. It can be a new data source, a new command, a new visualization, etc.
183
+
184
+ ##### Types of extensions
185
+
186
+ We primarily have 3 types of extensions:
187
+
188
+ 1. OpenBB Extensions - built and maintained by the OpenBB team (e.g. `openbb-equity`)
189
+ 2. Community Extensions - built by anyone and primarily maintained by OpenBB (e.g. `openbb-yfinance`)
190
+ 3. Independent Extensions - built and maintained independently by anyone
191
+
192
+ If your extension is of high quality and you think that it would be a good community extension, you can open a PR to the OpenBB Platform repository and we'll review it.
193
+
194
+ We encourage independent extensions to be shared with the community by publishing them to PyPI.
195
+
196
+ ## Dependency Management
197
+
198
+ ### High-Level Overview
199
+
200
+ - **Provider**: The base package with no dependencies on other `openbb` packages.
201
+ - **Core**: Depends on the Provider and serves as the main infrastructural package.
202
+ - **Extensions**: Utility packages that leverage Core's infrastructure. Each extension is its own package.
203
+ - **Providers**: Utility packages extending functionality to different providers, where each provider is its own package.
204
+
205
+ ### Dependency Management
206
+
207
+ #### Using Poetry
208
+
209
+ Ensure you're in a fresh conda environment before adjusting dependencies.
210
+ Dependencies are manages with `poetry`. Install poetry with `pip install poetry`
211
+
212
+ - **Add a Dependency**: `poetry add <my-dependency>`
213
+ - **Update Dependencies**:
214
+ - All: `poetry update`
215
+ - Specific: `poetry update <my-dependency>`
216
+ - **Remove a Dependency**: `poetry remove <my-dependency>`
217
+
218
+ ### Core and Extensions
219
+
220
+ #### Installation
221
+
222
+ For development setup, use the provided script to install all extensions and their dependencies:
223
+
224
+ - From the root of the repo call `python dev_install.py --extras`
225
+
226
+ > **Note**: If developing an extension, you can avoid installing all extensions to prevent unnecessary overhead.
227
+
228
+ #### Dependency Management with Poetry
229
+
230
+ - **Add Platform Extension**: `poetry add openbb-extension-name [--dev]`
231
+ - **Resolve Conflicts**: Adjust versions in `pyproject.toml` if notified by Poetry.
232
+ - **Update Dependencies Lock File**: `poetry lock`
233
+ - **Update Platform**: `poetry update openbb-platform`
234
+ - **Documentation**: Maintain `pyproject.toml` and `poetry.lock` for a clear record of dependencies.
235
+
236
+ ## Developer Guidelines
237
+
238
+ ### Expectations for Developers
239
+
240
+ 1. Use Cases:
241
+ - Ensure that your extensions or features align with the broader goals of the application.
242
+ - Understand that the OpenBB Platform is designed to be foundational; build in a way that complements and doesn't conflict with its core functionalities.
243
+
244
+ 2. Documentation:
245
+ - Provide clear and comprehensive documentation for any new feature or extension you develop.
246
+
247
+ 3. Code Quality:
248
+ - Adhere to the coding standards and conventions of the OpenBB Platform.
249
+ - Ensure your code is maintainable, well-organized, and commented where necessary.
250
+
251
+ 4. Testing:
252
+ - Thoroughly test any new feature or extension to ensure it works as expected.
253
+
254
+ 5. Performance:
255
+ - Ensure that your extensions or features do not adversely affect the performance of the OpenBB Platform.
256
+ - Optimize for scalability, especially if you anticipate high demand for your feature.
257
+
258
+ 6. Collaboration:
259
+ - Engage with the OpenBB community to gather feedback on your developments.
260
+
261
+ ### How to build OpenBB extensions?
262
+
263
+ We have a Cookiecutter template that will help you get started. It serves as a jumpstart for your extension development, so you can focus on the data and not on the boilerplate.
264
+
265
+ Please refer to the [Cookiecutter template](https://github.com/OpenBB-finance/openbb-cookiecutter) and follow the instructions there.
266
+
267
+ This document will walk you through the steps of adding a new extension to the OpenBB Platform.
268
+
269
+ The high level steps are:
270
+
271
+ - Generate the extension structure
272
+ - Install your dependencies
273
+ - Install your new package
274
+ - Use your extension (either from Python or the API interface)
275
+ - QA your extension
276
+ - Share your extension with the community
277
+
278
+ ### Building Extensions: Best Practices
279
+
280
+ 1. **Review Platform Dependencies**: Before adding any dependency, ensure it aligns with the Platform's existing dependencies.
281
+ 2. **Use Loose Versioning**: If possible, specify a range to maintain compatibility. E.g., `>=1.4,<1.5`.
282
+ 3. **Testing**: Test your extension with the Platform's core to avoid conflicts. Both unit and integration tests are recommended.
283
+ 4. **Document Dependencies**: Use `pyproject.toml` and `poetry.lock` for clear, up-to-date records.
284
+
285
+ ### How to add a new data point?
286
+
287
+ In this section, we'll be adding a new data point to the OpenBB Platform. We will add a new provider with an existing [standard data](core/openbb_core/provider/standard_models) model.
288
+
289
+ #### Identify which type of data you want to add
290
+
291
+ In this example, we'll be adding OHLC stock data that is used by the `obb.equity.price.historical` command.
292
+
293
+ Note that, if no command exists for your data, we need to add one under the right router.
294
+ Each router is categorized under different extensions (equity, currency, crypto, etc.).
295
+
296
+ #### Check if the standard model exists
297
+
298
+ Given the fact that there's already an endpoint for OHLCV stock data, we can check if the standard exists.
299
+
300
+ In this case, it's `EquityHistorical` which can be found in `/OpenBB/openbb_platform/core/openbb_core/provider/standard_models/equity_historical`.
301
+
302
+ If the standard model doesn't exist:
303
+
304
+ - you won't need to inherit from it in the next steps.
305
+ - all your provider query parameters will be under the `**kwargs` in the python interface.
306
+ - it might not work out-of-the box with other extensions that follow standardization e.g. the `charting` extension
307
+
308
+ ##### Create Query Parameters model
309
+
310
+ Query Parameters are the parameters that are passed to the API endpoint in order to make the request.
311
+
312
+ For the `EquityHistorical` example, this would look like the following:
313
+
314
+ ```python
315
+
316
+ class <ProviderName>EquityHistoricalQueryParams(EquityHistoricalQueryParams):
317
+ """<ProviderName> Equity Historical Query.
318
+
319
+ Source: https://www.<provider_name>.co/documentation/
320
+ """
321
+
322
+ # provider specific query parameters if any
323
+
324
+ ```
325
+
326
+ ##### Create Data Output model
327
+
328
+ The data output is the data that is returned by the API endpoint.
329
+ For the `EquityHistorical` example, this would look like the following:
330
+
331
+ ```python
332
+
333
+ class <ProviderName>EquityHistoricalData(EquityHistoricalData):
334
+ """<ProviderName> Equity Historical Data.
335
+
336
+ Source: https://www.<provider_name>.co/documentation/
337
+ """
338
+
339
+ # provider specific data output fields if any
340
+
341
+ ```
342
+
343
+ > Note that, since `EquityHistoricalData` inherits from pydantic's `BaseModel`, we can leverage validators to perform additional checks on the output model. A very good example of this, would be to transform a string date into a datetime object.
344
+
345
+ ##### Build the Fetcher
346
+
347
+ The `Fetcher` class is responsible for making the request to the API endpoint and providing the output.
348
+
349
+ It will receive the query parameters, and it will return the output while leveraging the pydantic model schemas.
350
+
351
+ For the `EquityHistorical` example, this would look like the following:
352
+
353
+ ```python
354
+ class <ProviderName>EquityHistoricalFetcher(
355
+ Fetcher[
356
+ <ProviderName>EquityHistoricalQueryParams,
357
+ List[<ProviderName>EquityHistoricalData],
358
+ ]
359
+ ):
360
+ """Transform the query, extract and transform the data."""
361
+
362
+ @staticmethod
363
+ def transform_query(params: Dict[str, Any]) -> <ProviderName>EquityHistoricalQueryParams:
364
+ """Transform the query parameters."""
365
+
366
+ return <ProviderName>EquityHistoricalQueryParams(**transformed_params)
367
+
368
+ @staticmethod
369
+ def extract_data(
370
+ query: <ProviderName>EquityHistoricalQueryParams,
371
+ credentials: Optional[Dict[str, str]],
372
+ **kwargs: Any,
373
+ ) -> dict:
374
+ """Return the raw data from the endpoint."""
375
+
376
+ obtained_data = my_request(query, credentials, **kwargs)
377
+
378
+ return obtained_data
379
+
380
+ @staticmethod
381
+ def transform_data(
382
+ query: <ProviderName>EquityHistoricalQueryParams,
383
+ data: dict,
384
+ **kwargs: Any,
385
+ ) -> List[<ProviderName>EquityHistoricalData]:
386
+ """Transform the data to the standard format."""
387
+
388
+ return [<ProviderName>EquityHistoricalData.model_validate(d) for d in data]
389
+ ```
390
+
391
+ > Make sure that you're following the TET pattern when building a `Fetcher` - **Transform, Extract, Transform**. See more on this [here](#the-tet-pattern).
392
+
393
+ By default the credentials declared on each `Provider` are required. This means that before a query is executed, we check that all the credentials are present and if not an exception is raised. If you want to make credentials optional on a given fetcher, even though they are declared on the `Provider`, you can add `require_credentials=False` to the `Fetcher` class. See the following example:
394
+
395
+ ```python
396
+ class <ProviderName>EquityHistoricalFetcher(
397
+ Fetcher[
398
+ <ProviderName>EquityHistoricalQueryParams,
399
+ List[<ProviderName>EquityHistoricalData],
400
+ ]
401
+ ):
402
+ """Transform the query, extract and transform the data."""
403
+
404
+ require_credentials = False
405
+
406
+ ...
407
+ ```
408
+
409
+ #### Make the provider visible
410
+
411
+ In order to make the new provider visible to the OpenBB Platform, you'll need to add it to the `__init__.py` file of the `providers/<provider_name>/openbb_<provider_name>/` folder.
412
+
413
+ ```python
414
+ """<Provider Name> Provider module."""
415
+ from openbb_core.provider.abstract.provider import Provider
416
+
417
+ from openbb_<provider_name>.models.equity_historical import <ProviderName>EquityHistoricalFetcher
418
+
419
+ <provider_name>_provider = Provider(
420
+ name="<provider_name>",
421
+ website="<URL to the provider website>",
422
+ description="Provider description goes here",
423
+ credentials=["api_key"],
424
+ fetcher_dict={
425
+ "EquityHistorical": <ProviderName>EquityHistoricalFetcher,
426
+ },
427
+ )
428
+ ```
429
+
430
+ If the provider does not require any credentials, you can remove that parameter. On the other hand, if it requires more than 2 items to authenticate, you can add a list of all the required items to the `credentials` list.
431
+
432
+ After running `pip install .` on `openbb_platform/providers/<provider_name>` your provider should be ready for usage, both from the Python interface and the API.
433
+
434
+ ### How to add custom data sources?
435
+
436
+ You will get your data either from a CSV file, local database or from an API endpoint.
437
+
438
+ If you don't want or don't need to partake in the data standardization framework, you have the option to add all the logic straight inside the router file. This is usually the case when you are returning custom data from your local CSV file, or similar. Keep in mind that we also serve the REST API and that you shouldn't send non-serializable objects as a response (e.g. a pandas dataframe).
439
+
440
+ Saying that, we highly recommend following the standardization framework, as it will make your life easier in the long run and unlock a set of features that are only available to standardized data.
441
+
442
+ When standardizing, all data is defined using two different pydantic models:
443
+
444
+ 1. Define the [query parameters](core/openbb_core/provider/abstract/query_params.py) model.
445
+ 2. Define the resulting [data schema](core/openbb_core/provider/abstract/data.py) model.
446
+
447
+ > The models can be entirely custom, or inherit from the OpenBB standardized models.
448
+ > They enforce a safe and consistent data structure, validation and type checking.
449
+
450
+ We call this the ***Know-Your-Data*** principle.
451
+
452
+ After you've defined both models, you'll need to define a `Fetcher` class which contains three methods:
453
+
454
+ 1. `transform_query` - transforms the query parameters to the format of the API endpoint.
455
+ 2. `extract_data` - makes the request to the API endpoint and returns the raw data.
456
+ 3. `transform_data` - transforms the raw data into the defined data model.
457
+
458
+ > Note that the `Fetcher` should inherit from the [`Fetcher`](core/openbb_core/provider/abstract/fetcher.py) class, which is a generic class that receives the query parameters and the data model as type parameters.
459
+
460
+ After finalizing your models, you need to make them visible to the Openbb Platform. This is done by adding the `Fetcher` to the `__init__.py` file of the `<your_package_name>/<your_module_name>` folder as part of the [`Provider`](core/openbb_core/provider/abstract/provider.py).
461
+
462
+ Any command, that uses the `Fetcher` class you've just defined, will be calling the `transform_query`, `extract_data` and `transform_data` methods under the hood in order to get the data and output it do the end user.
463
+
464
+ If you're not sure what's a command and why is it even using the `Fetcher` class, follow along!
465
+
466
+ #### OpenBB Platform commands
467
+
468
+ The OpenBB Platform will enable you to query and output your data in a very simple way.
469
+
470
+ > Any Platform endpoint will be available both from a Python interface and the API.
471
+
472
+ The command definition on the Platform follows [FastAPI](https://fastapi.tiangolo.com/) conventions, meaning that you'll be creating **endpoints**.
473
+
474
+ The Cookiecutter template generates for you a `router.py` file with a set of examples that you can follow, namely:
475
+
476
+ - Perform a simple `GET` and `POST` request - without worrying on any custom data definition.
477
+ - Using a custom data definition so you get your data the exact way you want it.
478
+
479
+ You can expect the following endpoint structure when using a `Fetcher` to serve the data:
480
+
481
+ ```python
482
+ @router.command(model="Example")
483
+ async def model_example( # create an async endpoint
484
+ cc: CommandContext,
485
+ provider_choices: ProviderChoices,
486
+ standard_params: StandardParams,
487
+ extra_params: ExtraParams,
488
+ ) -> OBBject:
489
+ """Example Data."""
490
+ return await OBBject.from_query(Query(**locals()))
491
+ ```
492
+
493
+ Let's break it down:
494
+
495
+ - `@router.command(...)` - this tells the OpenBB Platform that this is a command.
496
+ - `model="Example"` - this is the name of the `Fetcher` dictionary key that you've defined in the `__init__.py` file of the `<your_package_name>/<your_module_name>` folder.
497
+ - `cc: CommandContext` - this contains a set of user and system settings that is useful during the execution of the command - eg. api keys.
498
+ - `provider_choices: ProviderChoices` - all the providers that implement the `Example` `Fetcher`.
499
+ - `standard_params: StandardParams` - standardized parameters that are common to all providers that implement the `Example` `Fetcher`.
500
+ - `extra_params: ExtraParams` - it contains the provider specific arguments that are not standardized.
501
+
502
+ You only need to change the `model` parameter to the name of the `Fetcher` dictionary key and everything else will be handled by the OpenBB Platform.
503
+
504
+ ### Architectural considerations
505
+
506
+ #### Important classes
507
+
508
+ #### Import statements
509
+
510
+ ```python
511
+
512
+ # The `Data` class
513
+ from openbb_core.provider.abstract.data import Data
514
+
515
+ # The `QueryParams` class
516
+ from openbb_core.provider.abstract.query_params import QueryParams
517
+
518
+ # The `Fetcher` class
519
+ from openbb_core.provider.abstract.fetcher import Fetcher
520
+
521
+ # The `OBBject` class
522
+ from openbb_core.app.model.obbject import OBBject
523
+
524
+ # The `Router` class
525
+ from openbb_core.app.router import Router
526
+
527
+ ```
528
+
529
+ #### The TET pattern
530
+
531
+ The TET pattern is a pattern that we use to build the `Fetcher` classes. It stands for **Transform, Extract, Transform**.
532
+ As the OpenBB Platform has its own standardization framework and the data fetcher are a very important part of it, we need to ensure that the data is transformed and extracted in a consistent way, to help us do that, we came up with the **TET** pattern, which helps us build and ship faster as we have a clear structure on how to build the `Fetcher` classes.
533
+
534
+ 1. Transform - `transform_query(params: Dict[str, Any])`: transforms the query parameters. Given a `params` dictionary this method should return the transformed query parameters as a [`QueryParams`](core/openbb_core/provider/abstract/query_params.py) child so that we can leverage the pydantic model schemas and validation into the next step. This might also be the place do perform some transformations on any given parameter, i.e., if you want to transform an empty date into a `datetime.now().date()`.
535
+ 2. Extract - `extract_data(query: ExampleQueryParams,credentials: Optional[Dict[str, str]],**kwargs: Any,) -> Dict`: makes the request to the API endpoint and returns the raw data. Given the transformed query parameters, the credentials and any other extra arguments, this method should return the raw data as a dictionary.
536
+ 3. Transform - `transform_data(query: ExampleQueryParams, data: Dict, **kwargs: Any) -> List[ExampleHistoricalData]`: transforms the raw data into the defined data model. Given the transformed query parameters (might be useful for some filtering), the raw data and any other extra arguments, this method should return the transformed data as a list of [`Data`](core/openbb_core/provider/abstract/data.py) children.
537
+
538
+ #### Errors
539
+
540
+ To ensure a consistent error handling behavior our API relies on the convention below.
541
+
542
+ | Status code | Exception | Detail | Description |
543
+ | -------- | ------- | ------- | ------- |
544
+ | 400 | `OpenBBError` or child of `OpenBBError` | Custom message. | Use this to explicitly raise custom exceptions, like `EmptyDataError`. |
545
+ | 422 | `ValidationError` | `Pydantic` errors dict message. | Automatically raised to inform the user about query validation errors. ValidationErrors outside of the query are treated with status code 500 by default. |
546
+ | 500 | Any exception not covered above, eg `ValueError`, `ZeroDivisionError` | Unexpected error. | Unexpected exceptions, most likely a bug. |
547
+
548
+ #### Data processing commands
549
+
550
+ The data processing commands are commands that are used to process the data that may or may not come from the OpenBB Platform.
551
+ In order to create a data processing framework general enough to be used by any extension, we've created a special abstract class called [`Data`](core/openbb_core/provider/abstract/data.py) which **all** standardized (and consequently its child classes) will inherit from.
552
+
553
+ Why is this important?
554
+ So that we can ensure that all `OBBject.results` will share a common ground on which we can apply out-of-the-box data processing commands, such as the `ta`, `qa` or the `econometrics` menus.
555
+
556
+ But what's really the `Data` class?
557
+ It's a pydantic model that inherits from the `BaseModel` and can contain any given number of extra fields. In practice, it looks as follows:
558
+
559
+ ```python
560
+
561
+ >>> res = obb.equity.price.historical("AAPL")
562
+ >>> res.results[0]
563
+
564
+ AVEquityHistoricalData(date=2023-11-03 00:00:00, open=174.24, high=176.82, low=173.35, close=176.65, volume=79829246.0, vwap=None, adj_close=None, dividend_amount=None, split_coefficient=None)
565
+
566
+ ```
567
+
568
+ > The `AVEquityHistoricalData` class, is a child class of the `Data` class.
569
+
570
+ Note how we've indexed to get only the first element of the `results` list (which represents a single row, if we want to think about it as a tabular output). This simply means that we are getting a `List` of `AVEquityHistoricalData` from the `obb.equity.price.historical` command. Or, we can also say that that's equivalent to `List[Data]`!
571
+
572
+ This is very powerful, as we can now apply any data processing command to the `results` list, without worrying about the underlying data structure.
573
+ That's why, on data processing commands (such as the `ta` menu) we will find on its function signature the following:
574
+
575
+ ```python
576
+
577
+ def ema(
578
+ self,
579
+ data: Union[List[Data], pandas.DataFrame],
580
+ target: str = "close",
581
+ index: str = "date",
582
+ length: int = 50,
583
+ offset: int = 0,
584
+ chart: bool = False,
585
+ ) -> OBBject[List[Data]]:
586
+
587
+ ...
588
+
589
+ ```
590
+
591
+ > Note that `data` can actually be a different type, but we'll focus on the `List[Data]` case for now.
592
+
593
+ Does that mean that I can only use the data processing commands if I instantiate a class that inherits from `Data`?
594
+ Not at all! Consider the following example:
595
+
596
+ ```python
597
+
598
+ >>> from openbb_core.provider.abstract.data import Data
599
+ >>> my_data_item_1 = {"open": 1, "high": 2, "low": 3, "close": 4, "volume": 5, "date": "2020-01-01"}
600
+ >>> my_data_item_1_as_data = Data.model_validate(my_data_item_1)
601
+ >>> my_data_item_1_as_data
602
+
603
+ Data(open=1, high=2, low=3, close=4, volume=5, date=2020-01-01)
604
+
605
+ ```
606
+
607
+ This means that the `Data` class is clever enough to understand that you are passing a dictionary and it will try to validate it for you.
608
+ In other words, if you're using data that doesn't come from the OpenBBPlatform, you only need to ensure it's parsable by the `Data` class and you'll be able to use the data processing commands.
609
+ In other words, imagine you have a dataframe that you want to use with the `ta` menu. You can do the following:
610
+
611
+ ```python
612
+
613
+ >>> res = obb.equity.price.historical("AAPL")
614
+ >>> my_df = res.to_dataframe() # yes, you can convert your OBBject.results into a dataframe out-of-the-box!
615
+ >>> my_records = df.to_dict(orient="records")
616
+
617
+ >>> obb.ta.ema(data=my_record)
618
+
619
+ OBBject
620
+
621
+ results: [{'close': 77.62, 'close_EMA_50': None}, {'close': 80.25, 'close_EMA_50': ... # this is a `List[Data]` yet again
622
+
623
+ ```
624
+
625
+ > Note that that for this example we've used the `OBBject.to_dataframe()` method to have an example dataframe, but it could be any other dataframe that you have.
626
+
627
+ ##### Python Interface
628
+
629
+ When using the OpenBB Platform on a Python Interface, docstrings and type hints are your best friends as they provides plenty of context on how to use the commands.
630
+ Looking at an example on the `ta` menu:
631
+
632
+ ```python
633
+
634
+ def ema(
635
+ self,
636
+ data: Union[List[Data], pandas.DataFrame],
637
+ target: str = "close",
638
+ index: str = "date",
639
+ length: int = 50,
640
+ offset: int = 0,
641
+ chart: bool = False,
642
+ ) -> OBBject[List[Data]]:
643
+
644
+ ...
645
+
646
+ ```
647
+
648
+ We can easily deduct that the `ema` command accept data in the formats of `List[Data]` or `pandas.DataFrame`.
649
+
650
+ > Note that other types might be added in the future.
651
+
652
+ ##### API Interface
653
+
654
+ When using the OpenBB Platform on a API Interface, the types are a bit more limited than on the Python one, as, for example, we can't use `pandas.DataFrame` as a type. However the same principles apply for what `Data` means, i.e., any given data processing command, which are characterized as POST endpoints on the API, will accept data as a list of records on the **request body**, i.e.:
655
+
656
+ ```json
657
+
658
+ [
659
+ {
660
+ "open": 80,
661
+ "high": 80.69,
662
+ "low": 77.37,
663
+ "close": 77.62,
664
+ "volume": 2487300
665
+ }
666
+ ...
667
+ ]
668
+
669
+ ```
670
+
671
+ ## Contributor Guidelines
672
+
673
+ The Contributor Guidelines are intended to be a continuation of the [Developer Guidelines](#developer-guidelines). They are not a replacement, but rather an expansion, focusing specifically on those who seek to directly enhance the OpenBB Platform's codebase. It's crucial for Contributors to be familiar with both sets of guidelines to ensure a harmonious and productive engagement with the OpenBB Platform.
674
+
675
+ There are many ways to contribute to the OpenBB Platform. You can add a [new data point](#getting_started-add-a-new-data-point), add a [new command](#openbb-platform-commands), add a [new visualization](/openbb_platform/extensions/charting/README.md), add a [new extension](#getting_started-build-openbb-extensions), fix a bug, improve or create documentation, etc.
676
+
677
+ ### Expectations for Contributors
678
+
679
+ 1. Use Cases:
680
+ - Ensure that your contributions directly enhance the OpenBB Platform's functionality or extension ecosystem.
681
+
682
+ 2. Documentation:
683
+ - All code contributions should come with relevant documentation, including the purpose of the contribution, how it works, and any changes it makes to existing functionalities.
684
+ - Update any existing documentation if your contribution alters the behavior of the OpenBB Platform.
685
+
686
+ 3. Code Quality:
687
+ - Your code should adhere strictly to the OpenBB Platform's coding standards and conventions.
688
+ - Ensure clarity, maintainability, and proper organization in your code.
689
+
690
+ 4. Testing:
691
+ - All contributions must be thoroughly tested to avoid introducing bugs to the OpenBB Platform.
692
+ - Contributions should include relevant automated tests (unit and integration), and any new feature should come with its test cases.
693
+
694
+ 5. Performance:
695
+ - Your contributions should be optimized for performance and should not degrade the overall efficiency of the OpenBB Platform.
696
+ - Address any potential bottlenecks and ensure scalability.
697
+
698
+ 6. Collaboration:
699
+ - Engage actively with the OpenBB development team to ensure that your contributions align with the platform's roadmap and standards.
700
+ - Welcome feedback and be open to making revisions based on reviews and suggestions from the community.
701
+
702
+ ### Quality Assurance
703
+
704
+ We are strong believers in the Quality Assurance (QA) process and we want to make sure that all the extensions that are added to the OpenBB Platform are of high quality. To ensure this, we have a set of QA tools that you can use to test your extension.
705
+
706
+ Primarily, we have tools that semi-automate the creation of unit and integration tests.
707
+
708
+ > The QA tools are still in development and we are constantly improving them.
709
+
710
+ #### Unit tests
711
+
712
+ Each `Fetcher` comes equipped with a `test` method that will ensure that it is implemented correctly and that it is returning the expected data. It also ensures that all types are correct and that the data is valid.
713
+
714
+ To create unit tests for your Fetchers, you can run the following command:
715
+
716
+ ```bash
717
+ python openbb_platform/providers/tests/utils/unit_tests_generator.py
718
+ ```
719
+
720
+ > Note that you should be running this file from the root of the repository.
721
+ > Note that the `tests` folder must exist in order to generate the tests.
722
+
723
+ The automatic unit test generation will add unit tests for all the fetchers available in a given provider.
724
+
725
+ To record the unit tests, you can run the following command:
726
+
727
+ ```bash
728
+ pytest <path_to_the_unit_test_file> --record=all
729
+ ```
730
+
731
+ > Note that sometimes manual intervention is needed. For example, adjusting out-of-top level imports or adding specific arguments for a given fetcher.
732
+
733
+ #### Integration tests
734
+
735
+ The integration tests are a bit more complex than the unit tests, as we want to test both the Python interface and the API interface. For this, we have two scripts that will help you generate the integration tests.
736
+
737
+ To generate the integration tests for the Python interface, you can run the following command:
738
+
739
+ ```bash
740
+ python openbb_platform/extensions/tests/utils/integration_tests_generator.py
741
+ ```
742
+
743
+ To generate the integration tests for the API interface, you can run the following command:
744
+
745
+ ```bash
746
+ python openbb_platform/extensions/tests/utils/integration_tests_api_generator.py
747
+ ```
748
+
749
+ When testing the API interface, you'll need to run the OpenBB Platform locally before running the tests. To do so, you can run the following command:
750
+
751
+ ```bash
752
+ uvicorn openbb_platform.core.openbb_core.api.rest_api:app --host 0.0.0.0 --port 8000 --reload
753
+ ```
754
+
755
+ These automated tests are a great way to reduce the amount of code you need to write, but they are not a replacement for manual testing and might require tweaking. That's why we have unit tests that test the generated integration tests to ensure they cover all providers and parameters.
756
+
757
+ To run the tests we can do:
758
+
759
+ - Unit tests only:
760
+
761
+ ```bash
762
+ pytest openbb_platform -m "not integration"
763
+ ```
764
+
765
+ - Integration tests only:
766
+
767
+ ```bash
768
+ pytest openbb_platform -m integration
769
+ ```
770
+
771
+ - Both integration and unit tests:
772
+
773
+ ```bash
774
+ pytest openbb_platform
775
+ ```
776
+
777
+ #### Import time
778
+
779
+ We aim to have a short import time for the package. To measure that we use `tuna`.
780
+
781
+ - <https://pypi.org/project/tuna/>
782
+
783
+ To visualize the import time breakdown by module and find potential bottlenecks, run the
784
+ following commands from `openbb_platform` directory:
785
+
786
+ ```bash
787
+ pip install tuna
788
+ python -X importtime openbb/__init__.py 2> import.log
789
+ tuna import.log
790
+ ```
791
+
792
+ ### Sharing your extension
793
+
794
+ We encourage you to share your extension with the community. You can do that by publishing it to PyPI.
795
+
796
+ #### Publish your extension to PyPI
797
+
798
+ To publish your extension to PyPI, you'll need to have a PyPI account and a PyPI API token.
799
+
800
+ ##### Setup
801
+
802
+ Create an account and get an API token from <https://pypi.org/manage/account/token/>
803
+ Store the token with
804
+
805
+ ```bash
806
+ poetry config pypi-token.pypi pypi-YYYYYYYY
807
+ ```
808
+
809
+ ##### Release
810
+
811
+ `cd` into the directory where your extension `pyproject.toml` lives and make sure that the `pyproject.toml` specifies the version tag you want to release and run.
812
+
813
+ ```bash
814
+ poetry build
815
+ ```
816
+
817
+ This will create a `/dist` folder in the directory, which will contain the `.whl` and `tar.gz` files matching the version to release.
818
+
819
+ If you want to test your package locally you can do it with
820
+
821
+ ```bash
822
+ pip install dist/openbb_[FILE_NAME].whl
823
+ ```
824
+
825
+ ##### Publish
826
+
827
+ To publish your package to PyPI run:
828
+
829
+ ```bash
830
+ poetry publish
831
+ ```
832
+
833
+ Now, you can pip install your package from PyPI with:
834
+
835
+ ```bash
836
+ pip install openbb-some_ext
837
+ ```
838
+
839
+ ### Manage extensions
840
+
841
+ To install an extension hosted on PyPI, use the `pip install <extension>` command.
842
+
843
+ To install an extension that is developed locally, ensure that it contains a `pyproject.toml` file and then use the `pip install <extension>` command.
844
+
845
+ > To install the extension in editable mode using pip, add the `-e` argument.
846
+
847
+ Alternatively, for local extensions, you can add this line in the `LOCAL_DEPS` variable in `dev_install.py` file:
848
+
849
+ ```toml
850
+ # If this is a community dependency, add this under "Community dependencies",
851
+ # with additional argument optional = true
852
+ openbb-extension = { path = "<relative-path-to-the-extension>", develop = true }
853
+ ```
854
+
855
+ Now you can use the `python dev_install.py [-e]` command to install the local extension.
856
+
857
+ #### Add an extension as a dependency
858
+
859
+ To add the `openbb-qa` extension as a dependency, you'll need to add it to the `pyproject.toml` file:
860
+
861
+ ```toml
862
+ [tool.poetry.dependencies]
863
+ openbb-qa = "^0.0.0a2"
864
+ ```
865
+
866
+ Then you can follow the same process as above to install the extension.
867
+
868
+ ### Write code and commit
869
+
870
+ #### How to create a PR?
871
+
872
+ To create a PR to the OpenBB Platform, you'll need to fork the repository and create a new branch.
873
+
874
+ 1. Create your Feature Branch, e.g. `git checkout -b feature/AmazingFeature`
875
+ 2. Check the files you have touched using `git status`
876
+ 3. Stage the files you want to commit, e.g.
877
+ `git add openbb_platform/platform/core/openbb_core/app/constants.py`.
878
+ Note: **DON'T** add any files with personal information.
879
+ 4. Write a concise commit message under 50 characters, e.g. `git commit -m "meaningful commit message"`. If your PR
880
+ solves an issue raised by a user, you may specify such an issue by adding #ISSUE_NUMBER to the commit message, so that
881
+ these get linked. Note: If you installed pre-commit hooks and one of the formatters re-formats your code, you'll need
882
+ to go back to step 3 to add these.
883
+
884
+ ##### Branch Naming Conventions
885
+
886
+ The accepted branch naming conventions are:
887
+
888
+ - `feature/feature-name`
889
+ - `hotfix/hotfix-name`
890
+
891
+ These branches can only have PRs pointing to the `develop` branch.
openbb_platform/README.md ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # OpenBB Platform
2
+
3
+ [![Downloads](https://static.pepy.tech/badge/openbb)](https://pepy.tech/project/openbb)
4
+ [![LatestRelease](https://badge.fury.io/py/openbb.svg)](https://github.com/OpenBB-finance/OpenBB)
5
+
6
+ | OpenBB is committed to build the future of investment research by focusing on an open source infrastructure accessible to everyone, everywhere. |
7
+ | :---------------------------------------------------------------------------------------------------------------------------------------------: |
8
+ | ![OpenBBLogo](https://user-images.githubusercontent.com/25267873/218899768-1f0964b8-326c-4f35-af6f-ea0946ac970b.png) |
9
+ | Check our website at [openbb.co](www.openbb.co) |
10
+
11
+ ## Overview
12
+
13
+ The OpenBB Platform provides a convenient way to access raw financial data from multiple data providers. The package comes with a ready to use REST API - this allows developers from any language to easily create applications on top of OpenBB Platform.
14
+
15
+ Please find the complete documentation at [docs.openbb.co](https://docs.openbb.co/platform).
16
+
17
+ ## Installation
18
+
19
+ The command below provides access to the core functionalities behind the OpenBB Platform.
20
+
21
+ ```bash
22
+ pip install openbb
23
+ ```
24
+
25
+ This will install the following data providers:
26
+
27
+ These packages are what will be installed when `pip install openbb` is run
28
+
29
+ | Extension Name | Description | Installation Command | Minimum Subscription Type Required |
30
+ |----------------|-------------|----------------------|------------------------------------|
31
+ | openbb-benzinga | [Benzinga](https://www.benzinga.com/apis/en-ca/) data connector | pip install openbb-benzinga | Paid |
32
+ | openbb-bls | [Bureau of Labor Statistics](https://www.bls.gov/developers/home.htm) data connector | pip install openbb-bls | Free |
33
+ | openbb-cftc | [Commodity Futures Trading Commission](https://publicreporting.cftc.gov/stories/s/r4w3-av2u) data connector | pip install openbb-cftc | Free |
34
+ | openbb-econdb | [EconDB](https://econdb.com) data connector | pip install openbb-econdb | None |
35
+ | openbb-imf | [IMF](https://data.imf.org) data connector | pip install openbb-imf | None |
36
+ | openbb-fmp | [FMP](https://site.financialmodelingprep.com/developer/) data connector | pip install openbb-fmp | Free |
37
+ | openbb-fred | [FRED](https://fred.stlouisfed.org/) data connector | pip install openbb-fred | Free |
38
+ | openbb-intrinio | [Intrinio](https://intrinio.com/pricing) data connector | pip install openbb-intrinio | Paid |
39
+ | openbb-oecd | [OECD](https://data.oecd.org/) data connector | pip install openbb-oecd | Free |
40
+ | openbb-polygon | [Polygon](https://polygon.io/) data connector | pip install openbb-polygon | Free |
41
+ | openbb-sec | [SEC](https://www.sec.gov/edgar/sec-api-documentation) data connector | pip install openbb-sec | None |
42
+ | openbb-tiingo | [Tiingo](https://www.tiingo.com/about/pricing) data connector | pip install openbb-tiingo | Free |
43
+ | openbb-tradingeconomics | [TradingEconomics](https://tradingeconomics.com/api) data connector | pip install openbb-tradingeconomics | Paid |
44
+ | openbb-yfinance | [Yahoo Finance](https://finance.yahoo.com/) data connector | pip install openbb-yfinance | None |
45
+
46
+ ### Community Providers
47
+
48
+ These packages are not installed when `pip install openbb` is run. They are available for installation separately or by running `pip install openbb[all]`
49
+
50
+ | Extension Name | Description | Installation Command | Minimum Subscription Type Required |
51
+ |----------------|-------------|----------------------|------------------------------------|
52
+ | openbb-alpha-vantage | [Alpha Vantage](https://www.alphavantage.co/) data connector | pip install openbb-alpha-vantage | Free |
53
+ | openbb-biztoc | [Biztoc](https://api.biztoc.com/#biztoc-default) News data connector | pip install openbb-biztoc | Free |
54
+ | openbb-cboe | [Cboe](https://www.cboe.com/delayed_quotes/) data connector | pip install openbb-cboe | None |
55
+ | openbb-ecb | [ECB](https://data.ecb.europa.eu/) data connector | pip install openbb-ecb | None |
56
+ | openbb-federal-reserve | [Federal Reserve](https://www.federalreserve.gov/) data connector | pip install openbb-federal-reserve | None |
57
+ | openbb-finra | [FINRA](https://www.finra.org/finra-data) data connector | pip install openbb-finra | None / Free |
58
+ | openbb-finviz | [Finviz](https://finviz.com) data connector | pip install openbb-finviz | None |
59
+ | openbb-government-us | [US Government](https://data.gov) data connector | pip install openbb-us-government | None |
60
+ | openbb-nasdaq | [Nasdaq Data Link](https://data.nasdaq.com/) connector | pip install openbb-nasdaq | None / Free |
61
+ | openbb-seeking-alpha | [Seeking Alpha](https://seekingalpha.com/) data connector | pip install openbb-seeking-alpha | None |
62
+ | openbb-stockgrid | [Stockgrid](https://stockgrid.io) data connector | pip install openbb-stockgrid | None |
63
+ | openbb-tmx | [TMX](https://money.tmx.com) data connector | pip install openbb-tmx | None |
64
+ | openbb-tradier | [Tradier](https://tradier.com) data connector | pip install openbb-tradier | None |
65
+ | openbb-wsj | [Wall Street Journal](https://www.wsj.com/) data connector | pip install openbb-wsj | None |
66
+ To install extensions that expand the core functionalities specify the extension name or use `all` to install all.
67
+
68
+ ```bash
69
+ # Install a single extension, e.g. openbb-charting and yahoo finance
70
+ pip install openbb[charting]
71
+ pip install openbb-yfinance
72
+ ```
73
+
74
+ Alternatively, you can install all extensions at once.
75
+
76
+ ```bash
77
+ pip install openbb[all]
78
+ ```
79
+
80
+ > Note: These instruction are specific to v4. For installation instructions and documentation for v3 go to our [website](https://docs.openbb.co/sdk).
81
+
82
+ ## Python
83
+
84
+ ```python
85
+ >>> from openbb import obb
86
+ >>> output = obb.equity.price.historical("AAPL")
87
+ >>> df = output.to_dataframe()
88
+ >>> df.head()
89
+ open high low ... change_percent label change_over_time
90
+ date ...
91
+ 2022-09-19 149.31 154.56 149.10 ... 3.46000 September 19, 22 0.034600
92
+ 2022-09-20 153.40 158.08 153.08 ... 2.28000 September 20, 22 0.022800
93
+ 2022-09-21 157.34 158.74 153.60 ... -2.30000 September 21, 22 -0.023000
94
+ 2022-09-22 152.38 154.47 150.91 ... 0.23625 September 22, 22 0.002363
95
+ 2022-09-23 151.19 151.47 148.56 ... -0.50268 September 23, 22 -0.005027
96
+
97
+ [5 rows x 12 columns]
98
+ ```
99
+
100
+ ## API keys
101
+
102
+ To fully leverage the OpenBB Platform you need to get some API keys to connect with data providers. Here are the 3 options on where to set them:
103
+
104
+ 1. OpenBB Hub
105
+ 2. Runtime
106
+ 3. Local file
107
+
108
+ ### 1. OpenBB Hub
109
+
110
+ Set your keys at [OpenBB Hub](https://my.openbb.co/app/platform/credentials) and get your personal access token from <https://my.openbb.co/app/platform/pat> to connect with your account.
111
+
112
+ ```python
113
+ >>> from openbb import obb
114
+ >>> openbb.account.login(pat="OPENBB_PAT")
115
+
116
+ >>> # Persist changes in OpenBB Hub
117
+ >>> obb.account.save()
118
+ ```
119
+
120
+ ### 2. Runtime
121
+
122
+ ```python
123
+ >>> from openbb import obb
124
+ >>> obb.user.credentials.fmp_api_key = "REPLACE_ME"
125
+ >>> obb.user.credentials.polygon_api_key = "REPLACE_ME"
126
+
127
+ >>> # Persist changes in ~/.openbb_platform/user_settings.json
128
+ >>> obb.account.save()
129
+ ```
130
+
131
+ ### 3. Local file
132
+
133
+ You can specify the keys directly in the `~/.openbb_platform/user_settings.json` file.
134
+
135
+ Populate this file with the following template and replace the values with your keys:
136
+
137
+ ```json
138
+ {
139
+ "credentials": {
140
+ "fmp_api_key": "REPLACE_ME",
141
+ "polygon_api_key": "REPLACE_ME",
142
+ "benzinga_api_key": "REPLACE_ME",
143
+ "fred_api_key": "REPLACE_ME"
144
+ }
145
+ }
146
+ ```
147
+
148
+ ## REST API
149
+
150
+ The OpenBB Platform comes with a ready to use REST API built with FastAPI. Start the application using this command:
151
+
152
+ ```bash
153
+ uvicorn openbb_core.api.rest_api:app --host 0.0.0.0 --port 8000 --reload
154
+ ```
155
+
156
+ API documentation is found under "/docs", from the root of the server address, and is viewable in any browser supporting HTTP over localhost, such as Chrome.
157
+
158
+ Check `openbb-core` [README](https://pypi.org/project/openbb-core/) for additional info.
159
+
160
+ ## Install for development
161
+
162
+ To develop the OpenBB Platform you need to have the following:
163
+
164
+ - Git
165
+ - Python 3.9 or higher
166
+ - Virtual Environment with `poetry` installed
167
+ - To install these packages activate your virtual environment and run `pip install poetry toml`
168
+
169
+ How to install the platform in editable mode?
170
+
171
+ 1. Activate your virtual environment
172
+ 1. Navigate into the `openbb_platform` folder
173
+ 1. Run `python dev_install.py` to install the packages in editable mode
openbb_platform/dev_install.py ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Install for development script."""
2
+
3
+ # flake8: noqa: S603
4
+
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ from tomlkit import dumps, load, loads
10
+
11
+ PLATFORM_PATH = Path(__file__).parent.resolve()
12
+ LOCK = PLATFORM_PATH / "poetry.lock"
13
+ PYPROJECT = PLATFORM_PATH / "pyproject.toml"
14
+ CLI_PATH = Path(__file__).parent.parent.resolve() / "cli"
15
+ CLI_PYPROJECT = CLI_PATH / "pyproject.toml"
16
+ CLI_LOCK = CLI_PATH / "poetry.lock"
17
+
18
+ LOCAL_DEPS = """
19
+ [tool.poetry.dependencies]
20
+ python = ">=3.9.21,<3.13"
21
+ openbb-devtools = { path = "./extensions/devtools", develop = true, markers = "python_version >= '3.10'" }
22
+ openbb-core = { path = "./core", develop = true }
23
+ openbb-platform-api = { path = "./extensions/platform_api", develop = true }
24
+
25
+ openbb-benzinga = { path = "./providers/benzinga", develop = true }
26
+ openbb-bls = { path = "./providers/bls", develop = true }
27
+ openbb-cftc = { path = "./providers/cftc", develop = true }
28
+ openbb-econdb = { path = "./providers/econdb", develop = true }
29
+ openbb-federal-reserve = { path = "./providers/federal_reserve", develop = true }
30
+ openbb-fmp = { path = "./providers/fmp", develop = true }
31
+ openbb-fred = { path = "./providers/fred", develop = true }
32
+ openbb-imf = { path = "./providers/imf", develop = true }
33
+ openbb-intrinio = { path = "./providers/intrinio", develop = true }
34
+ openbb-oecd = { path = "./providers/oecd", develop = true }
35
+ openbb-polygon = { path = "./providers/polygon", develop = true }
36
+ openbb-sec = { path = "./providers/sec", develop = true }
37
+ openbb-tiingo = { path = "./providers/tiingo", develop = true }
38
+ openbb-tradingeconomics = { path = "./providers/tradingeconomics", develop = true }
39
+ openbb-us-eia = { path = "./providers/eia", develop = true }
40
+ openbb-yfinance = { path = "./providers/yfinance", develop = true }
41
+
42
+ openbb-commodity = { path = "./extensions/commodity", develop = true }
43
+ openbb-crypto = { path = "./extensions/crypto", develop = true }
44
+ openbb-currency = { path = "./extensions/currency", develop = true }
45
+ openbb-derivatives = { path = "./extensions/derivatives", develop = true }
46
+ openbb-economy = { path = "./extensions/economy", develop = true }
47
+ openbb-equity = { path = "./extensions/equity", develop = true }
48
+ openbb-etf = { path = "./extensions/etf", develop = true }
49
+ openbb-fixedincome = { path = "./extensions/fixedincome", develop = true }
50
+ openbb-index = { path = "./extensions/index", develop = true }
51
+ openbb-news = { path = "./extensions/news", develop = true }
52
+ openbb-regulators = { path = "./extensions/regulators", develop = true }
53
+
54
+ # Community dependencies
55
+ openbb-alpha-vantage = { path = "./providers/alpha_vantage", optional = true, develop = true }
56
+ openbb-biztoc = { path = "./providers/biztoc", optional = true, develop = true }
57
+ openbb-cboe = { path = "./providers/cboe", optional = true, develop = true }
58
+ openbb-deribit = { path = "./providers/deribit", optional = true, develop = true }
59
+ openbb-ecb = { path = "./providers/ecb", optional = true, develop = true }
60
+ openbb-finra = { path = "./providers/finra", optional = true, develop = true }
61
+ openbb-finviz = { path = "./providers/finviz", optional = true, develop = true }
62
+ openbb-government-us = { path = "./providers/government_us", optional = true, develop = true }
63
+ openbb-multpl = { path = "./providers/multpl", optional = true, develop = true }
64
+ openbb-nasdaq = { path = "./providers/nasdaq", optional = true, develop = true }
65
+ openbb-seeking-alpha = { path = "./providers/seeking_alpha", optional = true, develop = true }
66
+ openbb-stockgrid = { path = "./providers/stockgrid" , optional = true, develop = true }
67
+ openbb_tmx = { path = "./providers/tmx", optional = true, develop = true }
68
+ openbb_tradier = { path = "./providers/tradier", optional = true, develop = true }
69
+ openbb-wsj = { path = "./providers/wsj", optional = true, develop = true }
70
+
71
+ openbb-charting = { path = "./obbject_extensions/charting", optional = true, develop = true }
72
+ openbb-econometrics = { path = "./extensions/econometrics", optional = true, develop = true }
73
+ openbb-quantitative = { path = "./extensions/quantitative", optional = true, develop = true }
74
+ openbb-technical = { path = "./extensions/technical", optional = true, develop = true }
75
+ """
76
+
77
+
78
+ def extract_dependencies(local_dep_path, dev: bool = False):
79
+ """Extract development dependencies from a given package's pyproject.toml."""
80
+ package_pyproject_path = PLATFORM_PATH / local_dep_path
81
+ if package_pyproject_path.exists():
82
+ with open(package_pyproject_path / "pyproject.toml") as f:
83
+ package_pyproject_toml = load(f)
84
+ if dev:
85
+ return (
86
+ package_pyproject_toml.get("tool", {})
87
+ .get("poetry", {})
88
+ .get("group", {})
89
+ .get("dev", {})
90
+ .get("dependencies", {})
91
+ )
92
+ return (
93
+ package_pyproject_toml.get("tool", {})
94
+ .get("poetry", {})
95
+ .get("dependencies", {})
96
+ )
97
+ return {}
98
+
99
+
100
+ def get_all_dev_dependencies():
101
+ """Aggregate development dependencies from all local packages."""
102
+ all_dev_dependencies = {}
103
+ local_deps = loads(LOCAL_DEPS).get("tool", {}).get("poetry", {})["dependencies"]
104
+ for _, package_info in local_deps.items():
105
+ if "path" in package_info:
106
+ dev_deps = extract_dependencies(Path(package_info["path"]), dev=True)
107
+ all_dev_dependencies.update(dev_deps)
108
+ return all_dev_dependencies
109
+
110
+
111
+ def install_platform_local(_extras: bool = False):
112
+ """Install the Platform locally for development purposes."""
113
+ original_lock = LOCK.read_text()
114
+ original_pyproject = PYPROJECT.read_text()
115
+
116
+ local_deps = loads(LOCAL_DEPS).get("tool", {}).get("poetry", {})["dependencies"]
117
+ with open(PYPROJECT) as f:
118
+ pyproject_toml = load(f)
119
+ pyproject_toml.get("tool", {}).get("poetry", {}).get("dependencies", {}).update(
120
+ local_deps
121
+ )
122
+
123
+ # Extract and add devtools dependencies manually if Python version is 3.9
124
+ if sys.version_info[:2] == (3, 9):
125
+ devtools_deps = extract_dependencies(Path("./extensions/devtools"), dev=False)
126
+ devtools_deps.remove("python")
127
+ pyproject_toml.get("tool", {}).get("poetry", {}).get("dependencies", {}).update(
128
+ devtools_deps
129
+ )
130
+
131
+ if _extras:
132
+ dev_dependencies = get_all_dev_dependencies()
133
+ pyproject_toml.get("tool", {}).get("poetry", {}).setdefault(
134
+ "group", {}
135
+ ).setdefault("dev", {}).setdefault("dependencies", {})
136
+ pyproject_toml.get("tool", {}).get("poetry", {})["group"]["dev"][
137
+ "dependencies"
138
+ ].update(dev_dependencies)
139
+
140
+ TEMP_PYPROJECT = dumps(pyproject_toml)
141
+
142
+ try:
143
+ with open(PYPROJECT, "w", encoding="utf-8", newline="\n") as f:
144
+ f.write(TEMP_PYPROJECT)
145
+
146
+ CMD = [sys.executable, "-m", "poetry"]
147
+ extras_args = ["-E", "all"] if _extras else []
148
+
149
+ subprocess.run(
150
+ CMD + ["lock"],
151
+ cwd=PLATFORM_PATH,
152
+ check=True,
153
+ )
154
+ subprocess.run(
155
+ CMD + ["install"] + extras_args,
156
+ cwd=PLATFORM_PATH,
157
+ check=True,
158
+ )
159
+
160
+ except (Exception, KeyboardInterrupt) as e:
161
+ print(e) # noqa: T201
162
+ print("Restoring pyproject.toml and poetry.lock") # noqa: T201
163
+
164
+ finally:
165
+ # Revert pyproject.toml and poetry.lock to their original state.
166
+ with open(PYPROJECT, "w", encoding="utf-8", newline="\n") as f:
167
+ f.write(original_pyproject)
168
+
169
+ with open(LOCK, "w", encoding="utf-8", newline="\n") as f:
170
+ f.write(original_lock)
171
+
172
+
173
+ def install_platform_cli():
174
+ """Install the CLI locally for development purposes."""
175
+ original_lock = CLI_LOCK.read_text()
176
+ original_pyproject = CLI_PYPROJECT.read_text()
177
+
178
+ with open(CLI_PYPROJECT) as f:
179
+ pyproject_toml = load(f)
180
+
181
+ # remove "openbb" from dependencies
182
+ pyproject_toml.get("tool", {}).get("poetry", {}).get("dependencies", {}).pop(
183
+ "openbb", None
184
+ )
185
+
186
+ TEMP_PYPROJECT = dumps(pyproject_toml)
187
+
188
+ try:
189
+ with open(CLI_PYPROJECT, "w", encoding="utf-8", newline="\n") as f:
190
+ f.write(TEMP_PYPROJECT)
191
+
192
+ CMD = [sys.executable, "-m", "poetry"]
193
+
194
+ subprocess.run(
195
+ CMD + ["lock"],
196
+ cwd=CLI_PATH,
197
+ check=True, # noqa: S603
198
+ )
199
+ subprocess.run(CMD + ["install"], cwd=CLI_PATH, check=True) # noqa: S603
200
+
201
+ except (Exception, KeyboardInterrupt) as e:
202
+ print(e) # noqa: T201
203
+ print("Restoring pyproject.toml and poetry.lock") # noqa: T201
204
+
205
+ finally:
206
+ # Revert pyproject.toml and poetry.lock to their original state.
207
+ with open(CLI_PYPROJECT, "w", encoding="utf-8", newline="\n") as f:
208
+ f.write(original_pyproject)
209
+
210
+ with open(CLI_LOCK, "w", encoding="utf-8", newline="\n") as f:
211
+ f.write(original_lock)
212
+
213
+
214
+ if __name__ == "__main__":
215
+ args = sys.argv[1:]
216
+ extras = any(arg.lower() in ["-e", "--extras"] for arg in args)
217
+ cli = any(arg.lower() in ["-c", "--cli"] for arg in args)
218
+ install_platform_local(extras)
219
+ if cli:
220
+ install_platform_cli()
openbb_platform/poetry.lock ADDED
The diff for this file is too large to render. See raw diff
 
openbb_platform/pyproject.toml ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [tool.poetry]
2
+ name = "openbb"
3
+ version = "4.4.4"
4
+ description = "Investment research for everyone, anywhere."
5
+ authors = ["OpenBB Team <hello@openbb.co>"]
6
+ license = "AGPL-3.0-only"
7
+ readme = "README.md"
8
+ packages = [{ include = "openbb" }]
9
+
10
+ [tool.poetry.dependencies]
11
+ python = ">=3.9.21,<3.13"
12
+ openbb-core = "^1.4.7"
13
+ openbb-platform-api = "^1.1.9"
14
+
15
+ openbb-benzinga = "^1.4.1"
16
+ openbb-bls = "^1.1.2"
17
+ openbb-cftc = "^1.1.1"
18
+ openbb-econdb = "^1.3.1"
19
+ openbb-federal-reserve = "^1.4.2"
20
+ openbb-fmp = "^1.4.2"
21
+ openbb-fred = "^1.4.4"
22
+ openbb-imf = "^1.1.1"
23
+ openbb-intrinio = "^1.4.1"
24
+ openbb-oecd = "^1.4.1"
25
+ openbb-polygon = "^1.4.1"
26
+ openbb-sec = "^1.4.3"
27
+ openbb-tiingo = "^1.4.1"
28
+ openbb-tradingeconomics = "^1.4.1"
29
+ openbb-us-eia = "^1.1.1"
30
+ openbb-yfinance = "^1.4.6"
31
+
32
+ openbb-commodity = "^1.3.1"
33
+ openbb-crypto = "^1.4.1"
34
+ openbb-currency = "^1.4.1"
35
+ openbb-derivatives = "^1.4.1"
36
+ openbb-economy = "^1.4.2"
37
+ openbb-equity = "^1.4.1"
38
+ openbb-etf = "^1.4.1"
39
+ openbb-fixedincome = "^1.4.3"
40
+ openbb-index = "^1.4.1"
41
+ openbb-news = "^1.4.1"
42
+ openbb-regulators = "^1.4.2"
43
+
44
+ # Community dependencies
45
+ openbb-alpha-vantage = { version = "^1.4.1", optional = true }
46
+ openbb-biztoc = { version = "^1.4.2", optional = true }
47
+ openbb-cboe = { version = "^1.4.1", optional = true }
48
+ openbb-deribit = { version = "^1.0.1", optional = true }
49
+ openbb-ecb = { version = "^1.4.2", optional = true }
50
+ openbb-finra = { version = "^1.4.1", optional = true }
51
+ openbb-finviz = { version = "^1.3.1", optional = true }
52
+ openbb-government-us = { version = "^1.4.1", optional = true }
53
+ openbb-multpl = { version = "^1.1.1", optional = true }
54
+ openbb-nasdaq = { version = "^1.4.1", optional = true }
55
+ openbb-seeking-alpha = { version = "^1.4.1", optional = true }
56
+ openbb-stockgrid = { version = "^1.4.1", optional = true }
57
+ openbb-tmx = { version = "^1.3.2", optional = true }
58
+ openbb-tradier = { version = "^1.3.1", optional = true }
59
+ openbb-wsj = { version = "^1.4.1", optional = true }
60
+
61
+ openbb-charting = { version = "^2.3.4", optional = true }
62
+ openbb-econometrics = { version = "^1.5.3", optional = true }
63
+ openbb-quantitative = { version = "^1.4.3", optional = true }
64
+ openbb-technical = { version = "^1.4.3", optional = true }
65
+
66
+ [tool.poetry.extras]
67
+ alpha_vantage = ["openbb-alpha-vantage"]
68
+ biztoc = ["openbb-biztoc"]
69
+ cboe = ["openbb-cboe"]
70
+ charting = ["openbb-charting"]
71
+ ecb = ["openbb-ecb"]
72
+ econometrics = ["openbb-econometrics"]
73
+ finra = ["openbb-finra"]
74
+ finviz = ["openbb-finviz"]
75
+ government_us = ["openbb-government-us"]
76
+ nasdaq = ["openbb-nasdaq"]
77
+ multpl = ["openbb-multpl"]
78
+ quantitative = ["openbb-quantitative"]
79
+ seeking_alpha = ["openbb-seeking-alpha"]
80
+ stockgrid = ["openbb-stockgrid"]
81
+ technical = ["openbb-technical"]
82
+ tmx = ["openbb-tmx"]
83
+ tradier = ["openbb-tradier"]
84
+ wsj = ["openbb-wsj"]
85
+
86
+
87
+ all = [
88
+ "openbb-alpha-vantage",
89
+ "openbb-biztoc",
90
+ "openbb-cboe",
91
+ "openbb-charting",
92
+ "openbb-deribit",
93
+ "openbb-ecb",
94
+ "openbb-econometrics",
95
+ "openbb-finra",
96
+ "openbb-finviz",
97
+ "openbb-government-us",
98
+ "openbb-multpl",
99
+ "openbb-nasdaq",
100
+ "openbb-quantitative",
101
+ "openbb-seeking-alpha",
102
+ "openbb-stockgrid",
103
+ "openbb-technical",
104
+ "openbb-tmx",
105
+ "openbb-tradier",
106
+ "openbb-wsj",
107
+ ]
108
+
109
+ [build-system]
110
+ requires = ["poetry-core"]
111
+ build-backend = "poetry.core.masonry.api"