Cleanup (no new features)
This commit is contained in:
parent
b070bcdd9f
commit
f25156896d
186
indicators.py
186
indicators.py
@ -21,20 +21,13 @@ Could also come up with a value that ties to the trading volume.
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import datetime as dt
|
||||
# from util import get_data, get_price_volume, plot_data, 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 util import get_watchlist
|
||||
from numpy.fft import fft, ifft
|
||||
import scipy.signal as sig
|
||||
import plotly.express as px
|
||||
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 waitress import serve
|
||||
import json
|
||||
import io
|
||||
from flask_caching import Cache
|
||||
from dash.exceptions import PreventUpdate
|
||||
import dash_auth
|
||||
@ -106,7 +99,6 @@ def smooth(price, hsize=10, sigma=3):
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class security:
|
||||
"""
|
||||
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)
|
||||
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):
|
||||
"""
|
||||
Parameters
|
||||
@ -488,49 +386,9 @@ def get_sma_slope(stocks, wd = 50):
|
||||
|
||||
return slope
|
||||
|
||||
|
||||
# def modified_bollinger_strategy(stk):
|
||||
|
||||
# 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
|
||||
LB_YEAR = 3 # years of stock data to retrieve
|
||||
# PLT_YEAR = 2 # number of years data to plot
|
||||
LB_TRIGGER = 5 # days to lookback for triggering events
|
||||
|
||||
def intelligent_loop_plots(sym, stk_data):
|
||||
# Only plot ones that are standing out meaning:
|
||||
@ -563,25 +421,25 @@ def intelligent_loop_plots(sym, stk_data):
|
||||
# print('{:5}: '.format(sym), end = '')
|
||||
|
||||
# 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():
|
||||
# print('--RSI', end = '')
|
||||
plot_indicator += 'RSI, '
|
||||
|
||||
# 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():
|
||||
# print('--VoRSI', end = '')
|
||||
plot_indicator += 'VoRSI, '
|
||||
|
||||
# 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():
|
||||
# print('--MACD/R', end = '') # outside normal range
|
||||
plot_indicator += 'MACD/R, '
|
||||
|
||||
# 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_diff = macd_hist_sign.diff()
|
||||
if (abs(macd_hist_diff) > 1).any():
|
||||
@ -589,7 +447,7 @@ def intelligent_loop_plots(sym, stk_data):
|
||||
plot_indicator += 'MACD, '
|
||||
|
||||
# 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_diff = sma50_cross_sign.diff()
|
||||
if (abs(sma50_cross_diff) > 1).any():
|
||||
@ -597,7 +455,7 @@ def intelligent_loop_plots(sym, stk_data):
|
||||
plot_indicator += 'SMA50, '
|
||||
|
||||
# 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_diff = sma_cross_sign.diff()
|
||||
if (abs(sma_cross_diff) > 1).any():
|
||||
@ -605,9 +463,9 @@ def intelligent_loop_plots(sym, stk_data):
|
||||
plot_indicator += 'Golden/Death, '
|
||||
|
||||
# Price outside bollinger band or crossing
|
||||
price_tail = price.tail(lb_trigger)
|
||||
bol_low_tail = bol_low.tail(lb_trigger)
|
||||
bol_up_tail = bol_up.tail(lb_trigger)
|
||||
price_tail = price.tail(LB_TRIGGER)
|
||||
bol_low_tail = bol_low.tail(LB_TRIGGER)
|
||||
bol_up_tail = bol_up.tail(LB_TRIGGER)
|
||||
price_high = price_tail - bol_up_tail.values
|
||||
price_low = price_tail - bol_low_tail.values
|
||||
if (price_high >= 0).any() or (price_low <= 0).any():
|
||||
@ -615,7 +473,7 @@ def intelligent_loop_plots(sym, stk_data):
|
||||
plot_indicator += 'Bollinger, '
|
||||
|
||||
# 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_sign = np.sign(sma200_cross)
|
||||
sma200_cross_diff = sma200_cross_sign.diff()
|
||||
@ -624,7 +482,7 @@ def intelligent_loop_plots(sym, stk_data):
|
||||
plot_indicator += 'SMA200, '
|
||||
|
||||
# Large trading volume trigger
|
||||
volume_tail = vol.tail(lb_trigger)
|
||||
volume_tail = vol.tail(LB_TRIGGER)
|
||||
vol_mean = vol.tail(50).mean()
|
||||
vol_std = vol.tail(50).std()
|
||||
if ((volume_tail[1] - vol_mean - 2*vol_std) > 0).any():
|
||||
@ -667,12 +525,6 @@ def user_login(username, password):
|
||||
return True
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
lb_year = 3 # years of stock data to retrieve
|
||||
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(
|
||||
@ -792,11 +644,9 @@ if __name__ == "__main__":
|
||||
raise PreventUpdate
|
||||
# return no_update
|
||||
|
||||
# get data
|
||||
# tmp = si.get_data(sym, start_date=sd)[["adjclose", "volume"]]
|
||||
sym = col_chosen.split()[0]
|
||||
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_ed = end_date
|
||||
tmp = fetch_stk_data(sym, start_date) # cached function all
|
||||
@ -815,7 +665,6 @@ if __name__ == "__main__":
|
||||
data,
|
||||
x=data.index,
|
||||
y=data.columns.to_list(),
|
||||
# y=[sym, sym+'_BOL200L', sym+'_BOL200U', sym+'_SMA200', sym+'_SMA50', sym+'_WVMA50'],
|
||||
)
|
||||
|
||||
volume_line = px.bar(
|
||||
@ -876,5 +725,6 @@ if __name__ == "__main__":
|
||||
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user