Skip to main content

Unofficial async Python client for Nepal Stock Exchange (NEPSE)

Project description

nepseman-api

Unofficial, reverse-engineered REST + WebSocket API for Nepal Stock Exchange (NEPSE) market data. Not affiliated with NEPSE or nepalstock.com.np. Use at your own risk.

nepseman-api scrapes and serves live NEPSE data by reverse-engineering the authentication layer of nepalstock.com.np — including WASM-based token obfuscation and salt-based payload signing — with no dependency on any third-party NEPSE library.


Quick Start

Option 1 — Use the live hosted API (no setup needed)

Base URL: https://nepseman-api-production.up.railway.app

# Market status
curl https://nepseman-api-production.up.railway.app/api/v1/market/status

# Today's prices
curl https://nepseman-api-production.up.railway.app/api/v1/prices/today

# Top gainers
curl https://nepseman-api-production.up.railway.app/api/v1/prices/top/gainers

# NEPSE index
curl https://nepseman-api-production.up.railway.app/api/v1/indices/nepse

# Company details
curl https://nepseman-api-production.up.railway.app/api/v1/securities/NABIL

Interactive docs: https://nepseman-api-production.up.railway.app/docs


Option 2 — Install and run locally

Via pip (from GitHub):

pip install git+https://github.com/dipalkatuwal/nepseman-api.git

Then run:

nepseman-api
# → http://localhost:8000

Via Docker:

git clone https://github.com/dipalkatuwal/nepseman-api.git
cd nepseman-api
cp .env.example .env
docker compose up -d

API available at http://localhost:8000 · Docs at http://localhost:8000/docs


Features

  • Zero third-party NEPSE dependency — auth implemented from scratch using NEPSE's own WASM binary
  • Fully async — built on httpx + asyncio + asyncpg, non-blocking end to end
  • PostgreSQL persistence — every price fetch saved via SQLAlchemy async ORM, queryable with pagination and filtering
  • Alembic migrations — schema versioned and reproducible
  • WebSocket support — subscribe to live market data streams
  • CSV export — any list endpoint supports ?fmt=csv
  • Symbol validation — validate tickers with fuzzy suggestions
  • TTL caching — live data cached 30s, stable data 10 min
  • Rate limiting — per-IP rate limits via slowapi
  • Docker readydocker-compose up starts everything

Tech Stack

  • FastAPI + Uvicorn — async web framework
  • httpx — async HTTP client (~3× faster than requests)
  • wasmtime — runs NEPSE's own .wasm binary for token decoding
  • SQLAlchemy (async) + asyncpg — PostgreSQL ORM
  • Alembic — database migrations
  • slowapi — per-IP rate limiting
  • pydantic-settings — env-based config

Project Structure

nepseman-api/
├── app/
│   ├── main.py                  # FastAPI app — rate limiting, cache headers, health
│   ├── core/
│   │   ├── auth.py              # WASM token parser + payload calculator
│   │   ├── cache.py             # TTL in-memory cache + @cache.ttl decorator
│   │   ├── config.py            # Settings (env vars via pydantic-settings)
│   │   ├── endpoints.py         # All NEPSE endpoint paths
│   │   ├── nepse.wasm           # NEPSE's own WASM binary (bundled)
│   │   ├── session.py           # Async authenticated HTTP session (httpx)
│   │   └── symbols.py           # Symbol validation + fuzzy suggestions
│   ├── db/
│   │   ├── database.py          # SQLAlchemy async engine + session factory
│   │   ├── models.py            # ORM models: MarketSnapshot, MarketSummary
│   │   └── repository.py        # DB queries (save, get, paginate)
│   ├── services/
│   │   └── nepse.py             # All data functions — async + cached
│   ├── models/
│   │   └── responses.py         # Pydantic response models
│   └── api/
│       └── routes/
│           ├── market.py        # /api/v1/market/*
│           ├── prices.py        # /api/v1/prices/*
│           ├── indices.py       # /api/v1/indices/*
│           ├── securities.py    # /api/v1/securities/*
│           ├── meta.py          # /api/v1/floorsheet/*
│           └── ws.py            # /ws  WebSocket
├── alembic/
│   └── versions/
│       └── 001_create_market_tables.py
├── scripts/
│   └── test_all.py
├── tests/
│   ├── test_auth.py
│   └── test_api.py
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── .env.example

API Reference

System

Method Endpoint Description
GET / Service info
GET /health Uptime, last sync, cache stats
POST /cache/clear Clear all cached data
WS /ws WebSocket live stream

Market

Method Endpoint Description
GET /api/v1/market/status Open/closed status
GET /api/v1/market/summary Today's market summary
GET /api/v1/market/supply-demand Supply & demand

Prices

Method Endpoint Description
GET /api/v1/prices/today All stock prices (auto-persisted to PostgreSQL)
GET /api/v1/prices/today?fmt=csv Download as CSV
GET /api/v1/prices/today?persist=false Fetch without saving to DB
GET /api/v1/prices/live Live market data
GET /api/v1/prices/top/gainers Top gainers
GET /api/v1/prices/top/losers Top losers
GET /api/v1/prices/top/turnover Top by turnover
GET /api/v1/prices/top/trade Top by trade count
GET /api/v1/prices/top/transaction Top by transactions

