How to Stream Live Trading data using Python and AliceBlue ANT API
In this article, We shall discuss how to use the AliceBlue Python Wrapper with its basic commands. We will use Google Collab.
It is a cloud-based Jupyter notebook environment from Google Research. It comes with pre-installed packages. Pre-installed libraries are one of the reasons why Colab is a popular choice to set up your algo trading project almost instantly.
Advantages of Google Collab
- Google Colab is a cloud-based Jupyter notebook environment.
- It helps us write and execute Python based code and machine learning frameworks such as PyTorch, Tensorflow, Keras etc.
- It has seamless integration with GitHub.
- It runs on the web browser. So, We don’t need to install Python or set up an environment or install every trivial package.
- The computing power is free to a very good limit which solves our majority works.
- You can share Google Collab with other users like You share Google Docs.
Visit this link https://colab.research.google.com/#create=true to create a new Notebook.
Note – Here is the Github and Google Collab link which contains the sample code is in reference with our discussion.
Installation
Alice Blue library is not preinstalled. So You need to install this module into Google Collab via pip:
!pip install alice_blue
It will give this following response –
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Collecting alice_blue
Downloading alice_blue-2.0.2-py2.py3-none-any.whl (34 kB)
Collecting websocket-client
Downloading websocket_client-1.4.1-py3-none-any.whl (55 kB)
|████████████████████████████████| 55 kB 2.3 MB/s
Requirement already satisfied: pytz in /usr/local/lib/python3.7/dist-packages (from alice_blue) (2022.2.1)
Collecting cryptography
Downloading cryptography-38.0.1-cp36-abi3-manylinux_2_24_x86_64.whl (4.0 MB)
|████████████████████████████████| 4.0 MB 5.9 MB/s
Requirement already satisfied: requests in /usr/local/lib/python3.7/dist-packages (from alice_blue) (2.23.0)
Requirement already satisfied: cffi>=1.12 in /usr/local/lib/python3.7/dist-packages (from cryptography->alice_blue) (1.15.1)
Requirement already satisfied: pycparser in /usr/local/lib/python3.7/dist-packages (from cffi>=1.12->cryptography->alice_blue) (2.21)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests->alice_blue) (2022.6.15)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests->alice_blue) (3.0.4)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests->alice_blue) (2.10)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests->alice_blue) (1.24.3)
Installing collected packages: websocket-client, cryptography, alice-blue
Successfully installed alice-blue-2.0.2 cryptography-38.0.1 websocket-client-1.4.1
You can see it automatically installed the rest of the packages which were written on the requirements.
Getting started with API
Get api_id and api_secret
api_id
and api_secret
is unique for each and every account.
Follow this article to get your api_id
and api_secret
. Here is the code patch on whatever is discussed so far. The following code is essential to every program coded using this library.
#Importing AliceBlue Library
from alice_blue import *
#Only Replace it with your credentails
username = "enter_your_user_name"
password = "enter_your_password"
twoFA = "enter_byear"
app_id = "enter_app_id"
api_secret = "enter_api_secret"
session_id = AliceBlue.login_and_get_sessionID(username=username,password=password,twoFA=twoFA,app_id=app_id,api_secret=api_secret)
alice = AliceBlue(username = username, session_id = session_id, master_contracts_to_download=['NSE', 'BSE','NFO','MCX'])
- There is only one class in the whole library:
AliceBlue
. - The
login_and_get_sessionID()
static method is used to retrieve session ID from Alice Blue server. - A session ID is valid for 24 hours. [It gets reset at 7 am every morning.]. Ideally you only need to create a session ID once every day.
- With session ID, you can initialize an AliceBlue object.
username
, password
, twofa
, app id
and app secret
in this code and run it, You will get no response because there is no print command. It will just execute peacefully. Now, as our AliceBlue object named alice is initialized, We can play with all the methods referred to in the documentation. Getting Balance or Margin Limits of an Account
get_balance()
method.
print(alice.get_balance()) # get balance / margin limits
[{'symbol': 'ALL', 'cncMarginUsed': '0', 'spanmargin': '9198.50', 'branchAdhoc': '0.000000', 'adhocMargin': '0.000000', 'payoutamount': '0.00', 'cdsSpreadBenefit': '0', 'adhocscripmargin': '0.00', 'exposuremargin': '41468.30', 'scripbasketmargin': '0.00', 'credits': '96623.07', 'segment': 'ALL', 'net': '45729.32', 'turnover': '0.00', 'grossexposurevalue': '0.00', 'mfssAmountUsed': '0.00', 'realizedMtomPrsnt': '-0.00', 'product': 'ALL', 'stat': 'Ok', 'cncSellCrditPrsnt': '0', 'debits': '50893.75', 'varmargin': '0.00', 'multiplier': '10.00', 'elm': '0.00', 'mfamount': '0.00', 'cashmarginavailable': '96623.07', 'brokeragePrsnt': '101.328000', 'cncRealizedMtomPrsnt': '0', 'notionalCash': '0.000000', 'directcollateralvalue': '0.00', 'cncBrokeragePrsnt': '0', 'valueindelivery': '0', 'nfoSpreadBenefit': '0', 'losslimit': '0', 'subtotal': '50893.75', 'rmsPayInAmnt': '0', 'unrealizedMtomPrsnt': '-0.00', 'coverOrderMarginPrsnt': '0', 'exchange': 'ALL', 'category': 'ABFS-FREEDOM', 'collateralvalue': '0.00', 'rmsIpoAmnt': '0', 'cncUnrealizedMtomPrsnt': '0', 'premiumPrsnt': '125.625000'}, {'symbol': 'ALL', 'cncMarginUsed': '0', 'spanmargin': '0.00', 'branchAdhoc': '0.000000', 'adhocMargin': '0.000000', 'payoutamount': '0.00', 'cdsSpreadBenefit': '0', 'adhocscripmargin': '0.00', 'exposuremargin': '0.00', 'scripbasketmargin': '0.00', 'credits': '0.00', 'segment': 'COM', 'net': '0.00', 'turnover': '0.00', 'grossexposurevalue': '0.00', 'mfssAmountUsed': '0.00', 'realizedMtomPrsnt': '-0.00', 'product': 'ALL', 'stat': 'Ok', 'cncSellCrditPrsnt': '0', 'debits': '0.00', 'varmargin': '0.00', 'multiplier': '1.00', 'elm': '0.00', 'mfamount': '0.00', 'cashmarginavailable': '0.00', 'brokeragePrsnt': '0', 'cncRealizedMtomPrsnt': '0', 'notionalCash': '0.000000', 'directcollateralvalue': '0.00', 'cncBrokeragePrsnt': '0', 'valueindelivery': '0', 'nfoSpreadBenefit': '0', 'losslimit': '0', 'subtotal': '0.00', 'rmsPayInAmnt': '0', 'unrealizedMtomPrsnt': '-0.00', 'coverOrderMarginPrsnt': '0', 'exchange': 'ALL', 'category': 'NO_VAL', 'collateralvalue': '0.00', 'rmsIpoAmnt': '0', 'cncUnrealizedMtomPrsnt': '0', 'premiumPrsnt': '0'}]
Getting Info about a Stock or Futures or Index
get_scrip_info()
method. It takes an instrument as input. You will hear the term instrument a lot.
You can think it as of a custom made variable with a specific structure. These are named-tuples that are created while getting the master contracts. They are used when placing an order and searching for an instrument.
Let’s check how an instrument looks and what it contains.
#Getting Instrument of Crude Oil
crude_oil_symbol = alice.get_instrument_by_symbol('MCX', 'CRUDEOIL22OCTFUT')
crude_oil_symbol
The output will look like –
Instrument(exchange='MCX', token=240524, symbol='CRUDEOIL22OCTFUT', name='CRUDEOIL 19OCT22 FUT', expiry=datetime.date(2022, 10, 19), lot_size='100')
get_scrip_info()
method.
print(alice.get_scrip_info(alice.get_instrument_by_symbol("NSE", "INFY-EQ")))
print(alice.get_scrip_info(alice.get_instrument_by_symbol("NFO", "BANKNIFTY22SEPFUT")))
The output will look like –
{'optiontype': 'XX', 'SQty': 0, 'vwapAveragePrice': '1371.40', 'LTQ': '39', 'DecimalPrecision': 2, 'openPrice': '1366.35', 'LTP': '1367.95', 'Ltp': '1367.95', 'BRate': '1367.95', 'defmktproval': '3', 'symbolname': 'INFY', 'noMktPro': '0', 'BQty': 1158, 'mktpro': '1', 'LTT': '22/09/2022 15:48:58', 'TickSize': '5', 'Multiplier': 1, 'strikeprice': '00.00', 'TotalSell': 'NA', 'High': '1383.95', 'stat': 'Ok', 'yearlyLowPrice': '1360.00', 'yearlyHighPrice': '1953.90', 'exchFeedTime': '22-Sep-2022 15:50:26', 'BodLotQty': 1, 'PrvClose': '1367.95', 'Change': '00.00', 'SRate': '00.00', 'Series': 'EQ', 'TotalBuy': '1158', 'Low': '1360.00', 'UniqueKey': 'INFY', 'PerChange': '00.00', 'companyname': 'INFOSYS LIMITED', 'TradeVolume': '9168379', 'TSymbl': 'INFY-EQ', 'Exp': 'NA', 'LTD': 'NA'}
{'optiontype': 'XX', 'SQty': 25, 'vwapAveragePrice': '40800.48', 'LTQ': '25', 'Ltp': '40721.00', 'LTP': '40721.00', 'DecimalPrecision': 2, 'openPrice': '40978.00', 'BRate': '40714.00', 'defmktproval': '3', 'BQty': 50, 'symbolname': 'BANKNIFTY', 'noMktPro': '0', 'LTT': '22/09/2022 15:29:59', 'mktpro': '1', 'TickSize': '5', 'Multiplier': 1, 'strikeprice': '00.00', 'TotalSell': '85800', 'High': '41218.00', 'stat': 'Ok', 'BodLotQty': 25, 'yearlyHighPrice': '41218.00', 'yearlyLowPrice': '00.00', 'exchFeedTime': '22-Sep-2022 15:32:03', 'PrvClose': '41244.95', 'SRate': '40721.90', 'Change': '-523.95', 'Series': 'XX', 'TotalBuy': '72650', 'Low': '40413.00', 'UniqueKey': 'NA', 'PerChange': '-01.27', 'companyname': '', 'TradeVolume': '5396275', 'TSymbl': 'BANKNIFTY22SEPFUT', 'Exp': '29 Sep, 2022', 'LTD': 'NA'}
It is returned as a dict which also gives us LTP
of the said instrument as well. If you need the LTP
of an instrument once or twice or seldom, Use this function instead of wasting huge resources on Websocket method.
Starting the Websocket and Subscribing to a Scrip
Let’s talk about Websocket. Let’s say, In your strategy, You have to check the price of an instrument continuously.
If you keep posting Request to the server each second, it will bombard the server all totally. That’s why there are rate limits! In that case, Websocket is used. A websocket is like a channel between the server to your code. It will have a constant connection and every time there is a change in LTP
in the server, it will share it with you via Websocket.
tick = 0
def event_handler_quote_update(message):
global tick
tick=message
alice.start_websocket(subscribe_callback=event_handler_quote_update)
#This subscribe function takes the first variable type as Instrument. We had this from last block. Second variable is selection between Tick Data or Depth Data.
alice.subscribe(crude_oil_symbol, LiveFeedType.TICK_DATA)
alice.get_all_subscriptions()
In the above code,
- We are starting the websocket.
- We are subscribing to the Crude Oil instrument we discussed slightly ago.
- We are passing the Websocket’s data to a global variable named tick.
Websocket works in multithreading. So when you write the start_websocket() function, another python code started in the background and maintains the WebSocket connection.
Now the tick variable gets updated automatically when there is new data in the websocket. Let’s see how to use it.
from time import sleep
while True:
try:
print(tick['instrument'][2]+" : "+str(tick['ltp']))
except TypeError: #Tick data comes when there is no trade. We are checking for tick data each 5 seconds. If there is no trade in between those 5 seconds, it will reply 0. That will raise an error. We are ignoring it.
pass
sleep(5)
0
. It will happen if you try to get live tick data after real market time. If 0
comes, it will result in TypeError. That’s why try, except is used.
Now, how you use the WebSocket data is up to you. The above code’s output will be –
CRUDEOIL22OCTFUT : 6771.0
CRUDEOIL22OCTFUT : 6771.0
CRUDEOIL22OCTFUT : 6772.0
CRUDEOIL22OCTFUT : 6773.0
CRUDEOIL22OCTFUT : 6773.0
CRUDEOIL22OCTFUT : 6773.0
CRUDEOIL22OCTFUT : 6773.0
CRUDEOIL22OCTFUT : 6773.0
CRUDEOIL22OCTFUT : 6772.0
CRUDEOIL22OCTFUT : 6771.0
CRUDEOIL22OCTFUT : 6771.0
Now, If we had subscribed to multiple instruments, the output of tick variable would’ve been more different. You can always print the tick variable and inspect it and utilize it. Like You can make charts, candlesticks and all kind of stuff!
Well –
- If You’ve opened your Aliceblue account with us, We will provide you with lots of sample code and tools developed over this Trading API.
- If You have any questions, feel free to ask in our forum.
- For all sample codes in Google Collab, check out this repo.
- If you have spotted any issues in the wrapper, nudge in the Github.