├── MISC ├── get_last_weekday_list_version.py ├── get_last_weekday_numpy_version.py └── webhook_server │ ├── breeze_webhook_server.py │ └── readme.md ├── Option_Plus.py ├── README.md ├── get_started.py └── webinar ├── Analysing_historical_market_data_from_Breeze_API_using_Pandas_framework.py ├── Convert_JsonOutput_to_DataFrame.py ├── Equity_data_to_dataframe.py ├── How_to_save_historical_data_in_dataframe.py ├── MTF_Place_order_code ├── Multiples_Stock_token_WebsocketSubscription.py ├── ORB_webinar_file.txt ├── Option_Greeks_Calculation_using_OptionChain.py ├── Predefined_StraddleStrategy_SDK.py ├── README.md ├── Researching_trading_strategies_using_Pandas_framework.py ├── breeze_webinar_20230215.py ├── breeze_webinar_auto_strike_selection_20230407.py ├── chatGPT.py ├── how_to_calculate_sma.py ├── how_to_place_option_order.py ├── how_to_use_websockets.py ├── rsi_ema.txt ├── rsi_ema_executional_code.txt ├── rsi_strategy_code.py ├── trailing_stoploss.py └── trailing_stoploss_through_websocket.py /MISC/get_last_weekday_list_version.py: -------------------------------------------------------------------------------- 1 | import calendar as cal 2 | import sys 3 | from datetime import datetime 4 | 5 | def get_last_weekday(str_day, int_year, int_month): 6 | ''' 7 | Get the last weekday of a given month in a given year. 8 | Parameters: 9 | str_day (str): case insensitive day of week you want to seek. 10 | ex.: 'thursday', 'tuesday' 11 | int_year (int): integer representing year in YYYY format 12 | ex.: 1998, 2002 13 | int_month (int): integer representing the month in MM format 14 | ex.: 1, 11 15 | 16 | Returns: 17 | _ (datetime): date object from the Python's Standard datetime library 18 | 19 | 20 | ''' 21 | dict_day_codes = {'monday':1, 22 | 'tuesday':2, 23 | 'wednesday':3, 24 | 'thursday':4, 25 | 'friday':5, 26 | 'saturday':6, 27 | 'sunday':7} 28 | try: 29 | int_day=dict_day_codes[str_day] 30 | except KeyError: 31 | print("Check spelling!") 32 | sys.exit(0) 33 | list_calendar = cal.monthcalendar(int_year, int_month) 34 | list_weekdays = [1,2,3,4,5,6,7] 35 | list_product = [list_weekdays for dates in cal.monthcalendar(int_year,int_month)] 36 | 37 | l_cal = [x for sub_list in list_calendar for x in sub_list] 38 | l_prod = [x for sub_list in list_product for x in sub_list] 39 | l_out = [l_prod[i] if l_cal[i]!=0 else 0 for i in range(len(l_cal))] 40 | l_out.reverse() 41 | return datetime(int_year, int_month, l_cal[len(l_cal)-l_out.index(int_day)-1]) 42 | -------------------------------------------------------------------------------- /MISC/get_last_weekday_numpy_version.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import calendar as cal 3 | import sys 4 | from datetime import datetime 5 | 6 | def get_last_weekday(str_day, int_year, int_month): 7 | dict_day_codes = {'monday':1, 8 | 'tuesday':2, 9 | 'wednesday':3, 10 | 'thursday':4, 11 | 'friday':5, 12 | 'saturday':6, 13 | 'sunday':7} 14 | try: 15 | int_day=dict_day_codes[str_day.lower()] 16 | except KeyError: 17 | print("Check spelling!") 18 | sys.exit(0) 19 | list_calendar = cal.monthcalendar(int_year, int_month) 20 | list_weekdays = [1,2,3,4,5,6,7] 21 | list_product = [list_weekdays for dates in cal.monthcalendar(int_year,int_month)] 22 | 23 | arr_cal, arr_product=np.array(list_calendar), np.array(list_product) 24 | 25 | arr_zeros=np.zeros(arr_cal.shape, int) 26 | 27 | np.copyto(dst=arr_product, src=arr_zeros, where=arr_cal == 0) 28 | x = np.argwhere(arr_product==int_day)[-1] 29 | return datetime(int_year, int_month, arr_cal[x[0]][x[1]]) 30 | -------------------------------------------------------------------------------- /MISC/webhook_server/breeze_webhook_server.py: -------------------------------------------------------------------------------- 1 | from breeze_connect import BreezeConnect 2 | from flask import Flask, request 3 | import sys #to import configurations like keys 4 | 5 | sys.path.append('/path/to/this/file/') 6 | 7 | from breeze_configs import Breeze_Configs 8 | configs = Breeze_Configs() 9 | 10 | #set secret 11 | webhook_secret='whatever_i_want' 12 | 13 | try: 14 | breeze = BreezeConnect(api_key=configs.webhook_api_key) 15 | breeze.generate_session(api_secret=configs.webhook_api_secret, session_token=configs.webhook_session_token) 16 | breeze.ws_connect() 17 | breeze.subscribe_feeds(get_order_notification=True) 18 | except Exception as e: 19 | print(e) 20 | 21 | # create the Flask app 22 | app = Flask(__name__) 23 | 24 | @app.route('/place_order', methods=['POST']) 25 | def json_example(): 26 | request_data = request.get_json() 27 | if request_data: 28 | if request_data.pop('secret')==webhook_secret: 29 | try: 30 | dict_order_details = breeze.place_order(**request_data) 31 | print(dict_order_details) 32 | return dict_order_details 33 | except Exception as e: 34 | print(e) 35 | return e 36 | else: 37 | print("Authorization error: check credentials.") 38 | return "Authorization error: check credentials." 39 | else: 40 | return 'No data found.' 41 | 42 | if __name__ == '__main__': 43 | # run app in debug mode on port 5000 44 | app.run(debug=True, port=5000) 45 | -------------------------------------------------------------------------------- /MISC/webhook_server/readme.md: -------------------------------------------------------------------------------- 1 | # The Idea 2 | 3 | The idea is to receive JSON structures that are basically breeze.place_order() calls + a secret. If the secret matches, then the server sends a place order call over breeze. JSON can be created referring to [PyPi's place_order() documentation](https://pypi.org/project/breeze-connect/#place_order). 4 | 5 | # Examples 6 | 7 | breeze.place_order(stock_code="ICIBAN", 8 | exchange_code="NFO", 9 | product="futures", 10 | action="buy", 11 | order_type="limit", 12 | stoploss="0", 13 | quantity="3200", 14 | price="200", 15 | validity="day", 16 | validity_date="2022-08-22T06:00:00.000Z", 17 | disclosed_quantity="0", 18 | expiry_date="2022-08-25T06:00:00.000Z", 19 | right="others", 20 | strike_price="0", 21 | user_remark="Test") 22 | 23 | will translate to the following JSON: 24 | `'{"stock_code":"ICIBAN","exchange_code":"NFO","product":"futures","action":"buy","order_type":"limit","stoploss":"0","quantity":"3200","price":"200","validity":"day","validity_date":"2022-08-22T06:00:00.000Z","disclosed_quantity":"0","expiry_date":"2022-08-25T06:00:00.000Z","right":"others","strike_price":"0","user_remark":"Test","secret":"whatever_i_want"}'` 25 | 26 | where the `'secret'` is defined by you in your code, and is the only thing not used in the `place_order()` call. This is a **must** have because it's the only thing that prevents random people sending your server an instruction to place order. 27 | 28 | # Notes 29 | 30 | * Currently, this JSON needs to be sent to port 5000 of the web application's host. Once Gunicorn+nginx are added, we can then use port 80 and 443 like civilized human beings of culture. Don't try to force the app to serve on 80 (with `port=5000` changed to 80): best case scenario is that you will get an error, worst case is that you will negatively impact something already being served on port 80. 31 | * Following best practices, we place credentials in a dedicated class in a separate file named `breeze_configs.py` in the same directory as the application code. We instantiate an object from that class, then use the init variables. 32 | * Note the elegant use of *JSON -> dictionary -> kwargs*. This has been my biggest learning, and it came by a fluke: I just randomly thought that if \**kwargs can be used to denote an arbitrary dictionary of keyword arguments, it should apply in reverse as well. And it does! So first we transition from _JSON -> dictionary_ with `request.get_json()`, and then we transition from _dictionary -> kwargs_ with `place_order(**request_data)`. Smooth operator \*\*! 33 | 34 | 35 | # TODOs 36 | ## Functionlity: 37 | 1. Front end to show events (maybe use [Flask Turbo](https://blog.miguelgrinberg.com/post/dynamically-update-your-flask-web-pages-using-turbo-flask) by none other than Miguel Grinberg) 38 | 2. Order updates refreshes on front end (i.e. pipe order update socket.io to front end above) 39 | 3. Connectivity monitoring 40 | 41 | ## Deployment: 42 | 1. Gunicorn 43 | 2. nginx 44 | 3. Docker 45 | -------------------------------------------------------------------------------- /Option_Plus.py: -------------------------------------------------------------------------------- 1 | # Make sure to install latest library of Breeze before trying the below code. 2 | # shell command => pip install --upgrade breeze-connect 3 | 4 | 5 | #intialize keys 6 | api_key = "INSERT_YOUR_APP_KEY_HERE" 7 | api_secret = "INSERT_YOUR_SECRET_KEY_HERE" 8 | api_session = 'INSERT_YOUR_API_SESSION_HERE' 9 | 10 | #import libraries 11 | from breeze_connect import BreezeConnect 12 | 13 | # Initialize SDK 14 | api = BreezeConnect(api_key=api_key) 15 | 16 | # Generate Session 17 | api.generate_session(api_secret=api_secret, 18 | session_token=api_session) 19 | 20 | 21 | # Place Option Plus order. 22 | # Below code will place 2 orders - fresh order and cover SLTP order. 23 | # Cover SLTP order is the limit order which squares off your fresh order at limit price when the price hits stop loss trigger price. 24 | 25 | option_plus_order = api.place_order(stock_code="NIFTY", 26 | exchange_code="NFO", 27 | product="optionplus", 28 | action="buy", 29 | order_type="Limit", 30 | quantity="50", 31 | price="4", #limit price 32 | stoploss='10', # SLTP 33 | validity="day", 34 | disclosed_quantity="0", 35 | validity_date="2023-04-13T06:00:00.000Z", 36 | expiry_date="2023-04-13T06:00:00.000Z", 37 | right="put", 38 | strike_price="17750", 39 | order_type_fresh="Market", #Limit or Market 40 | order_rate_fresh="15", # fresh order price. 41 | user_remark="Test") 42 | 43 | print(option_plus_order) 44 | 45 | 46 | fresh_order_id = option_plus_order["Success"]["order_id"] 47 | detail = api.get_order_detail('NFO',fresh_order_id) 48 | cover_order_id = detail['Success'][0]['parent_order_id'] 49 | 50 | 51 | # To square off option plus order : 52 | # In Option Plus order, to square off your position - simply convert cover order from limit to market. 53 | 54 | modify_order = api.modify_order(order_id=cover_order_id, 55 | exchange_code="NFO", 56 | order_type="market", 57 | stoploss="0", 58 | quantity="50", 59 | price="0", 60 | validity="Day", 61 | disclosed_quantity="0", 62 | validity_date="2023-04-13T06:00:00.000Z") 63 | 64 | 65 | print(modify_order) 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Breeze-Python-Examples 2 | The official Python repo for sample codes that consume ICICIdirect Trading APIs (Breeze) to develop trading strategies. The strategies mentioned herein 3 | should be considered for learning and educational purposes only. 4 | 5 | 6 | -------------------------------------------------------------------------------- /get_started.py: -------------------------------------------------------------------------------- 1 | #intialize keys 2 | api_key = "INSERT_YOUR_APP_KEY_HERE" 3 | api_secret = "INSERT_YOUR_SECRET_KEY_HERE" 4 | api_session = 'INSERT_YOUR_API_SESSION_HERE' 5 | 6 | # Select Stock (USE SYMBOL AS SHOWN ON NSE) eg: RELIANCE 7 | STOCK = 'RELIANCE' 8 | 9 | # Import Libraries 10 | from breeze_connect import BreezeConnect 11 | 12 | # Setup my API keys 13 | api = BreezeConnect(api_key=api_key) 14 | api.generate_session(api_secret=api_secret,session_token=api_session) 15 | 16 | STOCK = api.get_names('NSE', STOCK)['isec_stock_code'] 17 | 18 | api.place_order(stock_code=STOCK, 19 | exchange_code="NSE",product="cash",action="buy", 20 | order_type="market",stoploss="",quantity="1",price="",validity="day") 21 | -------------------------------------------------------------------------------- /webinar/Analysing_historical_market_data_from_Breeze_API_using_Pandas_framework.py: -------------------------------------------------------------------------------- 1 | # code used in [Analysing historical market data from Breeze API using Pandas framework](https://www.youtube.com/watch?v=uZgAKrIMZBE) 2 | from breeze_connect import BreezeConnect 3 | from datetime import datetime 4 | from datetime import timedelta 5 | 6 | app_key = "" 7 | secret_key = "" 8 | session_token = "" 9 | 10 | # Initialize SDK 11 | breeze = BreezeConnect(api_key=app_key) 12 | 13 | # Generate Session 14 | breeze.generate_session(api_secret=secret_key, 15 | session_token=session_token) 16 | 17 | hdata = breeze.get_historical_data_v2(interval="1minute", 18 | from_date= "2022-08-15T07:00:00.000Z", 19 | to_date= "2022-08-17T07:00:00.000Z", 20 | stock_code="ICIBAN", 21 | exchange_code="NFO", 22 | product_type="futures", 23 | expiry_date="2022-08-25T07:00:00.000Z", 24 | right="others", 25 | strike_price="0") 26 | 27 | # SUPER UTLITY - POWER TOOL 28 | type(hdata) 29 | hdata.keys() 30 | type(hdata['Error']) 31 | type(hdata['Status']) 32 | type(hdata['Success']) 33 | 34 | hdata['Error']==None 35 | hdata['Status'] 36 | hdata['Success'] 37 | 38 | len(hdata['Success']) 39 | hdata['Success'][0] 40 | hdata['Success'][-1].keys() 41 | 42 | list_dict_hdata = hdata['Success'] 43 | 44 | # getting Breeze historical data in a loop 45 | dtm_from = datetime(2022, 1, 1, 0, 0, 0) 46 | dtm_to = datetime(2023, 1, 1, 0, 0, 0) 47 | 48 | # set up some helping variables 49 | tdelta_1day = timedelta(days=1) # note that this can be cahnged to 7 if you want only a particular weekday, like expiries. will require modifications below 50 | tdelta_days = dtm_to - dtm_from + tdelta_1day 51 | list_dtm_dates = [dtm_from] 52 | 53 | # for loop method 54 | for i in range(tdelta_days.days): 55 | list_dtm_dates.append(list_dtm_dates[-1] + tdelta_1day) 56 | 57 | # introducing list comprehension in python 58 | list_dtm_dates = [] 59 | list_dtm_dates = [dtm_from + tdelta_1day*i for i in range(0, tdelta_days.days)] 60 | 61 | # removing weekends 62 | list_dtm_dates = [x for x in list_dtm_dates if x.weekday()<5] # this step can also be used to isolate an expiry date 63 | 64 | list_dtm_dates[0] 65 | list_dtm_dates[-1] 66 | len(list_dtm_dates) 67 | 68 | # finding out how many days to request at a time given a candle size - note that constants are denoted by ALL CAPS variable names to differentiate from common variables that can be changed by the program itself 69 | import math 70 | int_candle_size = 5 # we want 5 minute candles 71 | CANDLES_IN_A_DAY = 375 # NSE runs from 9:15 to 15:30, which means there are 45 + 5*60 + 30 = 375 minutes in 1 trading session on NSE 72 | MAX_LINES = 1000 # Max number of historical candles that Breeze can send 73 | 74 | int_max_days = math.floor(MAX_LINES/(CANDLES_IN_A_DAY/int_candle_size)) 75 | len(list_dtm_dates)/int_max_days 76 | 77 | list_data = [] 78 | 79 | date_start = list_dtm_dates[0] 80 | for i in range(int(len(list_dtm_dates)/int_max_days)): 81 | print(i) 82 | try: 83 | date_end = list_dtm_dates[int_max_days*(i+1)] 84 | except: 85 | date_end = list_dtm_dates[-1] + tdelta_1day 86 | print(date_start) 87 | print(date_end) 88 | list_dict_hdata = breeze.get_historical_data_v2(interval=str(int_candle_size)+"minute", 89 | from_date= date_start.isoformat(), 90 | to_date= date_end.isoformat(), 91 | stock_code="ICIBAN", 92 | exchange_code="NSE", 93 | product_type="cash" 94 | )["Success"] 95 | list_data = list_data + list_dict_hdata 96 | try: 97 | date_start = list_dtm_dates[list_dtm_dates.index(date_end)+1] 98 | except: 99 | pass 100 | 101 | # LISTS 102 | a = [1,2,3,4,5,6] 103 | b = ['a', 'b', 'c'] 104 | a+b 105 | b+a 106 | a.append(b) 107 | 108 | # DICTIONARIES 109 | a = {'ltp': 100, 'ltq': 20, 'oi': 10000} 110 | a.keys() 111 | a.values() 112 | 113 | a['ltp'] 114 | a.get('ltq') 115 | 116 | a('close') 117 | 118 | if a.get('close')==None: 119 | a['close'] = 200 120 | 121 | # pip install pandas 122 | import pandas as pd 123 | 124 | # basic time series in Pandas - with explanation of descriptive, diagnostic, predictive, prescriptive analytics 125 | a = {'a': 1, 'b':2, 'c': 3} 126 | series_a = pd.Series(a.values(), a.keys()) 127 | series_a['a'] 128 | series_a.get('a') 129 | series_a.get(0) 130 | series_a.iloc[0] 131 | 132 | # apply SMA in Pandas 133 | df_hdata = pd.DataFrame(list_data) 134 | df_hdata.shape 135 | df_hdata.head() 136 | df_hdata.head(10) 137 | df_hdata.tail() 138 | df_hdata.tail(10) 139 | df_hdata['datetime'][0] 140 | df_hdata['datetime'][17339] 141 | df_hdata.columns 142 | df_hdata.columns[0] 143 | df_hdata.columns[-1] 144 | 145 | # POWERTOOL ! export data to CSV or Excel format 146 | df_hdata.to_csv('/home/builder/Downloads/ICICIBANK_HistoricalData.csv') 147 | df_hdata.to_excel('/home/builder/Downloads/ICICIBANK_.xlsx') 148 | 149 | type(df_hdata['close']) 150 | dir(df_hdata['close']) 151 | 152 | 153 | df_hdata['pandas_SMA_12'] = df_hdata['close'].rolling(window=12).mean() 154 | df_hdata.head(13) 155 | 156 | # visualize 157 | import matplotlib.pyplot as plot 158 | ts = pd.Series(data=df_hdata['pandas_SMA_12'], index=df_hdata['pandas_SMA_12']) 159 | ts.plot() 160 | plot.show() 161 | 162 | df_hdata.plot(x='pandas_SMA_12', y='close') 163 | plot.show() 164 | df_hdata['pandas_SMA_12'].drop() 165 | 166 | # backtest Moving Average Crossover in Pandas 167 | # NEXT SESSION 168 | -------------------------------------------------------------------------------- /webinar/Convert_JsonOutput_to_DataFrame.py: -------------------------------------------------------------------------------- 1 | 2 | #import library 3 | from breeze_connect import BreezeConnect 4 | 5 | #Initiliaze SDK 6 | breeze = BreezeConnect(api_key="xxxxx") 7 | 8 | #Generate Session 9 | breeze.generate_session(api_secret="xxxxxx",session_token="xxxxx") 10 | 11 | 12 | #Use get_historical_data_v2 SDK to fetch historical data 13 | df = breeze.get_historical_data_v2(interval="1second", 14 | from_date= "2023-08-08T:40:00.000Z", 15 | to_date= "2023-08-08T12:41:00.000Z", 16 | stock_code="NIFTY", 17 | exchange_code="NFO", 18 | product_type="options", 19 | expiry_date="2023-08-10T07:00:00.000Z", 20 | right="put", 21 | strike_price="19550") 22 | 23 | #Parse data to dataframe 24 | df = pd.DataFrame(df["Success"]) 25 | 26 | print(df) -------------------------------------------------------------------------------- /webinar/Equity_data_to_dataframe.py: -------------------------------------------------------------------------------- 1 | # Make sure to install latest library of Breeze before trying the below code. 2 | # shell command => pip install --upgrade breeze-connect 3 | 4 | 5 | #intialize keys 6 | api_key = "INSERT_YOUR_APP_KEY_HERE" 7 | api_secret = "INSERT_YOUR_SECRET_KEY_HERE" 8 | api_session = 'INSERT_YOUR_API_SESSION_HERE' 9 | 10 | #import libraries 11 | from breeze_connect import BreezeConnect 12 | 13 | # Initialize SDK 14 | api = BreezeConnect(api_key=api_key) 15 | 16 | # Generate Session 17 | api.generate_session(api_secret=api_secret, 18 | session_token=api_session) 19 | 20 | 21 | # Fetch Data using historical data API v2 22 | data = api.get_historical_data_v2(interval="1minute", 23 | from_date= "2022-08-15T07:00:00.000Z", 24 | to_date= "2022-08-17T07:00:00.000Z", 25 | stock_code="ITC", 26 | exchange_code="NSE", 27 | product_type="cash") 28 | 29 | 30 | # Convert data (API JSON response) into a table / dataframe using pandas library 31 | import pandas as pd 32 | df = pd.DataFrame(data['Success']) 33 | 34 | print(df) 35 | -------------------------------------------------------------------------------- /webinar/How_to_save_historical_data_in_dataframe.py: -------------------------------------------------------------------------------- 1 | # code used in [How to get started with Breeze API](https://www.youtube.com/watch?v=GtqrSDpj0NE) 2 | from breeze_connect import BreezeConnect 3 | import pandas as pd 4 | 5 | app_key = "" 6 | secret_key = "" 7 | session_token = "" 8 | 9 | # Initialize SDK 10 | breeze = BreezeConnect(api_key=app_key) 11 | 12 | # Generate Session 13 | breeze.generate_session(api_secret=secret_key, 14 | session_token=session_token) 15 | 16 | 17 | hdata = breeze.get_historical_data_v2(interval="1minute", 18 | from_date= "2022-08-15T07:00:00.000Z", 19 | to_date= "2022-08-17T07:00:00.000Z", 20 | stock_code="ICIBAN", 21 | exchange_code="NFO", 22 | product_type="futures", 23 | expiry_date="2022-08-25T07:00:00.000Z", 24 | right="others", 25 | strike_price="0") 26 | 27 | df_hdata = pd.DataFrame(hdata['Success']) 28 | -------------------------------------------------------------------------------- /webinar/MTF_Place_order_code: -------------------------------------------------------------------------------- 1 | breeze.place_order(stock_code="SAIL", 2 | exchange_code="NSE", 3 | product="mtf", 4 | action="buy", 5 | order_type="limit", 6 | stoploss="", 7 | quantity="1", 8 | price="110", 9 | validity="day" 10 | ) 11 | 12 | Output: 13 | {'Success': {'order_id': '20254444444111', 14 | 'message': 'Equity MTF Order placed successfully through RI reference no 20250227N300012345', 15 | 'user_remark': None}, 16 | 'Status': 200, 17 | 'Error': None} 18 | -------------------------------------------------------------------------------- /webinar/Multiples_Stock_token_WebsocketSubscription.py: -------------------------------------------------------------------------------- 1 | import time 2 | from breeze_connect import BreezeConnect 3 | from datetime import datetime, timedelta 4 | key_api = "" 5 | key_secret = "" 6 | key_session = "" 7 | breeze = BreezeConnect(api_key=key_api) 8 | breeze.generate_session(api_secret=key_secret, session_token=key_session) 9 | 10 | # Connect to websocket(it will connect to tick-by-tick data server) 11 | breeze.ws_connect() 12 | 13 | # Callback to receive ticks. 14 | def on_ticks(ticks): 15 | print("Ticks: {}".format(ticks)) 16 | 17 | # Assign the callbacks. 18 | breeze.on_ticks = on_ticks 19 | 20 | 21 | # Sample Code for Subscribing Live Feeds for Multiple Stocks: 22 | 23 | breeze.get_names(exchange_code = 'NSE',stock_code = 'TATASTEEL')["isec_token_level1"] 24 | 25 | # Output: "4.1!3499" 26 | 27 | breeze.get_names(exchange_code = 'NSE',stock_code = 'RELIANCE')["isec_token_level1"] 28 | 29 | # Output : "4.1!2885" 30 | 31 | breeze.subscribe_feeds(stock_token=['4.1!3499','4.1!2885']) 32 | 33 | 34 | # Stock token can be find out from below file also. 35 | 36 | # https://traderweb.icicidirect.com/Content/File/txtFile/ScripFile/StockScriptNew.csv 37 | 38 | -------------------------------------------------------------------------------- /webinar/ORB_webinar_file.txt: -------------------------------------------------------------------------------- 1 | ''' 2 | ORB stands for Opening Range Breakout. 3 | 4 | In simple terms, it's a trading strategy that focuses on the price range formed in the first part of the trading session—often the first 15 or 30 minutes. 5 | Traders look at the high and lowe prices during that initial time period, and use them as key levels to decide when to enter a trade. 6 | 7 | Here's how it works in a straightforward way: 8 | 9 | Opening Range: This is the high and low price of a stock during the first 15 or 30 minutes after the market opens. 10 | 11 | Breakout: If the stock price moves above the high of the opening range, it's called a breakout to the upside. 12 | Traders might decide to buy because the price is breaking out of the range and could keep going higher. 13 | 14 | Similarly, If the stock price drops below the low of the opening range, it's called a breakout to the downside (or breakdown). 15 | Traders might decide to sell or short the stock because the price could keep going lower. 16 | 17 | Why use ORB? 18 | Momentum: The idea is that the stock might continue moving in the direction of the breakout (up or down) because of strong market momentum. 19 | Clarity: It provides clear levels (the high and low of the opening range) for traders to make decisions. 20 | ''' 21 | 22 | #Libraries needed to be installed, Some are in built in python and some you need to install 23 | #To install a missing library just follow this command : pip install library_name 24 | import pandas as pd 25 | from datetime import datetime, timedelta 26 | import pytz 27 | import json 28 | import os 29 | import time 30 | import urllib 31 | import schedule 32 | import shutil 33 | import os 34 | import csv 35 | from breeze_connect import BreezeConnect 36 | 37 | #inputs to be given by the user 38 | breeze = BreezeConnect(api_key="enter your API Key") 39 | breeze.generate_session(api_secret="enter your secret key", 40 | session_token="enter your session token") 41 | first_order = None 42 | first_orders = {} 43 | completed_orders_stocks = set() 44 | # Initialize dictionaries to track order counts 45 | order_counts = {} 46 | # Define MAX_ORDERS_PER_STOCK. If 2 it will place a buy and a sell order only 47 | MAX_ORDERS_PER_STOCK = 2 48 | # Declare target and stop-loss percentages manually 49 | buy_target_percentage = 1.005 # Example: 0.5% target for buy order 50 | buy_stoploss_percentage = 0.99 # Example: 1% stop-loss for buy order 51 | sell_target_percentage =0.995 # Example: 0.5% target for sell order 52 | sell_stoploss_percentage = 1.01 # Example: 1% stop-loss for sell order 53 | 54 | 55 | # Define the consistent column structure 56 | COLUMNS = ['symbol', 'open', 'last', 'high', 'low', 'ltt', 'close', 'exchange', 'stock_name'] 57 | 58 | def save_tick_to_file(symbol, tick): 59 | filename = f"{symbol}.csv" 60 | temp_filename = f"{symbol}.csv.tmp" # Temporary file for atomic write 61 | backup_filename = f"{symbol}.csv.bak" # Backup in case of corruption 62 | 63 | try: 64 | # Create a DataFrame with the fixed column structure 65 | tick_df = pd.DataFrame([{ 66 | 'symbol': tick.get('symbol', ''), 67 | 'open': tick.get('open', 0), 68 | 'last': tick.get('last', 0), 69 | 'high': tick.get('high', 0), 70 | 'low': tick.get('low', 0), 71 | 'ltt': tick.get('ltt', ''), 72 | 'close': tick.get('close', 0), 73 | 'exchange': tick.get('exchange', ''), 74 | 'stock_name': tick.get('stock_name', '') 75 | }], columns=COLUMNS) 76 | 77 | # Check if the file exists and is valid 78 | if os.path.exists(filename) and not is_valid_csv(filename): 79 | log_message(f"CSV file {filename} is corrupted, backing up and creating a new one.") 80 | shutil.move(filename, backup_filename) # Rename corrupted file to .bak 81 | 82 | # Write data to a temporary file 83 | if os.path.exists(filename): 84 | tick_df.to_csv(temp_filename, mode='a', header=False, index=False) 85 | else: 86 | tick_df.to_csv(temp_filename, mode='w', header=True, index=False) 87 | 88 | # Atomically replace the original file with the new one 89 | shutil.move(temp_filename, filename) 90 | 91 | log_message(f"Tick saved for {symbol}: {tick.get('symbol', '')}, Last: {tick.get('last', 'N/A')}, LTT: {tick.get('ltt', 'N/A')}") 92 | 93 | except Exception as e: 94 | log_message(f"Error saving tick for {symbol}: {e}") 95 | # Remove temp file in case of failure 96 | if os.path.exists(temp_filename): 97 | os.remove(temp_filename) 98 | 99 | def is_valid_csv(filename): 100 | """ 101 | Check if the CSV file has valid content and can be read. 102 | Returns True if valid, False if corrupted. 103 | """ 104 | try: 105 | with open(filename, 'r') as f: 106 | reader = csv.reader(f) 107 | headers = next(reader, None) 108 | # Check if headers are present and match expected columns 109 | if headers is None or len(headers) != len(COLUMNS): 110 | log_message(f"CSV file {filename} is corrupted or missing columns.") 111 | return False 112 | return True 113 | except Exception as e: 114 | log_message(f"Error checking validity of {filename}: {e}") 115 | return False 116 | 117 | 118 | def get_latest_tick(symbol, retries=3): 119 | filename = f"{symbol}.csv" 120 | attempts = 0 121 | 122 | while attempts < retries: 123 | try: 124 | # Check if file exists and is valid 125 | if not os.path.exists(filename): 126 | log_message(f"No file found for {symbol}") 127 | return None 128 | 129 | if os.path.getsize(filename) == 0 or not is_valid_csv(filename): 130 | log_message(f"File {symbol}.csv is invalid or empty, skipping.") 131 | return None 132 | 133 | # Read the CSV file, skipping bad lines 134 | df = pd.read_csv(filename, on_bad_lines='skip') 135 | if df.empty: 136 | log_message(f"No data found in {symbol}.csv") 137 | return None 138 | 139 | # Ensure 'ltt' column is present 140 | if 'ltt' not in df.columns: 141 | log_message(f"'ltt' column missing in {symbol}.csv") 142 | return None 143 | 144 | # Convert 'ltt' to datetime format for proper sorting 145 | df['ltt'] = pd.to_datetime(df['ltt'], errors='coerce') 146 | 147 | # Get the row with the latest 'ltt' timestamp 148 | latest_tick_row = df.loc[df['ltt'].idxmax()] 149 | 150 | return latest_tick_row.to_dict() 151 | 152 | except Exception as e: 153 | log_message(f"Error getting latest tick for {symbol}: {e}, Attempt {attempts+1}/{retries}") 154 | attempts += 1 155 | 156 | if attempts == retries: 157 | log_message(f"Failed to get latest tick for {symbol} after {retries} retries.") 158 | return None 159 | 160 | def first_order_placed(stock_token): 161 | return first_orders.get(stock_token) is not None 162 | def set_first_order(stock_token, action, price): 163 | first_orders[stock_token] = (action, price) 164 | def initialize_order_count(symbol): 165 | order_counts[symbol] = { 166 | 'buy_count': 0, 167 | 'sell_count': 0, 168 | 'total_orders': 0 169 | } 170 | 171 | def check_order_limits(symbol): 172 | return order_counts[symbol]['total_orders'] < MAX_ORDERS_PER_STOCK 173 | 174 | def update_order_counts(symbol, action): 175 | if action == 'buy': 176 | order_counts[symbol]['buy_count'] += 1 177 | elif action == 'sell': 178 | order_counts[symbol]['sell_count'] += 1 179 | order_counts[symbol]['total_orders'] += 1 180 | 181 | def check_ticks(): 182 | global first_order 183 | log_message("Checking ticks...") 184 | 185 | current_time = datetime.now(pytz.timezone("Asia/Kolkata")).time() 186 | if current_time >= datetime.strptime("15:00:00", "%H:%M:%S").time(): 187 | log_message("Order placing is disabled after 3:00 PM.") 188 | return 189 | 190 | for symbol in stock_high_low.keys(): 191 | if symbol in completed_orders_stocks: 192 | continue 193 | 194 | # Initialize order count if not done yet 195 | if symbol not in order_counts: 196 | initialize_order_count(symbol) 197 | 198 | # Check if order limits are exceeded 199 | if not check_order_limits(symbol): 200 | log_message(f"Order limit reached for {symbol}, skipping further orders.") 201 | completed_orders_stocks.add(symbol) 202 | continue 203 | 204 | latest_tick = get_latest_tick(symbol) 205 | if latest_tick is None: 206 | log_message(f"No valid tick for {symbol}, skipping this iteration.") 207 | continue # Ignore this symbol and move to the next one 208 | if latest_tick: 209 | last_price = latest_tick['last'] # Assuming 'ltp' is the last traded price 210 | high = stock_high_low[symbol]['high'] 211 | low = stock_high_low[symbol]['low'] 212 | 213 | # Check if first order has been placed 214 | if not first_order_placed(symbol): 215 | # Decide based on the price crossing high or low 216 | if last_price > high and order_counts[symbol]['total_orders'] % 2 == 0: 217 | # Place buy order 218 | order_params = create_order_params(latest_tick, action="buy", price="0", stoploss_price="0") 219 | log_message(f"Placing first buy order: {order_params}") 220 | order_id = place_order(order_params) 221 | if order_id: 222 | update_order_counts(symbol, "buy") 223 | set_first_order(symbol, "buy", last_price) 224 | 225 | elif last_price < low and order_counts[symbol]['total_orders'] % 2 == 0: 226 | # Place sell order 227 | order_params = create_order_params(latest_tick, action="sell", price="0", stoploss_price="0") 228 | log_message(f"Placing first sell order: {order_params}") 229 | order_id = place_order(order_params) 230 | if order_id: 231 | update_order_counts(symbol, "sell") 232 | set_first_order(symbol, "sell", last_price) 233 | 234 | else: 235 | # First order already placed 236 | first_order_action, first_order_price = first_orders[symbol] 237 | 238 | if first_order_action == "buy" and (last_price > first_order_price * buy_target_percentage or last_price < first_order_price * buy_stoploss_percentage) and order_counts[symbol]['total_orders'] % 2 != 0: 239 | # Place sell order after buy 240 | order_params = create_order_params(latest_tick, action="sell", price="0", stoploss_price=0) 241 | log_message(f"Placing sell order after buy: {order_params}") 242 | order_id = place_order(order_params) 243 | if order_id: 244 | update_order_counts(symbol, "sell") 245 | first_orders.pop(symbol, None) 246 | 247 | elif first_order_action == "sell" and (last_price < first_order_price * sell_target_percentage or last_price > first_order_price * sell_stoploss_percentage) and order_counts[symbol]['total_orders'] % 2 != 0: 248 | # Place buy order after sell 249 | order_params = create_order_params(latest_tick, action="buy", price="0", stoploss_price=0) 250 | log_message(f"Placing buy order after sell: {order_params}") 251 | order_id = place_order(order_params) 252 | if order_id: 253 | update_order_counts(symbol, "buy") 254 | first_orders.pop(symbol, None) 255 | 256 | if first_order_placed(symbol) and len(first_orders) == 0: 257 | completed_orders_stocks.add(symbol) 258 | 259 | # Now integrate this function into your main loop as before. 260 | 261 | def create_order_params(tick, action, price, stoploss_price): 262 | stock_token = tick['symbol'] 263 | stock_code = None 264 | for name, codes in stock_isec_codes.items(): 265 | if codes['stock_token'] == stock_token: 266 | stock_code = codes['isec_stock_code'] 267 | break 268 | if stock_code is None: 269 | log_message(f"Error: stock_code not found for {stock_token}") 270 | return None 271 | return { 272 | "stock_code": stock_code, 273 | "exchange_code": "NSE", 274 | "product": "margin", 275 | "action": action, 276 | "order_type": "market", 277 | "stoploss": str(stoploss_price), 278 | "quantity": "1", #change if you want to change 279 | "price": price, 280 | "validity": "day", 281 | "user_remark": "strategyorder" 282 | } 283 | breeze.ws_connect() 284 | def save_tick_to_file(symbol, tick): 285 | filename = f"{symbol}.csv" 286 | try: 287 | # Check and extract fields, ensuring they are not lists 288 | tick_df = pd.DataFrame([{ 289 | 'symbol': tick.get('symbol', ''), 290 | 'open': tick.get('open', [None])[0] if isinstance(tick.get('open'), list) else tick.get('open'), 291 | 'last': tick.get('last', [None])[0] if isinstance(tick.get('last'), list) else tick.get('last'), 292 | 'high': tick.get('high', [None])[0] if isinstance(tick.get('high'), list) else tick.get('high'), 293 | 'low': tick.get('low', [None])[0] if isinstance(tick.get('low'), list) else tick.get('low'), 294 | 'ltt': tick.get('ltt', [None])[0] if isinstance(tick.get('ltt'), list) else tick.get('ltt'), 295 | 'close': tick.get('close', [None])[0] if isinstance(tick.get('close'), list) else tick.get('close'), 296 | 'exchange': tick.get('exchange', ''), 297 | 'stock_name': tick.get('stock_name', '') 298 | }]) 299 | 300 | if os.path.exists(filename): 301 | # Append to the existing CSV file 302 | existing_df = pd.read_csv(filename) 303 | df = pd.concat([existing_df, tick_df], ignore_index=True, sort=False) 304 | else: 305 | # Create a new CSV file if it doesn't exist 306 | df = tick_df 307 | 308 | df.to_csv(filename, index=False) 309 | log_message(f"Tick saved for {symbol}: {tick.get('symbol')}, LTP: {tick.get('last')}, LTT: {tick.get('ltt')}") 310 | 311 | except Exception as e: 312 | log_message(f"Error saving tick: {e}") 313 | 314 | 315 | 316 | def log_tick_information(tick): 317 | """Log only essential information about the tick.""" 318 | try: 319 | symbol = tick.get('symbol') 320 | last_price = tick.get('last') 321 | ltt = tick.get('ltt') 322 | 323 | log_message(f"Tick received - Symbol: {symbol}, LTP: {last_price}, LTT: {ltt}") 324 | 325 | except Exception as e: 326 | log_message(f"Error logging tick information: {e}") 327 | 328 | 329 | def on_ticks(ticks): 330 | log_message("Received ticks") 331 | try: 332 | if isinstance(ticks, dict): 333 | ticks_list = [ticks] 334 | elif isinstance(ticks, list): 335 | ticks_list = ticks 336 | else: 337 | log_message(f"Error: Ticks should be a list or a dictionary, but received: {type(ticks)}") 338 | return 339 | 340 | for tick in ticks_list: 341 | if not isinstance(tick, dict): 342 | log_message(f"Error: Tick is not a dictionary") 343 | continue 344 | 345 | symbol = tick.get('symbol') 346 | if symbol: 347 | log_tick_information(tick) # Log only necessary fields 348 | save_tick_to_file(symbol, tick) # Save filtered columns 349 | else: 350 | log_message("Error: Symbol missing in tick data") 351 | 352 | except Exception as e: 353 | log_message(f"Error in on_ticks: {e}") 354 | 355 | def get_stock_names(filename): 356 | log_message("Getting stock names...") 357 | try: 358 | # filename = 'Stock_List_Nifty50.csv' 359 | df = pd.read_csv(filename) 360 | stock_names = df.iloc[:, 0].tolist() 361 | log_message(f"Extracted stock names: {stock_names}") 362 | 363 | stock_isec_codes = {} 364 | for stock_name in stock_names: 365 | response = breeze.get_names(exchange_code='NSE', stock_code=stock_name) 366 | if isinstance(response, dict) and 'isec_stock_code' in response and 'isec_token_level1' in response: 367 | stock_isec_codes[stock_name] = { 368 | 'isec_stock_code': response['isec_stock_code'], 369 | 'stock_token': response['isec_token_level1'] 370 | } 371 | else: 372 | log_message(f"Error: Unexpected response format for {stock_name}") 373 | return stock_isec_codes 374 | except Exception as e: 375 | log_message(f"Error getting stock names: {e}") 376 | return {} 377 | def get_high_low_for_stocks(stock_isec_codes): 378 | log_message("Getting high and low values for stocks...") 379 | try: 380 | today = datetime.now(pytz.timezone("Asia/Kolkata")) 381 | if datetime.now().time() >= datetime.strptime("09:30:00", "%H:%M:%S").time() and datetime.now().time() < datetime.strptime("09:45:00", "%H:%M:%S").time(): 382 | from_date = today.replace(hour=9, minute=15, second=0, microsecond=0) 383 | to_date = today.replace(hour=9, minute=30, second=0, microsecond=0) 384 | else: 385 | from_date = today.replace(hour=9, minute=15, second=0, microsecond=0) 386 | to_date = today.replace(hour=9, minute=45, second=0, microsecond=0) 387 | from_date_str = from_date.strftime("%Y-%m-%dT%H:%M:%S.000Z") 388 | to_date_str = to_date.strftime("%Y-%m-%dT%H:%M:%S.000Z") 389 | stock_high_low = {} 390 | for stock_name, codes in stock_isec_codes.items(): 391 | response = breeze.get_historical_data_v2( 392 | stock_code=codes['isec_stock_code'], 393 | interval="5minute", 394 | from_date=from_date_str, 395 | to_date=to_date_str, 396 | exchange_code="NSE", 397 | product_type="cash" 398 | ) 399 | if isinstance(response, dict) and 'Success' in response: 400 | highs = [item['high'] for item in response['Success']] 401 | lows = [item['low'] for item in response['Success']] 402 | highest = max(highs) 403 | lowest = min(lows) 404 | stock_token = codes['stock_token'] 405 | stock_high_low[stock_token] = {'high': highest, 'low': lowest} 406 | log_message(f"Token {stock_token}: High = {highest}, Low = {lowest}") 407 | else: 408 | log_message(f"No data found for {stock_name}.") 409 | return stock_high_low 410 | except Exception as e: 411 | log_message(f"Error getting high and low values: {e}") 412 | return {} 413 | def get_isec_tokens(stock_isec_codes): 414 | log_message("Getting isec_tokens for WebSocket subscription...") 415 | try: 416 | isec_tokens = [] 417 | for stock_name, codes in stock_isec_codes.items(): 418 | isec_tokens.append(codes['stock_token']) 419 | return isec_tokens 420 | except Exception as e: 421 | log_message(f"Error getting isec_tokens: {e}") 422 | return [] 423 | def place_order(order_params): 424 | try: 425 | response = breeze.place_order(**order_params) 426 | if response.get('Status') == 200: 427 | order_id = response['Success'].get('order_id') 428 | log_message(f"Order placed: {order_params}, Order ID: {order_id}") 429 | return order_id 430 | else: 431 | log_message(f"Failed to place order: {response.get('Error')}") 432 | return None 433 | except Exception as e: 434 | log_message(f"Error placing order: {e}") 435 | return None 436 | def verify_orders(): 437 | global buy_order_count, sell_order_count 438 | today_date = datetime.now().strftime("%Y-%m-%d") 439 | from_date = f"{today_date}T07:00:00.000Z" 440 | to_date = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.000Z") 441 | try: 442 | order_response = breeze.get_order_list( 443 | exchange_code="NSE", 444 | from_date=from_date, 445 | to_date=to_date 446 | ) 447 | orders = order_response.get('Success', []) 448 | if not orders: # Check if orders list is empty or None 449 | log_message("No strategy orders found in the verification step.") 450 | return 0, 0 451 | buy_order_count = 0 452 | sell_order_count = 0 453 | for order in orders: 454 | if order.get('user_remark') == 'strategyorder': 455 | log_message(f"Order verified: {order}") 456 | if order.get('action', '').lower() == 'buy': 457 | buy_order_count += 1 458 | elif order.get('action', '').lower() == 'sell': 459 | sell_order_count += 1 460 | return buy_order_count, sell_order_count 461 | except Exception as e: 462 | log_message(f"Error verifying orders: {e}") 463 | return 0, 0 464 | 465 | def run_check_ticks(): 466 | check_ticks() 467 | 468 | def log_message(message): 469 | """Log messages to a file.""" 470 | log_filename = "trade_log.txt" 471 | with open(log_filename, 'a') as log_file: 472 | log_file.write(f"{datetime.now()}: {message}\n") 473 | print(message) 474 | 475 | def main(): 476 | try: 477 | log_message("Starting main function") 478 | global stock_isec_codes 479 | global stock_high_low 480 | global order_ids # Define order_ids as a global variable 481 | global sell_order_count, buy_order_count # Define sell_order_count and buy_order_count as global variables 482 | 483 | # Initialize variables 484 | order_ids = [] 485 | sell_order_count = 0 486 | buy_order_count = 0 487 | 488 | filename = "Stock_List_Nifty50.csv" 489 | stock_isec_codes = get_stock_names(filename) 490 | 491 | if not stock_isec_codes: 492 | log_message("Error: No stock names found.") 493 | return 494 | 495 | isec_tokens = get_isec_tokens(stock_isec_codes) 496 | 497 | if not isec_tokens: 498 | log_message("Error: No isec_tokens found for WebSocket subscription.") 499 | return 500 | 501 | breeze.on_ticks = on_ticks 502 | breeze.subscribe_feeds(isec_tokens) 503 | 504 | # Waiting for 9:30 AM 505 | while True: 506 | current_time = datetime.now(pytz.timezone("Asia/Kolkata")).time() 507 | if current_time >= datetime.strptime("09:30:00", "%H:%M:%S").time(): 508 | break 509 | else: 510 | log_message("Waiting for 9:30 AM") 511 | time.sleep(10) # Wait until 9:30 AM 512 | 513 | # Fetch high/low values after 9:30 AM 514 | stock_high_low = get_high_low_for_stocks(stock_isec_codes) 515 | if not stock_high_low: 516 | log_message("Error: No high/low values found.") 517 | return 518 | 519 | # Main loop: Call check_ticks() every minute after 9:30 AM 520 | while True: 521 | current_time = datetime.now(pytz.timezone("Asia/Kolkata")).time() 522 | if current_time >= datetime.strptime("15:00:00", "%H:%M:%S").time(): 523 | log_message("Trading hours are over. No further orders will be placed after 3:00 PM.") 524 | breeze.ws_disconnect() 525 | break 526 | check_ticks() 527 | log_message("check_ticks called") 528 | time.sleep(30) 529 | 530 | 531 | except Exception as e: 532 | log_message(f"Error in main execution: {e}") 533 | 534 | if __name__ == "__main__": 535 | main() 536 | -------------------------------------------------------------------------------- /webinar/Option_Greeks_Calculation_using_OptionChain.py: -------------------------------------------------------------------------------- 1 | from breeze_connect import BreezeConnect 2 | import urllib 3 | import warnings 4 | warnings.filterwarnings('ignore') 5 | import pandas as pd 6 | from py_vollib.black_scholes import black_scholes 7 | from py_vollib.black_scholes.greeks.numerical import delta, gamma, theta, vega, rho 8 | from scipy.optimize import brentq 9 | import numpy as np 10 | from datetime import datetime 11 | 12 | #Connecting to Breeze 13 | breeze = BreezeConnect(api_key=str(app_key)) 14 | 15 | print("https://api.icicidirect.com/apiuser/login?api_key="+urllib.parse.quote_plus(str(app_key))) 16 | 17 | breeze.generate_session(api_secret=str(secret_key),session_token=str(session_key)) 18 | 19 | #Finding price of an option 20 | 21 | #call 22 | 23 | S = 24117 # Underlying asset price 24 | K_call = 24150 # Option strike price 25 | t = 7/365 # Time to expiration in years 26 | r = 0.10 # Risk-free interest rate 27 | sigma_call = 0.13 # Volatility 28 | flag_call = 'c' # 'c' for Call, 'p' for Put 29 | 30 | # Option price 31 | option_price_call = black_scholes(flag_call, S, K_call, t, r, sigma_call) 32 | print("Option Price_Call:", option_price_call) 33 | 34 | #Put 35 | 36 | S = 24117 # Underlying asset price 37 | K_put = 24150 # Option strike price 38 | t = 7/365 # Time to expiration in years 39 | r = 0.10 # Risk-free interest rate 40 | sigma_put = 0.17 # Volatility 41 | flag_put = 'p' # 'c' for Call, 'p' for Put 42 | 43 | # Option price 44 | option_price_put = black_scholes(flag_put, S, K_put, t, r, sigma_put) 45 | print("Option Price_Put:", option_price_put) 46 | 47 | #Finding Greeks of an option 48 | 49 | #Put 50 | 51 | # Delta 52 | delta_value_put = delta(flag_put, S, K_put, t, r, sigma_put) 53 | print("Delta_put:", delta_value_put) 54 | 55 | # Gamma 56 | gamma_value_put = gamma(flag_put, S, K_put, t, r, sigma_put) 57 | print("Gamma_put:", gamma_value_put) 58 | 59 | # Theta 60 | theta_value_put = theta(flag_put, S, K_put, t, r, sigma_put) 61 | print("Theta_put:", theta_value_put) 62 | 63 | # Vega 64 | vega_value_put = vega(flag_put, S, K_put, t, r, sigma_put) 65 | print("Vega_put:", vega_value_put) 66 | 67 | # Rho 68 | rho_value_put = rho(flag_put, S, K_put, t, r, sigma_put) 69 | print("Rho_put:", rho_value_put) 70 | 71 | #call 72 | 73 | # Delta 74 | delta_value_call = delta(flag_call, S, K_call, t, r, sigma_call) 75 | print("Delta_call:", delta_value_call) 76 | 77 | # Gamma 78 | gamma_value_call =gamma(flag_call, S, K_call, t, r, sigma_call) 79 | print("Gamma_call:", gamma_value_call) 80 | 81 | # Theta 82 | theta_value_call = theta(flag_call, S, K_call, t, r, sigma_call) 83 | print("Theta_call:", theta_value_call) 84 | 85 | # Vega 86 | vega_value_call = vega(flag_call, S, K_call, t, r, sigma_call) 87 | print("Vega_call:", vega_value_call) 88 | 89 | # Rho 90 | rho_value_call = rho(flag_call, S, K_call, t, r, sigma_call) 91 | print("Rho_call:", rho_value_call) 92 | 93 | # Calculating Option Greeks in Option Chain 94 | 95 | 96 | #find ATM strike Price 97 | Quotes = breeze.get_quotes(stock_code="NIFTY", 98 | exchange_code="NSE", 99 | expiry_date="", 100 | product_type="cash", 101 | right="", 102 | strike_price="") 103 | 104 | Spot = Quotes["Success"][0]["ltp"] 105 | ATM = round((Quotes["Success"][0]["ltp"])/50)*50 106 | print(ATM) 107 | 108 | 109 | # Simulate the data retrieval from breeze for Call 110 | df = breeze.get_option_chain_quotes(stock_code="NIFTY", 111 | exchange_code="NFO", 112 | product_type="options", 113 | expiry_date="2024-08-14T06:00:00.000Z", 114 | right="call")["Success"] 115 | 116 | # Convert to DataFrame 117 | df = pd.DataFrame(df) 118 | 119 | # Convert strike_price to float 120 | df['strike_price'] = df['strike_price'].astype(float) 121 | 122 | # Define target strike and range parameters 123 | target_strike = ATM 124 | strike_increment = 50 125 | range_size = 5 126 | 127 | # Define the range for strike prices 128 | lower_bound = target_strike - range_size * strike_increment 129 | upper_bound = target_strike + range_size * strike_increment 130 | 131 | # Filter the rows where the strike price is within the range and in increments of 50 132 | filtered_df = df[(df['strike_price'] >= lower_bound) & 133 | (df['strike_price'] <= upper_bound) & 134 | (df['strike_price'] % strike_increment == 0)] 135 | 136 | # Print the filtered DataFrame to debug 137 | #print("Filtered DataFrame:", filtered_df[['strike_price']]) 138 | 139 | # Check if any rows match the criteria 140 | if filtered_df.empty: 141 | print("No strike prices found within the specified range.") 142 | else: 143 | # Sort by strike price 144 | sorted_df = filtered_df.sort_values('strike_price').reset_index(drop=True) 145 | 146 | # Check if the target_strike exists 147 | if target_strike in sorted_df['strike_price'].values: 148 | target_index = sorted_df[sorted_df['strike_price'] == target_strike].index[0] 149 | 150 | # Slice the DataFrame to get 5 rows above and 5 rows below the target 151 | start_index = max(0, target_index - 5) 152 | end_index = min(len(sorted_df), target_index + 6) 153 | final_df = sorted_df.iloc[start_index:end_index] 154 | 155 | # Select only the required columns 156 | final_df = final_df[['stock_code', 'expiry_date', 'right', 'strike_price', 'ltp']] 157 | 158 | # Define constants for Greeks calculation 159 | risk_free_rate = 0.05 # Example risk-free rate (5%) 160 | 161 | # Add spot price column for the calculation 162 | final_df['spot_price'] = Spot # Example spot price 163 | 164 | # Function to calculate implied volatility using LTP 165 | def calculate_implied_volatility(row): 166 | S = row['spot_price'] # Spot price 167 | K = row['strike_price'] # Strike price 168 | T = (pd.to_datetime(row['expiry_date']) - pd.Timestamp.now()).days / 365 # Time to expiration in years 169 | r = risk_free_rate # Risk-free rate 170 | option_price = row['ltp'] # Last traded price 171 | right = row['right'].lower() # 'call' or 'put' 172 | 173 | # Define the function to calculate implied volatility 174 | def objective_function(sigma): 175 | if right == 'call': 176 | option_type = 'c' 177 | elif right == 'put': 178 | option_type = 'p' 179 | else: 180 | raise ValueError("Invalid option type") 181 | 182 | return black_scholes(option_type, S, K, T, r, sigma) - option_price 183 | 184 | # Solve for implied volatility 185 | try: 186 | implied_vol = brentq(objective_function, 0.01, 5.0) 187 | except ValueError: 188 | implied_vol = np.nan 189 | return implied_vol 190 | 191 | # Calculate implied volatility and add to DataFrame 192 | final_df['implied_volatility'] = final_df.apply(calculate_implied_volatility, axis=1) 193 | 194 | # Function to calculate Greeks 195 | def calculate_greeks(row): 196 | S = row['spot_price'] # Spot price 197 | K = row['strike_price'] # Strike price 198 | T = (pd.to_datetime(row['expiry_date']) - pd.Timestamp.now()).days / 365 # Time to expiration in years 199 | r = risk_free_rate # Risk-free rate 200 | sigma = row['implied_volatility'] # Implied volatility 201 | right = row['right'].lower() # 'call' or 'put' 202 | 203 | if right == 'call': 204 | option_type = 'c' 205 | elif right == 'put': 206 | option_type = 'p' 207 | else: 208 | raise ValueError("Invalid option type") 209 | 210 | # Calculate Greeks using py_vollib 211 | delta_value = delta(option_type, S, K, T, r, sigma) 212 | gamma_value = gamma(option_type, S, K, T, r, sigma) 213 | theta_value = theta(option_type, S, K, T, r, sigma) 214 | vega_value = vega(option_type, S, K, T, r, sigma) 215 | rho_value = rho(option_type, S, K, T, r, sigma) 216 | 217 | return pd.Series([delta_value, gamma_value, theta_value, vega_value, rho_value], 218 | index=['Delta', 'Gamma', 'Theta', 'Vega', 'Rho']) 219 | 220 | # Calculate Greeks and add to DataFrame 221 | greeks_df = final_df.apply(calculate_greeks, axis=1) 222 | result_df = pd.concat([final_df, greeks_df], axis=1) 223 | 224 | # Round the values 225 | result_df['implied_volatility'] = result_df['implied_volatility'].round(2) 226 | result_df['Delta'] = result_df['Delta'].round(2) 227 | result_df['Theta'] = result_df['Theta'].round(2) 228 | result_df['Vega'] = result_df['Vega'].round(2) 229 | result_df['Rho'] = result_df['Rho'].round(2) 230 | 231 | # Print the resulting DataFrame with Greeks 232 | print("Final DataFrame with Greeks for Call:") 233 | print(result_df) 234 | else: 235 | print(f"Strike price {target_strike} not found in the filtered data.") 236 | 237 | # Option greeks for Put 238 | 239 | df = breeze.get_option_chain_quotes(stock_code="NIFTY", 240 | exchange_code="NFO", 241 | product_type="options", 242 | expiry_date="2024-08-14T06:00:00.000Z", 243 | right="put")["Success"] 244 | 245 | # Convert to DataFrame 246 | df = pd.DataFrame(df) 247 | 248 | # Convert strike_price to float 249 | df['strike_price'] = df['strike_price'].astype(float) 250 | 251 | # Define target strike and range parameters 252 | target_strike = ATM 253 | strike_increment = 50 254 | range_size = 5 255 | 256 | # Define the range for strike prices 257 | lower_bound = target_strike - range_size * strike_increment 258 | upper_bound = target_strike + range_size * strike_increment 259 | 260 | # Filter the rows where the strike price is within the range and in increments of 50 261 | filtered_df = df[(df['strike_price'] >= lower_bound) & 262 | (df['strike_price'] <= upper_bound) & 263 | (df['strike_price'] % strike_increment == 0)] 264 | 265 | # Print the filtered DataFrame to debug 266 | #print("Filtered DataFrame:", filtered_df[['strike_price']]) 267 | 268 | # Check if any rows match the criteria 269 | if filtered_df.empty: 270 | print("No strike prices found within the specified range.") 271 | else: 272 | # Sort by strike price 273 | sorted_df = filtered_df.sort_values('strike_price').reset_index(drop=True) 274 | 275 | # Check if the target_strike exists 276 | if target_strike in sorted_df['strike_price'].values: 277 | target_index = sorted_df[sorted_df['strike_price'] == target_strike].index[0] 278 | 279 | # Slice the DataFrame to get 5 rows above and 5 rows below the target 280 | start_index = max(0, target_index - 5) 281 | end_index = min(len(sorted_df), target_index + 6) 282 | final_df = sorted_df.iloc[start_index:end_index] 283 | 284 | # Select only the required columns 285 | final_df = final_df[['stock_code', 'expiry_date', 'right', 'strike_price', 'ltp']] 286 | 287 | # Define constants for Greeks calculation 288 | risk_free_rate = 0.05 # Example risk-free rate (5%) 289 | 290 | # Add spot price column for the calculation 291 | final_df['spot_price'] = Spot # Example spot price 292 | 293 | # Function to calculate implied volatility using LTP 294 | def calculate_implied_volatility(row): 295 | S = row['spot_price'] # Spot price 296 | K = row['strike_price'] # Strike price 297 | T = (pd.to_datetime(row['expiry_date']) - pd.Timestamp.now()).days / 365 # Time to expiration in years 298 | r = risk_free_rate # Risk-free rate 299 | option_price = row['ltp'] # Last traded price 300 | right = row['right'].lower() # 'call' or 'put' 301 | 302 | # Define the function to calculate implied volatility 303 | def objective_function(sigma): 304 | if right == 'call': 305 | option_type = 'c' 306 | elif right == 'put': 307 | option_type = 'p' 308 | else: 309 | raise ValueError("Invalid option type") 310 | 311 | return black_scholes(option_type, S, K, T, r, sigma) - option_price 312 | 313 | # Solve for implied volatility 314 | try: 315 | implied_vol = brentq(objective_function, 0.01, 5.0) 316 | except ValueError: 317 | implied_vol = np.nan 318 | return implied_vol 319 | 320 | # Calculate implied volatility and add to DataFrame 321 | final_df['implied_volatility'] = final_df.apply(calculate_implied_volatility, axis=1) 322 | 323 | # Function to calculate Greeks 324 | def calculate_greeks(row): 325 | S = row['spot_price'] # Spot price 326 | K = row['strike_price'] # Strike price 327 | T = (pd.to_datetime(row['expiry_date']) - pd.Timestamp.now()).days / 365 # Time to expiration in years 328 | r = risk_free_rate # Risk-free rate 329 | sigma = row['implied_volatility'] # Implied volatility 330 | right = row['right'].lower() # 'call' or 'put' 331 | 332 | if right == 'call': 333 | option_type = 'c' 334 | elif right == 'put': 335 | option_type = 'p' 336 | else: 337 | raise ValueError("Invalid option type") 338 | 339 | # Calculate Greeks using py_vollib 340 | delta_value = delta(option_type, S, K, T, r, sigma) 341 | gamma_value = gamma(option_type, S, K, T, r, sigma) 342 | theta_value = theta(option_type, S, K, T, r, sigma) 343 | vega_value = vega(option_type, S, K, T, r, sigma) 344 | rho_value = rho(option_type, S, K, T, r, sigma) 345 | 346 | return pd.Series([delta_value, gamma_value, theta_value, vega_value, rho_value], 347 | index=['Delta', 'Gamma', 'Theta', 'Vega', 'Rho']) 348 | 349 | # Calculate Greeks and add to DataFrame 350 | greeks_df = final_df.apply(calculate_greeks, axis=1) 351 | result_df = pd.concat([final_df, greeks_df], axis=1) 352 | 353 | # Round the values 354 | result_df['implied_volatility'] = result_df['implied_volatility'].round(2) 355 | result_df['Delta'] = result_df['Delta'].round(2) 356 | result_df['Theta'] = result_df['Theta'].round(2) 357 | result_df['Vega'] = result_df['Vega'].round(2) 358 | result_df['Rho'] = result_df['Rho'].round(2) 359 | 360 | # Print the resulting DataFrame with Greeks 361 | print("Final DataFrame with Greeks for Put:") 362 | print(result_df) 363 | else: 364 | print(f"Strike price {target_strike} not found in the filtered data.") 365 | -------------------------------------------------------------------------------- /webinar/Predefined_StraddleStrategy_SDK.py: -------------------------------------------------------------------------------- 1 | #Import the library 2 | from breeze_strategies import Strategies 3 | 4 | #Configure the strategy using API Keys and set stoploss/takeprofit level. 5 | api_key = "YOUR_APP_KEY" 6 | api_secret = "YOUR_SECRET_KEY" 7 | api_session = 'YOUR_SESSION_KEY' 8 | 9 | #Configure the strategy using API Keys and set stoploss/takeprofit level. 10 | obj = Strategies(app_key = api_key, 11 | secret_key =api_secret, 12 | api_session = api_session, 13 | max_profit = "100", 14 | max_loss = "-100") 15 | 16 | 17 | #Execute the strategy 18 | obj.straddle(strategy_type = "long", 19 | stock_code = "NIFTY", 20 | strike_price = "18700", 21 | quantity = "50", 22 | expiry_date = "2023-06-29T06:00:00.000Z") 23 | #SquareOff existing positions and exit the strategy of straddle 24 | obj.stop() 25 | -------------------------------------------------------------------------------- /webinar/README.md: -------------------------------------------------------------------------------- 1 | These are code files that we used in our webinars. 2 | 3 | * tutorial1.py - code used in [How to get started with Breeze API](https://www.youtube.com/watch?v=GtqrSDpj0NE) 4 | * creating session and simply downloading historical data and taking it into a Pandas DataFrame 5 | 6 | * tutorial2.py - code used in [Analysing historical market data from Breeze API using Pandas framework](https://www.youtube.com/watch?v=uZgAKrIMZBE) 7 | * working with Python's ```datetime``` basics 8 | * working with Python's ```list``` basics 9 | * working with Python's ```dictionary``` basics 10 | * working with Python's ```pandas Series``` and ```pandas DataFrame``` basics 11 | * using list of dates to download historical data in a loop, and taking the dictionaries into a DataFrame 12 | * playing with the market data in a DataFrame 13 | 14 | * tutorial3.py - code used in [Researching trading strategies using Pandas framework](https://www.youtube.com/watch?v=I4BAUYUyr7Q) 15 | * reading historical data csv into a Pandas DataFrame 16 | * exploratory analysis of the DataFrame 17 | * basic charting using MatPlotLib 18 | * applying Simple Moving Averages over 20 period and 50 period windows using Pandas built-in functions 19 | * deriving trading Signals and Positions from the SMA20 and SMA50 indicators 20 | * charting the indicators and generated trades over the price data 21 | 22 | * breeze_webinar_20230215.py 23 | * get_names() example 24 | * place get_historical_data_v2() call and take data into a dataframe 25 | * preview_order() example 26 | 27 | * breeze_webinar_auto_strike_selection_20230407.py 28 | * get_option_chain_quotes() used to download active option chain 29 | * weeding out illiquid strikes/contracts 30 | * strike/contract selection based on absolute number of strikes away 31 | * strike/contract selection based on greeks, with the example of Delta-based selection 32 | * [TBD] strike/contract selection based on premium we want to pay 33 | 34 | * chatGPT.py 35 | * code generated by ChatGPT is operationalized by Breeze APIs to trade an intra-day short-straddle selling strategy 36 | 37 | * data.py 38 | * simple sample code to place a single call to get_historical_data_v2() to get equity data and take into a Pandas dataframe 39 | 40 | * how_to_calculate_sma.py 41 | * simple sample code to download stock data and apply a Simple Moving Average indicator to the data 42 | 43 | * how_to_place_option_order.py 44 | * simple sample code to place a market order in a given options contract 45 | 46 | * how_to_use_websockets.py 47 | * simple sample code to subscribe to live market feed for an options contract 48 | 49 | * sdk_straddle.py 50 | * executing a stoploss-teke profit inclusive short straddle in JUST 14 lines of code, by using the breeze_strategies helper module 51 | 52 | * trailing_stoploss.py 53 | * how to implement a trailing stoploss in a while loop 54 | 55 | * Option_Plus.py 56 | * how to place and modify an OptionPlus order 57 | 58 | * get_started.py 59 | * how to connect to Breeze API and place a simple stock buy market order 60 | -------------------------------------------------------------------------------- /webinar/Researching_trading_strategies_using_Pandas_framework.py: -------------------------------------------------------------------------------- 1 | # code used in [Researching trading strategies using Pandas framework](https://www.youtube.com/watch?v=I4BAUYUyr7Q) 2 | import pandas as pd 3 | import matplotlib.pyplot as plt 4 | import numpy as np 5 | 6 | df_hdata = pd.read_csv('/home/builder/Downloads/ICICIBANK_HistoricalData.csv') 7 | df_hdata.shape 8 | df_hdata.columns 9 | df_hdata.head(10) 10 | df_hdata.tail() 11 | 12 | df_close = df_hdata[['datetime', 'close']].copy() 13 | df_close.shape 14 | df_close.columns 15 | df_close.head() 16 | df_close.tail() 17 | df_close['close'].max() 18 | df_close['close'].min() 19 | 20 | #let's take a look at the chart, how does it look, get a feel for it 21 | df_close['close'].plot(fontsize = 12) 22 | plt.grid() 23 | plt.ylabel('Price in Rupees') 24 | plt.show() 25 | 26 | # Create 20 days simple moving average column 27 | df_close['20_SMA'] = df_close['close'].rolling(window = 20, min_periods = 20).mean() 28 | # Create 50 days simple moving average column 29 | df_close['50_SMA'] = df_close['close'].rolling(window = 50, min_periods = 50).mean() 30 | # take a peep 31 | df_close.head(25) 32 | df_close.tail() 33 | 34 | # plot short and long moving averages 35 | plt.figure(figsize = (20, 10)) 36 | #ultratech_df['Close Price'].plot(color = 'k', lw = 1) 37 | df_close['close'].plot(color = 'r', lw = 1) 38 | df_close['20_SMA'].plot(color = 'b', lw = 1) 39 | df_close['50_SMA'].plot(color = 'g', lw = 1) 40 | plt.grid() 41 | plt.show() 42 | 43 | # generate signals 44 | df_close['Signal'] = 0.0 45 | df_close['Signal'] = np.where(df_close['20_SMA'] > df_close['50_SMA'], 1.0, 0.0) 46 | 47 | 48 | # create a new column 'Position' which is a day-to-day difference of the 'Signal' column. 49 | df_close['Position'] = df_close['Signal'].diff() 50 | 51 | # display the dataframe 52 | df_close.tail(10) 53 | 54 | # visualize the strategy as it would play out 55 | plt.figure(figsize = (20,10)) 56 | plt.tick_params(axis = 'both', labelsize = 14) 57 | # plot close price, short-term and long-term moving averages 58 | df_close['close'].plot(color = 'k', lw = 1, label = 'Close Price') 59 | df_close['20_SMA'].plot(color = 'b', lw = 1, label = '20-day SMA') 60 | df_close['50_SMA'].plot(color = 'g', lw = 1, label = '50-day SMA') 61 | 62 | # plot 'buy' signals 63 | plt.plot(df_close[df_close['Position'] == 1].index, 64 | df_close['20_SMA'][df_close['Position'] == 1], 65 | '^', markersize = 15, color = 'g', alpha = 0.7, label = 'buy') 66 | 67 | # plot 'sell' signals 68 | plt.plot(df_close[df_close['Position'] == -1].index, 69 | df_close['20_SMA'][df_close['Position'] == -1], 70 | 'v', markersize = 15, color = 'r', alpha = 0.7, label = 'sell') 71 | plt.ylabel('Price in Rupees', fontsize = 15 ) 72 | plt.xlabel('Date', fontsize = 15 ) 73 | plt.title('ICICIBANK - SMA Crossover chart', fontsize = 20) 74 | plt.legend() 75 | plt.grid() 76 | plt.show() 77 | 78 | df_close.to_csv('/home/builder/Downloads/ICICIBANK_SMA20-50_Strategy.csv') 79 | -------------------------------------------------------------------------------- /webinar/breeze_webinar_20230215.py: -------------------------------------------------------------------------------- 1 | from breeze_connect import BreezeConnect 2 | from datetime import datetime 3 | import pandas as pd 4 | 5 | breeze = BreezeConnect(api_key="YOUR_API_KEY") 6 | breeze.generate_session(api_secret="YOUR_SECRET_KEY", session_token="YOUR_SESSION_TOKEN") 7 | 8 | symbol = "CNXBAN" 9 | time_interval = "1second" 10 | start_date = datetime(2022, 12, 1, 9, 15,0) 11 | end_date = datetime(2022, 12, 1, 10, 15,0) 12 | exchange = "NFO" 13 | expiry = datetime(2022, 12, 29, 0,0,0) 14 | 15 | #!Note how get_names() is used to convert any symbology to any other symbology 16 | breeze.get_names(exchange_code="NSE", stock_code=symbol) 17 | ''' 18 | { 19 | 'exchange_code': 'NSE', 20 | 'exchange_stock_code': 'NIFTY BANK', 21 | 'isec_stock_code': 'CNXBAN', 22 | 'isec_token': 'NIFTY BANK', 23 | 'company name': 'NIFTY BANK', 24 | 'isec_token_level1': '4.1!NIFTY BANK', 25 | 'isec_token_level2': '4.2!NIFTY BANK' 26 | } 27 | ''' 28 | 29 | #! Use get_names to fetch 1second data 30 | data2 = breeze.get_historical_data_v2(interval = time_interval, 31 | from_date = start_date, 32 | to_date = end_date, 33 | stock_code = breeze.get_names(exchange_code="NSE", stock_code=symbol)['isec_stock_code'], 34 | product_type="futures", 35 | expiry_date=expiry, 36 | exchange_code = exchange) 37 | 38 | df2 = pd.DataFrame(data2['Success']) 39 | 40 | #!One Click F&O Sockets 41 | # Connect to Breeze socket 42 | breeze.ws_connect() 43 | # Define data handling function - whenever a tick comes in, this is what will be done with it 44 | def on_event_data(ticks): 45 | print("Time: ", datetime.now().isoformat() , " Ticks: {}".format(ticks)) 46 | # Assign above function to Breeze socket listener 47 | breeze.on_ticks = on_event_data 48 | 49 | 50 | #!Preview Order 51 | breeze.preview_order( 52 | stock_code = "ICIBAN", 53 | exchange_code = "NSE", 54 | product = "margin", 55 | order_type = "limit", 56 | price = "907.05", 57 | action = "buy", 58 | quantity = "1", 59 | specialflag = "N" 60 | ) 61 | 62 | ''' 63 | { 64 | 'Success': { 65 | 'brokerage': 6.8029, 66 | 'exchange_turnover_charges': 0.0254, 67 | 'stamp_duty': 0.1361, 68 | 'stt': 0.9071, 69 | 'sebi_charges': 0.0009, 70 | 'gst': 1.2293, 71 | 'total_turnover_and_sebi_charges': 0.0263, 72 | 'total_other_charges': 2.2987, 73 | 'total_brokerage': 9.1015 74 | }, 75 | 'Status': 200, 76 | 'Error': None 77 | } 78 | ''' 79 | -------------------------------------------------------------------------------- /webinar/breeze_webinar_auto_strike_selection_20230407.py: -------------------------------------------------------------------------------- 1 | from breeze_connect import BreezeConnect 2 | import sys 3 | import bisect 4 | import datetime 5 | import mibian #to easily calculate iv and greeks (not the fastest way though) 6 | 7 | flt_rf = 0.058 8 | int_days_to_expiry = (datetime.datetime(2023,4,27, 0, 0, 0) - datetime.datetime.today()).days 9 | 10 | sys.path.append('/media/builder/briefcase/Documents/') 11 | 12 | from breeze_configs import Breeze_Configs 13 | 14 | configs = Breeze_Configs() 15 | def n_highest(int_strikes_away, flt_spot, list_strikes): 16 | ''' 17 | REQUIRES: 18 | import bisect (https://docs.python.org/3/library/bisect.html) 19 | 20 | INPUTS: 21 | int_strikes_away = how many strikes away do you want to find? negative will look ITM, positive OTM 22 | flt_spot = the spot price wrt which we're looking for a spot 23 | list_strikes = list of all available strikes 24 | 25 | OUTPUT: 26 | flt_next_highest_strike = returns the strike needed to be used 27 | ''' 28 | a = sorted(list_strikes) 29 | flt_next_highest_strike = a[bisect.bisect_left(a, flt_spot) + int_strikes_away - 1] 30 | return flt_next_highest_strike 31 | 32 | app = BreezeConnect(api_key=configs.api_key) 33 | app.generate_session(api_secret=configs.api_secret, 34 | session_token=configs.session_token) 35 | 36 | list_call_chain = app.get_option_chain_quotes( 37 | stock_code='CNXBAN', 38 | exchange_code='NFO', 39 | right='call', 40 | expiry_date=datetime.date(2023,4,27).strftime(r'%d-%b-%Y'), 41 | product_type='options' 42 | )['Success'] 43 | list_put_chain = app.get_option_chain_quotes( 44 | stock_code='CNXBAN', 45 | exchange_code='NFO', 46 | right='put', 47 | expiry_date=datetime.date(2023,4,27).strftime(r'%d-%b-%Y'), 48 | product_type='options' 49 | )['Success'] 50 | 51 | list_call_chain = [item for item in list_call_chain if item['ltt']!=''] 52 | list_put_chain = [item for item in list_put_chain if item['ltt']!=''] 53 | 54 | list_call_strikes = [item['strike_price'] for item in list_call_chain] 55 | list_put_strikes = [item['strike_price'] for item in list_put_chain] 56 | 57 | list_diff = list(set(list_call_strikes).symmetric_difference(set(list_put_strikes))) 58 | 59 | list_call_chain = [item for item in list_call_chain if item['strike_price'] not in list_diff] 60 | list_put_chain = [item for item in list_put_chain if item['strike_price'] not in list_diff] 61 | len(list_call_chain) 62 | len(list_put_chain) 63 | 64 | list_call_strikes = [item['strike_price'] for item in list_call_chain] 65 | list_put_strikes = [item['strike_price'] for item in list_put_chain] 66 | 67 | 68 | dict_fut_quote = app.get_quotes( 69 | stock_code='CNXBAN', 70 | exchange_code='NFO', 71 | product_type='futures', 72 | expiry_date=datetime.date(2023,4,27).strftime(r'%d-%b-%Y') 73 | )['Success'][0] 74 | 75 | #!STRIKE SELECTION BY ABSOLUTE COUNT AWAY FROM ATM 76 | #?: "ATM" is defined as per NSE definition in VIX documentation: "the strike price immediately lower than the spot". 77 | n_highest(int_strikes_away=-5, 78 | flt_spot=dict_fut_quote['ltp'], 79 | list_strikes=list_call_strikes) 80 | 81 | 82 | #!STRIKE SELECTION BASED ON DELTA 83 | #? assume we want a call with Delta 84 | for item in list_call_chain: 85 | iv = mibian.BS([dict_fut_quote['ltp'], item['strike_price'], flt_rf, int_days_to_expiry], callPrice=item['ltp']).impliedVolatility 86 | delta = mibian.BS([dict_fut_quote['ltp'], item['strike_price'], flt_rf, int_days_to_expiry],volatility=iv).callDelta 87 | item['iv'] = iv 88 | item['delta'] = delta 89 | for item in list_put_chain: 90 | iv = mibian.BS([dict_fut_quote['ltp'], item['strike_price'], flt_rf, int_days_to_expiry], putPrice=item['ltp']).impliedVolatility 91 | delta = mibian.BS([dict_fut_quote['ltp'], item['strike_price'], flt_rf, int_days_to_expiry],volatility=iv).putDelta 92 | item['iv'] = iv 93 | item['delta'] = delta 94 | 95 | list_call_delta = [item['delta'] for item in list_call_chain] 96 | list_put_delta = [item['delta'] for item in list_put_chain] 97 | 98 | list_sum_delta = [cd + pd for cd, pd in zip(list_call_delta, list_put_delta)] 99 | 100 | list_sum_delta[bisect.bisect(list_sum_delta, 0)] 101 | ind_zero_delta = list_sum_delta.index(0.061036296556833514) 102 | list_call_chain[ind_zero_delta] 103 | list_put_chain[ind_zero_delta] 104 | 105 | #!STRIKE SELECTION BASED ON PREMIUM WE WANT TO PAY 106 | #? let's assume that we want to pay less than 100 as premium for any OTM call 107 | 108 | 109 | https://api.icicidirect.com/apiuser/home -------------------------------------------------------------------------------- /webinar/chatGPT.py: -------------------------------------------------------------------------------- 1 | #Configure the strategy using API Keys and set stoploss/takeprofit level. 2 | api_key = "YOUR_APP_KEY" 3 | api_secret = "YOUR_SECRET_KEY" 4 | api_session = 'YOUR_SESSION_KEY' 5 | 6 | #Import the library 7 | from breeze_connect import BreezeConnect 8 | 9 | #Create API library object 10 | api = BreezeConnect(api_key=api_key) 11 | api.generate_session(api_secret=api_secret,session_token=api_session) 12 | 13 | # Function to place a straddle. Make sure to change the contract details i.e. expiry_date, vailidity_date, strike_price, quantity etc. 14 | def place(): 15 | 16 | for option_type in ['call','put']: 17 | response = api.place_order(stock_code="NIFTY", 18 | exchange_code="NFO", 19 | product="options", 20 | action="buy", 21 | order_type="market", 22 | stoploss="", 23 | quantity="50", 24 | price="", 25 | validity="day", 26 | validity_date="2023-07-19T06:00:00.000Z", 27 | disclosed_quantity="0", 28 | expiry_date="2023-07-20T06:00:00.000Z", 29 | right= option_type, 30 | strike_price="19800") 31 | print(response) 32 | 33 | 34 | # Function to square off a straddle. Make sure to change the action to 'buy' or 'sell' depending upon open position. 35 | def squareoff(): 36 | 37 | for option_type in ['call','put']: 38 | response = api.square_off(exchange_code="NFO", 39 | product="options", 40 | stock_code="NIFTY", 41 | expiry_date="2023-07-20T06:00:00.000Z", 42 | right=option_type, 43 | strike_price="19800", 44 | action="sell", 45 | order_type="market", 46 | validity="day", 47 | stoploss="0", 48 | quantity="50", 49 | price="0", 50 | validity_date="2023-07-19T06:00:00.000Z", 51 | trade_password="", 52 | disclosed_quantity="0") 53 | 54 | print(response) 55 | 56 | # Function to calculate P&L 57 | def calculate_pnl(): 58 | 59 | pnl = 0 60 | response = api.get_portfolio_positions() 61 | 62 | if response['Status'] == 200: 63 | response = response['Success'] 64 | 65 | for item in response: 66 | ltp = float(item['ltp']) 67 | cost = float(item['average_price']) 68 | qty = int(item['quantity']) 69 | # print((item['ltp'],item['average_price'])) 70 | pnl += round((ltp - cost)*qty, 2) 71 | 72 | print(f"P&L : {pnl}") 73 | return pnl 74 | 75 | 76 | # Function to check if market is open 77 | def is_market_open(): 78 | current_time = datetime.datetime.now().time() 79 | market_open_time = datetime.time(9, 15) # Assuming market opens at 9:15 AM 80 | market_close_time = datetime.time(15, 30) # Assuming market closes at 3:30 PM 81 | return market_open_time <= current_time <= market_close_time 82 | 83 | # Function to place a short straddle 84 | def place_straddle(): 85 | # Code to place the straddle order goes here 86 | place() 87 | print("Long straddle order placed.") 88 | 89 | # Function to square off the position 90 | def square_off_position(): 91 | # Code to square off the position goes here 92 | squareoff() 93 | print("Position squared off.") 94 | 95 | # Function to square off the position 96 | def profit_or_loss_threshold_reached(): 97 | # Code to calculate PnL 98 | print("\nCHECKING P&L...") 99 | pnl = calculate_pnl() 100 | if pnl < -100: 101 | return True 102 | else: 103 | return False 104 | 105 | 106 | # Main function 107 | def main(): 108 | 109 | # Place the straddle 110 | place_straddle() 111 | 112 | print("Waiting for 3 seconds for order execution") 113 | time.sleep(3) 114 | 115 | while is_market_open(): 116 | # Check if profit or loss threshold is reached 117 | # Replace the condition below with your own logic 118 | if profit_or_loss_threshold_reached(): 119 | square_off_position() 120 | break 121 | 122 | print("Waiting for 20 seconds for P&L check") 123 | time.sleep(60) # Sleep for 60 seconds before checking again 124 | 125 | if __name__ == "__main__": 126 | main() 127 | -------------------------------------------------------------------------------- /webinar/how_to_calculate_sma.py: -------------------------------------------------------------------------------- 1 | ### Enter your API Keys 2 | api_key = "INSERT_YOUR_APP_KEY_HERE" 3 | api_secret = "INSERT_YOUR_SECRET_KEY_HERE" 4 | api_session = 'INSERT_YOUR_API_SESSION_HERE' 5 | 6 | import time 7 | import pandas as pd 8 | from datetime import timedelta, datetime 9 | 10 | from breeze_connect import BreezeConnect 11 | 12 | # Initialize SDK 13 | breeze = BreezeConnect(api_key=api_key) 14 | 15 | # Generate Session 16 | breeze.generate_session(api_secret=api_secret, 17 | session_token=api_session) 18 | 19 | # initialize user inputs 20 | 21 | 22 | def get_sma(): 23 | STOCK = "BHEL" 24 | current_time = datetime.now() 25 | from_date = current_time - timedelta(days=20) 26 | 27 | # note that we have converted dates to ISO time-format before making API call 28 | data = breeze.get_historical_data_v2(interval='1day', 29 | from_date = from_date.strftime('%Y-%m-%dT%H:%M:%S.000Z'), 30 | to_date = current_time.strftime('%Y-%m-%dT%H:%M:%S.000Z'), 31 | stock_code=STOCK, 32 | exchange_code="NSE", 33 | product_type="cash") 34 | 35 | 36 | # Calculate simple moving average of 'close' price 37 | data = pd.DataFrame(data['Success']) 38 | data.close = data.close.astype(float) 39 | sma = round(data.close.mean(),2) 40 | return sma 41 | 42 | if __name__ == "__main__": 43 | indicator = get_sma() 44 | print(indicator) 45 | -------------------------------------------------------------------------------- /webinar/how_to_place_option_order.py: -------------------------------------------------------------------------------- 1 | #intialize keys 2 | 3 | api_key = "INSERT_YOUR_APP_KEY_HERE" 4 | api_secret = "INSERT_YOUR_SECRET_KEY_HERE" 5 | api_session = 'INSERT_YOUR_API_SESSION_HERE' 6 | 7 | 8 | 9 | # Define Contract 10 | stock = 'NIFTY', 11 | strike = '17750', 12 | expiry = '2023-04-20T06:00:00.000Z', 13 | right = 'call', 14 | 15 | 16 | 17 | 18 | # Import Libraries 19 | 20 | from datetime import datetime 21 | from breeze_connect import BreezeConnect 22 | 23 | # Setup my API keys 24 | api = BreezeConnect(api_key=api_key) 25 | api.generate_session(api_secret=api_secret,session_token=api_session) 26 | 27 | # Place order 28 | buy_order = api.place_order(stock_code=stock, 29 | exchange_code="NFO", 30 | product="options", 31 | action='buy', 32 | order_type='market', 33 | stoploss="", 34 | quantity="50", 35 | price="", 36 | validity="day", 37 | validity_date=today, 38 | disclosed_quantity="0", 39 | expiry_date=expiry, 40 | right=right, 41 | strike_price=strike) 42 | 43 | print(buy_order) 44 | -------------------------------------------------------------------------------- /webinar/how_to_use_websockets.py: -------------------------------------------------------------------------------- 1 | #intialize keys 2 | 3 | api_key = "INSERT_YOUR_APP_KEY_HERE" 4 | api_secret = "INSERT_YOUR_SECRET_KEY_HERE" 5 | api_session = 'INSERT_YOUR_API_SESSION_HERE' 6 | 7 | # ********************************************************************************************************************************************************************* 8 | 9 | 10 | 11 | # Import Libraries 12 | 13 | from datetime import datetime 14 | import pandas as pd 15 | from breeze_connect import BreezeConnect 16 | 17 | # Setup my API keys 18 | api = BreezeConnect(api_key=api_key) 19 | api.generate_session(api_secret=api_secret,session_token=api_session) 20 | 21 | 22 | # ********************************************************************************************************************************************************************* 23 | 24 | # Callback to receive ticks. 25 | # Event based function 26 | 27 | def on_ticks(ticks): 28 | print(ticks) 29 | 30 | # ********************************************************************************************************************************************************************* 31 | 32 | 33 | # Main Function 34 | if __name__ == "__main__": 35 | print ("Starting Execution \n") 36 | 37 | #Switch on Websockets 38 | api.ws_connect() 39 | api.on_ticks = on_ticks 40 | 41 | api.subscribe_feeds(exchange_code="NFO", 42 | stock_code='NIFTY', 43 | product_type="options", 44 | expiry_date='27-Apr-2023', 45 | strike_price='17500', 46 | right='call', interval="1minute") 47 | -------------------------------------------------------------------------------- /webinar/rsi_ema.txt: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from breeze_connect import BreezeConnect 4 | import backtrader as bt 5 | from datetime import datetime 6 | import backtrader.analyzers as btanalyzers 7 | import matplotlib.pyplot as plt 8 | import warnings 9 | warnings.filterwarnings('ignore') 10 | 11 | file = open("config.txt", "r") 12 | keys = file.read().split(",") 13 | 14 | key_api = keys[0] 15 | key_secret = keys[1] 16 | key_session = keys[2] 17 | 18 | 19 | breeze = BreezeConnect(api_key=key_api) 20 | breeze.generate_session(api_secret=key_secret, session_token=key_session) 21 | 22 | class RsiEmaStrategy(bt.Strategy): 23 | params = ( 24 | ('rsi_period', 14), # Default RSI period 25 | ('ema_short', 12), # Short-term EMA 26 | ('ema_long', 26), # Long-term EMA 27 | ('rsi_overbought', 70), # RSI overbought level 28 | ('rsi_oversold', 30), # RSI oversold level 29 | ) 30 | 31 | def __init__(self): 32 | # Define indicators 33 | self.rsi = bt.indicators.RSI_Safe(self.data.close, period=self.params.rsi_period) 34 | self.ema_short = bt.indicators.EMA(self.data.close, period=self.params.ema_short) 35 | self.ema_long = bt.indicators.EMA(self.data.close, period=self.params.ema_long) 36 | 37 | def next(self): 38 | if not self.position: 39 | # Buy conditions 40 | if self.rsi < self.params.rsi_oversold and self.ema_short > self.ema_long: 41 | self.buy() 42 | else: 43 | # Sell conditions 44 | if self.rsi > self.params.rsi_overbought or self.ema_short < self.ema_long: 45 | self.sell() 46 | 47 | 48 | class CustomPandsData(bt.feeds.PandasData): 49 | params = (('datetime', 'datetime'), 50 | ('open', 'open'), 51 | ('high', 'high'), 52 | ('low', 'low'), 53 | ('close', 'close'), 54 | ('volume', 'volume') 55 | ) 56 | 57 | def datetime_to_iso(dt): 58 | return dt.strftime('%Y-%m-%dT%H:%M:%S') + '.000Z' 59 | 60 | def datetime_converter(dt_string): 61 | return pd.to_datetime(dt_string) 62 | 63 | 64 | if __name__ == "__main__": 65 | current_time = datetime.now() 66 | to_date = datetime_to_iso(current_time) 67 | 68 | data_df = breeze.get_historical_data_v2(interval="5minute", 69 | from_date="2023-08-15T07:00:00.000Z", 70 | to_date=to_date, 71 | stock_code="ITC", 72 | exchange_code="NSE", 73 | product_type="cash")["Success"] 74 | 75 | data_df = pd.DataFrame(data_df) 76 | data_df["datetime"] = data_df["datetime"].apply(datetime_converter) 77 | 78 | cerebro = bt.Cerebro() 79 | cerebro.addstrategy(RsiEmaStrategy) 80 | 81 | data_feed = CustomPandsData(dataname=data_df) 82 | cerebro.adddata(data_feed) 83 | 84 | #Set up Broker Account 85 | cerebro.broker = bt.brokers.BackBroker() 86 | cerebro.broker.set_cash(1000000) 87 | 88 | #Run the Backtest 89 | cerebro.run() 90 | cerebro.plot() 91 | 92 | 93 | -------------------------------------------------------------------------------- /webinar/rsi_ema_executional_code.txt: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from breeze_connect import BreezeConnect 4 | from datetime import datetime 5 | import threading 6 | import queue 7 | import logging as logger 8 | import json 9 | 10 | logger.basicConfig(level = logger.INFO, handlers=[logger.StreamHandler()]) 11 | 12 | file = open("config.txt", "r") 13 | keys = file.read().split(",") 14 | 15 | key_api = keys[0] 16 | key_secret = keys[1] 17 | key_session = keys[2] 18 | try: 19 | breeze = BreezeConnect(api_key=key_api) 20 | breeze.generate_session(api_secret=key_secret, session_token=key_session) 21 | logger.info("Breeze Session Initialized Successfully.") 22 | except Exception as ex: 23 | logger.error(f"Error Initializing Breeze Session:{ex}") 24 | exit(1) # Immediate Exit 25 | 26 | #Queues for ticks 27 | ticks_queue = queue.Queue() 28 | running = True 29 | position = None #Track Position Buy Sell or None 30 | ema_short_period = 12 31 | ema_long_period = 26 32 | rsi_period = 14 33 | rsi_overbought = 70 34 | rsi_oversold = 30 35 | 36 | #Historical Data to Calculate Indicators 37 | tick_data = pd.DataFrame(columns=["datetime", "close"]) 38 | 39 | def calculate_ema(prices,period): 40 | "Calculate EMA" 41 | return prices.ewm(span=period, adjust=False).mean().iloc[-1] 42 | 43 | def calculate_rsi(prices, period): 44 | "Calculate RSI" 45 | delta = prices.diff() 46 | gain = (delta.where(delta>0, 0)).rolling(window=period).mean() 47 | loss = (-delta.where(delta<0,0)).rolling(window=period).mean() 48 | rs = gain/loss 49 | return 100-(100/(1+rs)).iloc[-1] 50 | 51 | def on_ticks(ticks): 52 | "Callback to handle ticks" 53 | try: 54 | ticks = json.load(ticks) if isinstance(ticks, str) else ticks 55 | print(f"ticks:{ticks}") 56 | # for tick in ticks: 57 | timestamp = datetime.now() 58 | close_price = ticks.get("last", None) 59 | print(f"Close Price:{close_price}") 60 | if close_price: 61 | tick_data.loc[len(tick_data)] = {"datetime":timestamp, "close":close_price} 62 | #Keep only recent data 63 | if len(tick_data) > rsi_period + ema_long_period: 64 | tick_data.drop(index=0, inplace=True) 65 | ticks_queue.put(close_price) 66 | except Exception as ex: 67 | logger.error(f"Error processing tick:{ex}") 68 | 69 | 70 | breeze.on_ticks = on_ticks 71 | 72 | def execute_trade(action:str): 73 | try: 74 | if action == "buy": 75 | logger.info("Placing Buy Order") 76 | # breeze.place_order(stock_code="ITC", 77 | # exchange_code="NSE", 78 | # product="cash", 79 | # action="buy", 80 | # order_type="limit", 81 | # stoploss="", 82 | # quantity="1", 83 | # price="305", 84 | # validity="day" 85 | # ) 86 | elif action == "sell": 87 | logger.info("Placing a sell order") 88 | # breeze.place_order(stock_code="ITC", 89 | # exchange_code="NSE", 90 | # product="cash", 91 | # action="sell", 92 | # order_type="limit", 93 | # stoploss="", 94 | # quantity="1", 95 | # price="305", 96 | # validity="day" 97 | # ) 98 | 99 | except Exception as ex: 100 | logger.error(f"Error placing order:{ex}") 101 | 102 | def process_ticks(): 103 | """"Process and Exceute the strategy""" 104 | global position 105 | while running: 106 | try: 107 | price = ticks_queue.get_nowait() 108 | prices = tick_data["close"] 109 | 110 | if len(prices) >= rsi_period + ema_long_period: 111 | #Calculate Indictaors 112 | ema_short = calculate_ema(prices, ema_short_period) 113 | ema_short = round(ema_short, 2) 114 | ema_long = calculate_ema(prices, ema_long_period) 115 | ema_long = round(ema_long, 2) 116 | rsi = calculate_rsi(prices, rsi_period) 117 | rsi = round(rsi, 2) 118 | 119 | logger.info(f"EMA Short:{ema_short}, EMA Long{ema_long}") 120 | logger.info(f"RSI:{rsi}") 121 | #Strategy Logic 122 | if position is None: 123 | if rsi < rsi_oversold and ema_short > ema_long: 124 | print("Oversold Condition Met..") 125 | execute_trade("buy") 126 | position = "buy" 127 | 128 | elif position == "buy": 129 | if rsi > rsi_overbought or ema_short < ema_long: 130 | print("Over Bought Condition Met..") 131 | execute_trade("sell") 132 | position = None 133 | except queue.Empty: 134 | continue 135 | 136 | #Start Processing Threads 137 | ticks_thread = threading.Thread(target=process_ticks, daemon=True) 138 | ticks_thread.start() 139 | 140 | try: 141 | breeze.ws_connect() 142 | breeze.subscribe_feeds( 143 | exchange_code="NFO", 144 | stock_code="NIFTY", 145 | product_type="options", 146 | expiry_date = "26-Dec-2024", 147 | strike_price = "24000", 148 | right="Call", 149 | get_exchange_quotes=True, 150 | get_market_depth=False 151 | ) 152 | while running: 153 | pass #Keep main Thread Running 154 | except KeyboardInterrupt: 155 | logger.info("Gracefully Shutting Down") 156 | 157 | finally: 158 | running = False 159 | ticks_thread.join() 160 | breeze.ws_disconnect() 161 | logger.info("Application Terminated") 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /webinar/rsi_strategy_code.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from breeze_connect import BreezeConnect 4 | import backtrader as bt 5 | from datetime import datetime 6 | import backtrader.analyzers as btanalyzers 7 | import matplotlib.pyplot as plt 8 | import warnings 9 | warnings.filterwarnings('ignore') 10 | 11 | file = open("config.txt", "r") 12 | keys = file.read().split(",") 13 | 14 | key_api = keys[0] 15 | key_secret = keys[1] 16 | key_session = keys[2] 17 | 18 | 19 | breeze = BreezeConnect(api_key=key_api) 20 | breeze.generate_session(api_secret=key_secret, session_token=key_session) 21 | 22 | class RSIStrategy(bt.Strategy): 23 | params = ( 24 | ("rsi_period", 14), 25 | ("rsi_overbought", 70), 26 | ("rsi_oversold", 30) 27 | ) 28 | 29 | def __init__(self): 30 | self. rsi = bt.indicators.RelativeStrengthIndex(period=self.params.rsi_period) 31 | 32 | def next(self): 33 | if self.rsi < self.params.rsi_oversold: 34 | self.buy() 35 | # self.place_buy_order() 36 | 37 | elif self.rsi > self.params.rsi_overbought: 38 | self.sell() 39 | # self.place_sell_order() 40 | 41 | # def place_buy_order(self): 42 | # breeze.place_order(stock_code="ITC", 43 | # exchange_code="NSE", 44 | # product="cash", 45 | # action="buy", 46 | # order_type="market", 47 | # stoploss="", 48 | # quantity="1", 49 | # price="", 50 | # validity="day" 51 | # ) 52 | 53 | # def place_sell_order(self): 54 | 55 | # breeze.place_order(stock_code="ITC", 56 | # exchange_code="NSE", 57 | # product="cash", 58 | # action="sell", 59 | # order_type="market", 60 | # stoploss="", 61 | # quantity="1", 62 | # price="", 63 | # validity="day" 64 | # ) 65 | 66 | class CustomPandasData(bt.feeds.PandasData): 67 | params = (('datetime','datetime'), 68 | ('open', 'open'), 69 | ('high', 'high'), 70 | ('low', 'low'), 71 | ('close', 'close'), 72 | ('volume', 'volume') 73 | ) 74 | 75 | 76 | def datetime_to_iso(dt): 77 | return dt.strftime('%Y-%m-%dT%H:%M:%S') + '.000Z' 78 | 79 | def datetime_converter(dt_string): 80 | return pd.to_datetime(dt_string) 81 | 82 | 83 | if __name__ == "__main__": 84 | current_time = datetime.now() 85 | to_date = datetime_to_iso(current_time) 86 | 87 | data_df = breeze.get_historical_data_v2(interval="5minute", 88 | from_date= "2023-08-15T07:00:00.000Z", 89 | to_date= to_date, 90 | stock_code="ITC", 91 | exchange_code="NSE", 92 | product_type="cash")["Success"] 93 | 94 | 95 | data_df = pd.DataFrame(data_df) 96 | 97 | data_df["datetime"] = data_df["datetime"].apply(datetime_converter) 98 | 99 | cerebro = bt.Cerebro() 100 | cerebro.addstrategy(RSIStrategy) 101 | 102 | data_feed = CustomPandasData(dataname=data_df) 103 | cerebro.adddata(data_feed) 104 | 105 | #Set up broker account 106 | cerebro.broker = bt.brokers.BackBroker() 107 | cerebro.broker.set_cash(100000) 108 | 109 | 110 | # #Run the Backtest 111 | cerebro.run() 112 | cerebro.plot() 113 | 114 | 115 | -------------------------------------------------------------------------------- /webinar/trailing_stoploss.py: -------------------------------------------------------------------------------- 1 | #intialize keys 2 | 3 | api_key = "INSERT_YOUR _APP_KEY_HERE" 4 | api_secret = "INSERT_YOUR_SECRET_KEY_HERE" 5 | api_session = 'INSERT_YOUR_API_SESSION_HERE' 6 | 7 | 8 | 9 | # Define Contract 10 | stock = 'NIFTY', 11 | strike = '17750', 12 | expiry = '2023-04-20T06:00:00.000Z', 13 | right = 'call', 14 | 15 | 16 | 17 | 18 | 19 | # Import Libraries 20 | from datetime import datetime 21 | from breeze_connect import BreezeConnect 22 | 23 | # Setup my API keys 24 | api = BreezeConnect(api_key=api_key) 25 | api.generate_session(api_secret=api_secret,session_token=api_session) 26 | 27 | # Place order 28 | buy_order = api.place_order(stock_code=stock, 29 | exchange_code="NFO", 30 | product="options", 31 | action='buy', 32 | order_type='market', 33 | stoploss="", 34 | quantity="50", 35 | price="", 36 | validity="day", 37 | validity_date=today, 38 | disclosed_quantity="0", 39 | expiry_date=expiry, 40 | right=right, 41 | strike_price=strike) 42 | 43 | # Store Order ID 44 | order_id = buy_order['Success']['order_id'] 45 | 46 | # Get current price 47 | price = api.get_quotes(stock_code=stock, 48 | exchange_code="NFO", 49 | product_type="options", 50 | expiry_date=expiry, 51 | right=right, 52 | strike_price=strike) 53 | 54 | # Get the buy price of order 55 | cost = float(api.get_order_detail('nfo',order_id)['Success'][0]['average_price']) 56 | trailing_stoploss = round(cost * 0.95,1) 57 | 58 | # Run Loop 59 | while(True): 60 | 61 | if(price > cost * 1.10): 62 | cost = price 63 | trailing_stoploss = round(cost * 0.95,1) 64 | 65 | elif(price < cost): 66 | 67 | # Place square off order 68 | sq_off_order = api.square_off(exchange_code="NFO", 69 | product="options", 70 | stock_code=stock, 71 | expiry_date=expiry, 72 | right=right, 73 | strike_price=strike, 74 | action='sell', 75 | order_type="market", 76 | validity="day", 77 | stoploss="", 78 | quantity="50", 79 | price="0", 80 | validity_date=datetime.now().strftime('%Y-%m-%dT06:00:00.000Z') , 81 | trade_password="", 82 | disclosed_quantity="0") 83 | 84 | 85 | if(sq_off_order['Status']==200) : 86 | print(sq_off_order) 87 | 88 | 89 | break 90 | 91 | time.sleep(2) 92 | -------------------------------------------------------------------------------- /webinar/trailing_stoploss_through_websocket.py: -------------------------------------------------------------------------------- 1 | from breeze_connect import BreezeConnect 2 | import pandas as pd 3 | from datetime import datetime, time as datetime_time 4 | import time 5 | import threading 6 | import queue 7 | import logging as logger 8 | import warnings 9 | warnings.filterwarnings('ignore') 10 | 11 | file = open("config.txt", "r") 12 | keys = file.read().split(",") 13 | 14 | key_api = keys[0] 15 | key_secret = keys[1] 16 | key_session = keys[2] 17 | 18 | logger.basicConfig(level=logger.INFO, handlers=[logger.StreamHandler()]) 19 | 20 | options_basket = [ 21 | {"stock_code": "NIFTY", "expiry_date": "25-Jul-2024", "strike_price": "24950", "right": "Call"}, 22 | ] 23 | 24 | max_loss = 1000 25 | max_profit = 500 26 | end_time = datetime_time(15, 30) 27 | trailing_percentage = 10 28 | quantity = 25 29 | 30 | # Initialize BreezeConnect 31 | breeze = BreezeConnect(api_key=key_api) 32 | breeze.generate_session(api_secret=key_secret, session_token=key_session) 33 | 34 | # Create a queue to store ticks 35 | ticks_queue = queue.Queue() 36 | 37 | last_price_tick = None 38 | last_price_tick_lock = threading.Lock() 39 | 40 | # Callback to receive ticks and put them in the queue 41 | def on_ticks(ticks): 42 | ticks_queue.put(ticks) 43 | 44 | # Assign the callbacks 45 | breeze.on_ticks = on_ticks 46 | breeze.subscribe_feeds(get_order_notification=True) 47 | running = True 48 | 49 | # Function to continuously process ticks and save them into a DataFrame 50 | def process_ticks(): 51 | global last_price_tick 52 | while running: 53 | ticks = [] 54 | while not ticks_queue.empty(): 55 | ticks.append(ticks_queue.get()) 56 | if ticks: 57 | df = pd.DataFrame(ticks) 58 | latest_tick = df.iloc[-1].to_dict() 59 | with last_price_tick_lock: 60 | last_price_tick = latest_tick["last"] 61 | 62 | # Start a separate thread for continuous processing 63 | ticks_thread = threading.Thread(target=process_ticks, daemon=True) 64 | ticks_thread.start() 65 | 66 | # Connect to the websocket 67 | breeze.ws_connect() 68 | 69 | # Subscribe to feeds for each option in the basket 70 | for option in options_basket: 71 | breeze.subscribe_feeds(exchange_code="NFO", 72 | stock_code=option["stock_code"], 73 | product_type="options", 74 | expiry_date=option["expiry_date"], 75 | strike_price=option["strike_price"], 76 | right=option["right"], 77 | get_exchange_quotes=True, 78 | get_market_depth=False) 79 | 80 | order_placed_flag = False 81 | 82 | class TrailingStopLoss: 83 | def __init__(self, initial_price, trailing_percentage): 84 | self.initial_price = initial_price 85 | self.trailing_percentage = trailing_percentage 86 | self.trailing_stop = initial_price * (1 - trailing_percentage / 100) 87 | self.highest_price = initial_price 88 | 89 | def update_price(self, current_price): 90 | # Update the highest price if the current price is higher 91 | if current_price > self.highest_price: 92 | self.highest_price = current_price 93 | self.trailing_stop = self.highest_price * (1 - self.trailing_percentage / 100) 94 | return self.trailing_stop 95 | 96 | def should_sell(self, current_price): 97 | # Check if the current price has hit the trailing stop 98 | return current_price <= self.trailing_stop 99 | 100 | def place_orders(option): 101 | global order_placed_flag 102 | if not order_placed_flag: 103 | # Place Order 104 | res = breeze.place_order(stock_code=option["stock_code"], 105 | exchange_code="NFO", 106 | product="options", 107 | action="buy", 108 | order_type="market", 109 | stoploss="", 110 | quantity="25", 111 | price="", 112 | validity="day", 113 | validity_date="2024-07-03T06:00:00.000Z", 114 | disclosed_quantity="0", 115 | expiry_date=option["expiry_date"], 116 | right=option["right"], 117 | strike_price=option["strike_price"]) 118 | 119 | print(f"res:{res}") 120 | print("Call Buy Order Placed") 121 | order_id = res["Success"]["order_id"] 122 | print(f"order_id:{order_id}") 123 | order_placed_flag = True 124 | for _ in range(10): 125 | order_detail = breeze.get_order_detail(exchange_code="NFO", order_id=order_id) 126 | status = order_detail["Success"][0]["status"] 127 | if status == "Executed": 128 | return order_detail 129 | time.sleep(1) 130 | 131 | return None 132 | 133 | 134 | def calculate_pnl(initial_price, current_price): 135 | pnl = (current_price - initial_price) * quantity 136 | return pnl 137 | 138 | def monitor_strategy(): 139 | time.sleep(1) 140 | global running 141 | initial_price = None 142 | cumulative_pnl = 0 143 | trailing_stop_loss = None 144 | 145 | option = options_basket[0] 146 | 147 | while running: 148 | try: 149 | current_time = datetime.now().time() 150 | if current_time >= end_time: 151 | logger.info(f"End time reached") 152 | break 153 | 154 | with last_price_tick_lock: 155 | if last_price_tick is None: 156 | continue 157 | current_price = last_price_tick 158 | 159 | if initial_price is None: 160 | order_detail = place_orders(option) 161 | if order_detail: 162 | status = order_detail["Success"][0]["status"] 163 | logger.info(f"status:{status}") 164 | if status == "Executed": 165 | initial_price = float(order_detail["Success"][0]["average_price"]) 166 | logger.info(f"Initial Price:{initial_price}") 167 | trailing_stop_loss = TrailingStopLoss(initial_price, trailing_percentage) 168 | logger.info(f"Trailing Stoploss:{trailing_stop_loss}") 169 | 170 | if trailing_stop_loss: 171 | 172 | trailing_stop = trailing_stop_loss.update_price(current_price) 173 | cumulative_pnl = calculate_pnl(initial_price, current_price) 174 | 175 | logger.info(f"Current Price: {current_price}, Trailing Stop: {trailing_stop}, PnL: {cumulative_pnl}") 176 | 177 | if trailing_stop_loss.should_sell(current_price): 178 | logger.info(f"Trailing stop hit, selling at price: {current_price}") 179 | # Execute sell logic here 180 | # breeze.place_order(stock_code=option["stock_code"], 181 | # exchange_code="NFO", 182 | # product="options", 183 | # action="sell", 184 | # order_type="market", 185 | # stoploss="", 186 | # quantity="25", 187 | # price="", 188 | # validity="day", 189 | # validity_date="2024-07-03T06:00:00.000Z", 190 | # disclosed_quantity="0", 191 | # expiry_date=option["expiry_date"], 192 | # right=option["right"], 193 | # strike_price=option["strike_price"]) 194 | break 195 | 196 | if cumulative_pnl <= -max_loss: 197 | logger.info(f"Max loss reached, exiting all positions at price: {current_price}") 198 | # Execute exit logic here 199 | # breeze.place_order(stock_code=option["stock_code"], 200 | # exchange_code="NFO", 201 | # product="options", 202 | # action="sell", 203 | # order_type="market", 204 | # stoploss="", 205 | # quantity="25", 206 | # price="", 207 | # validity="day", 208 | # validity_date="2024-07-03T06:00:00.000Z", 209 | # disclosed_quantity="0", 210 | # expiry_date=option["expiry_date"], 211 | # right=option["right"], 212 | # strike_price=option["strike_price"]) 213 | break 214 | 215 | if cumulative_pnl >= max_profit: 216 | logger.info(f"Max profit reached, exiting all positions at price: {current_price}") 217 | # Execute exit logic here 218 | # breeze.place_order(stock_code=option["stock_code"], 219 | # exchange_code="NFO", 220 | # product="options", 221 | # action="sell", 222 | # order_type="market", 223 | # stoploss="", 224 | # quantity="25", 225 | # price="", 226 | # validity="day", 227 | # validity_date="2024-07-03T06:00:00.000Z", 228 | # disclosed_quantity="0", 229 | # expiry_date=option["expiry_date"], 230 | # right=option["right"], 231 | # strike_price=option["strike_price"]) 232 | break 233 | 234 | except KeyboardInterrupt: 235 | print("Exiting") 236 | running = False 237 | except Exception as ex: 238 | print(str(ex)) 239 | running = False 240 | 241 | 242 | # Start monitoring strategy 243 | monitor_strategy() --------------------------------------------------------------------------------