Main.py
import os
from flask import Flask, render_template, request, redirect
from google.cloud import datastore
from dataplots.graphing import data_plot
from dataplots.table import data_table
"""DASH IMPORTS BEGINING"""
from dash import dash, html
from dataplots.company_data_table import company_data_table
from dataplots.topic_data_table import topic_data_table
"""DASH IMPORTS ENDING"""
app = Flask(__name__)
# Initialize the Datastore client
client = datastore.Client()
@app.route('/')
def mainpage():
return redirect("/view_data")
@app.route('/view_data')
def view_data():
return render_template('view_data.html')
@app.route('/company_info')
def company_info():
return render_template('company_info.html')
@app.route('/topics')
def topics():
return render_template('topics.html')
@app.route('/dataplot_placeholder')
def dataplot_placeholder():
return render_template('dataplot_placeholder.html')
@app.route('/dataplots/data_plot')
def graph():
ticker = request.args.get('ticker')
industry = request.args.get('industry')
startmonth = request.args.get('startmonth')
endmonth = request.args.get('endmonth')
output = data_plot(ticker=ticker, industry=industry, startmonth=startmonth, endmonth=endmonth)
if output == 429:
output = render_template("429.html")
return output
@app.route('/dataplots/data_table')
def table():
ticker = request.args.get('ticker')
industry = request.args.get('industry')
startmonth = request.args.get('startmonth')
endmonth = request.args.get('endmonth')
output = data_table(ticker=ticker, industry=industry, startmonth=startmonth, endmonth=endmonth)
if output == 429:
output = render_template("429.html")
return output
@app.route('/submit_company_info', methods=['POST'])
def submit_company_info():
if request.method == 'POST':
yahoo_ticker = request.form['yahoo_ticker']
industry = request.form['industry']
long_name = request.form['long_name']
# Check if the Yahoo ticker already exists in the database
query = client.query(kind='CompanyInfo')
query.add_filter('YahooTicker', '=', yahoo_ticker)
results = list(query.fetch(limit=1))
# If the ticker exists, update the entity
if results:
company_entity = results[0] # Get the existing entity
company_entity.update({
'YahooTicker': yahoo_ticker,
'Industry': industry,
'LongName': long_name,
})
client.put(company_entity)
return 'Yahoo ticker information updated successfully!'
else:
# If the ticker doesn't exist, create a new entity
key = client.key('CompanyInfo')
company_entity = datastore.Entity(key=key)
company_entity.update({
'YahooTicker': yahoo_ticker,
'Industry': industry,
'LongName': long_name,
})
client.put(company_entity)
return 'Company information submitted successfully!'
# If the request method is not POST, just return the form page
return render_template('index.html')
"""DASH BEGINNING"""
# dashapp_company = dash.Dash(server=app, routes_pathname_prefix="/dataplots/company_data_table/")
# company_data_table(dashapp_company)
dashapp_topic = dash.Dash(server=app, routes_pathname_prefix="/dataplots/topic_data_table/")
topic_data_table(dashapp_topic)
"""DASH ENDING"""
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Requirements.txt
Flask==3.0.0
gunicorn==20.1.0
Werkzeug==3.0.1
google-cloud-datastore==2.19.0
plotly==5.19.0
dash==2.16.1
view_data.html
<!DOCTYPE html>
<html lang="en">
<style>
body {
font-family: "Roboto", sans-serif;
}
#quota-progressbar {
background-color: rgb(224, 224, 224);
border-radius: 7px;
padding: 2px;
width: 300px;
}
#quota-progressbar>div {
background-color: rgb(0, 191, 165);
width: 40%;
height: 10px;
border-radius: 5px;
}
/* Center the loader */
.loader {
position: absolute;
left: 50%;
top: 50%;
border: 16px solid #f3f3f3;
/* Light grey */
border-top: 16px solid #000E2F;
/* Blue */
border-bottom: 16px solid #000E2F;
border-radius: 50%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>UConn Sentiment Data Manager</title>
</head>
<body>
<h1>UConn Sentiment Data Manager</h1>
<a href="company_info"><button>Edit Company Info</button></a>
<a href="topics"><button>Edit Topics</button></a>
<button type="button" disabled>View Data</button>
<hr>
<h2>View Sentiment Data</h2>
<div id="div-dev-quota">
<label>Cloud Firestore Quota: 35000/50000 (50.1%)</label>
<button>Refresh</button>
<div id="quota-progressbar">
<div></div>
</div>
<br>
</div>
<label for="view_ticker">By Ticker:</label>
<input type="text" id="ticker" name="Ticker">
<select name="operator" id="operator">
<option value="OR">OR</option>
<option value="AND">AND</option>
</select>
<label for="view_industry">By Industry:</label>
<input type="text" id="ticker" name="Ticker"><br><br>
<label for="view_data_range">Date Range</label>
<input type="month" id="start-month" name="start-month">
<input type="month" id="end-month" name="end-month"><br><br>
<input id="viewPlot" type="button" value="View Plot" onclick="viewPlot()">
<input id="viewTable" type="button" value="View Table" onclick="viewTable()"><br><br>
<div class="loader" id="loader" style="display: none;"></div>
<iframe id="data_plot" title="Data Plot" style="border:none;" width="100%" height="600" src="/dataplot_placeholder">
</iframe>
<hr>
<script>
function hideSpinner() {
document.getElementById("loader").style.display = "none";
document.getElementById("viewPlot").disabled = false
document.getElementById("viewTable").disabled = false
}
function showSpinner() {
document.getElementById("loader").style.display = "block";
document.getElementById("viewPlot").disabled = true
document.getElementById("viewTable").disabled = true
}
function viewPlot() {
let tickerText = document.getElementById("ticker").value;
if (tickerText == "") {
alert("Input Needed")
return
}
tickerText.replace(/%20/g, " ")
document.getElementById("data_plot").setAttribute("src", "/dataplots/data_plot?ticker=" + tickerText)
showSpinner()
setTimeout(hideSpinner, 7500)
}
function viewTable() {
let tickerText = document.getElementById("ticker").value;
if (tickerText == "") {
alert("Input Needed")
return
}
tickerText.replace(/%20/g, " ")
document.getElementById("data_plot").setAttribute("src", "/dataplots/data_table?ticker=" + tickerText)
showSpinner()
setTimeout(hideSpinner, 7500)
}
</script>
</body>
</html>
graphing.py
from google.cloud import datastore
import plotly.graph_objs as go
from plotly.offline import plot
def data_plot(kind='Sentiment_Details', ticker='WM US', industry=None, startmonth=None, endmonth=None):
# Initialize the Datastore client
client = datastore.Client()
if "," in ticker:
ticker = ticker.split(",")
tickers = []
for v in ticker:
tickers.append(v.strip())
# Create a query to fetch entities from the Datastore
query = client.query(kind=kind)
query.order = ['CallDate']
# Fetch the data
try:
entities = list(query.fetch())
except:
return 429
# Prepare the data for plotting
keyword_period_scores = {}
# Filter entities after fetching
filtered_entities = [e for e in entities if e['YahooTicker'] in tickers]
for entity in filtered_entities:
period = entity['Period']
keyword = entity['YahooTicker'] + ": " + entity['Keyword']
score = entity['Score']
if keyword not in keyword_period_scores:
keyword_period_scores[keyword] = {}
if period in keyword_period_scores[keyword]:
keyword_period_scores[keyword][period].append(score)
else:
keyword_period_scores[keyword][period] = [score]
# Prepare the Plotly graph
fig = go.Figure()
for keyword, period_scores in keyword_period_scores.items():
unique_periods = sorted(period_scores.keys())
average_scores = [sum(scores) / len(scores)
for scores in period_scores.values()]
# Create a trace for each keyword
fig.add_trace(go.Scatter(
x=unique_periods,
y=average_scores,
mode='lines+markers',
name=keyword
))
fig.update_layout(
title=f'Average Sentiment Scores Over Time by Keyword for YahooTicker {tickers}',
xaxis_title='Period',
yaxis_title='Average Sentiment Score',
legend_title='Keywords',
xaxis=dict(tickangle=45),
yaxis_range=[-1, 1]
)
# Return HTML div
return plot(fig, include_plotlyjs=True, output_type='div')
No comments:
Post a Comment