This is a programming lesson. So there will be very less amount of explanation and more code. If you’re stuck somewhere, feel free to comment.
Execute a buy order for Sun Pharma stock based on specific conditions –
If these conditions are satisfied, then place a limit order for Sun Pharma stock.
Note – The structure of historical data and live data from Zerodha is identical. During the development and testing of functions, it’s not feasible to wait for days or months to validate their performance using live data.
To address this, we’ll initially test and validate our functions using historical data. Once we have confirmed that the functions generate accurate signals and execute trades correctly with historical data, we can seamlessly transition to using live data for real-time trading.
				
					def get_historical_data(kite, instrument_token, start_date, end_date, interval):
    return kite.historical_data(instrument_token, start_date, end_date, interval, 0)
def calculate_rsi(za):
    rsi_period = 14
    chg = za["close"].diff(1)
    gain = chg.mask(chg < 0, 0)
    loss = chg.mask(chg > 0, 0)
    avg_gain = gain.ewm(com=rsi_period - 1, min_periods=rsi_period).mean()
    avg_loss = loss.ewm(com=rsi_period - 1, min_periods=rsi_period).mean()
    rs = abs(avg_gain / avg_loss)
    rsi = 100 - (100 / (1 + rs))
    za['rsi'] = rsi
    return za.iloc[-1, 6]
def place_order(kite, symbol, quantity, price, transaction_type):
    kite.place_order(
        variety="regular",
        tradingsymbol=symbol,
        quantity=quantity,
        exchange='NSE',
        order_type='LIMIT',
        price=price,
        transaction_type=transaction_type,
        product='CNC'
    )
    print("One order placed")
def livedata():
    while True:
        km = datetime.datetime.now().minute
        ks = datetime.datetime.now().second
        if km % 1 == 0 and ks == 1:
            historical_data = get_historical_data(kite, 857857, "2019-01-05", "2019-06-02", "minute")
            za = pd.DataFrame(historical_data)
            rsi_value = calculate_rsi(za)
            if rsi_value > 30 and za.iloc[-2, 2] > za.iloc[-1, 2]:
                place_order(kite, 'SUNPHARMA', 1, 453, 'BUY')
                break
            else:
                pass
            time.sleep(60)
livedata()
 
				
			
		Output –
				
					
File ~/apps/zerodha/../kiteconnect/connect.py:671, in KiteConnect._request(self, route, method, parameters)
    669         # native Kite errors
    670         exp = getattr(ex, data["error_type"], ex.GeneralException)
--> 671         raise exp(data["message"], code=r.status_code)
    673     return data["data"]
    674 elif "csv" in r.headers["content-type"]:
InputException: interval exceeds max limit: 60 days 
				
			
		The error message indicates that the specified time interval for data retrieval exceeds the maximum limit, which is set to 60 days. This means you cannot retrieve data for a period longer than 60 days using the given interval.
So, Let’s modify the historical_data request to fetch data for today and the past 50 days.
				
					start_date = (datetime.date.today() - datetime.timedelta(days=50)).strftime("%Y-%m-%d")
end_date = datetime.date.today().strftime("%Y-%m-%d")
    
def livedata():
    while True:
        km = datetime.datetime.now().minute
        ks = datetime.datetime.now().second
        if km % 1 == 0 and ks == 1:
            historical_data = get_historical_data(kite, 857857, start_date, end_date, "minute")
            za = pd.DataFrame(historical_data)
            rsi_value = calculate_rsi(za)
            if rsi_value > 30 and za.iloc[-2, 2] > za.iloc[-1, 2]:
                print("RSI Value is " +str(rsi_value))
                place_order(kite, 'SUNPHARMA', 1, 453, 'BUY')
                break
            else:
                pass
            time.sleep(60)
livedata()
 
				
			
		Output –
				
					RSI Value is 35.53216733131616
One order placed 
				
			
		
				
					import matplotlib.pyplot as plt
historical_data = get_historical_data(kite, 857857, start_date, end_date, "minute")
za = pd.DataFrame(historical_data)
rsi_values = []  # List to store RSI values
for i in range(len(za)):
    # Create a DataFrame containing a single row from 'za'
    single_row = pd.DataFrame(za.iloc[i]).T
    rsi_value = calculate_rsi(single_row)
    rsi_values.append(rsi_value)
