Files
OpenBB/tests/openbb_terminal/stocks/options/test_tradier_model.py
Danglewood a7edda330d Feature/options - OpenBB Options Enhancement Proposal (Part 1 - SDK) (#5079)
* add model file for Montreal Options Exchange

* mypy fixes

* define attributes under __init__

* type error fix

* another pylint fix

* adds tests for tmx_model

* black

* mypy

* adds expirations test and re-records

* black

* capture error message in test

* mypy

* add __docformat__ line

* improves get_all_ticker_symbols

* removes python magic command for new cell

* adds TMX as source for SDK chains

* starts on a new method for loading options data returning a standardized object

* add load_options as SDK endpoint

* intrinio response - not complete

* adds tradier to load_options

* add source attribute to options object

* restore legacy nasdaq last price function

* yFinance underlying_price fixes

* yFinance model fix

* adds cboe to sdk options load

* table fix

* creates options_chains_model.py and updates SDK map

* docstrings added for the class.

* updates tmx_model tests

* fix options_controller test

* adds cboe_model tests

* spelling in docstring

* ruff - unused import

* mypy fixes

* more mypy fixes

* pylint

* attempt to manually resolve merge conflict.

* nasdaq_model fix

* adds test coverage for options/nasdaq_model

* docstrings update for nasdaq_model

* mypy fix

* adds unit testing for options_chains_model

* adds additional tests for intrinio_model

* unused import fix

* fix for .TO symbol and TMX EOD chains

* make CBOE Pydantic

* cboe update

* adds switch for pydantic output from all sources

* black

* index options error handling for Intrinio

* add warning message for index options from Intrinio

* tmx_model enhancements

* cleans up get_ticker_iv() in cboe_model

* fix ticker info for index symbols from cboe

* typo in comments

* adds test for tradier_model.load_options

* cboe optionType as lower case

* add function for calculating chains stats

* black

* trailmap for calculate_chains_stats

* adds test for calculate_stats()

* more details to nasdaq.underlying_price

* typo in docstrings

* mypy - options_chains_model.py

* black - options_chains_model.py

* pylint options_chains_model.py

* standardize response from intrinio underlying price

* add function to validate input of function

* missed type hint

* additional error handling for stats

* adds DTE as column for all sources

* adds strategies function and input validation

* add yFinance test for load_options()

* add Nasdaq test for load_options()

* tests for new functions in options_chains_model

* update sdk trailmap

* rewrite tests

* fixes for tests

* fix tmx_model test

* more pytest

* pytest..

* add vertical call spread function

* some cleanup

* update nasdaq tests

* more cleanup

* black

* pylint

* black

* ruff

* black

* pylint

* black

* pylint..

* tests rewrite

* more pytest

* recapture tests

* Different tests were collected between gw1 and gw0

* adds vertical spreads

* vertical_put_spread

* improve calculate_stats

* mypy

* edge cases

* black

* update tmx,yfinance tests

* new cboe tests

* new tmx_model tests

* fix nasdaq test

* test updates

* fix nasdaq tests

* add test_options_chains_model

* refactor data sources

* black

* pylint

* fixing stuff

* forgot a file..

* codespell

* linting

* mypy...

* refactor OptionsChains class

* pylint

* reconfigure SDK entry point

* fix error handling when data request fails

* ruff

* pylint

* pylint

* Add inheritance and a repr string

* add method for skew

* add method for skew

* fix nasdaq test

* add skew to tests

---------

Co-authored-by: James Maslek <jmaslek11@gmail.com>
2023-06-19 13:11:16 +00:00

183 lines
4.9 KiB
Python

# IMPORTATION STANDARD
# IMPORTATION THIRDPARTY
import pandas as pd
import pytest
import requests
# IMPORTATION INTERNAL
from openbb_terminal.stocks.options import tradier_model
@pytest.fixture(scope="module")
def vcr_config():
return {
"filter_headers": [("Authorization", "MOCK_TOKEN")],
"filter_query_parameters": [
("before", "MOCK_BEFORE"),
("after", "MOCK_AFTER"),
],
}
@pytest.mark.vcr
def test_get_historical_options(recorder):
result_df = tradier_model.get_historical_options(
symbol="AAPL",
expiry="2025-01-17",
strike=90.0,
put=True,
chain_id="",
)
recorder.capture(result_df)
@pytest.mark.vcr(record_mode="none")
def test_get_historical_options_invalid_status(mocker):
mock_response = requests.Response()
mock_response.status_code = 400
mocker.patch(
target="openbb_terminal.helper_funcs.requests.get",
new=mocker.Mock(return_value=mock_response),
)
result_df = tradier_model.get_historical_options(
symbol="AAPL",
expiry="2025-01-17",
strike=90.0,
put=True,
chain_id="MOCK_CHAIN_ID",
)
assert result_df.empty
@pytest.mark.vcr(record_mode="none")
def test_get_historical_options_no_data(mocker):
mock_response = requests.Response()
mock_response.status_code = 200
mocker.patch.object(
target=mock_response,
attribute="json",
return_value={"history": None},
)
mocker.patch(
target="openbb_terminal.helper_funcs.requests.get",
new=mocker.Mock(return_value=mock_response),
)
result_df = tradier_model.get_historical_options(
symbol="AAPL",
expiry="2022-02-25",
strike=90.0,
put=True,
chain_id="MOCK_CHAIN_ID",
)
assert result_df.empty
@pytest.mark.vcr
def test_option_expirations(recorder):
result_list = tradier_model.option_expirations(symbol="AAPL")
recorder.capture(result_list)
@pytest.mark.vcr
def test_option_expirations_json_error(mocker):
mock_response = requests.Response()
mock_response.status_code = 200
mocker.patch.object(
target=mock_response,
attribute="json",
side_effect=TypeError(),
)
mocker.patch(
target="openbb_terminal.helper_funcs.requests.get",
new=mocker.Mock(return_value=mock_response),
)
result_list = tradier_model.option_expirations(symbol="AAPL")
assert result_list == []
@pytest.mark.vcr(record_mode="none")
def test_option_expirations_invalid_status(mocker):
mock_response = requests.Response()
mock_response.status_code = 400
mocker.patch(
target="openbb_terminal.helper_funcs.requests.get",
new=mocker.Mock(return_value=mock_response),
)
result_list = tradier_model.option_expirations(symbol="AAPL")
assert result_list == []
@pytest.mark.vcr
def test_get_option_chains(recorder):
chain = tradier_model.get_option_chain(symbol="AAPL", expiry="2025-01-17")
recorder.capture(chain)
@pytest.mark.vcr(record_mode="none")
def test_get_option_chains_invalid_status(mocker):
mock_response = requests.Response()
mock_response.status_code = 400
mocker.patch(
target="openbb_terminal.helper_funcs.requests.get",
new=mocker.Mock(return_value=mock_response),
)
result_df = tradier_model.get_option_chain(symbol="AAPL", expiry="2025-01-17")
assert result_df.empty
@pytest.mark.vcr
def test_last_price(recorder):
result = tradier_model.get_last_price(symbol="AAPL")
recorder.capture(result)
@pytest.mark.vcr(record_mode="none")
def test_get_historical_greeks_invalid_status(mocker):
mock_response = requests.Response()
mock_response.status_code = 400
mocker.patch(
target="openbb_terminal.helper_funcs.requests.get",
new=mocker.Mock(return_value=mock_response),
)
result = tradier_model.get_last_price(symbol="AAPL")
assert result is None
@pytest.mark.vcr
def test_load_options(recorder):
results = tradier_model.load_options(symbol="AAPL")
results1 = tradier_model.load_options(symbol="AAPL", pydantic=True)
assert hasattr(results, "chains")
assert hasattr(results1, "chains")
assert isinstance(results.chains, pd.DataFrame)
assert isinstance(results1.chains, dict)
assert isinstance(results.expirations, list)
assert isinstance(results1.expirations, list)
assert isinstance(results.underlying_price, pd.Series)
assert isinstance(results1.underlying_price, dict)
assert (
results.chains["volume"].sum() == pd.DataFrame(results1.chains)["volume"].sum()
)
recorder.capture(
[
results.chains.columns.to_list(),
results.underlying_price.index.to_list(),
results.SYMBOLS.columns.to_list(),
results.underlying_name,
results1.underlying_name,
]
)