Sujatha commited on
Commit
edcde5c
Β·
verified Β·
1 Parent(s): 8bb816d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +110 -72
app.py CHANGED
@@ -1,12 +1,12 @@
1
  import os
2
- import sys
3
  import gradio as gr
4
  import pandas as pd
5
  import numpy as np
6
  import plotly.graph_objects as go
 
7
  from datetime import datetime
 
8
  import json
9
- from typing import Dict, List, Tuple, Optional
10
 
11
  # ========== Optional memory monitoring ==========
12
  try:
@@ -16,7 +16,7 @@ try:
16
  except ImportError:
17
  pass
18
 
19
- # ========== Lazy imports for heavy modules ==========
20
  def get_llm():
21
  from langchain_openai import ChatOpenAI
22
  from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
@@ -30,21 +30,92 @@ def get_llm():
30
  temperature=0.3,
31
  )
32
 
33
- def get_realtime_calculator():
34
- from data_sources import RealTimeIndexCalculator, IndianStockAPI, GlobalStockAPI
35
- return RealTimeIndexCalculator(), IndianStockAPI(), GlobalStockAPI()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- # ========== Simple memory (optional, not heavily used) ==========
38
- class SimpleMemory:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  def __init__(self):
40
- self.messages = []
41
- def add_message(self, message: str, role: str):
42
- self.messages.append({'role': role, 'content': message})
43
- def get_history(self):
44
- return self.messages
45
 
46
- memory = SimpleMemory()
 
 
47
 
 
48
  SYSTEM_PROMPT = """You are an expert financial analyst specializing in index numbers and real-time market data.
49
  You help users understand, calculate, and analyze various types of indices including:
50
  - Laspeyres, Paasche, and Fisher price indices
@@ -59,11 +130,7 @@ When users ask about stocks or indices, fetch live data. Provide clear explanati
59
 
60
  # ========== Core conversational function ==========
61
  def process_query(query: str, history: List, exchange: str) -> Tuple[str, List, pd.DataFrame, str]:
62
- """
63
- Process user query with real-time data awareness
64
- """
65
  rt_calc, indian_api, global_api = get_realtime_calculator()
66
-
67
  response_text = ""
68
  data_preview = pd.DataFrame()
69
 
@@ -127,7 +194,6 @@ def process_query(query: str, history: List, exchange: str) -> Tuple[str, List,
127
 
128
  messages = [SystemMessage(content=SYSTEM_PROMPT)]
129
  if history:
130
- # history is a flat list: [user1, assistant1, user2, assistant2, ...]
131
  for i in range(0, len(history), 2):
132
  if i < len(history):
133
  messages.append(HumanMessage(content=history[i]))
@@ -140,7 +206,7 @@ def process_query(query: str, history: List, exchange: str) -> Tuple[str, List,
140
  except Exception as e:
141
  response_text = f"LLM error: {str(e)}"
142
 
143
- # Update history (keep last 10 exchanges to avoid memory bloat)
144
  updated_history = history + [query, response_text]
145
  if len(updated_history) > 20:
146
  updated_history = updated_history[-20:]
@@ -155,7 +221,6 @@ def fetch_live_stock(symbol: str, exchange: str):
155
  data = indian_api.get_stock_price(symbol, exchange)
156
  if data and 'data' in data:
157
  formatted = indian_api.format_for_index(data)
158
- # Simple chart
159
  fig = go.Figure()
160
  fig.add_trace(go.Indicator(
161
  mode="number+delta",
@@ -191,8 +256,7 @@ def build_custom_index(symbols_df: pd.DataFrame, index_type: str, exchange: str)
191
  if exchange in ["NSE", "BSE"]:
192
  data = indian_api.get_stock_price(symbol, exchange)
193
  if data and 'data' in data:
194
- # Adjust based on actual API structure
195
- price = data['data'][0]['last_price'] if 'data' in data and data['data'] else 0
196
  else:
197
  price = 0
198
  else:
@@ -203,15 +267,18 @@ def build_custom_index(symbols_df: pd.DataFrame, index_type: str, exchange: str)
203
  total_weight += weight
204
 
205
  # Normalize weights if total != 1
206
- if total_weight != 1:
207
  weights = [w/total_weight for w in weights]
208
 
209
- if index_type == "Price-Weighted":
210
- index_value = sum(prices) / len(prices) if prices else 0
211
- elif index_type == "Equal-Weighted":
212
- index_value = sum(prices) / len(prices) if prices else 0
213
- elif index_type == "Market Cap-Weighted":
214
- index_value = sum(w * p for w, p in zip(weights, prices)) if prices else 0
 
 
 
215
  else:
216
  index_value = 0
217
 
@@ -250,13 +317,13 @@ def compare_live_indices(symbols_str: str, exchange: str):
250
  return data, fig
251
 
252
  # ========== Main Gradio interface ==========
253
- with gr.Blocks(title="AI-Powered Index Analyst with Real-Time Data", theme=gr.themes.Soft()) as demo:
254
  gr.Markdown("""