plt.figure(figsize=(12, 6))
plt.plot(za["date"], rsi_values, label="RSI", color='blue')
plt.axhline(y=30, color='red', linestyle='--', label="RSI 30")
plt.axhline(y=70, color='green', linestyle='--', label="RSI 70")
plt.title("RSI Between {} and {}".format(start_date, end_date))
plt.xlabel("Date")
plt.ylabel("RSI Value")
plt.legend()
plt.grid(True)
plt.show() 
				
			
		Output –

So, Let’s debug –
				
					print(za) 
				
			
		Output –
				
					date	open	high	low	close	volume
0	2023-10-05 09:15:00+05:30	1124.65	1128.65	1122.80	1124.45	19041
1	2023-10-05 09:16:00+05:30	1125.20	1126.50	1125.05	1126.50	7274
2	2023-10-05 09:17:00+05:30	1126.10	1127.45	1125.50	1127.00	6414
3	2023-10-05 09:18:00+05:30	1127.00	1128.05	1125.85	1125.85	3172
4	2023-10-05 09:19:00+05:30	1125.85	1126.35	1125.00	1125.65	5333
...	...	...	...	...	...	...
13051	2023-11-24 13:16:00+05:30	1194.40	1194.50	1193.35	1193.95	2385
13052	2023-11-24 13:17:00+05:30	1193.95	1194.45	1193.55	1193.70	1695
13053	2023-11-24 13:18:00+05:30	1194.35	1195.00	1193.65	1195.00	5209
13054	2023-11-24 13:19:00+05:30	1195.00	1195.30	1194.05	1194.75	3679
13055	2023-11-24 13:20:00+05:30	1194.75	1194.75	1194.10	1194.10	84
13056 rows × 6 columns 
				
			
		
				
					print(rsi_values) 
				
			
		Output –
				
					[nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 nan,
 ...
 ...] 
				
			
		To calculate the Relative Strength Index (RSI) for a specific day, you require data from the previous 14 days. Therefore, you should create a separate function to calculate the RSI for each day, excluding the first 14 days where RSI cannot be calculated due to insufficient historical data. This function will compute the RSI values and return a list of RSI values for the remaining days in your dataset.
Here’s an example of how to create such a function and use it in your code.
				
					def calculate_rsi_list(df):
    rsi_period = 14
    rsi_values = []
    for i in range(len(df)):
        if i < rsi_period:
            rsi_values.append(None)  # Cannot calculate RSI for the first 14 days
        else:
            chg = df["close"].diff(1)
            gain = chg.where(chg > 0, 0)
            loss = -chg.where(chg < 0, 0)
            avg_gain = gain.iloc[i - rsi_period + 1:i + 1].mean()
            avg_loss = loss.iloc[i - rsi_period + 1:i + 1].mean()
            if avg_loss == 0:
                rsi = 100
            else:
                rs = avg_gain / avg_loss
                rsi = 100 - (100 / (1 + rs))
            rsi_values.append(rsi)
    return rsi_values
rsi_values = calculate_rsi_list(za)
print(rsi_values) 
				
			
		Output –
				
					[None, None, None, None, None, None, None, None, None, None, None, None, None, None, 39.730639730639666, 30.078124999999943, 26.377952755905184, 27.459016393442283, 32.9457364341083, 39.50177935943041, 41.240875912409294, 43.840579710144745, 44.322344322344435, 43.999999999999666, 44.322344322344435, 38.43416370106739, 38.848920863308756, 21.513944223108012, 35.08771929824533, 38.84297520661151, 39.49579831932781, 41.409691629956676, 37.850467289719845, 37.26415094339563, 35.648148148146845, 39.0350877192979, 47.39130434782545, 56.476683937824085, 56.92307692307779, 55.778894472362374, 60.655737704918444, 71.33757961783407, 67.85714285714286, 61.83206106870202, 63.77952755905532, 71.05263157894643, 61.67664670658586, 55.24475524475518, 60.81081081081126, 52.63157894736933, 44.73684210526421, 50.0, 48.0314960629921, ...] 
				
			
		So, Let’s plot this RSI data against dates.
				
					import matplotlib.pyplot as plt
# Assuming you have already calculated the rsi_values using calculate_rsi_list
plt.figure(figsize=(12, 6))
plt.plot(za["date"],rsi_values, label="RSI", color='blue', linewidth=0.1)  
plt.axhline(y=30, color='red', linestyle='--', label="RSI 30")
plt.axhline(y=70, color='green', linestyle='--', label="RSI 70")
plt.title("RSI Plot")
plt.xlabel("Date")
plt.ylabel("RSI Value")
plt.legend()
plt.grid(True)
plt.show()
 
				
			
		Output –


