File size: 11,901 Bytes
24dc7cc
 
 
 
 
 
 
109d294
9b90e49
24dc7cc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b90e49
 
 
 
24dc7cc
9b90e49
92f11dd
93e7414
9b90e49
 
93e7414
24dc7cc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dcbd3df
24dc7cc
dcbd3df
24dc7cc
591898c
24dc7cc
dcbd3df
 
 
 
591898c
 
 
 
 
dcbd3df
 
24dc7cc
 
 
 
 
f7f78be
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
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']}")