├── 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 | 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. ![image](https://user-images.githubusercontent.com/38440742/85207234-4dc96f80-b2f5-11ea-990c-df013dd69cf2.png) 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) ![image](https://user-images.githubusercontent.com/38440742/89105781-343a3e00-d3f2-11ea-9f86-92dda88aa5bf.png) 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 | --------------------------------------------------------------------------------