255
  # πŸ“ˆ AI-Powered Index Analyst with Real-Time Market Data
256
 
257
  Welcome to your intelligent financial index assistant! This enhanced version includes:
258
- - **Real-time Indian stock data** from NSE/BSE (free, no API key) [citation:1]
259
- - **Global market data** via Yahoo Finance [citation:2]
260
  - **Custom index builder** with live prices
261
  - **Conversational AI** for market insights
262
  - **Multiple index formulas** (Laspeyres, Paasche, Fisher, etc.)
@@ -284,7 +351,6 @@ with gr.Blocks(title="AI-Powered Index Analyst with Real-Time Data", theme=gr.th
284
  data_output = gr.DataFrame(label="Data Preview")
285
  calc_output = gr.Textbox(label="Calculation Results", lines=3)
286
 
287
- # Output mapping: (response, updated_history, data_preview, status)
288
  submit.click(
289
  process_query,
290
  inputs=[msg, chat_history, exchange_selector],
@@ -309,9 +375,9 @@ with gr.Blocks(title="AI-Powered Index Analyst with Real-Time Data", theme=gr.th
309
  ### πŸ“‘ Real-Time Market Data
310
 
311
  Fetch live stock prices from:
312
- - **NSE** (National Stock Exchange of India) [citation:1]
313
- - **BSE** (Bombay Stock Exchange) [citation:1]
314
- - **Global Markets** via Yahoo Finance [citation:2]
315
  """)
316
 
317
  exchange = gr.Radio(
@@ -373,38 +439,11 @@ with gr.Blocks(title="AI-Powered Index Analyst with Real-Time Data", theme=gr.th
373
  )
374
 
375
  with gr.Tab("πŸ“Š Index Calculator"):
376
- try:
377
- from app import create_index_ui, calculate_indices
378
- except ImportError:
379
- # Stub functions if module not available
380
- def create_index_ui():
381
- with gr.Blocks():
382
- gr.Markdown("Index Calculator placeholder – implement if needed.")
383
- return {}
384
- def calculate_indices(file, items, p0, q0, p1, q1):
385
- return "Calculation placeholder", 0, 0, 0, go.Figure()
386
-
387
- calc_ui = create_index_ui()
388
- if calc_ui and 'btn' in calc_ui:
389
- # Connect the calculator button if UI defined
390
- calc_ui["btn"].click(
391
- calculate_indices,
392
- inputs=[
393
- calc_ui.get("file"),
394
- calc_ui.get("items"),
395
- calc_ui.get("p0"),
396
- calc_ui.get("q0"),
397
- calc_ui.get("p1"),
398
- calc_ui.get("q1")
399
- ],
400
- outputs=[
401
- calc_ui.get("results"),
402
- calc_ui.get("laspeyres"),
403
- calc_ui.get("paasche"),
404
- calc_ui.get("fisher"),
405
- calc_ui.get("plot")
406
- ]
407
- )
408
 
409
  with gr.Tab("πŸ”„ Index Comparison"):
410
  comp_ui = create_comparison_ui()
@@ -417,11 +456,10 @@ with gr.Blocks(title="AI-Powered Index Analyst with Real-Time Data", theme=gr.th
417
  gr.Markdown("""
418
  ---
419
  ### πŸ“š Resources & Credits
420
- - [Free Indian Stock Market API](https://github.com/0xramm/Indian-Stock-Market-API) - No API key required [citation:1]
421
- - [yfinance](https://pypi.org/project/yfinance/) - Yahoo Finance Python library [citation:2]
422
  - [CFA Institute](https://www.cfainstitute.org)
423
 
424
- *Note: Free APIs may have rate limits. The Indian API caches data for 60 seconds.*
425
  """)
426
 
427
  if __name__ == "__main__":
 
1
  import os
 
2
  import gradio as gr
3
  import pandas as pd
4
  import numpy as np
5
  import plotly.graph_objects as go
6
+ import yfinance as yf
7
  from datetime import datetime
8
+ from typing import List, Tuple, Dict, Optional
9
  import json
 
10
 
11
  # ========== Optional memory monitoring ==========
12
  try:
 
16
  except ImportError:
17
  pass
18
 
19
+ # ========== Lazy LLM import ==========
20
  def get_llm():
21
  from langchain_openai import ChatOpenAI
22
  from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
 
30
  temperature=0.3,
31
  )
32
 
33
+ # ========== Stock API classes using yfinance ==========
34
+ class IndianStockAPI:
35
+ """Fetch Indian stock data via yfinance (NSE symbols with .NS)"""
36
+
37
+ def get_stock_price(self, symbol: str, exchange: str = "NSE"):
38
+ """Get stock data for Indian market"""
39
+ try:
40
+ # For NSE/BSE, yfinance uses .NS suffix
41
+ yf_symbol = symbol + ".NS" if exchange == "NSE" else symbol + ".BO"
42
+ ticker = yf.Ticker(yf_symbol)
43
+ info = ticker.info
44
+ hist = ticker.history(period="1d")
45
+ if hist.empty:
46
+ return None
47
+
48
+ last_price = hist['Close'].iloc[-1]
49
+ prev_close = info.get('regularMarketPreviousClose', last_price)
50
+ change = last_price - prev_close
51
+ pct_change = (change / prev_close) * 100 if prev_close else 0
52
+
53
+ return {
54
+ 'data': [{
55
+ 'symbol': symbol,
56
+ 'last_price': last_price,
57
+ 'change': change,
58
+ 'percent_change': pct_change,
59
+ 'day_low': hist['Low'].iloc[-1],
60
+ 'day_high': hist['High'].iloc[-1],
61
+ 'year_low': info.get('fiftyTwoWeekLow', 0),
62
+ 'year_high': info.get('fiftyTwoWeekHigh', 0),
63
+ 'market_cap': info.get('marketCap', 0) / 1e7, # in Cr
64
+ 'pe_ratio': info.get('trailingPE', 0),
65
+ 'company_name': info.get('longName', symbol)
66
+ }]
67
+ }
68
+ except Exception as e:
69
+ print(f"Error fetching Indian stock {symbol}: {e}")
70
+ return None
71
+
72
+ def format_for_index(self, data):
73
+ """Format API response to match expected structure"""
74
+ if data and 'data' in data and len(data['data']) > 0:
75
+ return data['data'][0]
76
+ return {}
77
 
78
+ class GlobalStockAPI:
79
+ """Fetch global stock data via yfinance"""
80
+
81
+ def get_stock_info(self, symbol: str):
82
+ """Get stock data for global markets"""
83
+ try:
84
+ ticker = yf.Ticker(symbol)
85
+ info = ticker.info
86
+ hist = ticker.history(period="1d")
87
+ if hist.empty:
88
+ return None
89
+
90
+ last_price = hist['Close'].iloc[-1]
91
+ prev_close = info.get('regularMarketPreviousClose', last_price)
92
+ change = last_price - prev_close
93
+ pct_change = (change / prev_close) * 100 if prev_close else 0
94
+
95
+ return {
96
+ 'symbol': symbol,
97
+ 'company_name': info.get('longName', symbol),
98
+ 'last_price': last_price,
99
+ 'change': change,
100
+ 'percent_change': pct_change,
101
+ 'day_low': hist['Low'].iloc[-1],
102
+ 'day_high': hist['High'].iloc[-1],
103
+ 'market_cap': info.get('marketCap', 0),
104
+ }
105
+ except Exception as e:
106
+ print(f"Error fetching global stock {symbol}: {e}")
107
+ return None
108
+
109
+ class RealTimeIndexCalculator:
110
+ """Placeholder for index calculations (not heavily used)"""
111
  def __init__(self):
112
+ pass
 
 
 
 
113
 
114
+ # ========== Helper to get API instances ==========
115
+ def get_realtime_calculator():
116
+ return RealTimeIndexCalculator(), IndianStockAPI(), GlobalStockAPI()
117
 
118
+ # ========== System prompt ==========
119
  SYSTEM_PROMPT = """You are an expert financial analyst specializing in index numbers and real-time market data.
120
  You help users understand, calculate, and analyze various types of indices including:
121
  - Laspeyres, Paasche, and Fisher price indices
 
130
 
131
  # ========== Core conversational function ==========
132
  def process_query(query: str, history: List, exchange: str) -> Tuple[str, List, pd.DataFrame, str]:
 
 
 
133
  rt_calc, indian_api, global_api = get_realtime_calculator()
 
134
  response_text = ""
135
  data_preview = pd.DataFrame()
136
 
 
194
 
195
  messages = [SystemMessage(content=SYSTEM_PROMPT)]
196
  if history:
 
197
  for i in range(0, len(history), 2):
198
  if i < len(history):
199
  messages.append(HumanMessage(content=history[i]))
 
206
  except Exception as e:
207
  response_text = f"LLM error: {str(e)}"
208
 
209
+ # Update history (keep last 10 exchanges)
210
  updated_history = history + [query, response_text]
211
  if len(updated_history) > 20:
212
  updated_history = updated_history[-20:]
 
221
  data = indian_api.get_stock_price(symbol, exchange)
222
  if data and 'data' in data:
223
  formatted = indian_api.format_for_index(data)
 
224
  fig = go.Figure()
225
  fig.add_trace(go.Indicator(
226
  mode="number+delta",
 
256
  if exchange in ["NSE", "BSE"]:
257
  data = indian_api.get_stock_price(symbol, exchange)
258
  if data and 'data' in data:
259
+ price = data['data'][0]['last_price']
 
260
  else:
261
  price = 0
262
  else:
 
267
  total_weight += weight
268
 
269
  # Normalize weights if total != 1
270
+ if total_weight != 1 and total_weight > 0:
271
  weights = [w/total_weight for w in weights]
272
 
273
+ if prices:
274
+ if index_type == "Price-Weighted":
275
+ index_value = sum(prices) / len(prices)
276
+ elif index_type == "Equal-Weighted":
277
+ index_value = sum(prices) / len(prices)
278
+ elif index_type == "Market Cap-Weighted":
279
+ index_value = sum(w * p for w, p in zip(weights, prices))
280
+ else:
281
+ index_value = 0
282
  else:
283
  index_value = 0
284
 
 
317
  return data, fig
318
 
319
  # ========== Main Gradio interface ==========
320
+ with gr.Blocks(title="AI-Powered Index Analyst with Real-Time Data") as demo:
321
  gr.Markdown("""
322
  # πŸ“ˆ AI-Powered Index Analyst with Real-Time Market Data
323
 
324
  Welcome to your intelligent financial index assistant! This enhanced version includes:
325
+ - **Real-time Indian stock data** from NSE/BSE via Yahoo Finance
326
+ - **Global market data** via Yahoo Finance
327
  - **Custom index builder** with live prices
328
  - **Conversational AI** for market insights
329
  - **Multiple index formulas** (Laspeyres, Paasche, Fisher, etc.)
 
351
  data_output = gr.DataFrame(label="Data Preview")
352
  calc_output = gr.Textbox(label="Calculation Results", lines=3)
353
 
 
354
  submit.click(
355
  process_query,
356
  inputs=[msg, chat_history, exchange_selector],
 
375
  ### πŸ“‘ Real-Time Market Data
376
 
377
  Fetch live stock prices from:
378
+ - **NSE** (National Stock Exchange of India) via Yahoo Finance
379
+ - **BSE** (Bombay Stock Exchange) via Yahoo Finance
380
+ - **Global Markets** via Yahoo Finance
381
  """)
382
 
383
  exchange = gr.Radio(
 
439
  )
440
 
441
  with gr.Tab("πŸ“Š Index Calculator"):
442
+ # Simplified placeholder – you can expand with actual calculations later
443
+ gr.Markdown("""
444
+ ### Index Calculator
445
+ This tab is under construction. For now, use the Conversational Assistant to ask about index calculations.
446
+ """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
 
448
  with gr.Tab("πŸ”„ Index Comparison"):
449
  comp_ui = create_comparison_ui()
 
456
  gr.Markdown("""
457
  ---
458
  ### πŸ“š Resources & Credits
459
+ - Data provided by [Yahoo Finance](https://finance.yahoo.com/) via [yfinance](https://pypi.org/project/yfinance/)
 
460
  - [CFA Institute](https://www.cfainstitute.org)
461
 
462
+ *Note: Free APIs may have rate limits. Data is cached for performance.*
463
  """)
464
 
465
  if __name__ == "__main__":