Workspace Integration
The OPD Python Package can be used as a Workspace custom backend, both as a fully-loaded data source, or as the bare shell and launcher of a FastAPI application.
OpenBB API
openbb-api
is a command line executable, similar to uvicorn
, for starting a FastAPI app instance, generating and serving configuration files OpenBB Workspace requires.
It can be installed as standalone with:
pip install openbb-platform-api
See the documentation here for a detailed description of parameters and example snippets.
The sections below will outline a few scenarios.
Launch
To include the installed extensions and endpoints as widgets in the custom backend connector:
Open a terminal, activate the environment where openbb
was installed, then enter:
openbb-api
By default, this starts the server over http://127.0.0.1:6900.
-
Next, open your browser and login to pro.openbb.co.
-
From the sidebar, click "Data Connectors".
-
Then, click the "Add Data" button.
-
Enter a name for the connection, and use the server address displayed in the console.
-
Then, click the "Test" button.
If a connection error displays after pressing the "Test" button, your browser might be blocking access because of "mixed content". Browsers such as Safari, and Brave, do not permit HTTP connections.
Try using Chrome, specifically, or start the server over HTTPS.
See the Desktop App to get started.
- Finally, click the "Add" button.
All data endpoints are now configured to use and are available to the Search.
Launch Custom Platform App
Let's say, you want to create a custom backend that presents data differently, and you don't want any of the built-in widgets to populate. You want complete control over the generated view.
In this scenario, use the --app
argument to point to a new instance of FastAPI. Widgets will now only populate from this instance, and not the OpenBB environment.
from fastapi import FastAPI
from openbb import obb
app = FastAPI()
@app.get("/company_description")
async def company_description(symbol: str = "AAPL") -> str:
"""Reference data for the given company using yFinance."""
response = obb.equity.profile(symbol, provider="yfinance")
description = response.results[0].long_description
md = f"""
# **{response.results[0].name}**
## **{response.results[0].sector}**
### **{response.results[0].industry_category}**
<details>
<summary mdxType="summary">Company Description</summary>
{description}
</details>
{response.results[0].company_url}
"""
return md
Launch the backend by including the path to the Python file as the --app
argument.
openbb-api --app /Users/path/to/some/folder/some_file.py --reload
Launch Any FastAPI App
For this, the only requirements are:
- Python version between 3.9 and 3.12, inclusively.
openbb-platform-api
package, installable from PyPI.
Add the path to the Python file with the FastAPI instance to launch.
openbb-api --app /Users/path/to/some/folder/some_file.py
At this time, only "GET" methods are supported by custom backends.
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
async def hello() -> str:
"""Widget Description Generated By Docstring"""
return "Hello, from OpenBB!"
Function arguments will populate as widget parameters.
Parameters With Dropdown
Literal types of function parameters will automatically be recognized as choices in a dropdown menu.
from typing import Literal, Optional
app = FastAPI()
@app.get("/hello")
async def hello(param1: Optional[str] = None, param2: Literal["Choice 1", "Choice 2"] = None, param3: bool = False) -> str:
"""Widget Description Generated By Docstring"""
if not param1 and not param2 and not param3:
return "Enter a parameter or make a choice!"
if param3:
return f"Param3 enabled!"
if param2:
return f"You selected: {param2}"
if param1:
return f"You entered: {param1}"
return "Nothing to return!"
Table Widget
Create a table widget by returning data shaped as a list of dictionaries (records)
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
async def hello() -> list:
"""Widget Description Generated By Docstring"""
return [{"Column 1": "Hello", "Column 2": "from OpenBB!"}]
Annotated Functions
Annotated parameters and responses will create column definitions and hover descriptions.
For data responses, return a list of Pydantic models to get the most bang-for-the-buck.
from typing import Annotated
from fastapi import FastAPI, Query
from openbb_core.provider.abstract.data import Data # Inherit this instead of pydantic.BaseModel to represent 1 row of data.
from pydantic import Field
app = FastAPI()
class MyData(Data):
"""MyData Response Model."""
column_1: str = Field(title="Some Text", description="Hover text for Column 1")
column_2: int = Field(title="Some Number", description="Hover text for Column 2")
column_3: float = Field(
title="Some Percent",
description="Hover text for Column 3",
json_schema_extra={"x-unit_measurement": "percent"},
)
column_4: float = Field(
title="Some Normalized Percent",
description="Hover text for Column 4",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
@app.get("/table")
async def table(
param1: Annotated[str, Query(description="Hover text for param1")] = None,
param2: Annotated[int, Query(description="Some Number")] = None,
date: Annotated[str, Query(description="Date selector")] = None,
) -> list[MyData]:
"""Widget Description Generated By Docstring"""
return [
MyData.model_validate(
{
"column_1": "Hello",
"column_2": 10,
"column_3": 33.345,
"column_4": -0.33345,
}
),
]