Metadata-Version: 2.4
Name: angelone-connect
Version: 2.0.1
Summary: A Zerodha-Kite-Connect-shaped, Python SDK for Angel One SmartAPI: market data, historical OHLC, options chains/Greeks, portfolio, orders, and streaming.
Author-email: Mahesh Kumar <maheshrajbhar90@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/maheshrajbhar90/angelone-connect.git
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas>=1.3.0
Requires-Dist: numpy>=1.21.0
Requires-Dist: requests>=2.25.0
Requires-Dist: pytz>=2020.1
Requires-Dist: pyotp>=2.6.0
Requires-Dist: cachetools>=4.2.0
Requires-Dist: smartapi-python>=1.4.0
Requires-Dist: logzero>=1.7.0
Requires-Dist: websocket-client>=1.2.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Dynamic: license-file

# angelone-connect

A production-grade, **Zerodha-Kite-Connect-shaped** Python SDK for Angel One's SmartAPI. It covers market data, historical OHLC, options chains/Greeks, portfolio, orders, and live streaming behind a clean, typed, provider-neutral interface — so a TradingBot can depend on this SDK's shapes and swap providers (Angel One today; Zerodha/Yahoo Finance/NSE adapters later) without touching call sites.

> **v2.0.0** is a ground-up rewrite, published under a new PyPI name (`angelone-connect`, previously `smartapi_login`). If you're upgrading from the old `smartapi_login` 1.x package, see [Migrating from 1.x](#migrating-from-1x) below — your old code keeps working via a deprecated compatibility shim, you just need to `pip install angelone-connect` and change your top-level import from `smartapi_login` to `angelone_connect`.

## Install

```bash
pip install angelone-connect
```

## Quick start

```python
from angelone_connect import Config, SmartAPIClient

config = Config(
    api_key="YOUR_API_KEY",
    client_code="YOUR_CLIENT_CODE",
    password="YOUR_MPIN_OR_PASSWORD",
    totp_secret="YOUR_TOTP_SECRET",
)
client = SmartAPIClient(config)
client.login()

client.quote("NSE:INFY")                                      # full quote
client.ltp("NSE:INFY", "NSE:TCS")                             # {"NSE:INFY": 1500.0, ...}
client.historical_data("INFY", "day", "2024-01-01", "2024-06-01")
client.option_chain("NIFTY", expiry, spot_symbol="Nifty 50")
client.positions()
client.holdings()
client.margins()
client.orders()
```

Every method returns typed dataclasses (`Quote`, `HistoricalCandle`, `OptionChain`, `Holding`, `Position`, `Order`, ...) from `angelone_connect.models`, not raw dicts.

**Equity symbols just work.** Angel One's instrument master uses a `"-EQ"` series suffix for NSE equities (`"RELIANCE-EQ"`) but a plain, un-suffixed symbol for the same stock on BSE (`"RELIANCE"`). You never need to know this: pass the bare company symbol (`"RELIANCE"`, `"TCS"`, `"INFY"`) — with or without an `"NSE:"`/`"BSE:"` exchange prefix — to `quote()`/`ltp()`/`ohlc()`/`historical_data()`/`place_order()`/etc. and the SDK resolves NSE's `-EQ` listing first, falling back to BSE automatically if the stock isn't listed on NSE at all. Already-qualified symbols (`"RELIANCE-EQ"`, option/future contract symbols, index names) still match exactly, so this never interferes with non-equity lookups.

## Architecture

```
angelone_connect/
    auth/           session management: TOTP login, token refresh, thread safety
    instruments/    instrument master download/cache, symbol<->token, lot/tick size
    market/         quote() / ltp() / ohlc() — Angel One's getMarketData
    historical/     historical_data() with automatic chunking + week/month resampling
    options/        option_chain(), Greeks, PCR, max pain, ATM/ITM/OTM tagging
    derivatives/    OI build-up, put/call ratio, gainers/losers (real Angel One endpoints)
    portfolio/      holdings(), positions(), margins(), pnl(), allocation()
    orders/         place/modify/cancel orders, order book, trade book
    websocket/      SmartTicker — live tick streaming (LTP/quote/full modes)
    quant/          beta, alpha, ATR, volatility, drawdown, correlation — pure math over candles
    providers/      pluggable interfaces for data Angel One doesn't expose (see below)
    models/         typed dataclasses shared by every module
    utils/          retry with backoff, rate limiting, structured logging, parsing helpers
    cache/          thread-safe TTL cache (instrument master, quotes)
    exceptions.py   one exception hierarchy; SmartApi's raw exceptions are translated into it
    client.py       SmartAPIClient — the Zerodha-shaped facade over everything above
```

`SmartAPIClient` is the one class most consumers need; the per-domain modules underneath (`client.market`, `client.options`, `client.portfolio`, ...) are available directly if you want finer-grained control.

## What's real vs. pluggable

Angel One's SmartAPI genuinely exposes: live quotes, historical OHLC, option Greeks, put/call ratio, OI build-up (long/short build-up, short covering, long unwinding), a gainers/losers scanner, holdings/positions/margins, orders, and WebSocket streaming. All of that is implemented for real in this SDK, backed by the actual `SmartConnect` methods (`getMarketData`, `getCandleData`, `optionGreek`, `putCallRatio`, `oIBuildup`, `gainersLosers`, `holding`, `position`, `rmsLimit`, `placeOrder`, ...).

