057bc4493e
Wraps the entire yfinance public API behind a single binary `yfin` with
51 subcommands across 13 namespaces (ticker, download, tickers, search,
lookup, market, sector, industry, calendars, screen, live, auth, config).
Output renders as Rich tables on TTY, JSON when piped; --format / --out
support table | json | ndjson | csv | tsv | parquet | yaml.
Highlights:
- 1857 LOC across 18 Python files under cli/yfin/
- Typer + Rich, packaged via hatchling + uv
- Install globally: `cd cli && uv tool install -e .`
- ~/.yfin/config.toml for persistent proxy/cookies/locale defaults
- Friendly YFRateLimitError handler (exit 2, no Rich traceback)
- Validated end-to-end with 33 live tests against Yahoo from a
residential exit (AAPL, MSFT, NVDA, options, screens, calendars,
financials, news, holders, parquet round-trip)
yfinance-tools.yaml is the single source of truth:
- tools (49) — every public yfinance entry point with parameters
- cli (13 groups) — exact CLI invocations, mapped back to tool names
- outputSchemas (27) — actual return shapes captured from live calls
- learnings (19) — IP rate-limit, crumb handshake, Typer gotchas,
screen-build wrapping rules, upstream stubs, etc.
CLAUDE.md documents the upstream codebase layout for future agents.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
"""`yfin calendars ...` — market-wide event calendars."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Optional
|
|
|
|
import typer
|
|
import yfinance as yf
|
|
|
|
from .._shared import render_via_state
|
|
|
|
|
|
app = typer.Typer(no_args_is_help=True, help="Market-wide event calendars.")
|
|
|
|
|
|
def _cal(start: Optional[str], end: Optional[str]) -> yf.Calendars:
|
|
return yf.Calendars(start=start, end=end)
|
|
|
|
|
|
@app.command("earnings")
|
|
def earnings(
|
|
ctx: typer.Context,
|
|
start: Optional[str] = typer.Option(None, "--start"),
|
|
end: Optional[str] = typer.Option(None, "--end"),
|
|
market_cap: Optional[float] = typer.Option(None, "--market-cap"),
|
|
filter_most_active: bool = typer.Option(True, "--filter-most-active/--no-filter-most-active"),
|
|
limit: int = typer.Option(12, "--limit"),
|
|
offset: int = typer.Option(0, "--offset"),
|
|
force: bool = typer.Option(False, "--force/--no-force"),
|
|
):
|
|
"""Earnings calendar."""
|
|
df = _cal(start, end).get_earnings_calendar(
|
|
market_cap=market_cap,
|
|
filter_most_active=filter_most_active,
|
|
start=start, end=end,
|
|
limit=limit, offset=offset, force=force,
|
|
)
|
|
render_via_state(ctx, df)
|
|
|
|
|
|
@app.command("ipo")
|
|
def ipo(
|
|
ctx: typer.Context,
|
|
start: Optional[str] = typer.Option(None, "--start"),
|
|
end: Optional[str] = typer.Option(None, "--end"),
|
|
limit: int = typer.Option(12, "--limit"),
|
|
offset: int = typer.Option(0, "--offset"),
|
|
force: bool = typer.Option(False, "--force/--no-force"),
|
|
):
|
|
"""IPO calendar."""
|
|
df = _cal(start, end).get_ipo_info_calendar(
|
|
start=start, end=end, limit=limit, offset=offset, force=force
|
|
)
|
|
render_via_state(ctx, df)
|
|
|
|
|
|
@app.command("economic")
|
|
def economic(
|
|
ctx: typer.Context,
|
|
start: Optional[str] = typer.Option(None, "--start"),
|
|
end: Optional[str] = typer.Option(None, "--end"),
|
|
limit: int = typer.Option(12, "--limit"),
|
|
offset: int = typer.Option(0, "--offset"),
|
|
force: bool = typer.Option(False, "--force/--no-force"),
|
|
):
|
|
"""Economic events calendar (CPI, FOMC, etc.)."""
|
|
df = _cal(start, end).get_economic_events_calendar(
|
|
start=start, end=end, limit=limit, offset=offset, force=force
|
|
)
|
|
render_via_state(ctx, df)
|
|
|
|
|
|
@app.command("splits")
|
|
def splits(
|
|
ctx: typer.Context,
|
|
start: Optional[str] = typer.Option(None, "--start"),
|
|
end: Optional[str] = typer.Option(None, "--end"),
|
|
limit: int = typer.Option(12, "--limit"),
|
|
offset: int = typer.Option(0, "--offset"),
|
|
force: bool = typer.Option(False, "--force/--no-force"),
|
|
):
|
|
"""Upcoming stock-splits calendar."""
|
|
df = _cal(start, end).get_splits_calendar(
|
|
start=start, end=end, limit=limit, offset=offset, force=force
|
|
)
|
|
render_via_state(ctx, df)
|