PostgreSQL Snapshots

Method Endpoint Description
GET /api/v1/prices/snapshots Query persisted snapshots (paginated)
GET /api/v1/prices/snapshots?symbol=NABIL Filter by symbol
GET /api/v1/prices/snapshots?business_date=2025-06-09 Filter by date
GET /api/v1/prices/snapshots?limit=100&offset=0 Pagination
GET /api/v1/prices/snapshots/{symbol}/latest Latest snapshot for a symbol

Indices

Method Endpoint Description
GET /api/v1/indices/nepse NEPSE index
GET /api/v1/indices/subindices All sub-indices
GET /api/v1/indices/graph/{index_name} Index graph data

Securities

Method Endpoint Description
GET /api/v1/securities/companies All listed companies
GET /api/v1/securities/list Securities list
GET /api/v1/securities/sectors Grouped by sector
GET /api/v1/securities/validate/{symbol} Validate + fuzzy suggestions
GET /api/v1/securities/{symbol} Company details
GET /api/v1/securities/{symbol}/history OHLCV price history
GET /api/v1/securities/{symbol}/depth Market depth
GET /api/v1/securities/history/bulk?symbols=NABIL,NICA Parallel bulk OHLCV

Floorsheet

Method Endpoint Description
GET /api/v1/floorsheet/ Full floorsheet (paginated)
GET /api/v1/floorsheet/{symbol} Floorsheet for a company

WebSocket

Connect to ws://localhost:8000/ws

{ "route": "live_market" }
{ "route": "subscribe", "channel": "live_market", "interval": 10 }
{ "route": "unsubscribe", "channel": "live_market" }

Testing

# Unit tests (no network or DB needed)
pytest tests/ -v

# Smoke test all endpoints (Nepal IP + running server required)
python scripts/test_all.py

Troubleshooting

Error Cause Fix
SSL: CERTIFICATE_VERIFY_FAILED Incomplete NEPSE cert chain Set NEPSE_VERIFY_SSL=false in .env
403 / connection refused Foreign IP geo-blocked Run from a Nepal network
Connection refused (5432) PostgreSQL not running docker-compose up postgres
Symbol 'XYZ' not found Invalid ticker Check /api/v1/securities/validate/XYZ
Token expired errors NEPSE session TTL Automatic — session re-authenticates every 45s

Deployment

Run Alembic migrations before (re)deploying

Always migrate the database before rolling out a new image so schema changes are applied before the app starts serving traffic:

docker compose run --rm nepse-api alembic upgrade head

This runs in a throwaway container against the live postgres service and exits cleanly when done.

Zero-downtime redeploy

Rebuild and restart only the API container without touching postgres or nginx:

docker compose up -d --no-deps --build nepse-api

--no-deps prevents Compose from restarting dependency services (postgres, nginx), so the database stays up and in-flight connections are unaffected. --build rebuilds the image from the current source before starting the new container. Docker Compose stops the old container and starts the new one with a brief gap (single-instance downtime); for true zero-downtime you would front this with nginx upstream health checks and run two API replicas.

Crash recovery

Both nepse-api and postgres are configured with restart: unless-stopped. If either crashes, Docker restarts it automatically without manual intervention. Combined with the healthcheck (/health polled every 30 s), Docker will also restart the container if it becomes unresponsive.

Full stack bring-up

# First run — build image, migrate, start everything
docker compose up -d --build
docker compose run --rm nepse-api alembic upgrade head

# Subsequent deploys
docker compose run --rm nepse-api alembic upgrade head
docker compose up -d --no-deps --build nepse-api

Disclaimer

This project is unofficial and not affiliated with NEPSE or nepalstock.com.np in any way. It reverse-engineers the public-facing web interface for educational and personal use. Data accuracy is not guaranteed. Do not use in production trading systems.


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nepseman_api-1.0.0.tar.gz (18.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nepseman_api-1.0.0-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

File details

Details for the file nepseman_api-1.0.0.tar.gz.

File metadata

  • Download URL: nepseman_api-1.0.0.tar.gz
  • Upload date:
  • Size: 18.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for nepseman_api-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a82ec5a14d11de4dfb1d24ec00c602394c52814e285ec4c476f80d77f76b877f
MD5 577ab8f38485d077aa2166729b175b68
BLAKE2b-256 24280f6231c7ea9ccaa333b8e46069984d4b2f5d8b12df8d39fc0fbc40b84aec

See more details on using hashes here.

File details

Details for the file nepseman_api-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: nepseman_api-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 16.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for nepseman_api-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6202976c1485f9eed38f9be4906b8ccd1a582d893d23c6903b4ef85de6b03906
MD5 17f074e5760a1f99c97d81a5f03ec8d4
BLAKE2b-256 21fe8995212b550f547c233a9e697cb1a8b0086477121a035efa8a581b187ba9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page