Skip to content

Commit

Permalink
[Feature] Add Finviz Screener Presets (V3 Compatible) (#6601)
Browse files Browse the repository at this point in the history
* add finviz screener presets

* codespell

* init docstring

* no-else-raise

* test params

* not needed in json_schema_extra

* order by settings

* preset description
  • Loading branch information
deeleeramone authored Jul 30, 2024
1 parent 586df54 commit a4ed8ab
Show file tree
Hide file tree
Showing 33 changed files with 6,124 additions and 17 deletions.
12 changes: 7 additions & 5 deletions cli/openbb_cli/argparse_translator/argparse_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,22 +400,23 @@ def execute_func(
"""
kwargs = self._unflatten_args(vars(parsed_args))
kwargs = self._update_with_custom_types(kwargs)

provider = kwargs.get("provider")
provider_args = []
provider_args: List = []
if provider and provider in self.provider_parameters:
provider_args = self.provider_parameters[provider]
else:
for args in self.provider_parameters.values():
provider_args.extend(args)

# remove kwargs that doesn't match the signature or provider parameters
# remove kwargs not matching the signature, provider parameters, or are empty.
kwargs = {
key: value
for key, value in kwargs.items()
if key in self.signature.parameters or key in provider_args
if (
(key in self.signature.parameters or key in provider_args)
and (value or value is False)
)
}

return self.func(**kwargs)

def parse_args_and_execute(self) -> Any:
Expand All @@ -426,6 +427,7 @@ def parse_args_and_execute(self) -> Any:
Any: The return value of the original function.
"""
parsed_args = self._parser.parse_args()

return self.execute_func(parsed_args)

def translate(self) -> Callable:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Equity Screener Standard Model."""

from typing import List, Set, Union
from typing import Optional

from pydantic import Field, field_validator
from pydantic import Field

from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
Expand All @@ -17,12 +17,4 @@ class EquityScreenerData(Data):
"""Equity Screener Data."""

symbol: str = Field(description=DATA_DESCRIPTIONS.get("symbol", ""))
name: str = Field(description="Name of the company.")

@field_validator("symbol", mode="before", check_fields=False)
@classmethod
def to_upper(cls, v: Union[str, List[str], Set[str]]):
"""Convert field to uppercase."""
if isinstance(v, str):
return v.upper()
return ",".join([symbol.upper() for symbol in list(v)])
name: Optional[str] = Field(default=None, description="Name of the company.")
16 changes: 16 additions & 0 deletions openbb_platform/extensions/equity/integration/test_equity_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,22 @@ def test_equity_search(params, headers):
"provider": "nasdaq",
}
),
(
{
"metric": "overview",
"signal": None,
"preset": None,
"filters_dict": None,
"sector": "consumer_defensive",
"industry": "grocery_stores",
"index": "all",
"exchange": "all",
"mktcap": "all",
"recommendation": "all",
"limit": None,
"provider": "finviz",
}
),
],
)
@pytest.mark.integration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,22 @@ def test_equity_search(params, obb):
"provider": "nasdaq",
}
),
(
{
"metric": "overview",
"signal": None,
"preset": None,
"filters_dict": None,
"sector": "consumer_defensive",
"industry": "grocery_stores",
"index": "all",
"exchange": "all",
"mktcap": "all",
"recommendation": "all",
"limit": None,
"provider": "finviz",
}
),
],
)
@pytest.mark.integration
Expand Down
100 changes: 99 additions & 1 deletion openbb_platform/providers/finviz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This extension integrates the [Finviz](https://finviz.com/) data provider into the OpenBB Platform.

It will install, [finvizfinance](https://github.com/lit26/finvizfinance/), to power the functions.

## Installation

To install the extension:
Expand All @@ -10,4 +12,100 @@ To install the extension:
pip install openbb-finviz
```

Documentation available [here](https://docs.openbb.co/platform/developer_guide/contributing).
## Endpoints

- obb.equity.compare.groups
- obb.equity.estimates.price_target
- obb.equity.fundamental.metrics
- obb.equity.profile
- obb.equity.price.performance
- obb.equity.screener

## Screener

The screener is a faithful replication of the public-facing stock screener - https://finviz.com/screener.ashx?

Some options are directly accessible through the function parameters, all others are exposed via `presets` or `filters_dict`.
The filters list below are exposed in the function, with choices visible in the docstring:

- `exchange`
- `index`
- `sector`
- `industry`
- `mktcap`
- `recommendation` (analyst's mean score from 1-5)
- `signal` (same as the "Signal" on the Finviz page)

When the function is run without any parameters, it will default to the "top_gainers" signal.

```python
res = obb.equity.screener(provider="finviz")
```

### Metric

The `metric` parameter defines the type of data fields to return. Choices are:

- `overview`
- `ownership`
- `performance`
- `technical`
- `valuation`

Default is, "overview".

```
res = obb.equity.screener(provider="finviz", metric="performance")
```

### Preset Files

Presets can be created and customized in the "OpenBBUserData" folder. Template and default presets are created on the first run of the function.

Files are loaded on runtime, changes are effective without restarting the Python interpreter.

The `preset` parameter will override all others, except `metric` and `limit`.

Run the function to create the template and default presets in your `OpenBBUserData` folder.

Presets from the legacy OpenBB Terminal will continue to work, simply move your presets into the folder below.

```python
res = obb.equity.screener(provider="finviz", index="nasdaq")
```

Then find the presets here: `$HOME/OpenBBUserData/presets/finviz`

```python
res = obb.equity.screener(provider="finviz", preset="short_squeeze")
```

### Filters Dict

The `filters_dict` parameter acts as an alternative to `preset`, accepting a dictionary or JSON encoded string.

```python
res = obb.equity.screener(provider="finviz", filters_dict={"Index": "NASDAQ 100"})
```

Or as a JSON:

```python
res = obb.equity.screener(provider="finviz", filters_dict='{"Index": "NASDAQ 100"}')
```

When using the Fast API, this is sent in the request body.

### Error Messages

All parameters are validated, incorrect keys and choices will raise an error with information to help correct. For example:

```python
obb.equity.screener(provider="finviz", filters_dict='{"Index": "NASDAQ"}')
```

```console
Invalid filter option 'NASDAQ'. Possible filter options: ['Any', 'S&P 500', 'NASDAQ 100', 'DJIA', 'RUSSELL 2000']
```

Read the OpenBB Platform documentation [here](https://docs.openbb.co)
2 changes: 2 additions & 0 deletions openbb_platform/providers/finviz/openbb_finviz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from openbb_core.provider.abstract.provider import Provider
from openbb_finviz.models.compare_groups import FinvizCompareGroupsFetcher
from openbb_finviz.models.equity_profile import FinvizEquityProfileFetcher
from openbb_finviz.models.equity_screener import FinvizEquityScreenerFetcher
from openbb_finviz.models.key_metrics import FinvizKeyMetricsFetcher
from openbb_finviz.models.price_performance import FinvizPricePerformanceFetcher
from openbb_finviz.models.price_target import FinvizPriceTargetFetcher
Expand All @@ -16,6 +17,7 @@
"CompareGroups": FinvizCompareGroupsFetcher,
"EtfPricePerformance": FinvizPricePerformanceFetcher,
"EquityInfo": FinvizEquityProfileFetcher,
"EquityScreener": FinvizEquityScreenerFetcher,
"KeyMetrics": FinvizKeyMetricsFetcher,
"PricePerformance": FinvizPricePerformanceFetcher,
"PriceTarget": FinvizPriceTargetFetcher,
Expand Down
Loading

0 comments on commit a4ed8ab

Please sign in to comment.