mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
Merge branch 'develop' into feature/openbb-sdk-v4
This commit is contained in:
@@ -278,6 +278,7 @@ def print_rich_table(
|
||||
print_to_console: bool = False,
|
||||
limit: Optional[int] = 1000,
|
||||
source: Optional[str] = None,
|
||||
columns_keep_types: Optional[List[str]] = None,
|
||||
):
|
||||
"""Prepare a table from df in rich.
|
||||
|
||||
@@ -313,6 +314,8 @@ def print_rich_table(
|
||||
console.
|
||||
source: Optional[str]
|
||||
Source of the table. If provided, it will be displayed in the header of the table.
|
||||
columns_keep_types: Optional[List[str]]
|
||||
Columns to keep their types, i.e. not convert to numeric
|
||||
"""
|
||||
if export:
|
||||
return
|
||||
@@ -329,6 +332,8 @@ def print_rich_table(
|
||||
# convert non-str that are not timestamp or int into str
|
||||
# eg) praw.models.reddit.subreddit.Subreddit
|
||||
for col in df.columns:
|
||||
if columns_keep_types is not None and col in columns_keep_types:
|
||||
continue
|
||||
try:
|
||||
if not any(
|
||||
isinstance(df[col].iloc[x], pd.Timestamp)
|
||||
|
||||
@@ -172,9 +172,17 @@ def display_price_target_from_analysts(
|
||||
name="Price Target",
|
||||
mode="markers",
|
||||
customdata=df_analyst_plot.apply(
|
||||
lambda row: f"{row['Company']} ({row['Rating']})", axis=1
|
||||
).values,
|
||||
hovertemplate="%{customdata}<br><br>Price Target: %{y:.2f}",
|
||||
lambda row: "<br>".join(
|
||||
[
|
||||
f"<b>${x['Price Target']}</b> - <b>{x['Company']} ({x['Rating']})</b>"
|
||||
for _, x in df_analyst_plot[df_analyst_plot.index == row.name]
|
||||
.sort_values(by="Price Target", ascending=False)
|
||||
.iterrows()
|
||||
]
|
||||
),
|
||||
axis=1,
|
||||
),
|
||||
hovertemplate="<br>%{customdata}",
|
||||
marker=dict(
|
||||
color=colors,
|
||||
line=dict(width=1, color="DarkSlateGrey"),
|
||||
@@ -183,6 +191,8 @@ def display_price_target_from_analysts(
|
||||
line=dict(color=theme.get_colors()[1]),
|
||||
)
|
||||
|
||||
fig.update_layout(hovermode="x unified")
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
|
||||
@@ -35,7 +35,8 @@ def get_option_history(
|
||||
price : Union[str, Union[int, float]]
|
||||
Strike price for a specific option
|
||||
chain_id: str
|
||||
OCC option symbol. Overwrites other inputs
|
||||
Option symbol. Overwrites other inputs. ChartExchange uses the format:
|
||||
`{TICKER}{YYYYMMDD}{C/P}{PRICE}`, where the price has no leading and trailing zeros.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
@@ -72,6 +72,7 @@ def display_raw(
|
||||
price: float = 90,
|
||||
limit: int = 10,
|
||||
chain_id: Optional[str] = None,
|
||||
raw: bool = False,
|
||||
export: str = "",
|
||||
sheet_name: Optional[str] = None,
|
||||
external_axes: bool = False,
|
||||
@@ -109,22 +110,27 @@ def display_raw(
|
||||
option_type = "call" if call else "put"
|
||||
fig = plot_chart(df, option_type, symbol, price)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"hist",
|
||||
df,
|
||||
sheet_name,
|
||||
fig,
|
||||
)
|
||||
print_rich_table(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
show_index=True,
|
||||
index_name="Date",
|
||||
title=f"{symbol.upper()} raw data",
|
||||
export=bool(export),
|
||||
limit=limit,
|
||||
)
|
||||
if export:
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"hist",
|
||||
df,
|
||||
sheet_name,
|
||||
fig,
|
||||
)
|
||||
return None
|
||||
|
||||
if raw:
|
||||
print_rich_table(
|
||||
df,
|
||||
headers=list(df.columns),
|
||||
show_index=True,
|
||||
index_name="Date",
|
||||
title="Historical Option Prices",
|
||||
export=bool(export),
|
||||
limit=limit,
|
||||
)
|
||||
return None
|
||||
|
||||
return fig.show(external=external_axes)
|
||||
|
||||
@@ -71,6 +71,8 @@ def display_historical(
|
||||
headers=[x.title() for x in df_hist.columns],
|
||||
title="Historical Option Prices",
|
||||
export=bool(export),
|
||||
show_index=True,
|
||||
index_name="Date",
|
||||
)
|
||||
|
||||
df_hist.columns = [x.title() for x in df_hist.columns]
|
||||
|
||||
@@ -800,6 +800,7 @@ class OptionsController(BaseController):
|
||||
call=not ns_parser.put,
|
||||
price=ns_parser.strike,
|
||||
limit=ns_parser.limit,
|
||||
raw=ns_parser.raw,
|
||||
export=ns_parser.export,
|
||||
chain_id=ns_parser.chain_id,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
|
||||
@@ -72,6 +72,8 @@ def display_historical(
|
||||
headers=[x.title() for x in df_hist.columns],
|
||||
title="Historical Option Prices",
|
||||
export=bool(export),
|
||||
show_index=True,
|
||||
index_name="Date",
|
||||
)
|
||||
|
||||
op_type = ["call", "put"][put]
|
||||
|
||||
@@ -18,6 +18,7 @@ from typing import Any, Dict, List, Optional
|
||||
|
||||
import certifi
|
||||
import pandas as pd
|
||||
import requests
|
||||
from prompt_toolkit import PromptSession
|
||||
from prompt_toolkit.completion import NestedCompleter
|
||||
from prompt_toolkit.formatted_text import HTML
|
||||
@@ -331,15 +332,15 @@ class TerminalController(BaseController):
|
||||
)
|
||||
|
||||
def parse_input(self, an_input: str) -> List:
|
||||
"""Overwrite the BaseController parse_input for `askobb`
|
||||
"""Overwrite the BaseController parse_input for `askobb` and 'exe'
|
||||
|
||||
This will allow us to search for something like "P/E" ratio
|
||||
"""
|
||||
# Filtering out sorting parameters with forward slashes like P/E
|
||||
sort_filter = r"((\ -q |\ --question|\ ).*?(/))"
|
||||
|
||||
custom_filters = [sort_filter]
|
||||
|
||||
# Filter out urls
|
||||
url = r"(exe (--url )?(https?://)?my\.openbb\.(dev|co)/u/.*/routine/.*)"
|
||||
custom_filters = [sort_filter, url]
|
||||
return parse_and_split_input(an_input=an_input, custom_filters=custom_filters)
|
||||
|
||||
def call_guess(self, other_args: List[str]) -> None:
|
||||
@@ -591,16 +592,6 @@ class TerminalController(BaseController):
|
||||
def call_intro(self, _):
|
||||
"""Process intro command."""
|
||||
webbrowser.open("https://docs.openbb.co/terminal/usage/basics")
|
||||
# import json
|
||||
|
||||
# intro: dict = json.load((Path(__file__).parent / "intro.json").open()) # type: ignore
|
||||
|
||||
# for prompt in intro.get("prompts", []):
|
||||
# console.print(panel.Panel(f"[purple]{prompt['header']}[/purple]"))
|
||||
# console.print("".join(prompt["content"]))
|
||||
# if input("") == "q":
|
||||
# break
|
||||
# console.print("\n")
|
||||
|
||||
def call_exe(self, other_args: List[str]):
|
||||
"""Process exe command."""
|
||||
@@ -629,7 +620,9 @@ class TerminalController(BaseController):
|
||||
required="-h" not in other_args
|
||||
and "--help" not in other_args
|
||||
and "-e" not in other_args
|
||||
and "--example" not in other_args,
|
||||
and "--example" not in other_args
|
||||
and "--url" not in other_args
|
||||
and "my.openbb" not in other_args[0],
|
||||
type=str,
|
||||
nargs="+",
|
||||
)
|
||||
@@ -648,10 +641,15 @@ class TerminalController(BaseController):
|
||||
action="store_true",
|
||||
default=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--url", help="URL to run openbb script from.", dest="url", type=str
|
||||
)
|
||||
if other_args and "-" not in other_args[0][0]:
|
||||
other_args.insert(0, "--file")
|
||||
if other_args[0].startswith("my.") or other_args[0].startswith("http"):
|
||||
other_args.insert(0, "--url")
|
||||
else:
|
||||
other_args.insert(0, "--file")
|
||||
ns_parser = self.parse_known_args_and_warn(parser, other_args)
|
||||
|
||||
if ns_parser:
|
||||
if ns_parser.example:
|
||||
routine_path = (
|
||||
@@ -662,11 +660,37 @@ class TerminalController(BaseController):
|
||||
"to learn how to create your own script.[/info]\n"
|
||||
)
|
||||
time.sleep(3)
|
||||
elif ns_parser.url:
|
||||
if not ns_parser.url.startswith(
|
||||
"https"
|
||||
) and not ns_parser.url.startswith("http:"):
|
||||
url = "https://" + ns_parser.url
|
||||
else:
|
||||
if ns_parser.url.startswith("http://"):
|
||||
url = ns_parser.url.replace("http://", "https://")
|
||||
else:
|
||||
url = ns_parser.url
|
||||
username = url.split("/")[-3]
|
||||
script_name = url.split("/")[-1]
|
||||
file_name = f"{username}_{script_name}.openbb"
|
||||
final_url = f"{url}?raw=true"
|
||||
response = requests.get(final_url, timeout=10)
|
||||
if response.status_code != 200:
|
||||
console.print("[red]Could not find the requested script.[/red]")
|
||||
return
|
||||
routine_text = response.json()["script"]
|
||||
file_path = Path(get_current_user().preferences.USER_ROUTINES_DIRECTORY)
|
||||
routine_path = file_path / file_name
|
||||
with open(routine_path, "w") as file:
|
||||
file.write(routine_text)
|
||||
self.update_runtime_choices()
|
||||
|
||||
elif ns_parser.file:
|
||||
file_path = " ".join(ns_parser.file) # type: ignore
|
||||
# if string is not in this format "default/file.openbb" then check for files in ROUTINE_FILES
|
||||
file_path = " ".join(ns_parser.file)
|
||||
full_path = file_path
|
||||
hub_routine = file_path.split("/")
|
||||
hub_routine = file_path.split("/") # type: ignore
|
||||
# Change with: my.openbb.co
|
||||
if hub_routine[0] == "default":
|
||||
routine_path = Path(
|
||||
self.ROUTINE_DEFAULT_FILES.get(hub_routine[1], full_path)
|
||||
@@ -676,7 +700,7 @@ class TerminalController(BaseController):
|
||||
self.ROUTINE_PERSONAL_FILES.get(hub_routine[1], full_path)
|
||||
)
|
||||
else:
|
||||
routine_path = Path(self.ROUTINE_FILES.get(file_path, full_path))
|
||||
routine_path = Path(self.ROUTINE_FILES.get(file_path, full_path)) # type: ignore
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
@@ -23,12 +23,12 @@ def vcr_config():
|
||||
@pytest.mark.vcr
|
||||
@pytest.mark.record_stdout
|
||||
@pytest.mark.parametrize(
|
||||
"tab",
|
||||
"raw",
|
||||
[True, False],
|
||||
)
|
||||
def test_display_raw(mocker, tab):
|
||||
def test_display_raw(mocker, raw):
|
||||
# MOCK CHARTS
|
||||
preferences = PreferencesModel(USE_TABULATE_DF=tab)
|
||||
preferences = PreferencesModel(USE_TABULATE_DF=raw)
|
||||
mock_current_user = copy_user(preferences=preferences)
|
||||
mocker.patch(
|
||||
target="openbb_terminal.core.session.current_user.__current_user",
|
||||
@@ -39,9 +39,5 @@ def test_display_raw(mocker, tab):
|
||||
mocker.patch(target="openbb_terminal.stocks.options.chartexchange_view.plot_chart")
|
||||
|
||||
chartexchange_view.display_raw(
|
||||
export="",
|
||||
symbol="GME",
|
||||
expiry="2021-02-05",
|
||||
call=True,
|
||||
price=90,
|
||||
export="", symbol="GME", expiry="2021-02-05", call=True, price=90, raw=raw
|
||||
)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
Open High Low Close Change Volume Open Interest Change Since
|
||||
Date
|
||||
2021-01-25 20.70 85.70 13.90 20.00 0.00000 1834.0 552.0 -0.99850
|
||||
2021-01-26 27.50 75.79 21.00 70.17 2.50850 1763.0 572.0 -0.99957
|
||||
2021-01-27 210.20 285.50 70.80 255.90 2.64686 309.0 461.0 -0.99988
|
||||
2021-01-28 225.40 385.55 62.75 130.65 -0.48945 49.0 450.0 -0.99977
|
||||
2021-01-29 232.15 296.20 183.10 183.10 0.40145 37.0 445.0 -0.99984
|
||||
2021-02-01 232.60 232.60 133.09 133.09 -0.27313 107.0 441.0 -0.99977
|
||||
2021-02-02 64.61 76.20 18.50 23.70 -0.82193 1991.0 555.0 -0.99873
|
||||
2021-02-03 40.45 40.45 13.50 14.26 -0.39831 2124.0 1074.0 -0.99790
|
||||
2021-02-04 13.70 14.00 0.75 0.75 -0.94741 5945.0 2386.0 -0.96000
|
||||
2021-02-05 0.57 14.79 0.01 0.03 -0.96000 6580.0 2017.0 0.00000
|
||||
|
||||
Reference in New Issue
Block a user