Let’s build a simple intraday strategy:
Buy when RSI < 30 and Close > 20 EMA
Sell when RSI > 70 and Close < 20 EMA
We’ll use:
This is for learning/demo only. Not for live trading — yet!
1. Install necessary libraries (only once): You can run this in Google Colab or your local Python setup.
!pip install yfinance ta
Note:
This command installs two Python libraries needed for market data analysis and technical indicator calculations:
yfinance – used to fetch historical and real-time market data directly from Yahoo Finance into Python.
ta – a Technical Analysis library that provides ready-to-use functions for computing indicators like RSI, EMA, MACD, Bollinger Bands, etc.
The ! at the start allows this to be run as a shell command inside Jupyter Notebook or Google Colab, so the packages are installed into your current environment before running the rest of your algo trading code.
2. Import the libraries
import yfinance as yf import ta import pandas as pd
Note:
This code imports three essential Python libraries for algo trading:
yfinance (yf) to fetch historical and real-time market data from Yahoo Finance.
ta to calculate technical indicators such as RSI, EMA, MACD, Bollinger Bands, and others.
pandas (pd) for storing, processing, and analyzing time-series market data in DataFrames.
Together, they allow you to download price data, calculate technical indicators, and manipulate the resulting dataset for strategy building and backtesting.
3. Get intraday price data
data = yf.download("RELIANCE.NS", period="5d", interval="15m") data.dropna(inplace=True)
This gives you 15-minute candles of Reliance for the last 5 days. The securities quoted are exemplary and are not recommendatory
4. Calculate RSI and 20 EMA
data['rsi'] = ta.momentum.RSIIndicator(close=data['Close']).rsi() data['ema20'] = ta.trend.EMAIndicator(close=data['Close'], window=20).ema_indicator()
Note:
ta.momentum.RSIIndicator: Creates a Relative Strength Index (RSI) indicator object from the ta (technical analysis) library.
close=data['Close']: Uses the 'Close' price column from your data DataFrame to calculate RSI.
.rsi(): Computes the RSI values for each row (default period is usually 14 unless specified) and returns a Pandas Series.
data['rsi'] = ...: Stores the resulting RSI values in a new column called 'rsi' in your DataFrame.
ta.trend.EMAIndicator: Creates an Exponential Moving Average (EMA) indicator object.
close=data['Close']: Again, uses the 'Close' price as the data source for calculation.
window=20: Sets the EMA lookback period to 20 bars (e.g., 20 days for daily data).
.ema_indicator(): Calculates the EMA values for the given period.
data['ema20'] = ...: Saves the computed EMA values into a new column 'ema20' in your DataFrame.
Boom — indicators added to your DataFrame.
5. Define the Buy/Sell logic
def generate_signal(row): if row['rsi'] < 30 and row['Close'] > row['ema20']: return "BUY" elif row['rsi'] > 70 and row['Close'] < row['ema20']: return "SELL" else: return "HOLD"
data['signal'] = data.apply(generate_signal, axis=1)
This function checks every row (i.e., every 15-min candle) and assigns a signal
6. View the result
print(data[['Close', 'rsi', 'ema20', 'signal']].tail(10))
Note:
This line prints the last 10 rows of selected columns from the data DataFrame:
'Close' – the closing price of the asset for each period.
'rsi' – the Relative Strength Index values calculated earlier.
'ema20' – the 20-period Exponential Moving Average values.
'signal' – a trading signal column (likely generated by your strategy logic).
The .tail(10) function limits the output to the most recent 10 rows, making it easier to review the latest market data, indicators, and generated trade signals without printing the entire dataset.
You’ll see output like:
| Close | RSI | EMA20 | Signal |
|---|---|---|---|
2850 | 29 | 2830 | BUY |
2895 | 72 | 2901 | HOLD |
2880 | 74 | 2885 | SELL |
This helps you backtest if the logic makes sense visually.
You can now add order execution, logging, and alerts to this strategy step by step.
Want to see how many buy/sell signals came up?
print(data['signal'].value_counts())
Disclaimer: This article is for informational purposes only and does not constitute financial advice. It is not produced by the desk of the Kotak Securities Research Team, nor is it a report published by the Kotak Securities Research Team. The information presented is compiled from several secondary sources available on the internet and may change over time. Investors should conduct their own research and consult with financial professionals before making any investment decisions. Read the full disclaimer here.
Investments in securities market are subject to market risks, read all the related documents carefully before investing. Brokerage will not exceed SEBI prescribed limit. The securities are quoted as an example and not as a recommendation. SEBI Registration No-INZ000200137 Member Id NSE-08081; BSE-673; MSE-1024, MCX-56285, NCDEX-1262.
Disclaimer: This article is for informational purposes only and does not constitute financial advice. It is not produced by the desk of the Kotak Securities Research Team, nor is it a report published by the Kotak Securities Research Team. The information presented is compiled from several secondary sources available on the internet and may change over time. Investors should conduct their own research and consult with financial professionals before making any investment decisions. Read the full disclaimer here.
Investments in securities market are subject to market risks, read all the related documents carefully before investing. Brokerage will not exceed SEBI prescribed limit. The securities are quoted as an example and not as a recommendation. SEBI Registration No-INZ000200137 Member Id NSE-08081; BSE-673; MSE-1024, MCX-56285, NCDEX-1262.
Explore our comprehensive video library that blends expert market insights with Kotak's innovative financial solutions to support your goals.