Added ChartExchange as source option (#829)

* Added chartexchange source

* Fixed black

* Didier updates

* Updated

* James changes

* Small fixes

* Adding updates

Co-authored-by: Colin Delahunty <colindelahunty@Colins-Air.indiana.edu>
Co-authored-by: Colin Delahunty <colindelahunty@Colins-MacBook-Air.local>
This commit is contained in:
Colin Delahunty
2021-10-19 11:33:47 -04:00
committed by GitHub
parent ede36834c5
commit 507ce66a73
5 changed files with 167 additions and 3 deletions

View File

@@ -0,0 +1,60 @@
"""Chartexchange model"""
__docformat__ = "numpy"
import requests
import pandas as pd
from bs4 import BeautifulSoup
from gamestonk_terminal.options.op_helpers import convert
def get_option_history(ticker: str, date: str, call: bool, price: str) -> pd.DataFrame:
"""Historic prices for a specific option [chartexchange]
Parameters
----------
ticker : str
Ticker to get historical data from
date : str
Date as a string YYYYMMDD
call : bool
Whether to show a call or a put
price : str
Strike price for a specific option
Returns
-------
historical : pd.Dataframe
Historic information for an option
"""
url = (
f"https://chartexchange.com/symbol/opra-{ticker.lower()}{date.replace('-', '')}"
)
url += f"{'c' if call else 'p'}{float(price):g}/historical/"
data = requests.get(url, headers={"User-Agent": "test"}).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;"})
clean_rows = []
if rows:
for row in rows[1:]:
item = row.find_all("div")
clean_rows.append([x.text for x in item])
else:
print("No data for this option\n")
return pd.DataFrame()
df = pd.DataFrame()
df["Date"] = [x[0] for x in clean_rows]
df["Open"] = [convert(x[1], ",") for x in clean_rows]
df["High"] = [convert(x[2], ",") for x in clean_rows]
df["Low"] = [convert(x[3], ",") for x in clean_rows]
df["Close"] = [convert(x[4], ",") for x in clean_rows]
df["Change"] = [convert(x[5], "%") for x in clean_rows]
df["Volume"] = [convert(x[6], ",") for x in clean_rows]
df["Open Interest"] = [convert(x[7], ",") for x in clean_rows]
df["Change Since"] = [convert(x[8], "%") for x in clean_rows]
return df

View File

@@ -0,0 +1,56 @@
"""Chartexchange view"""
__docformat__ = "numpy"
import os
from tabulate import tabulate
from gamestonk_terminal.helper_funcs import export_data
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.options import chartexchange_model
def display_raw(
export: str, ticker: str, date: str, call: bool, price: str, num: int = 20
) -> None:
"""Return raw stock data[chartexchange]
Parameters
----------
export : str
Export data as CSV, JSON, XLSX
ticker : str
Ticker for the given option
date : str
Date of expiration for the option
call : bool
Whether the underlying asset should be a call or a put
price : float
The stike of the expiration
num : int
Number of rows to show
"""
df = chartexchange_model.get_option_history(ticker, date, call, price)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"hist",
df,
)
if gtff.USE_TABULATE_DF:
print(
tabulate(
df.head(num),
headers=df.columns,
tablefmt="fancy_grid",
showindex=True,
floatfmt=".2f",
)
)
else:
print(df.to_string(index=False))
print("")

View File

@@ -62,6 +62,26 @@ def calculate_max_pain(chain: pd.DataFrame) -> int:
return max_pain
def convert(orig: str, to: str) -> float:
"""Convert a string to a specific type of number
Parameters
----------
orig: str
String to convert
Returns
-------
number : float
Decimal value of string
"""
if to == "%":
clean = orig.replace("%", "").replace("+", "")
return float(clean) / 100
if to == ",":
clean = orig.replace(",", "")
return float(clean)
raise ValueError("Invalid to format, please use '%' or ','.")
opt_chain_cols = {
"lastTradeDate": {"format": "date", "label": "Last Trade Date"},
"strike": {"format": "${x:.2f}", "label": "Strike"},

View File

@@ -30,7 +30,7 @@ from gamestonk_terminal.options import (
yfinance_view,
)
from gamestonk_terminal.stocks import stocks_controller
from gamestonk_terminal.options import payoff_controller
from gamestonk_terminal.options import payoff_controller, chartexchange_view
class OptionsController:
@@ -631,7 +631,7 @@ Current Expiry: {self.selected_date or None}
"--strike",
dest="strike",
type=float,
required="--chain" not in other_args or "-h" not in other_args,
required="--chain" not in other_args and "-h" not in other_args,
help="Strike price to look at",
)
parser.add_argument(
@@ -660,6 +660,21 @@ Current Expiry: {self.selected_date or None}
dest="export",
help="Export dataframe data to csv,json,xlsx file",
)
parser.add_argument(
"--source",
dest="source",
type=str,
choices=["td", "ce"],
default="ce" if TRADIER_TOKEN == "REPLACE_ME" else "td",
help="Choose Tradier(TD) or ChartExchange (CE), only affects raw data",
)
parser.add_argument(
"-n",
"--num",
dest="num",
type=int,
help="Number of data rows to show",
)
try:
if (
@@ -678,9 +693,21 @@ Current Expiry: {self.selected_date or None}
if not self.selected_date:
print("No expiry loaded. First use `exp ` \n")
return
if ns_parser.source.lower() == "ce":
chartexchange_view.display_raw(
ns_parser.export,
self.ticker,
self.selected_date,
not ns_parser.put,
ns_parser.strike,
ns_parser.num,
)
return
if TRADIER_TOKEN == "REPLACE_ME":
print("TRADIER TOKEN not supplied. \n")
return
tradier_view.display_historical(
ticker=self.ticker,
expiry=self.selected_date,

View File

@@ -1,5 +1,5 @@
```
usage: hist [-s STRIKE] [-p] [--chain CHAIN_ID] [-r,--raw] [--export {csv,json,xlsx}] [-h]
usage: hist [-s STRIKE] [-p] [--chain CHAIN_ID] [-r,--raw] [--export {csv,json,xlsx}] [--source SOURCE] [-h]
```
Gets historical quotes for given option chain
@@ -10,6 +10,7 @@ optional arguments:
Strike price to look at (default: None)
-p, --put Flag for showing put option (default: False)
--chain CHAIN_ID OCC option symbol (default: None)
--source SOURCE Source of data (default: TradierView)
-r,--raw Display raw data (default: False)
--export {csv,json,xlsx}
Export dataframe data to csv,json,xlsx file (default: )