streamlit st.columns to show live stock data - python

Problem statement:
I need multiple columns in streamlit to categorize different stocks and show their current live value.
I have 2 dummy columns as shown below (in the code) to track live values but the problem is instead of overwriting the current ticker value, it starts to append the column and write new values below the existing one.
import streamlit as st
import yfinance as yf
st.set_page_config(page_title="Test", layout='wide')
tech_list = ['btc-usd', 'eth-usd']
etf_list = ['etc-usd']
(tech_ticker, tech_price, etf_ticker, etf_price, crypto_ticker, crypto_price,
finance_ticker, finance_price, transport_ticker, transport_price) = st.columns(10, gap='small')
with tech_ticker:
for index, val in enumerate(tech_list):
st.write(val)
with etf_ticker:
for index, val in enumerate(etf_list):
st.write(val)
while True:
with tech_price:
number1 = st.empty()
with number1.container():
for index, val in enumerate(tech_list):
stock = yf.Ticker(val)
price = stock.info['regularMarketPrice']
st.write(": ", round(price, 1))
with etf_price:
number2 = st.empty()
with number2.container():
for index, val in enumerate(etf_list):
stock = yf.Ticker(val)
price = stock.info['regularMarketPrice']
st.write(": ", round(price, 1))

Put all the columns to an empty container:
import streamlit as st
import yfinance as yf
st.set_page_config(page_title="Test", layout='wide')
tech_list = ['btc-usd', 'eth-usd']
etf_list = ['etc-usd']
with st.empty():
while True:
(tech_ticker, tech_price, etf_ticker, etf_price, crypto_ticker,
crypto_price, finance_ticker, finance_price, transport_ticker,
transport_price) = st.columns(10, gap='small')
with tech_ticker:
for index, val in enumerate(tech_list):
st.write(val)
with etf_ticker:
for index, val in enumerate(etf_list):
st.write(val)
with tech_price:
for index, val in enumerate(tech_list):
stock = yf.Ticker(val)
price = stock.info['regularMarketPrice']
st.write(": ", round(price, 1))
with etf_price:
for index, val in enumerate(etf_list):
stock = yf.Ticker(val)
price = stock.info['regularMarketPrice']
st.write(": ", round(price, 1))

Define the holder outside the infinite loop.
# with etf_ticker:
# for index, val in enumerate(etf_list):
# st.write(val)
# Define holders.
with tech_price:
number1 = st.empty()
with etf_price:
number2 = st.empty()
# Update data - infinite loop
while True:
with number1.container():
for index, val in enumerate(tech_list):
stock = yf.Ticker(val)
price = stock.info['regularMarketPrice']
st.write(": ", round(price, 1))
with number2.container():
for index, val in enumerate(etf_list):
stock = yf.Ticker(val)
price = stock.info['regularMarketPrice']
st.write(": ", round(price, 1))
Output

Related

KeyError: 'Close', I think I deleted a key for my dictionary! Algo Trading

