File size: 8,097 Bytes
40a48fb
ad9f8c5
 
54e930d
ad9f8c5
54e930d
4018845
40a48fb
54e930d
2544f4c
 
 
 
 
 
 
 
 
 
 
8eb4d8c
 
 
2544f4c
 
 
 
 
 
 
 
 
e314039
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b7d96b6
 
 
 
 
91d4d53
40a48fb
b7d96b6
40a48fb
b7d96b6
40a48fb
b7d96b6
 
40a48fb
 
b7d96b6
 
 
 
40a48fb
 
b7d96b6
 
 
ad9f8c5
40a48fb
b7d96b6
f8f52b4
 
 
 
b7d96b6
 
 
 
 
 
 
 
 
 
 
 
8eb4d8c
9a0bbc7
 
 
 
b7d96b6
 
 
 
 
f8f52b4
 
b7d96b6
 
8eb4d8c
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
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

# Your Hugging Face API Token (set this safely)
HF_TOKEN = os.getenv("HUGGINGFACE_TOKEN")  # Recommended: use environment variable

# Mistral Inference API URL
API_URL = "https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.3"

# Headers for authentication
headers = {
    "Authorization": f"Bearer {HF_TOKEN}"
}

# Load summarizer model
summarizer = pipeline("summarization", model="facebook/bart-large-cnn")

# Function to query Mistral API
def query_mistral(question):
    payload = {
        "inputs": question,
        "parameters": {"max_length": 256}
    }
    response = requests.post(API_URL, headers=headers, json=payload)
    output = response.json()
    return output[0]["generated_text"]

# 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.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=query_mistral, 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()