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:
@@ -375,7 +375,6 @@ def upload_config(
|
||||
value: str,
|
||||
type_: Literal["settings", "terminal_style"],
|
||||
auth_header: str,
|
||||
base_url: str = BackendEnvironment.BASE_URL,
|
||||
timeout: int = TIMEOUT,
|
||||
) -> Optional[requests.Response]:
|
||||
"""Patch user configurations to the server.
|
||||
@@ -390,8 +389,6 @@ def upload_config(
|
||||
The type of the patch.
|
||||
auth_header : str
|
||||
The authorization header, e.g. "Bearer <token>".
|
||||
base_url : str
|
||||
The base url, by default BASE_URL
|
||||
timeout : int
|
||||
The timeout, by default TIMEOUT
|
||||
|
||||
@@ -409,7 +406,7 @@ def upload_config(
|
||||
try:
|
||||
console.print("Sending to OpenBB hub...")
|
||||
response = requests.patch(
|
||||
url=base_url + "terminal/user",
|
||||
url=BackendEnvironment.BASE_URL + "terminal/user",
|
||||
headers={"Authorization": auth_header},
|
||||
json=data,
|
||||
timeout=timeout,
|
||||
|
||||
@@ -419,9 +419,12 @@ TRANSFORM = {
|
||||
SCALES = {
|
||||
"Thousands": 1_000,
|
||||
"Tens of thousands": 10_000,
|
||||
"Hundreds of thousands": 100_000,
|
||||
"Millions": 1_000_000,
|
||||
"Tens of millions": 10_000_000,
|
||||
"Hundreds of millions": 100_000_000,
|
||||
"Billions": 1_000_000_000,
|
||||
"Tens of billions": 10_000_000_000,
|
||||
"Units": 1,
|
||||
}
|
||||
|
||||
|
||||
@@ -2078,7 +2078,7 @@ def check_start_less_than_end(start_date: str, end_date: str) -> bool:
|
||||
|
||||
# Write an abstract helper to make requests from a url with potential headers and params
|
||||
def request(
|
||||
url: str, method: str = "GET", timeout: int = 0, **kwargs
|
||||
url: str, method: str = "get", timeout: int = 0, **kwargs
|
||||
) -> requests.Response:
|
||||
"""Abstract helper to make requests from a url with potential headers and params.
|
||||
|
||||
@@ -2086,8 +2086,11 @@ def request(
|
||||
----------
|
||||
url : str
|
||||
Url to make the request to
|
||||
method : str, optional
|
||||
HTTP method to use. Can be "GET" or "POST", by default "GET"
|
||||
method : str
|
||||
HTTP method to use. Choose from:
|
||||
delete, get, head, patch, post, put, by default "get"
|
||||
timeout : int
|
||||
How many seconds to wait for the server to send data
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -2099,6 +2102,9 @@ def request(
|
||||
ValueError
|
||||
If invalid method is passed
|
||||
"""
|
||||
method = method.lower()
|
||||
if method not in ["delete", "get", "head", "patch", "post", "put"]:
|
||||
raise ValueError(f"Invalid method: {method}")
|
||||
current_user = get_current_user()
|
||||
# We want to add a user agent to the request, so check if there are any headers
|
||||
# If there are headers, check if there is a user agent, if not add one.
|
||||
@@ -2108,21 +2114,13 @@ def request(
|
||||
|
||||
if "User-Agent" not in headers:
|
||||
headers["User-Agent"] = get_user_agent()
|
||||
if method.upper() == "GET":
|
||||
return requests.get(
|
||||
url,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
**kwargs,
|
||||
)
|
||||
if method.upper() == "POST":
|
||||
return requests.post(
|
||||
url,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
**kwargs,
|
||||
)
|
||||
raise ValueError("Method must be GET or POST")
|
||||
func = getattr(requests, method)
|
||||
return func(
|
||||
url,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
def remove_timezone_from_dataframe(df: pd.DataFrame) -> pd.DataFrame:
|
||||
|
||||
@@ -231,7 +231,7 @@ class SettingsController(BaseController):
|
||||
" Then, place the downloaded file 'openbb_config.richstyle.json'"
|
||||
f" inside {get_current_user().preferences.USER_STYLES_DIRECTORY} or "
|
||||
f"{STYLES_DIRECTORY_REPO}. If you have a hub account you can change colors "
|
||||
f"here {BackendEnvironment.HUB_URL + 'app/terminal/theme'}.",
|
||||
f"here {BackendEnvironment.BASE_URL + 'app/terminal/theme'}.",
|
||||
)
|
||||
if other_args and "-" not in other_args[0][0]:
|
||||
other_args.insert(0, "-s")
|
||||
@@ -246,7 +246,6 @@ class SettingsController(BaseController):
|
||||
value=ns_parser.style,
|
||||
type_="settings",
|
||||
auth_header=get_current_user().profile.get_auth_header(),
|
||||
base_url=BackendEnvironment.HUB_URL,
|
||||
)
|
||||
console.print("")
|
||||
console.print("Colors updated.")
|
||||
@@ -267,7 +266,7 @@ class SettingsController(BaseController):
|
||||
dest="style",
|
||||
choices=["dark", "light"],
|
||||
help="Choose chart style. If you have a hub account you can change theme "
|
||||
f"here {BackendEnvironment.HUB_URL + 'app/terminal/theme/charts-tables'}.",
|
||||
f"here {BackendEnvironment.BASE_URL + 'app/terminal/theme/charts-tables'}.",
|
||||
required="-h" not in other_args and "--help" not in other_args,
|
||||
)
|
||||
if other_args and "-" not in other_args[0][0]:
|
||||
@@ -283,7 +282,6 @@ class SettingsController(BaseController):
|
||||
value=ns_parser.style,
|
||||
type_="terminal_style",
|
||||
auth_header=get_current_user().profile.get_auth_header(),
|
||||
base_url=BackendEnvironment.HUB_URL,
|
||||
)
|
||||
console.print("")
|
||||
theme.apply_style(ns_parser.style)
|
||||
@@ -305,7 +303,7 @@ class SettingsController(BaseController):
|
||||
dest="style",
|
||||
choices=["dark", "light"],
|
||||
help="Choose table style. If you have a hub account you can change theme "
|
||||
f"here {BackendEnvironment.HUB_URL + 'app/terminal/theme/charts-tables'}.",
|
||||
f"here {BackendEnvironment.BASE_URL + 'app/terminal/theme/charts-tables'}.",
|
||||
required="-h" not in other_args and "--help" not in other_args,
|
||||
)
|
||||
if other_args and "-" not in other_args[0][0]:
|
||||
@@ -321,7 +319,6 @@ class SettingsController(BaseController):
|
||||
value=ns_parser.style,
|
||||
type_="terminal_style",
|
||||
auth_header=get_current_user().profile.get_auth_header(),
|
||||
base_url=BackendEnvironment.HUB_URL,
|
||||
)
|
||||
console.print("")
|
||||
console.print("Table theme updated.\n")
|
||||
|
||||
@@ -246,7 +246,7 @@ class StocksController(StockBaseController):
|
||||
parser,
|
||||
other_args,
|
||||
EXPORT_ONLY_RAW_DATA_ALLOWED,
|
||||
limit=10,
|
||||
limit=0,
|
||||
):
|
||||
# Mapping
|
||||
sector = stocks_helper.map_parse_choices(self.sector)[ns_parser.sector]
|
||||
@@ -263,7 +263,7 @@ class StocksController(StockBaseController):
|
||||
list(stocks_helper.market_coverage_suffix.keys())
|
||||
)[ns_parser.exchange_country]
|
||||
|
||||
stocks_helper.search(
|
||||
df = stocks_helper.search(
|
||||
query=" ".join(ns_parser.query),
|
||||
country=ns_parser.country,
|
||||
sector=sector,
|
||||
@@ -272,8 +272,22 @@ class StocksController(StockBaseController):
|
||||
exchange=exchange,
|
||||
exchange_country=exchange_country,
|
||||
all_exchanges=ns_parser.all_exchanges,
|
||||
limit=ns_parser.limit,
|
||||
)
|
||||
if ns_parser.export:
|
||||
export_data(
|
||||
ns_parser.export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"search",
|
||||
df,
|
||||
" ".join(ns_parser.sheet_name) if ns_parser.sheet_name else None,
|
||||
)
|
||||
if not ns_parser.export:
|
||||
stocks_helper.print_rich_table(
|
||||
df,
|
||||
show_index=False,
|
||||
headers=df.columns,
|
||||
title="Stock Search Results",
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def call_tob(self, other_args: List[str]):
|
||||
|
||||
@@ -120,7 +120,6 @@ def search(
|
||||
exchange: str = "",
|
||||
exchange_country: str = "",
|
||||
all_exchanges: bool = False,
|
||||
limit: int = 0,
|
||||
) -> pd.DataFrame:
|
||||
"""Search selected query for tickers.
|
||||
|
||||
@@ -142,8 +141,6 @@ def search(
|
||||
Search by exchange country to find stock matching the criteria
|
||||
all_exchanges: bool
|
||||
Whether to search all exchanges, without this option only the United States market is searched
|
||||
limit : int
|
||||
The limit of results shown, where 0 means all the results
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -228,43 +225,11 @@ def search(
|
||||
|
||||
df = df[["name", "country", "sector", "industry_group", "industry", "exchange"]]
|
||||
# To automate renaming columns
|
||||
headers = [col.replace("_", " ") for col in df.columns.tolist()]
|
||||
|
||||
title = "Companies found"
|
||||
if query:
|
||||
title += f" on term {query}"
|
||||
if exchange_country and exchange:
|
||||
title += f" on the exchange {exchange} in {exchange_country.replace('_', ' ').title()}"
|
||||
if exchange and not exchange_country:
|
||||
title += f" on the exchange {exchange}"
|
||||
if exchange_country and not exchange:
|
||||
title += f" on an exchange in {exchange_country.replace('_', ' ').title()}"
|
||||
if country:
|
||||
title += f" in {country.replace('_', ' ').title()}"
|
||||
if sector:
|
||||
title += f" within {sector}"
|
||||
if industry_group:
|
||||
title += f" and {industry_group}"
|
||||
if industry:
|
||||
title += f" and {industry}"
|
||||
if not sector and industry_group:
|
||||
title += f" within {industry_group}"
|
||||
if not sector and industry:
|
||||
title += f" within {industry}"
|
||||
|
||||
df.columns = [col.replace("_", " ") for col in df.columns.tolist()]
|
||||
df = df.fillna(value=np.nan)
|
||||
df = df.iloc[df.isnull().sum(axis=1).mul(1).argsort()]
|
||||
|
||||
print_rich_table(
|
||||
df,
|
||||
show_index=True,
|
||||
headers=headers,
|
||||
index_name="Symbol",
|
||||
title=title,
|
||||
limit=limit,
|
||||
)
|
||||
|
||||
return df
|
||||
return df.reset_index()
|
||||
|
||||
|
||||
def load( # pylint: disable=too-many-return-statements
|
||||
@@ -1108,3 +1073,45 @@ def heikin_ashi(data: pd.DataFrame) -> pd.DataFrame:
|
||||
]
|
||||
|
||||
return pd.concat([data, ha], axis=1)
|
||||
|
||||
|
||||
def calculate_adjusted_prices(df: pd.DataFrame, column: str, dividends: bool = False):
|
||||
"""Calculates the split-adjusted prices, or split and dividend adjusted prices.
|
||||
|
||||
Parameters
|
||||
------------
|
||||
df: pd.DataFrame
|
||||
DataFrame with unadjusted OHLCV values + Split Factor + Dividend
|
||||
column: str
|
||||
The column name to adjust.
|
||||
dividends: bool
|
||||
Whether to adjust for both splits and dividends. Default is split-adjusted only.
|
||||
|
||||
Returns
|
||||
--------
|
||||
pd.DataFrame
|
||||
DataFrame with adjusted prices.
|
||||
"""
|
||||
|
||||
df = df.copy()
|
||||
adj_column = "Adj " + column
|
||||
|
||||
# Reverse the DataFrame order, sorting by date in descending order
|
||||
df.sort_index(ascending=False, inplace=True)
|
||||
|
||||
price_col = df[column].values
|
||||
split_col = df["Volume Factor"] if column == "Volume" else df["Split Factor"].values
|
||||
dividend_col = df["Dividend"].values if dividends else np.zeros(len(price_col))
|
||||
adj_price_col = np.zeros(len(df.index))
|
||||
adj_price_col[0] = price_col[0]
|
||||
|
||||
for i in range(1, len(price_col)):
|
||||
adj_price_col[i] = adj_price_col[i - 1] + adj_price_col[i - 1] * (
|
||||
((price_col[i] * split_col[i - 1]) - price_col[i - 1] - dividend_col[i - 1])
|
||||
/ price_col[i - 1]
|
||||
)
|
||||
df[adj_column] = adj_price_col
|
||||
|
||||
# Change the DataFrame order back to dates ascending
|
||||
df.sort_index(ascending=True, inplace=True)
|
||||
return df
|
||||
|
||||
@@ -266,7 +266,6 @@ def test_call_func_expect_queue(expected_queue, func, queue):
|
||||
[],
|
||||
dict(
|
||||
query="microsoft",
|
||||
limit=1,
|
||||
country="",
|
||||
sector="",
|
||||
industry_group="",
|
||||
|
||||
@@ -57,7 +57,7 @@ def test_search(mocker, use_tab):
|
||||
target="openbb_terminal.core.session.current_user.__current_user",
|
||||
new=mock_current_user,
|
||||
)
|
||||
stocks_helper.search(
|
||||
df = stocks_helper.search(
|
||||
query="microsoft",
|
||||
country="United_States",
|
||||
sector="",
|
||||
@@ -66,7 +66,9 @@ def test_search(mocker, use_tab):
|
||||
exchange="",
|
||||
exchange_country="",
|
||||
all_exchanges=False,
|
||||
limit=5,
|
||||
)
|
||||
stocks_helper.print_rich_table(
|
||||
df, show_index=False, title="Company Search Results", headers=df.columns
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
name country sector industry_group industry exchange
|
||||
symbol
|
||||
MSFT Microsoft Corporation United States Information Technology Software & Services Software NMS
|
||||
symbol name country sector industry group industry exchange
|
||||
0 MSFT Microsoft Corporation United States Information Technology Software & Services Software NMS
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
name country sector industry_group industry exchange
|
||||
symbol
|
||||
MSFT Microsoft Corporation United States Information Technology Software & Services Software NMS
|
||||
symbol name country sector industry group industry exchange
|
||||
0 MSFT Microsoft Corporation United States Information Technology Software & Services Software NMS
|
||||
|
||||
Reference in New Issue
Block a user