mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
More Options Tradier Fixes (#2309)
* Added features * Fixed tests Co-authored-by: James Maslek <jmaslek11@gmail.com>
This commit is contained in:
@@ -43,7 +43,10 @@ def get_option_history(ticker: str, date: str, call: bool, price: str) -> pd.Dat
|
||||
data = requests.get(url, headers={"User-Agent": get_user_agent()}).content
|
||||
soup = BeautifulSoup(data, "html.parser")
|
||||
table = soup.find("div", attrs={"style": "display: table; font-size: 0.9em; "})
|
||||
rows = table.find_all("div", attrs={"style": "display: table-row;"})
|
||||
if table:
|
||||
rows = table.find_all("div", attrs={"style": "display: table-row;"})
|
||||
else:
|
||||
return pd.DataFrame()
|
||||
clean_rows = []
|
||||
|
||||
if rows:
|
||||
|
||||
@@ -17,7 +17,7 @@ from openbb_terminal.helper_funcs import (
|
||||
)
|
||||
from openbb_terminal.stocks.options import chartexchange_model
|
||||
from openbb_terminal.config_terminal import theme
|
||||
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.helper_funcs import (
|
||||
plot_autoscale,
|
||||
lambda_long_number_format_y_axis,
|
||||
@@ -55,6 +55,9 @@ def display_raw(
|
||||
"""
|
||||
|
||||
df = chartexchange_model.get_option_history(ticker, date, call, price)[::-1]
|
||||
if df.empty:
|
||||
console.print("[red]No data found[/red]\n")
|
||||
return
|
||||
df["Date"] = pd.to_datetime(df["Date"])
|
||||
df = df.set_index("Date")
|
||||
|
||||
|
||||
@@ -545,9 +545,15 @@ class OptionsController(BaseController):
|
||||
console.print("")
|
||||
|
||||
if self.ticker and self.selected_date:
|
||||
self.chain = yfinance_model.get_option_chain(
|
||||
self.ticker, self.selected_date
|
||||
)
|
||||
try:
|
||||
self.chain = yfinance_model.get_option_chain(
|
||||
self.ticker, self.selected_date
|
||||
)
|
||||
except ValueError:
|
||||
console.print(
|
||||
f"[red]{self.ticker} does not have expiration"
|
||||
f" {self.selected_date}.[/red]"
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def call_exp(self, other_args: List[str]):
|
||||
@@ -679,7 +685,10 @@ class OptionsController(BaseController):
|
||||
)
|
||||
|
||||
else:
|
||||
if TRADIER_TOKEN != "REPLACE_ME": # nosec
|
||||
if (
|
||||
TRADIER_TOKEN != "REPLACE_ME"
|
||||
or self.source == "tradier"
|
||||
): # nosec
|
||||
tradier_view.display_historical(
|
||||
ticker=self.ticker,
|
||||
expiry=self.selected_date,
|
||||
@@ -835,7 +844,7 @@ class OptionsController(BaseController):
|
||||
if (
|
||||
ns_parser.source == "tradier"
|
||||
and TRADIER_TOKEN != "REPLACE_ME" # nosec
|
||||
):
|
||||
) or self.source == "tradier":
|
||||
tradier_view.plot_vol(
|
||||
ticker=self.ticker,
|
||||
expiry=self.selected_date,
|
||||
@@ -904,7 +913,7 @@ class OptionsController(BaseController):
|
||||
if (
|
||||
ns_parser.source == "tradier"
|
||||
and TRADIER_TOKEN != "REPLACE_ME" # nosec
|
||||
):
|
||||
) or self.source == "tradier":
|
||||
tradier_view.plot_volume_open_interest(
|
||||
ticker=self.ticker,
|
||||
expiry=self.selected_date,
|
||||
@@ -934,7 +943,8 @@ class OptionsController(BaseController):
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="oi",
|
||||
description="Plot open interest. Open interest represents the number of contracts that exist.",
|
||||
description="""Plot open interest. Open interest represents the number of
|
||||
contracts that exist.""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-m",
|
||||
@@ -979,7 +989,7 @@ class OptionsController(BaseController):
|
||||
if (
|
||||
ns_parser.source == "tradier"
|
||||
and TRADIER_TOKEN != "REPLACE_ME" # nosec
|
||||
):
|
||||
) or self.source == "tradier":
|
||||
tradier_view.plot_oi(
|
||||
ticker=self.ticker,
|
||||
expiry=self.selected_date,
|
||||
|
||||
@@ -241,7 +241,10 @@ def last_price(ticker: str):
|
||||
},
|
||||
)
|
||||
if r.status_code == 200:
|
||||
return float(r.json()["quotes"]["quote"]["last"])
|
||||
last = r.json()["quotes"]["quote"]["last"]
|
||||
if last is None:
|
||||
return 0
|
||||
return float(last)
|
||||
else:
|
||||
console.print("Error getting last price")
|
||||
return None
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
"""Tradier options view"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import warnings
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
from bisect import bisect_left
|
||||
from typing import List, Optional
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import mplfinance as mpf
|
||||
@@ -31,6 +32,28 @@ from openbb_terminal import rich_config
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
column_map = {"mid_iv": "iv", "open_interest": "oi", "volume": "vol"}
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
def get_strike_bounds(
|
||||
options: pd.DataFrame, current_price: float, min_sp: float, max_sp: float
|
||||
) -> Tuple[float, float]:
|
||||
if min_sp == -1:
|
||||
if current_price == 0:
|
||||
min_strike = options["strike"].iat[0]
|
||||
else:
|
||||
min_strike = 0.75 * current_price
|
||||
else:
|
||||
min_strike = min_sp
|
||||
|
||||
if max_sp == -1:
|
||||
if current_price == 0:
|
||||
max_strike = options["strike"].iat[-1]
|
||||
else:
|
||||
max_strike = 1.25 * current_price
|
||||
else:
|
||||
max_strike = max_sp
|
||||
return min_strike, max_strike
|
||||
|
||||
|
||||
def lambda_red_highlight(val) -> str:
|
||||
@@ -145,15 +168,7 @@ def display_chains(
|
||||
columns = to_display + ["strike", "option_type"]
|
||||
chains_df = chains_df[columns].rename(columns=column_map)
|
||||
|
||||
if min_sp == -1:
|
||||
min_strike = np.percentile(chains_df["strike"], 25)
|
||||
else:
|
||||
min_strike = min_sp
|
||||
|
||||
if max_sp == -1:
|
||||
max_strike = np.percentile(chains_df["strike"], 75)
|
||||
else:
|
||||
max_strike = max_sp
|
||||
min_strike, max_strike = get_strike_bounds(chains_df, 0, min_sp, max_sp)
|
||||
|
||||
chains_df = chains_df[chains_df["strike"] >= min_strike]
|
||||
chains_df = chains_df[chains_df["strike"] <= max_strike]
|
||||
@@ -245,15 +260,11 @@ def plot_oi(
|
||||
options = tradier_model.get_option_chains(ticker, expiry)
|
||||
current_price = tradier_model.last_price(ticker)
|
||||
|
||||
if min_sp == -1:
|
||||
min_strike = 0.75 * current_price
|
||||
else:
|
||||
min_strike = min_sp
|
||||
min_strike, max_strike = get_strike_bounds(options, current_price, min_sp, max_sp)
|
||||
|
||||
if max_sp == -1:
|
||||
max_strike = 1.25 * current_price
|
||||
else:
|
||||
max_strike = max_sp
|
||||
if max_strike == min_strike:
|
||||
console.print("[red]Not enough data for analysis[/red]\n")
|
||||
return
|
||||
|
||||
if calls_only and puts_only:
|
||||
console.print("Both flags selected, please select one", "\n")
|
||||
@@ -340,15 +351,7 @@ def plot_vol(
|
||||
options = tradier_model.get_option_chains(ticker, expiry)
|
||||
current_price = tradier_model.last_price(ticker)
|
||||
|
||||
if min_sp == -1:
|
||||
min_strike = 0.75 * current_price
|
||||
else:
|
||||
min_strike = min_sp
|
||||
|
||||
if max_sp == -1:
|
||||
max_strike = 1.25 * current_price
|
||||
else:
|
||||
max_strike = max_sp
|
||||
min_strike, max_strike = get_strike_bounds(options, current_price, min_sp, max_sp)
|
||||
|
||||
if calls_only and puts_only:
|
||||
console.print("Both flags selected, please select one", "\n")
|
||||
|
||||
@@ -1,23 +1,45 @@
|
||||
vol_x strike vol_y
|
||||
0 [green]0[/green] 148.0 [red]15[/red]
|
||||
1 [green]0[/green] 149.0 [red]11[/red]
|
||||
2 [green]144[/green] 150.0 [red]375[/red]
|
||||
3 [green]1[/green] 152.5 [red]82[/red]
|
||||
4 [green]3[/green] 155.0 [red]745[/red]
|
||||
5 [green]1[/green] 157.5 [red]291[/red]
|
||||
6 [green]158[/green] 160.0 [red]1204[/red]
|
||||
7 [green]36[/green] 162.5 [red]747[/red]
|
||||
8 [green]140[/green] 165.0 [red]1968[/red]
|
||||
9 [green]82[/green] 167.5 [red]2392[/red]
|
||||
10 [green]439[/green] 170.0 [red]2361[/red]
|
||||
11 [green]1043[/green] 172.5 [red]1860[/red]
|
||||
12 [green]4640[/green] 175.0 [red]1046[/red]
|
||||
13 [green]1442[/green] 177.5 [red]80[/red]
|
||||
14 [green]5482[/green] 180.0 [red]158[/red]
|
||||
15 [green]1218[/green] 182.5 [red]25[/red]
|
||||
16 [green]2680[/green] 185.0 [red]20[/red]
|
||||
17 [green]385[/green] 187.5 [red]1[/red]
|
||||
18 [green]519[/green] 190.0 [red]1[/red]
|
||||
19 [green]875[/green] 192.5 [red]0[/red]
|
||||
20 [green]394[/green] 195.0 [red]1[/red]
|
||||
21 [green]19[/green] 197.5 [red]0[/red]
|
||||
0 [green]0[/green] 105.0 [red]370[/red]
|
||||
1 [green]0[/green] 110.0 [red]0[/red]
|
||||
2 [green]0[/green] 115.0 [red]9[/red]
|
||||
3 [green]0[/green] 120.0 [red]921[/red]
|
||||
4 [green]0[/green] 125.0 [red]28[/red]
|
||||
5 [green]0[/green] 130.0 [red]146[/red]
|
||||
6 [green]0[/green] 135.0 [red]33[/red]
|
||||
7 [green]4[/green] 140.0 [red]125[/red]
|
||||
8 [green]2[/green] 145.0 [red]203[/red]
|
||||
9 [green]20[/green] 146.0 [red]21[/red]
|
||||
10 [green]0[/green] 147.0 [red]5[/red]
|
||||
11 [green]0[/green] 148.0 [red]15[/red]
|
||||
12 [green]0[/green] 149.0 [red]11[/red]
|
||||
13 [green]144[/green] 150.0 [red]375[/red]
|
||||
14 [green]1[/green] 152.5 [red]82[/red]
|
||||
15 [green]3[/green] 155.0 [red]745[/red]
|
||||
16 [green]1[/green] 157.5 [red]291[/red]
|
||||
17 [green]158[/green] 160.0 [red]1204[/red]
|
||||
18 [green]36[/green] 162.5 [red]747[/red]
|
||||
19 [green]140[/green] 165.0 [red]1968[/red]
|
||||
20 [green]82[/green] 167.5 [red]2392[/red]
|
||||
21 [green]439[/green] 170.0 [red]2361[/red]
|
||||
22 [green]1043[/green] 172.5 [red]1860[/red]
|
||||
23 [green]4640[/green] 175.0 [red]1046[/red]
|
||||
24 [green]1442[/green] 177.5 [red]80[/red]
|
||||
25 [green]5482[/green] 180.0 [red]158[/red]
|
||||
26 [green]1218[/green] 182.5 [red]25[/red]
|
||||
27 [green]2680[/green] 185.0 [red]20[/red]
|
||||
28 [green]385[/green] 187.5 [red]1[/red]
|
||||
29 [green]519[/green] 190.0 [red]1[/red]
|
||||
30 [green]875[/green] 192.5 [red]0[/red]
|
||||
31 [green]394[/green] 195.0 [red]1[/red]
|
||||
32 [green]19[/green] 197.5 [red]0[/red]
|
||||
33 [green]202[/green] 200.0 [red]0[/red]
|
||||
34 [green]46[/green] 205.0 [red]0[/red]
|
||||
35 [green]315[/green] 210.0 [red]0[/red]
|
||||
36 [green]0[/green] 215.0 [red]0[/red]
|
||||
37 [green]7[/green] 220.0 [red]0[/red]
|
||||
38 [green]1[/green] 225.0 [red]0[/red]
|
||||
39 [green]0[/green] 230.0 [red]0[/red]
|
||||
40 [green]0[/green] 235.0 [red]0[/red]
|
||||
41 [green]164[/green] 240.0 [red]0[/red]
|
||||
42 [green]21[/green] 245.0 [red]0[/red]
|
||||
43 [green]1[/green] 250.0 [red]0[/red]
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
vol strike
|
||||
0 370 105.0
|
||||
2 0 110.0
|
||||
4 9 115.0
|
||||
6 921 120.0
|
||||
8 28 125.0
|
||||
10 146 130.0
|
||||
12 33 135.0
|
||||
14 125 140.0
|
||||
16 203 145.0
|
||||
19 21 146.0
|
||||
20 5 147.0
|
||||
22 15 148.0
|
||||
24 11 149.0
|
||||
26 375 150.0
|
||||
@@ -21,3 +32,14 @@
|
||||
61 0 192.5
|
||||
62 1 195.0
|
||||
65 0 197.5
|
||||
66 0 200.0
|
||||
68 0 205.0
|
||||
70 0 210.0
|
||||
72 0 215.0
|
||||
74 0 220.0
|
||||
77 0 225.0
|
||||
78 0 230.0
|
||||
80 0 235.0
|
||||
82 0 240.0
|
||||
84 0 245.0
|
||||
86 0 250.0
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
vol strike
|
||||
1 0 105.0
|
||||
3 0 110.0
|
||||
5 0 115.0
|
||||
7 0 120.0
|
||||
9 0 125.0
|
||||
11 0 130.0
|
||||
13 0 135.0
|
||||
15 4 140.0
|
||||
17 2 145.0
|
||||
18 20 146.0
|
||||
21 0 147.0
|
||||
23 0 148.0
|
||||
25 0 149.0
|
||||
27 144 150.0
|
||||
@@ -21,3 +32,14 @@
|
||||
60 875 192.5
|
||||
63 394 195.0
|
||||
64 19 197.5
|
||||
67 202 200.0
|
||||
69 46 205.0
|
||||
71 315 210.0
|
||||
73 0 215.0
|
||||
75 7 220.0
|
||||
76 1 225.0
|
||||
79 0 230.0
|
||||
81 0 235.0
|
||||
83 164 240.0
|
||||
85 21 245.0
|
||||
87 1 250.0
|
||||
|
||||
Reference in New Issue
Block a user