Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 4 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,6 @@
# API-Stock-Signalling
###### NOTE: this is a project to practice your Python industry skills. Please upload your solutions by opening a new branch to the main. All files that are instantly merged to the main will be deleted.
## Overview
A small consultancy who is currently delivering client work for a major bank wants to monitor the prices for the following stocks: Tesla, Apple, Microsoft, Google, and Nike. Once the stock falls below a certain price, they want to be immediately notified so that they can purchase more stocks.
## Goal
Write a real time Python application that monitors the prices then notifies the user when the price of any of these stocks falls by at least £0.25 GBP. The user should also be notified if today's price is less than the 7-day average of that stock price.
## Brief
To do this, the client has recommended using a popular automation website called IFTTT: https://ifttt.com/. They are willing to use a different provider or solution (use those consultancy skills!) if you believe there is a better option.
#### IFTTT Applet
# Stock-Monitor

IFTTT stands for “If This Then That” and it’s an automation platform that allows you to connect different apps and services together. An applet is a connection between two or more apps or devices that enables you to do something that those services couldn’t do on their own. Applets consists of two parts triggers and actions. Triggers tell an applet to start, and actions are the end result of an applet run. To use an applet, you’ll need to create a free IFTTT account and connect your apps and devices to IFTTT so that they can talk to each other.
Overview:
This application monitors the prices for the following stocks: Tesla, Apple, Microsoft, Google, and Nike and sends out tailored alerts.

#### Proposed Workflow
- Write a script that returns the stock prices. This will involve making an API request.
- Set up a IFTTT account and applet. This will be accessible via the mobile app which allows you to trigger the webhook service provided by IFTTT.
- You will need to configure the 'webhooks' service to receive web requests. You can find more details here: https://ifttt.com/maker_webhooks.
- From here you can write an application that utilises the requests package to make POST and GET requests.
- Think of what aspects or components of your proposed solution needs to be tested and what would these tests look like and attempt to implement such tests.

## Main Considerations
- Choose an automation approach. Are you planning on using IFTTT or another workflow?
- What API are you going to use? You can use this as a starting point: https://github.com/public-apis/public-apis
- Remember, this is a proposed workflow. If you believe you have a more efficient approach please reach out to the Academy Team.
#### Requirements Gathering
The start to any project is to make sure you have clear and well-defined requirements for your project. Most projects start with a vague idea of what the stakeholder wants, and as a consultant, we will never have as much knowledge about their problem/business context as they do. Therefore, we need to get as much information out of them as possible, as they will subconsciously assume that we know everything. For this project, Alex Naylor will be the stakeholder.

If you don't know the answer to any question then you should always ask - NEVER ASSUME. This will only risk the accuracy of your work and end up having to do everything all over again if you wrongly assume.

Questions to ask yourself constantly throughout the project are:

- What is the purpose of this project, why does the stakeholder want this and what is the desired outcome of the project?
- Is there any extra info that the stakeholder could tell you to help tailor the project to what they want?

## Assessment
For the assessment, you will have a 15 minute technical interview. This will consist of a strict 5 minute presentation on your technical solution. There is no need to create slides for this but you may want to demo your code. For the second half of the session, you will be asked technical questions related to the project. You will be assessed on:
- Project Complexity
- Brief Completness i.e. have you managed to meet the client brief?
- Coding Standards

Good Luck!
If the price of a stock falls by more than £0.25, this will immediately trigger a notification to be sent out, allowing the purchase of more stock. If the stock price falls below the 7 day average, this will also trigger an alert. For our notifications, we have used automation website IFTTT: https://ifttt.com/.
119 changes: 119 additions & 0 deletions stock_monitor.py

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was done well:

  • Really good use of different types of documentation throughout the script
  • Really explicit code - it is easy to see what purpose each line of code serves in regards to the overall project
  • Good naming - variable and function names were relevant and long enough to inform myself and other reviewers the purpose of certain functions, but not overly long.

Critiques:

  • If adhering to the PEP8 standard, then some line did go over the 79 character limit. Would suggest using backwards slash "" to break lines up.

Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import requests
import schedule
import time
import os
# IEX Cloud and IFTTT API token
API_TOKEN = os.environ.get('IEX_API_KEY')
IFTTT_KEY = os.environ.get('IFTTT_API_KEY')

