Metadata-Version: 2.4
Name: grynn-fplot
Version: 0.4.6
Summary: CLI tool for plotting financial data and analyzing options
Project-URL: Homepage, https://github.com/Grynn/grynn_cli_fplot
Project-URL: Issues, https://github.com/Grynn/grynn_cli_fplot/issues
Project-URL: Repository, https://github.com/Grynn/grynn_cli_fplot
Author-email: Grynn <vishal.doshi@gmail.com>
License: MIT
Keywords: cli,finance,options,plotting,stocks
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.12
Requires-Dist: click>=8.1.7
Requires-Dist: dateparser>=1.2.0
Requires-Dist: fastapi>=0.115.0
Requires-Dist: grynn-pylib
Requires-Dist: ipywidgets>=8.1.5
Requires-Dist: matplotlib>=3.9.2
Requires-Dist: mplcursors>=0.5.3
Requires-Dist: mplfinance>=0.12.9
Requires-Dist: pandas>=2.2.3
Requires-Dist: scikit-learn>=1.6.1
Requires-Dist: tabulate>=0.9.0
Requires-Dist: uvicorn>=0.32.0
Requires-Dist: yfinance
Provides-Extra: dev
Requires-Dist: ipykernel>=6.29.5; extra == 'dev'
Requires-Dist: ipython>=8.18.1; extra == 'dev'
Requires-Dist: mypy>=1.14.1; extra == 'dev'
Requires-Dist: pytest>=8.3.4; extra == 'dev'
Requires-Dist: ruff>=0.9.2; extra == 'dev'
Description-Content-Type: text/markdown

# fplot - Financial Plotting & Options Analysis CLI

