File size: 7,916 Bytes
40a48fb
ad9f8c5
 
54e930d
ad9f8c5
54e930d
4018845
40a48fb
54e930d
e314039
a6edca8
5280395
 
 
 
273cacd
5280395
 
e314039
 
5280395
 
e314039
fcc1ce5
a6edca8
40a48fb
54e930d
 
f8f52b4
92aeff5
 
 
 
 
 
 
ad9f8c5
9e02f8a
 
 
 
 
40a48fb
 
d780f21
ad9f8c5
54e930d
40a48fb
9e02f8a
 
 
40a48fb
 
ad9f8c5
54e930d
 
 
40a48fb
54e930d
4333cf4
54e930d
9e02f8a
54e930d
 
40a48fb
9e02f8a
 
40a48fb
9e02f8a
54e930d
 
40a48fb
9e02f8a
 
40a48fb
 
d780f21
54e930d
 
 
40a48fb
9e02f8a
 
54e930d
 
 
 
9e02f8a
54e930d
ad9f8c5
40a48fb
 
 
 
 
 
f8f52b4
40a48fb
 
 
 
 
f8f52b4
 
 
 
c7fe441
 
f8f52b4
 
c7fe441
 
 
 
 
 
 
f8f52b4
 
c7fe441
 
52c8526
 
 
 
 
 
 
 
 
c7fe441
 
 
52c8526
 
c7fe441
b7d96b6
40a48fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fcc1ce5
40a48fb
b7d96b6
 
 
 
 
91d4d53
40a48fb
b7d96b6
40a48fb
b7d96b6
40a48fb
b7d96b6
 
40a48fb
 
b7d96b6
 
 
 
40a48fb
 
b7d96b6
 
 
ad9f8c5
40a48fb
b7d96b6
f8f52b4
 
 
 
b7d96b6
 
 
 
 
 
 
 
 
 
 
 
5280395
 
 
 
 
 
e314039
b7d96b6
 
 
 
 
f8f52b4
 
b7d96b6
 
 
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
import pandas as pd
import matplotlib.pyplot as plt
import gradio as gr
import requests
import os
import datetime
import tempfile
from transformers import pipeline


# Load Two Models
light_chat_model = pipeline(
    "text-generation",
    model="mistralai/Mistral-7B-Instruct-v0.2",
    revision="refs/pr/23",  # Use latest stable revision if needed
    use_auth_token="HUGGINGFACE_TOKEN",
    max_length=256
)
advanced_summarizer = pipeline("summarization", model="facebook/bart-large-cnn")

def answer_investing_question(question):
    response = light_chat_model(question)[0]['generated_text']
    return response.strip()


# API Key
POLYGON_API_KEY = os.getenv("POLYGON_API_KEY")

# Sector Averages
sector_averages = {
    "Technology": {"P/E Ratio": 25, "P/S Ratio": 5, "P/B Ratio": 6},
    "Healthcare": {"P/E Ratio": 20, "P/S Ratio": 4, "P/B Ratio": 3},
    "Financials": {"P/E Ratio": 15, "P/S Ratio": 2, "P/B Ratio": 1.5},
    "Energy": {"P/E Ratio": 12, "P/S Ratio": 1.2, "P/B Ratio": 1.3},
}

# Safe Request Function
def safe_request(url):
    try:
        response = requests.get(url)
        response.raise_for_status()
        return response
    except:
        return None

# Fetch Functions
def get_company_info(symbol):
    url = f"https://api.polygon.io/v3/reference/tickers/{symbol}?apiKey={POLYGON_API_KEY}"
    response = safe_request(url)
    if response:
        data = response.json().get('results', {})
        sector = data.get('market', 'Technology')
        if sector.lower() == 'stocks':
            sector = 'Technology'
        return {
            'Name': data.get('name', 'N/A'),
            'Industry': data.get('sic_description', 'N/A'),
            'Sector': sector,
            'Market Cap': data.get('market_cap', 0),
            'Total Revenue': data.get('total_employees', 0) * 100000
        }
    return None

def get_current_price(symbol):
    url = f"https://api.polygon.io/v2/aggs/ticker/{symbol}/prev?adjusted=true&apiKey={POLYGON_API_KEY}"
    response = safe_request(url)
    if response:
        return response.json()['results'][0]['c']
    return None

def get_dividends(symbol):
    url = f"https://api.polygon.io/v3/reference/dividends?ticker={symbol}&apiKey={POLYGON_API_KEY}"
    response = safe_request(url)
    if response:
        return response.json()['results'][0].get('cash_amount', 0)
    return 0

def get_historical_prices(symbol):
    end = datetime.date.today()
    start = end - datetime.timedelta(days=365)
    url = f"https://api.polygon.io/v2/aggs/ticker/{symbol}/range/1/day/{start}/{end}?adjusted=true&sort=asc&apiKey={POLYGON_API_KEY}"
    response = safe_request(url)
    if response:
        results = response.json()['results']
        dates = [datetime.datetime.fromtimestamp(r['t']/1000) for r in results]
        prices = [r['c'] for r in results]
        return dates, prices
    return [], []

