Bug: min/max price filters on options.chain are never validated (min_bid > max_bid passes silently)
Problem
OptionsChainInput declares a model_validator that is meant to enforce
min ≤ max on the bid/ask price filters. In practice the check never runs:
it reuses the date-only helper _validate_min_max_dates, which compares the two
values only when both look like dates. The bid/ask filters are floats, so the
comparison is skipped entirely and an inverted range is accepted without error.
This means an obviously invalid request such as min_bid=5, max_bid=1 is sent
to the API as-is instead of being rejected client-side, defeating the purpose of
the validator.
Reproduction
from marketdata.input_types.options import OptionsChainInput
# Expected: a validation error (min greater than max).
# Actual: constructs fine, no error raised.
OptionsChainInput(symbol="AAPL", min_bid=5.0, max_bid=1.0)
OptionsChainInput(symbol="AAPL", min_ask=10.0, max_ask=2.0)
Root Cause
src/marketdata/input_types/options.py:124
@model_validator(mode="after")
def validate_input(self) -> "OptionsChainInput":
params_typles = [
("min_bid", "max_bid"),
("min_ask", "max_ask"),
]
for min_param, max_param in params_typles:
self._validate_min_max_dates(min_param, max_param)
return self
The helper it calls (src/marketdata/input_types/base.py:14) gates the
comparison behind a date check:
def _validate_min_max_dates(self, min_param, max_param) -> None:
min_value = getattr(self, min_param)
max_value = getattr(self, max_param)
min_is_date = check_is_date(min_value)
max_is_date = check_is_date(max_value)
if min_is_date and max_is_date: # <- never True for float prices
if min_value > max_value:
raise MinMaxDateValidationError(...)
check_is_date (src/marketdata/utils.py:36) returns False for any non-date,
non-string value, so for float prices min_is_date/max_is_date are always
False and the min > max comparison is unreachable.
Minor: the local variable is also misspelled params_typles (should be
params_tuples).
Suggested Fix
Validate numeric ranges with a numeric-aware check rather than the date helper.
For example, add a generic min/max helper on BaseInputType:
def _validate_min_max(self, min_param: str, max_param: str) -> None:
min_value = getattr(self, min_param)
max_value = getattr(self, max_param)
if min_value is not None and max_value is not None and min_value > max_value:
raise ValueError(f"{min_param} must be less than or equal to {max_param}")
and call it from OptionsChainInput.validate_input for the price pairs (keeping
_validate_min_max_dates for genuine date ranges like from_date/to_date).
While here, consider extending the check to the other ordered numeric pairs in
the model that currently aren't validated at all, e.g. min_open_interest /
min_volume bounds if max counterparts exist, and fix the params_typles
typo.
Recommendation
Add tests asserting that:
OptionsChainInput(min_bid=5, max_bid=1) raises a validation error,
- a valid range (
min_bid=1, max_bid=5) constructs without error,
- the existing date-range validation on
from_date/to_date still works.
Bug: min/max price filters on
options.chainare never validated (min_bid > max_bidpasses silently)Problem
OptionsChainInputdeclares amodel_validatorthat is meant to enforcemin ≤ maxon the bid/ask price filters. In practice the check never runs:it reuses the date-only helper
_validate_min_max_dates, which compares the twovalues only when both look like dates. The bid/ask filters are floats, so the
comparison is skipped entirely and an inverted range is accepted without error.
This means an obviously invalid request such as
min_bid=5, max_bid=1is sentto the API as-is instead of being rejected client-side, defeating the purpose of
the validator.
Reproduction
Root Cause
src/marketdata/input_types/options.py:124The helper it calls (
src/marketdata/input_types/base.py:14) gates thecomparison behind a date check:
check_is_date(src/marketdata/utils.py:36) returnsFalsefor any non-date,non-string value, so for
floatpricesmin_is_date/max_is_dateare alwaysFalseand themin > maxcomparison is unreachable.Minor: the local variable is also misspelled
params_typles(should beparams_tuples).Suggested Fix
Validate numeric ranges with a numeric-aware check rather than the date helper.
For example, add a generic min/max helper on
BaseInputType:and call it from
OptionsChainInput.validate_inputfor the price pairs (keeping_validate_min_max_datesfor genuine date ranges likefrom_date/to_date).While here, consider extending the check to the other ordered numeric pairs in
the model that currently aren't validated at all, e.g.
min_open_interest/min_volumebounds if max counterparts exist, and fix theparams_typlestypo.
Recommendation
Add tests asserting that:
OptionsChainInput(min_bid=5, max_bid=1)raises a validation error,min_bid=1, max_bid=5) constructs without error,from_date/to_datestill works.