In this post, we are going to use the Alpha Vantage API and the Slack API to create a Slack bot to notify us if the stock indicators meet some conditions of interests. First of all, you need to sign up for the 2 APIs and get your private key for each.
import requests
import json
import plotly as px
import csv
import requests
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
import os
import time
import re
from slackclient import SlackClient
import numpy as np
import argparse
Get stock information from Alpha Vantage
Assume that we are interested in the following stock indexes: price, SMA, STOCH and MACDEXT. Next, we would like to get information about the “NVDA” stock. The following functions define API calls to get such information:
key = "YOUR_API_KEY"
def getPrice(symbol="NVDA"):
CSV_URL = base_url + "query?function=TIME_SERIES_DAILY&symbol=" + symbol
CSV_URL += "&apikey=" + key
with requests.Session() as s:
res = s.get(CSV_URL).json()
return res
def getSMA(symbol="NVDA", interval="daily", slice="year1month1", time_period="14",series_type="open"):
CSV_URL = base_url + "query?function=SMA&symbol=" + symbol
CSV_URL += "&interval=" + interval + "&time_period=" + time_period
CSV_URL += "&series_type=" + series_type + "&apikey=" + key
with requests.Session() as s:
res = s.get(CSV_URL).json()
return res
def getSTOCH(symbol="NVDA", interval="daily"):
CSV_URL = base_url + "query?function=STOCH&symbol=" + symbol
CSV_URL += "&interval=" + interval + "&apikey=" + key
with requests.Session() as s:
res = s.get(CSV_URL).json()
return res
def getMACDEXT():
CSV_URL = base_url + "query?function=MACDEXT&symbol=" + "STM.DEX"
CSV_URL += "&interval=" + "daily" +"&series_type="+"open"+"&apikey=" + key
with requests.Session() as s:
res = s.get(CSV_URL).json()
return res
price_list = getPrice()
sna_list = getSMA()
stoch_list = getSTOCH()
macd_list = getMACDEXT()
We can transform the raw data to Pandas dataframes for processing:
prices_df = pd.DataFrame(price_list["Time Series (Daily)"]).transpose()[:n_days]
sma_df = pd.DataFrame(sna_list['Technical Analysis: SMA']).transpose()[:n_days]
stoch_df = pd.DataFrame(stoch_list['Technical Analysis: STOCH']).transpose()[:n_days]
macd_df = pd.DataFrame(macd_list['Technical Analysis: MACDEXT']).transpose()[:n_days]
We can also create a joint dataframe:
join_df = prices_df.join(sma_df).join(stoch_df).join(macd_df)
join_df = join_df.rename_axis('date').reset_index()
join_df = join_df.rename(columns={'1. open': 'open', '2. high': 'high', '3. low': 'low','4. close': 'close','5. volume': 'volume'})
columns = ["open", "high","low","close","volume","SMA", "SlowK","SlowD", "MACD_Hist", "MACD", "MACD_Signal"]
for c in columns:
join_df[c] = pd.to_numeric(join_df[c], downcast="float")
join_df.head()
join_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 100 non-null object
1 open 100 non-null float32
2 high 100 non-null float32
3 low 100 non-null float32
4 close 100 non-null float32
5 volume 100 non-null float32
6 SMA 99 non-null float32
7 SlowD 99 non-null float32
8 SlowK 99 non-null float32
9 MACD 98 non-null float32
10 MACD_Hist 98 non-null float32
11 MACD_Signal 98 non-null float32
dtypes: float32(11), object(1)
memory usage: 5.2+ KB
Plotly provides a convenient way to plot time series data:
df_sma = pd.melt(join_df, id_vars = ['date'], value_vars = ['SMA', 'close'])
xi = x for (x, y) in intersections]
yi = [y for (x, y) in intersections]
fig1 = px.line(df_sma, x = 'date', y = 'value', color = 'variable')
# Show plot
fig1.show()
The resulting plot can be saved as interactive (.html) or static (e.g. .png) images:
fig1.write_image("sma_close.webp")
fig1.write_html("sma_close.html")
Create a Slack Bot for notification
You will need the slack_sdk package to make the API calls directly with python:
import logging
import os
# Import WebClient from Python SDK (github.com/slackapi/python-slack-sdk)
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
def send_message(msg, channel="money"):
client = WebClient(token=SLACK_BOT_TOKEN)
logger = logging.getLogger(__name__)
try:
# Call the conversations.list method using the WebClient
result = client.chat_postMessage(
channel=channel,
text=msg, # You could also use a blocks[] array to send richer content
username='Cute Bot',
icon_emoji=':robot_face:'
)
logger.info(result)
except SlackApiError as e:
print(f"Error: {e}")
def send_file(file_name, init_cmt = "Here's my file :smile:", channel="money"):
client = WebClient(token=SLACK_BOT_TOKEN)
logger = logging.getLogger(__name__)
try:
# Call the conversations.list method using the WebClient
result = client.files_upload(
channels=channel,
initial_comment=init_cmt,
file=file_name,
username='Cute Bot',
icon_emoji=':robot_face:'
)
# Log the result
logger.info(result)
except SlackApiError as e:
print(f"Error: {e}")
We can try sending something to our channel:
send_message("hello")
send_file("sma_close.webp")
Deploy the Stock Bot on server (coming ….)
Now as we are all set, we can deploy our bot to a server so that it checks the price every 5 minutes and sends you a Slack notice if some predefined conditions are met. We can deploy to some remote server such as Heroku, or set up a local server on Raspberry Pi and deploy to it. I will come back to this in a later post.