├── .gitignore ├── README.md ├── data └── userdata.csv ├── fyers_integration ├── README ├── __init__.py ├── auth │ ├── __init__.py │ ├── auth_server.py │ └── json_util.py ├── e_strategy.py ├── requirements.txt ├── run.py ├── sample │ ├── __init__.py │ ├── auth.py │ ├── auth_server_2.py │ ├── quote.py │ ├── run.py │ ├── test.py │ └── web_socket.py ├── single_run.py ├── strategy.py └── util.py ├── indicators ├── ATR.py ├── EMA.py ├── MACD.py ├── MFI.py ├── RSI.py ├── SuperTrend.py ├── VWAP.py └── __init__.py ├── log ├── 2022-07-24.txt ├── 2022-07-27.txt ├── 2022-08-02.txt ├── 2023-03-23.txt └── pycharm_log.txt ├── main.py ├── requirements.txt └── zerodha ├── README.md ├── __init__.py ├── backtest.py ├── ema_crossover.py ├── example ├── historical_data_test.py └── simple.py ├── modules ├── __init__.py ├── auth.py └── historical_data.py ├── setup.py ├── stock_screener.py └── supertrend_strategy.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # Csv files 6 | *.csv 7 | 8 | # Distribution / packaging 9 | .Python 10 | dev/ 11 | data/ 12 | 13 | # Vscode 14 | .vscode 15 | 16 | # Ignore IntelliJ IDEA project files 17 | .idea/ 18 | *.iml 19 | *.ipr 20 | *.iws 21 | 22 | # User-specific files 23 | .idea/workspace.xml 24 | .idea/tasks.xml 25 | .idea/dictionaries 26 | .idea/libraries 27 | .idea/vcs.xml 28 | 29 | # Avoid ignoring Android Studio / WebStorm libraries 30 | !.idea/libraries/ 31 | 32 | # Ignore run/debug configurations 33 | .idea/**/runConfigurations/*.xml 34 | 35 | # IDE and configuration files 36 | .context/ 37 | .cursorrules 38 | .idea/ 39 | context.yaml 40 | 41 | # API credentials 42 | data/userdata.csv 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithmic Trading Platform 2 | 3 | A Python-based algorithmic trading platform that integrates with Zerodha for automated trading strategies. The platform provides a comprehensive set of technical indicators and backtesting capabilities. 4 | 5 | ## 🚀 Quick Start 6 | 7 | 1. Clone the repository: 8 | ```bash 9 | git clone https://github.com/yourusername/algotrading.git 10 | cd algotrading 11 | ``` 12 | 13 | 2. Set up the environment: 14 | ```bash 15 | python -m venv venv 16 | source venv/bin/activate # On Windows: venv\Scripts\activate 17 | pip install -r requirements.txt 18 | ``` 19 | 20 | 3. Configure Zerodha credentials and trading parameters 21 | 22 | ## 📊 Technical Indicators 23 | 24 | The platform includes the following technical indicators: 25 | 26 | | Indicator | Description | Implementation | 27 | |-----------|-------------|----------------| 28 | | EMA | Exponential Moving Average | `indicators/EMA.py` | 29 | | MACD | Moving Average Convergence Divergence | `indicators/MACD.py` | 30 | | RSI | Relative Strength Index | `indicators/RSI.py` | 31 | | ATR | Average True Range | `indicators/ATR.py` | 32 | | MFI | Money Flow Index | `indicators/MFI.py` | 33 | | SuperTrend | Trend-following indicator | `indicators/SuperTrend.py` | 34 | | VWAP | Volume Weighted Average Price | `indicators/VWAP.py` | 35 | 36 | ## 📁 Project Structure 37 | 38 | ``` 39 | algotrading/ 40 | ├── data/ # Data storage and configuration 41 | ├── indicators/ # Technical analysis indicators 42 | │ ├── ATR.py # Average True Range 43 | │ ├── EMA.py # Exponential Moving Average 44 | │ ├── MACD.py # Moving Average Convergence Divergence 45 | │ ├── MFI.py # Money Flow Index 46 | │ ├── RSI.py # Relative Strength Index 47 | │ ├── SuperTrend.py # SuperTrend indicator 48 | │ └── VWAP.py # Volume Weighted Average Price 49 | ├── zerodha/ # Zerodha trading integration 50 | │ ├── backtest.py # Backtesting functionality 51 | │ ├── setup.py # Trading setup and configuration 52 | │ └── ema_crossover.py # EMA Crossover strategy 53 | └── requirements.txt # Python dependencies 54 | ``` 55 | 56 | ## 💻 Usage 57 | 58 | ### Running a Strategy 59 | ```python 60 | from zerodha import setup 61 | from indicators import RSI, MACD 62 | 63 | # Initialize trading setup 64 | trading_setup = setup.initialize() 65 | 66 | # Example: EMA Crossover Strategy 67 | from zerodha.ema_crossover import EMACrossover 68 | strategy = EMACrossover() 69 | strategy.run() 70 | ``` 71 | 72 | ### Backtesting 73 | ```python 74 | from zerodha import backtest 75 | 76 | # Run backtest on historical data 77 | backtest.run(strategy, start_date='2023-01-01', end_date='2023-12-31') 78 | ``` 79 | 80 | ## 🛠 Development 81 | 82 | ### Adding New Indicators 83 | 1. Create a new file in `indicators/` 84 | 2. Follow the existing pattern: 85 | - Use type hints 86 | - Add comprehensive docstrings 87 | - Include error handling 88 | 3. Add tests in `tests/` 89 | 90 | ### Testing 91 | ```bash 92 | pytest 93 | ``` 94 | 95 | ## 📝 License 96 | 97 | MIT License - See [LICENSE](LICENSE) for details. 98 | 99 | ## ⚠️ Disclaimer 100 | 101 | This software is for educational purposes only. Use it at your own risk. The authors and contributors are not responsible for any financial losses incurred through the use of this software. -------------------------------------------------------------------------------- /data/userdata.csv: -------------------------------------------------------------------------------- 1 | user_name,api_key,api_secret,access_token,token_req_date,user_id,public_token 2 | ,,,,,, 3 | -------------------------------------------------------------------------------- /fyers_integration/README: -------------------------------------------------------------------------------- 1 | Activate app (if created new)[OPTIONAL] 2 | https://api-t1.fyers.in/api/v3/generate-authcode?client_id=Q9494VAZSX-100&redirect_uri=http://127.0.0.1:27070/generate-authcode&response_type=code&state=ABCD 3 | 4 | Run Auth Server 5 | Step 1 : Update client id, redirect uri, & secret in data/token.json [OPTIONAL] 6 | Step 2 : Run auth/auth_server.py 7 | Step 3 : Open in browser http://127.0.0.1:27070/login 8 | 9 | For Token Refresh 10 | Open in browser http://127.0.0.1:27070/refresh-token 11 | 12 | -------------------------------------------------------------------------------- /fyers_integration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debanshur/algotrading/4e6fe65f8d5091bcad51437c3641c84d91bdc47f/fyers_integration/__init__.py -------------------------------------------------------------------------------- /fyers_integration/auth/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debanshur/algotrading/4e6fe65f8d5091bcad51437c3641c84d91bdc47f/fyers_integration/auth/__init__.py -------------------------------------------------------------------------------- /fyers_integration/auth/auth_server.py: -------------------------------------------------------------------------------- 1 | import webbrowser 2 | 3 | import requests 4 | 5 | from json_util import get_json_value, update_json_key 6 | from datetime import datetime 7 | 8 | from flask import Flask, json, request 9 | 10 | from fyers_apiv3 import fyersModel 11 | 12 | app = Flask(__name__) 13 | 14 | 15 | @app.route('/', methods=['GET']) 16 | def ping(): 17 | return "Welcome to Algotrading" 18 | 19 | 20 | @app.route('/login', methods=['GET']) 21 | def login(): 22 | client_id = get_json_value('client_id') 23 | redirect_uri = get_json_value('redirect_uri') 24 | state = get_json_value('state') 25 | 26 | # Construct the URL 27 | base_url = "https://api-t1.fyers.in/api/v3/generate-authcode" 28 | response_type = "code" 29 | 30 | generated_url = f"{base_url}?client_id={client_id}&redirect_uri={redirect_uri}&response_type={response_type}&state={state}" 31 | 32 | print(generated_url) 33 | 34 | # Open the generated URL in the default web browser 35 | webbrowser.open(generated_url) 36 | return generated_url 37 | 38 | 39 | @app.route('/generate-authcode', methods=['GET']) 40 | def get_auth_code(): 41 | args = request.args 42 | auth_code = args["auth_code"] 43 | 44 | if args['s'] == 'ok' and (args['state'] == get_json_value('state')): 45 | update_json_key('auth_code', auth_code) 46 | update_json_key('update', '1') # <--- add `id` value. 47 | update_json_key('time', datetime.now().strftime('%Y-%m-%d %H:%M:%S')) 48 | 49 | status = generate_token() 50 | if status != 'error': 51 | return "AuthCode & Access Token Generated Successfully. ##### You can close this #####" 52 | 53 | return "error" 54 | 55 | 56 | @app.route('/refresh-token', methods=['GET']) 57 | def refresh_token(): 58 | client_id = get_json_value('client_id') 59 | secret_key = get_json_value('secret_key') 60 | refresh_token = get_json_value('refresh_token') 61 | pin = get_json_value('pin') 62 | 63 | grant_type = "refresh_token" 64 | url = 'https://api-t1.fyers.in/api/v3/validate-refresh-token' 65 | 66 | session = fyersModel.SessionModel( 67 | client_id=client_id, 68 | secret_key=secret_key, 69 | ) 70 | 71 | headers = { 72 | 'Content-Type': 'application/json', 73 | } 74 | 75 | data = { 76 | "grant_type": grant_type, 77 | "appIdHash": session.get_hash().hexdigest(), 78 | "refresh_token": refresh_token, 79 | "pin": pin 80 | } 81 | 82 | 83 | response = requests.post(url, headers=headers, data=json.dumps(data)) 84 | 85 | print(response) 86 | if response.status_code == 200: 87 | response_data = response.json() 88 | update_json_key('access_token', response_data.get('access_token')) 89 | return "Token Refresh Successful" 90 | else: 91 | return "error" 92 | 93 | 94 | 95 | def generate_token(): 96 | client_id = get_json_value('client_id') 97 | secret_key = get_json_value('secret_key') 98 | redirect_uri = get_json_value('redirect_uri') 99 | response_type = "code" 100 | grant_type = "authorization_code" 101 | 102 | auth_code = get_json_value('auth_code') 103 | 104 | # Create a session object to handle the Fyers API authentication and token generation 105 | session = fyersModel.SessionModel( 106 | client_id=client_id, 107 | secret_key=secret_key, 108 | redirect_uri=redirect_uri, 109 | response_type=response_type, 110 | grant_type=grant_type 111 | ) 112 | 113 | session.set_token(auth_code) 114 | response = session.generate_token() 115 | print(response) 116 | if response['s'] == 'ok': 117 | update_json_key('access_token', response['access_token']) 118 | update_json_key('refresh_token', response['refresh_token']) 119 | return "Access Token Generation Successful" 120 | else: 121 | return "error" 122 | 123 | 124 | app.run(host='localhost', port=27070) 125 | -------------------------------------------------------------------------------- /fyers_integration/auth/json_util.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def get_json_value(key): 5 | with open('/Users/debanshu.rout/repo/external/algotrading/fyers_integration/data/token.json', 'r+') as f: 6 | data = json.load(f) 7 | return data[key] 8 | 9 | 10 | def update_json_key(key, value): 11 | with open('/Users/debanshu.rout/repo/external/algotrading/fyers_integration/data/token.json', 'r+') as f: 12 | data = json.load(f) 13 | data[key] = value # <--- add `id` value. 14 | f.seek(0) # <--- should reset file position to the beginning. 15 | json.dump(data, f, indent=4) 16 | f.truncate() 17 | -------------------------------------------------------------------------------- /fyers_integration/e_strategy.py: -------------------------------------------------------------------------------- 1 | import time 2 | from math import floor, ceil 3 | import pandas as pd 4 | import requests 5 | from fyers_api import accessToken, fyersModel 6 | 7 | 8 | 9 | 10 | from fyers_integration.util import get_historical_data 11 | from indicators import SuperTrend, EMA, MACD, RSI, MFI, VWAP 12 | import datetime 13 | 14 | from auth.json_util import get_json_value 15 | 16 | # pd.set_option('display.max_rows', None) 17 | # pd.set_option('display.max_columns', None) 18 | 19 | 20 | access_token = get_json_value('access_token') 21 | client_id = "TC8P3VH4H7-100" 22 | fyers = fyersModel.FyersModel(token=access_token, is_async=False, client_id=client_id, log_path="/Users/debanshu.rout/repo/external/algotrading/log") 23 | #print(fyers.get_profile()['data']['name']) 24 | 25 | run_count = 0 26 | exit_count = 0 27 | supertrend_period = 10 28 | supertrend_multiplier=3 29 | orderslist = {} 30 | time_frame = "10" 31 | one_hour_rsi = 50 32 | 33 | stockList = ["NSE:RELIANCE-EQ", "NSE:SBIN-EQ"] 34 | 35 | 36 | def compute_data(stock): 37 | global one_hour_rsi 38 | #enddate = datetime.datetime(2020, 5, 4, 15,30,0,0) 39 | end_date = datetime.datetime.today() 40 | start_date = end_date - datetime.timedelta(5) 41 | 42 | try: 43 | df = get_historical_data(fyers, stock, time_frame, start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d")) 44 | 45 | df = EMA.calc(df, 'close', 'ema_5', 5) 46 | #df = EMA.calc(df, 'close', 'ema_20', 20) 47 | #df = MACD.calc(df) 48 | #df = MFI.calc(df) 49 | #df = VWAP.calc(df) 50 | 51 | #df = SuperTrend.calc(df, supertrend_period, supertrend_multiplier) 52 | #rsi = get_historical_data(fyers, stock, "60", start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d")) 53 | #rsi = RSI.calc(rsi) 54 | #one_hour_rsi = rsi.RSI_14.values[-1] 55 | 56 | print(df) 57 | except Exception as e: 58 | print("******* ERROR Computing Historical Data ********", e) 59 | return df 60 | 61 | 62 | # 63 | # ## Quotes 64 | # 65 | # data = {"symbols": "NSE:SBIN-EQ"} 66 | # print(fyers.quotes(data)) 67 | # # 68 | # # ## Market Depth 69 | # # 70 | # data = {"symbol": "NSE:SBIN-EQ", "ohlcv_flag": "1"} 71 | # print(fyers.depth(data)) 72 | 73 | def check_volume(open, volume): 74 | if open <= 400 and volume >= 1000000: 75 | return True 76 | elif open > 400 and open <=700 and volume >= 500000: 77 | return True 78 | elif open > 700 and open <=1000 and volume >= 300000: 79 | return True 80 | elif open > 1000 and volume >= 100000: 81 | return True 82 | else: 83 | return False 84 | 85 | def run_strategy(): 86 | global orderslist 87 | global one_hour_rsi 88 | for i in range(0, len(stockList)): 89 | if stockList[i] in orderslist: 90 | continue 91 | try: 92 | histdata = compute_data(stockList[i]) 93 | # print(histdata) 94 | super_trend = histdata.STX.values 95 | 96 | high = histdata.high.values[-2] 97 | low = histdata.low.values[-2] 98 | macd = histdata.hist_12_26_9.values[-2] 99 | stoploss_buy = histdata.ST.values[-2] # histdata.low.values[-3] # third last candle as stoploss 100 | stoploss_sell = histdata.ST.values[-2] # third last candle as stoploss 101 | 102 | volume = histdata.volume.values[-2] 103 | has_volume = check_volume(histdata.open.values[-2], volume) 104 | 105 | # if stoploss_buy > lastclose * 0.996: 106 | # stoploss_buy = lastclose * 0.996 # minimum stoploss as 0.4 % 107 | 108 | # if stoploss_sell < lastclose * 1.004: 109 | # stoploss_sell = lastclose * 1.004 # minimum stoploss as 0.4 % 110 | # print("lastclose",lastclose) 111 | # print("stoploss abs",stoploss) 112 | 113 | print(stockList[i], high, low, super_trend[-4:], round(macd, 4), int(one_hour_rsi), volume) 114 | 115 | if not has_volume: 116 | print("Sorry, Volume is low") 117 | continue 118 | 119 | if super_trend[-1] == 'up' and super_trend[-2] == 'up' and super_trend[-3] == 'down' and super_trend[ 120 | -4] == 'down' \ 121 | and macd > 0 and one_hour_rsi > 50: 122 | 123 | stoploss_buy = high - stoploss_buy 124 | # print("stoploss delta", stoploss) 125 | 126 | quantity = 1 # floor(max(1, (risk_per_trade/stoploss_buy))) 127 | target = stoploss_buy * 2 # risk reward as 3 128 | 129 | price = high + (0.05 * high) / 100 130 | # print(price) 131 | # price = int(ceil(price)) 132 | price = int(100 * (ceil(price / 0.05) * 0.05)) / 100 133 | stoploss_buy = int(100 * (floor(stoploss_buy / 0.05) * 0.05)) / 100 134 | quantity = int(quantity) 135 | target = int(100 * (floor(target / 0.05) * 0.05)) / 100 136 | 137 | #orderslist[stockList[i]] = price - stoploss_buy 138 | # print(price) 139 | 140 | data = { 141 | "symbol": stockList[i], 142 | "qty": quantity, 143 | "type": 3, 144 | "side": 1, 145 | "productType": "INTRADAY", 146 | "limitPrice": 0, 147 | "stopPrice": stoploss_buy, 148 | "validity": "DAY", 149 | "disclosedQty": 0, 150 | "offlineOrder": "False", 151 | "stopLoss": 0, 152 | "takeProfit": 0 153 | } 154 | 155 | print(fyers.place_order(data)) 156 | 157 | print(" Order : ", "BUY", stockList[i], "high : ", high, "quantity:", quantity, "price:", 158 | price, datetime.datetime.now()) 159 | 160 | if super_trend[-1] == 'down' and super_trend[-2] == 'down' and super_trend[-3] == 'up' and super_trend[ 161 | -4] == 'up' \ 162 | and macd < 0 and one_hour_rsi < 50: 163 | 164 | if not has_volume: 165 | print("Sorry, Volume is low") 166 | # continue 167 | 168 | stoploss_sell = stoploss_sell - low 169 | # print("stoploss delta", stoploss) 170 | 171 | quantity = 1 # floor(max(1, (risk_per_trade/stoploss_sell))) 172 | target = stoploss_sell * 2 # risk reward as 3 173 | 174 | price = low - (0.05 * low) / 100 175 | # price = int(floor(price)) 176 | price = int(100 * (floor(price / 0.05) * 0.05)) / 100 177 | stoploss_sell = int(100 * (floor(stoploss_sell / 0.05) * 0.05)) / 100 178 | quantity = int(quantity) 179 | target = int(100 * (floor(target / 0.05) * 0.05)) / 100 180 | 181 | #orderslist[stockList[i]] = price + stoploss_sell 182 | 183 | data = { 184 | "symbol": stockList[i], 185 | "qty": quantity, 186 | "type": 3, 187 | "side": -1, 188 | "productType": "INTRADAY", 189 | "limitPrice": 0, 190 | "stopPrice": stoploss_sell, 191 | "validity": "DAY", 192 | "disclosedQty": 0, 193 | "offlineOrder": "False", 194 | "stopLoss": 0, 195 | "takeProfit": 0 196 | } 197 | 198 | print(fyers.place_order(data)) 199 | 200 | print(" Order : ", "SELL", stockList[i], "low : ", low, "quantity:", quantity, "price:", price, 201 | datetime.datetime.now()) 202 | 203 | except Exception as e: 204 | print(e) 205 | 206 | 207 | def check_order_status(): 208 | global orderslist 209 | df = pd.DataFrame(columns=['order_id', 'status', 'tradingsymbol', 'instrument_token', 'transaction_type', 'quantity']) 210 | try: 211 | data = fyers.get_orders() 212 | df = pd.DataFrame.from_dict(data, orient='columns', dtype=None) 213 | #print(df) 214 | if not df.empty: 215 | df = df[['order_id', 'status', 'tradingsymbol', 'instrument_token', 'transaction_type', 'quantity']] 216 | except Exception as e: 217 | print("******* ERROR Fetching Historical Data ********", e) 218 | for ind in df.index: 219 | token = df['tradingsymbol'][ind] 220 | orderslist[token] = "0" 221 | #print(df['tradingsymbol'][ind], df['transaction_type'][ind]) 222 | 223 | print(orderslist) 224 | return df 225 | 226 | 227 | def run(): 228 | global run_count 229 | global exit_count 230 | trade_start_time = int(11) * 60 + int(25) # specify in int (hr) and int (min) format 231 | order_end_time = int(14) * 60 + int(55) # do not place fresh order 232 | square_off_time = int(15) * 60 + int(15) # square off all open positions 233 | prev_time = trade_start_time 234 | schedule_interval = 60 # run at every 1 min 235 | #runcount = 0 236 | #check_order_status() 237 | 238 | next_time = trade_start_time 239 | 240 | # set next_time to the nearest 5th minute of current time 241 | if (datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) % 10 == 0: 242 | next_time = datetime.datetime.now().hour * 60 + \ 243 | ((datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) + 5) 244 | 245 | else: 246 | next_time = datetime.datetime.now().hour * 60 + \ 247 | (datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) 248 | 249 | while True: 250 | curr_time = datetime.datetime.now().hour * 60 + datetime.datetime.now().minute 251 | #check_order_status() 252 | if curr_time >= square_off_time: 253 | #close_positions() 254 | print("***** Trading Day closed *****") 255 | break 256 | if curr_time >= trade_start_time: 257 | if next_time <= curr_time < order_end_time: 258 | next_time = curr_time + 10 259 | time.sleep(2) 260 | print("\n\n {} Run Count : Time - {} ".format(run_count, datetime.datetime.now())) 261 | if run_count >= 0: 262 | try: 263 | run_strategy() 264 | except Exception as e: 265 | print("******* Run Error *********", e) 266 | run_count = run_count + 1 267 | 268 | if curr_time >= order_end_time and curr_time >= next_time: 269 | next_time = curr_time + 5 270 | time.sleep(2) 271 | print("\n\n {} Exit Count : Time - {} ".format(exit_count, datetime.datetime.now())) 272 | if exit_count >= 0: 273 | try: 274 | check_order_status() 275 | except Exception as e: 276 | print("******* Run Error *********", e) 277 | exit_count = exit_count + 1 278 | 279 | else: 280 | print('****** Waiting ********', datetime.datetime.now()) 281 | time.sleep(1) 282 | 283 | 284 | if __name__ == '__main__': 285 | #run() 286 | compute_data('NSE:SBIN-EQ') 287 | #print(fyers.tradebook()) ## This will provide all the trade related information 288 | 289 | #print(fyers.orderbook()) ## This will provide the user with all the order realted information 290 | 291 | #print(fyers.positions()) -------------------------------------------------------------------------------- /fyers_integration/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2021.10.8 2 | charset-normalizer==2.0.12 3 | click==8.1.3 4 | Flask==2.1.3 5 | idna==3.3 6 | importlib-metadata==4.12.0 7 | itsdangerous==2.1.2 8 | Jinja2==3.1.2 9 | MarkupSafe==2.1.1 10 | numpy==1.22.3 11 | pandas==1.4.2 12 | python-dateutil==2.8.2 13 | pytz==2022.1 14 | requests==2.27.1 15 | six==1.16.0 16 | urllib3==1.26.9 17 | Werkzeug==2.1.2 18 | zipp==3.8.1 19 | -------------------------------------------------------------------------------- /fyers_integration/run.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from fyers_api import accessToken, fyersModel 3 | 4 | from auth.json_util import get_json_value 5 | access_token = get_json_value('access_token') 6 | client_id = "TC8P3VH4H7-100" 7 | 8 | fyers = fyersModel.FyersModel(token=access_token, is_async=False, client_id=client_id, log_path="/Users/debanshu.rout/repo/external/algotrading/log") 9 | 10 | ### After this point you can call the relevant apis and get started with 11 | 12 | #################################################################################################################### 13 | """ 14 | 1. User Apis : This includes (Profile,Funds,Holdings) 15 | """ 16 | print("---- GET PROFILE----") 17 | print(fyers.get_profile()) ## This will provide us with the user related data 18 | 19 | print("---- GET FUNDS----") 20 | print(fyers.funds()) ## This will provide us with the funds the user has 21 | 22 | print("---- GET HOLDINGS----") 23 | print(fyers.holdings()) ## This will provide the available holdings the user has 24 | 25 | ######################################################################################################################## 26 | 27 | """ 28 | 2. Transaction Apis : This includes (Tradebook,Orderbook,Positions) 29 | """ 30 | 31 | print("---- GET TRADEBOOK----") 32 | print(fyers.tradebook()) ## This will provide all the trade related information 33 | 34 | print("---- GET ORDERBOOK----") 35 | print(fyers.orderbook()) ## This will provide the user with all the order realted information 36 | 37 | print("---- GET POSITIONS----") 38 | print(fyers.positions()) ## This will provide the user with all the positions the user has on his end 39 | 40 | ###################################################################################################################### 41 | 42 | """ 43 | 3. Order Placement : This Apis helps to place order. 44 | There are two ways to place order 45 | a. single order : wherein you can fire one order at a time 46 | b. multi order : this is used to place a basket of order but the basket size can max be 10 symbols 47 | """ 48 | 49 | ## SINGLE ORDER 50 | 51 | data = { 52 | "symbol": "NSE:SBIN-EQ", 53 | "qty": 1, 54 | "type": 2, 55 | "side": 1, 56 | "productType": "INTRADAY", 57 | "limitPrice": 0, 58 | "stopPrice": 0, 59 | "validity": "DAY", 60 | "disclosedQty": 0, 61 | "offlineOrder": "False", 62 | "stopLoss": 0, 63 | "takeProfit": 0 64 | } ## This is a samplea example to place a limit order you can make the further changes based on your requriements 65 | 66 | print("---- GET PLACE ORDER----") 67 | print(fyers.place_order(data)) 68 | 69 | ## MULTI ORDER 70 | 71 | data = [{"symbol": "NSE:SBIN-EQ", 72 | "qty": 1, 73 | "type": 1, 74 | "side": 1, 75 | "productType": "INTRADAY", 76 | "limitPrice": 61050, 77 | "stopPrice": 0, 78 | "disclosedQty": 0, 79 | "validity": "DAY", 80 | "offlineOrder": "False", 81 | "stopLoss": 0, 82 | "takeProfit": 0 83 | }, 84 | { 85 | "symbol": "NSE:HDFC-EQ", 86 | "qty": 1, 87 | "type": 2, 88 | "side": 1, 89 | "productType": "INTRADAY", 90 | "limitPrice": 0, 91 | "stopPrice": 0, 92 | "disclosedQty": 0, 93 | "validity": "DAY", 94 | "offlineOrder": "False", 95 | "stopLoss": 0, 96 | "takeProfit": 0 97 | }] ### This takes input as a list containing multiple single order data into it and the execution of the orders goes in the same format as mentioned. 98 | 99 | #print(fyers.place_basket_orders(data)) 100 | 101 | ################################################################################################################### 102 | 103 | """ 104 | 4. Other Transaction : This includes (modify_order,exit_position,cancel_order,convert_positions) 105 | """ 106 | 107 | ## Modify_order request 108 | data = { 109 | "id": 7574657627567, 110 | "type": 1, 111 | "limitPrice": 61049, 112 | "qty": 1 113 | } 114 | 115 | print("---- GET MODIFY ORDER----") 116 | print(fyers.modify_order(data)) 117 | 118 | ## Modify Multi Order 119 | 120 | data = [ 121 | {"id": 8102710298291, 122 | "type": 1, 123 | "limitPrice": 61049, 124 | "qty": 0 125 | }, 126 | { 127 | "id": 8102710298292, 128 | "type": 1, 129 | "limitPrice": 61049, 130 | "qty": 1 131 | }] 132 | 133 | #print(fyers.modify_basket_orders(data)) 134 | 135 | ### Cancel_order 136 | data = {"id": '808058117761'} 137 | 138 | print("---- GET CANCEL ORDER----") 139 | print(fyers.cancel_order(data)) 140 | 141 | ### cancel_multi_order 142 | data = [ 143 | { 144 | "id": '808058117761' 145 | }, 146 | { 147 | "id": '808058117762' 148 | }] 149 | 150 | #print(fyers.cancel_basket_orders(data)) 151 | 152 | ### Exit Position 153 | data = { 154 | "id": "NSE:SBIN-EQ-INTRADAY" 155 | } 156 | 157 | print("---- GET EXIT ORDER----") 158 | print(fyers.exit_positions(data)) 159 | 160 | ### Convert Position 161 | 162 | data = { 163 | "symbol": "MCX:SILVERMIC20NOVFUT", 164 | "positionSide": 1, 165 | "convertQty": 1, 166 | "convertFrom": "INTRADAY", 167 | "convertTo": "CNC" 168 | } 169 | 170 | #print(fyers.convert_position(data)) 171 | 172 | ################################################################################################################# 173 | 174 | """ 175 | DATA APIS : This includes following Apis(History,Quotes,MarketDepth) 176 | """ 177 | 178 | ## Historical Data 179 | 180 | data = {"symbol": "NSE:SBIN-EQ", "resolution": "D", "date_format": "0", "range_from": "1622097600", 181 | "range_to": "1622097685", "cont_flag": "1"} 182 | 183 | print("---- GET HISTORY DATA----") 184 | print(fyers.history(data)) 185 | 186 | ## Quotes 187 | 188 | data = {"symbols": "NSE:SBIN-EQ"} 189 | print("---- GET QUOTES DATA----") 190 | print(fyers.quotes(data)) 191 | 192 | ## Market Depth 193 | 194 | data = {"symbol": "NSE:SBIN-EQ", "ohlcv_flag": "1"} 195 | print("---- GET MARKET DEPTH DATA----") 196 | print(fyers.depth(data)) 197 | -------------------------------------------------------------------------------- /fyers_integration/sample/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debanshur/algotrading/4e6fe65f8d5091bcad51437c3641c84d91bdc47f/fyers_integration/sample/__init__.py -------------------------------------------------------------------------------- /fyers_integration/sample/auth.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import requests 4 | from fyers_api import accessToken 5 | from fyers_api import fyersModel 6 | import webbrowser 7 | 8 | """ 9 | In order to get started with Fyers API we would like you to do the following things first. 10 | 1. Checkout our API docs : https://myapi.fyers.in/docs/ 11 | 2. Create an APP using our API dashboard : https://myapi.fyers.in/dashboard/ 12 | Once you have created an APP you can start using the below SDK 13 | """ 14 | 15 | #### Generate an authcode and then make a request to generate an accessToken (Login Flow) 16 | 17 | """ 18 | 1. Input parameters 19 | """ 20 | 21 | #PASS = Fyers@12345 22 | #redirect_uri = "https://localhost:20202" ## redircet_uri you entered while creating APP. 23 | redirect_uri = "https://trade.fyers.in/api-login/redirect-uri/index.html" 24 | client_id = "9UZA9YK19H-100" ## Client_id here refers to APP_ID of the created app 25 | secret_key = "22IP9FRBOT" ## app_secret key which you got after creating the app 26 | grant_type = "authorization_code" ## The grant_type always has to be "authorization_code" 27 | response_type = "code" ## The response_type always has to be "code" 28 | state = "samplea" ## The state field here acts as a session manager. you will be sent with the state field after successfull generation of auth_code 29 | 30 | ### Connect to the sessionModel object here with the required input parameters 31 | appSession = accessToken.SessionModel(client_id=client_id, redirect_uri=redirect_uri, response_type=response_type, 32 | state=state, secret_key=secret_key, grant_type=grant_type) 33 | 34 | 35 | 36 | ### Make a request to generate_authcode object this will return a login url which you need to open in your browser from where you can get the generated auth_code 37 | generateTokenUrl = appSession.generate_authcode() 38 | 39 | """There are two method to get the Login url if you are not automating the login flow 40 | 1. Just by printing the variable name 41 | 2. There is a library named as webbrowser which will then open the url for you without the hasel of copy pasting 42 | both the methods are mentioned below""" 43 | print((generateTokenUrl)) 44 | webbrowser.open(generateTokenUrl, new=1) 45 | 46 | #eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkubG9naW4uZnllcnMuaW4iLCJpYXQiOjE2NTYxNDU3MzAsImV4cCI6MTY1NjE3NTczMCwibmJmIjoxNjU2MTQ1MTMwLCJhdWQiOlsieDowIiwieDoxIiwieDoyIiwiZDoxIiwiZDoyIiwieDoxIiwieDowIl0sInN1YiI6ImF1dGhfY29kZSIsImRpc3BsYXlfbmFtZSI6IlhEMTE4NTAiLCJub25jZSI6IiIsImFwcF9pZCI6IjlVWkE5WUsxOUgiLCJ1dWlkIjoiNjlhNWQ1YWQ5NjEzNDk0ZTk4ZjUzMjVhZTk1NTBjNTciLCJpcEFkZHIiOiI0OS4zNy4xNjMuMTUxIiwic2NvcGUiOiIifQ.fCet3kjwSYkSE5ndkerIuVtgT0XQ2sad262rpxUGfFU 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /fyers_integration/sample/auth_server_2.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | from werkzeug import Request, Response, run_simple 3 | 4 | from fyers_integration.sample.auth import get_json_value, update_json_key 5 | 6 | q = [] 7 | 8 | def get_token() -> None: 9 | global q 10 | @Request.application 11 | def app(request: Request) -> Response: 12 | global q 13 | q = request.args 14 | return Response("", 204) 15 | 16 | run_simple("localhost", 27070, app) 17 | 18 | if __name__ == "__main__": 19 | p = multiprocessing.Process(target=get_token, args=()) 20 | p.start() 21 | print("waiting") 22 | token = q 23 | print(token) 24 | #wait till token updated -> maybe logged out 25 | #p.terminate() 26 | 27 | local_state = get_json_value('state') 28 | if(token['state'] == local_state): 29 | update_json_key('auth_code',token['auth_code']) 30 | p.terminate() 31 | 32 | 33 | # -------------------------------------------------------------------------------- /fyers_integration/sample/quote.py: -------------------------------------------------------------------------------- 1 | from fyers_api import fyersModel 2 | 3 | from fyers_integration.auth.json_util import get_json_value 4 | import time 5 | from datetime import datetime as dt 6 | 7 | 8 | def main(): 9 | client_id = get_json_value('client_id') 10 | access_token = get_json_value('access_token') 11 | 12 | fyers = fyersModel.FyersModel(client_id=client_id, token=access_token, 13 | log_path="/Users/debanshu.rout/repo/external/algotrading/fyers_integration/data") 14 | 15 | symbol = { 16 | "symbols": "NSE:SBIN-EQ" 17 | } 18 | symbol = { 19 | "symbols": "NSE:TATAMOTORS-EQ" 20 | } 21 | print("%s,%s,%s,%s,%s,%s" % ("TimeStamp", "Name", "Token", "LTP", "Bid", "Ask")) 22 | 23 | # for x in range(200): 24 | while 0 < 10: 25 | time.sleep(1) 26 | response = fyers.quotes(data=symbol) 27 | # print(response) 28 | if response is not None and response['s'] == 'ok': 29 | data = response['d'][0]['v'] 30 | ltp = data['lp'] 31 | ask = data['ask'] 32 | bid = data['bid'] 33 | token = data['fyToken'][-4:] 34 | name = data['short_name'] 35 | # t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(data['cmd']['t'])) 36 | t = dt.now().strftime('%Y-%m-%d %H:%M:%S') 37 | # print(data['cmd']['t']) 38 | print("%s,%s,%s,%.2f,%.2f,%.2f" % (t,name, token, ltp, bid, ask)) 39 | else: 40 | print(f"Error : {response}") 41 | 42 | 43 | if __name__ == '__main__': 44 | main() 45 | -------------------------------------------------------------------------------- /fyers_integration/sample/run.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from fyers_api import accessToken, fyersModel 3 | 4 | #redirect_uri = "https://localhost:20202" ## redircet_uri you entered while creating APP. 5 | from auth.util import get_json_value 6 | 7 | redirect_uri = "https://trade.fyers.in/api-login/redirect-uri/index.html" 8 | client_id = "9UZA9YK19H-100" ## Client_id here refers to APP_ID of the created app 9 | secret_key = "22IP9FRBOT" ## app_secret key which you got after creating the app 10 | grant_type = "authorization_code" ## The grant_type always has to be "authorization_code" 11 | response_type = "code" ## The response_type always has to be "code" 12 | state = "samplea" ## The state field here acts as a session manager. you will be sent with the state field after successfull generation of auth_code 13 | 14 | ### Connect to the sessionModel object here with the required input parameters 15 | appSession = accessToken.SessionModel(client_id=client_id, redirect_uri=redirect_uri, response_type=response_type, 16 | state=state, secret_key=secret_key, grant_type=grant_type) 17 | """ 18 | run the code firstly upto this after you generate the auth_code comment the above code and start executing the below code """ 19 | ########################################################################################################################## 20 | 21 | ### After succesfull login the user can copy the generated auth_code over here and make the request to generate the accessToken 22 | 23 | #response = appSession.generate_authcode() 24 | 25 | 26 | auth_code = get_json_value('auth_code') 27 | 28 | appSession.set_token(auth_code) 29 | response = appSession.generate_token() 30 | 31 | ### There can be two cases over here you can successfully get the acccessToken over the request or you might get some error over here. so to avoid that have this in try except block 32 | try: 33 | access_token = response["access_token"] 34 | except Exception as e: 35 | print(e, 36 | response) ## This will help you in debugging then and there itself like what was the error and also you would be able to see the value you got in response variable. instead of getting key_error for unsuccessfull response. 37 | 38 | ## Once you have generated accessToken now we can call multiple trading related or data related apis after that in order to do so we need to first initialize the fyerModel object with all the requried params. 39 | """ 40 | fyerModel object takes following values as arguments 41 | 1. accessToken : this is the one which you received from above 42 | 2. client_id : this is basically the app_id for the particular app you logged into 43 | """ 44 | 45 | print("access_token:") 46 | print(access_token) 47 | 48 | fyers = fyersModel.FyersModel(token=access_token, is_async=False, client_id=client_id, log_path="/home/downloads/") 49 | 50 | ### After this point you can call the relevant apis and get started with 51 | 52 | #################################################################################################################### 53 | """ 54 | 1. User Apis : This includes (Profile,Funds,Holdings) 55 | """ 56 | 57 | print(fyers.get_profile()) ## This will provide us with the user related data 58 | 59 | print(fyers.funds()) ## This will provide us with the funds the user has 60 | 61 | print(fyers.holdings()) ## This will provide the available holdings the user has 62 | 63 | ######################################################################################################################## 64 | 65 | """ 66 | 2. Transaction Apis : This includes (Tradebook,Orderbook,Positions) 67 | """ 68 | 69 | print(fyers.tradebook()) ## This will provide all the trade related information 70 | 71 | print(fyers.orderbook()) ## This will provide the user with all the order realted information 72 | 73 | print(fyers.positions()) ## This will provide the user with all the positions the user has on his end 74 | 75 | ###################################################################################################################### 76 | 77 | """ 78 | 3. Order Placement : This Apis helps to place order. 79 | There are two ways to place order 80 | a. single order : wherein you can fire one order at a time 81 | b. multi order : this is used to place a basket of order but the basket size can max be 10 symbols 82 | """ 83 | 84 | ## SINGLE ORDER 85 | 86 | data = { 87 | "symbol": "NSE:ONGC-EQ", 88 | "qty": 1, 89 | "type": 1, 90 | "side": 1, 91 | "productType": "INTRADAY", 92 | "limitPrice": 0, 93 | "stopPrice": 0, 94 | "validity": "DAY", 95 | "disclosedQty": 0, 96 | "offlineOrder": "False", 97 | "stopLoss": 0, 98 | "takeProfit": 0 99 | } ## This is a samplea example to place a limit order you can make the further changes based on your requriements 100 | 101 | print(fyers.place_order(data)) 102 | 103 | ## MULTI ORDER 104 | 105 | data = [{"symbol": "NSE:SBIN-EQ", 106 | "qty": 1, 107 | "type": 1, 108 | "side": 1, 109 | "productType": "INTRADAY", 110 | "limitPrice": 61050, 111 | "stopPrice": 0, 112 | "disclosedQty": 0, 113 | "validity": "DAY", 114 | "offlineOrder": "False", 115 | "stopLoss": 0, 116 | "takeProfit": 0 117 | }, 118 | { 119 | "symbol": "NSE:HDFC-EQ", 120 | "qty": 1, 121 | "type": 2, 122 | "side": 1, 123 | "productType": "INTRADAY", 124 | "limitPrice": 0, 125 | "stopPrice": 0, 126 | "disclosedQty": 0, 127 | "validity": "DAY", 128 | "offlineOrder": "False", 129 | "stopLoss": 0, 130 | "takeProfit": 0 131 | }] ### This takes input as a list containing multiple single order data into it and the execution of the orders goes in the same format as mentioned. 132 | 133 | print(fyers.place_basket_orders(data)) 134 | 135 | ################################################################################################################### 136 | 137 | """ 138 | 4. Other Transaction : This includes (modify_order,exit_position,cancel_order,convert_positions) 139 | """ 140 | 141 | ## Modify_order request 142 | data = { 143 | "id": 7574657627567, 144 | "type": 1, 145 | "limitPrice": 61049, 146 | "qty": 1 147 | } 148 | 149 | print(fyers.modify_order(data)) 150 | 151 | ## Modify Multi Order 152 | 153 | data = [ 154 | {"id": 8102710298291, 155 | "type": 1, 156 | "limitPrice": 61049, 157 | "qty": 0 158 | }, 159 | { 160 | "id": 8102710298292, 161 | "type": 1, 162 | "limitPrice": 61049, 163 | "qty": 1 164 | }] 165 | 166 | print(fyers.modify_basket_orders(data)) 167 | 168 | ### Cancel_order 169 | data = {"id": '808058117761'} 170 | print(fyers.cancel_order(data)) 171 | 172 | ### cancel_multi_order 173 | data = [ 174 | { 175 | "id": '808058117761' 176 | }, 177 | { 178 | "id": '808058117762' 179 | }] 180 | 181 | print(fyers.cancel_basket_orders(data)) 182 | 183 | ### Exit Position 184 | data = { 185 | "id": "NSE:SBIN-EQ-INTRADAY" 186 | } 187 | 188 | print(fyers.exit_positions(data)) 189 | 190 | ### Convert Position 191 | 192 | data = { 193 | "symbol": "MCX:SILVERMIC20NOVFUT", 194 | "positionSide": 1, 195 | "convertQty": 1, 196 | "convertFrom": "INTRADAY", 197 | "convertTo": "CNC" 198 | } 199 | 200 | print(fyers.convert_position(data)) 201 | 202 | ################################################################################################################# 203 | 204 | """ 205 | DATA APIS : This includes following Apis(History,Quotes,MarketDepth) 206 | """ 207 | 208 | ## Historical Data 209 | 210 | data = {"symbol": "NSE:SBIN-EQ", "resolution": "D", "date_format": "0", "range_from": "1622097600", 211 | "range_to": "1622097685", "cont_flag": "1"} 212 | 213 | print(fyers.history(data)) 214 | 215 | ## Quotes 216 | 217 | data = {"symbols": "NSE:SBIN-EQ"} 218 | print(fyers.quotes(data)) 219 | 220 | ## Market Depth 221 | 222 | data = {"symbol": "NSE:SBIN-EQ", "ohlcv_flag": "1"} 223 | print(fyers.depth(data)) 224 | -------------------------------------------------------------------------------- /fyers_integration/sample/test.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas_ta as ta 3 | 4 | def calc_2(df,n,f): #df is the dataframe, n is the period, f is the factor; f=3, n=7 are commonly used. 5 | #Calculation of ATR 6 | df['H-L']=abs(df['high']-df['low']) 7 | df['H-PC']=abs(df['high']-df['close'].shift(1)) 8 | df['L-PC']=abs(df['low']-df['close'].shift(1)) 9 | df['TR']=df[['H-L','H-PC','L-PC']].max(axis=1) 10 | df['ATR']=np.nan 11 | df.loc[n-1,'ATR']=df['TR'][:n-1].mean() 12 | for i in range(n,len(df)): 13 | df['ATR'][i]=(df['ATR'][i-1]*(n-1)+ df['TR'][i])/n 14 | 15 | #Calculation of SuperTrend 16 | df['Upper Basic']=(df['high']+df['low'])/2+(f*df['ATR']) 17 | df['Lower Basic']=(df['high']+df['low'])/2-(f*df['ATR']) 18 | df['Upper Band']=df['Upper Basic'] 19 | df['Lower Band']=df['Lower Basic'] 20 | for i in range(n,len(df)): 21 | if df['close'][i-1]<=df['Upper Band'][i-1]: 22 | df['Upper Band'][i]=min(df['Upper Basic'][i],df['Upper Band'][i-1]) 23 | else: 24 | df['Upper Band'][i]=df['Upper Basic'][i] 25 | for i in range(n,len(df)): 26 | if df['close'][i-1]>=df['Lower Band'][i-1]: 27 | df['Lower Band'][i]=max(df['Lower Basic'][i],df['Lower Band'][i-1]) 28 | else: 29 | df['Lower Band'][i]=df['Lower Basic'][i] 30 | df['SuperTrend']=np.nan 31 | for i in df['SuperTrend']: 32 | if df['close'][n-1]<=df['Upper Band'][n-1]: 33 | df['SuperTrend'][n-1]=df['Upper Band'][n-1] 34 | elif df['close'][n-1]>df['Upper Band'][i]: 35 | df['SuperTrend'][n-1]=df['Lower Band'][n-1] 36 | for i in range(n,len(df)): 37 | if df['SuperTrend'][i-1]==df['Upper Band'][i-1] and df['close'][i]<=df['Upper Band'][i]: 38 | df['SuperTrend'][i]=df['Upper Band'][i] 39 | elif df['SuperTrend'][i-1]==df['Upper Band'][i-1] and df['close'][i]>=df['Upper Band'][i]: 40 | df['SuperTrend'][i]=df['Lower Band'][i] 41 | elif df['SuperTrend'][i-1]==df['Lower Band'][i-1] and df['close'][i]>=df['Lower Band'][i]: 42 | df['SuperTrend'][i]=df['Lower Band'][i] 43 | elif df['SuperTrend'][i-1]==df['Lower Band'][i-1] and df['close'][i]<=df['Lower Band'][i]: 44 | df['SuperTrend'][i]=df['Upper Band'][i] 45 | return df 46 | 47 | 48 | def calc_3(df): 49 | sti = ta.supertrend(df['high'], df['low'], df['close'], 10, 3) 50 | print(sti) -------------------------------------------------------------------------------- /fyers_integration/sample/web_socket.py: -------------------------------------------------------------------------------- 1 | from fyers_api.Websocket import ws 2 | 3 | from fyers_integration.auth.json_util import get_json_value 4 | from time import strftime, localtime 5 | 6 | 7 | def run_process_foreground_symbol_data(access_token): 8 | '''This function is used for running the symbolData in foreground 9 | 1. log_path here is configurable this specifies where the output will be stored for you 10 | 2. data_type == symbolData this specfies while using this function you will be able to connect to symbolwebsocket to get the symbolData 11 | 3. run_background = False specifies that the process will be running in foreground''' 12 | data_type = "symbolData" 13 | # symbol = ["NSE:SBIN-EQ","NSE:ONGC-EQ"] ##NSE,BSE sample symbols 14 | # symbol = ["NSE:NIFTY50-INDEX", "NSE:NIFTYBANK-INDEX", "NSE:SBIN-EQ", "NSE:HDFC-EQ", "NSE:IOC-EQ"] 15 | symbol = ["NSE:SBIN-EQ"] 16 | # symbol =["MCX:SILVERMIC21NOVFUT","MCX:GOLDPETAL21SEPTFUT"] 17 | fs = ws.FyersSocket(access_token=access_token, run_background=False, log_path="/Users/debanshu.rout/repo/external/algotrading/fyers_integration/data") 18 | fs.websocket_data = custom_message 19 | fs.subscribe(symbol=symbol, data_type=data_type) 20 | fs.keep_running() 21 | # unsubscribe_symbol = ["NSE:SBIN-EQ"] 22 | # fs.unsubscribe(symbol=unsubscribe_symbol) 23 | 24 | 25 | def custom_message(msg): 26 | print(f"Custom:{msg}") 27 | 28 | print(strftime('%Y-%m-%d %H:%M:%S', localtime(msg[0]['timestamp']))) 29 | print(msg[0]['market_pic']) 30 | 31 | 32 | def main(): 33 | ### Insert the accessToken and app_id over here in the following format (APP_ID:access_token) 34 | token = get_json_value('access_token') 35 | client = get_json_value('client_id') 36 | access_token = client + ":" + token 37 | 38 | ## run a specific process you need to connect to get the updates on 39 | run_process_foreground_symbol_data(access_token) 40 | 41 | 42 | if __name__ == '__main__': 43 | main() -------------------------------------------------------------------------------- /fyers_integration/single_run.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from fyers_api import accessToken, fyersModel 3 | 4 | from auth.json_util import get_json_value 5 | access_token = get_json_value('access_token') 6 | client_id = "TC8P3VH4H7-100" 7 | 8 | fyers = fyersModel.FyersModel(token=access_token, is_async=False, client_id=client_id, log_path="/Users/debanshu.rout/repo/external/algotrading/log") 9 | 10 | ### After this point you can call the relevant apis and get started with 11 | 12 | #################################################################################################################### 13 | # """ 14 | # 1. User Apis : This includes (Profile,Funds,Holdings) 15 | # """ 16 | # print("---- GET PROFILE----") 17 | # print(fyers.get_profile()) ## This will provide us with the user related data 18 | # 19 | # print("---- GET FUNDS----") 20 | # print(fyers.funds()) ## This will provide us with the funds the user has 21 | # 22 | # print("---- GET HOLDINGS----") 23 | # print(fyers.holdings()) ## This will provide the available holdings the user has 24 | # 25 | # ######################################################################################################################## 26 | # 27 | # """ 28 | # 2. Transaction Apis : This includes (Tradebook,Orderbook,Positions) 29 | # """ 30 | # 31 | # print("---- GET TRADEBOOK----") 32 | # print(fyers.tradebook()) ## This will provide all the trade related information 33 | # 34 | # print("---- GET ORDERBOOK----") 35 | # print(fyers.orderbook()) ## This will provide the user with all the order realted information 36 | 37 | # print("---- GET POSITIONS----") 38 | # print(fyers.positions()) ## This will provide the user with all the positions the user has on his end 39 | 40 | # ###################################################################################################################### 41 | # 42 | # """ 43 | # 3. Order Placement : This Apis helps to place order. 44 | # There are two ways to place order 45 | # a. single order : wherein you can fire one order at a time 46 | # b. multi order : this is used to place a basket of order but the basket size can max be 10 symbols 47 | # """ 48 | # 49 | # ## SINGLE ORDER 50 | # 51 | # data = { 52 | # "symbol": "NSE:SBIN-EQ", 53 | # "qty": 1, 54 | # "type": 2, 55 | # "side": 1, 56 | # "productType": "INTRADAY", 57 | # "limitPrice": 0, 58 | # "stopPrice": 0, 59 | # "validity": "DAY", 60 | # "disclosedQty": 0, 61 | # "offlineOrder": "False", 62 | # "stopLoss": 0, 63 | # "takeProfit": 0 64 | # } ## This is a samplea example to place a limit order you can make the further changes based on your requriements 65 | # 66 | # print("---- GET PLACE ORDER----") 67 | # print(fyers.place_order(data)) 68 | # 69 | # ## MULTI ORDER 70 | # 71 | # data = [{"symbol": "NSE:SBIN-EQ", 72 | # "qty": 1, 73 | # "type": 1, 74 | # "side": 1, 75 | # "productType": "INTRADAY", 76 | # "limitPrice": 61050, 77 | # "stopPrice": 0, 78 | # "disclosedQty": 0, 79 | # "validity": "DAY", 80 | # "offlineOrder": "False", 81 | # "stopLoss": 0, 82 | # "takeProfit": 0 83 | # }, 84 | # { 85 | # "symbol": "NSE:HDFC-EQ", 86 | # "qty": 1, 87 | # "type": 2, 88 | # "side": 1, 89 | # "productType": "INTRADAY", 90 | # "limitPrice": 0, 91 | # "stopPrice": 0, 92 | # "disclosedQty": 0, 93 | # "validity": "DAY", 94 | # "offlineOrder": "False", 95 | # "stopLoss": 0, 96 | # "takeProfit": 0 97 | # }] ### This takes input as a list containing multiple single order data into it and the execution of the orders goes in the same format as mentioned. 98 | # 99 | # #print(fyers.place_basket_orders(data)) 100 | # 101 | # ################################################################################################################### 102 | # 103 | # """ 104 | # 4. Other Transaction : This includes (modify_order,exit_position,cancel_order,convert_positions) 105 | # """ 106 | # 107 | # ## Modify_order request 108 | # data = { 109 | # "id": 7574657627567, 110 | # "type": 1, 111 | # "limitPrice": 61049, 112 | # "qty": 1 113 | # } 114 | # 115 | # print("---- GET MODIFY ORDER----") 116 | # print(fyers.modify_order(data)) 117 | # 118 | # ## Modify Multi Order 119 | # 120 | # data = [ 121 | # {"id": 8102710298291, 122 | # "type": 1, 123 | # "limitPrice": 61049, 124 | # "qty": 0 125 | # }, 126 | # { 127 | # "id": 8102710298292, 128 | # "type": 1, 129 | # "limitPrice": 61049, 130 | # "qty": 1 131 | # }] 132 | # 133 | # #print(fyers.modify_basket_orders(data)) 134 | # 135 | # ### Cancel_order 136 | # data = {"id": '808058117761'} 137 | # 138 | # print("---- GET CANCEL ORDER----") 139 | # print(fyers.cancel_order(data)) 140 | # 141 | # ### cancel_multi_order 142 | # data = [ 143 | # { 144 | # "id": '808058117761' 145 | # }, 146 | # { 147 | # "id": '808058117762' 148 | # }] 149 | # 150 | # #print(fyers.cancel_basket_orders(data)) 151 | # 152 | # ### Exit Position 153 | # data = { 154 | # "id": "NSE:SBIN-EQ-INTRADAY" 155 | # } 156 | # 157 | # print("---- GET EXIT ORDER----") 158 | # print(fyers.exit_positions(data)) 159 | # 160 | # ### Convert Position 161 | # 162 | # data = { 163 | # "symbol": "MCX:SILVERMIC20NOVFUT", 164 | # "positionSide": 1, 165 | # "convertQty": 1, 166 | # "convertFrom": "INTRADAY", 167 | # "convertTo": "CNC" 168 | # } 169 | # 170 | # #print(fyers.convert_position(data)) 171 | # 172 | # ################################################################################################################# 173 | # 174 | # """ 175 | # DATA APIS : This includes following Apis(History,Quotes,MarketDepth) 176 | # """ 177 | # 178 | # ## Historical Data 179 | # 180 | data = {"symbol": "NSE:SBIN-EQ", "resolution": "10", "date_format": "1", "range_from": "2023-03-23", 181 | "range_to": "2023-03-23", "cont_flag": "1"} 182 | 183 | print("---- GET HISTORY DATA----") 184 | print(fyers.history(data)) 185 | # 186 | # ## Quotes 187 | # 188 | # data = {"symbols": "NSE:SBIN-EQ"} 189 | # print("---- GET QUOTES DATA----") 190 | # print(fyers.quotes(data)) 191 | # 192 | # ## Market Depth 193 | # 194 | # data = {"symbol": "NSE:SBIN-EQ", "ohlcv_flag": "1"} 195 | # print("---- GET MARKET DEPTH DATA----") 196 | # print(fyers.depth(data)) 197 | -------------------------------------------------------------------------------- /fyers_integration/strategy.py: -------------------------------------------------------------------------------- 1 | import time 2 | from math import floor, ceil 3 | import pandas as pd 4 | import requests 5 | from fyers_api import accessToken, fyersModel 6 | 7 | 8 | from fyers_integration.util import get_historical_data 9 | from indicators import SuperTrend, EMA, MACD, RSI 10 | import datetime 11 | 12 | from auth.json_util import get_json_value 13 | 14 | pd.set_option('display.max_rows', None) 15 | pd.set_option('display.max_columns', None) 16 | 17 | 18 | access_token = get_json_value('access_token') 19 | client_id = "SLWIS8N2SP-100" 20 | fyers = fyersModel.FyersModel(token=access_token, is_async=False, client_id=client_id, log_path="/Users/debanshu.rout/repo/external/algotrading/log") 21 | #print(fyers.get_profile()['data']['name']) 22 | 23 | run_count = 0 24 | exit_count = 0 25 | supertrend_period = 10 26 | supertrend_multiplier=3 27 | orderslist = {} 28 | time_frame = "10" 29 | one_hour_rsi = 50 30 | 31 | stockList = ["NSE:RELIANCE-EQ", "NSE:SBIN-EQ"] 32 | 33 | 34 | def compute_data(stock): 35 | global one_hour_rsi 36 | #enddate = datetime.datetime(2020, 5, 4, 15,30,0,0) 37 | end_date = datetime.datetime.today() 38 | start_date = end_date - datetime.timedelta(10) 39 | 40 | try: 41 | df = get_historical_data(fyers, stock, time_frame, start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d")) 42 | 43 | df = SuperTrend.calc(df, supertrend_period, supertrend_multiplier) 44 | df = MACD.calc(df) 45 | rsi = get_historical_data(fyers, stock, "60", start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d")) 46 | rsi = RSI.calc(rsi) 47 | one_hour_rsi = rsi.RSI_14.values[-1] 48 | 49 | print(df) 50 | except Exception as e: 51 | print("******* ERROR Computing Historical Data ********", e) 52 | return df 53 | 54 | 55 | # 56 | # ## Quotes 57 | # 58 | # data = {"symbols": "NSE:SBIN-EQ"} 59 | # print(fyers.quotes(data)) 60 | # # 61 | # # ## Market Depth 62 | # # 63 | # data = {"symbol": "NSE:SBIN-EQ", "ohlcv_flag": "1"} 64 | # print(fyers.depth(data)) 65 | 66 | def check_volume(open, volume): 67 | if open <= 400 and volume >= 1000000: 68 | return True 69 | elif open > 400 and open <=700 and volume >= 500000: 70 | return True 71 | elif open > 700 and open <=1000 and volume >= 300000: 72 | return True 73 | elif open > 1000 and volume >= 100000: 74 | return True 75 | else: 76 | return False 77 | 78 | def run_strategy(): 79 | global orderslist 80 | global one_hour_rsi 81 | for i in range(0, len(stockList)): 82 | if stockList[i] in orderslist: 83 | continue 84 | try: 85 | histdata = compute_data(stockList[i]) 86 | # print(histdata) 87 | super_trend = histdata.STX.values 88 | 89 | high = histdata.high.values[-2] 90 | low = histdata.low.values[-2] 91 | macd = histdata.hist_12_26_9.values[-2] 92 | stoploss_buy = histdata.ST.values[-2] # histdata.low.values[-3] # third last candle as stoploss 93 | stoploss_sell = histdata.ST.values[-2] # third last candle as stoploss 94 | 95 | volume = histdata.volume.values[-2] 96 | has_volume = check_volume(histdata.open.values[-2], volume) 97 | 98 | # if stoploss_buy > lastclose * 0.996: 99 | # stoploss_buy = lastclose * 0.996 # minimum stoploss as 0.4 % 100 | 101 | # if stoploss_sell < lastclose * 1.004: 102 | # stoploss_sell = lastclose * 1.004 # minimum stoploss as 0.4 % 103 | # print("lastclose",lastclose) 104 | # print("stoploss abs",stoploss) 105 | 106 | print(stockList[i], high, low, super_trend[-4:], round(macd, 4), int(one_hour_rsi), volume) 107 | 108 | if not has_volume: 109 | print("Sorry, Volume is low") 110 | continue 111 | 112 | if super_trend[-1] == 'up' and super_trend[-2] == 'up' and super_trend[-3] == 'down' and super_trend[ 113 | -4] == 'down' \ 114 | and macd > 0 and one_hour_rsi > 50: 115 | 116 | stoploss_buy = high - stoploss_buy 117 | # print("stoploss delta", stoploss) 118 | 119 | quantity = 1 # floor(max(1, (risk_per_trade/stoploss_buy))) 120 | target = stoploss_buy * 2 # risk reward as 3 121 | 122 | price = high + (0.05 * high) / 100 123 | # print(price) 124 | # price = int(ceil(price)) 125 | price = int(100 * (ceil(price / 0.05) * 0.05)) / 100 126 | stoploss_buy = int(100 * (floor(stoploss_buy / 0.05) * 0.05)) / 100 127 | quantity = int(quantity) 128 | target = int(100 * (floor(target / 0.05) * 0.05)) / 100 129 | 130 | #orderslist[stockList[i]] = price - stoploss_buy 131 | # print(price) 132 | 133 | data = { 134 | "symbol": stockList[i], 135 | "qty": quantity, 136 | "type": 3, 137 | "side": 1, 138 | "productType": "INTRADAY", 139 | "limitPrice": 0, 140 | "stopPrice": stoploss_buy, 141 | "validity": "DAY", 142 | "disclosedQty": 0, 143 | "offlineOrder": "False", 144 | "stopLoss": 0, 145 | "takeProfit": 0 146 | } 147 | 148 | print(fyers.place_order(data)) 149 | 150 | print(" Order : ", "BUY", stockList[i], "high : ", high, "quantity:", quantity, "price:", 151 | price, datetime.datetime.now()) 152 | 153 | if super_trend[-1] == 'down' and super_trend[-2] == 'down' and super_trend[-3] == 'up' and super_trend[ 154 | -4] == 'up' \ 155 | and macd < 0 and one_hour_rsi < 50: 156 | 157 | if not has_volume: 158 | print("Sorry, Volume is low") 159 | # continue 160 | 161 | stoploss_sell = stoploss_sell - low 162 | # print("stoploss delta", stoploss) 163 | 164 | quantity = 1 # floor(max(1, (risk_per_trade/stoploss_sell))) 165 | target = stoploss_sell * 2 # risk reward as 3 166 | 167 | price = low - (0.05 * low) / 100 168 | # price = int(floor(price)) 169 | price = int(100 * (floor(price / 0.05) * 0.05)) / 100 170 | stoploss_sell = int(100 * (floor(stoploss_sell / 0.05) * 0.05)) / 100 171 | quantity = int(quantity) 172 | target = int(100 * (floor(target / 0.05) * 0.05)) / 100 173 | 174 | #orderslist[stockList[i]] = price + stoploss_sell 175 | 176 | data = { 177 | "symbol": stockList[i], 178 | "qty": quantity, 179 | "type": 3, 180 | "side": -1, 181 | "productType": "INTRADAY", 182 | "limitPrice": 0, 183 | "stopPrice": stoploss_sell, 184 | "validity": "DAY", 185 | "disclosedQty": 0, 186 | "offlineOrder": "False", 187 | "stopLoss": 0, 188 | "takeProfit": 0 189 | } 190 | 191 | print(fyers.place_order(data)) 192 | 193 | print(" Order : ", "SELL", stockList[i], "low : ", low, "quantity:", quantity, "price:", price, 194 | datetime.datetime.now()) 195 | 196 | except Exception as e: 197 | print(e) 198 | 199 | 200 | def check_order_status(): 201 | global orderslist 202 | df = pd.DataFrame(columns=['order_id', 'status', 'tradingsymbol', 'instrument_token', 'transaction_type', 'quantity']) 203 | try: 204 | data = fyers.get_orders() 205 | df = pd.DataFrame.from_dict(data, orient='columns', dtype=None) 206 | #print(df) 207 | if not df.empty: 208 | df = df[['order_id', 'status', 'tradingsymbol', 'instrument_token', 'transaction_type', 'quantity']] 209 | except Exception as e: 210 | print("******* ERROR Fetching Historical Data ********", e) 211 | for ind in df.index: 212 | token = df['tradingsymbol'][ind] 213 | orderslist[token] = "0" 214 | #print(df['tradingsymbol'][ind], df['transaction_type'][ind]) 215 | 216 | print(orderslist) 217 | return df 218 | 219 | 220 | def run(): 221 | global run_count 222 | global exit_count 223 | trade_start_time = int(11) * 60 + int(25) # specify in int (hr) and int (min) format 224 | order_end_time = int(14) * 60 + int(55) # do not place fresh order 225 | square_off_time = int(15) * 60 + int(15) # square off all open positions 226 | prev_time = trade_start_time 227 | schedule_interval = 60 # run at every 1 min 228 | #runcount = 0 229 | #check_order_status() 230 | 231 | next_time = trade_start_time 232 | 233 | # set next_time to the nearest 5th minute of current time 234 | if (datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) % 10 == 0: 235 | next_time = datetime.datetime.now().hour * 60 + \ 236 | ((datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) + 5) 237 | 238 | else: 239 | next_time = datetime.datetime.now().hour * 60 + \ 240 | (datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) 241 | 242 | while True: 243 | curr_time = datetime.datetime.now().hour * 60 + datetime.datetime.now().minute 244 | #check_order_status() 245 | if curr_time >= square_off_time: 246 | #close_positions() 247 | print("***** Trading Day closed *****") 248 | break 249 | if curr_time >= trade_start_time: 250 | if next_time <= curr_time < order_end_time: 251 | next_time = curr_time + 10 252 | time.sleep(2) 253 | print("\n\n {} Run Count : Time - {} ".format(run_count, datetime.datetime.now())) 254 | if run_count >= 0: 255 | try: 256 | run_strategy() 257 | except Exception as e: 258 | print("******* Run Error *********", e) 259 | run_count = run_count + 1 260 | 261 | if curr_time >= order_end_time and curr_time >= next_time: 262 | next_time = curr_time + 5 263 | time.sleep(2) 264 | print("\n\n {} Exit Count : Time - {} ".format(exit_count, datetime.datetime.now())) 265 | if exit_count >= 0: 266 | try: 267 | check_order_status() 268 | except Exception as e: 269 | print("******* Run Error *********", e) 270 | exit_count = exit_count + 1 271 | 272 | else: 273 | print('****** Waiting ********', datetime.datetime.now()) 274 | time.sleep(1) 275 | 276 | 277 | if __name__ == '__main__': 278 | run() 279 | #compute_data() 280 | #print(fyers.tradebook()) ## This will provide all the trade related information 281 | 282 | #print(fyers.orderbook()) ## This will provide the user with all the order realted information 283 | 284 | #print(fyers.positions()) -------------------------------------------------------------------------------- /fyers_integration/util.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | # data = {"symbol": "NSE:SBIN-EQ", "resolution": "D", "date_format": "1", "range_from": "2022-07-18", 5 | # "range_to": "2022-07-24", "cont_flag": "1"} 6 | 7 | 8 | def get_historical_data(fyers, symbol, time_frame, start_date, end_date): 9 | data = {'symbol': symbol, 'resolution': time_frame, 'date_format': "1", 'range_from': start_date, 10 | 'range_to': end_date, 11 | 'cont_flag': "1"} 12 | 13 | data = fyers.history(data)['candles'] 14 | df = pd.DataFrame(columns=['date', 'open', 'high', 'low', 'close', 'volume']) 15 | 16 | try: 17 | df = pd.DataFrame(data, columns=['date', 'open', 'high', 'low', 'close', 'volume'], dtype=None) 18 | # print(df) 19 | if not df.empty: 20 | df = df[['date', 'open', 'high', 'low', 'close', 'volume']] 21 | df['date'] = pd.to_datetime(df['date'], unit='s', utc=True) 22 | # df['date'] = df['date'].dt.tz_localize('UTC') 23 | df['date'] = df['date'].dt.tz_convert('Asia/Kolkata') 24 | df['date'] = df['date'].astype(str).str[:-6] 25 | 26 | # df['date'] = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(df['date'])) 27 | # df['date'] = pd.to_datetime(df['date']) 28 | except Exception as e: 29 | print("******* ERROR Fetching Historical Data ********", e) 30 | df.reset_index(drop=True) 31 | return df 32 | -------------------------------------------------------------------------------- /indicators/ATR.py: -------------------------------------------------------------------------------- 1 | from indicators import EMA 2 | 3 | def calc(df, period, ohlc=['open', 'high', 'low', 'close']): 4 | """ 5 | Function to compute Average True Range (ATR) 6 | 7 | Args : 8 | df : Pandas DataFrame which contains ['date', 'open', 'high', 'low', 'close', 'volume'] columns 9 | period : Integer indicates the period of computation in terms of number of candles 10 | ohlc: List defining OHLC Column names (default ['Open', 'High', 'Low', 'Close']) 11 | 12 | Returns : 13 | df : Pandas DataFrame with new columns added for 14 | True Range (TR) 15 | ATR (ATR_$period) 16 | """ 17 | atr = 'ATR_' + str(period) 18 | 19 | # Compute true range only if it is not computed and stored earlier in the df 20 | if not 'TR' in df.columns: 21 | df['h-l'] = df[ohlc[1]] - df[ohlc[2]] 22 | df['h-yc'] = abs(df[ohlc[1]] - df[ohlc[3]].shift()) 23 | df['l-yc'] = abs(df[ohlc[2]] - df[ohlc[3]].shift()) 24 | 25 | df['TR'] = df[['h-l', 'h-yc', 'l-yc']].max(axis=1) 26 | 27 | df.drop(['h-l', 'h-yc', 'l-yc'], inplace=True, axis=1) 28 | 29 | # Compute EMA of true range using ATR formula after ignoring first row 30 | EMA.calc(df, 'TR', atr, period, alpha=True) 31 | 32 | return df -------------------------------------------------------------------------------- /indicators/EMA.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | # Source for tech indicator : https://github.com/arkochhar/Technical-Indicators/blob/master/indicator/indicators.py 4 | def calc(df, base, target, period, alpha=False): 5 | """ 6 | Function to compute Exponential Moving Average (EMA) 7 | 8 | Args : 9 | df : Pandas DataFrame which contains ['date', 'open', 'high', 'low', 'close', 'volume'] columns 10 | base : String indicating the column name from which the EMA needs to be computed from 11 | target : String indicates the column name to which the computed data needs to be stored 12 | period : Integer indicates the period of computation in terms of number of candles 13 | alpha : Boolean if True indicates to use the formula for computing EMA using alpha (default is False) 14 | 15 | Returns : 16 | df : Pandas DataFrame with new column added with name 'target' 17 | """ 18 | 19 | con = pd.concat([df[:period][base].rolling(window=period).mean(), df[period:][base]]) 20 | 21 | if (alpha == True): 22 | # (1 - alpha) * previous_val + alpha * current_val where alpha = 1 / period 23 | alpha = 1 / period 24 | df[target] = con.ewm(alpha, adjust=False).mean() 25 | 26 | else: 27 | # ((current_val - previous_val) * coeff) + previous_val where coeff = 2 / (period + 1) 28 | df[target] = con.ewm(span=period, adjust=False).mean() 29 | 30 | df[target].fillna(0, inplace=True) 31 | return df 32 | -------------------------------------------------------------------------------- /indicators/MACD.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from indicators import EMA 3 | 4 | 5 | def calc(df, fastEMA=12, slowEMA=26, signal=9, base='close'): 6 | """ 7 | Function to compute Moving Average Convergence Divergence (MACD) 8 | 9 | Args : 10 | df : Pandas DataFrame which contains ['date', 'open', 'high', 'low', 'close', 'volume'] columns 11 | fastEMA : Integer indicates faster EMA 12 | slowEMA : Integer indicates slower EMA 13 | signal : Integer indicates the signal generator for MACD 14 | base : String indicating the column name from which the MACD needs to be computed from (Default Close) 15 | 16 | Returns : 17 | df : Pandas DataFrame with new columns added for 18 | Fast EMA (ema_$fastEMA) 19 | Slow EMA (ema_$slowEMA) 20 | MACD (macd_$fastEMA_$slowEMA_$signal) 21 | MACD Signal (signal_$fastEMA_$slowEMA_$signal) 22 | MACD Histogram (MACD (hist_$fastEMA_$slowEMA_$signal)) 23 | """ 24 | 25 | fE = "ema_" + str(fastEMA) 26 | sE = "ema_" + str(slowEMA) 27 | macd = "macd_" + str(fastEMA) + "_" + str(slowEMA) + "_" + str(signal) 28 | sig = "signal_" + str(fastEMA) + "_" + str(slowEMA) + "_" + str(signal) 29 | hist = "hist_" + str(fastEMA) + "_" + str(slowEMA) + "_" + str(signal) 30 | 31 | # Compute fast and slow EMA 32 | EMA.calc(df, base, fE, fastEMA) 33 | EMA.calc(df, base, sE, slowEMA) 34 | 35 | # Compute MACD 36 | df[macd] = np.where(np.logical_and(np.logical_not(df[fE] == 0), np.logical_not(df[sE] == 0)), df[fE] - df[sE], 0) 37 | 38 | # Compute MACD Signal 39 | EMA.calc(df, macd, sig, signal) 40 | 41 | # Compute MACD Histogram 42 | df[hist] = np.where(np.logical_and(np.logical_not(df[macd] == 0), np.logical_not(df[sig] == 0)), df[macd] - df[sig], 0) 43 | df.drop(['ema_12', 'ema_26'], inplace=True, axis=1) 44 | 45 | return df 46 | -------------------------------------------------------------------------------- /indicators/MFI.py: -------------------------------------------------------------------------------- 1 | # Source : https://github.com/peerchemist/finta 2 | 3 | def TP(df) : 4 | """Typical Price refers to the arithmetic average of the high, low, and closing prices for a given period.""" 5 | df['TP'] = (df['high'] + df['low'] + df['close']) / 3 6 | return df 7 | 8 | 9 | def calc(df, period = 14) : 10 | """The money flow index (MFI) is a momentum indicator that measures 11 | the inflow and outflow of money into a security over a specific period of time. 12 | MFI can be understood as RSI adjusted for volume. 13 | The money flow indicator is one of the more reliable indicators of overbought and oversold conditions, perhaps partly because 14 | it uses the higher readings of 80 and 20 as compared to the RSI's overbought/oversold readings of 70 and 30""" 15 | 16 | TP(df) 17 | df['rmf'] = df['TP'] * df['volume'] 18 | df["delta"] = df["TP"].diff() 19 | def pos(row): 20 | if row["delta"] > 0: 21 | return row['rmf'] 22 | else: 23 | return 0 24 | 25 | def neg(row): 26 | if row["delta"] < 0: 27 | return row['rmf'] 28 | else: 29 | return 0 30 | 31 | df["neg"] = df.apply(neg, axis=1) 32 | df["pos"] = df.apply(pos, axis=1) 33 | 34 | 35 | mfratio = df["pos"].rolling(window=period).sum() / df["neg"].rolling(window=period).sum() 36 | 37 | df["mfi"] = 100 - (100 / (1 + mfratio)) 38 | df.drop(['rmf', 'pos', 'neg', 'delta', 'TP'], inplace=True, axis=1) 39 | return df -------------------------------------------------------------------------------- /indicators/RSI.py: -------------------------------------------------------------------------------- 1 | def calc(df, base="close", period=14): 2 | """ 3 | Function to compute Relative Strength Index (RSI) 4 | 5 | Args : 6 | df : Pandas DataFrame which contains ['date', 'open', 'high', 'low', 'close', 'volume'] columns 7 | base : String indicating the column name from which the RSI needs to be computed from (Default Close) 8 | period : Integer indicates the period of computation in terms of number of candles 9 | 10 | Returns : 11 | df : Pandas DataFrame with new columns added for 12 | Relative Strength Index (RSI_$period) 13 | """ 14 | 15 | delta = df[base].diff() 16 | up, down = delta.copy(), delta.copy() 17 | 18 | up[up < 0] = 0 19 | down[down > 0] = 0 20 | 21 | rUp = up.ewm(com=period - 1, adjust=False).mean() 22 | rDown = down.ewm(com=period - 1, adjust=False).mean().abs() 23 | 24 | df['RSI_' + str(period)] = 100 - 100 / (1 + rUp / rDown) 25 | df['RSI_' + str(period)].fillna(0, inplace=True) 26 | 27 | return df -------------------------------------------------------------------------------- /indicators/SuperTrend.py: -------------------------------------------------------------------------------- 1 | from indicators import ATR 2 | import numpy as np 3 | 4 | 5 | def calc(df, period, multiplier, ohlc=['open', 'high', 'low', 'close']): 6 | """ 7 | Function to compute SuperTrend 8 | 9 | Args : 10 | df : Pandas DataFrame which contains ['date', 'open', 'high', 'low', 'close', 'volume'] columns 11 | period : Integer indicates the period of computation in terms of number of candles 12 | multiplier : Integer indicates value to multiply the ATR 13 | ohlc: List defining OHLC Column names (default ['Open', 'High', 'Low', 'Close']) 14 | 15 | Returns : 16 | df : Pandas DataFrame with new columns added for 17 | True Range (TR), ATR (ATR_$period) 18 | SuperTrend (ST_$period_$multiplier) 19 | SuperTrend Direction (STX_$period_$multiplier) 20 | """ 21 | 22 | ATR.calc(df, period, ohlc=ohlc) 23 | atr = 'ATR_' + str(period) 24 | st = 'ST' #+ str(period) + '_' + str(multiplier) 25 | stx = 'STX' # + str(period) + '_' + str(multiplier) 26 | 27 | """ 28 | SuperTrend Algorithm : 29 | 30 | BASIC UPPERBAND = (HIGH + LOW) / 2 + Multiplier * ATR 31 | BASIC LOWERBAND = (HIGH + LOW) / 2 - Multiplier * ATR 32 | 33 | FINAL UPPERBAND = IF( (Current BASICUPPERBAND < Previous FINAL UPPERBAND) or (Previous Close > Previous FINAL UPPERBAND)) 34 | THEN (Current BASIC UPPERBAND) ELSE Previous FINALUPPERBAND) 35 | FINAL LOWERBAND = IF( (Current BASIC LOWERBAND > Previous FINAL LOWERBAND) or (Previous Close < Previous FINAL LOWERBAND)) 36 | THEN (Current BASIC LOWERBAND) ELSE Previous FINAL LOWERBAND) 37 | 38 | SUPERTREND = IF((Previous SUPERTREND = Previous FINAL UPPERBAND) and (Current Close <= Current FINAL UPPERBAND)) THEN 39 | Current FINAL UPPERBAND 40 | ELSE 41 | IF((Previous SUPERTREND = Previous FINAL UPPERBAND) and (Current Close > Current FINAL UPPERBAND)) THEN 42 | Current FINAL LOWERBAND 43 | ELSE 44 | IF((Previous SUPERTREND = Previous FINAL LOWERBAND) and (Current Close >= Current FINAL LOWERBAND)) THEN 45 | Current FINAL LOWERBAND 46 | ELSE 47 | IF((Previous SUPERTREND = Previous FINAL LOWERBAND) and (Current Close < Current FINAL LOWERBAND)) THEN 48 | Current FINAL UPPERBAND 49 | """ 50 | 51 | # Compute basic upper and lower bands 52 | df['basic_ub'] = (df[ohlc[1]] + df[ohlc[2]]) / 2 + multiplier * df[atr] 53 | df['basic_lb'] = (df[ohlc[1]] + df[ohlc[2]]) / 2 - multiplier * df[atr] 54 | 55 | # Compute final upper and lower bands 56 | df['final_ub'] = 0.00 57 | df['final_lb'] = 0.00 58 | for i in range(period, len(df)): 59 | df['final_ub'].iat[i] = df['basic_ub'].iat[i] if df['basic_ub'].iat[i] < df['final_ub'].iat[i - 1] or \ 60 | df[ohlc[3]].iat[i - 1] > df['final_ub'].iat[i - 1] else \ 61 | df['final_ub'].iat[i - 1] 62 | df['final_lb'].iat[i] = df['basic_lb'].iat[i] if df['basic_lb'].iat[i] > df['final_lb'].iat[i - 1] or \ 63 | df[ohlc[3]].iat[i - 1] < df['final_lb'].iat[i - 1] else \ 64 | df['final_lb'].iat[i - 1] 65 | 66 | # Set the Supertrend value 67 | df[st] = 0.00 68 | for i in range(period, len(df)): 69 | df[st].iat[i] = df['final_ub'].iat[i] if df[st].iat[i - 1] == df['final_ub'].iat[i - 1] and df[ohlc[3]].iat[ 70 | i] <= df['final_ub'].iat[i] else \ 71 | df['final_lb'].iat[i] if df[st].iat[i - 1] == df['final_ub'].iat[i - 1] and df[ohlc[3]].iat[i] > \ 72 | df['final_ub'].iat[i] else \ 73 | df['final_lb'].iat[i] if df[st].iat[i - 1] == df['final_lb'].iat[i - 1] and df[ohlc[3]].iat[i] >= \ 74 | df['final_lb'].iat[i] else \ 75 | df['final_ub'].iat[i] if df[st].iat[i - 1] == df['final_lb'].iat[i - 1] and df[ohlc[3]].iat[i] < \ 76 | df['final_lb'].iat[i] else 0.00 77 | 78 | # Mark the trend direction up/down 79 | df[stx] = np.where((df[st] > 0.00), np.where((df[ohlc[3]] < df[st]), 'down', 'up'), np.NaN) 80 | 81 | # Remove basic and final bands from the columns 82 | df.drop(['basic_ub', 'basic_lb', 'final_ub', 'final_lb'], inplace=True, axis=1) 83 | 84 | df.fillna(0, inplace=True) 85 | #for i in range(0, len(df[st])): 86 | #print(str(df[st][i])) 87 | return df 88 | -------------------------------------------------------------------------------- /indicators/VWAP.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | def TP(df) : 5 | """Typical Price refers to the arithmetic average of the high, low, and closing prices for a given period.""" 6 | df['TP'] = (df['high'] + df['low'] + df['close']) / 3 7 | return df 8 | 9 | 10 | def vwap(df): 11 | """ 12 | The volume weighted average price (VWAP) is a trading benchmark used especially in pension plans. 13 | VWAP is calculated by adding up the dollars traded for every transaction (price multiplied by number of shares traded) and then dividing 14 | by the total shares traded for the day. 15 | """ 16 | df['vwap'] = np.cumsum(df['volume'] * df['TP']) / np.cumsum(df['volume']) 17 | return df 18 | 19 | 20 | def calc(df): 21 | TP(df) 22 | df[['intraday','time']] = df['date'].astype(str).str.split(expand=True) 23 | df = df.groupby(df['intraday'], group_keys=False).apply(vwap) 24 | df.drop(['TP', 'intraday', 'time'], inplace=True, axis=1) 25 | return df 26 | 27 | -------------------------------------------------------------------------------- /indicators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debanshur/algotrading/4e6fe65f8d5091bcad51437c3641c84d91bdc47f/indicators/__init__.py -------------------------------------------------------------------------------- /log/2022-07-27.txt: -------------------------------------------------------------------------------- 1 | 2 | 1658907114744 :: get_profile :: SLWIS8N2SP-100:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZnllcnMuaW4iLCJpYXQiOjE2NTg5MDY5ODYsImV4cCI6MTY1ODk2ODI0NiwibmJmIjoxNjU4OTA2OTg2LCJhdWQiOlsieDowIiwieDoxIiwieDoyIiwiZDoxIiwiZDoyIiwieDoxIiwieDowIl0sInN1YiI6ImFjY2Vzc190b2tlbiIsImF0X2hhc2giOiJnQUFBQUFCaTRPbHE4ZVZtdlBSRWlJYk9mcGNUZ3Bma1RmYjlMZUdZWW41aHIycmx4Ym5WWnY0X2xibDdYaWNPVWZfeTFxTkp6TEVBZ2lHNVNyRDFEYUZpN1ZXQWxCM1FCVVlCNHhaeURDSWRYQ0Y4LXljMG5lcz0iLCJkaXNwbGF5X25hbWUiOiJERUJBTlNIVSBST1VUIiwiZnlfaWQiOiJYRDExODUwIiwiYXBwVHlwZSI6MTAwLCJwb2FfZmxhZyI6Ik4ifQ.HIjYsLtPzqKgXLXUYGXHc66Y4j1B2bKLEbLzTuXRdek :: 1658907115088 :: {'s': 'ok', 'code': 200, 'message': '', 'data': {'fy_id': 'XD11850', 'name': 'DEBANSHU ROUT', 'image': None, 'display_name': None, 'pin_change_date': '25-06-2022 12:11:59', 'email_id': 'debanshurout@gmail.com', 'pwd_change_date': '23-07-2022 11:51:52', 'PAN': '---------', 'pwd_to_expire': 147}} 3 | 4 | 1658907115089 :: tradebook :: None :: 1658907115996 :: {'s': 'ok', 'code': 200, 'message': '', 'tradeBook': [{'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 12:58:53', 'orderNumber': '122072766357', 'exchangeOrderNo': '1300000013600000', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.3, 'tradeValue': 522.3, 'tradeNumber': '78352007', 'id': '78352007', 'row': 1, 'symbol': 'NSE:SBIN-EQ'}]} 5 | 6 | 1658907115997 :: orderBook :: :: 1658907116461 :: {'s': 'ok', 'code': 200, 'message': '', 'orderBook': [{'orderDateTime': '27-Jul-2022 12:58:53', 'id': '122072766357', 'exchOrdId': '1300000013600000', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 1, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072766357:2', 'tradedPrice': 522.3, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.55, 'chp': 1.66, 'lp': 522.75, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}]} 7 | 8 | 1658907116462 :: positions :: :: 1658907117115 :: {'s': 'ok', 'code': 200, 'message': '', 'netPositions': [{'netQty': 1, 'qty': 1, 'avgPrice': 522.3, 'netAvg': 522.3, 'side': 1, 'productType': 'INTRADAY', 'realized_profit': 0.0, 'unrealized_profit': 0.45, 'pl': 0.45, 'ltp': 522.75, 'buyQty': 1, 'buyAvg': 522.3, 'buyVal': 522.3, 'sellQty': 0, 'sellAvg': 0.0, 'sellVal': 0.0, 'slNo': 0, 'fyToken': '10100000003045', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:SBIN-EQ', 'id': 'NSE:SBIN-EQ-INTRADAY', 'qtyMultiplier': 1.0}], 'overall': {'count_total': 1, 'count_open': 1, 'pl_total': 0.45, 'pl_realized': 0.0, 'pl_unrealized': 0.45}} 9 | 10 | 1658907251993 :: get_profile :: SLWIS8N2SP-100:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZnllcnMuaW4iLCJpYXQiOjE2NTg5MDY5ODYsImV4cCI6MTY1ODk2ODI0NiwibmJmIjoxNjU4OTA2OTg2LCJhdWQiOlsieDowIiwieDoxIiwieDoyIiwiZDoxIiwiZDoyIiwieDoxIiwieDowIl0sInN1YiI6ImFjY2Vzc190b2tlbiIsImF0X2hhc2giOiJnQUFBQUFCaTRPbHE4ZVZtdlBSRWlJYk9mcGNUZ3Bma1RmYjlMZUdZWW41aHIycmx4Ym5WWnY0X2xibDdYaWNPVWZfeTFxTkp6TEVBZ2lHNVNyRDFEYUZpN1ZXQWxCM1FCVVlCNHhaeURDSWRYQ0Y4LXljMG5lcz0iLCJkaXNwbGF5X25hbWUiOiJERUJBTlNIVSBST1VUIiwiZnlfaWQiOiJYRDExODUwIiwiYXBwVHlwZSI6MTAwLCJwb2FfZmxhZyI6Ik4ifQ.HIjYsLtPzqKgXLXUYGXHc66Y4j1B2bKLEbLzTuXRdek :: 1658907252518 :: {'s': 'ok', 'code': 200, 'message': '', 'data': {'fy_id': 'XD11850', 'name': 'DEBANSHU ROUT', 'image': None, 'display_name': None, 'pin_change_date': '25-06-2022 12:11:59', 'email_id': 'debanshurout@gmail.com', 'pwd_change_date': '23-07-2022 11:51:52', 'PAN': '---------', 'pwd_to_expire': 147}} 11 | 12 | 1658907252523 :: tradebook :: None :: 1658907252744 :: {'s': 'ok', 'code': 200, 'message': '', 'tradeBook': [{'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:00', 'orderNumber': '122072767397', 'exchangeOrderNo': '1300000013844692', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.85, 'tradeValue': 522.85, 'tradeNumber': '78402095', 'id': '78402095', 'row': 1, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 12:58:53', 'orderNumber': '122072766357', 'exchangeOrderNo': '1300000013600000', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.3, 'tradeValue': 522.3, 'tradeNumber': '78352007', 'id': '78352007', 'row': 2, 'symbol': 'NSE:SBIN-EQ'}]} 13 | 14 | 1658907252745 :: orderBook :: :: 1658907252975 :: {'s': 'ok', 'code': 200, 'message': '', 'orderBook': [{'orderDateTime': '27-Jul-2022 13:04:00', 'id': '122072767397', 'exchOrdId': '1300000013844692', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 1, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767397:2', 'tradedPrice': 522.85, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 12:58:53', 'id': '122072766357', 'exchOrdId': '1300000013600000', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 2, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072766357:2', 'tradedPrice': 522.3, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}]} 15 | 16 | 1658907252976 :: positions :: :: 1658907253184 :: {'s': 'ok', 'code': 200, 'message': '', 'netPositions': [{'netQty': 0, 'qty': 0, 'avgPrice': 0, 'netAvg': 0.0, 'side': 0, 'productType': 'INTRADAY', 'realized_profit': 0.55, 'unrealized_profit': 0.0, 'pl': 0.55, 'ltp': 522.95, 'buyQty': 1, 'buyAvg': 522.3, 'buyVal': 522.3, 'sellQty': 1, 'sellAvg': 522.85, 'sellVal': 522.85, 'slNo': 0, 'fyToken': '10100000003045', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:SBIN-EQ', 'id': 'NSE:SBIN-EQ-INTRADAY', 'qtyMultiplier': 1.0}], 'overall': {'count_total': 1, 'count_open': 0, 'pl_total': 0.55, 'pl_realized': 0.55, 'pl_unrealized': 0.0}} 17 | 18 | 1658907294067 :: get_profile :: SLWIS8N2SP-100:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZnllcnMuaW4iLCJpYXQiOjE2NTg5MDY5ODYsImV4cCI6MTY1ODk2ODI0NiwibmJmIjoxNjU4OTA2OTg2LCJhdWQiOlsieDowIiwieDoxIiwieDoyIiwiZDoxIiwiZDoyIiwieDoxIiwieDowIl0sInN1YiI6ImFjY2Vzc190b2tlbiIsImF0X2hhc2giOiJnQUFBQUFCaTRPbHE4ZVZtdlBSRWlJYk9mcGNUZ3Bma1RmYjlMZUdZWW41aHIycmx4Ym5WWnY0X2xibDdYaWNPVWZfeTFxTkp6TEVBZ2lHNVNyRDFEYUZpN1ZXQWxCM1FCVVlCNHhaeURDSWRYQ0Y4LXljMG5lcz0iLCJkaXNwbGF5X25hbWUiOiJERUJBTlNIVSBST1VUIiwiZnlfaWQiOiJYRDExODUwIiwiYXBwVHlwZSI6MTAwLCJwb2FfZmxhZyI6Ik4ifQ.HIjYsLtPzqKgXLXUYGXHc66Y4j1B2bKLEbLzTuXRdek :: 1658907294523 :: {'s': 'ok', 'code': 200, 'message': '', 'data': {'fy_id': 'XD11850', 'name': 'DEBANSHU ROUT', 'image': None, 'display_name': None, 'pin_change_date': '25-06-2022 12:11:59', 'email_id': 'debanshurout@gmail.com', 'pwd_change_date': '23-07-2022 11:51:52', 'PAN': '---------', 'pwd_to_expire': 147}} 19 | 20 | 1658907294524 :: tradebook :: None :: 1658907294690 :: {'s': 'ok', 'code': 200, 'message': '', 'tradeBook': [{'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:44', 'orderNumber': '122072767477', 'exchangeOrderNo': '1300000013874648', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.9, 'tradeValue': 522.9, 'tradeNumber': '78408449', 'id': '78408449', 'row': 1, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:00', 'orderNumber': '122072767397', 'exchangeOrderNo': '1300000013844692', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.85, 'tradeValue': 522.85, 'tradeNumber': '78402095', 'id': '78402095', 'row': 2, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 12:58:53', 'orderNumber': '122072766357', 'exchangeOrderNo': '1300000013600000', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.3, 'tradeValue': 522.3, 'tradeNumber': '78352007', 'id': '78352007', 'row': 3, 'symbol': 'NSE:SBIN-EQ'}]} 21 | 22 | 1658907294691 :: orderBook :: :: 1658907294897 :: {'s': 'ok', 'code': 200, 'message': '', 'orderBook': [{'orderDateTime': '27-Jul-2022 13:04:44', 'id': '122072767477', 'exchOrdId': '1300000013874648', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 1, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767477:2', 'tradedPrice': 522.9, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.6, 'chp': 1.67, 'lp': 522.8, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 13:04:00', 'id': '122072767397', 'exchOrdId': '1300000013844692', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 2, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767397:2', 'tradedPrice': 522.85, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.6, 'chp': 1.67, 'lp': 522.8, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 12:58:53', 'id': '122072766357', 'exchOrdId': '1300000013600000', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 3, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072766357:2', 'tradedPrice': 522.3, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.6, 'chp': 1.67, 'lp': 522.8, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}]} 23 | 24 | 1658907294898 :: positions :: :: 1658907295060 :: {'s': 'ok', 'code': 200, 'message': '', 'netPositions': [{'netQty': 1, 'qty': 1, 'avgPrice': 522.6, 'netAvg': 522.35, 'side': 1, 'productType': 'INTRADAY', 'realized_profit': 0.25, 'unrealized_profit': 0.3, 'pl': 0.55, 'ltp': 522.9, 'buyQty': 2, 'buyAvg': 522.6, 'buyVal': 1045.2, 'sellQty': 1, 'sellAvg': 522.85, 'sellVal': 522.85, 'slNo': 0, 'fyToken': '10100000003045', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:SBIN-EQ', 'id': 'NSE:SBIN-EQ-INTRADAY', 'qtyMultiplier': 1.0}], 'overall': {'count_total': 1, 'count_open': 1, 'pl_total': 0.55, 'pl_realized': 0.25, 'pl_unrealized': 0.3}} 25 | 26 | 1658907337150 :: get_profile :: SLWIS8N2SP-100:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZnllcnMuaW4iLCJpYXQiOjE2NTg5MDY5ODYsImV4cCI6MTY1ODk2ODI0NiwibmJmIjoxNjU4OTA2OTg2LCJhdWQiOlsieDowIiwieDoxIiwieDoyIiwiZDoxIiwiZDoyIiwieDoxIiwieDowIl0sInN1YiI6ImFjY2Vzc190b2tlbiIsImF0X2hhc2giOiJnQUFBQUFCaTRPbHE4ZVZtdlBSRWlJYk9mcGNUZ3Bma1RmYjlMZUdZWW41aHIycmx4Ym5WWnY0X2xibDdYaWNPVWZfeTFxTkp6TEVBZ2lHNVNyRDFEYUZpN1ZXQWxCM1FCVVlCNHhaeURDSWRYQ0Y4LXljMG5lcz0iLCJkaXNwbGF5X25hbWUiOiJERUJBTlNIVSBST1VUIiwiZnlfaWQiOiJYRDExODUwIiwiYXBwVHlwZSI6MTAwLCJwb2FfZmxhZyI6Ik4ifQ.HIjYsLtPzqKgXLXUYGXHc66Y4j1B2bKLEbLzTuXRdek :: 1658907337445 :: {'s': 'ok', 'code': 200, 'message': '', 'data': {'fy_id': 'XD11850', 'name': 'DEBANSHU ROUT', 'image': None, 'display_name': None, 'pin_change_date': '25-06-2022 12:11:59', 'email_id': 'debanshurout@gmail.com', 'pwd_change_date': '23-07-2022 11:51:52', 'PAN': '---------', 'pwd_to_expire': 147}} 27 | 28 | 1658907337447 :: tradebook :: None :: 1658907337660 :: {'s': 'ok', 'code': 200, 'message': '', 'tradeBook': [{'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:05:30', 'orderNumber': '122072767597', 'exchangeOrderNo': '1300000013905419', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000002885', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 2416.45, 'tradeValue': 2416.45, 'tradeNumber': '78415268', 'id': '78415268', 'row': 1, 'symbol': 'NSE:RELIANCE-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:44', 'orderNumber': '122072767477', 'exchangeOrderNo': '1300000013874648', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.9, 'tradeValue': 522.9, 'tradeNumber': '78408449', 'id': '78408449', 'row': 2, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:00', 'orderNumber': '122072767397', 'exchangeOrderNo': '1300000013844692', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.85, 'tradeValue': 522.85, 'tradeNumber': '78402095', 'id': '78402095', 'row': 3, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 12:58:53', 'orderNumber': '122072766357', 'exchangeOrderNo': '1300000013600000', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.3, 'tradeValue': 522.3, 'tradeNumber': '78352007', 'id': '78352007', 'row': 4, 'symbol': 'NSE:SBIN-EQ'}]} 29 | 30 | 1658907337661 :: orderBook :: :: 1658907337865 :: {'s': 'ok', 'code': 200, 'message': '', 'orderBook': [{'orderDateTime': '27-Jul-2022 13:05:30', 'id': '122072767597', 'exchOrdId': '1300000013905419', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 1, 'fyToken': '10100000002885', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767597:2', 'tradedPrice': 2416.45, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:RELIANCE-EQ', 'ch': -4.9, 'chp': -0.2, 'lp': 2416.6, 'ex_sym': 'RELIANCE', 'description': 'RELIANCE INDUSTRIES LTD'}, {'orderDateTime': '27-Jul-2022 13:04:44', 'id': '122072767477', 'exchOrdId': '1300000013874648', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 2, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767477:2', 'tradedPrice': 522.9, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.55, 'chp': 1.66, 'lp': 522.75, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 13:04:00', 'id': '122072767397', 'exchOrdId': '1300000013844692', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 3, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767397:2', 'tradedPrice': 522.85, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.55, 'chp': 1.66, 'lp': 522.75, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 12:58:53', 'id': '122072766357', 'exchOrdId': '1300000013600000', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 4, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072766357:2', 'tradedPrice': 522.3, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.55, 'chp': 1.66, 'lp': 522.75, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}]} 31 | 32 | 1658907337866 :: positions :: :: 1658907338071 :: {'s': 'ok', 'code': 200, 'message': '', 'netPositions': [{'netQty': -1, 'qty': 1, 'avgPrice': 2416.45, 'netAvg': 2416.45, 'side': -1, 'productType': 'INTRADAY', 'realized_profit': 0.0, 'unrealized_profit': -0.15, 'pl': -0.15, 'ltp': 2416.6, 'buyQty': 0, 'buyAvg': 0.0, 'buyVal': 0.0, 'sellQty': 1, 'sellAvg': 2416.45, 'sellVal': 2416.45, 'slNo': 0, 'fyToken': '10100000002885', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:RELIANCE-EQ', 'id': 'NSE:RELIANCE-EQ-INTRADAY', 'qtyMultiplier': 1.0}, {'netQty': 1, 'qty': 1, 'avgPrice': 522.6, 'netAvg': 522.35, 'side': 1, 'productType': 'INTRADAY', 'realized_profit': 0.25, 'unrealized_profit': 0.2, 'pl': 0.45, 'ltp': 522.8, 'buyQty': 2, 'buyAvg': 522.6, 'buyVal': 1045.2, 'sellQty': 1, 'sellAvg': 522.85, 'sellVal': 522.85, 'slNo': 1, 'fyToken': '10100000003045', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:SBIN-EQ', 'id': 'NSE:SBIN-EQ-INTRADAY', 'qtyMultiplier': 1.0}], 'overall': {'count_total': 2, 'count_open': 2, 'pl_total': 0.3, 'pl_realized': 0.25, 'pl_unrealized': 0.05}} 33 | 34 | 1658907375727 :: get_profile :: SLWIS8N2SP-100:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZnllcnMuaW4iLCJpYXQiOjE2NTg5MDY5ODYsImV4cCI6MTY1ODk2ODI0NiwibmJmIjoxNjU4OTA2OTg2LCJhdWQiOlsieDowIiwieDoxIiwieDoyIiwiZDoxIiwiZDoyIiwieDoxIiwieDowIl0sInN1YiI6ImFjY2Vzc190b2tlbiIsImF0X2hhc2giOiJnQUFBQUFCaTRPbHE4ZVZtdlBSRWlJYk9mcGNUZ3Bma1RmYjlMZUdZWW41aHIycmx4Ym5WWnY0X2xibDdYaWNPVWZfeTFxTkp6TEVBZ2lHNVNyRDFEYUZpN1ZXQWxCM1FCVVlCNHhaeURDSWRYQ0Y4LXljMG5lcz0iLCJkaXNwbGF5X25hbWUiOiJERUJBTlNIVSBST1VUIiwiZnlfaWQiOiJYRDExODUwIiwiYXBwVHlwZSI6MTAwLCJwb2FfZmxhZyI6Ik4ifQ.HIjYsLtPzqKgXLXUYGXHc66Y4j1B2bKLEbLzTuXRdek :: 1658907375901 :: {'s': 'ok', 'code': 200, 'message': '', 'data': {'fy_id': 'XD11850', 'name': 'DEBANSHU ROUT', 'image': None, 'display_name': None, 'pin_change_date': '25-06-2022 12:11:59', 'email_id': 'debanshurout@gmail.com', 'pwd_change_date': '23-07-2022 11:51:52', 'PAN': '---------', 'pwd_to_expire': 147}} 35 | 36 | 1658907375902 :: tradebook :: None :: 1658907376102 :: {'s': 'ok', 'code': 200, 'message': '', 'tradeBook': [{'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:06:00', 'orderNumber': '122072767717', 'exchangeOrderNo': '1300000013927127', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.8, 'tradeValue': 522.8, 'tradeNumber': '78419738', 'id': '78419738', 'row': 1, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:05:30', 'orderNumber': '122072767597', 'exchangeOrderNo': '1300000013905419', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000002885', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 2416.45, 'tradeValue': 2416.45, 'tradeNumber': '78415268', 'id': '78415268', 'row': 2, 'symbol': 'NSE:RELIANCE-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:44', 'orderNumber': '122072767477', 'exchangeOrderNo': '1300000013874648', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.9, 'tradeValue': 522.9, 'tradeNumber': '78408449', 'id': '78408449', 'row': 3, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:00', 'orderNumber': '122072767397', 'exchangeOrderNo': '1300000013844692', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.85, 'tradeValue': 522.85, 'tradeNumber': '78402095', 'id': '78402095', 'row': 4, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 12:58:53', 'orderNumber': '122072766357', 'exchangeOrderNo': '1300000013600000', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.3, 'tradeValue': 522.3, 'tradeNumber': '78352007', 'id': '78352007', 'row': 5, 'symbol': 'NSE:SBIN-EQ'}]} 37 | 38 | 1658907376103 :: orderBook :: :: 1658907376615 :: {'s': 'ok', 'code': 200, 'message': '', 'orderBook': [{'orderDateTime': '27-Jul-2022 13:06:00', 'id': '122072767717', 'exchOrdId': '1300000013927127', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 1, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767717:2', 'tradedPrice': 522.8, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 13:05:30', 'id': '122072767597', 'exchOrdId': '1300000013905419', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 2, 'fyToken': '10100000002885', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767597:2', 'tradedPrice': 2416.45, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:RELIANCE-EQ', 'ch': -3.7, 'chp': -0.15, 'lp': 2417.8, 'ex_sym': 'RELIANCE', 'description': 'RELIANCE INDUSTRIES LTD'}, {'orderDateTime': '27-Jul-2022 13:04:44', 'id': '122072767477', 'exchOrdId': '1300000013874648', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 3, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767477:2', 'tradedPrice': 522.9, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 13:04:00', 'id': '122072767397', 'exchOrdId': '1300000013844692', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 4, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767397:2', 'tradedPrice': 522.85, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 12:58:53', 'id': '122072766357', 'exchOrdId': '1300000013600000', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 5, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072766357:2', 'tradedPrice': 522.3, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}]} 39 | 40 | 1658907376617 :: positions :: :: 1658907376833 :: {'s': 'ok', 'code': 200, 'message': '', 'netPositions': [{'netQty': -1, 'qty': 1, 'avgPrice': 2416.45, 'netAvg': 2416.45, 'side': -1, 'productType': 'INTRADAY', 'realized_profit': 0.0, 'unrealized_profit': -1.35, 'pl': -1.35, 'ltp': 2417.8, 'buyQty': 0, 'buyAvg': 0.0, 'buyVal': 0.0, 'sellQty': 1, 'sellAvg': 2416.45, 'sellVal': 2416.45, 'slNo': 0, 'fyToken': '10100000002885', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:RELIANCE-EQ', 'id': 'NSE:RELIANCE-EQ-INTRADAY', 'qtyMultiplier': 1.0}, {'netQty': 0, 'qty': 0, 'avgPrice': 0, 'netAvg': 0.0, 'side': 0, 'productType': 'INTRADAY', 'realized_profit': 0.46, 'unrealized_profit': 0.0, 'pl': 0.46, 'ltp': 522.85, 'buyQty': 2, 'buyAvg': 522.6, 'buyVal': 1045.2, 'sellQty': 2, 'sellAvg': 522.83, 'sellVal': 1045.65, 'slNo': 1, 'fyToken': '10100000003045', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:SBIN-EQ', 'id': 'NSE:SBIN-EQ-INTRADAY', 'qtyMultiplier': 1.0}], 'overall': {'count_total': 2, 'count_open': 1, 'pl_total': -0.89, 'pl_realized': 0.46, 'pl_unrealized': -1.35}} 41 | 42 | 1658907417793 :: get_profile :: SLWIS8N2SP-100:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZnllcnMuaW4iLCJpYXQiOjE2NTg5MDY5ODYsImV4cCI6MTY1ODk2ODI0NiwibmJmIjoxNjU4OTA2OTg2LCJhdWQiOlsieDowIiwieDoxIiwieDoyIiwiZDoxIiwiZDoyIiwieDoxIiwieDowIl0sInN1YiI6ImFjY2Vzc190b2tlbiIsImF0X2hhc2giOiJnQUFBQUFCaTRPbHE4ZVZtdlBSRWlJYk9mcGNUZ3Bma1RmYjlMZUdZWW41aHIycmx4Ym5WWnY0X2xibDdYaWNPVWZfeTFxTkp6TEVBZ2lHNVNyRDFEYUZpN1ZXQWxCM1FCVVlCNHhaeURDSWRYQ0Y4LXljMG5lcz0iLCJkaXNwbGF5X25hbWUiOiJERUJBTlNIVSBST1VUIiwiZnlfaWQiOiJYRDExODUwIiwiYXBwVHlwZSI6MTAwLCJwb2FfZmxhZyI6Ik4ifQ.HIjYsLtPzqKgXLXUYGXHc66Y4j1B2bKLEbLzTuXRdek :: 1658907417958 :: {'s': 'ok', 'code': 200, 'message': '', 'data': {'fy_id': 'XD11850', 'name': 'DEBANSHU ROUT', 'image': None, 'display_name': None, 'pin_change_date': '25-06-2022 12:11:59', 'email_id': 'debanshurout@gmail.com', 'pwd_change_date': '23-07-2022 11:51:52', 'PAN': '---------', 'pwd_to_expire': 147}} 43 | 44 | 1658907417959 :: tradebook :: None :: 1658907418140 :: {'s': 'ok', 'code': 200, 'message': '', 'tradeBook': [{'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:06:39', 'orderNumber': '122072767867', 'exchangeOrderNo': '1300000013955565', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000002885', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 2418.35, 'tradeValue': 2418.35, 'tradeNumber': '78425581', 'id': '78425581', 'row': 1, 'symbol': 'NSE:RELIANCE-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:06:00', 'orderNumber': '122072767717', 'exchangeOrderNo': '1300000013927127', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.8, 'tradeValue': 522.8, 'tradeNumber': '78419738', 'id': '78419738', 'row': 2, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:05:30', 'orderNumber': '122072767597', 'exchangeOrderNo': '1300000013905419', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000002885', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 2416.45, 'tradeValue': 2416.45, 'tradeNumber': '78415268', 'id': '78415268', 'row': 3, 'symbol': 'NSE:RELIANCE-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:44', 'orderNumber': '122072767477', 'exchangeOrderNo': '1300000013874648', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.9, 'tradeValue': 522.9, 'tradeNumber': '78408449', 'id': '78408449', 'row': 4, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 13:04:00', 'orderNumber': '122072767397', 'exchangeOrderNo': '1300000013844692', 'exchange': 10, 'transactionType': -1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.85, 'tradeValue': 522.85, 'tradeNumber': '78402095', 'id': '78402095', 'row': 5, 'symbol': 'NSE:SBIN-EQ'}, {'clientId': 'XD11850', 'orderDateTime': '27-Jul-2022 12:58:53', 'orderNumber': '122072766357', 'exchangeOrderNo': '1300000013600000', 'exchange': 10, 'transactionType': 1, 'segment': 10, 'orderType': 2, 'fyToken': '10100000003045', 'productType': 'INTRADAY', 'tradedQty': 1, 'tradePrice': 522.3, 'tradeValue': 522.3, 'tradeNumber': '78352007', 'id': '78352007', 'row': 6, 'symbol': 'NSE:SBIN-EQ'}]} 45 | 46 | 1658907418141 :: orderBook :: :: 1658907418363 :: {'s': 'ok', 'code': 200, 'message': '', 'orderBook': [{'orderDateTime': '27-Jul-2022 13:06:39', 'id': '122072767867', 'exchOrdId': '1300000013955565', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 1, 'fyToken': '10100000002885', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767867:2', 'tradedPrice': 2418.35, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:RELIANCE-EQ', 'ch': -2.9, 'chp': -0.12, 'lp': 2418.6, 'ex_sym': 'RELIANCE', 'description': 'RELIANCE INDUSTRIES LTD'}, {'orderDateTime': '27-Jul-2022 13:06:00', 'id': '122072767717', 'exchOrdId': '1300000013927127', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 2, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767717:2', 'tradedPrice': 522.8, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 13:05:30', 'id': '122072767597', 'exchOrdId': '1300000013905419', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 3, 'fyToken': '10100000002885', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767597:2', 'tradedPrice': 2416.45, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:RELIANCE-EQ', 'ch': -2.9, 'chp': -0.12, 'lp': 2418.6, 'ex_sym': 'RELIANCE', 'description': 'RELIANCE INDUSTRIES LTD'}, {'orderDateTime': '27-Jul-2022 13:04:44', 'id': '122072767477', 'exchOrdId': '1300000013874648', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 4, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767477:2', 'tradedPrice': 522.9, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 13:04:00', 'id': '122072767397', 'exchOrdId': '1300000013844692', 'side': -1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 5, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072767397:2', 'tradedPrice': 522.85, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}, {'orderDateTime': '27-Jul-2022 12:58:53', 'id': '122072766357', 'exchOrdId': '1300000013600000', 'side': 1, 'segment': 10, 'instrument': 0, 'productType': 'INTRADAY', 'status': 2, 'qty': 1, 'remainingQuantity': 0, 'filledQty': 1, 'limitPrice': 0.0, 'stopPrice': 0.0, 'type': 2, 'discloseQty': 0, 'dqQtyRem': 0, 'orderValidity': 'DAY', 'source': 'W', 'slNo': 6, 'fyToken': '10100000003045', 'offlineOrder': False, 'message': 'TRADE CONFIRMED', 'orderNumStatus': '122072766357:2', 'tradedPrice': 522.3, 'exchange': 10, 'pan': 'CQEPR0695E', 'clientId': 'XD11850', 'symbol': 'NSE:SBIN-EQ', 'ch': 8.65, 'chp': 1.68, 'lp': 522.85, 'ex_sym': 'SBIN', 'description': 'STATE BANK OF INDIA'}]} 47 | 48 | 1658907418364 :: positions :: :: 1658907418700 :: {'s': 'ok', 'code': 200, 'message': '', 'netPositions': [{'netQty': 0, 'qty': 0, 'avgPrice': 0, 'netAvg': 0.0, 'side': 0, 'productType': 'INTRADAY', 'realized_profit': -1.9, 'unrealized_profit': 0.0, 'pl': -1.9, 'ltp': 2418.65, 'buyQty': 1, 'buyAvg': 2418.35, 'buyVal': 2418.35, 'sellQty': 1, 'sellAvg': 2416.45, 'sellVal': 2416.45, 'slNo': 0, 'fyToken': '10100000002885', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:RELIANCE-EQ', 'id': 'NSE:RELIANCE-EQ-INTRADAY', 'qtyMultiplier': 1.0}, {'netQty': 0, 'qty': 0, 'avgPrice': 0, 'netAvg': 0.0, 'side': 0, 'productType': 'INTRADAY', 'realized_profit': 0.46, 'unrealized_profit': 0.0, 'pl': 0.46, 'ltp': 522.9, 'buyQty': 2, 'buyAvg': 522.6, 'buyVal': 1045.2, 'sellQty': 2, 'sellAvg': 522.83, 'sellVal': 1045.65, 'slNo': 1, 'fyToken': '10100000003045', 'dummy': ' ', 'crossCurrency': 'N', 'rbiRefRate': 1.0, 'qtyMulti_com': 1.0, 'segment': 10, 'symbol': 'NSE:SBIN-EQ', 'id': 'NSE:SBIN-EQ-INTRADAY', 'qtyMultiplier': 1.0}], 'overall': {'count_total': 2, 'count_open': 0, 'pl_total': -1.44, 'pl_realized': -1.44, 'pl_unrealized': 0.0}} 49 | -------------------------------------------------------------------------------- /log/2022-08-02.txt: -------------------------------------------------------------------------------- 1 | 2 | 1659383468944 :: get_profile :: SLWIS8N2SP-100:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZnllcnMuaW4iLCJpYXQiOjE2NTg5MDY5ODYsImV4cCI6MTY1ODk2ODI0NiwibmJmIjoxNjU4OTA2OTg2LCJhdWQiOlsieDowIiwieDoxIiwieDoyIiwiZDoxIiwiZDoyIiwieDoxIiwieDowIl0sInN1YiI6ImFjY2Vzc190b2tlbiIsImF0X2hhc2giOiJnQUFBQUFCaTRPbHE4ZVZtdlBSRWlJYk9mcGNUZ3Bma1RmYjlMZUdZWW41aHIycmx4Ym5WWnY0X2xibDdYaWNPVWZfeTFxTkp6TEVBZ2lHNVNyRDFEYUZpN1ZXQWxCM1FCVVlCNHhaeURDSWRYQ0Y4LXljMG5lcz0iLCJkaXNwbGF5X25hbWUiOiJERUJBTlNIVSBST1VUIiwiZnlfaWQiOiJYRDExODUwIiwiYXBwVHlwZSI6MTAwLCJwb2FfZmxhZyI6Ik4ifQ.HIjYsLtPzqKgXLXUYGXHc66Y4j1B2bKLEbLzTuXRdek :: 1659383469355 :: {'s': 'error', 'code': -8, 'message': 'Your token has expired. Please generate a token'} 3 | -------------------------------------------------------------------------------- /log/pycharm_log.txt: -------------------------------------------------------------------------------- 1 | Traceback (most recent call last): 2 | File "/Users/debanshu.rout/repo/external/algotrading/fyers_integration/strategy.py", line 280, in 3 | run() 4 | File "/Users/debanshu.rout/repo/external/algotrading/fyers_integration/strategy.py", line 245, in run 5 | curr_time = datetime.datetime.now().hour * 60 + datetime.datetime.now().minute 6 | KeyboardInterrupt 7 | test 8 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | 2 | if __name__ == '__main__': 3 | print("Starting..") -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | asn1crypto==1.5.1 2 | attrs==21.4.0 3 | Automat==22.10.0 4 | boto3==1.17.112 5 | botocore==1.20.112 6 | cachetools==3.1.1 7 | certifi==2021.10.8 8 | cffi==1.15.1 9 | chardet==4.0.0 10 | constantly==15.1.0 11 | credstash==1.14.0 12 | cryptography==2.0.3 13 | enum34==1.1.10 14 | futures==3.4.0 15 | google-auth==2.17.3 16 | hyperlink==21.0.0 17 | idna==2.10 18 | incremental==22.10.0 19 | ipaddress==1.0.23 20 | jmespath==0.10.0 21 | kubernetes==18.20.0 22 | oauthlib==3.1.0 23 | pyasn1==0.4.8 24 | pyasn1-modules==0.2.8 25 | pycparser==2.21 26 | PyHamcrest==1.10.1 27 | python-dateutil==2.8.2 28 | PyYAML==5.4.1 29 | razorpay==1.3.1 30 | requests==2.27.1 31 | requests-oauthlib==1.3.1 32 | rsa==4.5 33 | s3transfer==0.4.2 34 | service-identity==21.1.0 35 | six==1.16.0 36 | Twisted==20.3.0 37 | typing==3.10.0.0 38 | urllib3==1.26.15 39 | websocket-client==0.59.0 40 | zope.interface==5.5.2 41 | kiteconnect==4.2.0 42 | pandas>=1.3.0 43 | service_identity==24.2.0 44 | pyOpenSSL==25.0.0 45 | cryptography==44.0.2 46 | attrs>=19.1.0 47 | pyasn1>=0.6.1 48 | pyasn1-modules>=0.4.2 49 | -------------------------------------------------------------------------------- /zerodha/README.md: -------------------------------------------------------------------------------- 1 | # algo-trading 2 | Algo Trading with Zerodha 3 | 4 | # install packages 5 | pip install -r requirements.txt 6 | 7 | # setup 8 | python setup.py 9 | 10 | # example (place an order) 11 | python simple.py 12 | 13 | # Developer's guide 14 | Check pep8 guidelines before every commit 15 | Follow installation guidelines from here : 16 | https://github.com/cbrueffer/pep8-git-hook 17 | -------------------------------------------------------------------------------- /zerodha/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debanshur/algotrading/4e6fe65f8d5091bcad51437c3641c84d91bdc47f/zerodha/__init__.py -------------------------------------------------------------------------------- /zerodha/backtest.py: -------------------------------------------------------------------------------- 1 | 2 | import datetime 3 | from kiteconnect import KiteConnect 4 | from modules import auth 5 | 6 | """ 7 | 1. Login to kite 8 | """ 9 | userdata = auth.get_userdata() 10 | kite = KiteConnect(api_key=userdata['api_key']) 11 | kite.set_access_token(userdata['access_token']) 12 | 13 | print("******** UserData Loaded ********* : ", datetime.datetime.now()) 14 | 15 | val = 20 16 | 17 | interval = "10minute" 18 | 19 | 20 | #list all tickers you want to trade 21 | #tickerlist = ["BAJAJFINSV"] 22 | #tokenlist = [4268801] 23 | 24 | tickerlist = ["BANKNIFTY20MAYFUT"] 25 | tokenlist = [13430018] 26 | 27 | #F&O nse 100 28 | #tickerlist = ['BAJAJFINSV', 'BRITANNIA', 'ULTRACEMCO', 'BAJFINANCE', 'SRF', 'DRREDDY', 'BAJAJ-AUTO', 'NAUKRI', 'HINDUNILVR', 'ASIANPAINT', 'HDFC', 'HEROMOTOCO', 'TCS', 'NIITTECH', 'DIVISLAB', 'KOTAKBANK', 'PVR', 'TORNTPHARM', 'APOLLOHOSP', 'ACC', 'INDIGO', 'RELIANCE', 'JUBLFOOD', 'PIDILITIND', 'BATAINDIA', 'HDFCBANK', 'PEL', 'LT', 'SIEMENS', 'MGL', 'GODREJPROP', 'SRTRANSFIN', 'COLPAL', 'UBL', 'MUTHOOTFIN', 'TITAN', 'SBILIFE', 'MINDTREE', 'BALKRISIND', 'INDUSINDBK', 'LUPIN', 'RAMCOCEM', 'GRASIM', 'GODREJCP', 'AMARAJABAT', 'HAVELLS', 'VOLTAS', 'BERGEPAINT', 'ESCORTS', 'HDFCLIFE', 'INFY', 'TECHM', 'CUMMINSIND', 'AXISBANK', 'DABUR', 'MCDOWELL-N', 'CIPLA', 'MFSL', 'AUROPHARMA', 'UPL', 'ICICIBANK', 'IGL', 'CENTURYTEX', 'HCLTECH', 'SUNPHARMA', 'JUSTDIAL', 'M&M', 'TVSMOTOR', 'BHARATFORG', 'ICICIPRULI', 'SUNTV', 'CONCOR', 'TATASTEEL', 'BPCL', 'BANDHANBNK', 'BHARTIARTL', 'LICHSGFIN', 'MARICO', 'TATACHEM', 'M&MFIN', 'CADILAHC', 'UJJIVAN', 'BIOCON', 'GLENMARK', 'ADANIPORTS', 'CHOLAFIN', 'RBLBANK', 'HINDPETRO', 'JSWSTEEL', 'TATACONSUM', 'INFRATEL', 'AMBUJACEM', 'PETRONET', 'SBIN', 'TORNTPOWER', 'ZEEL', 'IBULHSGFIN', 'WIPRO', 'ITC', 'DLF'] 29 | #tokenlist = [4268801, 140033, 2952193, 81153, 837889, 225537, 4267265, 3520257, 356865, 60417, 340481, 345089, 2953217, 2955009, 2800641, 492033, 3365633, 900609, 40193, 5633, 2865921, 738561, 4632577, 681985, 94977, 341249, 617473, 2939649, 806401, 4488705, 4576001, 1102337, 3876097, 4278529, 6054401, 897537, 5582849, 3675137, 85761, 1346049, 2672641, 523009, 315393, 2585345, 25601, 2513665, 951809, 103425, 245249, 119553, 408065, 3465729, 486657, 1510401, 197633, 2674433, 177665, 548353, 70401, 2889473, 1270529, 2883073, 160001, 1850625, 857857, 7670273, 519937, 2170625, 108033, 4774913, 3431425, 1215745, 895745, 134657, 579329, 2714625, 511233, 1041153, 871681, 3400961, 2029825, 4369665, 2911489, 1895937, 3861249, 175361, 4708097, 359937, 3001089, 878593, 7458561, 325121, 2905857, 779521, 3529217, 975873, 7712001, 969473, 424961, 3771393] 30 | 31 | #nifty50 32 | #tickerlist = ['BAJAJ-AUTO', 'BAJFINANCE', 'HEROMOTOCO', 'HINDUNILVR', 'TCS', 'HDFC', 'ASIANPAINT', 'RELIANCE', 'KOTAKBANK', 'HDFCBANK', 'LT', 'TITAN', 'INFY', 'CIPLA', 'BHARTIARTL', 'TECHM', 'HCLTECH', 'GRASIM', 'SUNPHARMA', 'INDUSINDBK', 'AXISBANK', 'M&M', 'UPL', 'ICICIBANK', 'BPCL', 'ADANIPORTS', 'TATASTEEL', 'INFRATEL', 'WIPRO', 'JSWSTEEL', 'SBIN', 'ITC', 'POWERGRID', 'ZEEL', 'COALINDIA', 'HINDALCO'] 33 | #tokenlist = [4267265, 81153, 345089, 356865, 2953217, 340481, 60417, 738561, 492033, 341249, 2939649, 897537, 408065, 177665, 2714625, 3465729, 1850625, 315393, 857857, 1346049, 1510401, 519937, 2889473, 1270529, 134657, 3861249, 895745, 7458561, 969473, 3001089, 779521, 424961, 3834113, 975873, 5215745, 348929] 34 | 35 | 36 | 37 | #Lets build a function for the strategy 38 | def strategy(records, token): 39 | total_closing_price = 0 40 | record_count = 0 41 | order_placed = False 42 | last_order_placed = None 43 | last_order_price = 0 44 | profit = 0 45 | 46 | for record in records: 47 | record_count += 1 48 | #print(record) 49 | total_closing_price += record['close'] 50 | 51 | #Moving average is calculated for every 5 ticks 52 | if record_count >= val: 53 | moving_average = total_closing_price/val 54 | #If moving average is greater than the last tick, we place a buy order 55 | if record['close'] > moving_average: 56 | if last_order_placed == "SELL" or last_order_placed is None: 57 | 58 | #If last order was Sell, we need to exit the stock first 59 | if last_order_placed == "SELL": 60 | #print("Exit SELL") 61 | 62 | #Calculate Profit 63 | profit += last_order_price - record['close'] 64 | last_order_price = record['close'] 65 | 66 | #New Buy Order 67 | #print("Place a new BUY Order") 68 | last_order_placed = "BUY" 69 | 70 | #If moving average is less than the last tick and there is a position, place a sell order 71 | elif record['close'] < moving_average: 72 | if last_order_placed == "BUY": 73 | 74 | #As last trade was a buy, lets exit it first 75 | #print("Exit BUY") 76 | 77 | #Calculate Profit again 78 | profit += record['close'] - last_order_price 79 | last_order_price = record['close'] 80 | 81 | #Fresh SELL Order 82 | #print("Place new SELL Order") 83 | last_order_placed = "SELL" 84 | 85 | total_closing_price -= records[record_count - val]['close'] 86 | print("Gross Profit",profit,"\n\n") 87 | #Place the last order 88 | #print(last_order_placed) 89 | place_order(last_order_placed, token) 90 | 91 | 92 | #Place an order based on the transaction type(BUY/SELL) 93 | def place_order(transaction_type, token): 94 | print("**",transaction_type,token) 95 | kite.place_order(variety="regular",tradingsymbol = token, exchange = "NSE", quantity = 1, transaction_type=transaction_type, 96 | order_type="MARKET",product="CNC") 97 | 98 | def start(): 99 | print("************ Backtesting Started *************") 100 | for i in range(0, len(tickerlist)): 101 | 102 | #startdate = enddate - datetime.timedelta(1) 103 | startdate = datetime.datetime(2020, 3, 15) 104 | enddate = datetime.datetime(2020, 4, 15) 105 | #enddate = datetime.datetime.today() 106 | 107 | print(interval) 108 | records = kite.historical_data(tokenlist[i], startdate, enddate, interval) 109 | 110 | #print("\n\n", records) 111 | 112 | #historical_data.get(kite, tokenlist[i], startdate, enddate, interval) 113 | print("\n************* ", tickerlist[i], "************") 114 | strategy(records, tokenlist[i]) 115 | 116 | start() 117 | 118 | 119 | -------------------------------------------------------------------------------- /zerodha/ema_crossover.py: -------------------------------------------------------------------------------- 1 | from kiteconnect import KiteConnect 2 | import datetime 3 | import pandas as pd 4 | import time 5 | 6 | from modules import auth 7 | from modules import historical_data 8 | from indicators import MACD, RSI, EMA, MFI, VWAP 9 | 10 | candlesize = '10minute' 11 | orderslist = {} 12 | mfilist = {} 13 | trailing_sl = {} 14 | one_hour_rsi = 50 15 | one_hour_mfi = 50 16 | reason = "" 17 | 18 | #pd.set_option('display.max_columns',50) 19 | pd.set_option('display.max_rows', None) 20 | print("\n******** Started ********* : ", datetime.datetime.now()) 21 | 22 | """ 23 | 1. Login to kite 24 | """ 25 | userdata = auth.get_userdata() 26 | kite = KiteConnect(api_key=userdata['api_key']) 27 | kite.set_access_token(userdata['access_token']) 28 | 29 | print("******** UserData Loaded ********* : ", datetime.datetime.now()) 30 | 31 | #list all tickers you want to trade 32 | tickerlist = ["RELIANCE"] 33 | tokenlist = [738561] 34 | 35 | #F&O nse 100 36 | #tickerlist = ['BAJAJFINSV', 'BRITANNIA', 'ULTRACEMCO', 'BAJFINANCE', 'SRF', 'DRREDDY', 'BAJAJ-AUTO', 'NAUKRI', 'HINDUNILVR', 'ASIANPAINT', 'HDFC', 'HEROMOTOCO', 'TCS', 'NIITTECH', 'DIVISLAB', 'KOTAKBANK', 'PVR', 'TORNTPHARM', 'APOLLOHOSP', 'ACC', 'INDIGO', 'RELIANCE', 'JUBLFOOD', 'PIDILITIND', 'BATAINDIA', 'HDFCBANK', 'PEL', 'LT', 'SIEMENS', 'MGL', 'GODREJPROP', 'SRTRANSFIN', 'COLPAL', 'UBL', 'MUTHOOTFIN', 'TITAN', 'SBILIFE', 'MINDTREE', 'BALKRISIND', 'INDUSINDBK', 'LUPIN', 'RAMCOCEM', 'GRASIM', 'GODREJCP', 'AMARAJABAT', 'HAVELLS', 'VOLTAS', 'BERGEPAINT', 'ESCORTS', 'HDFCLIFE', 'INFY', 'TECHM', 'CUMMINSIND', 'AXISBANK', 'DABUR', 'MCDOWELL-N', 'CIPLA', 'MFSL', 'AUROPHARMA', 'UPL', 'ICICIBANK', 'IGL', 'CENTURYTEX', 'HCLTECH', 'SUNPHARMA', 'JUSTDIAL', 'M&M', 'TVSMOTOR', 'BHARATFORG', 'ICICIPRULI', 'SUNTV', 'CONCOR', 'TATASTEEL', 'BPCL', 'BANDHANBNK', 'BHARTIARTL', 'LICHSGFIN', 'MARICO', 'TATACHEM', 'M&MFIN', 'CADILAHC', 'UJJIVAN', 'BIOCON', 'GLENMARK', 'ADANIPORTS', 'CHOLAFIN', 'RBLBANK', 'HINDPETRO', 'JSWSTEEL', 'TATACONSUM', 'INFRATEL', 'AMBUJACEM', 'PETRONET', 'SBIN', 'TORNTPOWER', 'ZEEL', 'IBULHSGFIN', 'WIPRO', 'ITC', 'DLF'] 37 | #tokenlist = [4268801, 140033, 2952193, 81153, 837889, 225537, 4267265, 3520257, 356865, 60417, 340481, 345089, 2953217, 2955009, 2800641, 492033, 3365633, 900609, 40193, 5633, 2865921, 738561, 4632577, 681985, 94977, 341249, 617473, 2939649, 806401, 4488705, 4576001, 1102337, 3876097, 4278529, 6054401, 897537, 5582849, 3675137, 85761, 1346049, 2672641, 523009, 315393, 2585345, 25601, 2513665, 951809, 103425, 245249, 119553, 408065, 3465729, 486657, 1510401, 197633, 2674433, 177665, 548353, 70401, 2889473, 1270529, 2883073, 160001, 1850625, 857857, 7670273, 519937, 2170625, 108033, 4774913, 3431425, 1215745, 895745, 134657, 579329, 2714625, 511233, 1041153, 871681, 3400961, 2029825, 4369665, 2911489, 1895937, 3861249, 175361, 4708097, 359937, 3001089, 878593, 7458561, 325121, 2905857, 779521, 3529217, 975873, 7712001, 969473, 424961, 3771393] 38 | 39 | #nifty50 40 | #tickerlist = ['BAJAJ-AUTO', 'BAJFINANCE', 'HEROMOTOCO', 'HINDUNILVR', 'TCS', 'HDFC', 'ASIANPAINT', 'RELIANCE', 'KOTAKBANK', 'HDFCBANK', 'LT', 'TITAN', 'INFY', 'CIPLA', 'BHARTIARTL', 'TECHM', 'HCLTECH', 'GRASIM', 'SUNPHARMA', 'INDUSINDBK', 'AXISBANK', 'M&M', 'UPL', 'ICICIBANK', 'BPCL', 'ADANIPORTS', 'TATASTEEL', 'INFRATEL', 'WIPRO', 'JSWSTEEL', 'SBIN', 'ITC', 'POWERGRID', 'ZEEL', 'COALINDIA', 'HINDALCO'] 41 | #tokenlist = [4267265, 81153, 345089, 356865, 2953217, 340481, 60417, 738561, 492033, 341249, 2939649, 897537, 408065, 177665, 2714625, 3465729, 1850625, 315393, 857857, 1346049, 1510401, 519937, 2889473, 1270529, 134657, 3861249, 895745, 7458561, 969473, 3001089, 779521, 424961, 3834113, 975873, 5215745, 348929] 42 | 43 | 44 | def compute_data(token): 45 | global one_hour_rsi 46 | global one_hour_mfi 47 | #enddate = datetime.datetime(2020, 5, 4, 15,30,0,0) 48 | enddate = datetime.datetime.today() 49 | startdate = enddate - datetime.timedelta(15) #12 50 | try: 51 | df = historical_data.get(kite, token, startdate, enddate, candlesize) 52 | df = EMA.calc(df,'close','ema_5',5) 53 | df = EMA.calc(df,'close','ema_20',20) 54 | df = MACD.calc(df) 55 | df = VWAP.calc(df) 56 | df = RSI.calc(df) 57 | df = MFI.calc(df) 58 | 59 | hour_data = historical_data.get(kite, token, startdate, enddate, "60minute") 60 | hour_data = RSI.calc(hour_data) 61 | hour_data = MFI.calc(hour_data) 62 | one_hour_rsi = hour_data.RSI_14.values[-2] 63 | one_hour_mfi = hour_data.mfi.values[-2] 64 | hour_data.drop(['RSI_14', 'mfi'], inplace=True, axis=1) 65 | 66 | except Exception as e: 67 | print("******* ERROR Computing Historical Data ********", token, e) 68 | return df 69 | 70 | 71 | def exit_data(token): 72 | #enddate = datetime.datetime(2020, 5, 4, 15,30,0,0) 73 | enddate = datetime.datetime.today() 74 | startdate = enddate - datetime.timedelta(15) #12 75 | try: 76 | df = historical_data.get(kite, token, startdate, enddate, candlesize) 77 | df = MACD.calc(df) 78 | df = MFI.calc(df) 79 | 80 | except Exception as e: 81 | print("******* ERROR Computing Historical Data ********", token, e) 82 | return df 83 | 84 | 85 | def check_volume(open, volume): 86 | if open <= 400 and volume >= 1000000: 87 | return True 88 | elif open > 400 and open <=700 and volume >= 500000: 89 | return True 90 | elif open > 700 and open <=1000 and volume >= 300000: 91 | return True 92 | elif open > 1000 and volume >= 100000: 93 | return True 94 | else: 95 | return False 96 | 97 | 98 | def run_strategy(): 99 | global orderslist 100 | global mfilist 101 | global trailing_sl 102 | global one_hour_rsi 103 | global one_hour_mfi 104 | for i in range(0, len(tickerlist)): 105 | 106 | if (tickerlist[i] in orderslist): 107 | continue 108 | try: 109 | histdata = compute_data(tokenlist[i]) 110 | print(histdata) 111 | pre_ema5 = histdata.ema_5.values[-3] 112 | pre_ema20 = histdata.ema_20.values[-3] 113 | pre_close = histdata.close.values[-3] 114 | 115 | ema5 = histdata.ema_5.values[-2] 116 | ema20 = histdata.ema_20.values[-2] 117 | macd = histdata.hist_12_26_9.values[-2] 118 | mfi = histdata.mfi.values[-2] 119 | vwap = histdata.vwap.values[-2] 120 | rsi = histdata.RSI_14.values[-2] 121 | 122 | open = histdata.open.values[-2] 123 | close = histdata.close.values[-2] 124 | high = histdata.high.values[-2] 125 | low = histdata.low.values[-2] 126 | 127 | volume = histdata.volume.values[-2] 128 | has_volume = check_volume(histdata.open.values[-2], volume) 129 | 130 | perc_change = ((close - pre_close) * 100) / open 131 | 132 | #print("-----------------------------------------------------------------------------------------") 133 | print(tickerlist[i],open,close,"::::",round(ema5,2),round(ema20,2),round(macd,4),int(mfi),int(rsi),\ 134 | int(one_hour_mfi),int(one_hour_rsi),round(vwap,2),round(perc_change,2),volume) 135 | 136 | if (ema5 > ema20) and (pre_ema5 < pre_ema20) and (macd > 0) and (close > vwap) and \ 137 | (one_hour_mfi > 40) and (one_hour_mfi < 70) and (one_hour_rsi > 40) and (mfi < 70): 138 | if abs(perc_change) > 4: 139 | print("Ignoring spike") 140 | continue 141 | 142 | quantity = round(max(1, (2500/high))) 143 | quantity = int(quantity) 144 | 145 | orderslist[tickerlist[i]] = close 146 | mfilist[tickerlist[i]] = mfi 147 | trailing_sl[tickerlist[i]] = 0 148 | 149 | order = kite.place_order(exchange='NSE', 150 | tradingsymbol=tickerlist[i], 151 | transaction_type="BUY", 152 | quantity=quantity, 153 | product='MIS', 154 | order_type='MARKET', 155 | validity='DAY', 156 | variety="regular" 157 | ) 158 | 159 | print(" Order : ","BUY",tickerlist[i],"quantity:",quantity,"macd",round(macd,4),"mfi:",round(mfi,2),"rsi:",round(rsi,2),\ 160 | "mfi_1hour:",round(one_hour_mfi,2),"rsi_1hour:",round(one_hour_rsi,2),"volume:",volume,datetime.datetime.now()) 161 | 162 | if (ema5 < ema20) and (pre_ema5 > pre_ema20) and (macd < 0) and (close < vwap) and (one_hour_mfi > 30) and (one_hour_mfi < 60) and (one_hour_rsi < 60): 163 | if not has_volume: 164 | print("Sorry, Volume is low") 165 | #continue 166 | 167 | if abs(perc_change) > 4: 168 | print("Ignoring spike") 169 | continue 170 | 171 | quantity = round(max(1, (2500/high))) 172 | quantity = int(quantity) 173 | 174 | orderslist[tickerlist[i]] = close 175 | mfilist[tickerlist[i]] = mfi 176 | trailing_sl[tickerlist[i]] = 0 177 | 178 | order = kite.place_order(exchange='NSE', 179 | tradingsymbol=tickerlist[i], 180 | transaction_type="SELL", 181 | quantity=quantity, 182 | product='MIS', 183 | order_type='MARKET', 184 | validity='DAY', 185 | variety="regular" 186 | ) 187 | 188 | print(" Order : ","SELL",tickerlist[i],"quantity:",quantity,"macd",round(macd,4),"mfi:",round(mfi,2),"rsi:",round(rsi,2),\ 189 | "mfi_1hour:",round(one_hour_mfi,2),"rsi_1hour:",round(one_hour_rsi,2),"volume:",volume,datetime.datetime.now()) 190 | 191 | except Exception as e : 192 | print(e) 193 | 194 | 195 | def check_perc(tradingsymbol, average_price, last_price): 196 | global trailing_sl 197 | global reason 198 | exit_con = 0 199 | perc = (abs(average_price - last_price )*100) / average_price 200 | if perc > 2.05: 201 | trailing_sl[tradingsymbol] = 2 202 | elif perc > 1.55: 203 | trailing_sl[tradingsymbol] = 1.5 204 | elif perc > 1.05: 205 | trailing_sl[tradingsymbol] = 1 206 | elif perc > 0.55: 207 | trailing_sl[tradingsymbol] = 0.5 208 | else : 209 | trailing_sl[tradingsymbol] = 0 210 | 211 | if trailing_sl[tradingsymbol] == 2: 212 | if perc < 1.95: 213 | exit_con = 1 214 | reason = "immediate. Percentage Exit 2%" 215 | 216 | if trailing_sl[tradingsymbol] == 1.5: 217 | if perc < 1.45: 218 | exit_con = 1 219 | reason = "immediate. Percentage Exit 1.5%" 220 | 221 | if trailing_sl[tradingsymbol] == 1: 222 | if perc < 0.95: 223 | exit_con = 1 224 | reason = "immediate. Percentage Exit 1%" 225 | 226 | if trailing_sl[tradingsymbol] == 0.5: 227 | if perc < 0.5: 228 | exit_con = 1 229 | reason = "immediate. Percentage Exit 0.5%" 230 | return exit_con 231 | 232 | 233 | def exit_buy(data, idx, immediate, force): 234 | #tradingsymbol instrument_token quantity average_price last_price 235 | #print(data) 236 | global trailing_sl 237 | global reason 238 | token = data['instrument_token'][idx] 239 | average_price = data['average_price'][idx] 240 | last_price = data['last_price'][idx] 241 | tradingsymbol = data['tradingsymbol'][idx] 242 | quantity = data['quantity'][idx] 243 | 244 | if force: 245 | reason = "Time up" 246 | 247 | if average_price <=0: 248 | return 249 | 250 | 251 | exit_con = 0 252 | 253 | if immediate: 254 | exit_con = check_perc(tradingsymbol, average_price, last_price) 255 | 256 | else : 257 | histdata = exit_data(token) 258 | if tradingsymbol not in mfilist: 259 | mfilist[tradingsymbol] = histdata.mfi.values[-2] 260 | 261 | else: 262 | if mfilist[tradingsymbol] < histdata.mfi.values[-2]: 263 | mfilist[tradingsymbol] = histdata.mfi.values[-2] 264 | 265 | print(tradingsymbol,last_price,histdata.hist_12_26_9.values[-2],mfilist[tradingsymbol],histdata.mfi.values[-2],trailing_sl[tradingsymbol]) 266 | 267 | exit_con = check_perc(tradingsymbol, average_price, last_price) 268 | 269 | if histdata.hist_12_26_9.values[-2] < 0: 270 | exit_con = 1 271 | reason = "macd change" 272 | 273 | elif mfilist[tradingsymbol] > 79: 274 | if histdata.mfi.values[-2] < 69: 275 | exit_con = 1 276 | reason = "mfi change" 277 | 278 | if exit_con == 1 or force: 279 | order = kite.place_order(exchange='NSE', 280 | tradingsymbol=tradingsymbol, 281 | transaction_type="SELL", 282 | quantity=quantity, 283 | product='MIS', 284 | order_type='MARKET', 285 | validity='DAY', 286 | variety="regular" 287 | ) 288 | 289 | print(" Exit : ","SELL",tradingsymbol,"price:",last_price,reason,datetime.datetime.now()) 290 | if tradingsymbol in orderslist: 291 | del orderslist[tradingsymbol] 292 | if tradingsymbol in mfilist: 293 | del mfilist[tradingsymbol] 294 | if tradingsymbol in trailing_sl: 295 | del trailing_sl[tradingsymbol] 296 | 297 | 298 | def exit_sell(data,idx, immediate, force): 299 | #tradingsymbol instrument_token quantity average_price last_price 300 | #print(data) 301 | global trailing_sl 302 | global reason 303 | token = data['instrument_token'][idx] 304 | average_price = data['average_price'][idx] 305 | last_price = data['last_price'][idx] 306 | tradingsymbol = data['tradingsymbol'][idx] 307 | quantity = abs(data['quantity'][idx]) 308 | 309 | if force: 310 | reason = "Time up" 311 | 312 | if average_price <=0: 313 | return 314 | 315 | 316 | exit_con = 0 317 | 318 | 319 | if immediate: 320 | exit_con = check_perc(tradingsymbol, average_price, last_price) 321 | 322 | else : 323 | histdata = exit_data(token) 324 | if tradingsymbol not in mfilist: 325 | mfilist[tradingsymbol] = histdata.mfi.values[-2] 326 | 327 | else: 328 | if mfilist[tradingsymbol] > histdata.mfi.values[-2]: 329 | mfilist[tradingsymbol] = histdata.mfi.values[-2] 330 | 331 | print(tradingsymbol,last_price,histdata.hist_12_26_9.values[-2],mfilist[tradingsymbol],histdata.mfi.values[-2],trailing_sl[tradingsymbol]) 332 | 333 | exit_con = check_perc(tradingsymbol,average_price, last_price) 334 | 335 | if histdata.hist_12_26_9.values[-2] > 0: 336 | exit_con = 1 337 | reason = "macd change" 338 | 339 | elif mfilist[tradingsymbol] < 21: 340 | if histdata.mfi.values[-2] > 31: 341 | exit_con = 1 342 | reason = "mfi condition" 343 | 344 | if exit_con == 1 or force: 345 | order = kite.place_order(exchange='NSE', 346 | tradingsymbol=tradingsymbol, 347 | transaction_type="BUY", 348 | quantity=quantity, 349 | product='MIS', 350 | order_type='MARKET', 351 | validity='DAY', 352 | variety="regular" 353 | ) 354 | 355 | print(" Exit : ","BUY",tradingsymbol,"price:",last_price,reason,datetime.datetime.now()) 356 | if tradingsymbol in orderslist: 357 | del orderslist[tradingsymbol] 358 | if tradingsymbol in mfilist: 359 | del mfilist[tradingsymbol] 360 | if tradingsymbol in trailing_sl: 361 | del trailing_sl[tradingsymbol] 362 | 363 | 364 | 365 | def check_order_status(immediate=False, force=False): 366 | global orderslist 367 | global mfilist 368 | global trailing_sl 369 | #print(kite.positions()['day']) 370 | #orderslist.clear() 371 | 372 | df = pd.DataFrame(columns=['tradingsymbol', 'instrument_token', 'quantity', 'average_price', 'last_price']) 373 | try: 374 | data = kite.positions()['day'] 375 | df = pd.DataFrame.from_dict(data, orient='columns', dtype=None) 376 | if not df.empty: 377 | df = df[['tradingsymbol', 'instrument_token', 'quantity', 'average_price', 'last_price']] 378 | for idx in df.index: 379 | if not df['tradingsymbol'][idx] in tickerlist: 380 | #print("Not applicable :", df['tradingsymbol'][idx]) 381 | continue 382 | 383 | if df['quantity'][idx] == 0: 384 | #df.drop([idx], inplace = True) 385 | if df['tradingsymbol'][idx] in orderslist: 386 | del orderslist[df['tradingsymbol'][idx]] 387 | 388 | if df['tradingsymbol'][idx] in mfilist: 389 | del mfilist[df['tradingsymbol'][idx]] 390 | 391 | if df['tradingsymbol'][idx] in trailing_sl: 392 | del trailing_sl[df['tradingsymbol'][idx]] 393 | 394 | elif df['quantity'][idx] > 0: 395 | if not df['tradingsymbol'][idx] in orderslist: 396 | print("orderlist empty. Suspicious") 397 | orderslist[df['tradingsymbol'][idx]] = df['average_price'][idx] 398 | 399 | exit_buy(df.iloc[[idx]], idx,immediate,force) 400 | elif df['quantity'][idx] < 0: 401 | if not df['tradingsymbol'][idx] in orderslist: 402 | print("orderlist empty. Suspicious") 403 | orderslist[df['tradingsymbol'][idx]] = df['average_price'][idx] 404 | 405 | exit_sell(df.iloc[[idx]],idx,immediate,force) 406 | #print(df['tradingsymbol'][idx], df['transaction_type'][idx]) 407 | except Exception as e: 408 | print("******* ERROR Check order ********", e) 409 | 410 | #print(df.iloc[[3]]) 411 | 412 | 413 | #print(orderslist) 414 | if not immediate: 415 | print(df) 416 | print(orderslist) 417 | print(mfilist) 418 | print(trailing_sl) 419 | return df 420 | 421 | 422 | def run(): 423 | global run_count 424 | global exitcount 425 | start_time = int(12) * 60 + int(1) # specify in int (hr) and int (min) foramte 426 | end_time = int(14) * 60 + int(55) # do not place fresh order 427 | square_time = int(15) * 60 + int(5) # square off all open positions 428 | 429 | next_time = start_time 430 | 431 | if (datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5)))%10 == 0: 432 | next_time = datetime.datetime.now().hour * 60 + \ 433 | ((datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) + 5) 434 | 435 | else : 436 | next_time = datetime.datetime.now().hour * 60 + \ 437 | (datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) 438 | 439 | schedule_interval = 600 # run at every 1 min 440 | 441 | time_offset = (5 - (datetime.datetime.now().minute % 5)) * 60 442 | exit_time = datetime.datetime.now().hour * 60 + \ 443 | (datetime.datetime.now().minute + (5 - (datetime.datetime.now().minute % 5))) 444 | #runcount = 0 445 | check_order_status() 446 | while True: 447 | check_order_status(immediate=True) 448 | #time.sleep(1) 449 | if (datetime.datetime.now().hour * 60 + datetime.datetime.now().minute) >= square_time: 450 | check_order_status(force=True) 451 | print("***** Trading day closed *****") 452 | break 453 | 454 | elif (datetime.datetime.now().hour * 60 + datetime.datetime.now().minute) >= start_time: 455 | 456 | if datetime.datetime.now().hour * 60 + datetime.datetime.now().minute >= exit_time: 457 | exit_time = datetime.datetime.now().hour * 60 + datetime.datetime.now().minute + 5 458 | time.sleep(2) 459 | print("\n\n {} Exit Count : Time - {} ".format(exitcount, datetime.datetime.now())) 460 | if exitcount >= 0: 461 | try: 462 | check_order_status() 463 | except Exception as e: 464 | print("******* Run Error *********", e) 465 | exitcount = exitcount + 1 466 | 467 | if datetime.datetime.now().hour * 60 + datetime.datetime.now().minute >= next_time: 468 | next_time = datetime.datetime.now().hour * 60 + datetime.datetime.now().minute + 10 469 | time.sleep(2) 470 | print("\n\n {} Run Count : Time - {} ".format(runcount, datetime.datetime.now())) 471 | if runcount >= 0: 472 | try: 473 | run_strategy() 474 | except Exception as e: 475 | print("******* Run Error *********", e) 476 | runcount = runcount + 1 477 | 478 | else: 479 | print('****** Waiting ********', datetime.datetime.now()) 480 | time.sleep(5) 481 | 482 | 483 | run_count = 0 484 | 485 | #run1() 486 | run() 487 | 488 | -------------------------------------------------------------------------------- /zerodha/example/historical_data_test.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from kiteconnect import KiteConnect 3 | import sys 4 | import os 5 | import datetime 6 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 7 | from modules import auth 8 | from modules import historical_data 9 | 10 | logging.basicConfig(level=logging.INFO) 11 | 12 | # Get authentication data 13 | userdata = auth.get_userdata() 14 | kite = KiteConnect(api_key=userdata['api_key']) 15 | kite.set_access_token(userdata['access_token']) 16 | 17 | # Set parameters for historical data 18 | token = 779521 # SBIN token 19 | end_date = datetime.datetime.now() 20 | start_date = end_date - datetime.timedelta(days=30) # Last 30 days 21 | interval = "day" # Daily candles 22 | 23 | # Fetch historical data 24 | df = historical_data.get(kite, token, start_date, end_date, interval) 25 | print("\nHistorical Data for SBIN:") 26 | print(df.tail()) # Print last 5 entries -------------------------------------------------------------------------------- /zerodha/example/simple.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from kiteconnect import KiteConnect 3 | import sys 4 | import os 5 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 6 | from modules import auth 7 | 8 | logging.basicConfig(level=logging.INFO) 9 | 10 | userdata = auth.get_userdata() 11 | kite = KiteConnect(api_key=userdata['api_key']) 12 | kite.set_access_token(userdata['access_token']) 13 | 14 | # Place an order 15 | 16 | try: 17 | order_id = kite.place_order( 18 | variety=kite.VARIETY_AMO, 19 | exchange=kite.EXCHANGE_NSE, 20 | tradingsymbol="SBIN", 21 | transaction_type=kite.TRANSACTION_TYPE_BUY, 22 | quantity=10, 23 | product=kite.PRODUCT_CNC, 24 | order_type=kite.ORDER_TYPE_MARKET 25 | ) 26 | 27 | logging.info("Order placed. ID is: {}".format(order_id)) 28 | except Exception as e: 29 | logging.info("Order placement failed: {}".format(e.message)) 30 | 31 | # Fetch all orders 32 | if __name__ == '__main__': 33 | orders = kite.orders() 34 | print(orders) 35 | 36 | -------------------------------------------------------------------------------- /zerodha/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/debanshur/algotrading/4e6fe65f8d5091bcad51437c3641c84d91bdc47f/zerodha/modules/__init__.py -------------------------------------------------------------------------------- /zerodha/modules/auth.py: -------------------------------------------------------------------------------- 1 | from kiteconnect import KiteConnect 2 | import pandas as pd 3 | import os 4 | import sys 5 | import datetime 6 | import logging 7 | 8 | logging.basicConfig(level=logging.INFO) 9 | 10 | # Get the directory where this module is located 11 | module_dir = os.path.dirname(os.path.abspath(__file__)) 12 | # Go up one level to get the zerodha directory 13 | zerodha_dir = os.path.dirname(module_dir) 14 | # Set the data path relative to the zerodha directory 15 | data_path = os.path.join(zerodha_dir, '../data') 16 | userdata_file = os.path.join(data_path, 'userdata.csv') 17 | 18 | def is_valid_token(api_key, access_token): 19 | try: 20 | kite = KiteConnect(api_key=api_key) 21 | kite.set_access_token(access_token) 22 | kite.profile() 23 | return True 24 | except Exception: 25 | return False 26 | 27 | def get_userdata(): 28 | try: 29 | if (os.path.exists(userdata_file)): 30 | userdata = pd.read_csv(userdata_file) 31 | api_key = userdata.loc[0, 'api_key'] 32 | access_token = userdata.loc[0, 'access_token'] 33 | user_id = userdata.loc[0, 'user_id'] 34 | public_token = userdata.loc[0, 'public_token'] 35 | if is_valid_token(api_key, access_token): 36 | data = ({"api_key": api_key, "access_token": access_token, \ 37 | "user_id": user_id, "public_token": public_token}) 38 | return data 39 | 40 | raise Exception("** Run setup.py") 41 | except Exception as e: 42 | print("** ERROR in setup. ", e, datetime.datetime.now()) -------------------------------------------------------------------------------- /zerodha/modules/historical_data.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | def get(kite, token, startdate, enddate, interval): 4 | df = pd.DataFrame(columns=['date', 'open', 'high', 'low', 'close', 'volume']) 5 | try: 6 | data = kite.historical_data(token, startdate, enddate, interval) 7 | df = pd.DataFrame.from_dict(data, orient='columns', dtype=None) 8 | #print(df) 9 | if not df.empty: 10 | df = df[['date', 'open', 'high', 'low', 'close', 'volume']] 11 | df['date'] = df['date'].astype(str).str[:-6] 12 | df['date'] = pd.to_datetime(df['date']) 13 | except Exception as e: 14 | print("******* ERROR Fetching Historical Data ********", token, e) 15 | return df -------------------------------------------------------------------------------- /zerodha/setup.py: -------------------------------------------------------------------------------- 1 | from kiteconnect import KiteConnect 2 | import pandas as pd 3 | import os 4 | import sys 5 | import datetime 6 | import logging 7 | import math 8 | 9 | logging.basicConfig(level=logging.INFO) 10 | 11 | cur_dir_path = os.path.dirname(os.path.abspath(sys.argv[0])) 12 | data_path = os.path.join(cur_dir_path, '../data') 13 | userdata_file = os.path.join(data_path, 'userdata.csv') 14 | 15 | def get_user_data(userdata): 16 | api_key = input("Enter api key: ") 17 | api_secret = input("Enter api secret: ") 18 | userdata.loc[0, 'api_key'] = api_key 19 | userdata.loc[0, 'api_secret'] = api_secret 20 | return userdata 21 | 22 | 23 | def check_data_validity(userdata): 24 | if userdata.isnull().loc[0,'api_key'] or userdata.isnull().loc[0,'api_secret'] \ 25 | or (not userdata.loc[0, 'api_key'].isalnum()) or (not userdata.loc[0, 'api_secret'].isalnum()): 26 | print("Provide valid api_key/api_secret") 27 | print("--------------------------------") 28 | return False 29 | return True 30 | 31 | 32 | def setup(): 33 | try: 34 | if (not os.path.exists(data_path)): 35 | os.makedirs(data_path) 36 | 37 | if (not os.path.exists(userdata_file)): 38 | userdata = pd.DataFrame( 39 | { 40 | "user_id" : [], 41 | "user_name" : [], 42 | "api_key" : [], 43 | "api_secret" : [], 44 | "access_token" : [], 45 | "public_token" : [], 46 | "token_req_date" : [] 47 | 48 | }) 49 | userdata = get_user_data(userdata) 50 | while not check_data_validity(userdata): 51 | get_user_data(userdata) 52 | userdata.to_csv(userdata_file, index=False) 53 | else: 54 | userdata = pd.read_csv(userdata_file) 55 | while not check_data_validity(userdata): 56 | get_user_data(userdata) 57 | userdata.to_csv(userdata_file, index=False) 58 | except Exception as e: 59 | print("** ERROR in setup. Run setup.py again.", e, datetime.datetime.now()) 60 | 61 | 62 | def is_valid_token(api_key, access_token): 63 | try: 64 | kite = KiteConnect(api_key=api_key) 65 | kite.set_access_token(access_token) 66 | kite.profile() 67 | return True 68 | except Exception: 69 | return False 70 | 71 | 72 | def generate_token(userdata): 73 | try: 74 | api_key = userdata.loc[0, 'api_key'] 75 | api_secret = userdata.loc[0, 'api_secret'] 76 | 77 | kite = KiteConnect(api_key=api_key) 78 | print("Login URL :=> " + kite.login_url()) 79 | request_token = input("Enter new request token value : ") 80 | res = kite.generate_session(request_token, api_secret) 81 | 82 | #print(res) 83 | userdata.loc[0, 'access_token'] = res['access_token'] 84 | userdata.loc[0, 'user_name'] = res['user_name'] 85 | userdata.loc[0, 'user_id'] = res['user_id'] 86 | userdata.loc[0, 'public_token'] = res['public_token'] 87 | userdata.loc[0, 'token_req_date'] = datetime.datetime.now() 88 | userdata.to_csv(userdata_file, index=False) 89 | except Exception as e: 90 | print("** ERROR in Access Token Generation. ", e, datetime.datetime.now()) 91 | 92 | 93 | def validate_access_token(): 94 | try: 95 | userdata = pd.read_csv(userdata_file) 96 | api_key = userdata.loc[0, 'api_key'] 97 | access_token = userdata.loc[0, 'access_token'] 98 | 99 | if not is_valid_token(api_key, access_token): 100 | raise Exception("Invalid Token") 101 | else : 102 | print("Authentication Done") 103 | 104 | except Exception as e: 105 | print("** ERROR in Access Token Validation. ", e, datetime.datetime.now()) 106 | generate_token(userdata) 107 | validate_access_token() 108 | 109 | 110 | setup() 111 | validate_access_token() -------------------------------------------------------------------------------- /zerodha/stock_screener.py: -------------------------------------------------------------------------------- 1 | from kiteconnect import KiteConnect 2 | from modules import auth 3 | import pandas as pd 4 | 5 | userdata = auth.get_userdata() 6 | kite = KiteConnect(api_key=userdata['api_key']) 7 | kite.set_access_token(userdata['access_token']) 8 | 9 | dict = {} 10 | 11 | def get_all_nse_instruments(): 12 | data = kite.instruments(exchange="NSE") 13 | 14 | df = pd.DataFrame(columns=[ 'instrument_token','tradingsymbol','name']) 15 | df = pd.DataFrame.from_dict(data, orient='columns', dtype=None) 16 | if not df.empty: 17 | df = df[['instrument_token','tradingsymbol','name']] 18 | 19 | for ind in df.index: 20 | tokenName = df['tradingsymbol'][ind] 21 | tokenNumber = df['instrument_token'][ind] 22 | dict[tokenName] = tokenNumber 23 | 24 | 25 | def isNaN(string): 26 | return string != string 27 | 28 | 29 | def get_custom_instruments(stocks_list): 30 | get_all_nse_instruments() 31 | 32 | tokenNames = stocks_list.Symbol.values 33 | tokenNameList = [] 34 | tokenNumberList = [] 35 | 36 | for tokenName in tokenNames: 37 | if not isNaN(tokenName): 38 | tokenName = tokenName.strip() 39 | tokenNameList.append(tokenName) 40 | tokenNumberList.append(dict[tokenName]) 41 | 42 | print("\nToken Name : \n",tokenNameList) 43 | print("\nToken Number : \n",tokenNumberList) 44 | 45 | 46 | stocks_list = pd.read_csv("data.csv") 47 | get_custom_instruments(stocks_list) 48 | -------------------------------------------------------------------------------- /zerodha/supertrend_strategy.py: -------------------------------------------------------------------------------- 1 | from kiteconnect import KiteConnect 2 | from math import floor, ceil 3 | import datetime 4 | import pandas as pd 5 | import time 6 | 7 | from modules import auth 8 | from modules import historical_data 9 | from indicators import SuperTrend, MACD, RSI 10 | 11 | risk_per_trade = 100 # Stoploss amount 12 | supertrend_period = 10 13 | supertrend_multiplier=3 14 | candlesize = '10minute' 15 | one_hour_rsi = 50 16 | orderslist = {} 17 | 18 | #pd.set_option('display.max_columns',50) 19 | pd.set_option('display.max_rows', None) 20 | print("\n******** Started ********* : ", datetime.datetime.now()) 21 | 22 | """ 23 | 1. Login to kite 24 | """ 25 | userdata = auth.get_userdata() 26 | kite = KiteConnect(api_key=userdata['api_key']) 27 | kite.set_access_token(userdata['access_token']) 28 | 29 | print("******** UserData Loaded ********* : ", datetime.datetime.now()) 30 | 31 | #list all tickers you want to trade 32 | tickerlist = ["BAJAJFINSV","ZEEL","HDFCBANK","LT","HDFC","ICICIBANK","LICHSGFIN","CENTURYTEX","SBIN","INDUSINDBK","TATASTEEL","RELIANCE","MARUTI","VEDL","AXISBANK","TATAMOTORS","SIEMENS","TATAMTRDVR","DLF","HINDALCO","M&M","ULTRACEMCO","TATACHEM","L&TFH","AMBUJACEM","UNIONBANK","CANBK","BANKINDIA","VOLTAS","TATAPOWER","GODREJIND","BAJAJ-AUTO","APOLLOTYRE","NCC","RECLTD","BHARATFORG","TATAGLOBAL","PFC","ACC","JSWSTEEL","M&MFIN","BHEL","HEROMOTOCO","ASHOKLEY","BANKBARODA","JINDALSTEL","SRF","ASIANPAINT","UPL","EXIDEIND","ONGC"] 33 | #tickerlist = ["HDFCBANK","LT","HDFC","ICICIBANK","LICHSGFIN","CENTURYTEX","SBIN","INDUSINDBK","TATASTEEL","RELIANCE"] 34 | #tickerlist = ["BAJAJFINSV"] 35 | tokenlist = [4268801,975873,341249,2939649,340481,1270529,511233,160001,779521,1346049,895745,738561,2815745,784129,1510401,884737,806401,4343041,3771393,348929,519937,2952193,871681,6386689,325121,2752769,2763265,1214721,951809,877057,2796801,4267265,41729,593665,3930881,108033,878593,3660545,5633,3001089,3400961,112129,345089,54273,1195009,1723649,837889,60417,2889473,173057,633601] 36 | #tokenlist = [341249,2939649,340481,1270529,511233,160001,779521,1346049,895745,738561] 37 | #tokenlist = [4268801] 38 | 39 | 40 | def compute_data(token): 41 | global one_hour_rsi 42 | #enddate = datetime.datetime(2020, 5, 4, 15,30,0,0) 43 | enddate = datetime.datetime.today() 44 | startdate = enddate - datetime.timedelta(3) 45 | try: 46 | df = historical_data.get(kite, token, startdate, enddate, candlesize) 47 | df = SuperTrend.calc(df, supertrend_period, supertrend_multiplier) 48 | df = MACD.calc(df) 49 | rsi = historical_data.get(kite, token, startdate, enddate, "60minute") 50 | rsi = RSI.calc(rsi) 51 | one_hour_rsi = rsi.RSI_14.values[-1] 52 | except Exception as e: 53 | print("******* ERROR Computing Historical Data ********", token, e) 54 | return df 55 | 56 | def check_volume(open, volume): 57 | if open <= 400 and volume >= 1000000: 58 | return True 59 | elif open > 400 and open <=700 and volume >= 500000: 60 | return True 61 | elif open > 700 and open <=1000 and volume >= 300000: 62 | return True 63 | elif open > 1000 and volume >= 100000: 64 | return True 65 | else: 66 | return False 67 | 68 | 69 | def run_strategy(): 70 | global orderslist 71 | global one_hour_rsi 72 | for i in range(0, len(tickerlist)): 73 | 74 | if (tickerlist[i] in orderslist): 75 | continue 76 | try: 77 | histdata = compute_data(tokenlist[i]) 78 | #print(histdata) 79 | super_trend = histdata.STX.values 80 | 81 | high = histdata.high.values[-2] 82 | low = histdata.low.values[-2] 83 | macd = histdata.hist_12_26_9.values[-2] 84 | stoploss_buy = histdata.ST.values[-2]#histdata.low.values[-3] # third last candle as stoploss 85 | stoploss_sell = histdata.ST.values[-2] # third last candle as stoploss 86 | 87 | volume = histdata.volume.values[-2] 88 | has_volume = check_volume(histdata.open.values[-2], volume) 89 | 90 | 91 | #if stoploss_buy > lastclose * 0.996: 92 | #stoploss_buy = lastclose * 0.996 # minimum stoploss as 0.4 % 93 | 94 | #if stoploss_sell < lastclose * 1.004: 95 | #stoploss_sell = lastclose * 1.004 # minimum stoploss as 0.4 % 96 | #print("lastclose",lastclose) 97 | #print("stoploss abs",stoploss) 98 | print(tickerlist[i],high,low,super_trend[-4:],round(macd,4),int(one_hour_rsi), volume) 99 | 100 | if super_trend[-1]=='up' and super_trend[-2]=='up' and super_trend[-3]=='down' and super_trend[-4]=='down' \ 101 | and macd>0 and one_hour_rsi > 50: 102 | if not has_volume: 103 | print("Sorry, Volume is low") 104 | #continue 105 | 106 | stoploss_buy = high - stoploss_buy 107 | #print("stoploss delta", stoploss) 108 | 109 | quantity = 1#floor(max(1, (risk_per_trade/stoploss_buy))) 110 | target = stoploss_buy*2 # risk reward as 3 111 | 112 | price = high + (0.05*high)/100 113 | #print(price) 114 | #price = int(ceil(price)) 115 | price = int(100 * (ceil(price / 0.05) * 0.05)) / 100 116 | stoploss_buy = int(100 * (floor(stoploss_buy / 0.05) * 0.05)) / 100 117 | quantity = int(quantity) 118 | target = int(100 * (floor(target / 0.05) * 0.05)) / 100 119 | 120 | orderslist[tickerlist[i]] = price - stoploss_buy 121 | #print(price) 122 | order = kite.place_order(exchange='NSE', 123 | tradingsymbol=tickerlist[i], 124 | transaction_type="BUY", 125 | quantity=quantity, 126 | trigger_price=price, 127 | product='MIS', 128 | order_type='SL-M', 129 | validity='DAY', 130 | variety="regular" 131 | ) 132 | 133 | print(" Order : ", "BUY", tickerlist[i], "high : ", high,"quantity:",quantity, "price:",price,datetime.datetime.now()) 134 | 135 | if super_trend[-1]=='down' and super_trend[-2]=='down' and super_trend[-3]=='up' and super_trend[-4]=='up' \ 136 | and macd<0 and one_hour_rsi < 50: 137 | 138 | if not has_volume: 139 | print("Sorry, Volume is low") 140 | #continue 141 | 142 | stoploss_sell= stoploss_sell - low 143 | #print("stoploss delta", stoploss) 144 | 145 | quantity = 1#floor(max(1, (risk_per_trade/stoploss_sell))) 146 | target = stoploss_sell*2 # risk reward as 3 147 | 148 | price = low - (0.05*low)/100 149 | #price = int(floor(price)) 150 | price = int(100 * (floor(price / 0.05) * 0.05)) / 100 151 | stoploss_sell = int(100 * (floor(stoploss_sell / 0.05) * 0.05)) / 100 152 | quantity = int(quantity) 153 | target = int(100 * (floor(target / 0.05) * 0.05)) / 100 154 | 155 | orderslist[tickerlist[i]] = price + stoploss_sell 156 | order = kite.place_order(exchange='NSE', 157 | tradingsymbol=tickerlist[i], 158 | transaction_type="SELL", 159 | quantity=quantity, 160 | trigger_price=price, 161 | product='MIS', 162 | order_type='SL-M', 163 | validity='DAY', 164 | variety="regular" 165 | ) 166 | print(" Order : ", "SELL", tickerlist[i],"low : ", low,"quantity:",quantity, "price:",price, datetime.datetime.now()) 167 | 168 | except Exception as e : 169 | print(e) 170 | 171 | def check_order_status1(): 172 | global orderslist 173 | df = pd.DataFrame(columns=['order_id', 'status', 'tradingsymbol', 'instrument_token', 'transaction_type', 'quantity']) 174 | try: 175 | data = kite.orders() 176 | df = pd.DataFrame.from_dict(data, orient='columns', dtype=None) 177 | #print(df) 178 | if not df.empty: 179 | df = df[['order_id', 'status', 'tradingsymbol', 'instrument_token', 'transaction_type', 'quantity']] 180 | except Exception as e: 181 | print("******* ERROR Fetching Historical Data ********", e) 182 | for ind in df.index: 183 | token = df['tradingsymbol'][ind] 184 | if token in orderslist: 185 | orderslist.pop(token) 186 | else: 187 | orderslist[token] = "0" 188 | #print(df['tradingsymbol'][ind], df['transaction_type'][ind]) 189 | 190 | print(orderslist) 191 | return df 192 | 193 | 194 | def check_order_status(): 195 | global orderslist 196 | df = pd.DataFrame(columns=['order_id', 'status', 'tradingsymbol', 'instrument_token', 'transaction_type', 'quantity']) 197 | try: 198 | data = kite.orders() 199 | df = pd.DataFrame.from_dict(data, orient='columns', dtype=None) 200 | #print(df) 201 | if not df.empty: 202 | df = df[['order_id', 'status', 'tradingsymbol', 'instrument_token', 'transaction_type', 'quantity']] 203 | except Exception as e: 204 | print("******* ERROR Fetching Historical Data ********", e) 205 | for ind in df.index: 206 | token = df['tradingsymbol'][ind] 207 | orderslist[token] = "0" 208 | #print(df['tradingsymbol'][ind], df['transaction_type'][ind]) 209 | 210 | print(orderslist) 211 | return df 212 | 213 | def run(): 214 | global run_count 215 | start_time = int(9) * 60 + int(25) # specify in int (hr) and int (min) foramte 216 | end_time = int(15) * 60 + int(10) # do not place fresh order 217 | stop_time = int(15) * 60 + int(15) # square off all open positions 218 | last_time = start_time 219 | schedule_interval = 60 # run at every 1 min 220 | #runcount = 0 221 | check_order_status() 222 | while True: 223 | if (datetime.datetime.now().hour * 60 + datetime.datetime.now().minute) >= end_time: 224 | if (datetime.datetime.now().hour * 60 + datetime.datetime.now().minute) >= stop_time: 225 | print("***** Trading day closed *****") 226 | break 227 | 228 | elif (datetime.datetime.now().hour * 60 + datetime.datetime.now().minute) >= start_time: 229 | if time.time() >= last_time: 230 | last_time = time.time() + schedule_interval 231 | print("\n\n {} Run Count : Time - {} ".format(runcount, datetime.datetime.now())) 232 | if runcount >= 0: 233 | try: 234 | run_strategy() 235 | except Exception as e: 236 | print("******* Run Error *********", e) 237 | runcount = runcount + 1 238 | else: 239 | print('****** Waiting ********', datetime.datetime.now()) 240 | time.sleep(1) 241 | 242 | run_count = 0 243 | run() 244 | --------------------------------------------------------------------------------