Building a Telegram Bot for NSE Alerts on Android (No Server Required)
DOYR | Not financial/legal/tax advice. For educational purposes only.
You're not at your desk. You're on a bus, or at a café, or just away from your laptop.
And Nifty just broke a key level. Or TCS gapped up 3% on earnings. Or your stock screener found a perfect setup.
How do you get the alert instantly?
Not email. Not a website refresh. Not a push notification that takes 5 minutes to arrive.
Telegram.
Telegram is perfect for trading alerts because:
- Instant delivery (1-2 seconds)
- Works on Android (no server needed)
- Free (no SMS charges, no email limits)
- Rich formatting (bold, charts, tables)
- Group support (share with friends)
- API is simple (10 lines of code)
This guide shows you how to build a complete Telegram bot for NSE alerts that runs on your Android phone via Termux. No cloud server. No VPS. No ₹500/month hosting.
Just your phone. Python. Telegram.
What You'll Build
| Feature | Function |
|---|---|
| Price alerts | Nifty crosses key levels |
| Screener alerts | Stock screener finds matches |
| News alerts | Important NSE news headlines |
| Performance alerts | Portfolio P&L updates |
| Daily brief | Morning market summary |
| Custom filters | Your rules, your alerts |
Cost: ₹0
Time: 1 hour
Platform: Termux/Android
Step 1: Create Telegram Bot
1.1 Get Bot Token from BotFather
- Open Telegram → Search @botfather
- Send
/newbot - Name your bot:
Shakti Trading Bot - Username:
shakti_nse_bot(must end inbot) - BotFather sends you a token:
123456789:ABCdefGhIJKlmNoPQRsTUVwxyz
Save this token. You'll need it.
1. Get Your Chat ID
- Search @userinfobot on Telegram
- Send
/start - It replies with your Chat ID:
123456789
Save this too.
Step 2: Install Dependencies on Termux
# Update Termux
pkg update -y && pkg upgrade -y
# Install Python + libraries
pkg install python python-dev pip -y
pip install requests python-telegram-bot==20.7 yfinance pandas schedule
# Verify
python -c "import telegram; print('Telegram bot ready')"
Key libraries:
| Library | Purpose |
|---------|---------|
| requests | Fetch NSE data |
| python-telegram-bot | Telegram API wrapper |
| yfinance | Stock data fallback |
| pandas | Data processing |
| schedule | Job scheduling |
Step 3: Basic Bot Structure
from telegram import Bot
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
import os
# Configuration
TOKEN = "YOUR_BOT_TOKEN_HERE"
CHAT_ID = "YOUR_CHAT_ID_HERE"
class NSEAlertBot:
def __init__(self):
self.bot = Bot(token=TOKEN)
self.chat_id = CHAT_ID
def send_message(self, text, parse_mode='Markdown'):
"""Send message to Telegram"""
try:
self.bot.send_message(
chat_id=self.chat_id,
text=text,
parse_mode=parse_mode
)
print(f"✅ Alert sent: {text[:50]}...")
except Exception as e:
print(f"❌ Failed to send: {e}")
def send_photo(self, photo_path, caption=None):
"""Send chart/image to Telegram"""
try:
with open(photo_path, 'rb') as photo:
self.bot.send_photo(
chat_id=self.chat_id,
photo=photo,
caption=caption
)
print(f"✅ Photo sent: {photo_path}")
except Exception as e:
print(f"❌ Failed to send photo: {e}")
# Test
bot = NSEAlertBot()
bot.send_message("🧪 *Test Alert*\n\nBot is working! Ready for NSE alerts.")
Run test:
python nse_bot.py
You should see: "🧪 Test Alert" in your Telegram.
Step 4: Price Alert System
import yfinance as yf
import time
class PriceAlertBot(NSEAlertBot):
def __init__(self):
super().__init__()
self.alerts = []
def add_alert(self, symbol, condition, target_price):
"""
Add price alert
condition: 'above' or 'below'
"""
self.alerts.append({
'symbol': symbol,
'condition': condition,
'target': target_price,
'triggered': False
})
def check_alerts(self):
"""Check all alerts against current prices"""
triggered = []
for alert in self.alerts:
if alert['triggered']:
continue
try:
# Fetch current price
ticker = f"{alert['symbol']}.NS"
stock = yf.Ticker(ticker)
hist = stock.history(period="1d")
if len(hist) == 0:
continue
current_price = hist['Close'].iloc[-1]
# Check condition
if alert['condition'] == 'above' and current_price >= alert['target']:
alert['triggered'] = True
triggered.append({
'symbol': alert['symbol'],
'condition': f"rose above ₹{alert['target']}",
'current': current_price,
'alert': alert
})
elif alert['condition'] == 'below' and current_price <= alert['target']:
alert['triggered'] = True
triggered.append({
'symbol': alert['symbol'],
'condition': f"fell below ₹{alert['target']}",
'current': current_price,
'alert': alert
})
except Exception as e:
print(f"Error checking {alert['symbol']}: {e}")
return triggered
def process_alerts(self):
"""Check alerts and send Telegram notifications"""
triggered = self.check_alerts()
for t in triggered:
emoji = "🔴" if "fell" in t['condition'] else "🟢"
message = f"""{emoji} *PRICE ALERT*
{t['symbol']} has {t['condition']}
Current price: ₹{t['current']:.2f}
Action: {'Consider selling' if 'fell' in t['condition'] else 'Consider buying'}"""
self.send_message(message)
# Usage
bot = PriceAlertBot()
# Add alerts
bot.add_alert('NIFTY', 'above', 22500)
bot.add_alert('NIFTY', 'below', 22000)
bot.add_alert('TCS', 'above', 4500)
bot.add_alert('RELIANCE', 'below', 2900)
# Check every 5 minutes during market hours
while True:
now = datetime.now()
if now.hour >= 9 and now.hour <= 15: # Market hours
bot.process_alerts()
time.sleep(300) # Check every 5 minutes
Step 5: Stock Screener Alerts
class ScreenerAlertBot(NSEAlertBot):
def __init__(self):
super().__init__()
self.screener_results = []
def send_screener_results(self, results_df):
"""Send screener results to Telegram"""
if results_df.empty:
message = "📊 *Daily Screener Results*\n\nNo stocks matched criteria today."
else:
message = f"📊 *Daily Screener Results*\n\n"
message += f"Found {len(results_df)} stocks:\n\n"
for _, row in results_df.iterrows():
message += f"*{row['symbol']}* ({row.get('name', '')})\n"
message += f"Price: ₹{row['close']}\n"
message += f"Change: {row.get('change_pct', 0)}%\n"
message += f"RSI: {row.get('rsi', 'N/A')}\n"
message += f"Momentum: {row.get('momentum', 'N/A')}%\n\n"
self.send_message(message)
def send_top_pick(self, row):
"""Send top pick with detailed analysis"""
message = f"""⭐ *TOP PICK: {row['symbol']}*
Price: ₹{row['close']}
Change: {row.get('change_pct', 0)}%
RSI: {row.get('rsi', 'N/A')}
Momentum: {row.get('momentum', 'N/A')}%
Volume Ratio: {row.get('volume_ratio', 'N/A')}x
Score: {row.get('score', 'N/A')}/100
Action: Consider buying at market price
Stop Loss: -5%
Target: +10%"""
self.send_message(message)
# Usage
screener_bot = ScreenerAlertBot()
# After running screener
results = screener.screen_nifty50()
screener_bot.send_screener_results(results)
# Send top pick
top_pick = results.iloc[0]
screener_bot.send_top_pick(top_pick)
Step 6: News Alert System
class NewsAlertBot(NSEAlertBot):
def __init__(self):
super().__init__()
self.keywords = [
'Nifty', 'Sensex', 'banking', 'IT stocks', 'RBI',
'SEBI', 'FII', 'budget', 'earnings', 'merger'
]
def fetch_nse_news(self):
"""Fetch latest NSE news"""
url = "https://www.nseindia.com/api/latest-circulars"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
}
try:
import requests
response = requests.get(url, headers=headers, timeout=10)
data = response.json()
headlines = []
for item in data.get('data', [])[:10]:
headlines.append({
'title': item.get('subject', ''),
'date': item.get('date', ''),
'url': item.get('link', '')
})
return headlines
except Exception as e:
print(f"Failed to fetch news: {e}")
return []
def filter_important_news(self, headlines):
"""Filter news based on keywords"""
important = []
for headline in headlines:
for keyword in self.keywords:
if keyword.lower() in headline['title'].lower():
important.append(headline)
break
return important
def send_news_alert(self):
"""Send important news to Telegram"""
headlines = self.fetch_nse_news()
important = self.filter_important_news(headlines)
if not important:
return
message = "📰 *Important NSE News*\n\n"
for i, news in enumerate(important[:5], 1):
message += f"{i}. *{news['title']}*\n"
message += f" Date: {news['date']}\n\n"
self.send_message(message)
# Usage
news_bot = NewsAlertBot()
news_bot.send_news_alert()
Step 7: Portfolio P&L Alerts
class PortfolioAlertBot(NSEAlertBot):
def __init__(self, portfolio):
super().__init__()
self.portfolio = portfolio # List of {symbol, qty, buy_price}
def calculate_pnl(self):
"""Calculate portfolio P&L"""
total_value = 0
total_cost = 0
pnl_details = []
for stock in self.portfolio:
try:
ticker = f"{stock['symbol']}.NS"
data = yf.Ticker(ticker)
hist = data.history(period="1d")
if len(hist) == 0:
continue
current_price = hist['Close'].iloc[-1]
current_value = current_price * stock['qty']
cost = stock['buy_price'] * stock['qty']
pnl = current_value - cost
pnl_pct = (current_price - stock['buy_price']) / stock['buy_price'] * 100
total_value += current_value
total_cost += cost
pnl_details.append({
'symbol': stock['symbol'],
'qty': stock['qty'],
'buy_price': stock['buy_price'],
'current': current_price,
'pnl': pnl,
'pnl_pct': pnl_pct
})
except Exception as e:
print(f"Error calculating {stock['symbol']}: {e}")
total_pnl = total_value - total_cost
total_pnl_pct = (total_pnl / total_cost * 100) if total_cost > 0 else 0
return {
'total_value': total_value,
'total_cost': total_cost,
'total_pnl': total_pnl,
'total_pnl_pct': total_pnl_pct,
'stocks': pnl_details
}
def send_portfolio_alert(self):
"""Send portfolio P&L to Telegram"""
pnl = self.calculate_pnl()
emoji = "🟢" if pnl['total_pnl'] > 0 else "🔴"
message = f"""{emoji} *Portfolio Update*
Total Value: ₹{pnl['total_value']:,.0f}
Total P&L: ₹{pnl['total_pnl']:,.0f} ({pnl['total_pnl_pct']:.1f}%)
*Stock-wise:*
"""
for stock in pnl['stocks']:
emoji_stock = "🟢" if stock['pnl'] > 0 else "🔴"
message += f"\n{emoji_stock} *{stock['symbol']}*: "
message += f"₹{stock['pnl']:,.0f} ({stock['pnl_pct']:.1f}%)"
self.send_message(message)
# Usage
portfolio = [
{'symbol': 'TCS', 'qty': 10, 'buy_price': 4200},
{'symbol': 'INFY', 'qty': 20, 'buy_price': 1550},
{'symbol': 'HDFC', 'qty': 15, 'buy_price': 1650}
]
portfolio_bot = PortfolioAlertBot(portfolio)
portfolio_bot.send_portfolio_alert()
Step 8: Schedule Daily Brief
from schedule import every, repeat, run_pending
import time
class DailyBriefBot(NSEAlertBot):
def send_morning_brief(self):
"""Send morning market brief"""
# Fetch Nifty data
nifty = yf.Ticker("^NSEI")
hist = nifty.history(period="2d")
if len(hist) >= 2:
prev_close = hist['Close'].iloc[-2]
current = hist['Close'].iloc[-1]
change = current - prev_close
change_pct = (change / prev_close) * 100
message = f"""☀️ *Good Morning! Market Brief*
*Nifty 50:*
- Previous Close: ₹{prev_close:,.0f}
- Current: ₹{current:,.0f}
- Change: ₹{change:,.0f} ({change_pct:+.2f}%)
*Global Cues:*
- US markets: {'Up' if change > 0 else 'Down'}
- Asian markets: Mixed
- VIX: {hist['Close'].iloc[-1] * 100:.1f}
*Today's Focus:*
- Key levels: 21,800 - 22,200
- Watch: TCS earnings, RBI policy
- Sentiment: {'Bullish' if change > 0 else 'Bearish'}
*Quote of the day:*
"The stock market is a device for transferring money from the impatient to the patient." — Buffett
Good luck trading today! 📈"""
self.send_message(message)
def send_eod_summary(self):
"""Send end-of-day summary"""
nifty = yf.Ticker("^NSEI")
hist = nifty.history(period="1d")
if len(hist) > 0:
close = hist['Close'].iloc[-1]
high = hist['High'].iloc[-1]
low = hist['Low'].iloc[-1]
message = f"""🌙 *Market Closed*
*Nifty 50:*
- Close: ₹{close:,.0f}
- High: ₹{high:,.0f}
- Low: ₹{low:,.0f}
- Range: {((high - low) / low * 100):.1f}%
*Tomorrow's Plan:*
- Review today's trades
- Check FII/DII data
- Run screener
- Set alerts for key levels
Rest up. Markets reopen at 9:15 AM. 🌅"""
self.send_message(message)
# Schedule
brief_bot = DailyBriefBot()
# Morning brief at 8:45 AM
@repeat(every().day.at("08:45"))
def morning_brief():
brief_bot.send_morning_brief()
# EOD summary at 3:45 PM
@repeat(every().day.at("15:45"))
def eod_summary():
brief_bot.send_eod_summary()
# Run scheduler
while True:
run_pending()
time.sleep(60)
Step 9: Advanced Features
9.1 Interactive Commands
from telegram.ext import CommandHandler
def start(update, context):
"""Handle /start command"""
welcome_message = """👋 Welcome to Shakti Trading Bot!
Commands:
/start - Show this message
/price SYMBOL - Get current price (e.g., /price TCS)
/portfolio - Show portfolio P&L
/alerts - List active alerts
/brief - Get morning brief
/news - Get latest NSE news
/help - Show help
Example: /price TCS"""
update.message.reply_text(welcome_message)
def price_command(update, context):
"""Handle /price command"""
if len(context.args) == 0:
update.message.reply_text("Usage: /price SYMBOL\nExample: /price TCS")
return
symbol = context.args[0].upper()
try:
ticker = f"{symbol}.NS"
stock = yf.Ticker(ticker)
hist = stock.history(period="1d")
if len(hist) > 0:
price = hist['Close'].iloc[-1]
change = hist['Close'].iloc[-1] - hist['Open'].iloc[0]
change_pct = (change / hist['Open'].iloc[0]) * 100
emoji = "🟢" if change > 0 else "🔴"
message = f"{emoji} *{symbol}*\n\n"
message += f"Price: ₹{price:.2f}\n"
message += f"Change: ₹{change:+.2f} ({change_pct:+.2f}%)"
update.message.reply_text(message, parse_mode='Markdown')
else:
update.message.reply_text(f"No data found for {symbol}")
except Exception as e:
update.message.reply_text(f"Error: {e}")
def portfolio_command(update, context):
"""Handle /portfolio command"""
portfolio_bot = PortfolioAlertBot(PORTFOLIO)
pnl = portfolio_bot.calculate_pnl()
emoji = "🟢" if pnl['total_pnl'] > 0 else "🔴"
message = f"{emoji} *Portfolio P&L*\n\n"
message += f"Total: ₹{pnl['total_pnl']:,.0f} ({pnl['total_pnl_pct']:+.1f}%)\n\n"
for stock in pnl['stocks']:
emoji_s = "🟢" if stock['pnl'] > 0 else "🔴"
message += f"{emoji_s} {stock['symbol']}: ₹{stock['pnl']:,.0f}\n"
update.message.reply_text(message, parse_mode='Markdown')
# Register handlers
updater = Updater(TOKEN)
dispatcher = updater.dispatcher
dispatcher.add_handler(CommandHandler("start", start))
dispatcher.add_handler(CommandHandler("price", price_command))
dispatcher.add_handler(CommandHandler("portfolio", portfolio_command))
# Start bot
updater.start_polling()
updater.idle()
9.2 Chart Generation
import matplotlib.pyplot as plt
class ChartBot(NSEAlertBot):
def send_price_chart(self, symbol, days=30):
"""Generate and send price chart"""
ticker = f"{symbol}.NS"
stock = yf.Ticker(ticker)
hist = stock.history(period=f"{days}d")
if len(hist) == 0:
return
# Create chart
plt.figure(figsize=(10, 6))
plt.plot(hist.index, hist['Close'], color='blue', linewidth=2)
plt.title(f"{symbol} - Last {days} Days")
plt.xlabel('Date')
plt.ylabel('Price (₹)')
plt.grid(True, alpha=0.3)
plt.tight_layout()
# Save
chart_path = f"/tmp/{symbol}_chart.png"
plt.savefig(chart_path, dpi=100)
plt.close()
# Send
self.send_photo(chart_path, caption=f"{symbol} price chart - {days} days")
# Clean up
os.remove(chart_path)
# Usage
chart_bot = ChartBot()
chart_bot.send_price_chart('TCS', days=30)
Step 10: Run on Termux as Background Service
Method 1: Termux:Boot + Service
# Install Termux:Boot app from F-Droid
# This allows auto-start on boot
# Create service script
cat > ~/nse_bot/nse_bot_service.sh << 'EOF'
#!/data/data/com.termux/files/home/usr/bin/bash
cd ~/nse_bot
python nse_bot.py >> logs/bot.log 2>&1
EOF
chmod +x ~/nse_bot/nse_bot_service.sh
Method 2: Cron Jobs (Recommended)
# Edit crontab
crontab -e
# Add these lines:
# Morning brief at 8:45 AM
45 8 * * 1-5 python ~/nse_bot/daily_brief.py >> ~/nse_bot/logs/brief.log 2>&1
# Price alerts every 5 min during market hours
*/5 9-15 * * 1-5 python ~/nse_bot/price_alerts.py >> ~/nse_bot/logs/alerts.log 2>&1
# EOD summary at 3:45 PM
45 15 * * 1-5 python ~/nse_bot/eod_summary.py >> ~/nse_bot/logs/eod.log 2>&1
# News alerts every 30 min
*/30 9-15 * * 1-5 python ~/nse_bot/news_alerts.py >> ~/nse_bot/logs/news.log 2>&1
Method 3: Keep Alive with Termux Widget
# Install Termux:Widget
# Add widget to home screen
# Point to script:
~/nse_bot/run_bot.sh
Complete Bot Code (Copy-Paste)
File: nse_bot_complete.py
from telegram import Bot
from telegram.ext import Updater, CommandHandler
import yfinance as yf
import pandas as pd
import time
from datetime import datetime
import os
TOKEN = "YOUR_TOKEN"
CHAT_ID = "YOUR_CHAT_ID"
class CompleteNSEBot:
def __init__(self):
self.bot = Bot(token=TOKEN)
self.chat_id = CHAT_ID
self.alerts = []
def send_message(self, text):
self.bot.send_message(chat_id=self.chat_id, text=text, parse_mode='Markdown')
def price_alert(self, symbol, condition, target):
self.alerts.append({'symbol': symbol, 'condition': condition, 'target': target})
def check_alerts(self):
for alert in self.alerts:
if alert.get('triggered'):
continue
try:
data = yf.Ticker(f"{alert['symbol']}.NS")
hist = data.history(period="1d")
if len(hist) == 0:
continue
price = hist['Close'].iloc[-1]
if alert['condition'] == 'above' and price >= alert['target']:
alert['triggered'] = True
self.send_message(f"🔔 {alert['symbol']} crossed ₹{alert['target']}!\nCurrent: ₹{price:.2f}")
elif alert['condition'] == 'below' and price <= alert['target']:
alert['triggered'] = True
self.send_message(f"🔔 {alert['symbol']} fell below ₹{alert['target']}!\nCurrent: ₹{price:.2f}")
except:
continue
def run(self):
"""Main loop"""
while True:
now = datetime.now()
if now.hour >= 9 and now.hour <= 15:
self.check_alerts()
time.sleep(300) # 5 minutes
if __name__ == "__main__":
bot = CompleteNSEBot()
# Add your alerts
bot.price_alert('NIFTY', 'above', 22500)
bot.price_alert('NIFTY', 'below', 22000)
bot.price_alert('TCS', 'above', 4500)
bot.run()
FAQ
Q1: Is Telegram bot free?
A: Yes. Telegram API is completely free. No limits on messages.
Q2: Can I run this without Termux?
A: Yes. Any Python environment works. Termux is just convenient for Android.
Q3: Do I need a server?
A: No. Your phone runs the bot 24/7 via Termux + cron.
Q4: What if my phone is off?
A: Bot stops. For 24/7 uptime, use a cheap VPS (~₹200/month) or Raspberry Pi.
Q5: Can I add multiple users?
A: Yes. Replace single CHAT_ID with a list. Send to all.
Q6: Is this secure?
A: Bot token = password. Don't share it. Use environment variables.
Q7: Can I send charts?
A: Yes. Use matplotlib to generate charts, send via send_photo().
Q8: What's the message limit?
A: Telegram allows ~30 messages/second per bot. Way more than you need.
The Bottom Line
A Telegram bot for NSE alerts gives you:
- Instant notifications (1-2 seconds)
- Zero cost (free API, no server)
- Works on Android (Termux)
- Customizable (your rules, your alerts)
- Scalable (add more features anytime)
This is what I use in nse_ai_agent. And now you can build it too.
Connect With Shakti Tiwari
- Website: optiontradingwithai.in
- Dev.to: @shaktitiwari715-ai
- GitHub: @shaktitiwari715-ai
- X/Twitter: @shaktitiwari
- Telegram: @shaktitrade
Published on Dev.to | Tags: #telegram #nse #trading #bot #python #android #termux
Author
Shakti Tiwari is an AI/quant trader and open-source developer from Chandigarh. He builds free trading tools for Indian retail traders and writes about NSE markets, Python, and AI in finance. Author of Right Brain Wins and Brain Markets.
Top comments (0)