Angel One does **not** expose fundamentals, macro indicators, news, broad FII/DII rupee flows, delivery %, block/bulk deals, or market breadth at all — there's no API to wrap. Those modules (`angelone_connect.providers.*`) ship as typed ABC interfaces you register a concrete adapter against:

```python
from angelone_connect.providers import fundamentals

class MyYFinanceFundamentals(fundamentals.FundamentalsProvider):
    def fetch_fundamentals(self, symbol):
        ...  # wrap yfinance, NSE, or any source you like
    # ... implement the rest of the interface

fundamentals.set_provider(MyYFinanceFundamentals())
fundamentals.fetch_fundamentals("RELIANCE")  # now works
```

Until a provider is registered, calling these functions raises `ProviderNotConfiguredError` rather than returning fake data. The same pattern applies to `providers.institutional`, `providers.macro`, `providers.news`, and `providers.market_breadth`.

`quant.risk` (beta, alpha, correlation, ATR, historical/realized volatility, drawdown, rolling returns, Sharpe) is **not** a provider stub — it's pure math computed from candles you already fetch via `historical_data()`, so it's implemented for real with no external dependency.

## Options

```python
from datetime import date

expiries = client.expiry_list("NIFTY")
chain = client.option_chain("NIFTY", expiries[0], spot_symbol="Nifty 50", spot_exchange="NSE")

chain.pcr            # OI-based put/call ratio for this expiry
chain.max_pain        # strike minimizing aggregate option-writer payout
chain.atm_strike
for call in chain.calls:
    call.strike, call.ltp, call.open_interest, call.moneyness, call.greeks.delta
```

`spot_symbol` matters: Angel One's instrument master doesn't use the same string for an index's option-chain grouping (`"NIFTY"`) and its tradable spot quote (often `"Nifty 50"`). Use `client.instruments.search("NIFTY")` to find the exact spot symbol for your account before relying on ATM tagging in production. If it can't be resolved, `spot_price`/`atm_strike`/`moneyness` come back as `None` rather than a guess.

## Streaming

```python
ticker = client.ticker()
ticker.on_ticks = lambda ticks: print(ticks)
ticker.connect(threaded=True)
ticker.subscribe([("NSE", "3045"), ("NFO", "50001")], mode="full")
```

Reconnection, resubscription, and heartbeats are handled by Angel One's own `SmartWebSocketV2` under the hood.

## Quant / risk

```python
from angelone_connect.quant import risk

candles = client.historical_data("INFY", "day", "2023-01-01", "2024-01-01")
benchmark = client.historical_data("NIFTY 50", "day", "2023-01-01", "2024-01-01", exchange="NSE")

risk.beta(candles, benchmark)
risk.atr(candles, period=14)
risk.historical_volatility(candles, window=21)
risk.max_drawdown(candles)
risk.risk_metrics(candles, benchmark=benchmark)   # bundles the above + Sharpe
```

Also available as `client.get_volatility_snapshot(symbol, benchmark_symbol=...)`.

## Reliability

- **Retries**: every call to Angel One is wrapped with exponential backoff + jitter (`Config.retry`), and a `TokenExpiredError` triggers an automatic session refresh before retrying — see `angelone_connect.utils.retry` and `angelone_connect._base.BaseAPI._call`.
- **Rate limiting**: a thread-safe token-bucket limiter (`Config.rate_limit`) throttles calls before they hit Angel One's per-endpoint ceilings.
- **Caching**: the instrument master is downloaded once and cached for `Config.instrument_cache_ttl` seconds (default 24h); override per-deployment.
- **Exceptions**: every error surfaces as a `angelone_connect.exceptions.SmartAPIError` subclass (`AuthenticationError`, `TokenExpiredError`, `RateLimitError`, `OrderError`, `InstrumentNotFoundError`, ...) — SmartApi's raw `smartExceptions` are translated automatically.
- **Thread safety**: `SessionManager` guards token state with per-connection locks so multiple modules can share one session across threads.

## Migrating from 1.x

The old `SmartAPIHelper` class still works, via a deprecated shim (`angelone_connect.legacy.SmartAPIHelper`) that forwards onto `SmartAPIClient`:

```python
from angelone_connect import SmartAPIHelper  # emits a DeprecationWarning

api = SmartAPIHelper()
api.login(api_key_hist="...", api_key_trading="...", uid="...", mpin="...", totp="...")
api.get_ltp("WIPRO")
api.get_ohlc("BANKNIFTY", "FIVE_MINUTE", "2024-01-01", "2024-02-01")  # still returns a DataFrame
```

New code should use `SmartAPIClient` directly — it's the same session under the hood, plus options/portfolio/orders/streaming/quant modules the 1.x helper never had. `get_tradingsymbols()`, mentioned in older docs, was never actually implemented in 1.x and has been dropped rather than carried forward broken.

## Testing

```bash
pip install -e ".[dev]"
pytest
```

The test suite is fully mocked (no live Angel One credentials or network calls required) — it patches `SmartConnect`/`SmartWebSocketV2` and instrument-master HTTP responses to verify request construction, response normalization, retry/refresh behavior, rate limiting, and the option-chain/quant math.

## Disclaimer

This is an independent, community-maintained SDK. It is not affiliated with or endorsed by Angel One or Zerodha. Angel One's SmartAPI field names and per-endpoint rate/history limits are sparsely documented and can change; this SDK parses responses defensively (falling back to `None` rather than crashing on a missing/renamed field) but you should still verify behavior against your own account before trading with it.
