Metadata-Version: 2.4
Name: sfin-client
Version: 0.1.0
Summary: Unofficial Python client for the hosted sfin StockAnalysis data API.
Project-URL: Homepage, https://api.sfin.bluedoor.sh/v1/health
Project-URL: API, https://api.sfin.bluedoor.sh/v1/openapi.json
Project-URL: Documentation, https://github.com/bluedoor-ai/sfin#readme
Project-URL: Source, https://github.com/bluedoor-ai/sfin
Author-email: BlueDoor <sam@bluedoor.sh>
License: MIT
Keywords: finance,market-data,sfin,stockanalysis,stocks
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: certifi>=2024.2.2
Provides-Extra: fast
Requires-Dist: curl-cffi>=0.7; extra == 'fast'
Description-Content-Type: text/markdown

# sfin-client

Unofficial Python client for the hosted `sfin` StockAnalysis data API.

The hosted API exposes CP2-confirmed public StockAnalysis.com contracts behind
a cached, rate-limited REST surface. It is not affiliated with, endorsed by, or
sponsored by StockAnalysis.com.

## Install

```bash
pip install sfin-client
```

## Quick Start

```python
from sfin_client import Client

client = Client(contact="you@example.com")

quote = client.quote("AAPL")
chart = client.chart("AAPL", period="1M")
fx = client.exchange_rates()

news = client.news_search("apple")
symbols = client.search("apple")

bulk = client.screener_bulk(
    fields=["price", "volume", "marketCap"],
    country="CA",
)
returns = client.compare_returns(["AAPL", "NVDA"])
```

Convenience wrappers are also available:

```python
import sfin_client

data = sfin_client.quote("AAPL")
news = sfin_client.news_search("semiconductors")
fx = sfin_client.exchange_rates()
```

The `sfin` import path is included as a compatibility alias:

```python
from sfin import Client
```

## Common Methods

- `Client.health()`, `Client.endpoints()`, and `Client.openapi()` expose
  discovery metadata.
- `Client.quote(symbol)` and `Client.chart(symbol, period=...)` expose
  StockAnalysis quote/chart snapshots.
- `Client.dividends(symbol)`, `Client.earnings(symbol)`, and
  `Client.financials_widget(symbol, period="quarterly")` expose per-symbol
  fundamentals widgets.
- `Client.quotes_bulk(symbols)`, `Client.watchlist(symbols, columns=...)`,
  `Client.multi_chart(symbols)`, and `Client.compare_returns(symbols)` wrap
  the multi-symbol endpoints.
- `Client.news_fetch(symbol)`, `Client.news_search(query)`,
  `Client.news_bulk(symbols)`, and `Client.news_fresh(symbol)` expose
  StockAnalysis news routes.
- `Client.screener_field(field)` and `Client.screener_bulk(fields, country=...)`
  expose the anonymous screener surface. Field names are camelCase, such as
  `marketCap`, `peRatio`, and `epsGrowth`.
- `Client.aggregation(table_id="industries_by_sector", cols=...)`,
  `Client.exchange_rates()`, and `Client.search(query)` cover aggregation, FX,
  and symbol lookup.

Set `SFIN_BASE_URL`, `SFIN_CONTACT`, or `SFIN_API_KEY` in the environment to
configure the default client.

The hosted API and SDK expose friendly public routes only. Source endpoint IDs,
raw passthrough routes, origin URL templates, and internal validation routes are
not part of the production surface.

## Rate Limits

The production API currently enforces the validated hosted limits:

- Anonymous: 1,200 requests/minute, 60 origin misses/minute.
- Contact header: 6,000 requests/minute, 600 origin misses/minute.
- API key: 30,000 requests/minute, 3,000 origin misses/minute.

Pass `contact="you@example.com"` or set `SFIN_CONTACT` to use the contact tier.
Manual API keys, when configured, are sent with `api_key=...` or `SFIN_API_KEY`.
