Spaces:
Build error
Build error
import requests | |
import json | |
from requests.api import delete, options | |
import streamlit as st | |
import time | |
import tweepy | |
import requests | |
from io import BytesIO | |
import base64 | |
import matplotlib.pyplot as plt | |
import numpy as np | |
from plotly.subplots import make_subplots | |
from config import * | |
from dateutil.relativedelta import relativedelta | |
from patterns import patterns | |
# import talibsddsfs | |
from datetime import datetime, timedelta, tzinfo | |
from alpaca_trade_api.rest import REST | |
from streamlit_tags import st_tags_sidebar | |
# from streamlit_autorefresh import st_autorefresh | |
# import plotly.express as px | |
from coinbaskets import * | |
import plotly.graph_objects as go | |
from mapping import * | |
import pandas as pd | |
import threading | |
from bs4 import BeautifulSoup | |
from ETFs import * | |
from dateutil import tz | |
import os | |
# try: | |
# from streamlit.ReportThread import add_report_ctx | |
# except Exception: | |
# # Streamlit >= 0.65.0 | |
# from streamlit.report_thread import add_report_ctx | |
# # from streamlit.scriptrunner import add_script_run_ctx | |
from streamlit.scriptrunner import add_script_run_ctx as add_report_ctx | |
def get_stocktwits_data(req,code,label): | |
r = requests.get(req) | |
trending_syms = pd.DataFrame(r.json()["stocks"]).T | |
trending_syms.index.name = "stock_id" | |
trending_syms.index = trending_syms.index.astype("int") | |
trending_score = pd.DataFrame(r.json()["table"][code]) | |
trending_score.set_index("stock_id",inplace = True) | |
most_trending_syms = pd.merge(trending_syms,trending_score,on= "stock_id") | |
most_trending_syms.sort_values("val",ascending = False, inplace = True) | |
most_trending_syms.set_index("symbol",inplace = True) | |
most_trending_syms.columns = ["Name","Price","%Change",label] | |
return most_trending_syms | |
def get_cnbc_data(symbol): | |
ticker = symbol.replace(" ","") | |
if ticker == "NASDAQ": | |
ticker = "NDX" | |
elif ticker == "NIFTY50": | |
ticker = ".NSEI" | |
# Get the symbol quote from yahoo finance, we are using Beautiful Soup for scraping | |
# df = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/1Y.json?symbol={ticker}").json()["barData"]["priceBars"]) | |
df_1D = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/1D.json?symbol={ticker}").json()["barData"]["priceBars"]) | |
# df["datetime"] = pd.to_datetime(df['tradeTimeinMills'],unit='ms') | |
# df["close"] = df["close"].astype(float) | |
df_1D["close"] = df_1D["close"].astype(float) | |
# df.set_index("datetime",inplace = True) | |
# dma200 = df["close"].rolling(200).mean() | |
close = (df_1D["close"].iloc[-1]) | |
return close | |
def vix_gradient(vix): | |
""" | |
Mapping is done as follows rsi<=20 --> -100, rsi>=80, 100, and then linear variation | |
""" | |
if vix<20: | |
return 100 | |
elif vix<30: | |
return (-20*vix+500) | |
else: | |
return -100 | |
def roro_comp_get(series,i,state, inverse = False): | |
current = series.iloc[-i] | |
current_idx = series.index[-i] | |
w_1_ago = current_idx - relativedelta(days=7) | |
w_2_ago = current_idx - relativedelta(days=14) | |
m_1_ago = current_idx - relativedelta(months=1) | |
if state == 0: | |
w_1_ret = (current - series.loc[w_1_ago:].iloc[0])*100/series.loc[w_1_ago:].iloc[0] | |
w_2_ret = (current - series.loc[w_2_ago:].iloc[0])*100/series.loc[w_2_ago:].iloc[0] | |
m_1_ret = (current - series.loc[m_1_ago:].iloc[0])*100/series.loc[m_1_ago:].iloc[0] | |
else: | |
w_1_ret = (current - series.iloc[-1-i])*100/series.iloc[-1-i] | |
w_2_ret = (current - series.iloc[-2-i])*100/series.iloc[-2-i] | |
m_1_ret = (current - series.iloc[-4-i])*100/series.iloc[-4-i] | |
sign_of = 1 | |
if inverse == True: | |
sign_of = -1 | |
val = 100*(3*(2*(sign_of*w_1_ret>0) - 1) + 2*(2*(sign_of*w_2_ret>0) - 1) + 2*(sign_of*m_1_ret>0) - 1)/6 | |
return val | |
def get_roro(tf = "1Y"): | |
df_spx = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=.SPX").json()["barData"]["priceBars"]) | |
df_spx["datetime"] = pd.to_datetime(df_spx['tradeTimeinMills'],unit='ms').dt.date | |
df_spx.set_index("datetime",inplace = True) | |
df_spx["close"] = df_spx["close"].astype(float) | |
df_vix = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=.VIX").json()["barData"]["priceBars"]) | |
df_vix["close"] = df_vix["close"].astype(float) | |
df_AUDJPY = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=AUDJPY=").json()["barData"]["priceBars"]) | |
df_AUDJPY["datetime"] = pd.to_datetime(df_AUDJPY['tradeTimeinMills'],unit='ms').dt.date | |
df_AUDJPY.set_index("datetime",inplace = True) | |
df_AUDJPY["close"] = df_AUDJPY["close"].astype(float) | |
df_gold = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=@GC.1").json()["barData"]["priceBars"]) | |
df_gold["datetime"] = pd.to_datetime(df_gold['tradeTimeinMills'],unit='ms').dt.date | |
df_gold.set_index("datetime",inplace = True) | |
df_gold["close"] = df_gold["close"].astype(float) | |
df_silver = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=@SI.1").json()["barData"]["priceBars"]) | |
df_silver["datetime"] = pd.to_datetime(df_silver['tradeTimeinMills'],unit='ms').dt.date | |
df_silver.set_index("datetime",inplace = True) | |
df_silver["close"] = df_silver["close"].astype(float) | |
gold_silver_ratio = df_gold["close"]/df_silver["close"] | |
df_bnd = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=BND").json()["barData"]["priceBars"]) | |
df_bnd["datetime"] = pd.to_datetime(df_bnd['tradeTimeinMills'],unit='ms').dt.date | |
df_bnd.set_index("datetime",inplace = True) | |
df_bnd["close"] = df_bnd["close"].astype(float) | |
df_sphb = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=SPHB").json()["barData"]["priceBars"]) | |
df_sphb["datetime"] = pd.to_datetime(df_sphb['tradeTimeinMills'],unit='ms').dt.date | |
df_sphb.set_index("datetime",inplace = True) | |
df_sphb["close"] = df_sphb["close"].astype(float) | |
df_splv = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=SPLV").json()["barData"]["priceBars"]) | |
df_splv["datetime"] = pd.to_datetime(df_splv['tradeTimeinMills'],unit='ms').dt.date | |
df_splv.set_index("datetime",inplace = True) | |
df_splv["close"] = df_splv["close"].astype(float) | |
sphb_splv_ratio = df_sphb["close"]/df_splv["close"] | |
df_HYG = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=HYG").json()["barData"]["priceBars"]) | |
df_HYG["datetime"] = pd.to_datetime(df_HYG['tradeTimeinMills'],unit='ms').dt.date | |
df_HYG.set_index("datetime",inplace = True) | |
df_HYG["close"] = df_HYG["close"].astype(float) | |
df_fnda = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=FNDA").json()["barData"]["priceBars"]) | |
df_fnda["datetime"] = pd.to_datetime(df_fnda['tradeTimeinMills'],unit='ms').dt.date | |
df_fnda.set_index("datetime",inplace = True) | |
df_fnda["close"] = df_fnda["close"].astype(float) | |
df_schx = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=SCHX").json()["barData"]["priceBars"]) | |
df_schx["datetime"] = pd.to_datetime(df_schx['tradeTimeinMills'],unit='ms').dt.date | |
df_schx.set_index("datetime",inplace = True) | |
df_schx["close"] = df_schx["close"].astype(float) | |
fnda_schx_ratio = df_fnda["close"]/df_schx["close"] | |
df_btc_usd = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{tf}.json?symbol=BTC.CB=").json()["barData"]["priceBars"]) | |
df_btc_usd["datetime"] = pd.to_datetime(df_btc_usd['tradeTimeinMills'],unit='ms').dt.date | |
df_btc_usd.set_index("datetime",inplace = True) | |
df_btc_usd["close"] = df_btc_usd["close"].astype(float) | |
periods = 300 | |
roro = [] | |
if tf == "5Y": | |
state = 1 | |
else: | |
state = 0 | |
for i in range(periods,0,-1): | |
temp = dict( | |
date = (pd.to_datetime(df_spx.index).date)[-i], | |
spx = roro_comp_get(df_spx["close"],i,state), | |
audjpy = roro_comp_get(df_AUDJPY["close"],i,state), | |
gold_silver = roro_comp_get(gold_silver_ratio,i,state,inverse = True), | |
bnd = roro_comp_get(df_bnd["close"],i,state,inverse = True), | |
sphb_splv = roro_comp_get(sphb_splv_ratio,i,state), | |
hyg = roro_comp_get(df_HYG["close"],i,state), | |
fnda_schx = roro_comp_get(fnda_schx_ratio,i,state), | |
vix = vix_gradient(df_vix["close"].iloc[-i]), | |
btc_usd = roro_comp_get(df_btc_usd["close"],i,state) | |
) | |
roro.append(temp) | |
return roro | |
# Setting the page layout as wide | |
st.set_page_config(layout="wide") | |
def get_data_yields(symbol,lookback_period): | |
global response_yields | |
df = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/{lookback_period}.json?symbol={symbol}").json()["barData"]["priceBars"]) | |
df["datetime"] = pd.to_datetime(df['tradeTimeinMills'],unit='ms') | |
df.set_index("datetime",inplace = True) | |
response_yields[symbol] = df["close"].astype(float) | |
def get_recommendation(symbol,rsi_val,drop_frm_ath,dist_from_5_yr_low): | |
global momentum_recommendations,cheap_recommendations | |
df = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/1Y.json?symbol={symbol}").json()["barData"]["priceBars"]) | |
df_all = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/ALL.json?symbol={symbol}").json()["barData"]["priceBars"]) | |
df_all["high"] = df_all["high"].astype(float) | |
df_all["low"] = df_all["low"].astype(float) | |
df["tradeTimeinMills"] = pd.to_datetime(df['tradeTimeinMills'],unit='ms') | |
df_all["tradeTimeinMills"] = pd.to_datetime(df_all['tradeTimeinMills'],unit='ms') | |
df["close"] = df["close"].astype(float) | |
df["open"] = df["open"].astype(float) | |
df.set_index("tradeTimeinMills",inplace = True) | |
df_all.set_index("tradeTimeinMills",inplace = True) | |
current_close = df["close"].iloc[-1] | |
df["50DMA"] = df["close"].rolling(50).mean() | |
df["100DMA"] = df["close"].rolling(100).mean() | |
df["Vol_mon_avg"] = 5*df["volume"].rolling(252).mean() | |
df["RSI"] = talib.RSI(df["close"]) | |
cond1 = current_close>df["50DMA"].iloc[-1] | |
cond2 = current_close>df["100DMA"].iloc[-1] | |
cond3 = df["volume"].rolling(5).sum().iloc[-1]>1.5*df["Vol_mon_avg"].iloc[-1] | |
mom_score = int(cond1)+int(cond2)+int(cond3) | |
ath = df_all["high"].max() | |
distance_from_ath = round((ath-current_close)*100/ath,2) | |
yr_2_ago_dt = datetime.now() - relativedelta(years=2) | |
yr_2_low = df_all["low"].loc[yr_2_ago_dt:].min() | |
distance_frm_2yr_low = round((current_close - yr_2_low)*100/current_close,2) | |
rsi = round(df["RSI"].iloc[-1],2) | |
cond_1 = rsi<rsi_val | |
cond_2 = distance_from_ath>=drop_frm_ath | |
cond_3 = distance_frm_2yr_low<=dist_from_5_yr_low | |
cheap_score = int(cond_1)+int(cond_2)+int(cond_3) | |
if (cond1 or cond2) or cond3: | |
momentum_recommendations[symbol] = {"LTP":current_close,"50DMA":df["50DMA"].iloc[-1],"100DMA":df["100DMA"].iloc[-1],"Vol>1.5avg":cond3,"score":mom_score,"sparkline": sparkline(data=df["close"])} | |
if cond_1 or cond_2 or cond_3: | |
cheap_recommendations[symbol] = {"LTP":current_close,"RSI":rsi,f'drop frm ATH':distance_from_ath,f"% away 2 yr low":distance_frm_2yr_low,"score":cheap_score,"sparkline": sparkline(data=df["close"])} | |
def sparkline(data, figsize=(4,0.25),**kwags): | |
data = list(data) | |
fig,ax = plt.subplots(1,1,figsize=figsize,**kwags) | |
ax.plot(data) | |
for k,v in ax.spines.items(): | |
v.set_visible(False) | |
ax.set_xticks([]) | |
ax.set_yticks([]) | |
plt.plot(len(data)-1, data[len(data)-1], 'r.') | |
ax.fill_between(range(len(data)), data, len(data)*[min(data)], alpha=0.1) | |
img = BytesIO() | |
plt.savefig(img, transparent=True, bbox_inches='tight') | |
img.seek(0) | |
# plt.show() | |
plt.close() | |
# return base64.b64encode(img.read()).decode("utf-8") | |
return '<img src="data:image/png;base64,{}"/>'.format(base64.b64encode(img.read())) | |
def highlight_rec_momentum(s): | |
arr = [] | |
arr.append('background-color: white') | |
if s["50DMA"]<s["LTP"]: | |
arr.append('background-color: #90EE90') | |
else: | |
arr.append('background-color: #FF7F7F') | |
if s["100DMA"]<s["LTP"]: | |
arr.append('background-color: #90EE90') | |
else: | |
arr.append('background-color: #FF7F7F') | |
if s["Vol>1.5avg"]: | |
arr.append('background-color: #90EE90') | |
else: | |
arr.append('background-color: #FF7F7F') | |
arr.append('background-color: white') | |
arr.append('background-color: white') | |
return arr | |
def font_color(s): | |
return ["color: black"]*len(s) | |
def highlight_rec_cheap(s,rsi_val,drop_frm_ath,dist_from_5_yr_low): | |
arr = [] | |
arr.append('background-color: white') | |
if s["RSI"]<rsi_val: | |
arr.append('background-color: #90EE90') | |
else: | |
arr.append('background-color: #FF7F7F') | |
if s[f"drop frm ATH"]>drop_frm_ath: | |
arr.append('background-color: #90EE90') | |
else: | |
arr.append('background-color: #FF7F7F') | |
if s[f"% away 2 yr low"]<dist_from_5_yr_low: | |
arr.append('background-color: #90EE90') | |
else: | |
arr.append('background-color: #FF7F7F') | |
arr.append('background-color: white') | |
arr.append('background-color: white') | |
return arr | |
def get_etf_rets(symbol): | |
global res_etf_ret, vol_etf_info,expense_ratios | |
df = pd.DataFrame(requests.get(f"https://ts-api.cnbc.com/harmony/app/charts/1Y.json?symbol={symbol}").json()["barData"]["priceBars"]) | |
df["tradeTimeinMills"] = pd.to_datetime(df['tradeTimeinMills'],unit='ms') | |
df["close"] = df["close"].astype(float) | |
df["open"] = df["open"].astype(float) | |
df.set_index("tradeTimeinMills",inplace = True) | |
df_new = df.resample("W-Sun").agg({"close":"last","open":"first"}) | |
price_1_yr_ago = df.loc[df_new.index[-1] - relativedelta(years = 1):].iloc[0]["open"] | |
price_1_mon_ago = df.loc[df.index[-1] - relativedelta(months=1):].iloc[0]["open"] | |
close = df.iloc[-1]["close"] | |
daily_ret = (close - df.iloc[-1]["open"].astype(float))*100/df.iloc[-1]["open"] | |
w_1_ret = round((close - df_new.iloc[-1]["open"])*100/df_new.iloc[-1]["open"],2) | |
w_2_ret = round((close - df_new.iloc[-2]["open"])*100/df_new.iloc[-2]["open"],2) | |
y_1_ret = round((close - price_1_yr_ago)*100/price_1_yr_ago,2) | |
m_1_ret = round((close - price_1_mon_ago)*100/price_1_mon_ago,2) | |
temp = dict(symbol = symbol,day_ret = daily_ret, w1_ret = w_1_ret, w2_ret = w_2_ret, year_ret = y_1_ret,m1_ret = m_1_ret) | |
res_etf_ret.append(temp) | |
iv = (df["close"].pct_change()*100).iloc[-30:].std()*np.sqrt(252) | |
vol_etf_info[symbol] = round(iv,2) | |
r = requests.get(f"https://etfdb.com/etf/{symbol}/#etf-ticker-profile") | |
soup = BeautifulSoup(r.content, 'html5lib') | |
expense_ratio = soup.find("div",{"class":"ticker-assets"}).find_all("div")[3].text.split("\n")[-2] | |
expense_ratios[symbol] = expense_ratio | |
return | |
def get_data(ticker, timeframe = 60*60 * 4): | |
# Function to get OHLC data for a symbol from FTX api | |
data = pd.DataFrame(json.loads(requests.get(f"https://ftx.com/api/markets/{ticker}/candles?resolution={timeframe}").text)["result"]) | |
return data | |
def in_squeeze(symbol,bb_mul, kc_mul,num_days,plot = False, timeframe = 60*60*4): | |
# Function to check whether Keltner Channel and Bollinger bands squeeze is happening | |
# Get Data | |
data = get_data(symbol,timeframe) | |
# Calculate BB | |
data["20sma"] = data["close"].rolling(window = 20).mean() | |
data["stddev"] = data["close"].rolling(window = 20).std() | |
data["lowerband"] = data["20sma"] - bb_mul*data["stddev"] | |
data["upperband"] = data["20sma"] + bb_mul*data["stddev"] | |
# Calculate KC | |
data["TR"] = data["high"] - data["low"] | |
data["ATR"] = data["TR"].rolling(window = 20).mean() | |
data['upperKC'] = data["20sma"] + kc_mul*data["ATR"] | |
data['lowerKC'] = data["20sma"] - kc_mul*data["ATR"] | |
data["squeeze_on"] = np.where( | |
np.logical_and(data["lowerband"]>data["lowerKC"], data["upperband"]<data["upperKC"]),1,0) | |
# Now if "num_days" days earlier BB were in KC but now, its not then that's breakout | |
if data.iloc[-num_days]["squeeze_on"] and not data.iloc[-1]["squeeze_on"]: | |
# If user wants to plot the candlestick then pass the plot = True | |
if plot == True: | |
# Template for plotting KC and BB and candlesticks | |
candlestick = go.Candlestick(x=data["startTime"],open=data["open"],high=data["high"],low=data["low"],close=data["close"], name = symbol) | |
upperband = go.Scatter(x = data["startTime"], y = data["upperband"], name = "Upper BB", line = dict(color = "blue")) | |
lowerband = go.Scatter(x = data["startTime"], y = data["lowerband"], name = "Lower BB", line = dict(color = "blue")) | |
upperKC = go.Scatter(x = data["startTime"], y = data["upperKC"], name = "Upper KC", line = dict(color = "green")) | |
lowerKC = go.Scatter(x = data["startTime"], y = data["lowerKC"], name = "Upper KC", line = dict(color = "green")) | |
fig = go.Figure(data = [candlestick,upperband, lowerband, upperKC, lowerKC]) | |
# Slider in Xaxes for 1month, 6month, YTD and 1Y | |
fig.update_xaxes( | |
rangeslider_visible=True, | |
rangeselector=dict( | |
buttons=list([ | |
dict(count=1, label="1mon", step="month", stepmode="backward"), | |
dict(count=6, label="6mon", step="month", stepmode="backward"), | |
dict(count=1, label="YTD", step="year", stepmode="todate"), | |
dict(count=1, label="1y", step="year", stepmode="backward"), | |
dict(step="all") | |
]) | |
)) | |
fig.update_layout(yaxis=dict(autorange = True,fixedrange= False)) | |
st.plotly_chart(fig,use_container_width=True) | |
else: | |
print(f"{symbol}") | |
def plot_candlestick(data): | |
# Function to plot candlestick out of a given OHLC dataframe | |
fig = go.Figure(data=[go.Candlestick(x=data.index, | |
open=data['open'], | |
high=data['high'], | |
low=data['low'], | |
close=data['close'])]) | |
fig.update_xaxes( | |
rangeslider_visible=True, | |
rangeselector=dict( | |
buttons=list([ | |
dict(count=1, label="1mon", step="month", stepmode="backward"), | |
dict(count=6, label="6mon", step="month", stepmode="backward"), | |
dict(count=1, label="YTD", step="year", stepmode="todate"), | |
dict(count=1, label="1y", step="year", stepmode="backward"), | |
dict(step="all") | |
]) | |
)) | |
return fig | |
def get_key(dict_given, val): | |
# Function to get the key of the required value from a dictionary | |
for key, value in dict_given.items(): | |
if val == value: | |
return key | |
def get_crypto_data_daily(symbol): | |
data = get_data(symbol,timeframe = 60*60*24) | |
data.to_csv(f"crypto_data/{symbol.replace('/','_')}.csv") | |
def get_cnbc_yields(symbol): | |
# Get the symbol quote from yahoo finance, we are using Beautiful Soup for scraping | |
URL = f"https://www.cnbc.com/quotes/US5Y" | |
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36'} | |
page = requests.get(URL, headers = headers) | |
soup = BeautifulSoup(page.text, "html.parser") | |
yields = ["US 2Y","US 5Y", "US 10Y","US 30Y"] | |
if symbol in yields: | |
elements = soup.find('div',{'class':'QuoteStrip-lastPriceStripContainer'}) | |
price = elements.find_all('span')[0].text.replace("%","") | |
return float(price.replace(",","")) | |
def get_yahoo_finance_quote(symbol): | |
# Get the symbol quote from yahoo finance, we are using Beautiful Soup for scraping | |
URL = f"https://finance.yahoo.com/quote/{symbol}" | |
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36'} | |
page = requests.get(URL, headers = headers) | |
soup = BeautifulSoup(page.text, "html.parser") | |
price = soup.find('div',{'class':'D(ib) Mend(20px)'}).find_all('fin-streamer')[0].text | |
return price.replace(",","") | |
def get_symbol_quote(ticker_tape, symbol,tck_tape, idx): | |
# Get the symbol quote from yahoo finance, we are using Beautiful Soup for scraping | |
URL = f"https://finance.yahoo.com/quote/{symbol}" | |
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36'} | |
page = requests.get(URL, headers = headers) | |
soup = BeautifulSoup(page.text, "html.parser") | |
price = soup.find('div',{'class':'D(ib) Mend(20px)'}).find_all('span')[0].text | |
change = soup.find('div',{'class':'D(ib) Mend(20px)'}).find_all('span')[1].text | |
change = change.split(" ")[1] | |
change = change[1:-1] | |
if ticker_tape == "US 10Y": | |
# US 10Y treated differently because of some formating purposes | |
change = float(change.replace("(","").replace(")","").replace("%","")) | |
price_now = float(price) | |
change = round(price_now - price_now/(1+change/100),2) | |
change = str(change) + "%" | |
tck_tape[idx].metric(label = ticker_tape ,value = price,delta = change) | |
# Set the twitter client and set the access token which comes from config.py | |
auth = tweepy.OAuthHandler(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET) | |
auth.set_access_token(TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_TOKEN_SECRET) | |
api = tweepy.API(auth) | |
if "trade_api" not in st.session_state: | |
# Now, if this api is not there in session_state then add it, | |
# we are doing this because we don't want to let the info go once site is refreshed | |
# And session_state is kind of memory used for caching required info | |
# Set the trade_api variable | |
st.session_state.trade_api = REST(API_KEY, SECRET_KEY, API_URL) | |
if "stocks" not in st.session_state: | |
# If stocks are not present then from companies.csv file add them | |
with open('datasets/companies.csv') as f: | |
companies = f.read().splitlines() | |
symbols = [] | |
for company in companies: | |
symbols.append(company.split(",")[0]) | |
st.session_state.stocks = symbols | |
if "login" not in st.session_state: | |
# If user has not logged in set login = False | |
# This is done because once logged in we want the program to remember that it logged in | |
# Hence setting the session_state | |
st.session_state.login = False | |
if st.session_state.login == False: | |
# If login is false then create a login window | |
st.sidebar.write("Login") | |
# Create sidebar login boxes | |
user = st.sidebar.text_input(label = "Username") | |
password = st.sidebar.text_input(label = "Password", type = "password") | |
login_btn = st.sidebar.button("Login") | |
if login_btn: | |
# This is the users list which will help in login and password for both is 123 | |
if user in ["Chaitanya", "Sagar"] and password == "Wizards@123Trade#": | |
st.sidebar.success(f"Logged In as {user}") | |
st.session_state.login = True | |
# Now if clicked on login wait for 1 second then reload the page using experimental_rerun | |
time.sleep(1) | |
st.experimental_rerun() | |
else: | |
# If incorrect credentials then pose an error | |
st.sidebar.warning("Incorrect Username/Password") | |
else: | |
# Get the crypto data from FTX api | |
df = pd.DataFrame(json.loads(requests.get("https://ftx.com/api/markets").text)["result"]) | |
# Get the LTP and 24H %change for BTCUSDT, ETHUSDT | |
st.session_state.index_btc = df[df["name"]=="BTC/USDT"]["last"].values[0] | |
st.session_state.index_btc_pct_change = round(df[df["name"]=="BTC/USDT"]["change24h"].values[0],2) | |
st.session_state.index_eth = df[df["name"]=="ETH/USDT"]["last"].values[0] | |
st.session_state.index_eth_pct_change = round(df[df["name"]=="ETH/USDT"]["change24h"].values[0],2) | |
st.session_state.roro = get_roro() | |
roro_df = pd.DataFrame(st.session_state.roro) | |
roro_df.set_index("date",inplace = True) | |
roro_df["sum"] = roro_df.sum(axis = 1) / len(roro_df.columns) | |
# Code below is for formatting purpose | |
cols_ticker_tape_cryp = st.columns([1,1]) | |
cols_ticker_tape_cryp[0].metric(label = "BTC",value = st.session_state.index_btc, delta = f"{st.session_state.index_btc_pct_change}%") | |
cols_ticker_tape_cryp[1].metric(label = "ETH", value = st.session_state.index_eth, delta = f"{st.session_state.index_eth_pct_change}%") | |
fig = go.Figure(go.Indicator( | |
mode = "number+delta", | |
value = round(roro_df["sum"].iloc[-1]), | |
domain = {'x': [0, 0.2], 'y': [0, 0.2]}, | |
delta = {'reference': round(roro_df["sum"].iloc[-2])}, | |
gauge = {'axis': {'range': [-100, 100]}}, | |
title = {'text': "RORO Indicator"})) | |
fig.add_trace(go.Scatter(y = roro_df["sum"].values,x = roro_df.index,mode = "lines",fill='tozeroy')) | |
st.plotly_chart(fig,use_container_width=True,use_container_height = True) | |
cols_ticker_tape = st.columns(5) | |
# Now, since fetching each symbol will take lots of time | |
# So, we are running all the process in threads parally multi-processing | |
thread_ticker = [] | |
for i in range(len (symbol_mapping.keys())): | |
# Get the symbol_mapping and run it in thread and display each of them | |
ticker_tape = list(symbol_mapping.keys())[i] | |
t_ticker = threading.Thread(target = get_symbol_quote, args = (ticker_tape, symbol_mapping[ticker_tape],cols_ticker_tape,i,)) | |
add_report_ctx(t_ticker) | |
t_ticker.start() | |
thread_ticker.append(t_ticker) | |
for x in thread_ticker: | |
# Wait for the threads to finish | |
x.join() | |
# This is a menu for various dashboard windows | |
option = st.sidebar.selectbox("Which Dashboard?", | |
("Watchlist","twitter","wallstreetbets","stocktwits","CryptoIndex","Chart","pattern", "MACRO", | |
"Technical Scanner", "coinBaskets", "Breakout","ETFs", "Commodities","Report","Recommendations","RORO Components")) | |
# If you want to momentarily hide your website from people then remove the below from commenting | |
# Or you could do one more thing, setup a pseudo id-password, which log in you to only limited features | |
# option = st.sidebar.selectbox("Which Dashboard?", | |
# ("twitter","coinBaskets")) | |
# Set the option value as header | |
st.header(option) | |
if option == "Watchlist": | |
# If watchlist is selected | |
st.subheader("Watchlist") | |
col1, col2 = st.columns([1,6.5]) | |
df_watchlist = pd.read_csv('watchlist.csv') | |
with col1: | |
# Now, create a form which will help you add symbol name, comments, etc | |
with st.form(key = "symbol_add"): | |
# df = pd.DataFrame(json.loads(requests.get("https://ftx.com/api/markets").text)["result"]) | |
# df = df[df["quoteCurrency"].isin(["USD","USDT"])] | |
# symbols = df.name.values | |
# asset_class = st.sidebar.selectbox("Asset Class",["Crypto","Fixed Income","Stocks","Index","Commodity"]) | |
asset_class = st.sidebar.selectbox("Asset Class",["Fixed Income","Stocks","Index","Commodity"]) | |
if asset_class == "Crypto": | |
symbol = st.selectbox("Symbol",symbols) | |
st.write("Currently working for crypto symbols from FTX") | |
elif asset_class == "Fixed Income": | |
symbol = st.selectbox("Symbol",["HYG","LQD","US 2Y","US 5Y","US 10Y","US 30Y"]) | |
elif asset_class == "Index": | |
symbol = st.selectbox("Symbol",["SPX","NASDAQ","NIFTY50","VIX"]) | |
st.write("If an alert got triggered, but you want to add another, first delete it, then add") | |
trigger = st.text_input("Trigger Price") | |
view_type = st.selectbox("View Type",["Above","Below"]) | |
dma200 = st.selectbox("DMA alert",["Yes", "No"]) | |
dma200_view_type = st.selectbox("DMA200 View Type",["Above","Below"]) | |
alert_type = st.selectbox("Alert Type",["Macro","Individual"]) | |
comments = st.text_area("Comments") | |
# Create buttons like add and delete symbols for use | |
add_symbol = st.form_submit_button("Add") | |
delete_symbol = st.form_submit_button("Remove") | |
# Empty watchlist button to clear whole watchlist | |
empty_checkbox = st.checkbox("Yes, I wish to empty the watchlist",value = False) | |
empty_watchlist = st.form_submit_button("Empty Watchlist") | |
with col2: | |
# If empty_watchlist button is clicked then, clear the watchlist | |
if empty_watchlist and empty_checkbox: | |
st.info("Watchlist cleared") | |
df_watchlist = pd.DataFrame(columns=["Symbol","Comments"]) | |
df_watchlist.to_csv('watchlist.csv',index=False) | |
elif empty_watchlist: | |
st.error("Could not clear the watchlist, please select the checkbox") | |
elif add_symbol: | |
if symbol not in df_watchlist["Symbol"].values: | |
# If symbol is added then add it to csv file, then update the csv file | |
st.info("Symbol added") | |
df_watchlist = df_watchlist.append(dict(Symbol = symbol, Trigger = float(trigger), alert_type = alert_type, view_type = view_type, status = "Pending",dma200 = dma200, dma200_view_type = dma200_view_type,dma_status = "Pending",Comments = comments), ignore_index=True) | |
df_watchlist.to_csv('watchlist.csv',index=False) | |
else: | |
st.warning("Symbol Already Present, Please check") | |
elif delete_symbol: | |
if symbol not in df_watchlist["Symbol"].values: | |
st.warning("Symbol not present, please check...") | |
else: | |
# Delte symbol and update the csv file | |
st.info("Symbol Deleted") | |
df_watchlist = df_watchlist[df_watchlist["Symbol"]!= symbol] | |
df_watchlist.to_csv('watchlist.csv',index=False) | |
if len(df_watchlist)>0: | |
# If there's something in watchlist then for cryptos fetch the LTP from FTX api | |
# Getting LTP is currently for Crypto only due to free data unavailability for stocks/ETFs | |
df_watchlist.set_index("Symbol",inplace = True) | |
df_watchlist["LTP"] = 0 | |
def get_data_symbol(symbol_name_for_quote): | |
global df_watchlist | |
try: | |
if symbol_name_for_quote in ["HYG","LQD","SPX","NASDAQ","NIFTY50","VIX","US 2Y","US 5Y", "US 10Y","US 30Y"]: | |
data_symbol = get_cnbc_data(symbol_name_for_quote) | |
else: | |
data_symbol = json.loads(requests.get(f"https://ftx.com/api/markets/{symbol_name_for_quote}").text)["result"]["price"] | |
df_watchlist.loc[symbol_name_for_quote,"LTP"] = data_symbol | |
except: | |
pass | |
threads_list = [] | |
for i in range(len(df_watchlist)): | |
symbol_name_for_quote = df_watchlist.index[i] | |
x = threading.Thread(target = get_data_symbol,args = (symbol_name_for_quote,)) | |
x.start() | |
add_report_ctx(x) | |
threads_list.append(x) | |
for thread in threads_list: | |
thread.join() | |
df_watchlist["pct_away"] = np.round(100*np.abs(df_watchlist["Trigger"] - df_watchlist["LTP"])/df_watchlist["LTP"]) | |
# Show the watchlist | |
st.dataframe(df_watchlist) | |
elif option == "RORO Components": | |
lkbck_perd = st.sidebar.selectbox("Lookback Period",["1Y","5Y"]) | |
st.sidebar.write("1Y will fetch daily data, 5Y --> weekly") | |
st.sidebar.write("Number of lookback periods is set as 300") | |
roro_run_btn = st.sidebar.button("Run") | |
if roro_run_btn: | |
roro_comp_df = pd.DataFrame(get_roro(lkbck_perd)) | |
roro_comp_df.set_index("date",inplace = True) | |
roro_comp_df["roro"] = roro_comp_df.sum(axis = 1)/(len(roro_comp_df.columns)) | |
fig = make_subplots(rows=len(roro_comp_df.columns), shared_xaxes=True,vertical_spacing=0.01,subplot_titles=(roro_comp_df.columns)) | |
counter = 1 | |
for key in roro_comp_df.columns: | |
if key!= "roro": | |
fig.add_scatter(x = roro_comp_df.index, y = roro_comp_df[key].values,mode = "lines",row = counter, col = 1, name = key) | |
else: | |
fig.add_scatter(y = roro_comp_df["roro"].values,x = roro_comp_df.index,mode = "lines",fill='tozeroy',row = counter,col =1,name = key) | |
counter+=1 | |
fig['layout'].update(height=2500, width=600, title='Subplots of components') | |
st.plotly_chart(fig,use_container_width = True) | |
elif option == "Recommendations": | |
select_asset = st.sidebar.selectbox("Asset Class",["ETF"]) | |
rsi_val = st.sidebar.number_input("RSI Thresh",value = 50) | |
drop_frm_ath = st.sidebar.number_input("Drop From ATH(%) Thresh",value = 50) | |
dist_from_5_yr_low = st.sidebar.number_input(f"%away from 2 yr Low Thresh",value = 20) | |
rec_run_btn = st.sidebar.button("Run") | |
st.sidebar.write("**Momentum Rising Screening Conditions**") | |
st.sidebar.write("LTP>50DMA") | |
st.sidebar.write("LTP>100DMA") | |
st.sidebar.write("5D Vol>1.5*(5D Vol. yearly_avg") | |
st.sidebar.write("**Cheap Stocks Screening Conditions**") | |
st.sidebar.write("RSI < RSI Thresh") | |
st.sidebar.write("Drop from ATH(%) > Drop from ATH(%) Thresh") | |
st.sidebar.write(f"% away from 2 yr Low < %away from 2 yr Low Thresh") | |
if rec_run_btn: | |
momentum_recommendations = {} | |
cheap_recommendations = {} | |
rec_threads = [] | |
if select_asset == "ETF": | |
options_for_assets = all_etfs | |
for asset in options_for_assets: | |
x = threading.Thread(target=get_recommendation,args = (asset,rsi_val,drop_frm_ath,dist_from_5_yr_low,)) | |
x.start() | |
rec_threads.append(x) | |
# get_recommendation(asset) | |
for rec in rec_threads: | |
rec.join() | |
# st.write(momentum_recommendations) | |
momentum_recommendations = pd.DataFrame(momentum_recommendations).T | |
momentum_recommendations.sort_values("score",ascending=False,inplace = True) | |
cheap_recommendations = pd.DataFrame(cheap_recommendations).T | |
cheap_recommendations.sort_values("score",ascending=False,inplace = True) | |
st.header("Momentum Rising") | |
st.dataframe(momentum_recommendations.style.apply(highlight_rec_momentum,axis = 1).apply(font_color)) | |
st.header("Cheap Stocks") | |
st.dataframe(cheap_recommendations.style.apply(highlight_rec_cheap,args = (rsi_val,drop_frm_ath,dist_from_5_yr_low),axis = 1).apply(font_color)) | |
elif option == "MACRO": | |
select_timeframe = st.sidebar.selectbox("Which Timeframe (finviz only)?",["Daily","Weekly","Monthly"]) | |
# select_lookback_period = st.sidebar.selectbox("LookbackPeriod for yields(yrs)",[1,2,3,4,5]) | |
select_lookback_period = st.sidebar.selectbox("LookbackPeriod for yields",["1D","1M","3M","6M","1Y","5Y"]) | |
timeframe_map = {"Daily":"d1","Weekly":"w1","Monthly":"mo"} | |
tf = timeframe_map[select_timeframe] | |
run_btn = st.sidebar.button("Run") | |
if run_btn: | |
col1, col2, col3 = st.columns([1,1,1]) | |
with col1: | |
st.image(f"https://finviz.com/fut_image.ashx?es_{tf}_s.png") | |
with col2: | |
st.image(f"https://finviz.com/fut_image.ashx?vx_{tf}_s.png") | |
with col3: | |
st.image(f"https://finviz.com/fut_image.ashx?nq_{tf}_s.png") | |
response_yields = {} | |
thread_yields = [] | |
for symbol in ["US1Y","US2Y","US5Y","US10Y","US30Y"]: | |
thread = threading.Thread(target = get_data_yields, args = (symbol,select_lookback_period,)) | |
thread.start() | |
thread_yields.append(thread) | |
for x in thread_yields: | |
x.join() | |
df_yields = pd.concat(response_yields,axis = 1) | |
df_yields["2y/10y"] = df_yields["US10Y"]-df_yields["US2Y"] | |
df_yields["10y/30y"] = df_yields["US30Y"]-df_yields["US10Y"] | |
df_yields["2y/5y"] = df_yields["US5Y"]-df_yields["US2Y"] | |
df_yields["1y/2y"] = df_yields["US2Y"]-df_yields["US1Y"] | |
st.line_chart(df_yields[["US1Y","US2Y","US5Y","US10Y","US30Y"]]) | |
col1, col2 = st.columns([1,1]) | |
with col1: | |
st.line_chart(df_yields["1y/2y"]) | |
st.line_chart(df_yields["2y/5y"]) | |
with col2: | |
st.line_chart(df_yields["2y/10y"]) | |
st.line_chart(df_yields["10y/30y"]) | |
# today = datetime.now().strftime("%Y-%m-%d") | |
# past = (datetime.now() - timedelta(days=365*select_lookback_period)).strftime("%Y-%m-%d") | |
# # https://fred.stlouisfed.org/graph/?id=DGS10,DGS5,DGS30,DGS3MO,DGS1,DGS2, | |
# url = f"""https://fred.stlouisfed.org/graph/fredgraph.png?dwnld=0&hires=1&type=image/png& | |
# bgcolor=%23e1e9f0&chart_type=line&drp=0&fo=open%20sans&graph_bgcolor=%23ffffff&height=450& | |
# mode=fred&recession_bars=on&txtcolor=%23444444&ts=12&tts=12&width=1168&nt=0&thu=0&trc=0& | |
# show_legend=yes&show_axis_titles=yes&show_tooltip=yes&id=DGS10,DGS5,DGS30,DGS3MO,DGS1,DGS2& | |
# scale=left,left,left,left,left,left&cosd={past},{past},{past},{past},{past},{past}& | |
# coed={today},{today},{today},{today},{today},{today}& | |
# line_color=%234572a7,%23aa4643,%2389a54e,%2380699b,%233d96ae,%23db843d& | |
# link_values=false,false,false,false,false,false&line_style=solid,solid,solid,solid,solid,solid& | |
# mark_type=none,none,none,none,none,none&mw=3,3,3,3,3,3&lw=2,2,2,2,2,2& | |
# ost=-99999,-99999,-99999,-99999,-99999,-99999&oet=99999,99999,99999,99999,99999,99999& | |
# mma=0,0,0,0,0,0&fml=a,a,a,a,a,a&fq=Daily,Daily,Daily,Daily,Daily,Daily& | |
# fam=avg,avg,avg,avg,avg,avg&fgst=lin,lin,lin,lin,lin,lin& | |
# fgsnd=2020-02-01,2020-02-01,2020-02-01,2020-02-01,2020-02-01,2020-02-01&line_index=1,2,3,4,5,6& | |
# transformation=lin,lin,lin,lin,lin,lin& | |
# vintage_date={today},{today},{today},{today},{today},{today}& | |
# revision_date={today},{today},{today},{today},{today},{today}& | |
# nd=1962-01-02,1962-01-02,1977-02-15,1981-09-01,1962-01-02,1976-06-01 | |
# """ | |
# url = url.replace("\n","") | |
# st.image(url,width = 800) | |
elif option == "twitter": | |
# If twitter is selected | |
today = datetime.today() | |
# Get the local timezone, this is important because then it works on a different timezone | |
to_zone = tz.tzlocal() | |
# Multibox for selecting multiple users | |
who = st.sidebar.multiselect("Choose person",tuple(TWITTER_USERNAMES)) | |
twitter_run_btn = st.sidebar.button("Run") | |
if twitter_run_btn: | |
# if twitter run button is clicked then all those people selected are called | |
if "SELECT ALL" in who: | |
users_list = TWITTER_USERNAMES[1:] | |
else: | |
users_list = who | |
for username in users_list: | |
# For a given username fetch the tweets, its username, image | |
user = api.get_user(screen_name = username) | |
tweets = api.user_timeline(screen_name = username, count = 100, tweet_mode = "extended") | |
st.subheader(username) | |
st.image(user.profile_image_url) | |
for tweet in tweets: | |
# In all his tweets, bring those to local timezone | |
tweet_date = ((tweet.created_at).astimezone(to_zone)).replace(tzinfo = None) | |
#Now, we don't want tweets older than 3 days | |
delta = (today - tweet_date).days | |
if delta>3: | |
continue | |
# For the following user names certain modification is done to get the tweets | |
if username in ["@chartmojo","@MacroCharts"]: | |
if tweet.in_reply_to_screen_name== None: | |
st.subheader(tweet._json["created_at"]) | |
st.write(tweet.full_text) | |
try: | |
for j in tweet.extended_entities["media"]: | |
st.image(j["media_url_https"], width=600) | |
except: | |
pass | |
else: | |
if tweet.in_reply_to_screen_name== None and len(tweet.entities["symbols"])>0: | |
symbols = [] | |
for i in range(len(tweet.entities["symbols"])): | |
symbols.append(tweet.entities["symbols"][i]["text"]) | |
st.subheader(" ".join(symbols)) | |
st.subheader(tweet._json["created_at"]) | |
st.subheader(tweet.full_text) | |
try: | |
for j in tweet.extended_entities["media"]: | |
st.image(j["media_url_https"], width = 600) | |
except: | |
pass | |
for symbol in symbols: | |
st.image(f"https://finviz.com/chart.ashx?t={symbol}&ta=1", width=600) | |
# elif option == "US Sectors": | |
# st.sidebar.write("Source - TradingView") | |
# select_sector = st.sidebar.selectbox("Select Sector", options = us_sectors) | |
# select_btn = st.sidebar.button("Run") | |
# url = "https://in.tradingview.com/markets/stocks-usa/sectorandindustry-sector/" | |
# r = requests.get(url) | |
# soup = BeautifulSoup(r.content, 'html5lib') # If this line causes an error, run 'pip install html5lib' or install html5lib | |
# req = soup.find_all('tr',attrs = {'class':'tv-data-table__row tv-data-table__stroke tv-screener-table__result-row'}) | |
# sectors = [] | |
# pct_change = [] | |
# for i in req: | |
# arr = [] | |
# for sector in i.find_all("td"): | |
# arr.append(sector.text) | |
# arr[0] = arr[0].split("\n")[3].split("\t")[0] | |
# sectors.append(arr[0]) | |
# pct_change.append(float(arr[3][:-1])) | |
# fig = go.Figure([go.Bar(x=sectors, y=pct_change, | |
# marker = dict(color = ['rgba(63, 195, 128, 1)' if value>0 else 'rgba(219, 10, 91, 1)' for value in pct_change], | |
# line = dict(color='rgb(0,0,0)',width=1.5)))]) | |
# st.plotly_chart(fig,use_container_width=True) | |
# if select_btn: | |
# val = "-".join(select_sector.lower().split(" ")) | |
# url = f"https://in.tradingview.com/markets/stocks-usa/sectorandindustry-sector/{val}/" | |
# r = requests.get(url) | |
# soup = BeautifulSoup(r.content, 'html5lib') # If this line causes an error, run 'pip install html5lib' or install html5lib | |
# req = soup.find_all('tr',attrs = {'class':'tv-data-table__row tv-data-table__stroke tv-screener-table__result-row'}) | |
# ticker = [] | |
# pct_change_ticker = [] | |
# company = [] | |
# for i in req: | |
# arr = [] | |
# for sector in i.find_all("td"): | |
# arr.append(sector.text) | |
# arr[0] = arr[0].split("\n")[4] | |
# # result.append(dict(ticker = arr[0],pct_change = float(arr[2][:-1]),vol = arr[5],mkt_cap = arr[6])) | |
# # ticker.append(arr[0]) | |
# company.append(us_stocks_mapping[arr[0]]) | |
# pct_change_ticker.append(float(arr[2][:-1])) | |
# layout = go.Layout( | |
# xaxis = go.XAxis( | |
# title = "Stocks", | |
# showticklabels = False | |
# ) | |
# ) | |
# fig = go.Figure([go.Bar(x=company, y=pct_change_ticker, | |
# marker = dict(color = ['rgba(63, 195, 128, 1)' if value>0 else 'rgba(219, 10, 91, 1)' for value in pct_change_ticker], | |
# line = dict(color='rgb(0,0,0)',width=1.5)))],layout = layout) | |
# st.write(len(company)) | |
# st.plotly_chart(fig,use_container_width=True) | |
# st_autorefresh(interval=120000, limit=10000, key="US sectors refresh") | |
elif option == "Commodities": | |
select_timeframe = st.sidebar.selectbox("Which Timeframe?",["Daily","Weekly","Monthly"]) | |
timeframe_map = {"Daily":"d1","Weekly":"w1","Monthly":"mo"} | |
tf = timeframe_map[select_timeframe] | |
col0,col1,col2 = st.columns([1,1,1]) | |
count = 0 | |
for key in commodity_mapping: | |
# https://finviz.com/futures_charts.ashx?t=YM&p=d1 | |
# Get the mapping for commodities, which is there in config.py | |
keyword_comm = commodity_mapping[key] | |
num = count%3 | |
if num ==0: | |
with col0: | |
st.image(f"https://finviz.com/fut_image.ashx?{keyword_comm}_{tf}_s.png") | |
elif num == 1: | |
with col1: | |
st.image(f"https://finviz.com/fut_image.ashx?{keyword_comm}_{tf}_s.png") | |
else: | |
with col2: | |
st.image(f"https://finviz.com/fut_image.ashx?{keyword_comm}_{tf}_s.png") | |
count = count+1 | |
elif option == "CryptoIndex": | |
# If cryptoIndex tab is selected | |
# Select which crypto index, then timeframe and accordingly fetch the data | |
type_index = st.sidebar.selectbox("Which?",["Major","Minor","Shit"]) | |
select_index_timeframe = st.sidebar.selectbox("Timeframe",["15s","1m","5m","15m","1h","4h","1d"]) | |
if select_index_timeframe[-1] == "s": | |
timeframe = int(select_index_timeframe[:-1]) | |
elif select_index_timeframe[-1] == "m": | |
timeframe = int(select_index_timeframe[:-1]) * 60 | |
elif select_index_timeframe[-1] == "h": | |
timeframe = int(select_index_timeframe[:-1])*60*60 | |
elif select_index_timeframe[-1] == "d": | |
timeframe = int(select_index_timeframe[:-1])* 60*60*24 | |
if type_index == "Major": | |
# Our crypto index is of 0.5BTC + 0.5 ETH | |
st.write("0.5BTC + 0.5ETH") | |
# Fetch data and create crypto index in same proportion | |
data_btc = pd.DataFrame(json.loads(requests.get(f"https://ftx.com/api/markets/BTC/USDT/candles?resolution={timeframe}").text)["result"]) | |
data_eth = pd.DataFrame(json.loads(requests.get(f"https://ftx.com/api/markets/ETH/USDT/candles?resolution={timeframe}").text)["result"]) | |
data_btc.set_index("startTime",inplace = True) | |
data_eth.set_index("startTime",inplace = True) | |
# Note crypto index are normalized | |
data = (data_btc["close"]*0.5/data_btc["close"][0] + data_eth["close"]*0.5/data_eth["close"][0])*100 | |
fig = go.Figure() | |
fig.add_trace(go.Scatter(x=data.index, y=data.values, | |
mode='lines', | |
name=type_index)) | |
fig.update_xaxes( | |
rangeslider_visible=True, | |
nticks = 20, | |
spikemode = "toaxis", | |
rangeselector=dict( | |
buttons=list([ | |
dict(count=1, label="1mon", step="month", stepmode="backward"), | |
dict(count=6, label="6mon", step="month", stepmode="backward"), | |
dict(count=1, label="YTD", step="year", stepmode="todate"), | |
dict(count=1, label="1y", step="year", stepmode="backward"), | |
dict(step="all") | |
]) | |
) | |
) | |
fig.update_layout( | |
xaxis_tickformat = '%Y-%m-%d', | |
height = 600, | |
width = 900, | |
hovermode = "x" | |
) | |
st.plotly_chart(fig) | |
elif option == "Report": | |
df = pd.DataFrame(json.loads(requests.get("https://ftx.com/api/markets").text)["result"]) | |
df = df[df["quoteCurrency"].isin(["USD","USDT"])] | |
symbols = df.name.values | |
to_analyze_symbol = st.sidebar.multiselect("Which symbol",symbols) | |
analysis_date = st.sidebar.selectbox("Which date for Analysis",["Current","Yesterday"]) | |
if analysis_date == "Yesterday": | |
locn = -2 | |
elif analysis_date == "Current": | |
locn = -1 | |
fetch_data_btn = st.sidebar.button("Fetch Data") | |
if fetch_data_btn: | |
threads = [] | |
for symbol in symbols: | |
t = threading.Thread(target = get_crypto_data_daily, args = (symbol,)) | |
t.start() | |
add_report_ctx(t) | |
threads.append(t) | |
for x in threads: | |
x.join() | |
res = {} | |
for req_symbol in to_analyze_symbol: | |
req_symbol_file = req_symbol.replace("/","_") | |
df_req = pd.read_csv(f"crypto_data/{req_symbol_file}.csv",index_col = 0, parse_dates = True) | |
ans = {} | |
for period in [20,50,100,200]: | |
df_req[f"MA{period}"] = talib.SMA(df_req["close"],period) | |
ans[f"% from MA{period}"] = round((df_req["close"].iloc[locn] - df_req[f"MA{period}"].iloc[locn])*100/df_req[f"MA{period}"].iloc[locn],2) | |
df_req["RSI14"] = talib.RSI(df_req["close"]) | |
ans["RSI"] = round(df_req["RSI14"].iloc[locn],2) | |
ans["LTP"] = df_req["close"].iloc[-1] | |
res[req_symbol] = ans | |
result = pd.DataFrame(res).T | |
st.dataframe(result) | |
elif option == "Breakout": | |
# If breakout tab is selected | |
# Get the crypto symbols | |
#Create buttons and boxes for selecting timeframe, BB number, KC multiplier | |
df = pd.DataFrame(json.loads(requests.get("https://ftx.com/api/markets").text)["result"]) | |
df = df[df["quoteCurrency"].isin(["USD","USDT"])] | |
symbols = df.name.values | |
select_consol_tf = st.sidebar.selectbox("Timeframe",["15s","1m","5m","15m","1h","4h","1d"]) | |
if select_consol_tf[-1] == "s": | |
timeframe = int(select_consol_tf[:-1]) | |
elif select_consol_tf[-1] == "m": | |
timeframe = int(select_consol_tf[:-1]) * 60 | |
elif select_consol_tf[-1] == "h": | |
timeframe = int(select_consol_tf[:-1])*60*60 | |
elif select_consol_tf[-1] == "d": | |
timeframe = int(select_consol_tf[:-1])* 60*60*24 | |
select_BB_mul = st.sidebar.text_input("Bollinger Band multiplier",value = "2") | |
select_KC_mul = st.sidebar.text_input("KC multiplier", value = "1.5") | |
select_num_days = st.sidebar.text_input("Consolidating before how many periods?",3) | |
num_days = int(select_num_days) | |
bb_mul = float(select_BB_mul) | |
kc_mul = float(select_KC_mul) | |
consol_run_btn = st.sidebar.button("Run") | |
if consol_run_btn: | |
# If user clicks on run button | |
# Again running in threads. | |
threads = [] | |
for symbol in symbols: | |
t = threading.Thread(target = in_squeeze, args = (symbol,bb_mul, kc_mul, num_days, True,60*60*24)) | |
add_report_ctx(t) | |
t.start() | |
threads.append(t) | |
for x in threads: | |
x.join() | |
st.sidebar.write("Task Complete") | |
elif option == "ETFs": | |
# If ETFs are selected | |
# Button to select ETF | |
selectETF = st.sidebar.selectbox("Select ETF class",etf.keys()) | |
today = datetime.now() - timedelta(days =80) | |
st.subheader(selectETF) | |
# Note Country ETFs are dealt differently as they have country names as well | |
if selectETF!= "Country": | |
# If ETF is not Country then its very easy just from ETF variable we can fetch it | |
etf_names = etf[selectETF].keys() | |
else: | |
# Select Markets, Country | |
selectMarket = st.sidebar.selectbox("Which Market?",etf[selectETF].keys()) | |
country_list = list(etf[selectETF][selectMarket].keys()) | |
etf_list = list(etf[selectETF][selectMarket].values()) | |
etf_names = [] | |
country_names = [] | |
# In a for loop fetch all the ETFs for selected entries | |
for i in range(len(etf_list)): | |
if type(etf_list[i])==str: | |
etf_names.append(etf_list[i]) | |
country_names.append(country_list[i]) | |
else: | |
for sub_etf_name in etf_list[i]: | |
etf_names.append(sub_etf_name) | |
country_names.append(country_list[i]) | |
select_timeframe = st.sidebar.selectbox("Which Timeframe?",["Daily","Weekly","Monthly"]) | |
timeframe_map = {"Daily":"d","Weekly":"w","Monthly":"m"} | |
etf_run_btn = st.sidebar.button("Run") | |
if etf_run_btn: | |
tf = timeframe_map[select_timeframe] | |
# If After giving all the entries, run button is clicked get the charts for all the ETFs | |
count = 0 | |
res_etf_ret = [] | |
thread_det = [] | |
vol_etf_info = {} | |
expense_ratios = {} | |
st.info("Loading..... Please Have Patience") | |
for n in etf_names: | |
thread = threading.Thread(target = get_etf_rets, args = (n,)) | |
thread.start() | |
thread_det.append(thread) | |
for x in thread_det: | |
x.join() | |
st.success("Finished Loading") | |
etf_rets_df = pd.DataFrame(res_etf_ret) | |
etf_rets_df.set_index("symbol",inplace=True) | |
col1,col2,col3,col4,col5 = st.columns([1,1,1,1,1]) | |
with col1: | |
# st.write("") | |
st.markdown("<h5 style='text-align: center; color: red;'>Daily Returns</h5>", unsafe_allow_html=True) | |
st.dataframe(etf_rets_df["day_ret"].sort_values(ascending=False)) | |
with col2: | |
st.markdown("<h5 style='text-align: center; color: red;'>1 Week Returns</h5>", unsafe_allow_html=True) | |
st.dataframe(etf_rets_df["w1_ret"].sort_values(ascending=False)) | |
with col3: | |
st.markdown("<h5 style='text-align: center; color: red;'>2 Week Returns</h5>", unsafe_allow_html=True) | |
st.dataframe(etf_rets_df["w2_ret"].sort_values(ascending=False)) | |
with col4: | |
st.markdown("<h5 style='text-align: center; color: red;'>1 Month Returns</h5>", unsafe_allow_html=True) | |
st.dataframe(etf_rets_df["m1_ret"].sort_values(ascending=False)) | |
with col5: | |
st.markdown("<h5 style='text-align: center; color: red;'>1 Year Returns</h5>", unsafe_allow_html=True) | |
st.dataframe(etf_rets_df["year_ret"].sort_values(ascending=False)) | |
st.dataframe(etf_rets_df) | |
cols1,cols2 = st.columns([1,1]) | |
if selectETF!= "Country": | |
for etf_name in etf_names: | |
num = count%2 | |
if num == 0: | |
with cols1: | |
try: | |
st.write(f"{etf[selectETF][etf_name]}, IV = {vol_etf_info[etf_name]}, ER = {expense_ratios[etf_name]}") | |
except: | |
pass | |
if tf == "d": | |
st.image(f"https://finviz.com/chart.ashx?t={etf_name}&ta=1&p={tf}") | |
else: | |
st.image(f"https://finviz.com/chart.ashx?t={etf_name}&p={tf}") | |
else: | |
with cols2: | |
try: | |
st.write(f"{etf[selectETF][etf_name]}, IV = {vol_etf_info[etf_name]}, ER = {expense_ratios[etf_name]}") | |
except: | |
pass | |
if tf == "d": | |
st.image(f"https://finviz.com/chart.ashx?t={etf_name}&ta=1&p={tf}") | |
else: | |
st.image(f"https://finviz.com/chart.ashx?t={etf_name}&p={tf}") | |
count = count + 1 | |
else: | |
for i in range(len(etf_names)): | |
try: | |
st.write(f"{country_names[i]}, IV = {vol_etf_info[etf_names[i]]}, ER = {expense_ratios[etf_names[i]]}") | |
except: | |
pass | |
if tf == "d": | |
st.image(f"https://finviz.com/chart.ashx?t={etf_names[i]}&ta=1&p={tf}") | |
else: | |
st.image(f"https://finviz.com/chart.ashx?t={etf_names[i]}&p={tf}") | |
elif option == "coinBaskets": | |
# If coinBaskets is selected | |
# Note, Mudrex was our reference here | |
baskets = st.sidebar.multiselect(label = "Baskets",options=names, default =names[0]) | |
run_basket = st.sidebar.button("Run") | |
select_crypto_timeframe = st.sidebar.selectbox("Crypto Timeframe", options = | |
["1d","1m","3m","5m","15m","30m","1h","2h","4h","6h","8h","12h","3d","1w","1M"]) | |
check_symbol = st.sidebar.text_input("Symbol check") | |
interval = select_crypto_timeframe | |
# Once all the inputs are given, and if any of the basket is chosen | |
if check_symbol != "": | |
for bkt in names: | |
# For each basket selected, get its components, fetch its price from Binance api | |
#Then plot all components in a single chart | |
#Here, you are giving in the symbol name and program is finding whether that symbol is there | |
# in any of the basket or not | |
if check_symbol in eval(bkt)["components"]: | |
fig_check = go.Figure() | |
st.write(bkt.upper()) | |
cols = st.columns(len(eval(bkt)["components"])) | |
for i in eval(bkt)["components"]: | |
ticker = f'{i.upper()}USDT' | |
req_params = dict(symbol = ticker, interval = interval) | |
url = "https://api.binance.com/api/v3/klines" | |
data = pd.DataFrame(json.loads(requests.get(url,params = req_params).text)) | |
data = data.iloc[:,0:5] | |
data.columns = ['datetime', 'open','high','low', 'close'] | |
data.index = [datetime.fromtimestamp(x/1000) for x in data.datetime] | |
data["close"] = data["close"].astype(float) | |
df = (data["close"].pct_change() + 1).cumprod() | |
fig_check.add_trace(go.Scatter(x=df.index, y=df.values, | |
mode='lines', | |
name=i)) | |
fig_check.update_xaxes( | |
rangeslider_visible=True, | |
nticks = 20, | |
spikemode = "toaxis", | |
rangeselector=dict( | |
buttons=list([ | |
dict(count=1, label="1mon", step="month", stepmode="backward"), | |
dict(count=6, label="6mon", step="month", stepmode="backward"), | |
dict(count=1, label="YTD", step="year", stepmode="todate"), | |
dict(count=1, label="1y", step="year", stepmode="backward"), | |
dict(step="all") | |
]) | |
) | |
) | |
fig_check.update_layout( | |
xaxis_tickformat = '%Y-%m-%d', | |
height = 600, | |
width = 900, | |
hovermode = "x" | |
) | |
fig_check.update_traces( | |
hovertemplate="<br>".join([ | |
"Price: %{y}" | |
])) | |
st.plotly_chart(fig_check) | |
if run_basket: | |
for basket in baskets: | |
# Here, you are choosing the baskets and program is plotting the baskets | |
st.write(basket.upper()) | |
st.table(eval(basket)) | |
# Create traces | |
fig = go.Figure() | |
for i in eval(basket)["components"]: | |
ticker = f'{i.upper()}USDT' | |
interval = select_crypto_timeframe | |
req_params = dict(symbol = ticker, interval = interval) | |
url = "https://api.binance.com/api/v3/klines" | |
data = pd.DataFrame(json.loads(requests.get(url,params = req_params).text)) | |
data = data.iloc[:,0:5] | |
data.columns = ['datetime', 'open','high','low', 'close'] | |
data.index = [datetime.fromtimestamp(x/1000) for x in data.datetime] | |
data["close"] = data["close"].astype(float) | |
df = (data["close"].pct_change() + 1).cumprod() | |
fig.add_trace(go.Scatter(x=df.index, y=df.values, | |
mode='lines', | |
name=i)) | |
fig.update_xaxes( | |
rangeslider_visible=True, | |
nticks = 20, | |
spikemode = "toaxis", | |
rangeselector=dict( | |
buttons=list([ | |
dict(count=1, label="1mon", step="month", stepmode="backward"), | |
dict(count=6, label="6mon", step="month", stepmode="backward"), | |
dict(count=1, label="YTD", step="year", stepmode="todate"), | |
dict(count=1, label="1y", step="year", stepmode="backward"), | |
dict(step="all") | |
]) | |
) | |
) | |
fig.update_layout( | |
xaxis_tickformat = '%Y-%m-%d', | |
height = 600, | |
width = 900, | |
hovermode = "x" | |
) | |
fig.update_traces( | |
hovertemplate="<br>".join([ | |
"Price: %{y}" | |
])) | |
st.plotly_chart(fig) | |
elif option == "Chart": | |
# Charting platform | |
# Get user inputs | |
symbols = st_tags_sidebar(label = "Choose the tickers", | |
text = 'Press enter to add more', maxtags = 100) | |
select_stock_timeframe = st.sidebar.selectbox("Stock Timeframe",options=["1Min", "5Min", "15Min", "day"]) | |
select_crypto_timeframe = st.sidebar.selectbox("Crypto Timeframe", options = | |
["1d","1m","3m","5m","15m","30m","1h","2h","4h","6h","8h","12h","3d","1w","1M"]) | |
select_periods = st.sidebar.text_input("Number of Days(Stock)",value = "30") | |
today = datetime.now() - timedelta(int(select_periods)) | |
if len(symbols)>0: | |
# If symbols are selected | |
for symbol in symbols: | |
# Run over all symbol in for loop and if they are crypto, treat them differently | |
#And if they are others, treat them differently | |
if f'{symbol.upper()}' in crypto_symbols: | |
# If crypto, get the data from Binance api | |
ticker = f'{symbol.upper()}USDT' | |
interval = select_crypto_timeframe | |
req_params = dict(symbol = ticker, interval = interval) | |
url = "https://api.binance.com/api/v3/klines" | |
st.subheader(ticker) | |
data = pd.DataFrame(json.loads(requests.get(url,params = req_params).text)) | |
data = data.iloc[:,0:5] | |
data.columns = ['datetime', 'open','high','low', 'close'] | |
data.index = [datetime.fromtimestamp(x/1000) for x in data.datetime] | |
data.drop("datetime",axis = 1, inplace = True) | |
else: | |
# If stocks then get it from trade_api | |
# Remember!!!--> trade_api was initiated in the session_state in the starting of code | |
data = st.session_state.trade_api.get_barset(symbol.upper(), select_stock_timeframe, start =today.strftime("%Y-%m-%d")).df | |
data = data[symbol.upper()] | |
st.subheader(symbol.upper()) | |
fig = plot_candlestick(data) | |
st.plotly_chart(fig, use_container_width=False) | |
elif option == "stocktwits": | |
# If stocktwits is selected | |
# This is almost similar to Larry's video, so you can reference that as well | |
# Display Trending stocks based on watchlist count | |
st.header("Most Trending Symbols") | |
most_trending_syms = get_stocktwits_data(req = "https://api.stocktwits.com/api/2/charts/ts", | |
code = "ts", label = "Trending Score") | |
st.dataframe(most_trending_syms) | |
st.header("Most messages in last 24 hrs") | |
most_active_syms = get_stocktwits_data(req = "https://api.stocktwits.com/api/2/charts/m_day", | |
code = "m_day", label = "#messages") | |
st.dataframe(most_active_syms) | |
st.header("Top New Watchers added in last 24 hrs") | |
most_active_syms = get_stocktwits_data(req = "https://api.stocktwits.com/api/2/charts/wl_ct_day", | |
code = "wl_ct_day", label = "Count") | |
st.dataframe(most_active_syms) | |
# For a given symbol, use request module to hit the stocktwits api and get the required info | |
symbol = st.sidebar.text_input("Symbol", value = "AAPL", max_chars = 5) | |
r = requests.get(f"https://api.stocktwits.com/api/2/streams/symbol/{symbol}.json") | |
data = r.json() | |
for message in data["messages"]: | |
st.image(message["user"]["avatar_url"]) | |
st.write(message['user']["username"]) | |
st.write(message["created_at"]) | |
st.write(message["body"]) | |
st.sidebar.write("Update time for -->") | |
st.sidebar.write("Top Watchlist Counts : 5mins") | |
st.sidebar.write("Most Messages : 1hr") | |
elif option == "Technical Scanner": | |
# If technical scanner is selected | |
# Then choose the pattern, timeframe, etc | |
pattern = st.sidebar.selectbox("Which Pattern?", tuple(patterns.values())) | |
keywords = st_tags_sidebar(label = "Choose the tickers", | |
text = 'Press enter to add more', maxtags = 100) | |
select_timeframe = st.sidebar.selectbox("Timeframe",options=["1Min", "5Min", "15Min", "day"]) | |
run_btn = st.sidebar.button("Run") | |
# Get the mapping for patterns from pattern.py file | |
pattern_code = get_key(patterns, pattern) | |
pattern_function = getattr(talib,pattern_code) | |
if run_btn: | |
# If clicked on run button | |
# Then for each symbol, check the output | |
keyword = [x.upper() for x in keywords] | |
data = st.session_state.trade_api.get_barset(keyword, select_timeframe, limit = 100).df | |
for symbol in keyword: | |
try: | |
# st.write(data) | |
result = pattern_function(data[symbol]["open"],data[symbol]["high"],data[symbol]["low"],data[symbol]["close"]) | |
last = result.tail(1).values[0] | |
# For some of the indicators value <0 is Bearish and value>0 is Bullish | |
# But for others there would be a different logic, you shall handle it differently | |
if last>0: | |
st.write(f"Bullish {symbol}") | |
elif last<0: | |
st.write(f"Bearish {symbol}") | |
except: | |
pass |