Skip to main content

Kkunal

A Python library for the Choice FINX Trading API. Supports REST API, Interactive WebSockets (order/trade updates), and Live Price Feed WebSockets (FIX3.0 compressed data).

Installation

pip install kkunal

All dependencies (requests, pycryptodome, websockets, pandas) are installed automatically.


Quick Start

from choice_api import ChoiceClient

client = ChoiceClient(
    vendor_id="YOUR_VENDOR_ID",
    vendor_key="YOUR_VENDOR_KEY",
    api_key="YOUR_JWT_BEARER_TOKEN",
    aes_key="YOUR_AES_KEY",
    aes_iv="YOUR_AES_IV"
)

# Login (TOTP flow is handled automatically)
session_id = client.login(mobile_no="1234567890")
print(f"Session ID: {session_id}")

Session Persistence

You can save and reload sessions to avoid logging in repeatedly during the same trading day:

session_file = "my_session.json"

if client.load_session(session_file):
    print("Restored today's session.")
else:
    client.login(mobile_no="1234567890")
    client.save_session(session_file)

Note: Sessions expire daily. load_session will return False if the saved session is from a previous day.


Scrip Master

The Scrip Master CSV is automatically downloaded when you log in. It maps instrument symbols to their tokens, lot sizes, and other metadata.

get_token(symbol, exchange=None)

Returns the token for a given symbol.

  • For NSE instruments, no exchange parameter is needed (returns NSE by default).
  • For BSE instruments, pass exchange="BSE" explicitly.
# NSE (default)
reliance_token = client.scrip_master.get_token("RELIANCE")

# BSE (must specify exchange)
reliance_bse_token = client.scrip_master.get_token("RELIANCE", exchange="BSE")

get_details(token)

Returns all CSV row details for a given token as a dictionary.

details = client.scrip_master.get_details("2885")
print(details)
# {'Exchange': 'NSE', 'Segment': '1', 'Token': '2885', 'Symbol': 'RELIANCE', ...}

get_lot_size(token)

Returns the market lot size for a token.

lot = client.scrip_master.get_lot_size("2885")
print(lot)  # 1 for equity, 250 for NIFTY futures, etc.

Orders

Important: Prices must be in paisa (multiply INR by 100). For F&O orders, qty must be in total shares (multiples of the lot size), not the number of lots.

client.orders.place_order(...)

Parameter Type Description
segment_id int 1 = NSE Cash, 2 = NSE F&O, 3 = BSE Cash
token int Instrument token from Scrip Master
order_type str "RL_MKT" = Market, "RL_LIMIT" = Limit
bs int 1 = Buy, 2 = Sell
qty int Total quantity in shares
price float Price in paisa (e.g., 1300 INR → 130000)
trigger_price float Trigger price in paisa (0 for non-SL orders)
validity int 1 = Day
product_type str "M" = Intraday (Margin), "D" = Delivery/CarryForward
disclosed_qty int Optional. Disclosed quantity (default 0)
response = client.orders.place_order(
    segment_id=1,
    token=2885,
    order_type="RL_MKT",
    bs=1,
    qty=1,
    price=0,
    trigger_price=0,
    validity=1,
    product_type="D"
)

client.orders.modify_order(...)

Modifies an existing order. Requires client_order_no, exchange_order_no, and gateway_order_no from the order book.

response = client.orders.modify_order(
    client_order_no=123456,
    exchange_order_no="1234567890",
    gateway_order_no="1234567890",
    segment_id=1,
    token=2885,
    order_type="RL_LIMIT",
    bs=1,
    qty=1,
    price=130000,
    trigger_price=0,
    validity=1,
    product_type="D"
)

client.orders.cancel_order(...)

Cancels an existing order. Same parameters as modify_order plus optional exchange_order_time.

client.orders.get_order_book()

Returns all orders placed during the current session.

order_book = client.orders.get_order_book()

client.orders.get_order_book_v2()

Returns the order book (version 2 format).

client.orders.get_order_by_no(order_no)

Returns details for a specific order number.

order = client.orders.get_order_by_no(123456)

client.orders.get_trade_book()

Returns all executed trades.

trades = client.orders.get_trade_book()

client.orders.get_order_messages(req_id)

Returns order-related messages for a given request ID.


Portfolio

client.portfolio.get_holdings()

Returns current holdings.

holdings = client.portfolio.get_holdings()

client.portfolio.get_net_position()

Returns net positions.

positions = client.portfolio.get_net_position()

client.portfolio.position_conversion(...)

Converts an open position from one product type to another (e.g., Intraday to Delivery).

Parameter Type Description
segment_id int Exchange segment
token int Instrument token
client_order_no int Client order number
buy_sell int 1 = Buy, 2 = Sell
quantity int Quantity to convert
product_type str Target product type
source_product_type str Current product type

client.portfolio.verify_dis(...)

Verifies eDIS (Electronic Delivery Instruction Slip) for delivery sell orders.

client.portfolio.get_dis_status()

Returns the current DIS verification status.


Funds

client.funds.get_funds_view()

Returns funds summary.

funds = client.funds.get_funds_view()

client.funds.get_funds_view_new()