# List of stock symbols to monitor
stock_symbols = ['TSLA', 'AAPL', 'MSFT', 'GOOGL', 'NKE']
previous_prices = {symbol: {'price': None, 'timestamp': None} for symbol in stock_symbols}

"""
This function will send alerts to the IFTTT app which will show up as a notification on your
mobile device
"""
def send_notification_to_ifttt(stock_alerts):
for symbol in stock_alerts:
url = f'https://maker.ifttt.com/trigger/stock_price_alert/with/key/{IFTTT_KEY}'
data = {'value1': f'Alert: Price drop for {symbol}'}
response = requests.post(url, json=data)
if response.status_code == 200:
print(f"Notification sent for {symbol}")
else:
print(f"Failed to send notification for {symbol}")

"""
Using the IEX API, this function will make a get request for each symbol in the list 'symbols'
which will be defined in the following line (stock_prices)
"""
def get_stock_prices(symbols):
stock_prices = {}
for symbol in symbols:
url = f'https://cloud.iexapis.com/stable/stock/{symbol}/quote?token={API_TOKEN}' # Construct the URL for the API request by formatting the symbol and API token
response = requests.get(url) # Send an HTTP GET request to the API endpoint
data = response.json()
stock_prices[symbol] = data['latestPrice'] # Retrieve the 'latestPrice' field from the parsed JSON data and store it in the dictionary
return stock_prices # Return the dictionary containing stock prices for each symbol

# Get stock prices for specificed symbols
stock_prices = get_stock_prices(stock_symbols)
# Get previous price for specificed symbols - this will be used
previous_prices = {symbol: {'price': None, 'timestamp': None} for symbol in stock_symbols}

# Quick View of current prices for all stocks
for symbol, price in stock_prices.items():
print(f'Current price of {symbol}: ${price}')

"""
This line defines a API request named get_historical_data that takes two parameters: symbol and range for the last 7 days.
"""
def get_historical_data(symbol, range='1m'):
url = f'https://cloud.iexapis.com/stable/stock/{symbol}/chart/{range}?token={API_TOKEN}'
response = requests.get(url)
data = response.json()
return data

"""
This function calculates the 7 day average using the data from the API get request above.
"""
def calculate_7_day_average(closing_prices):
return sum(closing_prices) / 7
seven_day_averages = {
symbol: calculate_7_day_average([entry['close'] for entry in get_historical_data(symbol)[-7:]])
for symbol in stock_symbols
}

"""
This function defines the rule for the alerts. A alert will be triggered if the current price is
at least 0.25 below the 7 day average.
"""
def check_price_alerts(current_prices, seven_day_averages, threshold=0.25):
alerts = []
for symbol in current_prices:
if symbol in seven_day_averages:
price_diff = seven_day_averages[symbol] - current_prices[symbol]
previous_price = previous_prices[symbol]['price']
if previous_price is not None:
diff = previous_price - current_prices[symbol] # Calculate the difference
if abs(diff) >= threshold: # Check if the absolute difference is greater than or equal to the threshold
print(f"Alert triggered for {symbol}: Price has dropped by more than $0.25!")
alerts.append(symbol)
send_notification_to_ifttt(alerts)
if price_diff >0:
print(f"Alert triggered for {symbol}: Current price is below 7-day average by {price_diff:.2f}")
alerts.append(symbol)
send_notification_to_ifttt(alerts)
return alerts

"""
This set's a schedule for the script to run every 5 seconds. It also updated the previous price
with the current price and timestamps
"""
current_prices = get_stock_prices(stock_symbols) # Get current stock prices
alerts = check_price_alerts(current_prices, seven_day_averages) #Check price alerts
def run_stock_monitor():
current_prices = get_stock_prices(stock_symbols)
seven_day_averages = {
symbol: calculate_7_day_average([entry['close'] for entry in get_historical_data(symbol)[-7:]])
for symbol in stock_symbols
}
alerts = check_price_alerts(current_prices, seven_day_averages)

if alerts:
send_notification_to_ifttt(alerts)
else:
print("No price alerts triggered.")
# Update the previous prices dictionary with the current prices and timestamps
for symbol in stock_symbols:
previous_prices[symbol]['price'] = current_prices[symbol]
previous_prices[symbol]['timestamp'] = time.time()

# Schedule the `run_stock_monitor` function to run every 5 seconds
schedule.every(5).seconds.do(run_stock_monitor)

# Run the scheduled tasks
while True:
schedule.run_pending()
time.sleep(1)