Files
OpenBB/gamestonk_terminal/options/chains_view.py
2021-04-27 13:46:53 -04:00

233 lines
6.1 KiB
Python

"""Helper functions for the options menu"""
__docformat__ = "numpy"
import argparse
from typing import List
import requests
import pandas as pd
import numpy as np
from tabulate import tabulate
from gamestonk_terminal.config_terminal import TRADIER_TOKEN
from gamestonk_terminal.helper_funcs import (
check_non_negative,
parse_known_args_and_warn,
)
option_columns = [
"bid",
"ask",
"strike",
"bidsize",
"asksize",
"volume",
"open_interest",
"option_type",
]
greek_columns = ["delta", "gamma", "theta", "vega", "ask_iv", "bid_iv", "mid_iv"]
df_columns = option_columns + greek_columns
column_map = {"mid_iv": "iv", "open_interest": "oi", "volume": "vol"}
default_columns = [
"mid_iv",
"vega",
"delta",
"gamma",
"theta",
"volume",
"open_interest",
"bid",
"ask",
]
def check_valid_option_chains_headers(headers: str) -> List[str]:
columns = [str(item) for item in headers.split(",")]
for header in columns:
if header not in df_columns:
raise argparse.ArgumentTypeError("Invalid option chains header selected!")
return columns
def process_chains(response: requests.models.Response) -> pd.DataFrame:
"""
Function to take in the requests.get and return a DataFrame
Parameters
----------
response: requests.models.Response
This is the response from tradier api.
Returns
-------
opt_chain: pd.DataFrame
Dataframe with all available options
"""
json_response = response.json()
options = json_response["options"]["option"]
opt_chain = pd.DataFrame(columns=df_columns)
for idx, option in enumerate(options):
data = [option[col] for col in option_columns]
data += [option["greeks"][col] for col in greek_columns]
opt_chain.loc[idx, :] = data
return opt_chain
def get_option_chains(symbol: str, expiry: str) -> pd.DataFrame:
"""
Parameters
----------
symbol : str
Ticker to get options for
expiry : str
Expiration date in the form of "YYYY-MM-DD"
Returns
-------
chains: pd.DataFrame
Dataframe with options for the gievn Symbol and Expiration date
"""
params = {"symbol": symbol, "expiration": expiry, "greeks": "true"}
headers = {"Authorization": f"Bearer {TRADIER_TOKEN}", "Accept": "application/json"}
response = requests.get(
"https://sandbox.tradier.com/v1/markets/options/chains",
params=params,
headers=headers,
)
if response.status_code == 401:
print("Error in request.get -- check token")
return
chains = process_chains(response)
return chains
def display_chains(symbol: str, expiry: str, other_args: List[str]):
parser = argparse.ArgumentParser(
prog="chains",
add_help=False,
description="Display option chains [Source: Tradier]",
)
parser.add_argument(
"--calls",
action="store_true",
default=False,
dest="calls_only",
help="Flag to show calls only",
)
parser.add_argument(
"--puts",
action="store_true",
default=False,
dest="puts_only",
help="Flag to show puts only",
)
parser.add_argument(
"-m",
"--min",
dest="min_sp",
type=check_non_negative,
default=-1,
help="minimum strike price to consider.",
)
parser.add_argument(
"-M",
"--max",
dest="max_sp",
type=check_non_negative,
default=-1,
help="maximum strike price to consider.",
)
parser.add_argument(
"-d",
"--display",
dest="to_display",
default=default_columns,
type=check_valid_option_chains_headers,
help="columns to look at. Columns can be: {bid, ask, strike, bidsize, asksize, volume, open_interest, delta, "
"gamma, theta, vega, ask_iv, bid_iv, mid_iv} ",
)
chains_df = get_option_chains(symbol, expiry)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
columns = ns_parser.to_display + ["strike", "option_type"]
chains_df = chains_df[columns].rename(columns=column_map)
if ns_parser.max_sp == -1 and ns_parser.min_sp == -1:
min_strike = np.percentile(chains_df["strike"], 25)
max_strike = np.percentile(chains_df["strike"], 75)
else:
min_strike = ns_parser.min_sp
max_strike = ns_parser.max_sp
chains_df = chains_df[chains_df["strike"] >= min_strike]
chains_df = chains_df[chains_df["strike"] <= max_strike]
calls_df = chains_df[chains_df.option_type == "call"].drop(
columns=["option_type"]
)
puts_df = chains_df[chains_df.option_type == "put"].drop(
columns=["option_type"]
)
if ns_parser.calls_only:
print(
tabulate(
calls_df,
headers=calls_df.columns,
tablefmt="grid",
showindex=False,
floatfmt=".2f",
)
)
return
if ns_parser.puts_only:
print(
tabulate(
puts_df,
headers=puts_df.columns,
tablefmt="grid",
showindex=False,
floatfmt=".2f",
)
)
return
puts_df = puts_df[puts_df.columns[::-1]]
chain_table = calls_df.merge(puts_df, on="strike")
headers = [
col.strip("_x")
if col.endswith("_x")
else col.strip("_y")
if col.endswith("_y")
else col
for col in chain_table.columns
]
print(
tabulate(
chain_table,
headers=headers,
tablefmt="fancy_grid",
showindex=False,
floatfmt=".2f",
)
)
print("")
except Exception as e:
print(e)
print("")
return