Add cboe top of book (#2830)

* Add cboe top of book

* test + merge 1 print table

* unit test + add stocks int test
This commit is contained in:
James Maslek
2022-10-14 13:16:06 -04:00
committed by GitHub
parent ff3f0f450a
commit 0b76e5b4c3
18 changed files with 371 additions and 0 deletions

View File

@@ -2,6 +2,7 @@
"stocks": {
"search": ["FinanceDatabase"],
"quote": ["YahooFinance"],
"tob": ["CBOE"],
"candle": [],
"codes": ["Polygon"],
"news": ["Feedparser", "NewsApi"],

View File

@@ -1889,6 +1889,7 @@ functions = {
},
"stocks.search": {"model": "openbb_terminal.stocks.stocks_helper.search"},
"stocks.quote": {"model": "openbb_terminal.stocks.stocks_helper.quote"},
"stocks.tob": {"model": "openbb_terminal.stocks.cboe_model.get_top_of_book"},
"stocks.candle": {"model": "openbb_terminal.stocks.stocks_helper.display_candle"},
"crypto.load": {
"model": "openbb_terminal.cryptocurrency.cryptocurrency_helpers.load"

View File

@@ -94,6 +94,7 @@ en:
stocks/load: load a specific stock ticker and additional info for analysis
stocks/_ticker: Stock
stocks/quote: view the current price for a specific stock ticker
stocks/tob: view top of book for loaded ticker (US exchanges only)
stocks/QUOTE: Current quote for stock ticker
stocks/QUOTE_ticker: Stock ticker
stocks/candle: view a candle chart for a specific stock ticker

View File

@@ -0,0 +1,59 @@
"""CBOE Model Functions"""
__docformat__ = "numpy"
from typing import Tuple
import pandas as pd
import requests
from openbb_terminal.rich_config import console
def get_top_of_book(
symbol: str, exchange: str = "BZX"
) -> Tuple[pd.DataFrame, pd.DataFrame]:
"""Get top of book bid and ask for ticker on exchange [CBOE.com]
Parameters
----------
symbol: str
Ticker to get
exchange: str
Exchange to look at. Can be `BZX`,`EDGX`, `BYX`, `EDGA`
Returns
-------
pd.DatatFrame
Dataframe of Bids
pd.DataFrame
Dataframe of asks
"""
if exchange not in ["BZX", "EDGX", "BYX", "EDGA"]:
console.print(f"[red]Exchange not valid: {exchange}[/red]")
return pd.DataFrame(), pd.DataFrame()
# exchange need to be lower case. Not sure why
url = f"https://www.cboe.com/json/{exchange.lower()}/book/{symbol}"
r = requests.get(
url,
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)"
" Chrome/106.0.0.0 Safari/537.36",
"referer": "https://www.cboe.com/us/equities/market_statistics/book_viewer/",
},
)
if r.status_code != 200:
console.print(f"[red]Request failed with code {r.status_code}[/red]")
return pd.DataFrame(), pd.DataFrame()
r_json = r.json()
if r_json["data"]["company"] == "unknown symbol":
console.print(f"[red]Unknown symbol: {symbol}[/red]")
return pd.DataFrame(), pd.DataFrame()
bids = pd.DataFrame(r_json["data"]["bids"], columns=["Size", "Price"])
asks = pd.DataFrame(r_json["data"]["asks"], columns=["Size", "Price"])
if bids.empty or asks.empty:
console.print(
"[red]No bid/ask data. Note this is real time so there is no data after market close.[/red]"
)
return bids, asks

View File

@@ -0,0 +1,34 @@
"""CBOE View"""
__docformat__ = "numpy"
import pandas as pd
from openbb_terminal.stocks import cboe_model
from openbb_terminal.helper_funcs import print_rich_table
from openbb_terminal.rich_config import console
def display_top_of_book(symbol: str, exchange: str = "BZX"):
"""Display top of book data [CBOE]
Parameters
----------
symbol: str
Symbol to get data for
exchange: str
Exchange to get data for
"""
bids, asks = cboe_model.get_top_of_book(symbol, exchange)
if not bids.empty and not asks.empty:
asks = asks[["Price", "Size"]]
bids.columns = ["Bid " + col for col in bids.columns]
asks.columns = ["Ask " + col for col in asks.columns]
merged = pd.concat([bids, asks], axis=1)
print_rich_table(
merged,
title=f"{symbol} Top of Book",
show_index=False,
headers=merged.columns,
)
console.print()

View File

@@ -16,6 +16,7 @@ from openbb_terminal import feature_flags as obbff
from openbb_terminal.common import feedparser_view, newsapi_view
from openbb_terminal.common.quantitative_analysis import qa_view
from openbb_terminal.decorators import log_start_end
from openbb_terminal.stocks import cboe_view
from openbb_terminal.helper_funcs import (
EXPORT_ONLY_RAW_DATA_ALLOWED,
@@ -46,6 +47,7 @@ class StocksController(StockBaseController):
"search",
"load",
"quote",
"tob",
"candle",
"news",
"resources",
@@ -77,6 +79,7 @@ class StocksController(StockBaseController):
country = financedatabase.show_options("equities", "countries")
sector = financedatabase.show_options("equities", "sectors")
industry = financedatabase.show_options("equities", "industries")
TOB_EXCHANGES = ["BZX", "EDGX", "BYX", "EDGA"]
def __init__(self, queue: List[str] = None):
"""Constructor"""
@@ -114,6 +117,10 @@ class StocksController(StockBaseController):
"--ticker": None,
"-t": "--ticker",
}
choices["tob"] = {
"--exchange": {c: {} for c in self.TOB_EXCHANGES},
"-e": "--exchange",
}
choices["search"] = {
"--query": None,
"-q": "--query",
@@ -179,6 +186,7 @@ class StocksController(StockBaseController):
mt.add_raw(self.add_info)
mt.add_raw("\n")
mt.add_cmd("quote", self.ticker)
mt.add_cmd("tob", self.ticker)
mt.add_cmd("candle", self.ticker)
mt.add_cmd("codes", self.ticker)
mt.add_cmd("news", self.ticker)
@@ -286,6 +294,41 @@ class StocksController(StockBaseController):
export=ns_parser.export,
)
@log_start_end(log=logger)
def call_tob(self, other_args: List[str]):
"""Process quote command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="quote",
description="Get top of book for loaded ticker from selected exchange",
)
parser.add_argument(
"-t",
"--ticker",
action="store",
dest="s_ticker",
required="-h" not in other_args and not self.ticker,
help="Ticker to get data for",
)
parser.add_argument(
"-e",
"--exchange",
default="BZX",
choices=self.TOB_EXCHANGES,
type=str,
dest="exchange",
)
if not self.ticker:
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-t")
ns_parser = self.parse_known_args_and_warn(parser, other_args)
if ns_parser:
ticker = ns_parser.s_ticker if ns_parser.s_ticker else self.ticker
cboe_view.display_top_of_book(ticker, ns_parser.exchange)
@log_start_end(log=logger)
def call_quote(self, other_args: List[str]):
"""Process quote command"""

9
scripts/test_stocks.openbb vendored Normal file
View File

@@ -0,0 +1,9 @@
stocks
search apple
load aapl -s 2022-10-01
tob
tob -e EDGX
candle
codes
news
exit

View File

@@ -0,0 +1,58 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/106.0.0.0 Safari/537.36
referer:
- https://www.cboe.com/us/equities/market_statistics/book_viewer/
method: GET
uri: https://www.cboe.com/json/bzx/book/AAPL
response:
body:
string: !!binary |
H4sIAAAAAAAAA72TT2uDMBiHv0p5zy4kMf5JbqXsMOjWHnaTMlLNWqlWMbajjH33vbFatPQ22EHI
k/fJL6+JfoM9pamxFlTbnIwHjSkqnYEKKKUeZLrVoL7BXsptVYCC+Xy9BA/0KW3z6gjqUxcWV6VV
WevjxQnr9fJ59vK2mC1Wr2jWjTmDYoITKV1iVZujY58w5nif7/aOBQlCx0X1hehLEvAOtW1dmRK/
ayjd6+POgHriJOzyzlVxKnGCB8KXMccNmsw0dtW8Nzoz1q1lEqOxZ3tATBKX2wWKjZeIAYIxhAg3
LRpDvNl4sM2zLunmc1SCARiCHADHfj/m0oHgV+iC2r7HJAHGFI8Uo3hkzD39G7thXyEx5W4GU/7N
vkrO96c+DeKpT+XE53Lk0+ttPvIHPZ7qwn+s3/zozuf37URTPxj7EYkl/6MfYlkMdji2QxKLazfu
hvPS2FaXNf4a/eG5ndo8PXy0lxo/XICfn1+23IgKhgMAAA==
headers:
Accept-Ranges:
- bytes
CF-Cache-Status:
- EXPIRED
CF-RAY:
- 75a156ac88625716-IAD
Cache-Control:
- no-cache=False, must-revalidate=False, max-age=5
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '376'
Content-Type:
- application/json
Date:
- Fri, 14 Oct 2022 15:27:21 GMT
Last-Modified:
- Fri, 14 Oct 2022 15:27:18 GMT
Link:
- <https://(null)(null)>; rel="canonical"
Server:
- cloudflare
Vary:
- Host,Accept-Encoding
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,58 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/106.0.0.0 Safari/537.36
referer:
- https://www.cboe.com/us/equities/market_statistics/book_viewer/
method: GET
uri: https://www.cboe.com/json/bzx/book/AAPL
response:
body:
string: !!binary |
H4sIAAAAAAAAA5WTTWuDQBCG/0qYsxV3dVfdWwg9FNImh94klK1uE4lfuJoSQv57ZzcKJoSCF/GZ
eXxnXJML6D5NldYgurZXDrSqqGUGgnme50AmOwniAvpcftcFCFgut2twQPZpl9cViB9ZaHwqrctG
VmcjbLfr18Xbx2qx2ryj2bTqBIIE1I1jk1g3qjLsu4QYPuT7g+HAZdxwUf8i+rHLqEWpO9P2XN8u
lB5ktVcgXqjLbd6pLvoSC5Rx5tEAB7SZavWm/WxlprQdRSgjuLM+IiaJybWBZOckfASKQDwe3shH
CsZWMAW22znwnWc2KhyqNEYlGiFC8EcIJ0MoRxjHU5vUDVsmCRAiaCy8CA8NT8Zch7c2t0PPjZmt
YM5zn4b3fsT5E58Fs/SAz9LnbjPx+b3POXvww3/8EM80muWT8HGfuT6/99nU5y73ifXNh85LpTtZ
NvgfufUJBVNOj1/ducFfMMD1+gcFcAyvjwMAAA==
headers:
Accept-Ranges:
- bytes
CF-Cache-Status:
- EXPIRED
CF-RAY:
- 75a1596f3f605830-IAD
Cache-Control:
- no-cache=False, must-revalidate=False, max-age=5
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '370'
Content-Type:
- application/json
Date:
- Fri, 14 Oct 2022 15:29:14 GMT
Last-Modified:
- Fri, 14 Oct 2022 15:29:13 GMT
Link:
- <https://(null)(null)>; rel="canonical"
Server:
- cloudflare
Vary:
- Host,Accept-Encoding
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,55 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/106.0.0.0 Safari/537.36
referer:
- https://www.cboe.com/us/equities/market_statistics/book_viewer/
method: GET
uri: https://www.cboe.com/json/bzx/book/JBEUCEBFY
response:
body:
string: !!binary |
H4sIAAAAAAAAA0yNzQrCMBCEX6XsOWC1txyVevCqHkSkrMmCpU1Sko1aiu9u+oN4m5nd+WYAT61D
DTIXoJER5AChN3fXgoTDtjzvyu3+AgK4NhQYTZfy9VoWG1kU2fm4KjEweZs+lDMd2j7do22se9ls
AQl4ujYamkac1+TDJDE0SVxvAu61XhTXqqm479IzjKseNS2nh7dolnysVspFyxNp7P/ZufULPgJC
VIpCArGPlCwjx3CiN8+42e+cHvGbPP9Fs5UZfL4AAAD//wMAf/v13SoBAAA=
headers:
CF-Cache-Status:
- MISS
CF-RAY:
- 75a15e4c5aa35e17-IAD
Cache-Control:
- must-revalidate=False, no-cache=False, max-age=5
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Fri, 14 Oct 2022 15:32:33 GMT
Last-Modified:
- Fri, 14 Oct 2022 15:32:33 GMT
Link:
- <https://www.cboe.com/json/bzx/book/JBEUCEBFY>; rel="canonical"
Server:
- cloudflare
Transfer-Encoding:
- chunked
Vary:
- Host,Accept-Encoding
X-Frame-Options:
- SAMEORIGIN
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,7 @@
import pytest
from openbb_terminal.stocks import cboe_model
@pytest.mark.vcr
def test_top_of_book():
cboe_model.get_top_of_book("AAPL")

View File

@@ -0,0 +1,14 @@
import pytest
from openbb_terminal.stocks import cboe_view
@pytest.mark.vcr
@pytest.mark.record_stdout
def test_top_of_book():
cboe_view.display_top_of_book("AAPL")
@pytest.mark.vcr
@pytest.mark.record_stdout
def test_top_of_book_bad_ticker():
cboe_view.display_top_of_book("JBEUCEBFY")

View File

@@ -271,6 +271,13 @@ def test_call_func_expect_queue(expected_queue, func, queue):
[],
dict(),
),
(
"call_tob",
["--ticker=AAPL"],
"cboe_view.display_top_of_book",
[],
dict(),
),
(
"call_candle",
[

View File

@@ -0,0 +1,7 @@
Bid Size Bid Price Ask Price Ask Size
0 700 140.29 140.31 200
1 800 140.28 140.32 600
2 300 140.27 140.33 1067
3 600 140.26 140.34 400
4 200 140.25 140.35 400

View File

@@ -0,0 +1,2 @@
[red]Unknown symbol: JBEUCEBFY[/red]

View File

@@ -8,6 +8,7 @@ Exchange:
Currency:
[unvl] quote view the current price for a specific stock ticker[/unvl] [YahooFinance]
[unvl] tob view top of book for loaded ticker (US exchanges only)[/unvl] [CBOE]
[unvl] candle view a candle chart for a specific stock ticker[/unvl]
[unvl] codes FIGI, SIK and SIC codes codes[/unvl] [Polygon]
[unvl] news latest news of the company[/unvl] [Feedparser, NewsApi]

View File

@@ -0,0 +1,12 @@
```
usage: quote [-t S_TICKER] [-e {BZX,EDGX,BYX,EDGA}] [-h]
```
Get top of book for loaded ticker from selected exchange
```
optional arguments:
-t S_TICKER, --ticker S_TICKER
Ticker to get data for (default: None)
-e {BZX,EDGX,BYX,EDGA}, --exchange {BZX,EDGX,BYX,EDGA}
-h, --help show this help message (default: False)
```
For more information and examples, use 'about quote' to access the related guide.

View File

@@ -1507,6 +1507,8 @@ main:
ref: /terminal/common/qa/unitroot
- name: quote
ref: /terminal/stocks/quote
- name: tob
ref: /terminal/stocks/tob
- name: research
ref: /terminal/stocks/res
sub: