Files
OpenBB/tests/openbb_terminal/stocks/options/test_yfinance_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

109 lines
2.9 KiB
Python

# IMPORTATION STANDARD
import pandas as pd
# IMPORTATION THIRDPARTY
import pytest
# IMPORTATION INTERNAL
from openbb_terminal.stocks.options import yfinance_model
@pytest.fixture(scope="module")
def vcr_config():
return {
"filter_headers": [("User-Agent", None)],
"filter_query_parameters": [
("period1", "MOCK_PERIOD_1"),
("period2", "MOCK_PERIOD_2"),
("date", "MOCK_DATE"),
("before", "MOCK_BEFORE"),
("after", "MOCK_AFTER"),
],
}
@pytest.mark.vcr(record_mode="none")
@pytest.mark.record_stdout
def test_option_expirations_no_dates(mocker):
# MOCK TICKER
mocker.patch(
target="openbb_terminal.stocks.options.yfinance_model.yf.Ticker",
)
# MOCK OPTION
mocker.patch(
target="openbb_terminal.stocks.options.yfinance_model.yf.Ticker.option",
return_value=(),
)
yfinance_model.option_expirations(symbol="PM")
@pytest.mark.vcr
def test_get_option_chain(mocker, recorder):
# FORCE SINGLE THREADING
yf_download = yfinance_model.yf.download
def mock_yf_download(*args, **kwargs):
kwargs["threads"] = False
return yf_download(*args, **kwargs)
mocker.patch("yfinance.download", side_effect=mock_yf_download)
result_tuple = yfinance_model.get_option_chain(symbol="AAPL", expiry="2023-07-21")
result_tuple = (result_tuple.calls, result_tuple.puts)
recorder.capture_list(result_tuple)
@pytest.mark.vcr
@pytest.mark.parametrize(
"func",
[
"option_expirations",
"get_dividend",
"get_price",
"get_closing",
"get_iv_surface",
],
)
def test_call_func(func, mocker, recorder):
# FORCE SINGLE THREADING
yf_download = yfinance_model.yf.download
def mock_yf_download(*args, **kwargs):
kwargs["threads"] = False
return yf_download(*args, **kwargs)
mocker.patch("yfinance.download", side_effect=mock_yf_download)
# MOCK OPTION
mocker.patch(
target="openbb_terminal.stocks.options.yfinance_model.get_dte",
return_value=1,
)
result = getattr(yfinance_model, func)(symbol="PM")
recorder.capture(result)
@pytest.mark.vcr
def test_load_options(recorder):
data = yfinance_model.load_options(symbol="OXY")
assert isinstance(data.chains, pd.DataFrame)
assert isinstance(data.last_price, float)
assert isinstance(data.underlying_price, pd.Series)
assert data.hasIV
df1 = data.chains
data2 = yfinance_model.load_options(symbol="OXY", pydantic=True)
assert isinstance(data2.chains, dict)
assert isinstance(data2.underlying_price, dict)
assert data2.hasIV
assert isinstance(data2.expirations, list)
assert isinstance(data2.strikes, list)
df2 = pd.DataFrame(data2.chains)
assert df1.equals(df2)
recorder.capture(data.underlying_price.index.to_list())
recorder.capture(df2.columns.to_list())