mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-01 23:12:21 +00:00
* 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>
183 lines
4.9 KiB
Python
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,
|
|
]
|
|
)
|