When I run the first two functions, CARG and Volatility, they work fine! When I run Sharpe, it runs into problems! I think I deleted a key in my dictionary somehow, it refers back to my CAGR function and point to the second line in there, saying KeyError: 'Close'. The return error info is at the very bottom
import yfinance as yf
import numpy as np
import pandas as pd
tickers = ["AAPL","AMC","SPY","BBBY"]
ohlcv_data = {}
for ticker in tickers:
temp = yf.download(ticker, period="7mo", interval="1d")
temp.dropna(how="any", inplace=True)
ohlcv_data[ticker] = temp
def CAGR(DF):
df = DF.copy()
df["return"] = DF["Close"].pct_change()
df["cum_return"] = (1+df["return"]).cumprod()
n = len(df)/252
CAGR = (df["cum_return"][-1])**(1/n) - 1
return CAGR
for ticker in ohlcv_data:
print("GAGR for {} = {}".format(ticker, CAGR(ohlcv_data[ticker])))
def Volatility(DF):
df = DF.copy()
df["return"] = DF["Close"].pct_change()
vol = df["return"].std() * np.sqrt(252)
return vol
for ticker in ohlcv_data:
print("Volatility of {} = {}".format(ticker, Volatility(ohlcv_data[ticker])))
def Sharpe(DF, rf=0.03):
df = DF.copy()
return (CAGR(df)- rf)/Volatility(df)
for ticker in ohlcv_data:
print("Sharpe for {} = {}".format(ticker, Sharpe(ohlcv_data, 0.03)))
def Sortino(DF, rf=0.03):
df= DF.copy()
df["return"] = df["Close"].pct_change()
neg_return = np.where(df["return"]>0,0,df["return"])
neg_vol = pd.Series(neg_return[neg_return!=0]).std()
return (CAGR(df)- rf)/neg_vol
for ticker in ohlcv_data:
print("Sortino for {} = {}".format(ticker, Sortino(ohlcv_data, 0.03)))
File "c:\users\cryst\onedrive\documents\algotradingcode\untitled11.py", line 56, in <module>
print("Sharpe for {} = {}".format(ticker, Sharpe(ohlcv_data, 0.03)))
File "c:\users\cryst\onedrive\documents\algotradingcode\untitled11.py", line 53, in Sharpe
return (CAGR(df)- rf)/Volatility(df)
File "c:\users\cryst\onedrive\documents\algotradingcode\untitled11.py", line 26, in CAGR
df["return"] = DF["Close"].pct_change()
KeyError: 'Close'
I see the same mistake when you run Sharpe() and Sortino()
You send ohlcv_data but you have to send ohlcv_data[ticker]
Funny is you have it correctly when you run CAGR() and Volatility()
Sharpe(ohlcv_data[ticker], 0.03)
Sortino(ohlcv_data[ticker], 0.03)
CAGR(ohlcv_data[ticker])
Volatility(ohlcv_data[ticker])
Eventually you should use .items() to make it more readable
for ticker, data in ohlcv_data.items():
result = Sharpe(data, 0.03)
# result = Sortino(data, 0.03)
# result = CAGR(data)
# result = Volatility(data)
Full working code with:
import yfinance as yf
import numpy as np
import pandas as pd
# --- functions --- # PEP8: all functions before main code
def CAGR(DF):
df = DF.copy()
df["return"] = df["Close"].pct_change()
df["cum_return"] = (1+df["return"]).cumprod()
n = len(df)/252
CAGR = (df["cum_return"][-1])**(1/n) - 1
return CAGR
def Volatility(DF):
df = DF.copy()
df["return"] = df["Close"].pct_change()
vol = df["return"].std() * np.sqrt(252)
return vol
def Sharpe(DF, rf=0.03):
df = DF.copy()
return (CAGR(df)- rf)/Volatility(df)
def Sortino(DF, rf=0.03):
df = DF.copy()
df["return"] = df["Close"].pct_change()
neg_return = np.where(df["return"]>0,0,df["return"])
neg_vol = pd.Series(neg_return[neg_return!=0]).std()
return (CAGR(df)- rf)/neg_vol
# --- main ---
tickers = ["AAPL","AMC","SPY","BBBY"]
ohlcv_data = {}
for ticker in tickers:
data = yf.download(ticker, period="7mo", interval="1d")
data.dropna(how="any", inplace=True)
ohlcv_data[ticker] = data
for ticker, data in ohlcv_data.items():
result = CAGR(data)
print(f"GAGR for {ticker} = {result}")
for ticker, data in ohlcv_data.items():
result = Volatility(data)
print(f"Volatility of {ticker} = {result}")
for ticker, data in ohlcv_data.items():
result = Sharpe(data, 0.03)
print(f"Sharpe for {ticker} = {result}")
for ticker, data in ohlcv_data.items():
result = Sortino(data, 0.03)
print(f"Sortino for {ticker} = {result}")
Result:
GAGR for AAPL = 0.11355213703707379
GAGR for AMC = -0.5829820257957625
GAGR for SPY = -0.05423536518372174
GAGR for BBBY = -0.4389927079102395
Volatility of AAPL = 0.3471946896720913
Volatility of AMC = 1.3227122428032356
Volatility of SPY = 0.24545485475277398
Volatility of BBBY = 1.5613839405009773
Sharpe for AAPL = 0.24064923664582766
Sharpe for AMC = -0.4634281032257359
Sharpe for SPY = -0.3431806849718452
Sharpe for BBBY = -0.30036988068403025
Sortino for AAPL = 5.847323456223871
Sortino for AMC = -11.478142948375877
Sortino for SPY = -8.132265719790464
Sortino for BBBY = -7.791889967534535
PEP 8 -- Style Guide for Python Code

