Spaces:
Paused
Paused
import streamlit as st | |
import pandas as pd | |
import yfinance as yf | |
from yahoo_fin import options | |
import pandas_ta as ta | |
from datetime import datetime, timedelta | |
import requests | |
import json | |
from transformers import pipeline | |
def get_option_stats(ticker): | |
option_expiry_dates = options.get_expiration_dates(ticker) | |
nearest_expiry = option_expiry_dates[0] | |
call_df = options.get_calls(ticker, nearest_expiry) | |
put_df = options.get_puts(ticker, nearest_expiry) | |
avg_call_iv = call_df["Implied Volatility"].str.rstrip("%").astype(float).mean() | |
avg_put_iv = put_df["Implied Volatility"].str.rstrip("%").astype(float).mean() | |
avg_call_last_price = call_df["Last Price"].mean() | |
avg_put_last_price = put_df["Last Price"].mean() | |
min_call_strike = call_df["Strike"].min() | |
max_call_strike = call_df["Strike"].max() | |
min_put_strike = put_df["Strike"].min() | |
max_put_strike = put_df["Strike"].max() | |
total_call_volume = call_df["Volume"].astype(str).str.replace('-', '0').astype(float).sum() | |
total_put_volume = put_df["Volume"].astype(str).str.replace('-', '0').astype(float).sum() | |
total_call_open_interest = call_df["Open Interest"].astype(str).str.replace('-', '0').astype(float).sum() | |
total_put_open_interest = put_df["Open Interest"].astype(str).str.replace('-', '0').astype(float).sum() | |
put_call_ratio = total_put_volume / total_call_volume if total_call_volume > 0 else 0 | |
call_iv_percentile = (call_df['Implied Volatility'].str.rstrip('%').astype(float) > avg_call_iv).mean() * 100 | |
put_iv_percentile = (put_df['Implied Volatility'].str.rstrip('%').astype(float) > avg_put_iv).mean() * 100 | |
iv_skew = avg_call_iv - avg_put_iv | |
option_stats = { | |
'Avg Call IV': avg_call_iv, | |
'Avg Put IV': avg_put_iv, | |
'Avg Call Last Price (in dollars)': avg_call_last_price, | |
'Avg Put Last Price (in dollars)': avg_put_last_price, | |
'Min Call Strike': min_call_strike, | |
'Max Call Strike': max_call_strike, | |
'Min Put Strike': min_put_strike, | |
'Max Put Strike': max_put_strike, | |
'Total Call Volume': total_call_volume, | |
'Total Put Volume': total_put_volume, | |
'Total Call Open Interest': total_call_open_interest, | |
'Total Put Open Interest': total_put_open_interest, | |
'Put/Call Ratio': put_call_ratio, | |
'Call IV Percentile': call_iv_percentile, | |
'Put IV Percentile': put_iv_percentile, | |
'IV Skew': iv_skew | |
} | |
return option_stats | |
def get_technical_indicators(ticker): | |
end_date = datetime.today() | |
start_date = end_date - timedelta(days=400) | |
stock_data = yf.download(ticker, start=start_date, end=end_date) | |
stock_data.ta.macd(append=True) | |
stock_data.ta.rsi(append=True) | |
stock_data.ta.bbands(append=True) | |
stock_data.ta.obv(append=True) | |
stock_data.ta.sma(length=20, append=True) | |
stock_data.ta.sma(length=50, append=True) | |
stock_data.ta.sma(length=200, append=True) | |
stock_data.ta.ema(length=50, append=True) | |
stock_data.ta.stoch(append=True) | |
stock_data.ta.adx(append=True) | |
stock_data.ta.willr(append=True) | |
stock_data.ta.cmf(append=True) | |
stock_data.ta.psar(append=True) | |
stock_data.ta.mfi(append=True) | |
stock_data.ta.roc(append=True) | |
stock_data.ta.trix(length=14, append=True) | |
stock_data.ta.cci(length=14, append=True) | |
stock_data['PP'] = (stock_data['High'] + stock_data['Low'] + stock_data['Close']) / 3 | |
stock_data['R1'] = (2 * stock_data['PP']) - stock_data['Low'] | |
stock_data['S1'] = (2 * stock_data['PP']) - stock_data['High'] | |
stock_data['OBV_in_million'] = stock_data['OBV'] / 1e6 | |
last_day_summary = stock_data.iloc[-1] | |
technical_indicators = { | |
'Open': last_day_summary['Open'], | |
'High': last_day_summary['High'], | |
'Low': last_day_summary['Low'], | |
'Close': last_day_summary['Close'], | |
'Adj Close': last_day_summary['Adj Close'], | |
'Volume': last_day_summary['Volume'], | |
'MACD_12_26_9': last_day_summary['MACD_12_26_9'], | |
'MACDh_12_26_9': last_day_summary['MACDh_12_26_9'], | |
'MACDs_12_26_9': last_day_summary['MACDs_12_26_9'], | |
'RSI_14': last_day_summary['RSI_14'], | |
'BBL_5_2.0': last_day_summary['BBL_5_2.0'], | |
'BBM_5_2.0': last_day_summary['BBM_5_2.0'], | |
'BBU_5_2.0': last_day_summary['BBU_5_2.0'], | |
'BBB_5_2.0': last_day_summary['BBB_5_2.0'], | |
'BBP_5_2.0': last_day_summary['BBP_5_2.0'], | |
'OBV': last_day_summary['OBV'], | |
'SMA_20': last_day_summary['SMA_20'], | |
'SMA_50': last_day_summary['SMA_50'], | |
'SMA_200': last_day_summary['SMA_200'], | |
'EMA_50': last_day_summary['EMA_50'], | |
'STOCHk_14_3_3': last_day_summary['STOCHk_14_3_3'], | |
'STOCHd_14_3_3': last_day_summary['STOCHd_14_3_3'], | |
'ADX_14': last_day_summary['ADX_14'], | |
'DMP_14': last_day_summary['DMP_14'], | |
'DMN_14': last_day_summary['DMN_14'], | |
'WILLR_14': last_day_summary['WILLR_14'], | |
'CMF_20': last_day_summary['CMF_20'], | |
'PSARl_0.02_0.2': last_day_summary['PSARl_0.02_0.2'], | |
'PSARs_0.02_0.2': last_day_summary['PSARs_0.02_0.2'], | |
'PSARaf_0.02_0.2': last_day_summary['PSARaf_0.02_0.2'], | |
'PSARr_0.02_0.2': last_day_summary['PSARr_0.02_0.2'], | |
'MFI_14': last_day_summary['MFI_14'], | |
'ROC_10': last_day_summary['ROC_10'], | |
'TRIX_14_9': last_day_summary['TRIX_14_9'], | |
'TRIXs_14_9': last_day_summary['TRIXs_14_9'], | |
'CCI_14_0.015': last_day_summary['CCI_14_0.015'], | |
'PP': last_day_summary['PP'], | |
'R1': last_day_summary['R1'], | |
'S1': last_day_summary['S1'], | |
'OBV_in_million': last_day_summary['OBV_in_million'] | |
} | |
return technical_indicators | |
def prompt_generator(ticker, option_stats, last_day_summary): | |
output_str = (f"Data for {ticker}...") | |
output_str += """Assume the role as a seasoned stock option analyst with a strong track record in dissecting intricate option data to discern valuable insights into stock sentiment. Proficient in utilizing advanced statistical models and data visualization techniques to forecast market trends and make informed trading decisions. Adept at interpreting option Greeks, implied volatility, and analyzing trading volumes to gauge investor sentiment accurately. Known for an exceptional ability to transform complex data into actionable trading strategies, consistently achieving optimal results for portfolio growth. Suggest an action such as buying options or puts or do nothing. Share you conviction from 1 to 10, 10 being high \n""" | |
option_stats_str = ( | |
f"Options Statistics for {ticker}:\n" | |
f"Average Implied Volatility for Call Options: {option_stats['Avg Call IV']:.2f}%\n" | |
f"Average Implied Volatility for Put Options: {option_stats['Avg Put IV']:.2f}%\n" | |
f"Average Last Price for Call Options (in dollars): {option_stats['Avg Call Last Price (in dollars)']:.2f}\n" | |
f"Average Last Price for Put Options (in dollars): {option_stats['Avg Put Last Price (in dollars)']:.2f}\n" | |
f"Minimum Strike Price for Call Options: {option_stats['Min Call Strike']}\n" | |
f"Maximum Strike Price for Call Options: {option_stats['Max Call Strike']}\n" | |
f"Minimum Strike Price for Put Options: {option_stats['Min Put Strike']}\n" | |
f"Maximum Strike Price for Put Options: {option_stats['Max Put Strike']}\n" | |
f"Total Volume for Call Options: {option_stats['Total Call Volume']:.0f}\n" | |
f"Total Volume for Put Options: {option_stats['Total Put Volume']:.0f}\n" | |
f"Total Open Interest for Call Options: {option_stats['Total Call Open Interest']:.0f}\n" | |
f"Total Open Interest for Put Options: {option_stats['Total Put Open Interest']:.0f}\n" | |
f"Put-Call Ratio: {option_stats['Put/Call Ratio']:.2f}\n" | |
f"Call Option Implied Volatility Percentile: {option_stats['Call IV Percentile']:.2f}\n" | |
f"Put Option Implied Volatility Percentile: {option_stats['Put IV Percentile']:.2f}\n" | |
f"Implied Volatility Skew: {option_stats['IV Skew']:.2f}\n" | |
) | |
tech_indicators_str = f"Technical Indicators for {ticker}:\n" | |
for key, value in last_day_summary.items(): | |
if abs(value) >= 1e6: | |
tech_indicators_str += f"{key}: {value:.2e}\n" | |
elif isinstance(value, float): | |
tech_indicators_str += f"{key}: {value:.2f}\n" | |
else: | |
tech_indicators_str += f"{key}: {value}\n" | |
output_str += "\n" + option_stats_str + "\n" + tech_indicators_str | |
return output_str | |
model_name = "Rahulholla/mistral-stock-model" | |
model = pipeline("text-generation", model=model_name, device_map="auto") | |
def send_prompt_to_api(prompt): | |
try: | |
generated_text = model(prompt, max_new_tokens=2048)[0]["generated_text"] | |
return {"success": True, "text": generated_text} | |
except Exception as e: | |
return {"success": False, "error_message": str(e)} | |
st.title('Stock Tracker, Analysis and Results (S.T.A.R)') | |
sp500_tickers = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')[0] | |
sp500_companies = sp500_tickers['Symbol'].tolist() | |
selected_company = st.selectbox('Select a company', sp500_companies) | |
ticker_symbol = yf.Ticker(selected_company) | |
disclaimer = "The investments and services offered by us may not be suitable for all investors. No guarantee can be offered that projections or estimates will actually occur. Actual results may be materially different from projections or estimates. If you have any doubts as to the merits of an investment, you should seek advice from an independent financial advisor." | |
if st.button("Analyze"): | |
with st.spinner('Analyzing...'): | |
try: | |
option_stats = get_option_stats(selected_company) | |
option_stats_df = pd.DataFrame(option_stats, index=[0]) | |
option_stats_df_transposed = option_stats_df.T.reset_index() | |
option_stats_df_transposed.columns = ['Indicator', 'Value'] | |
st.write('Option Statistics for', selected_company) | |
st.table(option_stats_df_transposed) | |
technical_indicators = get_technical_indicators(selected_company) | |
tech_indicators_df = pd.DataFrame(technical_indicators, index=[0]) | |
tech_indicators_df_transposed = tech_indicators_df.T.reset_index() | |
tech_indicators_df_transposed.columns = ['Indicator', 'Value'] | |
st.write('Technical Indicators for', selected_company) | |
st.table(tech_indicators_df_transposed) | |
except Exception as e: | |
st.error(f'Error while fetching stock stats due to {e}') | |
with st.spinner('Predicting...'): | |
prompt_generated = prompt_generator(selected_company, option_stats, technical_indicators) | |
start_time = datetime.now() | |
response = send_prompt_to_api(prompt_generated) | |
end_time = datetime.now() | |
if response["success"]: | |
try: | |
st.write("Raw response") | |
st.write(response) | |
st.write("----------------------------------------------------") | |
st.write("Below is the generate text") | |
generated_text = response["text"] | |
st.write("Our evaluation:") | |
st.write(generated_text) | |
st.markdown("### Disclaimer:") | |
st.write(disclaimer) | |
training_duration = end_time - start_time | |
st.write(f"Prompt generation started at : {start_time} and Prompt generation ended at : {end_time} and Total prompt generation duration : {training_duration}") | |
except Exception as e: | |
st.error(f"Error: Failed due to {e}") | |
else: | |
st.error(f"Error: {response['error_message']}") | |