Skip to content

Instantly share code, notes, and snippets.

@oliveratgithub
Last active December 2, 2025 22:26
Show Gist options
  • Select an option

  • Save oliveratgithub/d5236c2968417ecd8eefaba9ca771105 to your computer and use it in GitHub Desktop.

Select an option

Save oliveratgithub/d5236c2968417ecd8eefaba9ca771105 to your computer and use it in GitHub Desktop.
Python script to publish Stock price updates to Telegram Chat - python3.x compatible and can run as a nohup service

TSLA @ USD 571.62
📈 up +31.22 (last 15 minutes)

BTC-USD @ USD 91'494.52
📈 up +5'188.43 (last 11 hours)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ~~~~~
# Telegram Bot API configs for stock_notifications.py
# ~~~~~
token=''
chat=''
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ~~~~~
# == Setup ==
# % pip3 install [--user] requests
# % pip3 install [--user] yfinance
#
# Add and make Python-scripts executable:
# % chmod +x ./stock_price_notifier.py
# % chmod +x ./botconfigs.py
#
# == Usage ==
# one time (repeat every minute):
# % python3 ./stock_price_notifier.py "BTC-USD"
#
# running as a service (every 1 hour):
# % nohup python3 ./stock_price_notifier.py "TSLA" 3600 &
#
# running as a service (every 11 hours, if threshold above 99. 9):
# % nohup python3 ./stock_price_notifier.py "TSLA" 3600 99.9 &
#
# ~~~~~
# Original source: https://codeburst.io/indian-stock-market-price-notifier-bot-telegram-92e376b0c33a
# Resources:
# - Symbol: https://finance. yahoo.com/quote/TSLA?p=TSLA
# - YF for Python: https://pypi.org/project/fix-yahoo-finance/0.1.30/
# - YF4P docu: https://aroussi.com/post/python-yahoo-finance
# - Telegram Bot API: https://core.telegram.org/bots/api#sendmessage
# ~~~~~
import sys
import gc
import time
import requests
import urllib.parse
import yfinance as yf
import botconfigs as bot
# Check for stock symbol passed as script parameter
if len(sys.argv) <= 1:
print("Missing a valid symbol as parameter. Use something like 'TSLA' or 'BTC-USD'...")
sys.exit(1)
else:
symbol = sys.argv[1]
# Check for passed timer seconds parameter
if len(sys.argv) <= 2:
# Default: 1 minute = 60 seconds
repeat = 60
elif int(sys.argv[2]) >= 1:
repeat = int(sys.argv[2])
else:
print("Invalid second parameter: must be a number representing seconds to re-run script.")
sys.exit(1)
# Check for optional price notification threshold as 3rd parameter
if len(sys.argv) <= 3:
# Default: very low threshold of 0. 01 (so it needs at least a change)
price_threshold = 0.01
elif float(sys.argv[3]) > 0.00:
price_threshold = float(sys.argv[3])
else:
print("Invalid 3rd parameter: must be a positive number as price change threshold (e.g. 1.00).")
sys. exit(1)
# Global vars
currency = ''
price_initial = 0
price = 0
# Check for valid Telegram Bot Configs from botconfigs.py
if len(bot.token) > 40 and len(bot.chat) > 5:
bot_token = bot.token
bot_chatID = bot.chat
else:
print("Missing botconfigs!")
sys.exit(1)
# Get currency for symbol
if currency == '':
try:
ticker_meta = yf.Ticker(symbol)
ticker_info = ticker_meta.info
# Try different ways to get currency
if 'currency' in ticker_info:
currency = ticker_info['currency']
elif 'financialCurrency' in ticker_info:
currency = ticker_info['financialCurrency']
else:
# Default currency if none found
print(f"No currency info found for {symbol}, using USD")
currency = 'USD'
except Exception as e:
print(f"Error getting currency for {symbol}: {e}")
currency = 'USD'
def getStock():
global symbol
global price_threshold
global currency
global price_initial
global price
try:
# Get ticker data
ticker = yf.download(symbol, period="1d", auto_adjust=True)
# Check if we got data
if ticker.empty:
print(f"No data received for {symbol}")
return
# Get the latest close price (last row, Close column)
price = float(ticker['Close'].iloc[-1].iloc[0])
# Get initial price if not set
if price_initial == 0:
price_initial = float(ticker['Open']. iloc[0].iloc[0])
# Round after conversion
price = round(price, 2)
price_initial = round(price_initial, 2)
if price == price_initial:
price_diff = 0
price_diff_str = ''
elif price > price_initial:
price_diff = round(price - price_initial, 2)
price_diff_str = f"📈 up {str("+{0:,.2f}".format(price_diff)).replace(',', '\'')}"
else:
price_diff = round(price_initial - price, 2)
price_diff_str = f"📉 dip {str("-{0:,.2f}".format(price_diff)).replace(',', '\'')}"
# Price diff above given threshold AND change of stock price
if abs(price_diff) >= price_threshold:
time_checks_str = ''
if repeat >= 86400:
time_checks = int(repeat // 86400)
time_checks_str = f" (last {time_checks} {'day' if time_checks == 1 else 'days'})"
elif repeat >= 3600:
time_checks = int(repeat // 3600)
time_checks_str = f" (last {time_checks} {'hour' if time_checks == 1 else 'hours'})"
elif repeat >= 60:
time_checks = int(repeat // 60)
time_checks_str = f" (last {time_checks} {'minute' if time_checks == 1 else 'minutes'})"
else:
time_checks_str = f" (last {repeat} {'second' if repeat == 1 else 'seconds'})"
message = symbol+" @ *"+currency+" "+str("{0:,.2f}". format(price)).replace(',', '\'')+"*\n"+price_diff_str+time_checks_str
reserved_chars = ['(', ')', '?', '+', '-', '.', '^', '$']
for char in reserved_chars:
message = message.replace(char, f"\\{char}")
message = urllib.parse.quote_plus(message)
send = 'https://api.telegram.org/bot' + bot_token + '/sendMessage?parse_mode=MarkdownV2&disable_notification=true&chat_id=' + bot_chatID + '&text=' + message
try:
response = requests.get(send)
response.raise_for_status() # Raise an exception for bad status codes
# Set new price_initial to check against future changes
price_initial = price
except requests.exceptions.RequestException as e:
print(f"Error sending Telegram message: {e}")
return
except Exception as e:
print(f"Error in yfinance: {e}")
return
finally:
# Clean up memory
del ticker
gc.collect() # Force garbage collection
while True:
getStock()
time. sleep(repeat)
gc. collect() # Additional garbage collection after each iteration
MIT License
Copyright (c) 2025 Oliver <https://github.com/oliveratgithub>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@ruleroller
Copy link

And the script used to work well for about one month and just one day, I found it stop working.

@ruleroller Ah I see! I thought it never worked… Maybe yfinance must be updated? There‘s a very recent issue on their GitHub Repo about this, can you try that?
ranaroussi/yfinance#764

It works! Thanks! 👍

@oliveratgithub
Copy link
Author

It works! Thanks! 👍

Awesome 😎 I have to upgrade on my server as well then…

@ruleroller
Copy link

It works! Thanks! 👍

Awesome 😎 I have to upgrade on my server as well then…

Help, I just found many stocks in Shanghai market, symbol likes '600307.ss' '600282.ss' and so on can't fetch the data.

'TSLA', 'BTC-USD' are fine though.

The error msg is below:
image

@oliveratgithub
Copy link
Author

Help, I just found many stocks in Shanghai market, symbol likes '600307.ss' '600282.ss' and so on can't fetch the data.

@ruleroller can you try making a „simple“ Python Script to not do more than trying to fetch one of these symbols, in order to see if it‘s a Yfinance data issue? Here‘s a short guide that you could adapt: https://analyticsindiamag.com/hands-on-guide-to-using-yfinance-api-in-python/

@ruleroller
Copy link

Help, I just found many stocks in Shanghai market, symbol likes '600307.ss' '600282.ss' and so on can't fetch the data.

@ruleroller can you try making a „simple“ Python Script to not do more than trying to fetch one of these symbols, in order to see if it‘s a Yfinance data issue? Here‘s a short guide that you could adapt: https://analyticsindiamag.com/hands-on-guide-to-using-yfinance-api-in-python/

@oliveratgithub, thanks for your advise, but I know little python.

I googled, found that maybe the the VPS's IP reached the limit of the yfinance, or just yfinance data has temporary issue, or something else.

I also tried this script in another server and run the script for several hours, everything is fine for now (image below).
image

@oliveratgithub
Copy link
Author

👍

@aoi2010
Copy link

aoi2010 commented Mar 19, 2022

When i run it as told =  python3 ./stock_notifications.py "TSLA"

I get this error message

File "", line 1
python3 ./stock_notifications.py "TSLA"
^
SyntaxError: invalid syntax
and when i run it as normal it shows
Missing a valid symbol as parameter. Use something like 'TSLA' or 'BTC-USD'...
repl process died unexpectedly:

@oliveratgithub
Copy link
Author

oliveratgithub commented Mar 19, 2022

I get this error message
File "", line 1 python3 ./stock_notifications.py "TSLA" ^ SyntaxError: invalid syntax and when

@aoi2010 That sounds super strange.
Can you run other python scripts successfully?
And have you installed all required prerequisites (libraries) using pip?
Is the path to the stock_notifications.py actually correct (when you do ./ you should be in the same directory as the Script is stored in…)?

@ruleroller
Copy link

Hi, again~

Mine is not working for about one week, with Python 3.8.16, and the modules are also up to date, but still can't help.

image

Any idea to solve this?

@oliveratgithub
Copy link
Author

oliveratgithub commented Dec 18, 2022

Hi, again~

Mine is not working for about one week, with Python 3.8.16, and the modules are also up to date, but still can't help.

Any idea to solve this?

Thanks for bringing this to my attention @ruleroller – I think it’s related to this issue within the yfinance library, respectively that Yahoo started obfuscating the data: ranaroussi/yfinance#1246

I will need to adapt the decryption (there’s a python example in the Issue discussion linked above).

Update: a Fix is already in the works on level of the yfinance Library (where this issue should be handeld anyway IMHO). Let’s wait for this patch to be applied. ranaroussi/yfinance#1253

@ruleroller
Copy link

Hi, again~
Mine is not working for about one week, with Python 3.8.16, and the modules are also up to date, but still can't help.
Any idea to solve this?

Thanks for bringing this to my attention @ruleroller – I think it’s related to this issue within the yfinance library, respectively that Yahoo started obfuscating the data: ranaroussi/yfinance#1246

I will need to adapt the decryption (there’s a python example in the Issue discussion linked above).

Update: a Fix is already in the works on level of the yfinance Library (where this issue should be handeld anyway IMHO). Let’s wait for this patch to be applied. ranaroussi/yfinance#1253

Update to latest yfinance 0.1.94 , seems working again now~

😀

@ruleroller
Copy link

😭 Help...

Update yfinance to 0.2.3, turns to this:

image

@ruleroller
Copy link

😭 Help...

Update yfinance to 0.2.3, turns to this:

image

OK, solved.

Here is how:

Reconfige and reinstall the Pyhone 3 with sqlite.

Steps on stackoverflow

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment