each user gets own db table for list of stocks to watch.

This commit is contained in:
George 2024-10-05 00:26:01 -07:00
parent 862cccac7b
commit 3ca078f990

View File

@ -21,7 +21,6 @@ Could also come up with a value that ties to the trading volume.
import pandas as pd import pandas as pd
import numpy as np import numpy as np
import datetime as dt import datetime as dt
# from util import get_watchlist
from numpy.fft import fft, ifft from numpy.fft import fft, ifft
import scipy.signal as sig import scipy.signal as sig
import plotly.express as px import plotly.express as px
@ -55,22 +54,32 @@ def connect_db():
sys.exit(1) sys.exit(1)
return conn return conn
def sql_to_dataframe(conn, query): def get_watchlist(username : str):
cursor = conn.cursor() if username:
try: table_name = f"{username + '_watch_list'}"
cursor.execute(query) else: # username is None, use default table
except (Exception, psycopg2.DatabaseError) as error: table_name = "stock_watch_list"
print(f"Error: {error}")
cursor.close()
return 1
tuples_list = cursor.fetchall()
cursor.close()
df = pd.DataFrame(tuples_list)
return df
def get_watchlist(): QUERY1 = f'''CREATE TABLE IF NOT EXISTS {table_name}
QUERY = '''select * from stock_watch_list''' (
return sql_to_dataframe(connect_db(), QUERY) tick character varying(5) NOT NULL,
description text,
PRIMARY KEY (tick)
);'''
QUERY2 = f"INSERT INTO {table_name} SELECT 'SPY', 'SPDR S&P 500 ETF Trust' WHERE NOT EXISTS (SELECT NULL FROM {table_name});"
QUERY3 = f"SELECT * FROM {table_name};"
with connect_db() as conn:
with conn.cursor() as curs:
curs.execute(QUERY1)
curs.execute(QUERY2)
curs.execute(QUERY3)
tuples_list = curs.fetchall()
df = pd.DataFrame(tuples_list)
return df
def hash_password(password): def hash_password(password):
# Encode the password as bytes # Encode the password as bytes
@ -564,14 +573,14 @@ def intelligent_loop_plots(sym, stk_data):
class OIDCAuthCustom(OIDCAuth): # overide OIDCAuth to get logged in user info class OIDCAuthCustom(OIDCAuth): # overide OIDCAuth to get logged in user info
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.userinfo = None self.username = None
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def callback(self, idp: str): def callback(self, idp: str):
return_value = super().callback(idp) return_value = super().callback(idp)
client = self.get_oauth_client(idp) client = self.get_oauth_client(idp)
self.userinfo = client.userinfo() self.username = client.userinfo().get("username")
# ... # ...
return return_value return return_value
@ -598,10 +607,8 @@ auth.register_provider(
server_metadata_url=os.environ['SERVER_URL'], server_metadata_url=os.environ['SERVER_URL'],
) )
watchlist = get_watchlist() # watchlist = get_watchlist(auth.username)
# symbols = watchlist.index.values.tolist() # symbols = (watchlist.iloc[:, 0] + " - " + watchlist.iloc[:, 1]).tolist()
# symbols = (watchlist.index.values + " - " + watchlist["Sub Segment"]).tolist()
symbols = (watchlist.iloc[:, 0] + " - " + watchlist.iloc[:, 1]).tolist()
CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'} CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'}
cache = Cache() cache = Cache()
@ -614,10 +621,11 @@ def fetch_stk_data(sym, sd):
# App layout # App layout
app.layout = [ app.layout = [
html.Div([ html.Div([
html.Button('Reload', id="reload-button", n_clicks=0, html.Button('Load', id="reload-button", n_clicks=0,
style={'font-size': '12px', 'width': '120px', 'display': 'inline-block', 'margin-bottom': '10px', 'margin-right': '5px', 'height':'36px', 'verticalAlign': 'top'}), style={'font-size': '12px', 'width': '120px', 'display': 'inline-block', 'margin-bottom': '10px', 'margin-right': '5px', 'height':'36px', 'verticalAlign': 'top'}),
html.Div([ html.Div([
dcc.Dropdown(symbols, symbols[0], id='symbols_dropdown_list',), # dcc.Dropdown({'SPY - SPDR S&P 500 ETF Trust'}, 'SPY - SPDR S&P 500 ETF Trust', id='symbols_dropdown_list',),
dcc.Dropdown(id='symbols_dropdown_list',),
], style={'width': '330px', 'text-align': 'center'}), ], style={'width': '330px', 'text-align': 'center'}),
html.Button('Auto Play', id="start-button", n_clicks=0, html.Button('Auto Play', id="start-button", n_clicks=0,
style={'font-size': '12px', 'width': '120px', 'display': 'inline-block', 'margin-bottom': '10px', 'margin-right': '5px', 'height':'36px', 'verticalAlign': 'top'}), style={'font-size': '12px', 'width': '120px', 'display': 'inline-block', 'margin-bottom': '10px', 'margin-right': '5px', 'height':'36px', 'verticalAlign': 'top'}),
@ -628,14 +636,12 @@ app.layout = [
id='controls-and-graph', id='controls-and-graph',
style={'height':'85vh'} style={'height':'85vh'}
), ),
# dcc.Store(id="signal"),
# dcc.Store(id="dropdown_index", data='0'),
dcc.Interval( dcc.Interval(
id='interval-component', id='interval-component',
interval=3*1000, # in milliseconds interval=3*1000, # in milliseconds
n_intervals=0, n_intervals=0,
max_intervals=2*len(symbols), max_intervals=1,
# max_intervals=3, # for testing
disabled=True, disabled=True,
), ),
] ]
@ -674,14 +680,14 @@ def start_cycle(n, value):
# reload button callback # reload button callback
@callback(Output('symbols_dropdown_list', 'options'), @callback(Output('symbols_dropdown_list', 'options'),
Output('interval-component', 'n_intervals'), Output('interval-component', 'n_intervals'),
Output('interval-component', 'max_intervals'),
Input("reload-button", "n_clicks"),) Input("reload-button", "n_clicks"),)
def reload_syms(n): def reload_syms(n):
if n: if n:
watchlist = get_watchlist() watchlist = get_watchlist(auth.username)
# symbols = (watchlist.index.values + " - " + watchlist["Sub Segment"]).tolist()
symbols = (watchlist.iloc[:, 0] + " - " + watchlist.iloc[:, 1]).tolist() symbols = (watchlist.iloc[:, 0] + " - " + watchlist.iloc[:, 1]).tolist()
return symbols, 0 return symbols, 0, 2*len(symbols)
return no_update return no_update
# interval callback # interval callback