Returns funds summary in the new format.

client.funds.process_payout(amount, bank_acc_no, product_type=0)

Initiates a fund withdrawal.

client.funds.payment_via_netbanking(amount, bank_acc_no, bank_ifsc_code, return_url, segment_id, product_type=0)

Initiates a net banking payment.

client.funds.payment_via_hdfc_upi(amount, bank_acc_no, user_vpa, segment_id, product_type=0)

Initiates a HDFC UPI payment.

client.funds.check_vpa(user_vpa)

Validates a UPI VPA address.

client.funds.payment_via_razorpay(amount, bank_acc_no, bank_ifsc_code, upi_id, segment_id, payment_type=0, product_type=0)

Initiates a RazorPay payment.

client.funds.payment_ack_response(transaction_id)

Acknowledges a payment transaction.


Market

client.market.get_market_status()

Returns current market status across all segments.

status = client.market.get_market_status()

client.market.get_user_profile()

Returns the authenticated user's profile.

profile = client.market.get_user_profile()

client.market.get_multiple_touchline(multiple_seg_token)

Returns touchline data for multiple instruments.

# Format: "SegmentId1,Token1|SegmentId2,Token2"
touchline = client.market.get_multiple_touchline("1,2885|1,11536")

Historical Data

client.historical.get_historical_data(segment_id, token, from_date, to_date, resolution)

Returns historical OHLCV data as a Pandas DataFrame.

Parameter Type Description
segment_id int Exchange segment
token int Instrument token
from_date str or int Start date ("YYYY-MM-DD" or seconds from 1980)
to_date str or int End date ("YYYY-MM-DD" or seconds from 1980)
resolution str "1" = 1 min, "5" = 5 min, "D" = Daily
df = client.historical.get_historical_data(
    segment_id=1,
    token=2885,
    from_date="2024-01-01",
    to_date="2024-12-31",
    resolution="D"
)
print(df.head())
#                   Time     Open     High      Low    Close   Volume  OI
# 0  2024-01-01 00:00:00  2501.00  2520.50  2490.00  2515.30  1234567   0

The returned DataFrame has columns: Time, Open, High, Low, Close, Volume, OI. Prices are automatically adjusted using the PriceDivisor from the API response.


Interactive WebSockets

Receives live order updates, trade confirmations, and market status events.

import asyncio
from choice_api import InteractiveSocketClient

async def main():
    ws = InteractiveSocketClient(token=client.session_id)

    ws.on("ORD_NRML", lambda data: print(f"Order Update: {data}"))
    ws.on("TRD_MSG", lambda data: print(f"Trade: {data}"))
    ws.on("MKT_STAT", lambda data: print(f"Market Status: {data}"))

    await ws.connect()

asyncio.run(main())

Event types: ORD_NRML (order updates), TRD_MSG (trade confirmations), MKT_STAT (market open/close).


Price Feed WebSockets (FIX3.0)

Receives live Level 1 (Touchline) and Level 2 (Best Five / Depth) market data via TCP socket with Zlib compression.

import asyncio
from choice_api import PriceFeedSocketClient

async def main():
    feed = PriceFeedSocketClient(
        host=client.bcast_ip,
        port=client.bcast_port,
        user_id="YOUR_USER_ID"
    )

    feed.on_message(lambda raw: print(f"Feed: {raw}"))

    # Start connection (sends login automatically)
    asyncio.create_task(feed.connect())

    # Wait for connection, then subscribe
    await asyncio.sleep(2)
    feed.subscribe_touchline(client.session_id, segment_id=1, token=2885)
    feed.subscribe_best_five(client.session_id, segment_id=1, token=2885)

    # Keep running
    await asyncio.sleep(3600)

asyncio.run(main())

Logoff

client.logoff()

Download files

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

Source Distribution

kkunal-1.0.0.tar.gz (16.8 kB view details)

Uploaded Source

Built Distribution

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

kkunal-1.0.0-py3-none-any.whl (17.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: kkunal-1.0.0.tar.gz
  • Upload date:
  • Size: 16.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for kkunal-1.0.0.tar.gz
Algorithm Hash digest
SHA256 9430c1bcf6e915c5b8d098b4bd24c6c608324c214a1fb66bff6294cdc085fe0d
MD5 5fe1e3507635bbb507edb42ddd420594
BLAKE2b-256 7a4a8f86015142cfff42c7be833ffbb8ee481ada9748cfbd43029224b83cd72f

See more details on using hashes here.

Provenance

The following attestation bundles were made for kkunal-1.0.0.tar.gz:

Publisher: publish.yml on SomeshD24/Kkunal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: kkunal-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 17.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for kkunal-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 39bc97f9c7d0a5f28f1037a9abeb4a02c60add189cfb4975e28570b4cff7d48b
MD5 458f07a6c42d539b6cf38714203b89aa
BLAKE2b-256 f31ab82961b8891ebb8f9f750698dca00108dd82f5d9fda60c48789a641ebc11

See more details on using hashes here.

Provenance

The following attestation bundles were made for kkunal-1.0.0-py3-none-any.whl:

Publisher: publish.yml on SomeshD24/Kkunal

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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