aynse
aynse is a lean, modern python library for fetching data from the national stock exchange (nse) of india. it includes a resilient http client (http/2, retries with jitter, connection pooling), adaptive batching, and efficient streaming utilities.
features
- historical data: canonical stock, index, derivative, and index valuation records
- archive datasets: bhavcopy, full bhavcopy, F&O bhavcopy, index bhavcopy, bulk deals, and index constituents
- live market data: standardized quotes, option chains
- mutual funds: official AMFI scheme search, latest and historical NAVs, comparisons, and NAV-based analytics
- cli: simple commands for quick downloads
- resilient networking: http/2, connection pooling, retries with exponential backoff, rate limiting, circuit breaker
- batching & streaming: adaptive concurrency and low-memory processing
- comprehensive type hints: full typing support for ide autocomplete
- extensive test coverage: robust test suite for reliability
- streaming utilities: chunked CSV/JSON/ZIP processing for larger files
installation
install aynse directly from pypi:
pip install aynse
for development:
pip install aynse[dev]
# or
pip install -r requirements.dev.txt
etymology / musings
aynse is a portmanteau of "ayn" from miss ayn rand and "nse" from national stock exchange. ayn rand was a russian-american writer and philosopher known for her philosophy of objectivism, which emphasizes individualism and rational self-interest. among other things, she was a strong advocate for laissez-faire capitalism.
the name serves as a fun ironical reminder of the library's purpose: to provide a tool for individuals to access and analyze financial data independently, without relying on large institutions or complex systems.
in a cruel twist of fate, this open source library wouldn't be encouraged under ayn rand's philosophy, as she discouraged altruism and believed in the pursuit of one's own happiness as the highest moral purpose.
and as the final act of irony, we gather to use this library to analyze financial markets while generating zero (and possibly, negative) intrinsic value for humankind as a whole - this is capitalism.
quick start
get historical stock data
retrieve historical data for a stock as a pandas dataframe:
from aynse import stock_df
df = stock_df(
symbol="reliance",
from_date="2024-01-01",
to_date="2024-01-31",
)
print(df[["date", "symbol", "open", "close"]].head())
archive datasets
from aynse import bhavcopy_raw, bhavcopy_save
records = bhavcopy_raw("2024-07-26")
print(records[0])
path = bhavcopy_save("2024-07-26", "downloads/")
print(path)
get live stock quote
fetch live price information for a stock:
from aynse import NSELive
live = NSELive()
quote = live.stock_quote("INFY")
print(quote["symbol"])
print(quote["company_name"])
print(quote["price"]["last"])
print(quote["price"]["change_percent"])
get option chain data
fetch option chain for index or equity:
from aynse import NSELive, summarize_option_chain
live = NSELive()
chain = live.equities_option_chain("RELIANCE")
summary = summarize_option_chain(chain)
print(summary["at_the_money_strike"])
print(summary["put_call_ratio"])
print(summary["max_pain"])
print(summary["at_the_money_implied_volatility"])
metadata
from aynse import dataset_capabilities, supported_indices
print(dataset_capabilities()["historical"]["outputs"])
print(supported_indices()[:3])
mutual funds
from aynse import mutual_fund_search, mutual_fund_summary, compare_mutual_funds
matches = mutual_fund_search("Parag Parikh Flexi Cap Direct Growth")
scheme_code = matches[0]["scheme_code"]
summary = mutual_fund_summary(scheme_code, "2025-09-01", "2026-09-01")
print(summary["scheme"]["scheme_name"])
print(summary["metrics"])
comparison = compare_mutual_funds(
[scheme_code, "120503"],
"2025-09-01",
"2026-09-01",
)
print(comparison["from_date"], comparison["to_date"])
Mutual-fund prices are end-of-day NAVs published by AMFI, not live exchange
quotes. Return metrics are NAV returns, not total returns for IDCW options;
cash distributions, loads, taxes, and investor cash flows are excluded. AMFI
limits each historical download to 90 days, which aynse chunks automatically.
Multi-fund comparisons retain only NAV dates shared by all selected schemes
and recompute every metric from those exact observations, so return windows
remain like-for-like.
canonical contracts
accepted inputs
All public date boundaries accept:
datetime.datedatetime.datetime"YYYY-MM-DD"
Symbols are normalized at the boundary, so "reliance" and "RELIANCE" resolve the same way for symbol-based APIs.
historical record shape
stock_raw(...) returns rows like:
{
"date": date(2024, 1, 1),
"symbol": "RELIANCE",
"series": "EQ",
"open": 2850.0,
"high": 2875.0,
"low": 2832.0,
"close": 2868.0,
"previous_close": 2844.0,
"last_traded_price": 2867.5,
"volume": 1234567,
}
Time-series datasets are returned in chronological ascending order.
archive contract
Archive families follow the same triplet:
bhavcopy_raw(...),bhavcopy_df(...),bhavcopy_save(...)full_bhavcopy_raw(...),full_bhavcopy_df(...),full_bhavcopy_save(...)bhavcopy_fo_raw(...),bhavcopy_fo_df(...),bhavcopy_fo_save(...)bhavcopy_index_raw(...),bhavcopy_index_df(...),bhavcopy_index_save(...)bulk_deals_raw(...),bulk_deals_df(...),bulk_deals_save(...)index_constituent_raw(...),index_constituent_df(...),index_constituent_save(...)
live contract
live methods return stable top-level payloads. For example:
{
"symbol": "INFY",
"company_name": "Infosys Limited",
"price": {
"last": 1520.5,
"change": 12.4,
"change_percent": 0.82,
},
}
Option-chain methods return:
symbolmarket_typetimestampunderlying_valueexpiry_datesstrike_pricesrecordssummary
The summary includes call/put open interest, changes in open interest, traded volume, PCR, ATM strike and implied volatility, strongest call/put walls, and the open-interest-weighted max-pain strike.
public API highlights
historical + archives
stock_raw,stock_df,stock_csvindex_raw,index_df,index_csvindex_pe_raw,index_pe_dfderivatives_raw,derivatives_df,derivatives_csvbhavcopy_*,full_bhavcopy_*,bhavcopy_fo_*,bhavcopy_index_*bulk_deals_*index_constituent_*expiry_dates
live + metadata
NSELive.stock_quote,stock_quote_fno,trade_info,market_statusNSELive.option_chain_contract_info,index_option_chain,equities_option_chain,currency_option_chainNSELive.corporate_announcements,corporate_actions,results_calendarNSELive.metadatadataset_capabilities,supported_indices,supported_instruments,supported_event_categories
mutual funds
mutual_fund_latest_raw,mutual_fund_searchmutual_fund_history_raw,mutual_fund_history_dfmutual_fund_summary,analyze_mutual_fund,compare_mutual_fundsAMFIMutualFunds
analytics
add_returnsadd_rolling_volatility(configurable annualization period)add_moving_average(simple or exponential)add_rsiadd_atradd_bollinger_bandsadd_drawdownadd_gap_metricsadd_volume_metricssummarize_option_chainanalyze_event_window
CLI
# historical stock data
aynse stock -s RELIANCE -f 2024-01-01 -t 2024-03-31 -o reliance_q1.csv
# live quote
aynse quote -s RELIANCE
# archive download
aynse bhavcopy -d downloads/ -f 2024-07-26
# holidays
aynse holidays -y 2024
# AMFI mutual-fund discovery and NAV analytics
aynse mf search "Parag Parikh Flexi Cap Direct Growth"
aynse mf analyze -s 122639 -f 2025-09-01 -t 2026-09-01
testing
# deterministic/offline contracts
pytest -m offline -v --tb=short
# live NSE/RBI integration checks
pytest -m live -v --tb=short
# end-to-end integration checks
pytest -m e2e -v --tb=short
# full suite (offline + live)
pytest tests -v --tb=short
release workflow
releases are automated after the test workflow succeeds on master.
- make your changes and bump the version
make bump-patch # or bump-minor, bump-major
- commit and push to
master
git commit -am "Bump version to X.Y.Z"
git push
if X.Y.Z is not already published, github actions builds and verifies the
wheel and source distribution, publishes both to pypi, creates tag vX.Y.Z,
and creates the github release. live NSE tests remain advisory because upstream
availability is outside the package's control.
everything to do with release/version control
show current version
python scripts/bump_version.py --current
bump versions (updates pyproject.toml only)
python scripts/bump_version.py patch # 1.1.0 -> 1.1.1 python scripts/bump_version.py minor # 1.1.0 -> 1.2.0 python scripts/bump_version.py major # 1.1.0 -> 2.0.0 python scripts/bump_version.py --set 2.0.0 # set exact version
preview changes without modifying
python scripts/bump_version.py patch --dry-run
documentation
contributing
contributions are welcome. Please add or update contract tests whenever you change a public schema, accepted input, or save behavior.
license
this project has a (custom) mit* license but extends limitations. if you're an agency/corporate with >2 employees, you cannot wrap this project or use it without prior written permission from the author. if you're an individual, you can use it freely for personal projects.
this project is not intended for commercial use without prior permission. if caught using this project in violation of the license, it may result in automated reporting and/or legal action.
please see the license file for more details.
Release files for aynse 2.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aynse-2.3.2.tar.gz | 119.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aynse-2.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:201.7 kB
Release files / aynse-2.3.2.tar.gz
| Download URL | aynse-2.3.2.tar.gz |
|---|---|
| Size | 119.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4ac45ab36e5740360cf138e76e80d504d4a828337f93eb7cdb576ef45a5b7dec
|
|
BLAKE2b-256 checksum How to use checksums |
cda579910c00e7852a8d4459e3c0156c0cbf76be0f8539bd3ced4979a9246254
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / aynse-2.3.2-py3-none-any.whl
| Download URL | aynse-2.3.2-py3-none-any.whl |
|---|---|
| Size | 82.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7fa941ae11aaa28b60003d79d9e88f1a552a98c747e872cce3728037579617b8
|
|
BLAKE2b-256 checksum How to use checksums |
4bb9adc642563b9ac63f61b632100df01277749edc633f86a463caf309ac23a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|