[![PyPI version](https://img.shields.io/pypi/v/grynn-fplot.svg)](https://pypi.org/project/grynn-fplot/)
[![Python versions](https://img.shields.io/pypi/pyversions/grynn-fplot.svg)](https://pypi.org/project/grynn-fplot/)

A command-line tool for plotting comparative stock price history and analyzing options contracts.

## Installation

### From PyPI

```shell
pip install grynn-fplot
```

Or with uv:

```shell
uv tool install grynn-fplot
```

### From Source

For development, install the package in editable mode:

```shell
make dev
```

Or install locally:

```shell
make install  # Uses uv tool install .
```

## Usage

### Stock Plotting

```shell
fplot <ticker> [--since <date>] [--interval <interval>]
```

Examples:

- `fplot AAPL`
- `fplot AAPL --since 2020`
- `fplot AAPL,TSLA --since "mar 2023"`

#### Interactive Charts with Pre-fetched Data

**Fast, Interactive Navigation**: `fplot` pre-fetches up to 10 years of historical data for instant, smooth chart navigation:

- **10-year data pre-fetch**: Downloads and caches up to 10 years of price data regardless of `--since` parameter
- **`--since` controls view window**: The `--since` parameter sets the initial view range, not the data fetch range
- **24-hour cache**: Full dataset is cached for 24 hours for instant subsequent views
- **No network delays**: Pan and zoom through years of data without re-fetching

**Interactive Navigation** (matplotlib native features):
- **Pan**: Click and drag to move left/right through time
- **Zoom**: Use the zoom tool and select area, or scroll with mouse wheel
- **Home**: Reset to initial view
- **Hover**: Click on data points to see exact values

**Speed is the #1 priority**: Minimized time from typing command to seeing the chart.

Examples:
```shell
fplot AAPL                    # Opens chart with last 1 year (default), but 10 years cached
fplot AAPL --since "6m"       # Opens with 6-month view, full history available for panning
fplot AAPL --since "2020"     # Opens from 2020, can pan back to 2016 if data exists
```

### Options Listing

```shell
fplot <ticker> --call                  # List call options (default: 6 months max)
fplot <ticker> --put                   # List put options (default: 6 months max)
fplot <ticker> --call --max 3m         # List calls with 3 month max expiry
fplot <ticker> --put --all             # List all available put options
fplot <ticker> --call --min-dte 1y     # List long-dated calls (min 1 year)
fplot <ticker> --call --filter "dte>1y"  # Filter using time expressions
```

Examples:

- `fplot AAPL --call`
- `fplot TSLA --put --max 3m`
- `fplot AAPL --call --all`
- `fplot AAPL --call --min-dte 1y`  # Long-dated calls (1+ year)
- `fplot AAPL --call --min-dte 6m`  # Calls with 6+ months to expiry
- `fplot AAPL --call --filter "dte>10, dte<50"`  # 10-50 days to expiry
- `fplot AAPL --call --filter "dte>1y"`  # Options with 1+ year to expiry

The output format differs for calls and puts:

**Calls** include leverage and efficiency (useful for LEAPs):
```
AAPL 225C 35DTE ($5.25, 18.5%, 19.0x, eff:45)
AAPL 230C 35DTE ($3.10, 25.2%, 32.3x, eff:78)
```
Format: `TICKER STRIKE_C DTE (price, CAGR, leverage, eff:percentile)`

**Puts** display a table with spot price, expiry, strike, breakeven, volume, IV, and AR with premiums:
```
spot = $235.50

Expiry               Strike        Breakeven    Vol     IV   LT  AR: ask / bid / last
-------------------------------------------------------------------------------------
27/Mar/25 (35d)         220   $217.85 (-7.5%)    150   32%   1d  ask: $3.50 (28%) | bid: $2.80 (20%) | last: $3.10 (25%)
27/Mar/25 (35d)         215   $213.60 (-9.3%)     85   30%   3d  ask: $2.20 (18%) | bid: $1.60 (12%) | last: $1.90 (15%)
```

**Return metrics:**
- Calls: CAGR to breakeven
- Puts: AR = premium / capital-at-risk, annualized (capital-at-risk = strike - premium)

**Leverage & Efficiency (calls only):**
- Leverage: Implied leverage (Ω = Δ × S/O) where Δ is Black-Scholes delta, S is spot price, O is option price
  - Delta calculated using actual implied volatility from Yahoo Finance
  - Shows "N/A" if implied volatility is not available
  - Shows the percentage change in option value for a 1% change in stock price
  - Example: 10x leverage means a 1% stock move results in ~10% option move
- Efficiency: Percentile rank (0-100) of leverage/CAGR ratio
  - Higher = better (high leverage with low required stock movement)
  - 80+ = top 20% most efficient options
  - Shows "N/A" if leverage or return unavailable

**Expiry Filtering Options:**
- `--max <time>`: Filter to show only options expiring within the specified time
  - Examples: `3m` (3 months), `6m` (6 months), `1y` (1 year), `2w` (2 weeks), `30d` (30 days)
  - Default: `6m` (6 months)
- `--min-dte <time>`: Minimum days to expiry (useful for long-dated options)
  - Accepts plain days or time expressions: `300`, `1y`, `1.5y`, `6m`, `2w`
  - Examples: `--min-dte 1y` (1+ year), `--min-dte 6m` (6+ months)
  - Note: Using `--min-dte` automatically enables `--all` behavior
- `--all`: Show all available expiries (overrides `--max`)

**Advanced Filtering with `--filter`:**

The `--filter` option supports complex filter expressions with logical operators:

- **Syntax:**
  - Comma (`,`) represents AND operation
  - Plus (`+`) represents OR operation
  - Comparison operators: `>`, `<`, `>=`, `<=`, `=`, `!=`
  - Parentheses for grouping: `(expr1 + expr2), expr3`

- **Filter Fields:**
  - `dte`: Days to expiry
  - `volume`: Option volume
  - `price`: Last price
  - `return`, `ret`, `ar`: Return metric (CAGR for calls, AR for puts) - all aliases work
  - `strike_pct`, `sp`: Strike percentage above/below spot (positive = above spot, negative = below spot)
  - `lt_days`: Days since last trade (useful for filtering stale options)
  - `leverage`, `lev`: Implied leverage, calls only (Ω = Δ × S/O, using Black-Scholes delta)
  - `efficiency`, `eff`: Efficiency percentile, calls only (leverage/CAGR ratio, 0-100 scale)

- **Examples:**
  - `--filter "dte>300"` - Options with more than 300 days to expiry
  - `--filter "dte>10, dte<50"` - Options between 10-50 days (AND operation)
  - `--filter "dte<30 + dte>300"` - Short-term OR long-dated (OR operation)
  - `--filter "sp>5, sp<15"` - Strikes 5-15% above current spot price
  - `--filter "(dte>300 + dte<30), sp>5"` - Complex nested filters
  - `--filter "volume>=100"` - High volume options
  - `--filter "lt_days<=7"` - Options traded within last 7 days
  - `--filter "ar>50"` - Annualized return > 50%
  - `--filter "leverage>10"` - High leverage options (10x or more)
  - `--filter "lev>5, lev<20"` - Moderate leverage options (5x-20x)
  - `--filter "efficiency>80"` - Top 20% most efficient options
  - `--filter "eff>60, dte<60"` - Above-average efficiency with <60 days to expiry

- **Time Values:**
  - DTE-style expressions: `1y` (365 days), `6m` (180 days), `2w` (14 days)
  - Duration expressions: `2d15h`, `30m`, `1d` (converted to hours for duration fields)
  - Examples:
    - `--filter "dte>1y"` - Options with more than 1 year to expiry
    - `--filter "dte>6m"` - Options with more than 6 months to expiry
    - `--filter "lt_days<=7"` - Options traded in the last week

**Named Filter Presets:**

Save frequently used filters for quick reuse. Filters are separate for calls and puts,
stored in `~/.config/grynn_fplot/filters.json`.

```shell
# Save a put filter
fplot --put --save-filter vishal --filter "dte>7, lt_days<2d15h, sp<15, dte<33"

# Save a call filter
fplot --call --save-filter leaps --filter "dte>1y, sp>5"

# Use a saved filter
fplot AAPL --put --filter vishal
fplot AAPL --call --filter leaps

# List all saved filters (shows both calls and puts)
fplot --list-filters

# Delete a saved filter
fplot --put --delete-filter vishal

# Set a default filter (applied when no --filter is given)
fplot --put --default-filter vishal
fplot --call --default-filter leaps

# Clear the default
fplot --put --default-filter none
```

## Performance & Caching

**Price Data Caching**: Raw yfinance data is cached for 5 minutes to speed up repeated runs:
- Reduces network round-trips for quick re-runs and adjustments
- Cache stored in `~/.cache/grynn_fplot/`
- Short TTL ensures data stays fresh (splits, dividends are constantly updated)

**Options Data Caching**: Options data is cached for 1 hour to improve performance and reduce API calls.

## Alfred Workflow

Launch fplot charts directly from Alfred.

### Prerequisites
- [Alfred](https://www.alfredapp.com/) with Powerpack
- `fplot` installed and available on PATH (`uv tool install grynn-fplot` or `pip install grynn-fplot`)

### Install

**Option 1: Download from GitHub (Recommended)**

Download the pre-built workflow:
- [Latest release (attached to releases)](https://github.com/Grynn/grynn_cli_fplot/releases/latest/download/fplot.alfredworkflow)
- [Direct download from repository](https://github.com/Grynn/grynn_cli_fplot/raw/main/dist/fplot.alfredworkflow)

Double-click the downloaded file to install in Alfred.

**Option 2: Build from source**
1. Build the workflow: `make alfred`
2. Double-click `dist/fplot.alfredworkflow` to install in Alfred

### Usage
Type in Alfred:
- `fplot AAPL` — candlestick chart for AAPL (default 1 year)
- `fplot AAPL --since 2020` — chart from 2020
- `fplot AAPL,TSLA --since "mar 2023"` — comparative chart
- `fplot AAPL --call` — list call options

## TODO

- fplot --call | fzf lets you select a call; once a call is selected it should be possible to plot a chart for it (yfinance provides price history for option identifiers)
- need more examples of usage with fzf to pick a call
- use grynn_pylib to download options (does it have identifiers that can be used to fetch price history?)