List index out of range error when using Pandas and Yahoo_fin

This is a modified version of a program from a tutorial that extracts data from all of the stocks in the S&P 500 and picks stocks that match the criteria you specify.
The issue is that when I run the program List index out of range [stock symbol] pops up and those stocks are skipped and aren't added to the final CSV file.
Example:
list index out of range for ABMD
list index out of range for ABT
list index out of range for ADBE
list index out of range for ADI
I'm not really sure what the issue is, I would greatly appreciate it if someone would explain it to me! Also, I am not applying any of the specifying criteria yet and am just trying to get all of the stock data into the CSV file. Make sure to create a database named stock_data if you try the program. Thanks!
My code:
import pandas_datareader as web
import pandas as pd
from yahoo_fin import stock_info as si
import datetime as dt
dow_list = si.tickers_dow()
sp_list = si.tickers_sp500()
tickers = sp_list
'''tickers = list(set(tickers))
tickers.sort()'''
start = dt.datetime.now() - dt.timedelta(days=365)
end = dt.datetime.now()
sp500_df = web.DataReader('^GSPC', 'yahoo', start, end)
sp500_df['Pct Change'] = sp500_df['Adj Close'].pct_change()
sp500_return = (sp500_df['Pct Change'] + 1).cumprod()[-1]
return_list = []
final_df = pd.DataFrame(columns=['Ticker', 'Latest_Price', 'Score', 'PE_Ratio', 'PEG_Ratio', 'SMA_150', 'SMA_200', '52_Week_Low', '52_Week_High'])
counter = 0
for ticker in tickers:
df = web.DataReader(ticker, 'yahoo', start, end)
df.to_csv(f'stock_data/{ticker}.csv')
df['Pct Change'] = df['Adj Close'].pct_change()
stock_return = (df['Pct Change'] + 1).cumprod()[-1]
returns_compared = round((stock_return / sp500_return), 2)
return_list.append(returns_compared)
counter += 1
if counter == 100:
break
best_performers = pd.DataFrame(list(zip(tickers, return_list)), columns=['Ticker', 'Returns Compared'])
best_performers['Score'] = best_performers['Returns Compared'].rank(pct=True) * 100
best_performers = best_performers[best_performers['Score'] >= best_performers['Score'].quantile(0)] #picks stocks in top 25 percentile
for ticker in best_performers['Ticker']:
try:
df = pd.read_csv(f'stock_data/{ticker}.csv', index_col=0)
moving_averages = [150, 200]
for ma in moving_averages:
df['SMA_' + str(ma)] = round(df['Adj Close'].rolling(window=ma).mean(), 2)
latest_price = df['Adj Close'][-1]
pe_ratio = float(si.get_quote_table(ticker)['PE Ratio (TTM)'])
peg_ratio = float(si.get_stats_valuation(ticker)[1][4])
moving_average_150 = df['SMA_150'][-1]
moving_average_200 = df['SMA_200'][-1]
low_52week = round(min(df['Low'][-(52*5):]), 2)
high_52week = round(min(df['High'][-(52 * 5):]), 2)
score = round(best_performers[best_performers['Ticker'] == ticker]['Score'].tolist()[0])
condition_1 = latest_price > moving_average_150 > moving_average_200
condition_2 = latest_price >= (1.3 * low_52week)
condition_3 = latest_price >= (0.75 * high_52week)
condition_4 = pe_ratio < 25
condition_5 = peg_ratio < 2
final_df = final_df.append({'Ticker': ticker,
'Latest_Price': latest_price,
'Score': score,
'PE_Ratio': pe_ratio,
'PEG_Ratio': peg_ratio,
'SMA_150': moving_average_150,
'SMA_200': moving_average_200,
'52_Week_Low': low_52week,
'52_Week_High': high_52week}, ignore_index=True)
except Exception as e:
print(f"{e} for {ticker}")
final_df.sort_values(by='Score', ascending=False)
pd.set_option('display.max_columns', 10)
print(final_df)
final_df.to_csv('final.csv')
I have done the error shooting on your behalf. As a conclusion, I see that you have not checked the contents of the acquisition of the individual indicator data.
They are being added to the dictionary format and empty data frames as they are in index and named series. I believe that is the root cause of the error.
Specifying the last data and retrieving the values
iloc is not used.
52*5 lookbacks for 253 data
In addition, when additional indicators are acquired for the acquired issue data, there are cases where they can be acquired for the same issue, and cases where they cannot. (The cause is unknown.) Therefore, it may be necessary to change the method of processing pe_ratio and peg_ratio after obtaining them in advance.
for ticker in best_performers['Ticker']:
#print(ticker)
try:
df = pd.read_csv(f'stock_data/{ticker}.csv')#, index_col=0
moving_averages = [150, 200]
for ma in moving_averages:
df['SMA_' + str(ma)] = round(df['Adj Close'].rolling(window=ma).mean(), 2)
latest_price = df['Adj Close'][-1:].values[0]
pe_ratio = float(si.get_quote_table(ticker)['PE Ratio (TTM)'])
moving_average_150 = df['SMA_150'][-1:].values[0]
moving_average_200 = df['SMA_200'][-1:].values[0]
low_52week = round(min(df['Low'][-(52*1):]), 2)
high_52week = round(min(df['High'][-(52*1):]), 2)
#print(low_52week, high_52week)
score = round(best_performers[best_performers['Ticker'] == ticker]['Score'].tolist()[0])
#print(score)
#print(ticker, latest_price,score,pe_ratio,moving_average_200,low_52week,high_52week)
final_df = final_df.append({'Ticker': ticker,
'Latest_Price': latest_price,
'Score': score,
'PE_Ratio': pe_ratio,
'SMA_150': moving_average_150,
'SMA_200': moving_average_200,
'52_Week_Low': low_52week,
'52_Week_High': high_52week}, ignore_index=True)
#print(final_df)
except Exception as e:
print(f"{e} for {ticker}")
final_df
Ticker Latest_Price Score PE_Ratio SMA_150 SMA_200 52_Week_Low 52_Week_High
0 A 123.839996 40 31.42 147.26 150.31 123.06 126.75
1 AAP 218.250000 70 22.23 220.66 216.64 190.79 202.04
2 AAPL 165.070007 80 29.42 161.85 158.24 150.10 154.12
3 ABC 161.899994 90 21.91 132.94 129.33 132.00 137.79
4 ADBE 425.470001 10 42.46 552.19 571.99 407.94 422.38
Note
Some stocks are missing because additional indicators could not be obtained.
(tickers = sp_list[:10] tested on the first 10)