# Financial Calculations
def calculate_ratios(market_cap, total_revenue, price, dividend_amount, eps=5.0, growth=0.1, book_value=500000000):
    pe = price / eps if eps else 0
    ps = market_cap / total_revenue if total_revenue else 0
    pb = market_cap / book_value if book_value else 0
    peg = pe / (growth * 100) if growth else 0
    div_yield = (dividend_amount / price) * 100 if price else 0
    return {
        'P/E Ratio': pe,
        'P/S Ratio': ps,
        'P/B Ratio': pb,
        'PEG Ratio': peg,
        'Dividend Yield': div_yield
    }

def compare_to_sector(sector, ratios):
    if sector.lower() == 'stocks':
        sector = 'Technology'
    averages = sector_averages.get(sector, {})
    if not averages:
        return pd.DataFrame({"Metric": ["Sector data not available"], "Value": ["N/A"]})

    data = {
        "Ratio": [],
        "Stock Value": [],
        "Sector Average": [],
        "Difference": []
    }
    for key in averages:
        stock_value = ratios.get(key, 0)
        sector_value = averages.get(key, 0)
        diff = stock_value - sector_value

        # Add emoji based on difference
        if diff < 0:
            diff_display = f"{diff:.2f} 🟢"
        elif diff > 0:
            diff_display = f"{diff:.2f} 🔴"
        else:
            diff_display = f"{diff:.2f} ⚪"

        data["Ratio"].append(key)
        data["Stock Value"].append(round(stock_value, 2))
        data["Sector Average"].append(round(sector_value, 2))
        data["Difference"].append(diff_display)

    return pd.DataFrame(data)

def generate_summary(info, ratios):
    recommendation = "Hold"
    if ratios['P/E Ratio'] < 15 and ratios['P/B Ratio'] < 2 and ratios['PEG Ratio'] < 1.0 and ratios['Dividend Yield'] > 2:
        recommendation = "Buy"
    elif ratios['P/E Ratio'] > 30 and ratios['P/B Ratio'] > 5 and ratios['PEG Ratio'] > 2.0:
        recommendation = "Sell"
    report = (
        f"Company Overview:\n"
        f"Name: {info['Name']}\n"
        f"Industry: {info['Industry']}\n"
        f"Sector: {info['Sector']}\n"
        f"Market Cap: ${info['Market Cap']:,.2f}\n\n"
        f"Financial Metrics:\n"
        f"P/E Ratio: {ratios['P/E Ratio']:.2f}\n"
        f"P/S Ratio: {ratios['P/S Ratio']:.2f}\n"
        f"P/B Ratio: {ratios['P/B Ratio']:.2f}\n"
        f"PEG Ratio: {ratios['PEG Ratio']:.2f}\n"
        f"Dividend Yield: {ratios['Dividend Yield']:.2f}%\n\n"
        f"Recommended Investment Action: {recommendation}.\n"
    )
    return summarizer(report, max_length=250, min_length=100, do_sample=False)[0]['summary_text']


def stock_research(symbol, eps=5.0, growth=0.1, book=500000000):
    info = get_company_info(symbol)
    price = get_current_price(symbol)
    dividends = get_dividends(symbol)
    dates, prices = get_historical_prices(symbol)

    if not info or not price:
        return "⚠️ Error fetching stock info", None, None, None, None

    ratios = calculate_ratios(info['Market Cap'], info['Total Revenue'], price, dividends, eps, growth, book)
    summary = generate_summary(info, ratios)
    sector_comp = compare_to_sector(info['Sector'], ratios)

    fig, ax = plt.subplots()
    ax.plot(dates, prices)
    ax.set_title(f"{symbol} Historical Price (1Y)")
    ax.set_xlabel("Date")
    ax.set_ylabel("Price ($)")
    ax.grid(True)

    info_table = pd.DataFrame(info.items(), columns=["Metric", "Value"])
    ratios_table = pd.DataFrame(ratios.items(), columns=["Ratio", "Value"])

    return summary, info_table, ratios_table, sector_comp, fig

# Gradio UI
with gr.Blocks(theme="soft") as iface:
    with gr.Row():
        symbol = gr.Textbox(label="Stock Symbol (e.g., AAPL)")
        eps = gr.Number(label="Assumed EPS", value=5.0)
        growth = gr.Number(label="Assumed Growth Rate", value=0.1)
        book = gr.Number(label="Assumed Book Value", value=500000000)

    with gr.Tabs():
        with gr.Tab("AI Research Summary"):
            output_summary = gr.Textbox()
        with gr.Tab("Company Snapshot"):
            output_info = gr.Dataframe()
        with gr.Tab("Valuation Ratios"):
            output_ratios = gr.Dataframe()
        with gr.Tab("Sector Comparison"):
            output_sector = gr.Dataframe()
        with gr.Tab("Historical Price Chart"):
            output_chart = gr.Plot()
        with gr.Blocks(theme="soft") as iface:
            with gr.Tab("Ask About Investing"):
                user_question = gr.Textbox(label="Ask about investing...")
                answer_box = gr.Textbox(label="Answer")
                ask_button = gr.Button("Get Answer")
                ask_button.click(fn=answer_investing_question, inputs=[user_question], outputs=[answer_box])


    submit_btn = gr.Button("Run Analysis")
    download_btn = gr.Button("Download Report")
    file_output = gr.File()

    submit_btn.click(fn=stock_research, inputs=[symbol, eps, growth, book],
                     outputs=[output_summary, output_info, output_ratios, output_sector, output_chart])

if __name__ == "__main__":
    iface.launch()