1
0
mirror of https://gitlab.com/triple-hops-brewed/raspberry-pi-stock-ticker.git synced 2025-06-15 14:56:38 +00:00

143 lines
4.1 KiB
Python

import sys
import time
from math import ceil
import numpy as np
import requests
from bdfparse import Font
from keys import IEX_TOKEN
from rgbmatrix import RGBMatrix, RGBMatrixOptions, graphics
font_file = "matrix\\fonts\\9x15.bdf"
font = Font(font_file)
matrix_shape = (16, 32) # rows, cols
symbols = ["tsla", "psec", "aapl"]
options = RGBMatrixOptions()
options.chain_length = 1
options.parallel = 1
options.hardware_mapping = "regular"
options.rows, options.cols = matrix_shape
red = (255, 51, 51)
green = (51, 255, 51)
white = (255, 255, 255)
blank = np.zeros((matrix_shape[0], matrix_shape[1], 3))
def stockMatrix(symbols: list, matrix=blank):
array = blank
for symbol in symbols:
message, color = symbolData(symbol)
mess_arr = matrix_message(message, color, matrix_shape[0])
array = np.concatenate((array, mess_arr), axis=1)
return array
def symbolData(symbol: str):
"""
Takes a list of symbol and returns a dictionary of strings with information about the symbol.
"""
IEXurl = "https://cloud.iexapis.com/stable/stock/{symbol}/quote?token={IEX}".format(
symbol=symbol, IEX=IEX_TOKEN
)
response = requests.get(IEXurl)
if response.status_code is 200:
IEXData = response.json()
message = "The current stock price of {name} is {price}".format(
name=IEXData["companyName"], price=IEXData["latestPrice"]
)
# Determine wording of change text
change = round(IEXData["changePercent"] * 100, 2)
if change > 0:
message += ", the stock is currently up {change}% ".format(change=change)
color = green
elif change < 0:
message += ", the stock is currently down {change}% ".format(change=change)
color = red
else:
message += ", the stock hasn't shown any movement today."
color = white
else:
message = "The symbol: {symbol} was not found. ".format(symbol=symbol)
color = white
return (message, color)
def matrix_message(message, color, rows):
message_arr = fit_array(font.word(message), rows)
r = np.multiply(np.full(message_arr.shape, color[0]), message_arr)
g = np.multiply(np.full(message_arr.shape, color[1]), message_arr)
b = np.multiply(np.full(message_arr.shape, color[2]), message_arr)
array = np.zeros((message_arr.shape[0], message_arr.shape[1], 3), dtype=int)
array[:, :, 0] = np.add(array[:, :, 0], r)
array[:, :, 1] = np.add(array[:, :, 1], g)
array[:, :, 2] = np.add(array[:, :, 2], b)
return array
def fit_array(array, rows, operation="centered", fill_value=0):
rows = rows - array.shape[0]
cols = array.shape[1]
offset = (rows, cols)
if operation is "centered":
top = ceil(rows / 2)
top_fill = np.full((top, cols), fill_value)
bottom = rows // 2
bottom_fill = np.full((bottom, cols), fill_value)
return np.concatenate((top_fill, array, bottom_fill), axis=0)
elif operation is "top":
fill = np.full(offset, fill_value)
return np.concatenate((fill, array), axis=0)
elif operation is "bottom":
fill = np.full(offset, fill_value)
return np.concatenate((array, fill), axis=0)
else:
raise Exception("Invalid Operation. Must be either centered, top, or bottom.")
def run(matrix_message):
matrix = RGBMatrix(options=options)
canvas = matrix.CreateFrameCanvas()
for row in range(matrix_shape[0]):
for col in range(matrix_shape[1]):
r = matrix_message[row, col, 0]
g = matrix_message[row, col, 1]
b = matrix_message[row, col, 2]
canvas.SetPixel(row, col, r, g, b)
canvas = matrix.SwapOnVSync(canvas)
time.sleep(1)
try:
print("Press CTRL-C to stop.")
matrix = stockMatrix(symbols)
while True:
run(matrix)
matrix = matrix[:, 1:, :]
if matrix.shape[1] < matrix_shape[1]:
new_matrix = stockMatrix(symbols)
matrix = np.concatenate((matrix, new_matrix), axis=1)
except KeyboardInterrupt:
sys.exit(0)