How to get alternating trading signals?

I am trying to develop a simple RSI strategy by using this code. As you can see by plotting the code, there are too many consecutive sell signals. I'd like there were buy signals followed by a SINGLE sell signal and, after that, another buy signal in order to have, at the end, something like buy, sell, buy, sell... and not something like buy, sell, sell, sell, sell, buy, sell, sell... Here you are the code:
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import datetime as dt
import ta
start = dt.datetime(2020, 1, 1)
df = yf.download("^GSPC", start)
portfolio = 10000
df['rsi'] = ta.momentum.rsi(df.Close, window=10)
df['200ma'] = df.Close.rolling(200).mean()
df.dropna(inplace=True)
buy, sell = [], []
for i in range(1, len(df)):
if df.Close.iloc[i] > df['200ma'].iloc[i]:
if df['rsi'].iloc[i] < 30:
buy.append(i)
elif df['rsi'].iloc[i] > 40 or ((df['rsi'].iloc[i] - df.Close.iloc[i]) > 10):
sell.append(i)
realbuys = [i+1 for i in buy]
realsells = [i+1 for i in sell]
buyprices = df.Open.iloc[realbuys]
sellprices = df.Open.iloc[realsells]
# plt.figure(figsize = (12, 6))
# plt.scatter(df.iloc[buy].index, df.iloc[buy].Close, marker = "^", color = "green" )
# plt.scatter(df.iloc[sell].index, df.iloc[sell].Close, marker = "v", color = "red" )
# plt.plot(df.Close, label = "S&P", color='k')
# plt.legend()
# plt.show()
pnl = []
for i in range(len(sellprices)):
pnl.append(((sellprices[i] - buyprices[i])/buyprices[i]))
portfolio = portfolio + (portfolio * pnl[i])
averagepnl = sum(pnl) / len(pnl)
print(portfolio, averagepnl)
So. A variable 'order' has been created, in which we record the current transaction. As you will notice, the entry into the transaction occurs only in the opposite direction. For example, if you bought it now, then the next transaction will only be a sale. Or any transaction, if it's the first one.
In the portfolio, I purposefully reduced the cycle by one element. Since buying and selling transactions are not the same. That is, the current sale is not closed.
import yfinance as yf
import matplotlib.pyplot as plt
import datetime as dt
import ta
start = dt.datetime(2020, 1, 1)
df = yf.download("^GSPC", start)
portfolio = 10000
df['rsi'] = ta.momentum.rsi(df.Close, window=10)
df['200ma'] = df.Close.rolling(200).mean()
df.dropna(inplace=True)
buy, sell = [], []
order = ''
for i in range(1, len(df)):
if df.Close.iloc[i] > df['200ma'].iloc[i]:
if df['rsi'].iloc[i] < 30:
if order == 'sell' or order == '':
buy.append(i)
order = 'buy'
elif df['rsi'].iloc[i] > 40 or ((df['rsi'].iloc[i] - df.Close.iloc[i]) > 10):
if order == 'buy' or order == '':
sell.append(i)
order = 'sell'
realbuys = [i + 1 for i in buy]
realsells = [i + 1 for i in sell]
buyprices = df.Open.iloc[realbuys]
sellprices = df.Open.iloc[realsells]
plt.figure(figsize = (12, 6))
plt.scatter(df.iloc[buy].index, df.iloc[buy].Close, marker = "^", color = "green" )
plt.scatter(df.iloc[sell].index, df.iloc[sell].Close, marker = "v", color = "red" )
plt.plot(df.Close, label = "S&P", color='k')
plt.legend()
plt.show()
pnl = []
for i in range(len(sellprices)-1):
pnl.append(((sellprices[i] - buyprices[i]) / buyprices[i]))
portfolio = portfolio + (portfolio * pnl[i])
averagepnl = sum(pnl) / len(pnl)
print(portfolio, averagepnl)

