add range params

This commit is contained in:
Peter Hajas 2025-11-27 13:37:30 -07:00
parent e7968ac88d
commit b78b137508

View File

@ -30,6 +30,16 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
" no --expiration is provided)."
),
)
parser.add_argument(
"--exp-start",
type=int,
help="Start index (0-based) into the available expirations list.",
)
parser.add_argument(
"--exp-end",
type=int,
help="End index (0-based, exclusive) into the available expirations list.",
)
parser.add_argument(
"--calls-only",
action="store_true",
@ -44,6 +54,14 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
if args.calls_only and args.puts_only:
parser.error("Use only one of --calls-only or --puts-only.")
if args.expiration and (args.exp_start is not None or args.exp_end is not None):
parser.error("Use either --expiration or the exp-start/exp-end range, not both.")
if args.all_expirations and (args.exp_start is not None or args.exp_end is not None):
parser.error("Use either --all-expirations or the exp-start/exp-end range, not both.")
if args.exp_start is not None and args.exp_start < 0:
parser.error("--exp-start must be non-negative.")
if args.exp_end is not None and args.exp_end < 0:
parser.error("--exp-end must be non-negative.")
return args
@ -53,6 +71,8 @@ def pick_expirations(
requested: str | None,
include_all: bool,
default_limit: int | None,
range_start: int | None,
range_end: int | None,
) -> tuple[list[str], list[str]]:
available = list(ticker.options or [])
if not available:
@ -64,6 +84,17 @@ def pick_expirations(
f"Expiration {requested!r} not in available dates: {', '.join(available)}"
)
targets = [requested]
elif range_start is not None or range_end is not None:
start = range_start or 0
end = range_end if range_end is not None else len(available)
if start >= len(available):
raise ValueError(
f"--exp-start {start} is beyond available expirations (max index {len(available) - 1})."
)
end = min(end, len(available))
if start >= end:
raise ValueError("--exp-start must be less than --exp-end.")
targets = available[start:end]
elif include_all:
targets = available
else:
@ -113,12 +144,19 @@ def main(argv: list[str] | None = None) -> int:
default_limit = (
DEFAULT_EXPIRATION_LIMIT if args.expiration is None and not args.all_expirations else None
)
range_start = args.exp_start
range_end = args.exp_end
ticker = yf.Ticker(args.symbol)
try:
target_expirations, available_expirations = pick_expirations(
ticker, args.expiration, include_all_expirations, default_limit
ticker,
args.expiration,
include_all_expirations,
default_limit,
range_start,
range_end,
)
except (ValueError, RuntimeError) as exc:
print(f"error: {exc}", file=sys.stderr)