Cleanup (no new features)
This commit is contained in:
parent
b070bcdd9f
commit
f25156896d
246
indicators.py
246
indicators.py
@ -21,20 +21,13 @@ 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_data, get_price_volume, plot_data, get_watchlist
|
from util import get_watchlist
|
||||||
from util import get_price_volume, plot_data, get_watchlist
|
|
||||||
# from marketsim import compute_portvals, compute_portfolio_stats, normalize_data
|
|
||||||
# import matplotlib.pyplot as plt
|
|
||||||
# import matplotlib
|
|
||||||
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
|
||||||
from plotly.subplots import make_subplots
|
from plotly.subplots import make_subplots
|
||||||
# import plotly.graph_objects as go
|
|
||||||
from dash import Dash, html, dcc, callback, Output, Input, State, no_update
|
from dash import Dash, html, dcc, callback, Output, Input, State, no_update
|
||||||
from waitress import serve
|
from waitress import serve
|
||||||
import json
|
|
||||||
import io
|
|
||||||
from flask_caching import Cache
|
from flask_caching import Cache
|
||||||
from dash.exceptions import PreventUpdate
|
from dash.exceptions import PreventUpdate
|
||||||
import dash_auth
|
import dash_auth
|
||||||
@ -106,7 +99,6 @@ def smooth(price, hsize=10, sigma=3):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class security:
|
class security:
|
||||||
"""
|
"""
|
||||||
This can be a list of stocks, bonds, or otherinvestment vehicles.
|
This can be a list of stocks, bonds, or otherinvestment vehicles.
|
||||||
@ -350,100 +342,6 @@ class security:
|
|||||||
norm_hist = macd_hist.div(macd_long.values)
|
norm_hist = macd_hist.div(macd_long.values)
|
||||||
return macd_line, macd_sig, macd_hist, norm_hist
|
return macd_line, macd_sig, macd_hist, norm_hist
|
||||||
|
|
||||||
|
|
||||||
# def bollinger_sell(stock, wd=200):
|
|
||||||
# """
|
|
||||||
# Parameters
|
|
||||||
# ----------
|
|
||||||
# stock : TYPE class 'serurity'
|
|
||||||
# wd : TYPE, int, optional
|
|
||||||
# DESCRIPTION. Moving average windows. The default is 200.
|
|
||||||
|
|
||||||
# Returns
|
|
||||||
# -------
|
|
||||||
# TYPE DataFrame
|
|
||||||
# DESCRIPTION - +1 when stock price is above bollinger upper band
|
|
||||||
# . -1 when vice versa. transition days are of value +3 and -3
|
|
||||||
# respectively. A value of -3 is a sell signal
|
|
||||||
# """
|
|
||||||
# _, bol_up = stock.bollinger(wd)
|
|
||||||
# # bol_up = bol_up[bol_up.columns[-1]].to_frame()
|
|
||||||
# # bol_up = bol_up.iloc[:, [-1]]
|
|
||||||
# sell = np.sign(stock.price.sub(bol_up.values))
|
|
||||||
# sell_diff = sell.diff()
|
|
||||||
|
|
||||||
# return sell.add(sell_diff.values)
|
|
||||||
|
|
||||||
|
|
||||||
# def bollinger_buy(stock, wd=200):
|
|
||||||
# """
|
|
||||||
# Parameters
|
|
||||||
# ----------
|
|
||||||
# stock : TYPE class 'serurity'
|
|
||||||
# wd : TYPE, int, optional
|
|
||||||
# DESCRIPTION. Moving average windows. The default is 200.
|
|
||||||
|
|
||||||
# Returns
|
|
||||||
# -------
|
|
||||||
# TYPE DataFrame
|
|
||||||
# DESCRIPTION - +1 when stock price is above bollinger lower band
|
|
||||||
# . -1 when vice versa. transition days are of value +3 and -3
|
|
||||||
# respectively. A value of +3 is a buy signal
|
|
||||||
# """
|
|
||||||
# bol_low, _ = stock.bollinger(wd)
|
|
||||||
# buy = np.sign(stock.price.sub(bol_low.values))
|
|
||||||
# buy_diff = buy.diff()
|
|
||||||
|
|
||||||
# return buy.add(buy_diff.values)
|
|
||||||
|
|
||||||
# def simple_bollinger_strategy(stk):
|
|
||||||
|
|
||||||
# # buy orders
|
|
||||||
# buy = bollinger_buy(stk, 190)
|
|
||||||
# buy_orders = buy[np.any(buy>2, axis=1)]
|
|
||||||
|
|
||||||
# sell = bollinger_sell(stk, 190)
|
|
||||||
# sell_orders = sell[np.any(sell<-2, axis=1)]
|
|
||||||
|
|
||||||
# orders = pd.concat([buy_orders, sell_orders])
|
|
||||||
# orders = orders.sort_index()
|
|
||||||
|
|
||||||
# order_list = pd.DataFrame(columns = ['Date', 'Symbol', 'Order', 'Shares'])
|
|
||||||
# for index, row in orders.iterrows():
|
|
||||||
# for sym in orders.columns.values:
|
|
||||||
# if row[sym] > 2: # buy order
|
|
||||||
# order_list = order_list.append({'Date' : index, 'Symbol' : sym,
|
|
||||||
# 'Order' : 'BUY', 'Shares' : 100}, ignore_index = True )
|
|
||||||
# elif row[sym] < -2: # sell order
|
|
||||||
# order_list = order_list.append({'Date' : index, 'Symbol' : sym,
|
|
||||||
# 'Order' : 'SELL', 'Shares' : 100}, ignore_index = True )
|
|
||||||
# order_list = order_list.set_index('Date')
|
|
||||||
|
|
||||||
# return order_list
|
|
||||||
|
|
||||||
# def plot_against_sym(df, sym=['SPY']):
|
|
||||||
# df_temp = df.copy()
|
|
||||||
# df_sym = get_data(sym, pd.to_datetime(df_temp.index.values), addSPY=False)
|
|
||||||
# df_temp[sym[0]] = df_sym.values
|
|
||||||
# df_temp = normalize_data(df_temp)
|
|
||||||
# plot_data(df_temp)
|
|
||||||
# return df_sym
|
|
||||||
|
|
||||||
|
|
||||||
# def test_bollinger_sell():
|
|
||||||
# sd = dt.datetime(2010,1,1)
|
|
||||||
# # ed = dt.datetime.today()
|
|
||||||
# ed = dt.datetime(2012,12,31)
|
|
||||||
# symbol = ['XOM']
|
|
||||||
# dates = dates = pd.date_range(sd, ed)
|
|
||||||
# prices = get_data(symbol, dates, addSPY=False)
|
|
||||||
# # prices = prices.dropna()
|
|
||||||
# stk = security(prices)
|
|
||||||
# sell = bollinger_sell(stk)
|
|
||||||
# plot_data(sell)
|
|
||||||
# buy = bollinger_buy(stk, 190)
|
|
||||||
# plot_data(buy)
|
|
||||||
|
|
||||||
def get_crossing(stocks):
|
def get_crossing(stocks):
|
||||||
"""
|
"""
|
||||||
Parameters
|
Parameters
|
||||||
@ -488,49 +386,9 @@ def get_sma_slope(stocks, wd = 50):
|
|||||||
|
|
||||||
return slope
|
return slope
|
||||||
|
|
||||||
|
LB_YEAR = 3 # years of stock data to retrieve
|
||||||
# def modified_bollinger_strategy(stk):
|
# PLT_YEAR = 2 # number of years data to plot
|
||||||
|
LB_TRIGGER = 5 # days to lookback for triggering events
|
||||||
# rsi = stk.rsi()
|
|
||||||
# btemp = pd.DataFrame()
|
|
||||||
# # buy orders
|
|
||||||
# buy = bollinger_buy(stk, 190)
|
|
||||||
# buy_orders = buy[np.any(buy>2, axis=1)]
|
|
||||||
# for col in buy_orders.columns:
|
|
||||||
# buy_stk = buy_orders[col]
|
|
||||||
# buy_stk = buy_stk[buy_stk > 2]
|
|
||||||
# buy_stk = buy_stk[rsi[col].loc[buy_stk.index] < 70]
|
|
||||||
# btemp = btemp.join(buy_stk, how='outer')
|
|
||||||
|
|
||||||
# stemp = pd.DataFrame()
|
|
||||||
# sell = bollinger_sell(stk, 190)
|
|
||||||
# sell_orders = sell[np.any(sell<-2, axis=1)]
|
|
||||||
# for col in sell_orders.columns:
|
|
||||||
# sell_stk = sell_orders[col]
|
|
||||||
# sell_stk = sell_stk[sell_stk < -2]
|
|
||||||
# sell_stk = sell_stk[rsi[col].loc[sell_stk.index] > 30]
|
|
||||||
# stemp = stemp.join(sell_stk, how='outer')
|
|
||||||
|
|
||||||
# orders = pd.concat([btemp, stemp])
|
|
||||||
|
|
||||||
# # TODO - refine orders based on slope
|
|
||||||
# # TODO - revine further based on other conditions (RSI, MACD)
|
|
||||||
# # TODO - transaction shares determination
|
|
||||||
|
|
||||||
# orders = orders.sort_index()
|
|
||||||
|
|
||||||
# order_list = pd.DataFrame(columns = ['Date', 'Symbol', 'Order', 'Shares'])
|
|
||||||
# for index, row in orders.iterrows():
|
|
||||||
# for sym in orders.columns.values:
|
|
||||||
# if row[sym] > 2: # buy order
|
|
||||||
# order_list = order_list.append({'Date' : index, 'Symbol' : sym,
|
|
||||||
# 'Order' : 'BUY', 'Shares' : 100}, ignore_index = True )
|
|
||||||
# elif row[sym] < -2: # sell order
|
|
||||||
# order_list = order_list.append({'Date' : index, 'Symbol' : sym,
|
|
||||||
# 'Order' : 'SELL', 'Shares' : 100}, ignore_index = True )
|
|
||||||
# order_list = order_list.set_index('Date')
|
|
||||||
|
|
||||||
# return order_list
|
|
||||||
|
|
||||||
def intelligent_loop_plots(sym, stk_data):
|
def intelligent_loop_plots(sym, stk_data):
|
||||||
# Only plot ones that are standing out meaning:
|
# Only plot ones that are standing out meaning:
|
||||||
@ -563,25 +421,25 @@ def intelligent_loop_plots(sym, stk_data):
|
|||||||
# print('{:5}: '.format(sym), end = '')
|
# print('{:5}: '.format(sym), end = '')
|
||||||
|
|
||||||
# RSI outside window (over bought / over sold)
|
# RSI outside window (over bought / over sold)
|
||||||
rsi_tail = rsi.tail(lb_trigger)
|
rsi_tail = rsi.tail(LB_TRIGGER)
|
||||||
if (rsi_tail >= 70).any() or (rsi_tail <= 30).any():
|
if (rsi_tail >= 70).any() or (rsi_tail <= 30).any():
|
||||||
# print('--RSI', end = '')
|
# print('--RSI', end = '')
|
||||||
plot_indicator += 'RSI, '
|
plot_indicator += 'RSI, '
|
||||||
|
|
||||||
# VoRSI outside window (over bought / over sold)
|
# VoRSI outside window (over bought / over sold)
|
||||||
vorsi_tail = vorsi.tail(lb_trigger)
|
vorsi_tail = vorsi.tail(LB_TRIGGER)
|
||||||
if (vorsi_tail >= 70).any() or (vorsi_tail <= 30).any():
|
if (vorsi_tail >= 70).any() or (vorsi_tail <= 30).any():
|
||||||
# print('--VoRSI', end = '')
|
# print('--VoRSI', end = '')
|
||||||
plot_indicator += 'VoRSI, '
|
plot_indicator += 'VoRSI, '
|
||||||
|
|
||||||
# Normalized MACD histogram out of 3% range
|
# Normalized MACD histogram out of 3% range
|
||||||
norm_hist_tail = abs(norm_hist.tail(lb_trigger))
|
norm_hist_tail = abs(norm_hist.tail(LB_TRIGGER))
|
||||||
if (abs(norm_hist_tail) >= 0.02).any():
|
if (abs(norm_hist_tail) >= 0.02).any():
|
||||||
# print('--MACD/R', end = '') # outside normal range
|
# print('--MACD/R', end = '') # outside normal range
|
||||||
plot_indicator += 'MACD/R, '
|
plot_indicator += 'MACD/R, '
|
||||||
|
|
||||||
# MACD histogram zero crossing
|
# MACD histogram zero crossing
|
||||||
macd_hist_tail = macd_hist.tail(lb_trigger)
|
macd_hist_tail = macd_hist.tail(LB_TRIGGER)
|
||||||
macd_hist_sign = np.sign(macd_hist_tail)
|
macd_hist_sign = np.sign(macd_hist_tail)
|
||||||
macd_hist_diff = macd_hist_sign.diff()
|
macd_hist_diff = macd_hist_sign.diff()
|
||||||
if (abs(macd_hist_diff) > 1).any():
|
if (abs(macd_hist_diff) > 1).any():
|
||||||
@ -589,7 +447,7 @@ def intelligent_loop_plots(sym, stk_data):
|
|||||||
plot_indicator += 'MACD, '
|
plot_indicator += 'MACD, '
|
||||||
|
|
||||||
# Stock price crosses SMA50
|
# Stock price crosses SMA50
|
||||||
sma50_cross_tail = sma50.tail(lb_trigger) - price.tail(lb_trigger)
|
sma50_cross_tail = sma50.tail(LB_TRIGGER) - price.tail(LB_TRIGGER)
|
||||||
sma50_cross_sign = np.sign(sma50_cross_tail)
|
sma50_cross_sign = np.sign(sma50_cross_tail)
|
||||||
sma50_cross_diff = sma50_cross_sign.diff()
|
sma50_cross_diff = sma50_cross_sign.diff()
|
||||||
if (abs(sma50_cross_diff) > 1).any():
|
if (abs(sma50_cross_diff) > 1).any():
|
||||||
@ -597,7 +455,7 @@ def intelligent_loop_plots(sym, stk_data):
|
|||||||
plot_indicator += 'SMA50, '
|
plot_indicator += 'SMA50, '
|
||||||
|
|
||||||
# Death cross or golden cross - SMA50 vs SMA200
|
# Death cross or golden cross - SMA50 vs SMA200
|
||||||
sma_cross_tail = sma50.tail(lb_trigger) - sma200.tail(lb_trigger).values
|
sma_cross_tail = sma50.tail(LB_TRIGGER) - sma200.tail(LB_TRIGGER).values
|
||||||
sma_cross_sign = np.sign(sma_cross_tail)
|
sma_cross_sign = np.sign(sma_cross_tail)
|
||||||
sma_cross_diff = sma_cross_sign.diff()
|
sma_cross_diff = sma_cross_sign.diff()
|
||||||
if (abs(sma_cross_diff) > 1).any():
|
if (abs(sma_cross_diff) > 1).any():
|
||||||
@ -605,9 +463,9 @@ def intelligent_loop_plots(sym, stk_data):
|
|||||||
plot_indicator += 'Golden/Death, '
|
plot_indicator += 'Golden/Death, '
|
||||||
|
|
||||||
# Price outside bollinger band or crossing
|
# Price outside bollinger band or crossing
|
||||||
price_tail = price.tail(lb_trigger)
|
price_tail = price.tail(LB_TRIGGER)
|
||||||
bol_low_tail = bol_low.tail(lb_trigger)
|
bol_low_tail = bol_low.tail(LB_TRIGGER)
|
||||||
bol_up_tail = bol_up.tail(lb_trigger)
|
bol_up_tail = bol_up.tail(LB_TRIGGER)
|
||||||
price_high = price_tail - bol_up_tail.values
|
price_high = price_tail - bol_up_tail.values
|
||||||
price_low = price_tail - bol_low_tail.values
|
price_low = price_tail - bol_low_tail.values
|
||||||
if (price_high >= 0).any() or (price_low <= 0).any():
|
if (price_high >= 0).any() or (price_low <= 0).any():
|
||||||
@ -615,7 +473,7 @@ def intelligent_loop_plots(sym, stk_data):
|
|||||||
plot_indicator += 'Bollinger, '
|
plot_indicator += 'Bollinger, '
|
||||||
|
|
||||||
# Price cross 200 day moving average
|
# Price cross 200 day moving average
|
||||||
sma200_tail = sma200.tail(lb_trigger)
|
sma200_tail = sma200.tail(LB_TRIGGER)
|
||||||
sma200_cross = price_tail - sma200_tail.values
|
sma200_cross = price_tail - sma200_tail.values
|
||||||
sma200_cross_sign = np.sign(sma200_cross)
|
sma200_cross_sign = np.sign(sma200_cross)
|
||||||
sma200_cross_diff = sma200_cross_sign.diff()
|
sma200_cross_diff = sma200_cross_sign.diff()
|
||||||
@ -624,7 +482,7 @@ def intelligent_loop_plots(sym, stk_data):
|
|||||||
plot_indicator += 'SMA200, '
|
plot_indicator += 'SMA200, '
|
||||||
|
|
||||||
# Large trading volume trigger
|
# Large trading volume trigger
|
||||||
volume_tail = vol.tail(lb_trigger)
|
volume_tail = vol.tail(LB_TRIGGER)
|
||||||
vol_mean = vol.tail(50).mean()
|
vol_mean = vol.tail(50).mean()
|
||||||
vol_std = vol.tail(50).std()
|
vol_std = vol.tail(50).std()
|
||||||
if ((volume_tail[1] - vol_mean - 2*vol_std) > 0).any():
|
if ((volume_tail[1] - vol_mean - 2*vol_std) > 0).any():
|
||||||
@ -667,35 +525,29 @@ def user_login(username, password):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if __name__ == "__main__":
|
# Initialize the app
|
||||||
|
app = Dash()
|
||||||
lb_year = 3 # years of stock data to retrieve
|
dash_auth.BasicAuth(
|
||||||
plt_year = 2 # number of years data to plot
|
|
||||||
lb_trigger = 5 # days to lookback for triggering events
|
|
||||||
|
|
||||||
# Initialize the app
|
|
||||||
app = Dash()
|
|
||||||
dash_auth.BasicAuth(
|
|
||||||
app,
|
app,
|
||||||
# VALID_USERNAME_PASSWORD_PAIRS,
|
# VALID_USERNAME_PASSWORD_PAIRS,
|
||||||
auth_func=user_login,
|
auth_func=user_login,
|
||||||
secret_key="MK8dyS6PyDDuEuzrmqa7dJTJZ7eH2Jkh",
|
secret_key="MK8dyS6PyDDuEuzrmqa7dJTJZ7eH2Jkh",
|
||||||
)
|
)
|
||||||
|
|
||||||
watchlist = get_watchlist()
|
watchlist = get_watchlist()
|
||||||
# symbols = watchlist.index.values.tolist()
|
# symbols = watchlist.index.values.tolist()
|
||||||
symbols = (watchlist.index.values + " - " + watchlist["Sub Segment"]).tolist()
|
symbols = (watchlist.index.values + " - " + watchlist["Sub Segment"]).tolist()
|
||||||
|
|
||||||
CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'}
|
CACHE_CONFIG = {'CACHE_TYPE': 'SimpleCache'}
|
||||||
cache = Cache()
|
cache = Cache()
|
||||||
cache.init_app(app.server, config=CACHE_CONFIG)
|
cache.init_app(app.server, config=CACHE_CONFIG)
|
||||||
|
|
||||||
@cache.memoize(timeout=14400) # cache timeout set to 4 hours
|
@cache.memoize(timeout=14400) # cache timeout set to 4 hours
|
||||||
def fetch_stk_data(sym, sd):
|
def fetch_stk_data(sym, sd):
|
||||||
return si.get_data(sym, start_date=sd)[["adjclose", "volume"]]
|
return si.get_data(sym, start_date=sd)[["adjclose", "volume"]]
|
||||||
|
|
||||||
# App layout
|
# App layout
|
||||||
app.layout = [
|
app.layout = [
|
||||||
html.Div([
|
html.Div([
|
||||||
html.Button('Reload', id="reload-button", n_clicks=0,
|
html.Button('Reload', 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'}),
|
||||||
@ -721,9 +573,9 @@ if __name__ == "__main__":
|
|||||||
# max_intervals=3, # for testing
|
# max_intervals=3, # for testing
|
||||||
disabled=True,
|
disabled=True,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
app.clientside_callback(
|
app.clientside_callback(
|
||||||
"""
|
"""
|
||||||
function(id) {
|
function(id) {
|
||||||
document.addEventListener("keyup", function(event) {
|
document.addEventListener("keyup", function(event) {
|
||||||
@ -737,16 +589,16 @@ if __name__ == "__main__":
|
|||||||
""",
|
""",
|
||||||
Output("start-button", "id"),
|
Output("start-button", "id"),
|
||||||
Input("start-button", "id")
|
Input("start-button", "id")
|
||||||
)
|
)
|
||||||
|
|
||||||
# start / stop button callback
|
# start / stop button callback
|
||||||
@callback(Output('interval-component', 'disabled'),
|
@callback(Output('interval-component', 'disabled'),
|
||||||
Output("start-button", "children"),
|
Output("start-button", "children"),
|
||||||
Output('symbols_dropdown_list', 'disabled'),
|
Output('symbols_dropdown_list', 'disabled'),
|
||||||
Input("start-button", "n_clicks"),
|
Input("start-button", "n_clicks"),
|
||||||
State("start-button", "children"),)
|
State("start-button", "children"),)
|
||||||
|
|
||||||
def start_cycle(n, value):
|
def start_cycle(n, value):
|
||||||
if n:
|
if n:
|
||||||
if value == "Pause":
|
if value == "Pause":
|
||||||
return True, "Auto Play", False
|
return True, "Auto Play", False
|
||||||
@ -754,49 +606,47 @@ if __name__ == "__main__":
|
|||||||
return False, "Pause", True
|
return False, "Pause", True
|
||||||
return no_update
|
return no_update
|
||||||
|
|
||||||
# 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'),
|
||||||
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()
|
||||||
symbols = (watchlist.index.values + " - " + watchlist["Sub Segment"]).tolist()
|
symbols = (watchlist.index.values + " - " + watchlist["Sub Segment"]).tolist()
|
||||||
return symbols, 0
|
return symbols, 0
|
||||||
return no_update
|
return no_update
|
||||||
|
|
||||||
# interval callback
|
# interval callback
|
||||||
@callback(Output('symbols_dropdown_list', 'value'),
|
@callback(Output('symbols_dropdown_list', 'value'),
|
||||||
Input("interval-component", "n_intervals"),
|
Input("interval-component", "n_intervals"),
|
||||||
State('symbols_dropdown_list', 'options'),
|
State('symbols_dropdown_list', 'options'),
|
||||||
# State('dropdown-index', 'data'),
|
# State('dropdown-index', 'data'),
|
||||||
)
|
)
|
||||||
def cycle_syms(n, syms):
|
def cycle_syms(n, syms):
|
||||||
if syms:
|
if syms:
|
||||||
return syms[n % len(syms)]
|
return syms[n % len(syms)]
|
||||||
else:
|
else:
|
||||||
return no_update
|
return no_update
|
||||||
|
|
||||||
# dropdown callback
|
# dropdown callback
|
||||||
@callback(
|
@callback(
|
||||||
Output(component_id='controls-and-graph', component_property='figure'),
|
Output(component_id='controls-and-graph', component_property='figure'),
|
||||||
# Output("dropdown-index", "data"),
|
# Output("dropdown-index", "data"),
|
||||||
Input(component_id='symbols_dropdown_list', component_property='value'),
|
Input(component_id='symbols_dropdown_list', component_property='value'),
|
||||||
# State('symbols_dropdown_list', 'options')
|
# State('symbols_dropdown_list', 'options')
|
||||||
# Input(component_id='signal', component_property='data'),
|
# Input(component_id='signal', component_property='data'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_graph(col_chosen):
|
def update_graph(col_chosen):
|
||||||
if not col_chosen:
|
if not col_chosen:
|
||||||
raise PreventUpdate
|
raise PreventUpdate
|
||||||
# return no_update
|
# return no_update
|
||||||
|
|
||||||
# get data
|
|
||||||
# tmp = si.get_data(sym, start_date=sd)[["adjclose", "volume"]]
|
|
||||||
sym = col_chosen.split()[0]
|
sym = col_chosen.split()[0]
|
||||||
end_date = dt.datetime.today()
|
end_date = dt.datetime.today()
|
||||||
start_date = end_date - dt.timedelta(days = 365 * lb_year)
|
start_date = end_date - dt.timedelta(days = 365 * LB_YEAR)
|
||||||
# plot_sd = end_date - dt.timedelta(days = 365 * plt_year)
|
# plot_sd = end_date - dt.timedelta(days = 365 * plt_year)
|
||||||
# plot_ed = end_date
|
# plot_ed = end_date
|
||||||
tmp = fetch_stk_data(sym, start_date) # cached function all
|
tmp = fetch_stk_data(sym, start_date) # cached function all
|
||||||
@ -815,7 +665,6 @@ if __name__ == "__main__":
|
|||||||
data,
|
data,
|
||||||
x=data.index,
|
x=data.index,
|
||||||
y=data.columns.to_list(),
|
y=data.columns.to_list(),
|
||||||
# y=[sym, sym+'_BOL200L', sym+'_BOL200U', sym+'_SMA200', sym+'_SMA50', sym+'_WVMA50'],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
volume_line = px.bar(
|
volume_line = px.bar(
|
||||||
@ -876,5 +725,6 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
return fig
|
return fig
|
||||||
|
|
||||||
serve(app.server, host="0.0.0.0", port=8050, threads=7)
|
if __name__ == "__main__":
|
||||||
|
serve(app.server, host="0.0.0.0", port=8050, threads=7) # using production quality WSGI server Waitress
|
||||||
# app.run(debug=True)
|
# app.run(debug=True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user