KeyError for column that exits in dataframe

This works if I remove the schedule but if i leave it in i receive a key error for 'Symbol'
def tweet_and_archive(sl):
ticker_l = []
name_l = []
price_l = []
price_out_l = []
date_time = []
for index, row in sl.iterrows():
Stock = row['Symbol']
Price = row['Price']
Price_out = row['Price Out']
name_ = row['Name']
Date_ = row['DateTime']
if ...
schedule.every().monday.at('12:31').do(lambda: tweet_and_archive(short_list))
while True:
schedule.run_pending()
time.sleep(1)
This is the short_list dataframe:
Symbol Name Price % Change Price Out DateTime
0 ANGPY Anglo American Platinum Limited 25.82 7.14 NaN 28/02/2022

Pandas how to search one df for a certain date and return that data

I have two data frames and I am trying to search each row by date in the user.csv file and find the corresponding date in the Raven.csv file and then return the Price from the df1 and the date and amount from df2.
This is working but my Price is returning a value like this [[0.11465]], is there a way to remove these brackets or a better way to do this?
import pandas as pd
df1 = pd.read_csv('Raven.csv',)
df2 = pd.read_csv('User.csv')
df1 = df1.reset_index(drop=False)
df1.columns = ['index', 'Date', 'Price']
df2['Timestamp'] = pd.to_datetime(df2['Timestamp'], format="%Y-%m-%d %H:%M:%S").dt.date
df1['Date'] = pd.to_datetime(df1['Date'], format="%Y-%m-%d").dt.date
Looper = 0
Date = []
Price = []
amount = []
total_value = []
for x in df2['Timestamp']:
search = df2['Timestamp'].values[Looper]
Date.append(search)
price =(df1.loc[df1['Date'] == search,['index']] )
value = df1['Price'].values[price]
Price.append(value)
payout = df2['Amount'].values[Looper]
amount.append(payout)
payout_value = value * payout
total_value.append(payout_value)
Looper = Looper + 1
dict = {'Date': Date, 'Price': Price, 'Payout': amount, "Total Value": total_value}
df = pd.DataFrame(dict)
df.to_csv('out.csv')
You can do indexing to get the value:
value = [[0.11465]][0][0]
print(value)
You get:
0.11465
I hope this is what you need.

Categories