├── pya3
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-310.pyc
│ └── alicebluepy.cpython-310.pyc
└── alicebluepy.py
├── .idea
├── .gitignore
├── vcs.xml
├── misc.xml
├── inspectionProfiles
│ └── profiles_settings.xml
├── modules.xml
└── aliceblue-new-edition.iml
├── .gitattributes
├── LICENSE.txt
├── setup.py
└── README.md
/pya3/__init__.py:
--------------------------------------------------------------------------------
1 | from pya3.alicebluepy import *
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/pya3/__pycache__/__init__.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jerokpradeep/pya3/HEAD/pya3/__pycache__/__init__.cpython-310.pyc
--------------------------------------------------------------------------------
/pya3/__pycache__/alicebluepy.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jerokpradeep/pya3/HEAD/pya3/__pycache__/alicebluepy.cpython-310.pyc
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/aliceblue-new-edition.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2021 Stoneage Solutions Private Limited (India)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 | import os
3 | import io
4 | from setuptools import setup
5 |
6 |
7 | with open("README.md", "r") as f:
8 | readme = f.read()
9 |
10 | setup(
11 | name="pya3",
12 | version="1.0.29",
13 | author="Codifi",
14 | author_email="pradeep@codifi.in",
15 | description="Official Python SDK for Alice Blue API",
16 | license="MIT",
17 | long_description=readme,
18 | long_description_content_type="text/markdown",
19 | include_package_data=True,
20 | url="https://a3.aliceblueonline.com/",
21 | downloadable_url="https://github.com/jerokpradeep/pythonZebullAPI",
22 | packages=["pya3"],
23 | install_requires=["requests","pandas","websocket-client","rel"],
24 | classifiers=[
25 | "Programming Language :: Python :: 3.8",
26 | "License :: OSI Approved :: MIT License",
27 | "Operating System :: OS Independent",
28 | "Natural Language :: English",
29 | "Intended Audience :: Developers",
30 | ],
31 |
32 | python_requires='>=3.7',
33 | )
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Official Python SDK for Alice Blue API
3 |
4 | The Official Python library for communicating with the Alice Blue APIs.
5 |
6 | Alice Blue Python library provides an easy to use wrapper over the HTTPS APIs.
7 |
8 | The HTTP calls have been converted to methods and JSON responses are wrapped into Python-compatible objects.
9 |
10 |
11 | * __Author: [CodiFi](https://github.com/jerokpradeep)__
12 | * **Current Version: 1.0.29**
13 |
14 |
15 | ## Installation
16 |
17 | This module is installed via pip:
18 |
19 | ```
20 | pip install pya3
21 | ```
22 |
23 | To force upgrade existing installations:
24 | ```
25 | pip uninstall pya3
26 | pip --no-cache-dir install --upgrade pya3
27 | ```
28 |
29 | ### Prerequisites
30 |
31 | Python >=3.7
32 |
33 |
34 | ## Getting started with API
35 |
36 | ### Overview
37 | There is only two class in the whole library: `AliceBlue` and `Alice_Wrapper`. The `get_session_id` static method is used to retrieve a Session ID from the alice blue server. A Session ID is valid until the trading account logout.
38 | With a Session ID, you can instantiate an AliceBlue object. Ideally you only need to create a Session ID once every time login the trading account with password. After you have the Session ID, you can store it
39 | separately for re-use.
40 |
41 | #### NOTE: User should Login through Web(ant.aliceblueonline.com) or SSO or Mobile at least once in a day, before connecting the API
42 |
43 | ### Rate Limits
44 | The following are the rate limits for API users:
45 | 1. Orders - NOT LIMITED. Placing a new order, Modifying an existing order, square off positions and Cancelling an order are all not limited.
46 | 2. All other requests - Limited to 1800 requests per 15 minutes. This limit will be reset every 15 minutes to 1800 again.
47 |
48 | **Note:** In order to make sure all clients requests are treated equally, AliceBlue has set up certain limits to the number of requests each client can make through API.
49 | ### REST Documentation
50 | The original REST API that this SDK is based on is available online.
51 | [Alice Blue API REST documentation](https://v2api.aliceblueonline.com)
52 |
53 | ## Using the API
54 |
55 | ### Get a Session ID
56 | 1. Import pya3
57 | ```python
58 | from pya3 import *
59 | ```
60 |
61 | ### Create AliceBlue Object
62 | 1. You can create an AliceBlue object with your `UserID` and `API Key`.
63 | ```python
64 | alice = Aliceblue(user_id='username',api_key='API_KEY')
65 | ```
66 |
67 | 2. You can get a Session ID by running following command. Store it once a day
68 | ```python
69 | print(alice.get_session_id()) # Get Session ID
70 | ```
71 |
72 | 3. You can run commands here to check your connectivity
73 | ```python
74 | print(alice.get_balance()) # get balance / margin limits
75 | print(alice.get_profile()) # get profile
76 | print(alice.get_daywise_positions()) # get daywise positions
77 | print(alice.get_netwise_positions()) # get all netwise positions
78 | print(alice.get_holding_positions()) # get holding positions
79 | ```
80 | ### Alice Wrapper
81 | 1. Check Net Position Wrapper (Open/Close) Position:
82 | ```
83 | Net_position = alice.get_netwise_positions()
84 |
85 | open_position= Alice_Wrapper.open_net_position(Net_position)
86 | print("Open position :",open_position)
87 |
88 | close_position = Alice_Wrapper.close_net_poition(Net_position)
89 | print("Close position :",close_position)
90 | ```
91 | 2. Order History response wrapper:
92 | ```commandline
93 | order_history_response = alice.get_order_history('')
94 | print(Alice_Wrapper.get_order_history(order_history_response))
95 | ```
96 |
97 | 3. Balance response wrapper:
98 | ```commandline
99 | get_balance_response=alice.get_balance()
100 | print(Alice_Wrapper.get_balance(get_balance_response))
101 | ```
102 |
103 | 4. Profile response wrapper:
104 | ```commandline
105 | get_profile_response=alice.get_profile()
106 | print(Alice_Wrapper.get_profile(get_profile_response))
107 | ```
108 |
109 | ### Get master contracts
110 |
111 | Getting master contracts allow you to search for instruments by symbol name and place orders.
112 |
113 | Master contracts are stored as an CSV at local by token number and by symbol name. Whenever you get a trade update, order update, or quote update, the library will check if master contracts are loaded. If they are, it will attach the instrument object directly to the update. By default all master contracts of all enabled exchanges in your personal profile will be downloaded. i.e. If your profile contains the following as enabled exchanges `['NSE','CDS', 'BSE','BFO', 'MCX', NFO','INDICES']` all contract notes of all exchanges will be downloaded by default. If you feel it takes too much time to download all exchange, or if you don't need all exchanges to be downloaded, you can specify which exchange to download contract notes while creating the AliceBlue object.
114 |
115 |
116 | ```python
117 | alice.get_contract_master("MCX")
118 | alice.get_contract_master("NFO")
119 | alice.get_contract_master("NSE")
120 | alice.get_contract_master("BSE")
121 | alice.get_contract_master("CDS")
122 | alice.get_contract_master("BFO")
123 | alice.get_contract_master("INDICES")
124 | ```
125 |
126 | This will reduce a few milliseconds in object creation time of AliceBlue object.
127 |
128 | ### Get tradable instruments
129 | Symbols can be retrieved in multiple ways. Once you have the master contract loaded for an exchange, you can get an instrument in many ways.
130 |
131 | Get a single instrument by it's name:
132 | ```python
133 | print(alice.get_instrument_by_symbol('NSE','ONGC'))
134 | print(alice.get_instrument_by_symbol('BSE','TATASTEEL'))
135 | print(alice.get_instrument_by_symbol('MCX','GOLDM'))
136 | print(alice.get_instrument_by_symbol('INDICES','NIFTY 50'))
137 | print(alice.get_instrument_by_symbol('INDICES','NIFTY BANK'))
138 | ```
139 |
140 | Get a single instrument by it's token number (generally useful only for BSE Equities):
141 | ```python
142 | print(alice.get_instrument_by_token("MCX",239484))
143 | print(alice.get_instrument_by_token('BSE',500325))
144 | print(alice.get_instrument_by_token('NSE',22))
145 | print(alice.get_instrument_by_token('INDICES',26000)) # Nifty Indices
146 | print(alice.get_instrument_by_token('INDICES',26009)) # Bank Nifty
147 | ```
148 |
149 | Get FNO instruments easily by mentioning expiry, strike & call or put.
150 |
151 | ```python
152 | print(alice.get_instrument_for_fno(exch="NFO",symbol='BANKNIFTY', expiry_date="2022-09-25", is_fut=True,strike=None, is_CE=False))
153 | print(alice.get_instrument_for_fno(exch="NFO",symbol='BANKNIFTY', expiry_date="2022-09-04", is_fut=False,strike=37700, is_CE=False))
154 | print(alice.get_instrument_for_fno(exch="NFO",symbol='BANKNIFTY', expiry_date="2022-09-04", is_fut=False,strike=37700, is_CE=True))
155 | print(alice.get_instrument_for_fno(exch="CDS",symbol='USDINR', expiry_date="2022-09-16", is_fut=True,strike=None, is_CE=False))
156 | print(alice.get_instrument_for_fno(exch="CDS",symbol='USDINR', expiry_date="2022-09-23", is_fut=False,strike=79.50000, is_CE=False))
157 | print(alice.get_instrument_for_fno(exch="CDS",symbol='USDINR', expiry_date="2022-09-28", is_fut=False,strike=79.50000, is_CE=True))
158 | ```
159 |
160 | ### Search for symbols
161 | Search for multiple instruments by matching the name. This works case insensitive and returns all instrument which has the name in its symbol. It does not require contract master file.
162 | ```python
163 | all_sensex_scrips = alice.search_instruments('BSE', 'SENSEX')
164 | print(all_sensex_scrips)
165 | ```
166 | The above code results multiple symbol which has 'sensex' in its symbol.
167 |
168 |
169 | #### Instrument object
170 |
171 | Instruments are represented by instrument objects. These are named-tuples that are created while getting the master contracts. They are used when placing an order and searching for an instrument. The structure of an instrument tuple is as follows:
172 |
173 | ```python
174 |
175 | Instrument = namedtuple('Instrument', ['exchange', 'token', 'symbol','name', 'expiry', 'lot_size'])
176 |
177 | ```
178 |
179 |
180 | All instruments have the fields mentioned above. Wherever a field is not applicable for an instrument (for example, equity instruments don't have strike prices), that value will be `None`
181 |
182 |
183 | ### Place an order
184 | Place limit, market, SL, SL-M, AMO, BO, CO orders
185 |
186 | ```python
187 | # TransactionType.Buy, OrderType.Market, ProductType.Delivery
188 |
189 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
190 | print(
191 | alice.place_order(transaction_type = TransactionType.Buy,
192 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
193 | quantity = 1,
194 | order_type = OrderType.Market,
195 | product_type = ProductType.Delivery,
196 | price = 0.0,
197 | trigger_price = None,
198 | stop_loss = None,
199 | square_off = None,
200 | trailing_sl = None,
201 | is_amo = False,
202 | order_tag='order1')
203 | )
204 |
205 | # TransactionType.Buy, OrderType.Market, ProductType.Intraday
206 |
207 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
208 | print(
209 | alice.place_order(transaction_type = TransactionType.Buy,
210 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
211 | quantity = 1,
212 | order_type = OrderType.Market,
213 | product_type = ProductType.Intraday,
214 | price = 0.0,
215 | trigger_price = None,
216 | stop_loss = None,
217 | square_off = None,
218 | trailing_sl = None,
219 | is_amo = False,
220 | order_tag='order1')
221 | )
222 |
223 | # TransactionType.Buy, OrderType.Market, ProductType.CoverOrder
224 |
225 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
226 | print(
227 | alice.place_order(transaction_type = TransactionType.Buy,
228 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
229 | quantity = 1,
230 | order_type = OrderType.Market,
231 | product_type = ProductType.CoverOrder,
232 | price = 0.0,
233 | trigger_price = 7.5, # trigger_price Here the trigger_price is taken as stop loss (provide stop loss in actual amount)
234 | stop_loss = None,
235 | square_off = None,
236 | trailing_sl = None,
237 | is_amo = False,
238 | order_tag='order1')
239 | )
240 |
241 |
242 | # TransactionType.Buy, OrderType.Limit, ProductType.BracketOrder
243 | # OCO Order can't be of type market
244 |
245 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%4%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
246 | print(
247 | alice.place_order(transaction_type = TransactionType.Buy,
248 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
249 | quantity = 1,
250 | order_type = OrderType.Limit,
251 | product_type = ProductType.BracketOrder,
252 | price = 8.0,
253 | trigger_price = None,
254 | stop_loss = 6.0,
255 | square_off = 10.0,
256 | trailing_sl = None,
257 | is_amo = False,
258 | order_tag='order1')
259 | )
260 |
261 | # TransactionType.Buy, OrderType.Limit, ProductType.Intraday
262 |
263 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%5%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
264 | print(
265 | alice.place_order(transaction_type = TransactionType.Buy,
266 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
267 | quantity = 1,
268 | order_type = OrderType.Limit,
269 | product_type = ProductType.Intraday,
270 | price = 8.0,
271 | trigger_price = None,
272 | stop_loss = None,
273 | square_off = None,
274 | trailing_sl = None,
275 | is_amo = False,
276 | order_tag='order1')
277 | )
278 |
279 |
280 | # TransactionType.Buy, OrderType.Limit, ProductType.CoverOrder
281 |
282 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%6%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
283 | print(
284 | alice.place_order(transaction_type = TransactionType.Buy,
285 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
286 | quantity = 1,
287 | order_type = OrderType.Limit,
288 | product_type = ProductType.CoverOrder,
289 | price = 7.0,
290 | trigger_price = 6.5, # trigger_price Here the trigger_price is taken as stop loss (provide stop loss in actual amount)
291 | stop_loss = None,
292 | square_off = None,
293 | trailing_sl = None,
294 | is_amo = False,
295 | order_tag='order1')
296 | )
297 |
298 | ###############################
299 |
300 | # TransactionType.Buy, OrderType.StopLossMarket, ProductType.Delivery
301 |
302 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%7%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
303 | print(
304 | alice.place_order(transaction_type = TransactionType.Buy,
305 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
306 | quantity = 1,
307 | order_type = OrderType.StopLossMarket,
308 | product_type = ProductType.Delivery,
309 | price = 0.0,
310 | trigger_price = 8.0,
311 | stop_loss = None,
312 | square_off = None,
313 | trailing_sl = None,
314 | is_amo = False,
315 | order_tag='order1')
316 | )
317 |
318 |
319 | # TransactionType.Buy, OrderType.StopLossMarket, ProductType.Intraday
320 |
321 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%8%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
322 | print(
323 | alice.place_order(transaction_type = TransactionType.Buy,
324 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
325 | quantity = 1,
326 | order_type = OrderType.StopLossMarket,
327 | product_type = ProductType.Intraday,
328 | price = 0.0,
329 | trigger_price = 8.0,
330 | stop_loss = None,
331 | square_off = None,
332 | trailing_sl = None,
333 | is_amo = False,
334 | order_tag='order1')
335 | )
336 |
337 |
338 |
339 | # TransactionType.Buy, OrderType.StopLossMarket, ProductType.CoverOrder
340 | # CO order is of type Limit and And Market Only
341 |
342 | # TransactionType.Buy, OrderType.StopLossMarket, ProductType.BO
343 | # BO order is of type Limit and And Market Only
344 |
345 | ###################################
346 |
347 | # TransactionType.Buy, OrderType.StopLossLimit, ProductType.Delivery
348 |
349 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
350 | print(
351 | alice.place_order(transaction_type = TransactionType.Buy,
352 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
353 | quantity = 1,
354 | order_type = OrderType.StopLossMarket,
355 | product_type = ProductType.Delivery,
356 | price = 8.0,
357 | trigger_price = 8.0,
358 | stop_loss = None,
359 | square_off = None,
360 | trailing_sl = None,
361 | is_amo = False,
362 | order_tag='order1')
363 | )
364 |
365 |
366 | # TransactionType.Buy, OrderType.StopLossLimit, ProductType.Intraday
367 |
368 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%10%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
369 | print(
370 | alice.place_order(transaction_type = TransactionType.Buy,
371 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
372 | quantity = 1,
373 | order_type = OrderType.StopLossLimit,
374 | product_type = ProductType.Intraday,
375 | price = 8.0,
376 | trigger_price = 8.0,
377 | stop_loss = None,
378 | square_off = None,
379 | trailing_sl = None,
380 | is_amo = False,
381 | order_tag='order1')
382 | )
383 |
384 |
385 |
386 | # TransactionType.Buy, OrderType.StopLossLimit, ProductType.CoverOrder
387 | # CO order is of type Limit and And Market Only
388 |
389 |
390 | # TransactionType.Buy, OrderType.StopLossLimit, ProductType.BracketOrder
391 |
392 | print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%11%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
393 | print(
394 | alice.place_order(transaction_type = TransactionType.Buy,
395 | instrument = alice.get_instrument_by_symbol('NSE', 'INFY'),
396 | quantity = 1,
397 | order_type = OrderType.StopLossLimit,
398 | product_type = ProductType.BracketOrder,
399 | price = 8.0,
400 | trigger_price = 8.0,
401 | stop_loss = 1.0,
402 | square_off = 1.0,
403 | trailing_sl = 20,
404 | is_amo = False,
405 | order_tag='order1')
406 | )
407 | ```
408 |
409 | ### Place basket order
410 | Basket order is used to buy or sell group of securities simultaneously.
411 | ```python
412 | order1 = { "instrument" : alice.get_instrument_by_symbol('NSE', 'INFY'),
413 | "order_type" : OrderType.Market,
414 | "quantity" : 1,
415 | "transaction_type" : TransactionType.Buy,
416 | "product_type" : ProductType.Delivery,
417 | "order_tag" : "Order1"}
418 | order2 = { "instrument" : alice.get_instrument_by_symbol('NSE', 'SBIN'),
419 | "order_type" : OrderType.Limit,
420 | "quantity" : 2,
421 | "price" : 280.0,
422 | "transaction_type" : TransactionType.Sell,
423 | "product_type" : ProductType.Intraday,
424 | "order_tag" : "Order2"}
425 | orders = [order1, order2]
426 | print(alice.place_basket_order(orders))
427 | ```
428 |
429 | ### Websocket
430 | Connect the Websocket and subscribe script. To get market depth please set market_depth as `True`
431 | ```python
432 | LTP = 0
433 | socket_opened = False
434 | subscribe_flag = False
435 | subscribe_list = []
436 | unsubscribe_list = []
437 |
438 | def socket_open(): # Socket open callback function
439 | print("Connected")
440 | global socket_opened
441 | socket_opened = True
442 | if subscribe_flag: # This is used to resubscribe the script when reconnect the socket.
443 | alice.subscribe(subscribe_list)
444 |
445 | def socket_close(): # On Socket close this callback function will trigger
446 | global socket_opened, LTP
447 | socket_opened = False
448 | LTP = 0
449 | print("Closed")
450 |
451 | def socket_error(message): # Socket Error Message will receive in this callback function
452 | global LTP
453 | LTP = 0
454 | print("Error :", message)
455 |
456 | def feed_data(message): # Socket feed data will receive in this callback function
457 | global LTP, subscribe_flag
458 | feed_message = json.loads(message)
459 | if feed_message["t"] == "ck":
460 | print("Connection Acknowledgement status :%s (Websocket Connected)" % feed_message["s"])
461 | subscribe_flag = True
462 | print("subscribe_flag :", subscribe_flag)
463 | print("-------------------------------------------------------------------------------")
464 | pass
465 | elif feed_message["t"] == "tk":
466 | print("Token Acknowledgement status :%s " % feed_message)
467 | print("-------------------------------------------------------------------------------")
468 | pass
469 | else:
470 | print("Feed :", feed_message)
471 | LTP = feed_message[
472 | 'lp'] if 'lp' in feed_message else LTP # If LTP in the response it will store in LTP variable
473 |
474 | # Socket Connection Request
475 | alice.start_websocket(socket_open_callback=socket_open, socket_close_callback=socket_close,
476 | socket_error_callback=socket_error, subscription_callback=feed_data, run_in_background=True,market_depth=False)
477 |
478 | while not socket_opened:
479 | pass
480 |
481 | subscribe_list = [alice.get_instrument_by_token('INDICES', 26000)]
482 | alice.subscribe(subscribe_list)
483 | print(datetime.now())
484 | sleep(10)
485 | print(datetime.now())
486 | # unsubscribe_list = [alice.get_instrument_by_symbol("NSE", "RELIANCE")]
487 | # alice.unsubscribe(unsubscribe_list)
488 | # sleep(8)
489 |
490 | # Stop the websocket
491 | alice.stop_websocket()
492 | sleep(10)
493 | print(datetime.now())
494 |
495 | # Connect the socket after socket close
496 | alice.start_websocket(socket_open_callback=socket_open, socket_close_callback=socket_close,
497 | socket_error_callback=socket_error, subscription_callback=feed_data, run_in_background=True)
498 |
499 | ```
500 |
501 | ### Modify an order
502 |
503 | ```python
504 | print(
505 | alice.modify_order(transaction_type = TransactionType.Buy,
506 | instrument = alice.get_instrument_by_token('MCX', 242508),
507 | order_id="220803000207716",
508 | quantity = 1,
509 | order_type = OrderType.Limit,
510 | product_type = ProductType.Delivery,
511 | price=30.0,
512 | trigger_price = None)
513 | )
514 | ```
515 |
516 | ### Cancel an order
517 |
518 | ```python
519 | print(alice.cancel_order('191015000018737')) #Cancel an open order
520 | print(alice.cancel_order('220803000207716')) #Cancel an open order
521 | ```
522 |
523 | ### Getting order history and trade details
524 |
525 | #### Get order history of a particular order
526 | ```python
527 | print(alice.get_order_history('220803000207716'))
528 | ```
529 |
530 | #### Get order history of all orders.
531 | ```python
532 | print(alice.get_order_history(''))
533 | ```
534 |
535 | #### Get trade book
536 | ```python
537 | print(alice.get_trade_book())
538 | ```
539 |
540 | #### Get Script Info
541 | Get Current OHLC, Upper and Lower circuit data
542 | ```python
543 | print(alice.get_scrip_info(alice.get_instrument_by_token('MCX', 242508)))
544 | ```
545 |
546 | #### Get Historical Data
547 | Get Historical data of Open, High, Low, Close and Volume of Minutes, Day and Month.
548 | ```python
549 | from datetime import datetime
550 |
551 | alice = Aliceblue(user_id='',api_key='')
552 |
553 | instrument = alice.get_instrument_by_symbol("NFO", "RELIANCE")
554 | from_datetime = datetime.now() - datetime.timedelta(days=7) # From last & days
555 | to_datetime = datetime.now() # To now
556 | interval = "1" # ["1", "D"]
557 | indices = False # For Getting index data
558 | print(alice.get_historical(instrument, from_datetime, to_datetime, interval, indices))
559 |
560 | ```
561 |
562 | ### Order properties as enums
563 | Order properties such as TransactionType, OrderType, and others have been safely classified as enums so you don't have to write them out as strings
564 |
565 | #### TransactionType
566 | Transaction types indicate whether you want to buy or sell. Valid transaction types are of the following:
567 |
568 | * `TransactionType.Buy` - buy
569 | * `TransactionType.Sell` - sell
570 |
571 | #### OrderType
572 | Order type specifies the type of order you want to send. Valid order types include:
573 |
574 | * `OrderType.Market` - Place the order with a market price
575 | * `OrderType.Limit` - Place the order with a limit price (limit price parameter is mandatory)
576 | * `OrderType.StopLossLimit` - Place as a stop loss limit order
577 | * `OrderType.StopLossMarket` - Place as a stop loss market order
578 |
579 | #### ProductType
580 | Product types indicate the complexity of the order you want to place. Valid product types are:
581 |
582 | * `ProductType.Intraday` - Intraday order that will get squared off before market close
583 | * `ProductType.Delivery` - Delivery order that will be held with you after market close
584 | * `ProductType.CoverOrder` - Cover order
585 | * `ProductType.BracketOrder` - One cancels other order. Also known as bracket order
586 |
587 | ### Get Basket Margin
588 |
589 | Get margin-used and margin-used-trade for placed orders
590 | ```
591 | orders = [{
592 | "exchange": "NSE",
593 | "tradingSymbol": "INFY-EQ",
594 | "price": "1999.70",
595 | "qty" : "1",
596 | "product": "MIS",
597 | "priceType": "L",
598 | "triggerPrice" : "1995",
599 | "transType" : "B"
600 | }]
601 | ```
602 | ```python
603 | print(alice.basket_margin(orders))
604 | ```
605 |
606 | ## Read this before creating an issue
607 | Before creating an issue in this library, please follow the following steps.
608 |
609 | 1. Search the problem you are facing is already asked by someone else. There might be some issues already there, either solved/unsolved related to your problem. Go to [issues](https://github.com/jerokpradeep/pya3/issues)
610 | 2. If you feel your problem is not asked by anyone or no issues are related to your problem, then create a new issue.
611 | 3. Describe your problem in detail while creating the issue. If you don't have time to detail/describe the problem you are facing, assume that I also won't be having time to respond to your problem.
612 | 4. Post a sample code of the problem you are facing. If I copy paste the code directly from issue, I should be able to reproduce the problem you are facing.
613 | 5. Before posting the sample code, test your sample code yourself once. Only sample code should be tested, no other addition should be there while you are testing.
614 | 6. Have some print() function calls to display the values of some variables related to your problem.
615 | 7. Post the results of print() functions also in the issue.
616 | 8. Use the insert code feature of github to inset code and print outputs, so that the code is displayed neat. 
617 | 9. If you have multiple lines of code, use triple grave accent ( ``` ) to insert multiple lines of code. [Example:](https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks) 
618 |
619 |
--------------------------------------------------------------------------------
/pya3/alicebluepy.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import json
3 | import hashlib
4 | import enum
5 | import logging
6 | import pandas as pd
7 | from datetime import time, datetime
8 | from time import sleep
9 | from collections import namedtuple
10 | import os
11 | import websocket
12 | import rel
13 | import ssl
14 |
15 | import threading
16 |
17 | logger = logging.getLogger(__name__)
18 |
19 | Instrument = namedtuple('Instrument', ['exchange', 'token', 'symbol', 'name', 'expiry', 'lot_size'])
20 |
21 |
22 | class TransactionType(enum.Enum):
23 | Buy = 'BUY'
24 | Sell = 'SELL'
25 |
26 |
27 | class LiveFeedType(enum.IntEnum):
28 | MARKET_DATA = 1
29 | COMPACT = 2
30 | SNAPQUOTE = 3
31 | FULL_SNAPQUOTE = 4
32 |
33 |
34 | class OrderType(enum.Enum):
35 | Market = 'MKT'
36 | Limit = 'L'
37 | StopLossLimit = 'SL'
38 | StopLossMarket = 'SL-M'
39 |
40 |
41 | class ProductType(enum.Enum):
42 | Intraday = 'MIS'
43 | Delivery = 'CNC'
44 | CoverOrder = 'CO'
45 | BracketOrder = 'BO'
46 | Normal = 'NRML'
47 |
48 |
49 | def encrypt_string(hashing):
50 | sha = hashlib.sha256(hashing.encode()).hexdigest()
51 | return sha
52 |
53 |
54 | class Aliceblue:
55 | base_url = "https://ant.aliceblueonline.com/rest/AliceBlueAPIService/api/"
56 | api_name = "Codifi API Connect - Python Lib "
57 | version = "1.0.29"
58 | base_url_c = "https://v2api.aliceblueonline.com/restpy/static/contract_master/%s.csv"
59 | websocket_url = "wss://ant.aliceblueonline.com/order-notify/websocket"
60 | create_websocket_url = "https://ant.aliceblueonline.com/order-notify/ws/createWsToken"
61 |
62 | # Products
63 | PRODUCT_INTRADAY = "MIS"
64 | PRODUCT_COVER_ODRER = "CO"
65 | PRODUCT_CNC = "CNC"
66 | PRODUCT_BRACKET_ORDER = "BO"
67 | PRODUCT_NRML = "NRML"
68 |
69 | # Order Type
70 | REGULAR_ORDER = "REGULAR"
71 | LIMIT_ORDER = "L"
72 | STOPLOSS_ORDER = "SL"
73 | MARKET_ORDER = "MKT"
74 |
75 | # Transaction type
76 | BUY_ORDER = "BUY"
77 | SELL_ORDER = "SELL"
78 |
79 | # Positions
80 | RETENTION_DAY = "DAY" or "NET"
81 |
82 | # Exchanges
83 | EXCHANGE_NSE = "NSE"
84 | EXCHANGE_NFO = "NFO"
85 | EXCHANGE_CDS = "CDS"
86 | EXCHANGE_BSE = "BSE"
87 | EXCHANGE_BFO = "BFO"
88 | EXCHANGE_BCD = "BCD"
89 | EXCHANGE_MCX = "MCX"
90 |
91 | # Status constants
92 | STATUS_COMPLETE = "COMPLETE"
93 | STATUS_REJECTED = "REJECTED"
94 | STATUS_CANCELLED = "CANCELLED"
95 | ENC = None
96 | ws = None
97 | subscriptions = None
98 | __subscribe_callback = None
99 | __subscribers = None
100 | script_subscription_instrument = []
101 | ws_connection = False
102 | # response = requests.get(base_url);
103 | # Getscrip URI
104 | __ws_thread = None
105 | __stop_event = None
106 | market_depth = None
107 |
108 | _sub_urls = {
109 | # Authorization
110 | "encryption_key": "customer/getAPIEncpkey",
111 | "getsessiondata": "customer/getUserSID",
112 |
113 | # Market Watch
114 | "marketwatch_scrips": "marketWatch/fetchMWScrips",
115 | "addscrips": "marketWatch/addScripToMW",
116 | "getmarketwatch_list": "marketWatch/fetchMWList",
117 | "scripdetails": "ScripDetails/getScripQuoteDetails",
118 | "getdelete_scrips": "marketWatch/deleteMWScrip",
119 |
120 | # OrderManagement
121 | "squareoffposition": "positionAndHoldings/sqrOofPosition",
122 | "position_conversion": "positionAndHoldings/positionConvertion",
123 | "placeorder": "placeOrder/executePlaceOrder",
124 | "modifyorder": "placeOrder/modifyOrder",
125 | "marketorder": "placeOrder/executePlaceOrder",
126 | "exitboorder": "placeOrder/exitBracketOrder",
127 | "bracketorder": "placeOrder/executePlaceOrder",
128 | "positiondata": "positionAndHoldings/positionBook",
129 | "orderbook": "placeOrder/fetchOrderBook",
130 | "tradebook": "placeOrder/fetchTradeBook",
131 | "holding": "positionAndHoldings/holdings",
132 | "orderhistory": "placeOrder/orderHistory",
133 | "cancelorder": "placeOrder/cancelOrder",
134 | "profile": "customer/accountDetails",
135 | "basket_margin": "basket/getMargin",
136 | # Funds
137 | "fundsrecord": "limits/getRmsLimits",
138 | # Websockey
139 | "base_url_socket": "wss://ws1.aliceblueonline.com/NorenWS/"
140 |
141 | }
142 |
143 | # Common Method
144 | def __init__(self,
145 | user_id,
146 | api_key,
147 | base=None,
148 | session_id=None,
149 | disable_ssl=False):
150 |
151 | self.user_id = user_id.upper()
152 | self.api_key = api_key
153 | self.disable_ssl = disable_ssl
154 | self.session_id = session_id
155 | self.base = base or self.base_url
156 | self.__on_error = None
157 | self.__on_disconnect = None
158 | self.__on_open = None
159 | self.__exchange_codes = None
160 |
161 | def _get(self, sub_url, data=None):
162 | """Get method declaration"""
163 | url = self.base + self._sub_urls[sub_url]
164 | return self._request(url, "GET", data=data)
165 |
166 | def _post(self, sub_url, data=None):
167 | """Post method declaration"""
168 | url = self.base + self._sub_urls[sub_url]
169 | return self._request(url, "POST", data=data)
170 |
171 | def _dummypost(self, url, data=None):
172 | """Post method declaration"""
173 | return self._request(url, "POST", data=data)
174 |
175 | def _user_agent(self):
176 | return self.api_name + self.version
177 |
178 | """Authorization get to call all requests"""
179 |
180 | def _user_authorization(self):
181 | if self.session_id:
182 | return "Bearer " + self.user_id.upper() + " " + self.session_id
183 | else:
184 | return ""
185 |
186 | """Common request to call POST and GET method"""
187 |
188 | def _request(self, method, req_type, data=None):
189 | """
190 | Headers with authorization. For some requests authorization
191 | is not required. It will be send as empty String
192 | """
193 | _headers = {
194 | "X-SAS-Version": "2.0",
195 | "User-Agent": self._user_agent(),
196 | "Authorization": self._user_authorization()
197 | }
198 | if req_type == "POST":
199 | try:
200 | response = requests.post(method, json=data, headers=_headers, )
201 | except (requests.ConnectionError, requests.Timeout) as exception:
202 | return {'stat': 'Not_ok', 'emsg': exception, 'encKey': None}
203 | if response.status_code == 200:
204 | return json.loads(response.text)
205 | else:
206 | emsg = str(response.status_code) + ' - ' + response.reason
207 | return {'stat': 'Not_ok', 'emsg': emsg, 'encKey': None}
208 |
209 | elif req_type == "GET":
210 | try:
211 | response = requests.get(method, json=data, headers=_headers)
212 | except (requests.ConnectionError, requests.Timeout) as exception:
213 | return {'stat': 'Not_ok', 'emsg': exception, 'encKey': None}
214 | if response.status_code == 200:
215 | return json.loads(response.text)
216 | else:
217 | emsg = str(response.status_code) + ' - ' + response.reason
218 | return {'stat': 'Not_ok', 'emsg': emsg, 'encKey': None}
219 |
220 | def _error_response(self, message):
221 | return {"stat": "Not_ok", "emsg": message}
222 |
223 | # Methods to call HTTP Request
224 |
225 | """Userlogin method with userid and userapi_key"""
226 |
227 | def get_session_id(self, data=None):
228 | data = {'userId': self.user_id.upper()}
229 | response = self._post("encryption_key", data)
230 | if response['encKey'] is None:
231 | return response
232 | else:
233 | data = encrypt_string(self.user_id.upper() + self.api_key + response['encKey'])
234 | data = {'userId': self.user_id.upper(), 'userData': data}
235 | res = self._post("getsessiondata", data)
236 |
237 | if res['stat'] == 'Ok':
238 | self.session_id = res['sessionID']
239 | return res
240 |
241 | """GET Market watchlist"""
242 |
243 | def getmarketwatch_list(self):
244 | marketwatchrespdata = self._get("getmarketwatch_list")
245 | return marketwatchrespdata
246 |
247 | """GET Tradebook Records"""
248 |
249 | def get_trade_book(self):
250 | tradebookresp = self._get("tradebook")
251 | return tradebookresp
252 |
253 | def get_profile(self):
254 | profile = self._get("profile")
255 | return profile
256 |
257 | """GET Holdings Records"""
258 |
259 | def get_holding_positions(self):
260 | holdingresp = self._get("holding")
261 | return holdingresp
262 |
263 | """GET Orderbook Records"""
264 |
265 | def order_data(self):
266 | orderresp = self._get("orderbook")
267 | return orderresp
268 |
269 | def get_order_history(self, nextorder):
270 | orderresp = self._get("orderbook")
271 | if nextorder == '':
272 | # orderresp = self._get("orderbook")
273 | return orderresp
274 | else:
275 | # data = {'nestOrderNumber': nextorder}
276 | # orderhistoryresp = self._post("orderhistory", data)
277 | # return orderhistoryresp
278 | for order in orderresp:
279 | if order['Nstordno'] == nextorder:
280 | return order
281 |
282 | """Method to call Cancel Orders"""
283 |
284 | def cancel_order(self, nestordernmbr):
285 | data = {'nestOrderNumber': nestordernmbr}
286 | cancelresp = self._post("cancelorder", data)
287 | return cancelresp
288 |
289 | def marketwatch_scripsdata(self, mwname, ):
290 | data = {'mwName': mwname, }
291 | marketwatchresp = self._post("marketwatch_scrips", data)
292 | return marketwatchresp
293 |
294 | """Method to call Add Scrips"""
295 |
296 | def addscrips(self,
297 | mwname,
298 | exchange,
299 | token):
300 | data = {'mwName': mwname,
301 | 'exch': exchange,
302 | 'symbol': token, }
303 | addscripsresp = self._post("addscrips", data)
304 | return addscripsresp
305 |
306 | """Method to call Delete Scrips"""
307 |
308 | def deletescrips(self,
309 | mwname,
310 | exchange,
311 | token):
312 | data = {'mwName': mwname,
313 | 'exch': exchange,
314 | 'symbol': token, }
315 | deletescripsresp = self._post("getdelete_scrips", data)
316 | return deletescripsresp
317 |
318 | """Method to call Scrip Details"""
319 |
320 | def get_scrip_info(self, instrument):
321 | data = {'exch': instrument.exchange,
322 | 'symbol': str(instrument.token)}
323 | scripsdetailresp = self._post("scripdetails", data)
324 | return scripsdetailresp
325 |
326 | """Method to call Squareoff Positions"""
327 |
328 | def squareoff_positions(self,
329 | exchange,
330 | pCode,
331 | qty,
332 | tokenno,
333 | symbol):
334 | data = {'exchSeg': exchange,
335 | 'pCode': pCode,
336 | 'netQty': qty,
337 | 'tockenNo': tokenno,
338 | 'symbol': symbol}
339 | squareoffresp = self._post("squareoffposition", data)
340 | return squareoffresp
341 |
342 | """Method to call Place Order"""
343 |
344 | def place_order(self, transaction_type, instrument, quantity, order_type,
345 | product_type, price=0.0, trigger_price=None,
346 | stop_loss=None, square_off=None, trailing_sl=None,
347 | is_amo=False,
348 | order_tag=None,
349 | is_ioc=False):
350 | if transaction_type is None:
351 | raise TypeError("Required parameter transaction_type not of type TransactionType")
352 |
353 | if instrument is None:
354 | raise TypeError("Required parameter instrument not of type Instrument")
355 |
356 | if not isinstance(quantity, int):
357 | raise TypeError("Required parameter quantity not of type int")
358 |
359 | if order_type is None:
360 | raise TypeError("Required parameter order_type not of type OrderType")
361 |
362 | if product_type is None:
363 | raise TypeError("Required parameter product_type not of type ProductType")
364 |
365 | if price is not None and not isinstance(price, float):
366 | raise TypeError("Optional parameter price not of type float")
367 |
368 | if trigger_price is not None and not isinstance(trigger_price, float):
369 | raise TypeError("Optional parameter trigger_price not of type float")
370 | if is_amo == True:
371 | complexty = "AMO"
372 | else:
373 | complexty = "regular"
374 | discqty = 0
375 | exch = instrument.exchange
376 | if (instrument.exchange == 'NFO' or instrument.exchange == 'MCX') and (product_type.value == 'CNC'):
377 | pCode = "NRML"
378 | else:
379 | if product_type.value == 'BO':
380 | pCode = "MIS"
381 | complexty = "BO"
382 | else:
383 | pCode = product_type.value
384 | price = price
385 | prctyp = order_type.value
386 | qty = quantity
387 | if is_ioc:
388 | ret = 'IOC'
389 | else:
390 | ret = 'DAY'
391 | trading_symbol = instrument.name
392 | symbol_id = str(instrument.token)
393 | transtype = transaction_type.value
394 | trigPrice = trigger_price
395 | # print("pCode:",instrument)
396 | data = [{'complexty': complexty,
397 | 'discqty': discqty,
398 | 'exch': exch,
399 | 'pCode': pCode,
400 | 'price': price,
401 | 'prctyp': prctyp,
402 | 'qty': qty,
403 | 'ret': ret,
404 | 'symbol_id': symbol_id,
405 | 'trading_symbol': trading_symbol,
406 | 'transtype': transtype,
407 | "stopLoss": stop_loss,
408 | "target": square_off,
409 | "trailing_stop_loss": trailing_sl,
410 | "trigPrice": trigPrice,
411 | "orderTag": order_tag}]
412 | # print(data)
413 | placeorderresp = self._post("placeorder", data)
414 | if len(placeorderresp) == 1:
415 | return placeorderresp[0]
416 | else:
417 | return placeorderresp
418 |
419 | """Method to get Funds Data"""
420 |
421 | def get_balance(self):
422 | fundsresp = self._get("fundsrecord")
423 | return fundsresp
424 |
425 | """Method to call Modify Order"""
426 |
427 | def modify_order(self, transaction_type, instrument, product_type, order_id, order_type, quantity, price=0.0,
428 | trigger_price=0.0):
429 | if not isinstance(instrument, Instrument):
430 | raise TypeError("Required parameter instrument not of type Instrument")
431 |
432 | if not isinstance(order_id, str):
433 | raise TypeError("Required parameter order_id not of type str")
434 |
435 | if not isinstance(quantity, int):
436 | raise TypeError("Optional parameter quantity not of type int")
437 |
438 | if type(order_type) is not OrderType:
439 | raise TypeError("Optional parameter order_type not of type OrderType")
440 |
441 | if ProductType is None:
442 | raise TypeError("Required parameter product_type not of type ProductType")
443 |
444 | if price is not None and not isinstance(price, float):
445 | raise TypeError("Optional parameter price not of type float")
446 |
447 | if trigger_price is not None and not isinstance(trigger_price, float):
448 | raise TypeError("Optional parameter trigger_price not of type float")
449 | data = {'discqty': 0,
450 | 'exch': instrument.exchange,
451 | # 'filledQuantity': filledQuantity,
452 | 'nestOrderNumber': order_id,
453 | 'prctyp': order_type.value,
454 | 'price': price,
455 | 'qty': quantity,
456 | 'trading_symbol': instrument.name,
457 | 'trigPrice': trigger_price,
458 | 'transtype': transaction_type.value,
459 | 'pCode': product_type.value}
460 | # print(data)
461 | modifyorderresp = self._post("modifyorder", data)
462 | return modifyorderresp
463 |
464 | """Method to call Exitbook Order"""
465 |
466 | def exitboorder(self, nestOrderNumber, symbolOrderId, status, ):
467 | data = {'nestOrderNumber': nestOrderNumber,
468 | 'symbolOrderId': symbolOrderId,
469 | 'status': status, }
470 | exitboorderresp = self._post("exitboorder", data)
471 | return exitboorderresp
472 |
473 | """Method to get Position Book"""
474 |
475 | def positionbook(self, ret, ):
476 | data = {'ret': ret, }
477 | positionbookresp = self._post("positiondata", data)
478 | return positionbookresp
479 |
480 | def get_daywise_positions(self):
481 | data = {'ret': 'DAY'}
482 | positionbookresp = self._post("positiondata", data)
483 | return positionbookresp
484 |
485 | def get_netwise_positions(self, ):
486 | data = {'ret': 'NET'}
487 | positionbookresp = self._post("positiondata", data)
488 | return positionbookresp
489 |
490 | def place_basket_order(self, orders):
491 | data = []
492 | for i in range(len(orders)):
493 | order_data = orders[i]
494 | if 'is_amo' in order_data and order_data['is_amo']:
495 | complexty = "AMO"
496 | else:
497 | complexty = "regular"
498 | discqty = 0
499 | exch = order_data['instrument'].exchange
500 | if order_data['instrument'].exchange == 'NFO' and order_data['product_type'].value == 'CNC':
501 | pCode = "NRML"
502 | else:
503 | pCode = order_data['product_type'].value
504 | price = order_data['price'] if 'price' in order_data else 0
505 |
506 | prctyp = order_data['order_type'].value
507 | qty = order_data['quantity']
508 | if 'is_ioc' in order_data and order_data['is_ioc']:
509 | ret = 'IOC'
510 | else:
511 | ret = 'DAY'
512 | trading_symbol = order_data['instrument'].name
513 | symbol_id = str(order_data['instrument'].token)
514 | transtype = order_data['transaction_type'].value
515 | trigPrice = order_data['trigger_price'] if 'trigger_price' in order_data else None
516 | stop_loss = order_data['stop_loss'] if 'stop_loss' in order_data else None
517 | trailing_sl = order_data['trailing_sl'] if 'trailing_sl' in order_data else None
518 | square_off = order_data['square_off'] if 'square_off' in order_data else None
519 | ordertag = order_data['order_tag'] if 'order_tag' in order_data else None
520 | request_data = {'complexty': complexty,
521 | 'discqty': discqty,
522 | 'exch': exch,
523 | 'pCode': pCode,
524 | 'price': price,
525 | 'prctyp': prctyp,
526 | 'qty': qty,
527 | 'ret': ret,
528 | 'symbol_id': symbol_id,
529 | 'trading_symbol': trading_symbol,
530 | 'transtype': transtype,
531 | "stopLoss": stop_loss,
532 | "target": square_off,
533 | "trailing_stop_loss": trailing_sl,
534 | "trigPrice": trigPrice,
535 | "orderTag": ordertag}
536 | data.append(request_data)
537 | # print(data)
538 | placeorderresp = self._post("placeorder", data)
539 | return placeorderresp
540 |
541 | def get_contract_master(self, exchange):
542 | if len(exchange) == 3 or exchange == 'INDICES':
543 | print(
544 | "NOTE: Today's contract master file will be updated after 08:00 AM. Before 08:00 AM previous day contract file be downloaded.")
545 | if time(8, 00) <= datetime.now().time() or True:
546 | url = self.base_url_c % exchange.upper()
547 | response = requests.get(url)
548 | with open("%s.csv" % exchange.upper(), "w") as f:
549 | f.write(response.text)
550 | return self._error_response("Today contract File Downloaded")
551 | else:
552 | return self._error_response("Previous day contract file saved")
553 | elif exchange is None:
554 | return self._error_response("Invalid Exchange parameter")
555 | else:
556 | return self._error_response("Invalid Exchange parameter")
557 |
558 | def get_instrument_by_symbol(self, exchange, symbol):
559 | try:
560 | contract = pd.read_csv("%s.csv" % exchange)
561 | except OSError as e:
562 | if e.errno == 2:
563 | self.get_contract_master(exchange)
564 | contract = pd.read_csv("%s.csv" % exchange)
565 | else:
566 | return self._error_response(e)
567 | if exchange == 'INDICES':
568 | filter_contract = contract[contract['symbol'] == symbol.upper()]
569 | if len(filter_contract) == 0:
570 | return self._error_response("The symbol is not available in this exchange")
571 | else:
572 | filter_contract = filter_contract.reset_index()
573 | inst = Instrument(filter_contract['exch'][0], filter_contract['token'][0], filter_contract['symbol'][0],
574 | '', '', '')
575 | return inst
576 | else:
577 | filter_contract = contract[
578 | (contract['Symbol'] == symbol.upper()) | (contract['Trading Symbol'] == symbol.upper())]
579 | if len(filter_contract) == 0:
580 | return self._error_response("The symbol is not available in this exchange")
581 | else:
582 | filter_contract = filter_contract.reset_index()
583 | if 'expiry_date' in filter_contract:
584 | inst = Instrument(filter_contract['Exch'][0], filter_contract['Token'][0],
585 | filter_contract['Symbol'][0], filter_contract['Trading Symbol'][0],
586 | filter_contract['Expiry Date'][0], filter_contract['Lot Size'][0])
587 | else:
588 | inst = Instrument(filter_contract['Exch'][0], filter_contract['Token'][0],
589 | filter_contract['Symbol'][0], filter_contract['Trading Symbol'][0], '',
590 | filter_contract['Lot Size'][0])
591 | return inst
592 |
593 | def get_instrument_by_token(self, exchange, token):
594 | try:
595 | contract = pd.read_csv("%s.csv" % exchange)
596 | except OSError as e:
597 | if e.errno == 2:
598 | self.get_contract_master(exchange)
599 | contract = pd.read_csv("%s.csv" % exchange)
600 | else:
601 | return self._error_response(e)
602 | if exchange == 'INDICES':
603 | filter_contract = contract[contract['token'] == token].reset_index(drop=False)
604 | inst = Instrument(filter_contract['exch'][0], filter_contract['token'][0], filter_contract['symbol'][0], '',
605 | '', '')
606 | return inst
607 | else:
608 | filter_contract = contract[contract['Token'] == token]
609 | if len(filter_contract) == 0:
610 | return self._error_response("The symbol is not available in this exchange")
611 | else:
612 | filter_contract = filter_contract.reset_index()
613 | if 'expiry_date' in filter_contract:
614 | inst = Instrument(filter_contract['Exch'][0], filter_contract['Token'][0],
615 | filter_contract['Symbol'][0],
616 | filter_contract['Trading Symbol'][0], filter_contract['Expiry Date'][0],
617 | filter_contract['Lot Size'][0])
618 | else:
619 | inst = Instrument(filter_contract['Exch'][0], filter_contract['Token'][0],
620 | filter_contract['Symbol'][0],
621 | filter_contract['Trading Symbol'][0], '', filter_contract['Lot Size'][0])
622 | return inst
623 |
624 | def get_instrument_for_fno(self, exch, symbol, expiry_date, is_fut=True, strike=None, is_CE=False):
625 | # print(exch)
626 | if exch in ['NFO', 'CDS', 'MCX', 'BFO', 'BCD']:
627 | if exch == 'CDS':
628 | edate_format = '%d-%m-%Y'
629 | else:
630 | edate_format = '%Y-%m-%d'
631 | else:
632 | return self._error_response("Invalid exchange")
633 | if not symbol:
634 | return self._error_response("Symbol is Null")
635 | try:
636 | expiry_date = datetime.strptime(expiry_date, "%Y-%m-%d").date()
637 | except ValueError as e:
638 | return self._error_response(e)
639 | if type(is_CE) is bool:
640 | if is_CE == True:
641 | option_type = "CE"
642 | else:
643 | option_type = "PE"
644 | else:
645 | return self._error_response("is_fut is not boolean value")
646 | # print(option_type)
647 | try:
648 | contract = pd.read_csv("%s.csv" % exch)
649 | # print(strike,is_fut)
650 | except OSError as e:
651 | if e.errno == 2:
652 | self.get_contract_master(exch)
653 | contract = pd.read_csv("%s.csv" % exch)
654 | else:
655 | return self._error_response(e)
656 | if is_fut == False:
657 | if strike:
658 | filter_contract = contract[(contract['Exch'] == exch) & (
659 | (contract['Symbol'] == symbol) | (contract['Trading Symbol'] == symbol)) & (
660 | contract['Option Type'] == option_type) & (
661 | contract['Strike Price'] == strike) & (
662 | contract['Expiry Date'] == expiry_date.strftime(edate_format))]
663 | else:
664 | filter_contract = contract[(contract['Exch'] == exch) & (
665 | (contract['Symbol'] == symbol) | (contract['Trading Symbol'] == symbol)) & (
666 | contract['Option Type'] == option_type) & (
667 | contract['Expiry Date'] == expiry_date.strftime(edate_format))]
668 | if is_fut == True:
669 | if strike == None:
670 | filter_contract = contract[(contract['Exch'] == exch) & (
671 | (contract['Symbol'] == symbol) | (contract['Trading Symbol'] == symbol)) & (
672 | contract['Option Type'] == 'XX') & (
673 | contract['Expiry Date'] == expiry_date.strftime(edate_format))]
674 | else:
675 | return self._error_response("No strike price for future")
676 | # print(len(filter_contract))
677 | if len(filter_contract) == 0:
678 | return self._error_response("No Data")
679 | else:
680 | inst = []
681 | token = []
682 | filter_contract = filter_contract.reset_index()
683 | for i in range(len(filter_contract)):
684 | if filter_contract['Token'][i] not in token:
685 | token.append(filter_contract['Token'][i])
686 | inst.append(Instrument(filter_contract['Exch'][i], filter_contract['Token'][i],
687 | filter_contract['Symbol'][i], filter_contract['Trading Symbol'][i],
688 | filter_contract['Expiry Date'][i], filter_contract['Lot Size'][i]))
689 | if len(inst) == 1:
690 | return inst[0]
691 | else:
692 | return inst
693 |
694 | def invalid_sess(self, session_ID):
695 | url = self.base_url + 'ws/invalidateSocketSess'
696 | headers = {
697 | 'Authorization': 'Bearer ' + self.user_id + ' ' + session_ID,
698 | 'Content-Type': 'application/json'
699 | }
700 | payload = {"loginType": "API"}
701 | datas = json.dumps(payload)
702 | response = requests.request("POST", url, headers=headers, data=datas)
703 | return response.json()
704 |
705 | def createSession(self, session_ID):
706 | url = self.base_url + 'ws/createSocketSess'
707 | headers = {
708 | 'Authorization': 'Bearer ' + self.user_id + ' ' + session_ID,
709 | 'Content-Type': 'application/json'
710 | }
711 | payload = {"loginType": "API"}
712 | datas = json.dumps(payload)
713 | response = requests.request("POST", url, headers=headers, data=datas)
714 |
715 | return response.json()
716 |
717 | def __ws_run_forever(self):
718 | while self.__stop_event.is_set() is False:
719 | try:
720 | self.ws.run_forever(ping_interval=3, ping_payload='{"t":"h"}', sslopt={"cert_reqs": ssl.CERT_NONE})
721 | except Exception as e:
722 | logger.warning(f"websocket run forever ended in exception, {e}")
723 | sleep(0.1)
724 |
725 | def on_message(self, ws, message):
726 | self.__subscribe_callback(message)
727 | data = json.loads(message)
728 | # if 's' in data and data['s'] == 'OK':
729 | # self.ws_connection =True
730 | # data = {
731 | # "k": self.subscriptions,
732 | # "t": 't',
733 | # "m": "compact_marketdata"
734 | # }
735 | # ws.send(json.dumps(data))
736 |
737 | def on_error(self, ws, error):
738 | if (
739 | type(ws) is not websocket.WebSocketApp): # This workaround is to solve the websocket_client's compatiblity issue of older versions. ie.0.40.0 which is used in upstox. Now this will work in both 0.40.0 & newer version of websocket_client
740 | error = ws
741 | if self.__on_error:
742 | self.__on_error(error)
743 |
744 | def on_close(self, *arguments, **keywords):
745 | self.ws_connection = False
746 | if self.__on_disconnect:
747 | self.__on_disconnect()
748 |
749 | def stop_websocket(self):
750 | self.ws_connection = False
751 | self.ws.close()
752 | self.__stop_event.set()
753 |
754 | def on_open(self, ws):
755 | initCon = {
756 | "susertoken": self.ENC,
757 | "t": "c",
758 | "actid": self.user_id + "_API",
759 | "uid": self.user_id + "_API",
760 | "source": "API"
761 | }
762 | self.ws.send(json.dumps(initCon))
763 | self.ws_connection = True
764 | if self.__on_open:
765 | self.__on_open()
766 |
767 | def subscribe(self, instrument):
768 | # print("Subscribed")
769 | scripts = ""
770 | for __instrument in instrument:
771 | scripts = scripts + __instrument.exchange + "|" + str(__instrument.token) + "#"
772 | self.subscriptions = scripts[:-1]
773 | if self.market_depth:
774 | t = "d" # Subscribe Depth
775 | else:
776 | t = "t" # Subsribe token
777 | data = {
778 | "k": self.subscriptions,
779 | "t": t
780 | }
781 | # "m": "compact_marketdata"
782 | self.ws.send(json.dumps(data))
783 |
784 | def unsubscribe(self, instrument):
785 | # print("UnSubscribed")
786 | scripts = ""
787 | if self.subscriptions:
788 | split_subscribes = self.subscriptions.split('#')
789 | for __instrument in instrument:
790 | scripts = scripts + __instrument.exchange + "|" + str(__instrument.token) + "#"
791 | if self.subscriptions:
792 | split_subscribes.remove(__instrument.exchange + "|" + str(__instrument.token))
793 | self.subscriptions = split_subscribes
794 |
795 | if self.market_depth:
796 | t = "ud"
797 | else:
798 | t = "u"
799 |
800 | data = {
801 | "k": scripts[:-1],
802 | "t": t
803 | }
804 | self.ws.send(json.dumps(data))
805 |
806 | def search_instruments(self, exchange, symbol):
807 | base_url = self.base_url.replace('/AliceBlueAPIService/api', '')
808 | scrip_Url = base_url + "DataApiService/v2/exchange/getScripForSearchAPI"
809 | # print(scrip_Url)
810 | data = {'symbol': symbol, 'exchange': [exchange]}
811 | # print(data)
812 | scrip_response = self._dummypost(scrip_Url, data)
813 | if scrip_response == []:
814 | return self._error_response('Symbol not found')
815 | else:
816 | inst = []
817 | for i in range(len(scrip_response)):
818 | # print(scrip_response[i])
819 | inst.append(Instrument(scrip_response[i]['exch'], scrip_response[i]['token'],
820 | scrip_response[i]['formattedInsName'], scrip_response[i]['symbol'],
821 | scrip_response[i]['expiry'], scrip_response[i]['lotSize']))
822 | return inst
823 |
824 | def start_websocket(self, socket_open_callback=None, socket_close_callback=None, socket_error_callback=None,
825 | subscription_callback=None, check_subscription_callback=None, run_in_background=False,
826 | market_depth=False):
827 | if check_subscription_callback != None:
828 | check_subscription_callback(self.script_subscription_instrument)
829 | session_request = self.session_id
830 | self.__on_open = socket_open_callback
831 | self.__on_disconnect = socket_close_callback
832 | self.__on_error = socket_error_callback
833 | self.__subscribe_callback = subscription_callback
834 | self.market_depth = market_depth
835 | if self.__stop_event != None and self.__stop_event.is_set():
836 | self.__stop_event.clear()
837 | if session_request:
838 | session_id = session_request
839 | sha256_encryption1 = hashlib.sha256(session_id.encode('utf-8')).hexdigest()
840 | self.ENC = hashlib.sha256(sha256_encryption1.encode('utf-8')).hexdigest()
841 | invalidSess = self.invalid_sess(session_id)
842 | if invalidSess['stat'] == 'Ok':
843 | print("STAGE 1: Invalidate the previous session :", invalidSess['stat'])
844 | createSess = self.createSession(session_id)
845 | if createSess['stat'] == 'Ok':
846 | print("STAGE 2: Create the new session :", createSess['stat'])
847 | print("Connecting to Socket ...")
848 | self.__stop_event = threading.Event()
849 | websocket.enableTrace(False)
850 | self.ws = websocket.WebSocketApp(self._sub_urls['base_url_socket'],
851 | on_open=self.on_open,
852 | on_message=self.on_message,
853 | on_close=self.on_close,
854 | on_error=self.on_error)
855 |
856 | # if run_in_background:
857 | # print("Running background!")
858 | # self.__ws_thread = threading.Thread(target=self.__ws_run_forever())
859 | # self.__ws_thread.daemon = True
860 | # self.__ws_thread.start()
861 | # else:
862 | # try:
863 | # self.ws.run_forever(dispatcher=rel) # Set dispatcher to automatic reconnection
864 | # rel.signal(2, rel.abort) # Keyboard Interrupt
865 | # rel.dispatch()
866 | # except Exception as e:
867 | # print("Error:",e)
868 | if run_in_background is True:
869 | self.__ws_thread = threading.Thread(target=self.__ws_run_forever)
870 | self.__ws_thread.daemon = True
871 | self.__ws_thread.start()
872 | else:
873 | self.__ws_run_forever()
874 |
875 | def get_historical(self, instrument, from_datetime, to_datetime, interval, indices=False):
876 | # intervals = ["1", "D"]
877 | payload = json.dumps({"token": str(instrument.token),
878 | "exchange": instrument.exchange if not indices else f"{instrument.exchange}::index",
879 | "from": str(int(from_datetime.timestamp())) + '000',
880 | "to": str(int(to_datetime.timestamp())) + '000',
881 | "resolution": interval
882 | })
883 | _headers = {
884 | "X-SAS-Version": "2.0",
885 | "User-Agent": self._user_agent(),
886 | "Authorization": self._user_authorization(),
887 | 'Content-Type': 'application/json'
888 | }
889 | lst = requests.post(self.base_url + "chart/history", data=payload, headers=_headers)
890 | response = lst.json()
891 | if response['stat'] == 'Not_Ok':
892 | return response
893 | else:
894 | df = pd.DataFrame(lst.json()['result'])
895 | df = df.rename(columns={'time': 'datetime'})
896 | df = df[['datetime', 'open', 'high', 'low', 'close', 'volume']]
897 | return df
898 |
899 | def basket_margin(self, basketmargins):
900 | basket_data = []
901 | for basket_list in basketmargins:
902 | basket_data.append({
903 | "exchange": basket_list['exchange'],
904 | "tradingSymbol": basket_list['tradingSymbol'],
905 | "price": basket_list['price'],
906 | "qty": basket_list['qty'],
907 | "product": basket_list['product'],
908 | "priceType": basket_list['priceType'],
909 | "triggerPrice": basket_list['triggerPrice'],
910 | "transType": basket_list['transType']
911 | })
912 | response = self._post("basket_margin", basket_data)
913 | return response
914 |
915 | def create_websocket_token(self):
916 | user_token = self.get_session_id()
917 | session_ID = user_token['sessionID']
918 | headers = {
919 | 'Authorization': 'Bearer Token' + ' ' + session_ID,
920 | 'Content-Type': 'application/json'
921 | }
922 | response = requests.request("GET", self.create_websocket_url, headers=headers)
923 | parse_data = response.json()
924 | websocket_Token = parse_data['result'][0]['orderToken']
925 | return websocket_Token
926 |
927 | def connect_webcoscket(self, userid):
928 |
929 | ws_token = self.create_websocket_token()
930 | print("WebSocket connection established.")
931 | headers = {
932 | 'Content-Type': 'application/json'
933 | }
934 | payload = {
935 | "orderToken": ws_token,
936 | "userId": userid
937 | }
938 | session_data = json.dumps(payload)
939 |
940 | def on_message(ws, message):
941 | print(message)
942 |
943 | def on_error(ws, error):
944 | if type(ws) is not websocket.WebSocketApp:
945 | error = ws
946 | if self.__on_error:
947 | self.__on_error(error)
948 |
949 | def on_close(ws, close_status_code, close_msg):
950 | self.ws_connection = False
951 | if self.__on_disconnect:
952 | self.__on_disconnect()
953 | print(f"WebSocket Closed. Status code: {close_status_code}, Reason: {close_msg}")
954 |
955 | def on_open(ws):
956 | print("WebSocket Connection Opened")
957 | ws.send(session_data)
958 | threading.Thread(target=heart_beat_connection, args=(ws,), daemon=True).start()
959 |
960 | def heart_beat_connection(ws):
961 | heartbeat_Flag = True
962 | while heartbeat_Flag:
963 | payload = {
964 | "heartbeat": "h",
965 | "userId": userid
966 | }
967 | hearbeat_data = json.dumps(payload)
968 | ws.send(hearbeat_data)
969 | time.sleep(55)
970 |
971 | # Create the WebSocket connection
972 | ws = websocket.WebSocketApp(
973 | self.websocket_url,
974 | on_message=on_message,
975 | on_error=on_error,
976 | on_close=on_close,
977 | on_open=on_open,
978 | header=headers # Pass headers if required
979 | )
980 | ws.run_forever()
981 |
982 |
983 | class Alice_Wrapper():
984 | def open_net_position(Net_position):
985 | open_net_position = [data for data in Net_position if data['Netqty'] != '0']
986 | return open_net_position
987 |
988 | def close_net_poition(Net_position):
989 | close_net_position = [data for data in Net_position if data['Netqty'] == '0']
990 | return close_net_position
991 |
992 | def subscription(script_list):
993 | if len(script_list) > 0:
994 | Aliceblue.script_subscription_instrument = script_list
995 | sub_prams = ''
996 | # print(script_list)
997 | for i in range(len(script_list)):
998 | end_point = '' if i == len(script_list) - 1 else '#'
999 | sub_prams = sub_prams + script_list[i].exchange + '|' + str(script_list[i].token) + end_point
1000 | return sub_prams
1001 | else:
1002 | return {'stat': 'Not_ok', 'emsg': 'Script response is not fetched properly. Please check once'}
1003 |
1004 | def get_order_history(response):
1005 | if response:
1006 | pending = []
1007 | completed = []
1008 | for i in range(len(response)):
1009 | data = {
1010 | "validity": response[i]['Validity'],
1011 | "user_order_id": response[i]['RequestID'],
1012 | "trigger_price": response[i]['Trgprc'],
1013 | "transaction_type": response[i]['Trantype'],
1014 | "trading_symbol": response[i]['Trsym'],
1015 | "remaining_quantity": response[i]['Unfilledsize'],
1016 | "rejection_reason": response[i]['RejReason'],
1017 | "quantity": response[i]['Qty'],
1018 | "product": response[i]['Pcode'],
1019 | "price": response[i]['Prc'],
1020 | "order_type": response[i]['Prctype'],
1021 | "order_tag": response[i]['remarks'],
1022 | "order_status": response[i]['Status'],
1023 | "order_entry_time": response[i]['iSinceBOE'],
1024 | "oms_order_id": response[i]['Nstordno'],
1025 | "nest_request_id": response[i]['RequestID'],
1026 | "lotsize": response[i]['multiplier'],
1027 | "login_id": response[i]['user'],
1028 | "leg_order_indicator": "",
1029 | "instrument_token": response[i]['token'],
1030 | "filled_quantity": response[i]['Fillshares'],
1031 | "exchange_time": response[i]['OrderedTime'],
1032 | "exchange_order_id": response[i]['ExchOrdID'],
1033 | "exchange": response[i]['Exchange'],
1034 | "disclosed_quantity": response[i]['Dscqty'],
1035 | "client_id": response[i]['accountId'],
1036 | "average_price": float(response[i]['Avgprc'])
1037 | }
1038 | if response[i]['Status'] == 'open':
1039 | pending.append(data)
1040 | else:
1041 | completed.append(data)
1042 |
1043 | old_response = {
1044 | "status": "success",
1045 | "message": "",
1046 | "data": {
1047 | "pending_orders": pending,
1048 | "completed_orders": completed
1049 | }
1050 | }
1051 | return old_response
1052 | else:
1053 | return response
1054 |
1055 | def get_balance(response):
1056 | cash_pos = []
1057 | for i in range(len(response)):
1058 | data = {
1059 | "utilized": {
1060 | "var_margin": response[i]['varmargin'],
1061 | "unrealised_m2m": response[i]['unrealizedMtomPrsnt'],
1062 | "span_margin": response[i]['spanmargin'],
1063 | "realised_m2m": response[i]['realizedMtomPrsnt'],
1064 | "premium_present": response[i]['premiumPrsnt'],
1065 | "pay_out": response[i]['payoutamount'],
1066 | "multiplier": response[i]['multiplier'],
1067 | "exposure_margin": response[i]['exposuremargin'],
1068 | "elm": response[i]['elm'],
1069 | "debits": response[i]['debits']
1070 | },
1071 | "segment": response[i]['segment'],
1072 | "net": response[i]['net'],
1073 | "category": response[i]['category'],
1074 | "available": {
1075 | "pay_in": response[i]['rmsPayInAmnt'],
1076 | "notionalCash": response[i]['notionalCash'],
1077 | "direct_collateral_value": response[i]['directcollateralvalue'],
1078 | "credits": response[i]['credits'],
1079 | "collateral_value": response[i]['collateralvalue'],
1080 | "cashmarginavailable": response[i]['cashmarginavailable'],
1081 | "adhoc_margin": response[i]['adhocMargin']
1082 | }
1083 | }
1084 | cash_pos.append(data)
1085 | if 'stat' not in response:
1086 | old_response = {
1087 | "status": "success",
1088 | "message": "",
1089 | "data": {
1090 | "cash_positions": cash_pos
1091 | }
1092 | }
1093 | return old_response
1094 | else:
1095 | return response
1096 |
1097 | def get_profile(response):
1098 | if 'stat' not in response:
1099 | exch = response['exchEnabled']
1100 | exch_enabled = []
1101 | if '|' in exch:
1102 | exchange = exch.split('|')
1103 | for ex in exchange:
1104 | data = ex.split('_')[0].upper()
1105 | if data != '':
1106 | exch_enabled.append(data)
1107 | else:
1108 | exch_enabled.append(exch.split('_')[0].upper())
1109 | old_response = {
1110 | "status": "success",
1111 | "message": "",
1112 | "data": {
1113 | "phone": response['cellAddr'],
1114 | "pan_number": "",
1115 | "name": response['accountName'],
1116 | "login_id": response['accountId'],
1117 | "exchanges": exch_enabled,
1118 | "email_address": response['emailAddr'],
1119 | "dp_ids": [],
1120 | "broker_name": "ALICEBLUE",
1121 | "banks": [],
1122 | "backoffice_enabled": None
1123 | }
1124 | }
1125 | return old_response
1126 | else:
1127 | return response
1128 |
1129 | def get_daywise_positions(response):
1130 | if 'stat' not in response:
1131 | true = True
1132 | positions = []
1133 | for i in range(len(response)):
1134 | data = {
1135 | "total_buy_quantity": int(response[i]['Bqty']),
1136 | "instrument_token": response[i]['Token'],
1137 | "close_price_mtm": '',
1138 | "close_price": '',
1139 | "total_sell_quantity": int(response[i]['Sqty']),
1140 | "buy_amount_mtm": response[i]['Fillbuyamt'].replace(',', ''),
1141 | "average_sell_price": response[i]['Sellavgprc'],
1142 | "sell_amount": response[i]['Fillsellamt'],
1143 | "average_buy_price_mtm": response[i]['Buyavgprc'],
1144 | "oms_order_id": '',
1145 | "trading_symbol": response[i]['Tsym'],
1146 | "unrealised_pnl": response[i]['unrealisedprofitloss'],
1147 | "sell_amount_mtm": response[i]['Fillsellamt'],
1148 | "product": response[i]['Pcode'],
1149 | "cf_buy_quantity": '',
1150 | "enabled": '',
1151 | "cf_average_sell_price": '',
1152 | "average_buy_price": response[i]['Buyavgprc'],
1153 | "net_amount_mtm": response[i]['MtoM'],
1154 | "ltp": response[i]['LTP'],
1155 | "realised_pnl": response[i]['realisedprofitloss'],
1156 | "fill_id": response[i]['BEP'],
1157 | "cf_average_buy_price": '',
1158 | "cf_sell_quantity": '',
1159 | "bep": response[i]['BEP'],
1160 | "buy_amount": response[i]['Fillbuyamt'].replace(',', ''),
1161 | "client_id": response[i]['actid'],
1162 | "net_quantity": int(response[i]['Netqty']),
1163 | "average_sell_price_mtm": response[i]['Sellavgprc'],
1164 | "buy_quantity": response[i]['Bqty'],
1165 | "strike_price": response[i]['Stikeprc'],
1166 | "multiplier": '',
1167 | "net_amount": response[i]['Netamt'],
1168 | "exchange": response[i]['Exchange'],
1169 | "m2m": response[i]['MtoM'],
1170 | "sell_quantity": response[i]['Sqty']
1171 | }
1172 | positions.append(data)
1173 |
1174 | old_response = {
1175 | "status": "success",
1176 | "message": "",
1177 | "data": {
1178 | "positions": positions
1179 | }
1180 | }
1181 | return old_response
1182 |
1183 | def get_netwise_positions(response):
1184 | if 'stat' not in response:
1185 | positions = []
1186 | true = True
1187 | for i in range(len(response)):
1188 | data = {
1189 | "total_buy_quantity": int(response[i]['Bqty']),
1190 | "instrument_token": response[i]['Token'],
1191 | "close_price_mtm": '',
1192 | "close_price": '',
1193 | "total_sell_quantity": int(response[i]['Sqty']),
1194 | "buy_amount_mtm": response[i]['Fillbuyamt'].replace(',', ''),
1195 | "average_sell_price": response[i]['Sellavgprc'],
1196 | "sell_amount": response[i]['Fillsellamt'],
1197 | "average_buy_price_mtm": response[i]['Buyavgprc'],
1198 | "oms_order_id": '',
1199 | "trading_symbol": response[i]['Tsym'],
1200 | "unrealised_pnl": response[i]['unrealisedprofitloss'],
1201 | "sell_amount_mtm": response[i]['Fillsellamt'],
1202 | "product": response[i]['Pcode'],
1203 | "cf_buy_quantity": '',
1204 | "enabled": '',
1205 | "cf_average_sell_price": '',
1206 | "average_buy_price": response[i]['Buyavgprc'],
1207 | "net_amount_mtm": response[i]['MtoM'],
1208 | "ltp": response[i]['LTP'],
1209 | "realised_pnl": response[i]['realisedprofitloss'],
1210 | "fill_id": response[i]['BEP'],
1211 | "cf_average_buy_price": '',
1212 | "cf_sell_quantity": '',
1213 | "bep": response[i]['BEP'],
1214 | "buy_amount": response[i]['Fillbuyamt'].replace(',', ''),
1215 | "client_id": response[i]['actid'],
1216 | "net_quantity": int(response[i]['Netqty']),
1217 | "average_sell_price_mtm": response[i]['Sellavgprc'],
1218 | "buy_quantity": response[i]['Bqty'],
1219 | "strike_price": response[i]['Stikeprc'],
1220 | "multiplier": '',
1221 | "net_amount": response[i]['Netamt'],
1222 | "exchange": response[i]['Exchange'],
1223 | "m2m": response[i]['MtoM'],
1224 | "sell_quantity": response[i]['Sqty']
1225 | }
1226 | positions.append(data)
1227 |
1228 | old_response = {
1229 | "status": "success",
1230 | "message": "",
1231 | "data": {
1232 | "positions": positions
1233 | }
1234 | }
1235 | return old_response
1236 |
1237 | def get_holding_positions(response):
1238 | if response['stat'] == 'Ok':
1239 | total_holdings = response['HoldingVal']
1240 | holding = []
1241 | client_id = response['clientid']
1242 | for i in range(len(total_holdings)):
1243 | data = {
1244 | "withheld_qty": total_holdings[i]['WHqty'],
1245 | "used_quantity": total_holdings[i]['Usedqty'],
1246 | "trading_symbol": total_holdings[i]['Bsetsym'] if total_holdings[i]['ExchSeg1'] == 'BSE' else
1247 | total_holdings[i]['Nsetsym'],
1248 | "target_product": total_holdings[i]['Tprod'],
1249 | "t1_quantity": total_holdings[i]['SellableQty'],
1250 | "quantity": total_holdings[i]['Holdqty'],
1251 | "product": total_holdings[i]['Pcode'],
1252 | "price": total_holdings[i]['LTcse'],
1253 | "nse_ltp": total_holdings[i]['LTnse'],
1254 | "isin": total_holdings[i]['isin'],
1255 | "instrument_token": total_holdings[i]['Token1'],
1256 | "holding_update_quantity": total_holdings[i]['HUqty'],
1257 | "haircut": total_holdings[i]['Haircut'],
1258 | "exchange": total_holdings[i]['ExchSeg1'],
1259 | "collateral_update_quantity": total_holdings[i]['CUqty'],
1260 | "collateral_type": total_holdings[i]['Coltype'],
1261 | "collateral_quantity": total_holdings[i]['Colqty'],
1262 | "client_id": client_id,
1263 | "buy_avg_mtm": total_holdings[i]['pdc'],
1264 | "buy_avg": total_holdings[i]['Price'],
1265 | "bse_ltp": total_holdings[i]['LTbse']
1266 | }
1267 | holding.append(data)
1268 | old_response = {
1269 | "status": "success",
1270 | "message": "",
1271 | "data": {
1272 | "holdings": holding
1273 | }
1274 | }
1275 | return old_response
1276 | else:
1277 | return response
1278 |
1279 | def place_order(response):
1280 | if response[0]['stat'] == 'Ok':
1281 | old_response = {'status': 'success', 'message': '', 'data': {'oms_order_id': response[0]['NOrdNo']}}
1282 | return old_response
1283 | else:
1284 | return response
1285 |
1286 | def place_basket_order(response):
1287 | Flag = 0
1288 | for i in range(len(response)):
1289 | if response[i]['stat'] == 'Ok':
1290 | Flag = Flag + 1
1291 | if Flag - len(response) == 0:
1292 | old_response = {'status': 'success', 'message': 'Order placed successfully', 'data': {}}
1293 | return old_response
1294 | else:
1295 | return response
1296 |
1297 | def modify_order(response):
1298 | if response['stat'] == 'Ok':
1299 | data = response['Result'].split(":")
1300 | old_response = {'status': 'success', 'message': '', 'data': {'oms_order_id': [data[1]]}}
1301 | return old_response
1302 | else:
1303 | return response
1304 |
1305 | def get_trade_book(response):
1306 | if response:
1307 | trades = []
1308 | for i in range(len(response)):
1309 | data = {
1310 | "user_order_id": response[i]['NOReqID'],
1311 | "transaction_type": response[i]['Trantype'],
1312 | "trading_symbol": response[i]['Tsym'],
1313 | "trade_price": float(response[i]['Price']),
1314 | "trade_id": response[i]['FillId'],
1315 | "product": response[i]['Pcode'],
1316 | "order_entry_time": response[i]['iSinceBOE'],
1317 | "oms_order_id": response[i]['Nstordno'],
1318 | "instrument_token": response[i]['Symbol'],
1319 | "filled_quantity": response[i]['Filledqty'],
1320 | "exchange_time": response[i]['Exchtime'],
1321 | "exchange_order_id": response[i]['ExchordID'],
1322 | "exchange": response[i]['Exchange']
1323 | }
1324 | trades.append(data)
1325 | old_response = {
1326 | "status": "success",
1327 | "message": "",
1328 | "data": {
1329 | "trades": trades
1330 | }
1331 | }
1332 | return old_response
1333 | else:
1334 | return response
1335 |
1336 | def cancel_order(response):
1337 | if 'stat' in response:
1338 | if response['stat'] == 'Ok':
1339 | old_response = {'status': 'success', 'message': '', 'data': {'status': response['stat']}}
1340 | else:
1341 | old_response = {'status': '', 'message': '', 'data': {'status': response['stat']}}
1342 | return old_response
1343 | else:
1344 | return response
1345 |
--------------------------------------------------------------------------------