mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
Add nasdaq as an options source (#2397)
* Get all nasdaq chains * Get all expirations * Add chain by expiry and clean up columns * add nasdaq to load and exp * Add OI plot for nasdaq * add volume plot * Update vol + oi to have nasdaq + raw flag * Add VOI functionality with nasdaq * Add nasdaq chains function * Run isort * doesnt * Change menu for sources and edit yfinance to expiration instead of expiry * lint * oops * unused imports Co-authored-by: DidierRLopes <dro.lopes@campus.fct.unl.pt>
This commit is contained in:
18
data_sources_default.json
vendored
18
data_sources_default.json
vendored
@@ -39,7 +39,8 @@
|
||||
"options": {
|
||||
"load": [
|
||||
"yf",
|
||||
"tradier"
|
||||
"tradier",
|
||||
"nasdaq"
|
||||
],
|
||||
"hist": [
|
||||
"chartexchange",
|
||||
@@ -47,19 +48,26 @@
|
||||
],
|
||||
"vol": [
|
||||
"yf",
|
||||
"tradier"
|
||||
"tradier",
|
||||
"nasdaq"
|
||||
],
|
||||
"voi": [
|
||||
"yf",
|
||||
"tradier"
|
||||
"tradier",
|
||||
"nasdaq"
|
||||
],
|
||||
"oi": [
|
||||
"yf",
|
||||
"tradier"
|
||||
"tradier",
|
||||
"nasdaq"
|
||||
],
|
||||
"chains": [
|
||||
"yf",
|
||||
"tradier"
|
||||
"tradier",
|
||||
"nasdaq"
|
||||
],
|
||||
"greeks": [
|
||||
"yf"
|
||||
]
|
||||
},
|
||||
"disc": {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
"""AlphaQuery View"""
|
||||
__docforma__ = "numpy"
|
||||
|
||||
from typing import Optional, List
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.config_plot import PLOT_DPI
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
export_data,
|
||||
plot_autoscale,
|
||||
is_valid_axes_count,
|
||||
plot_autoscale,
|
||||
)
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.stocks.options import alphaquery_model
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import logging
|
||||
from typing import Dict, Optional, List
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.config_plot import PLOT_DPI
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import plot_autoscale, is_valid_axes_count
|
||||
from openbb_terminal.helper_funcs import is_valid_axes_count, plot_autoscale
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.stocks.options import calculator_model
|
||||
|
||||
|
||||
@@ -3,25 +3,23 @@ __docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import Optional, List
|
||||
from typing import List, Optional
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import mplfinance as mpf
|
||||
import pandas as pd
|
||||
|
||||
import mplfinance as mpf
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
export_data,
|
||||
print_rich_table,
|
||||
is_valid_axes_count,
|
||||
)
|
||||
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,
|
||||
plot_autoscale,
|
||||
print_rich_table,
|
||||
)
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.stocks.options import chartexchange_model
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -11,19 +11,13 @@ from prompt_toolkit.completion import NestedCompleter
|
||||
|
||||
from openbb_terminal import feature_flags as obbff
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
check_non_negative,
|
||||
print_rich_table,
|
||||
)
|
||||
from openbb_terminal.helper_funcs import check_non_negative, print_rich_table
|
||||
from openbb_terminal.menu import session
|
||||
from openbb_terminal.parent_classes import BaseController
|
||||
from openbb_terminal.rich_config import console, MenuText
|
||||
from openbb_terminal.rich_config import MenuText, console
|
||||
from openbb_terminal.stocks.options.hedge import hedge_view
|
||||
from openbb_terminal.stocks.options.hedge.hedge_model import add_hedge_option
|
||||
from openbb_terminal.stocks.options.yfinance_model import (
|
||||
get_option_chain,
|
||||
get_price,
|
||||
)
|
||||
from openbb_terminal.stocks.options.yfinance_model import get_option_chain, get_price
|
||||
from openbb_terminal.stocks.options.yfinance_view import plot_payoff
|
||||
|
||||
# pylint: disable=R0902
|
||||
|
||||
@@ -5,9 +5,7 @@ import logging
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from openbb_terminal.helper_funcs import (
|
||||
print_rich_table,
|
||||
)
|
||||
from openbb_terminal.helper_funcs import print_rich_table
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.stocks.options.hedge import hedge_model
|
||||
|
||||
|
||||
230
openbb_terminal/stocks/options/nasdaq_model.py
Normal file
230
openbb_terminal/stocks/options/nasdaq_model.py
Normal file
@@ -0,0 +1,230 @@
|
||||
"""Nasdaq Model"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import requests
|
||||
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.rich_config import console
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_full_chain(symbol: str) -> pd.DataFrame:
|
||||
"""Get the full option chain for symbol over all expirations
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Symbol to get options for. Can be a stock, etf or index.
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Dataframe of option chain
|
||||
"""
|
||||
# Nasdaq requires an asset code, so instead of making user supply one, just loop through all
|
||||
for asset in ["stocks", "index", "etf"]:
|
||||
url = (
|
||||
f"https://api.nasdaq.com/api/quote/{symbol}/option-chain?assetclass={asset}&"
|
||||
"fromdate=2010-09-09&todate=2030-09-09&excode=oprac&callput=callput&money=all&type=all"
|
||||
)
|
||||
# I have had issues with nasdaq requests, and this user agent seems to work in US and EU
|
||||
response_json = requests.get(
|
||||
url,
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
|
||||
" AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15"
|
||||
},
|
||||
).json()
|
||||
if response_json["status"]["rCode"] == 200:
|
||||
df = pd.DataFrame(response_json["data"]["table"]["rows"]).drop(
|
||||
columns=["c_colour", "p_colour", "drillDownURL"]
|
||||
)
|
||||
df["expirygroup"] = (
|
||||
df["expirygroup"].replace("", np.nan).fillna(method="ffill")
|
||||
)
|
||||
# Make numeric
|
||||
df = (
|
||||
df.fillna(np.nan)
|
||||
.dropna(axis=0)
|
||||
.replace("--", 0)
|
||||
.astype(
|
||||
{
|
||||
"c_Last": float,
|
||||
"c_Change": float,
|
||||
"c_Bid": float,
|
||||
"c_Ask": float,
|
||||
"c_Volume": int,
|
||||
"c_Openinterest": int,
|
||||
"strike": float,
|
||||
"p_Last": float,
|
||||
"p_Change": float,
|
||||
"p_Bid": float,
|
||||
"p_Ask": float,
|
||||
"p_Volume": int,
|
||||
"p_Openinterest": int,
|
||||
}
|
||||
)
|
||||
)
|
||||
return df
|
||||
|
||||
console.print(f"[red]{symbol} Option Chain not found.[/red]\n")
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_expirations(symbol: str) -> List[str]:
|
||||
"""Get available expirations
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol
|
||||
|
||||
Returns
|
||||
-------
|
||||
List[str]
|
||||
List of expiration dates
|
||||
"""
|
||||
df = get_full_chain(symbol)
|
||||
if df.empty:
|
||||
return []
|
||||
# get everything that is not an empty string
|
||||
exps = [exp for exp in list(df.expirygroup.unique()) if exp]
|
||||
# Convert 'January 11, 1993' into '1993-01-11'
|
||||
return [datetime.strptime(exp, "%B %d, %Y").strftime("%Y-%m-%d") for exp in exps]
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_chain_given_expiration(symbol: str, expiration: str) -> pd.DataFrame:
|
||||
"""Get option chain for symbol at a given expiration
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Symbol to get chain for
|
||||
expiration
|
||||
Expiration to get chain for
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Dataframe of option chain
|
||||
"""
|
||||
for asset in ["stocks", "index", "etf"]:
|
||||
url = (
|
||||
f"https://api.nasdaq.com/api/quote/{symbol}/option-chain?assetclass={asset}&"
|
||||
f"fromdate={expiration}&todate={expiration}&excode=oprac&callput=callput&money=all&type=all"
|
||||
)
|
||||
|
||||
response_json = requests.get(
|
||||
url,
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
|
||||
" AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15"
|
||||
},
|
||||
).json()
|
||||
if response_json["status"]["rCode"] == 200:
|
||||
df = (
|
||||
pd.DataFrame(response_json["data"]["table"]["rows"])
|
||||
.drop(columns=["c_colour", "p_colour", "drillDownURL", "expirygroup"])
|
||||
.fillna(np.nan)
|
||||
.dropna(axis=0)
|
||||
)
|
||||
# Make numeric
|
||||
df = df.replace("--", 0).astype(
|
||||
{
|
||||
"c_Last": float,
|
||||
"c_Change": float,
|
||||
"c_Bid": float,
|
||||
"c_Ask": float,
|
||||
"c_Volume": int,
|
||||
"c_Openinterest": int,
|
||||
"strike": float,
|
||||
"p_Last": float,
|
||||
"p_Change": float,
|
||||
"p_Bid": float,
|
||||
"p_Ask": float,
|
||||
"p_Volume": int,
|
||||
"p_Openinterest": int,
|
||||
}
|
||||
)
|
||||
return df
|
||||
|
||||
console.print(f"[red]{symbol} Option Chain not found.[/red]\n")
|
||||
return pd.DataFrame()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def get_last_price(symbol: str) -> float:
|
||||
"""Get the last price from nasdaq
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Symbol to get quote for
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Last price
|
||||
"""
|
||||
for asset in ["stocks", "index", "etf"]:
|
||||
url = f"https://api.nasdaq.com/api/quote/{symbol}/info?assetclass={asset}"
|
||||
response_json = requests.get(
|
||||
url,
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
|
||||
" AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15"
|
||||
},
|
||||
).json()
|
||||
if response_json["status"]["rCode"] == 200:
|
||||
return float(
|
||||
response_json["data"]["primaryData"]["lastSalePrice"]
|
||||
.strip("$")
|
||||
.replace(",", "")
|
||||
)
|
||||
console.print(f"[red]Last price for {symbol} not found[/red]\n")
|
||||
return np.nan
|
||||
|
||||
|
||||
# Ugh this doesn't get the full chain
|
||||
# TODO: apply CRR binomial tree to backtrack IV for greeks
|
||||
@log_start_end(log=logger)
|
||||
def get_option_greeks(symbol: str, expiration: str) -> pd.DataFrame:
|
||||
"""Get option greeks from nasdaq
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Symbol to get
|
||||
expiration: str
|
||||
Option expiration
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Dataframe with option greeks
|
||||
"""
|
||||
for asset in ["stocks", "index", "etf"]:
|
||||
url_greeks = f"https://api.nasdaq.com/api/quote/{symbol}/option-chain/greeks?assetclass={asset}&date={expiration}"
|
||||
response_json = requests.get(
|
||||
url_greeks,
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
|
||||
" AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15"
|
||||
},
|
||||
).json()
|
||||
if response_json["status"]["rCode"] == 200:
|
||||
|
||||
greeks = pd.DataFrame(response_json["data"]["table"]["rows"])
|
||||
greeks = greeks.drop(columns="url")
|
||||
return greeks
|
||||
|
||||
console.print(f"[red]Greeks not found for {symbol} on {expiration}[/red].")
|
||||
return pd.DataFrame()
|
||||
333
openbb_terminal/stocks/options/nasdaq_view.py
Normal file
333
openbb_terminal/stocks/options/nasdaq_view.py
Normal file
@@ -0,0 +1,333 @@
|
||||
"""Nasdaq View"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import List, Optional
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
import openbb_terminal.config_plot as cfp
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
export_data,
|
||||
is_valid_axes_count,
|
||||
plot_autoscale,
|
||||
print_rich_table,
|
||||
)
|
||||
from openbb_terminal.stocks.options import nasdaq_model
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_oi(
|
||||
symbol: str,
|
||||
expiration: str,
|
||||
min_sp: float = -1,
|
||||
max_sp: float = -1,
|
||||
raw: bool = False,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Plot open interest
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Ticker symbol
|
||||
expiration: str
|
||||
Expiry date for options
|
||||
min_sp: float
|
||||
Min strike to consider
|
||||
max_sp: float
|
||||
Max strike to consider
|
||||
raw: bool
|
||||
Flag to display raw data
|
||||
export: str
|
||||
Format to export file
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
option_chain = nasdaq_model.get_chain_given_expiration(symbol, expiration)
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"oi_nasdaq",
|
||||
option_chain,
|
||||
)
|
||||
current_price = nasdaq_model.get_last_price(symbol)
|
||||
|
||||
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
|
||||
|
||||
if external_axes is None:
|
||||
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=cfp.PLOT_DPI)
|
||||
elif is_valid_axes_count(external_axes, 1):
|
||||
(ax,) = external_axes
|
||||
else:
|
||||
return
|
||||
ax.plot(
|
||||
option_chain.strike,
|
||||
option_chain["c_Openinterest"] / 1000,
|
||||
ls="-",
|
||||
marker="o",
|
||||
label="Calls",
|
||||
)
|
||||
ax.plot(
|
||||
option_chain.strike,
|
||||
option_chain["p_Openinterest"] / 1000,
|
||||
ls="-",
|
||||
marker="o",
|
||||
label="Puts",
|
||||
)
|
||||
|
||||
ax.axvline(current_price, lw=2, ls="--", label="Current Price", alpha=0.7)
|
||||
ax.set_xlabel("Strike Price")
|
||||
ax.set_ylabel("Open Interest (1k) ")
|
||||
ax.set_xlim(min_strike, max_strike)
|
||||
ax.legend(loc="best")
|
||||
ax.set_title(f"Open Interest for {symbol.upper()} expiring {expiration}")
|
||||
|
||||
theme.style_primary_axis(ax)
|
||||
if external_axes is None:
|
||||
theme.visualize_output()
|
||||
|
||||
if raw:
|
||||
to_print = option_chain[["c_Openinterest", "strike", "p_Openinterest"]]
|
||||
|
||||
print_rich_table(
|
||||
to_print[(to_print.strike < max_strike) & (to_print.strike > min_strike)],
|
||||
headers=to_print.columns,
|
||||
title=f"Open Interest for {symbol} expiring on {expiration}.",
|
||||
)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_volume(
|
||||
symbol: str,
|
||||
expiration: str,
|
||||
min_sp: float = -1,
|
||||
max_sp: float = -1,
|
||||
raw: bool = False,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Plot volume
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Ticker symbol
|
||||
expiration: str
|
||||
Expiry date for options
|
||||
min_sp: float
|
||||
Min strike to consider
|
||||
max_sp: float
|
||||
Max strike to consider
|
||||
raw:bool
|
||||
Flag to display raw data
|
||||
export: str
|
||||
Format to export file
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
option_chain = nasdaq_model.get_chain_given_expiration(symbol, expiration)
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"oi_nasdaq",
|
||||
option_chain,
|
||||
)
|
||||
current_price = nasdaq_model.get_last_price(symbol)
|
||||
|
||||
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
|
||||
|
||||
if external_axes is None:
|
||||
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=cfp.PLOT_DPI)
|
||||
elif is_valid_axes_count(external_axes, 1):
|
||||
(ax,) = external_axes
|
||||
else:
|
||||
return
|
||||
ax.plot(
|
||||
option_chain.strike,
|
||||
option_chain["c_Volume"] / 1000,
|
||||
ls="-",
|
||||
marker="o",
|
||||
label="Calls",
|
||||
)
|
||||
ax.plot(
|
||||
option_chain.strike,
|
||||
option_chain["p_Volume"] / 1000,
|
||||
ls="-",
|
||||
marker="o",
|
||||
label="Puts",
|
||||
)
|
||||
|
||||
ax.axvline(current_price, lw=2, ls="--", label="Current Price", alpha=0.7)
|
||||
ax.set_xlabel("Strike Price")
|
||||
ax.set_ylabel("Volume (1k) ")
|
||||
ax.set_xlim(min_strike, max_strike)
|
||||
ax.legend(loc="best")
|
||||
ax.set_title(f"Volume for {symbol.upper()} expiring {expiration}")
|
||||
|
||||
theme.style_primary_axis(ax)
|
||||
if external_axes is None:
|
||||
theme.visualize_output()
|
||||
|
||||
if raw:
|
||||
to_print = option_chain[["c_Volume", "strike", "p_Volume"]]
|
||||
|
||||
print_rich_table(
|
||||
to_print[(to_print.strike < max_strike) & (to_print.strike > min_strike)],
|
||||
headers=to_print.columns,
|
||||
title=f"Volume for {symbol} expiring on {expiration}.",
|
||||
)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_volume_and_oi(
|
||||
symbol: str,
|
||||
expiration: str,
|
||||
min_sp: float = -1,
|
||||
max_sp: float = -1,
|
||||
raw: bool = False,
|
||||
export: str = "",
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
):
|
||||
"""Plot volume and open interest
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Ticker symbol
|
||||
expiration: str
|
||||
Expiry date for options
|
||||
min_sp: float
|
||||
Min strike to consider
|
||||
max_sp: float
|
||||
Max strike to consider
|
||||
raw:bool
|
||||
Flag to display raw data
|
||||
export: str
|
||||
Format to export file
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
option_chain = nasdaq_model.get_chain_given_expiration(symbol, expiration)
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"voi_nasdaq",
|
||||
option_chain,
|
||||
)
|
||||
current_price = nasdaq_model.get_last_price(symbol)
|
||||
|
||||
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
|
||||
|
||||
if raw:
|
||||
to_print = option_chain[
|
||||
["c_Openinterest", "c_Volume", "strike", "p_Volume", "p_Openinterest"]
|
||||
]
|
||||
|
||||
print_rich_table(
|
||||
to_print[(to_print.strike < max_strike) & (to_print.strike > min_strike)],
|
||||
headers=to_print.columns,
|
||||
title=f"Volume and Open Interest for {symbol} expiring on {expiration}.",
|
||||
)
|
||||
|
||||
option_chain = option_chain.copy()[
|
||||
["c_Volume", "c_Openinterest", "strike", "p_Openinterest", "p_Volume"]
|
||||
]
|
||||
option_chain[["p_Openinterest", "p_Volume"]] = (
|
||||
option_chain[["p_Openinterest", "p_Volume"]] * -1 / 1000
|
||||
)
|
||||
option_chain[["c_Openinterest", "c_Volume"]] = (
|
||||
option_chain[["c_Openinterest", "c_Volume"]] / 1000
|
||||
)
|
||||
|
||||
if external_axes is None:
|
||||
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=cfp.PLOT_DPI)
|
||||
elif is_valid_axes_count(external_axes, 1):
|
||||
(ax,) = external_axes
|
||||
else:
|
||||
return
|
||||
|
||||
ax.bar(
|
||||
option_chain.strike,
|
||||
option_chain.c_Openinterest,
|
||||
color="green",
|
||||
label="Calls: OI",
|
||||
)
|
||||
ax.bar(
|
||||
option_chain.strike,
|
||||
option_chain.c_Volume,
|
||||
color="lightgreen",
|
||||
label="Calls: Vol",
|
||||
)
|
||||
|
||||
ax.bar(
|
||||
option_chain.strike, option_chain.p_Openinterest, color="red", label="Puts: OI"
|
||||
)
|
||||
ax.bar(option_chain.strike, option_chain.p_Volume, color="pink", label="Puts:Vol")
|
||||
|
||||
ax.axvline(
|
||||
current_price, lw=2, ls="--", label=f"Current Price: {current_price}", alpha=0.7
|
||||
)
|
||||
ax.set_xlabel("Strike Price")
|
||||
ax.set_ylabel("Volume or OI (1k)")
|
||||
ax.set_xlim(min_strike, max_strike)
|
||||
ax.legend(loc="best")
|
||||
ax.set_title(f"Volume and Open Interest for {symbol.upper()} expiring {expiration}")
|
||||
|
||||
theme.style_primary_axis(ax)
|
||||
if external_axes is None:
|
||||
theme.visualize_output()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_chains(symbol: str, expiration: str, export: str = ""):
|
||||
"""Display option chain for given expiration
|
||||
|
||||
Parameters
|
||||
----------
|
||||
symbol: str
|
||||
Ticker symbol
|
||||
expiration: str
|
||||
Expiry date for options
|
||||
export: str
|
||||
Format to export data
|
||||
"""
|
||||
option_chain = nasdaq_model.get_chain_given_expiration(symbol, expiration)
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"chain_nasdaq",
|
||||
option_chain,
|
||||
)
|
||||
|
||||
print_rich_table(option_chain, headers=option_chain.columns)
|
||||
@@ -1,8 +1,9 @@
|
||||
"""Option helper functions"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
from math import log, e
|
||||
from math import e, log
|
||||
from typing import Union
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from scipy.stats import norm
|
||||
@@ -131,9 +132,23 @@ opt_chain_cols = {
|
||||
|
||||
# pylint: disable=R0903
|
||||
class Chain:
|
||||
def __init__(self, df: pd.DataFrame):
|
||||
self.calls = df[df["option_type"] == "call"]
|
||||
self.puts = df[df["option_type"] == "put"]
|
||||
def __init__(self, df: pd.DataFrame, source: str = "tradier"):
|
||||
if source == "tradier":
|
||||
self.calls = df[df["option_type"] == "call"]
|
||||
self.puts = df[df["option_type"] == "put"]
|
||||
elif source == "nasdaq":
|
||||
# These guys have different column names
|
||||
call_columns = ["expiryDate", "strike"] + [
|
||||
col for col in df.columns if col.startswith("c_")
|
||||
]
|
||||
put_columns = ["expiryDate", "strike"] + [
|
||||
col for col in df.columns if col.startswith("p_")
|
||||
]
|
||||
self.calls = df[call_columns]
|
||||
self.puts = df[put_columns]
|
||||
else:
|
||||
self.calls = None
|
||||
self.puts = None
|
||||
|
||||
|
||||
class Option:
|
||||
|
||||
@@ -1,31 +1,38 @@
|
||||
"""Options API."""
|
||||
import os
|
||||
from openbb_terminal.helper_classes import ModelsNamespace as _models
|
||||
|
||||
# flake8: noqa
|
||||
# pylint: disable=unused-import
|
||||
|
||||
# Menu commands
|
||||
from .calculator_view import view_calculator as calc
|
||||
from .fdscanner_view import display_options as unu
|
||||
|
||||
import os
|
||||
|
||||
from openbb_terminal.helper_classes import ModelsNamespace as _models
|
||||
|
||||
from .alphaquery_view import display_put_call_ratio as pcr
|
||||
from .barchart_view import print_options_data as info
|
||||
from .screen.syncretism_view import view_historical_greeks as grhist
|
||||
|
||||
# Menu commands
|
||||
from .calculator_view import view_calculator as calc
|
||||
from .chartexchange_view import display_raw as hist_ce
|
||||
from .tradier_view import display_historical as hist_tr
|
||||
from .fdscanner_view import display_options as unu
|
||||
from .screen.syncretism_view import view_historical_greeks as grhist
|
||||
from .tradier_view import display_chains as chains
|
||||
from .tradier_view import plot_vol as vol_tr
|
||||
from .yfinance_view import plot_vol as vol_yf
|
||||
from .tradier_view import plot_volume_open_interest as voi_tr
|
||||
from .yfinance_view import plot_volume_open_interest as voi_yf
|
||||
from .tradier_view import plot_oi as oi_tr
|
||||
from .tradier_view import display_expirations as exp
|
||||
from .tradier_view import display_historical as hist_tr
|
||||
from .tradier_view import plot_oi as oi_tr
|
||||
from .tradier_view import plot_vol as vol_tr
|
||||
from .tradier_view import plot_volume_open_interest as voi_tr
|
||||
from .yfinance_view import display_vol_surface as vsurf
|
||||
from .yfinance_view import plot_oi as oi_yf
|
||||
from .yfinance_view import plot_plot as plot
|
||||
from .yfinance_view import show_parity as parity
|
||||
from .yfinance_view import plot_vol as vol_yf
|
||||
from .yfinance_view import plot_volume_open_interest as voi_yf
|
||||
from .yfinance_view import show_binom as binom
|
||||
from .yfinance_view import show_greeks as greeks
|
||||
from .yfinance_view import display_vol_surface as vsurf
|
||||
from .yfinance_view import show_parity as parity
|
||||
|
||||
# flake8: noqa
|
||||
# pylint: disable=unused-import
|
||||
|
||||
|
||||
# Models
|
||||
|
||||
@@ -5,7 +5,7 @@ import argparse
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Any
|
||||
from typing import Any, List
|
||||
|
||||
import pandas as pd
|
||||
from prompt_toolkit.completion import NestedCompleter
|
||||
@@ -17,8 +17,8 @@ from openbb_terminal.helper_funcs import (
|
||||
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
||||
EXPORT_ONLY_FIGURES_ALLOWED,
|
||||
EXPORT_ONLY_RAW_DATA_ALLOWED,
|
||||
valid_date,
|
||||
get_ordered_list_sources,
|
||||
valid_date,
|
||||
)
|
||||
from openbb_terminal.menu import session
|
||||
from openbb_terminal.parent_classes import BaseController
|
||||
@@ -29,18 +29,18 @@ from openbb_terminal.stocks.options import (
|
||||
calculator_view,
|
||||
chartexchange_view,
|
||||
fdscanner_view,
|
||||
nasdaq_model,
|
||||
nasdaq_view,
|
||||
op_helpers,
|
||||
tradier_model,
|
||||
tradier_view,
|
||||
yfinance_model,
|
||||
yfinance_view,
|
||||
op_helpers,
|
||||
)
|
||||
|
||||
from openbb_terminal.stocks.options.pricing import pricing_controller
|
||||
from openbb_terminal.stocks.options.hedge import hedge_controller
|
||||
from openbb_terminal.stocks.options.pricing import pricing_controller
|
||||
from openbb_terminal.stocks.options.screen import screener_controller, syncretism_view
|
||||
|
||||
|
||||
# pylint: disable=R1710,C0302,R0916
|
||||
|
||||
# TODO: HELP WANTED! This controller requires some MVC style refactoring
|
||||
@@ -183,10 +183,12 @@ class OptionsController(BaseController):
|
||||
mt.add_raw("\n")
|
||||
mt.add_cmd("pcr", "AlphaQuery", self.ticker and self.selected_date)
|
||||
mt.add_cmd("info", "Barchart", self.ticker and self.selected_date)
|
||||
mt.add_cmd("chains", "Tradier", self.ticker and self.selected_date)
|
||||
mt.add_cmd("oi", "Tradier/YFinance", self.ticker and self.selected_date)
|
||||
mt.add_cmd("vol", "Tradier/YFinance", self.ticker and self.selected_date)
|
||||
mt.add_cmd("voi", "Tradier/YFinance", self.ticker and self.selected_date)
|
||||
mt.add_cmd(
|
||||
"chains", "Tradier/NASDAQ/Yfinance", self.ticker and self.selected_date
|
||||
)
|
||||
mt.add_cmd("oi", "Tradier/YFinance/NASDAQ", self.ticker and self.selected_date)
|
||||
mt.add_cmd("vol", "Tradier/YFinance/NASDAQ", self.ticker and self.selected_date)
|
||||
mt.add_cmd("voi", "Tradier/YFinance/NASDAQ", self.ticker and self.selected_date)
|
||||
mt.add_cmd("hist", "Tradier", self.ticker and self.selected_date)
|
||||
mt.add_cmd("vsurf", "Yfinance", self.ticker and self.selected_date)
|
||||
mt.add_cmd("grhist", "Syncretism", self.ticker and self.selected_date)
|
||||
@@ -539,6 +541,9 @@ class OptionsController(BaseController):
|
||||
if ns_parser.source == "yf":
|
||||
self.source = "yf"
|
||||
self.expiry_dates = yfinance_model.option_expirations(self.ticker)
|
||||
elif ns_parser.source == "nasdaq":
|
||||
self.source = "nasdaq"
|
||||
self.expiry_dates = nasdaq_model.get_expirations(self.ticker)
|
||||
else:
|
||||
self.source = "tradier"
|
||||
self.expiry_dates = tradier_model.option_expirations(self.ticker)
|
||||
@@ -611,6 +616,11 @@ class OptionsController(BaseController):
|
||||
self.chain = yfinance_model.get_option_chain(
|
||||
self.ticker, self.selected_date
|
||||
)
|
||||
elif self.source == "nasdaq":
|
||||
df = nasdaq_model.get_chain_given_expiration(
|
||||
self.ticker, self.selected_date
|
||||
)
|
||||
self.chain = op_helpers.Chain(df, self.source)
|
||||
else:
|
||||
df = tradier_model.get_option_chains(
|
||||
self.ticker, self.selected_date
|
||||
@@ -776,13 +786,19 @@ class OptionsController(BaseController):
|
||||
elif ns_parser.source == "yf":
|
||||
yfinance_view.display_chains(
|
||||
symbol=self.ticker,
|
||||
expiry=self.selected_date,
|
||||
expiration=self.selected_date,
|
||||
min_sp=ns_parser.min_sp,
|
||||
max_sp=ns_parser.max_sp,
|
||||
calls_only=ns_parser.calls,
|
||||
puts_only=ns_parser.puts,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
elif ns_parser.source == "nasdaq":
|
||||
nasdaq_view.display_chains(
|
||||
symbol=self.ticker,
|
||||
expiration=self.selected_date,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
else:
|
||||
console.print("No expiry loaded. First use `exp {expiry date}`\n")
|
||||
else:
|
||||
@@ -832,7 +848,8 @@ class OptionsController(BaseController):
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
parser,
|
||||
other_args,
|
||||
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
||||
export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
||||
raw=True,
|
||||
)
|
||||
if ns_parser:
|
||||
if self.ticker:
|
||||
@@ -850,16 +867,27 @@ class OptionsController(BaseController):
|
||||
puts_only=ns_parser.puts,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
else:
|
||||
elif ns_parser.source == "yf":
|
||||
yfinance_view.plot_vol(
|
||||
symbol=self.ticker,
|
||||
expiry=self.selected_date,
|
||||
expiration=self.selected_date,
|
||||
min_sp=ns_parser.min,
|
||||
max_sp=ns_parser.max,
|
||||
calls_only=ns_parser.calls,
|
||||
puts_only=ns_parser.puts,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
elif ns_parser.source == "nasdaq":
|
||||
nasdaq_view.display_volume(
|
||||
symbol=self.ticker,
|
||||
expiration=self.selected_date,
|
||||
min_sp=ns_parser.min,
|
||||
max_sp=ns_parser.max,
|
||||
export=ns_parser.export,
|
||||
raw=ns_parser.raw,
|
||||
)
|
||||
else:
|
||||
return
|
||||
else:
|
||||
console.print("No expiry loaded. First use `exp {expiry date}`\n")
|
||||
else:
|
||||
@@ -899,9 +927,7 @@ class OptionsController(BaseController):
|
||||
help="maximum strike price to consider in the plot.",
|
||||
)
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
parser,
|
||||
other_args,
|
||||
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
||||
parser, other_args, EXPORT_BOTH_RAW_DATA_AND_FIGURES, raw=True
|
||||
)
|
||||
if ns_parser:
|
||||
if self.ticker:
|
||||
@@ -918,15 +944,26 @@ class OptionsController(BaseController):
|
||||
min_vol=ns_parser.min_vol,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
else:
|
||||
elif ns_parser.source == "yf":
|
||||
yfinance_view.plot_volume_open_interest(
|
||||
symbol=self.ticker,
|
||||
expiry=self.selected_date,
|
||||
expiration=self.selected_date,
|
||||
min_sp=ns_parser.min_sp,
|
||||
max_sp=ns_parser.max_sp,
|
||||
min_vol=ns_parser.min_vol,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
elif ns_parser.source == "nasdaq":
|
||||
nasdaq_view.display_volume_and_oi(
|
||||
symbol=self.ticker,
|
||||
expiration=self.selected_date,
|
||||
min_sp=ns_parser.min_sp,
|
||||
max_sp=ns_parser.max_sp,
|
||||
raw=ns_parser.raw,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
console.print("No expiry loaded. First use `exp {expiry date}`\n")
|
||||
else:
|
||||
@@ -977,7 +1014,8 @@ class OptionsController(BaseController):
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
parser,
|
||||
other_args,
|
||||
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
||||
raw=True,
|
||||
export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
||||
)
|
||||
if ns_parser:
|
||||
if self.ticker:
|
||||
@@ -995,16 +1033,25 @@ class OptionsController(BaseController):
|
||||
puts_only=ns_parser.puts,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
else:
|
||||
elif ns_parser.source == "yf":
|
||||
yfinance_view.plot_oi(
|
||||
symbol=self.ticker,
|
||||
expiry=self.selected_date,
|
||||
expiration=self.selected_date,
|
||||
min_sp=ns_parser.min,
|
||||
max_sp=ns_parser.max,
|
||||
calls_only=ns_parser.calls,
|
||||
puts_only=ns_parser.puts,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
elif ns_parser.source == "nasdaq":
|
||||
nasdaq_view.display_oi(
|
||||
self.ticker,
|
||||
expiration=self.selected_date,
|
||||
min_sp=ns_parser.min,
|
||||
max_sp=ns_parser.max,
|
||||
export=ns_parser.export,
|
||||
raw=ns_parser.raw,
|
||||
)
|
||||
else:
|
||||
console.print("No expiry loaded. First use `exp {expiry date}`\n")
|
||||
else:
|
||||
@@ -1165,7 +1212,8 @@ class OptionsController(BaseController):
|
||||
help="Maximum strike price to show.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a" "--all",
|
||||
"-a",
|
||||
"--all",
|
||||
dest="all",
|
||||
action="store_true",
|
||||
default=False,
|
||||
@@ -1181,17 +1229,18 @@ class OptionsController(BaseController):
|
||||
elif not self.selected_date:
|
||||
console.print("No expiry loaded. First use `exp {expiry date}`\n")
|
||||
else:
|
||||
opt_type = -1 if ns_parser.put else 1
|
||||
yfinance_view.show_greeks(
|
||||
symbol=self.ticker,
|
||||
div_cont=ns_parser.dividend,
|
||||
expiry=self.selected_date,
|
||||
rf=ns_parser.risk_free,
|
||||
opt_type=opt_type,
|
||||
mini=ns_parser.min,
|
||||
maxi=ns_parser.max,
|
||||
show_all=ns_parser.all,
|
||||
)
|
||||
if ns_parser.source == "yf":
|
||||
opt_type = -1 if ns_parser.put else 1
|
||||
yfinance_view.show_greeks(
|
||||
symbol=self.ticker,
|
||||
div_cont=ns_parser.dividend,
|
||||
expiration=self.selected_date,
|
||||
rf=ns_parser.risk_free,
|
||||
opt_type=opt_type,
|
||||
mini=ns_parser.min,
|
||||
maxi=ns_parser.max,
|
||||
show_all=ns_parser.all,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def call_parity(self, other_args: List[str]):
|
||||
|
||||
@@ -13,7 +13,7 @@ from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import print_rich_table
|
||||
from openbb_terminal.menu import session
|
||||
from openbb_terminal.parent_classes import BaseController
|
||||
from openbb_terminal.rich_config import console, MenuText
|
||||
from openbb_terminal.rich_config import MenuText, console
|
||||
from openbb_terminal.stocks.options import yfinance_view
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -10,13 +10,10 @@ from prompt_toolkit.completion import NestedCompleter
|
||||
|
||||
from openbb_terminal import feature_flags as obbff
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
EXPORT_ONLY_RAW_DATA_ALLOWED,
|
||||
check_positive,
|
||||
)
|
||||
from openbb_terminal.helper_funcs import EXPORT_ONLY_RAW_DATA_ALLOWED, check_positive
|
||||
from openbb_terminal.menu import session
|
||||
from openbb_terminal.parent_classes import BaseController
|
||||
from openbb_terminal.rich_config import console, MenuText
|
||||
from openbb_terminal.rich_config import MenuText, console
|
||||
from openbb_terminal.stocks.comparison_analysis import ca_controller
|
||||
from openbb_terminal.stocks.options.screen import syncretism_view
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@ from typing import List, Optional
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal import config_plot as cfp
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
export_data,
|
||||
is_valid_axes_count,
|
||||
plot_autoscale,
|
||||
print_rich_table,
|
||||
is_valid_axes_count,
|
||||
)
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.stocks.options.screen import syncretism_model
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Tradier options view"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import warnings
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import warnings
|
||||
from bisect import bisect_left
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
@@ -14,20 +14,20 @@ import numpy as np
|
||||
import pandas as pd
|
||||
import seaborn as sns
|
||||
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal import config_plot as cfp
|
||||
from openbb_terminal import rich_config
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
export_data,
|
||||
is_valid_axes_count,
|
||||
lambda_long_number_format_y_axis,
|
||||
patch_pandas_text_adjustment,
|
||||
plot_autoscale,
|
||||
print_rich_table,
|
||||
lambda_long_number_format_y_axis,
|
||||
is_valid_axes_count,
|
||||
)
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.stocks.options import op_helpers, tradier_model, yfinance_model
|
||||
from openbb_terminal import rich_config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
"""Yfinance options model"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import warnings
|
||||
import logging
|
||||
import math
|
||||
from datetime import datetime, date, timedelta
|
||||
import warnings
|
||||
from datetime import date, datetime, timedelta
|
||||
from typing import Any, Dict, List, Tuple
|
||||
|
||||
import pandas as pd
|
||||
import yfinance as yf
|
||||
|
||||
from openbb_terminal.stocks.options.op_helpers import Option
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import get_rf
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.stocks.options.op_helpers import Option
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ __docformat__ = "numpy"
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from bisect import bisect_left
|
||||
from datetime import date, datetime, timedelta
|
||||
import re
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import matplotlib.dates as mdates
|
||||
@@ -18,17 +18,17 @@ import yfinance as yf
|
||||
from openpyxl import Workbook
|
||||
from scipy.stats import binom
|
||||
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.config_plot import PLOT_DPI
|
||||
import openbb_terminal.config_plot as cfp
|
||||
from openbb_terminal.config_plot import PLOT_DPI
|
||||
from openbb_terminal.config_terminal import theme
|
||||
from openbb_terminal.decorators import log_start_end
|
||||
from openbb_terminal.helper_funcs import (
|
||||
excel_columns,
|
||||
export_data,
|
||||
get_rf,
|
||||
is_valid_axes_count,
|
||||
plot_autoscale,
|
||||
print_rich_table,
|
||||
is_valid_axes_count,
|
||||
)
|
||||
from openbb_terminal.rich_config import console
|
||||
from openbb_terminal.stocks.options import op_helpers, yfinance_model
|
||||
@@ -70,7 +70,7 @@ def header_fmt(header: str) -> str:
|
||||
@log_start_end(log=logger)
|
||||
def display_chains(
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
min_sp: float = 0.0,
|
||||
max_sp: float = np.inf,
|
||||
calls_only: bool = False,
|
||||
@@ -83,7 +83,7 @@ def display_chains(
|
||||
----------
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
expiry: str
|
||||
expiration: str
|
||||
Expiration for option chain
|
||||
min_sp: float
|
||||
Min strike
|
||||
@@ -108,7 +108,7 @@ def display_chains(
|
||||
put_bool = True
|
||||
|
||||
option_chains = yfinance_model.get_full_option_chain(
|
||||
symbol=symbol, expiration=expiry, calls=call_bool, puts=put_bool
|
||||
symbol=symbol, expiration=expiration, calls=call_bool, puts=put_bool
|
||||
).fillna("-")
|
||||
if option_chains.empty:
|
||||
console.print("[red]Option chains not found.[/red]")
|
||||
@@ -231,7 +231,7 @@ def display_chains(
|
||||
|
||||
print_rich_table(
|
||||
option_chains,
|
||||
title=f"Yahoo Option Chain (15 min delayed) for {expiry} (Greeks calculated by OpenBB)",
|
||||
title=f"Yahoo Option Chain (15 min delayed) for {expiration} (Greeks calculated by OpenBB)",
|
||||
headers=[header_fmt(x) for x in option_chains.columns],
|
||||
)
|
||||
export_data(
|
||||
@@ -245,7 +245,7 @@ def display_chains(
|
||||
@log_start_end(log=logger)
|
||||
def plot_oi(
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
min_sp: float = -1,
|
||||
max_sp: float = -1,
|
||||
calls_only: bool = False,
|
||||
@@ -259,8 +259,8 @@ def plot_oi(
|
||||
----------
|
||||
symbol: str
|
||||
Ticker symbol
|
||||
expiry: str
|
||||
Expiry date for options
|
||||
expiration: str
|
||||
expiration date for options
|
||||
min_sp: float
|
||||
Min strike to consider
|
||||
max_sp: float
|
||||
@@ -274,7 +274,7 @@ def plot_oi(
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
options = yfinance_model.get_option_chain(symbol, expiry)
|
||||
options = yfinance_model.get_option_chain(symbol, expiration)
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
@@ -339,7 +339,7 @@ def plot_oi(
|
||||
ax.set_ylabel("Open Interest [1k] ")
|
||||
ax.set_xlim(min_strike, max_strike)
|
||||
ax.legend()
|
||||
ax.set_title(f"Open Interest for {symbol.upper()} expiring {expiry}")
|
||||
ax.set_title(f"Open Interest for {symbol.upper()} expiring {expiration}")
|
||||
|
||||
theme.style_primary_axis(ax)
|
||||
|
||||
@@ -350,7 +350,7 @@ def plot_oi(
|
||||
@log_start_end(log=logger)
|
||||
def plot_vol(
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
min_sp: float = -1,
|
||||
max_sp: float = -1,
|
||||
calls_only: bool = False,
|
||||
@@ -364,8 +364,8 @@ def plot_vol(
|
||||
----------
|
||||
symbol: str
|
||||
Ticker symbol
|
||||
expiry: str
|
||||
Expiry date for options
|
||||
expiration: str
|
||||
expiration date for options
|
||||
min_sp: float
|
||||
Min strike to consider
|
||||
max_sp: float
|
||||
@@ -379,7 +379,7 @@ def plot_vol(
|
||||
external_axes : Optional[List[plt.Axes]], optional
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
options = yfinance_model.get_option_chain(symbol, expiry)
|
||||
options = yfinance_model.get_option_chain(symbol, expiration)
|
||||
|
||||
calls = options.calls
|
||||
puts = options.puts
|
||||
@@ -431,7 +431,7 @@ def plot_vol(
|
||||
ax.set_ylabel("Volume [1k] ")
|
||||
ax.set_xlim(min_strike, max_strike)
|
||||
ax.legend()
|
||||
ax.set_title(f"Volume for {symbol.upper()} expiring {expiry}")
|
||||
ax.set_title(f"Volume for {symbol.upper()} expiring {expiration}")
|
||||
theme.style_primary_axis(ax)
|
||||
|
||||
if external_axes is None:
|
||||
@@ -447,7 +447,7 @@ def plot_vol(
|
||||
@log_start_end(log=logger)
|
||||
def plot_volume_open_interest(
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
min_sp: float = -1,
|
||||
max_sp: float = -1,
|
||||
min_vol: float = -1,
|
||||
@@ -460,7 +460,7 @@ def plot_volume_open_interest(
|
||||
----------
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
expiry: str
|
||||
expiration: str
|
||||
Option expiration
|
||||
min_sp: float
|
||||
Min strike price
|
||||
@@ -474,7 +474,7 @@ def plot_volume_open_interest(
|
||||
External axes (1 axis is expected in the list), by default None
|
||||
"""
|
||||
|
||||
options = yfinance_model.get_option_chain(symbol, expiry)
|
||||
options = yfinance_model.get_option_chain(symbol, expiration)
|
||||
|
||||
calls = options.calls
|
||||
puts = options.puts
|
||||
@@ -604,7 +604,7 @@ def plot_volume_open_interest(
|
||||
g.set_xticklabels(xlabels)
|
||||
|
||||
ax.set_title(
|
||||
f"{symbol} volumes for {expiry} \n(open interest displayed only during market hours)",
|
||||
f"{symbol} volumes for {expiration} \n(open interest displayed only during market hours)",
|
||||
)
|
||||
ax.invert_yaxis()
|
||||
|
||||
@@ -640,7 +640,7 @@ def plot_volume_open_interest(
|
||||
@log_start_end(log=logger)
|
||||
def plot_plot(
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
put: bool = False,
|
||||
x: str = "s",
|
||||
y: str = "iv",
|
||||
@@ -654,7 +654,7 @@ def plot_plot(
|
||||
----------
|
||||
symbol: str
|
||||
Stock ticker symbol
|
||||
expiry: str
|
||||
expiration: str
|
||||
Option expiration
|
||||
x: str
|
||||
variable to display in x axis, choose from:
|
||||
@@ -690,7 +690,7 @@ def plot_plot(
|
||||
x = convert[x]
|
||||
y = convert[y]
|
||||
varis = op_helpers.opt_chain_cols
|
||||
chain = yfinance_model.get_option_chain(symbol, expiry)
|
||||
chain = yfinance_model.get_option_chain(symbol, expiration)
|
||||
values = chain.puts if put else chain.calls
|
||||
|
||||
if external_axes is None:
|
||||
@@ -705,7 +705,7 @@ def plot_plot(
|
||||
ax.plot(x_data, y_data, "--bo")
|
||||
option = "puts" if put else "calls"
|
||||
ax.set_title(
|
||||
f"{varis[y]['label']} vs. {varis[x]['label']} for {symbol} {option} on {expiry}"
|
||||
f"{varis[y]['label']} vs. {varis[x]['label']} for {symbol} {option} on {expiration}"
|
||||
)
|
||||
ax.set_ylabel(varis[y]["label"])
|
||||
ax.set_xlabel(varis[x]["label"])
|
||||
@@ -732,7 +732,7 @@ def plot_payoff(
|
||||
options: List[Dict[Any, Any]],
|
||||
underlying: float,
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
external_axes: Optional[List[plt.Axes]] = None,
|
||||
) -> None:
|
||||
"""Generate a graph showing the option payoff diagram"""
|
||||
@@ -750,7 +750,7 @@ def plot_payoff(
|
||||
ax.plot(x, ya, label="Payoff After Premium")
|
||||
else:
|
||||
ax.plot(x, yb, label="Payoff")
|
||||
ax.set_title(f"Option Payoff Diagram for {symbol} on {expiry}")
|
||||
ax.set_title(f"Option Payoff Diagram for {symbol} on {expiration}")
|
||||
ax.set_ylabel("Profit")
|
||||
ax.set_xlabel("Underlying Asset Price at Expiration")
|
||||
ax.legend()
|
||||
@@ -765,7 +765,7 @@ def plot_payoff(
|
||||
@log_start_end(log=logger)
|
||||
def show_parity(
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
put: bool = False,
|
||||
ask: bool = False,
|
||||
mini: float = None,
|
||||
@@ -778,7 +778,7 @@ def show_parity(
|
||||
----------
|
||||
symbol : str
|
||||
Ticker symbol to get expirations for
|
||||
expiry : str
|
||||
expiration : str
|
||||
Expiration to use for options
|
||||
put : bool
|
||||
Whether to use puts or calls
|
||||
@@ -791,7 +791,7 @@ def show_parity(
|
||||
export : str
|
||||
Export data
|
||||
"""
|
||||
r_date = datetime.strptime(expiry, "%Y-%m-%d").date()
|
||||
r_date = datetime.strptime(expiration, "%Y-%m-%d").date()
|
||||
delta = (r_date - date.today()).days
|
||||
rate = ((1 + get_rf()) ** (delta / 365)) - 1
|
||||
stock = get_price(symbol)
|
||||
@@ -809,7 +809,7 @@ def show_parity(
|
||||
|
||||
next_div = last_div + timedelta(days=91)
|
||||
dividends = []
|
||||
while next_div < datetime.strptime(expiry, "%Y-%m-%d"):
|
||||
while next_div < datetime.strptime(expiration, "%Y-%m-%d"):
|
||||
day_dif = (next_div - datetime.now()).days
|
||||
dividends.append((avg_div, day_dif))
|
||||
next_div += timedelta(days=91)
|
||||
@@ -818,7 +818,7 @@ def show_parity(
|
||||
else:
|
||||
pv_dividend = 0
|
||||
|
||||
chain = get_option_chain(symbol, expiry)
|
||||
chain = get_option_chain(symbol, expiration)
|
||||
name = "ask" if ask else "lastPrice"
|
||||
o_type = "put" if put else "call"
|
||||
|
||||
@@ -1050,7 +1050,7 @@ def export_binomial_calcs(
|
||||
@log_start_end(log=logger)
|
||||
def show_binom(
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
strike: float = 0,
|
||||
put: bool = False,
|
||||
europe: bool = False,
|
||||
@@ -1064,7 +1064,7 @@ def show_binom(
|
||||
----------
|
||||
symbol : str
|
||||
The ticker symbol of the option's underlying asset
|
||||
expiry : str
|
||||
expiration : str
|
||||
The expiration for the option
|
||||
strike : float
|
||||
The strike price for the option
|
||||
@@ -1080,18 +1080,18 @@ def show_binom(
|
||||
The annualized volatility for the underlying asset
|
||||
"""
|
||||
up, prob_up, discount, und_vals, opt_vals, days = yfinance_model.get_binom(
|
||||
symbol, expiry, strike, put, europe, vol
|
||||
symbol, expiration, strike, put, europe, vol
|
||||
)
|
||||
|
||||
if export:
|
||||
export_binomial_calcs(up, prob_up, discount, und_vals, opt_vals, days, symbol)
|
||||
|
||||
if plot:
|
||||
plot_expected_prices(und_vals, prob_up, symbol, expiry)
|
||||
plot_expected_prices(und_vals, prob_up, symbol, expiration)
|
||||
|
||||
option = "put" if put else "call"
|
||||
console.print(
|
||||
f"{symbol} {option} at ${strike:.2f} expiring on {expiry} is worth ${opt_vals[0][0]:.2f}\n"
|
||||
f"{symbol} {option} at ${strike:.2f} expiring on {expiration} is worth ${opt_vals[0][0]:.2f}\n"
|
||||
)
|
||||
|
||||
|
||||
@@ -1155,7 +1155,7 @@ def display_vol_surface(
|
||||
@log_start_end(log=logger)
|
||||
def show_greeks(
|
||||
symbol: str,
|
||||
expiry: str,
|
||||
expiration: str,
|
||||
div_cont: float = 0,
|
||||
rf: float = None,
|
||||
opt_type: int = 1,
|
||||
@@ -1172,7 +1172,7 @@ def show_greeks(
|
||||
The ticker symbol value of the option
|
||||
div_cont: float
|
||||
The dividend continuous rate
|
||||
expiry: str
|
||||
expiration: str
|
||||
The date of expiration, format "YYYY-MM-DD", i.e. 2010-12-31.
|
||||
rf: float
|
||||
The risk-free rate
|
||||
@@ -1187,7 +1187,7 @@ def show_greeks(
|
||||
"""
|
||||
|
||||
df = yfinance_model.get_greeks(
|
||||
symbol, expiry, div_cont, rf, opt_type, mini, maxi, show_all
|
||||
symbol, expiration, div_cont, rf, opt_type, mini, maxi, show_all
|
||||
)
|
||||
|
||||
column_formatting = [
|
||||
|
||||
@@ -38,7 +38,7 @@ def test_plot_oi(calls_only, max_sp, min_sp, mocker, puts_only):
|
||||
|
||||
yfinance_view.plot_oi(
|
||||
symbol="PM",
|
||||
expiry="2022-01-07",
|
||||
expiration="2022-01-07",
|
||||
min_sp=min_sp,
|
||||
max_sp=max_sp,
|
||||
calls_only=calls_only,
|
||||
@@ -67,7 +67,7 @@ def test_plot_vol(calls_only, max_sp, min_sp, mocker, puts_only):
|
||||
|
||||
yfinance_view.plot_vol(
|
||||
symbol="PM",
|
||||
expiry="2022-01-07",
|
||||
expiration="2022-01-07",
|
||||
min_sp=min_sp,
|
||||
max_sp=max_sp,
|
||||
calls_only=calls_only,
|
||||
@@ -96,7 +96,7 @@ def test_plot_volume_open_interest(max_sp, min_sp, min_vol, mocker):
|
||||
|
||||
yfinance_view.plot_volume_open_interest(
|
||||
symbol="PM",
|
||||
expiry="2022-01-07",
|
||||
expiration="2022-01-07",
|
||||
min_sp=min_sp,
|
||||
max_sp=max_sp,
|
||||
min_vol=min_vol,
|
||||
@@ -117,7 +117,7 @@ def test_plot_plot(mocker):
|
||||
|
||||
yfinance_view.plot_plot(
|
||||
symbol="PM",
|
||||
expiry="2022-01-07",
|
||||
expiration="2022-01-07",
|
||||
put=True,
|
||||
x="c",
|
||||
y="v",
|
||||
@@ -142,7 +142,7 @@ def test_plot_payoff(mocker):
|
||||
options=[],
|
||||
underlying=0,
|
||||
symbol="PM",
|
||||
expiry="2022-06-05",
|
||||
expiration="2022-06-05",
|
||||
)
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ def test_show_parity(mocker):
|
||||
|
||||
yfinance_view.show_parity(
|
||||
symbol="PM",
|
||||
expiry="2022-01-07",
|
||||
expiration="2022-01-07",
|
||||
put=True,
|
||||
ask=True,
|
||||
mini=0.0,
|
||||
@@ -206,7 +206,7 @@ def test_show_binom(mocker):
|
||||
|
||||
yfinance_view.show_binom(
|
||||
symbol="PM",
|
||||
expiry="2022-01-07",
|
||||
expiration="2022-01-07",
|
||||
strike=90.0,
|
||||
put=True,
|
||||
europe=False,
|
||||
@@ -219,12 +219,12 @@ def test_show_binom(mocker):
|
||||
@pytest.mark.default_cassette("test_show_greeks")
|
||||
@pytest.mark.vcr
|
||||
def test_show_greeks():
|
||||
yfinance_view.show_greeks(symbol="AAPL", expiry="2022-01-28", div_cont=0)
|
||||
yfinance_view.show_greeks(symbol="AAPL", expiration="2022-01-28", div_cont=0)
|
||||
|
||||
|
||||
@pytest.mark.default_cassette("test_display_chains")
|
||||
@pytest.mark.vcr
|
||||
def test_display_chains():
|
||||
yfinance_view.display_chains(
|
||||
symbol="AAPL", expiry="2022-07-29", min_sp=-1, max_sp=-1
|
||||
symbol="AAPL", expiration="2022-07-29", min_sp=-1, max_sp=-1
|
||||
)
|
||||
|
||||
@@ -11,10 +11,10 @@ Expiry:
|
||||
|
||||
[unvl] pcr display put call ratio for ticker[/unvl] [AlphaQuery]
|
||||
[unvl] info display option information (volatility, IV rank etc)[/unvl] [Barchart]
|
||||
[unvl] chains display option chains with greeks[/unvl] [Tradier]
|
||||
[unvl] oi plot open interest[/unvl] [Tradier/YFinance]
|
||||
[unvl] vol plot volume[/unvl] [Tradier/YFinance]
|
||||
[unvl] voi plot volume and open interest[/unvl] [Tradier/YFinance]
|
||||
[unvl] chains display option chains with greeks[/unvl] [Tradier/NASDAQ/Yfinance]
|
||||
[unvl] oi plot open interest[/unvl] [Tradier/YFinance/NASDAQ]
|
||||
[unvl] vol plot volume[/unvl] [Tradier/YFinance/NASDAQ]
|
||||
[unvl] voi plot volume and open interest[/unvl] [Tradier/YFinance/NASDAQ]
|
||||
[unvl] hist plot option history[/unvl] [Tradier]
|
||||
[unvl] vsurf show 3D volatility surface[/unvl] [Yfinance]
|
||||
[unvl] grhist plot option greek history[/unvl] [Syncretism]
|
||||
|
||||
Reference in New Issue
Block a user