Quickstart - Workspace Custom Backend
The OpenBB Platform 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.
The sections below will outline a few scenarios.
Launch Platform App
To include all installed OpenBB extensions as widgets in the custom backend connector:
Open a terminal, activate the environment where openbb
was installed, then enter:
openbb-api
-
Next, open your browswer 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 page here for the steps to do it.
- 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 --exclude
argument to ignore the entire /api/*
path.
Widgets will now only populate from endpoints added to the imported app
instance.
from openbb_platform_api.main import app
from openbb import obb
@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 --exclude '"/api/v1/*"' --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,
}
),
]