Darshan03 commited on
Commit
0e754f2
·
verified ·
1 Parent(s): f791d75

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -353
app.py CHANGED
@@ -1,11 +1,9 @@
1
- import streamlit as st
2
  import os
3
  import json
4
  import pickle
 
 
5
  from dotenv import load_dotenv
6
- import asyncio
7
- import google.generativeai as genai
8
- from io import BytesIO
9
  from portfolio import (
10
  fetch_stock_data,
11
  store_stock_data,
@@ -20,378 +18,116 @@ from scenario import (
20
  get_response,
21
  extract_json_content
22
  )
 
 
23
  from simluation_data import monte_carlo_simulation
24
- # add this part here
25
- import platform
26
- if platform.system() == "Windows":
27
- asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
28
 
29
  # Load environment variables from .env
30
  load_dotenv()
31
 
32
- # Configuration
33
- class Config:
34
- ALPHA_VANTAGE_API_KEY = os.getenv("ALPHA_VANTAGE_API_KEY")
35
- GROQ_API_KEY = os.getenv("GROQ_API_KEY")
36
- GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
37
- STOCK_DATA_DIR = "stock_data_NSE"
38
- OUTPUT_DIR = "output_files"
39
- OUTPUT_FILE = os.path.join(OUTPUT_DIR, "portfolio.json")
40
- SCENARIO_OUTPUT_FILE = os.path.join(OUTPUT_DIR, "scenario.json")
41
- UPDATED_SCENARIO_FILE = os.path.join(OUTPUT_DIR, "updated_scenario_data.json")
42
- SIMULATION_RESULTS_FILE = os.path.join(OUTPUT_DIR, "simulation_results.json")
43
- SAVED_DATA_FRAMES_FILE = os.path.join(OUTPUT_DIR, "saved_dataframes.pkl")
44
- SECTORS = [
45
- "Communication Services",
46
- "Consumer Discretionary",
47
- "Consumer Staples",
48
- "Energy",
49
- "Financials",
50
- "Health Care",
51
- "Industrials",
52
- "Information Technology",
53
- "Materials",
54
- "Real Estate",
55
- "Utilities"
56
- ]
57
-
58
-
59
- # Helper function to load stock data from a JSON file
60
- def load_stock_data(filepath):
61
- """Loads stock data from a JSON file.
62
-
63
- Args:
64
- filepath (str): The path to the JSON file.
65
-
66
- Returns:
67
- dict: A dictionary containing the stock data, or None if an error occurs.
68
- """
69
- try:
70
- with open(filepath, 'r') as f:
71
- data = json.load(f)
72
- return data
73
- except FileNotFoundError:
74
- st.error(f"Error: File not found at '{filepath}'")
75
- return None
76
- except json.JSONDecodeError:
77
- st.error(f"Error: Invalid JSON format in '{filepath}'")
78
- return None
79
- except Exception as e:
80
- st.error(f"An unexpected error occurred: {e}")
81
- return None
82
-
83
-
84
- def configure_generative_ai():
85
- """Configures the generative AI model and starts a chat session."""
86
- genai.configure(api_key=Config.GOOGLE_API_KEY)
87
-
88
- generation_config = {
89
- "temperature": 1,
90
- "top_p": 0.95,
91
- "top_k": 40,
92
- "max_output_tokens": 8192,
93
- "response_mime_type": "text/plain",
94
- }
95
-
96
- model = genai.GenerativeModel(
97
- model_name="gemini-2.0-flash-exp",
98
- generation_config=generation_config,
99
- )
100
-
101
- return model.start_chat()
102
-
103
-
104
- # Function to save dataframes to a pickle file
105
- def save_dataframes(dataframes_dict, filename):
106
- with open(filename, 'wb') as file:
107
- pickle.dump(dataframes_dict, file)
108
- st.success(f"DataFrames successfully saved to {filename}.")
109
-
110
-
111
- # Function to load dataframes from a pickle file
112
- def load_dataframes(filename):
113
- try:
114
- with open(filename, 'rb') as file:
115
- saved_dataframes = pickle.load(file)
116
- st.success(f"DataFrames successfully loaded from {filename}.")
117
- return saved_dataframes
118
- except FileNotFoundError:
119
- st.error(f"File {filename} not found.")
120
- return None
121
-
122
 
123
- def process_data(stock_data):
124
- """Main function to process stock data and generate output files."""
125
- # 1. Fetch stock data
126
  stock_symbols = [value["symbol"] for value in stock_data.values()]
127
- with st.spinner("Fetching stock data..."):
128
- stock_dfs = fetch_stock_data(stock_symbols)
129
-
130
- # Save DataFrames in a dictionary for future use
131
- saved_dataframes = {}
132
- if stock_dfs:
133
- for symbol, df in stock_dfs.items():
134
- if df is not None:
135
- # Save DataFrame in the variable
136
- saved_dataframes[symbol] = df
137
- st.success(f"Data for '{symbol}' loaded into variable.")
138
- else:
139
- st.error(f"No data found for '{symbol}'")
140
- else:
141
- st.error("Error occurred during fetching data. DataFrames are not returned.")
142
- return False
143
 
144
- save_dataframes(saved_dataframes, Config.SAVED_DATA_FRAMES_FILE)
 
 
 
145
 
146
- # 2. Store data
147
- with st.spinner("Storing stock data..."):
148
- store_stock_data(stock_dfs)
149
 
150
- # 3. Load the last price
151
- with st.spinner("Loading stock prices..."):
152
- extracted_data = load_stock_data_and_extract_price(Config.STOCK_DATA_DIR)
153
-
154
- # 4. Merge extracted price with the main dictionary
155
  merged_stock_data = merge_stock_data_with_price(stock_data, extracted_data)
156
 
157
- # 5. Generate prompt for LLM
158
  formatted_prompt = generate_prompt(merged_stock_data)
159
- st.write("LLM Prompt:")
160
- st.text(formatted_prompt)
 
 
 
 
 
 
 
 
161
 
162
- # 6. Invoke LLM
163
- with st.spinner("Invoking LLM for portfolio analysis..."):
164
- try:
165
- portfolio_output = invoke_llm_for_portfolio(formatted_prompt)
166
- st.write("LLM Portfolio Output:")
167
- st.text(portfolio_output)
168
- except Exception as e:
169
- st.error(f"An unexpected error occurred during the LLM invocation: {e}")
170
- return False
171
- else:
172
- # 7. Save portfolio output to JSON
173
- portfolio_to_json(portfolio_output)
174
 
175
- # 8. Generate market scenarios
176
  url = "https://www.livemint.com/market/stock-market-news/page-7"
177
- with st.spinner("Extracting text from website..."):
178
- context_data = asyncio.run(extract_text_from_website(url))
179
-
180
- chat_session = configure_generative_ai()
181
 
 
182
  scenario_prompt = f"""
183
  # TASK: Analyze market context and identify potential market scenarios.
184
-
185
- # CONTEXT:
186
- {context_data}
187
- # END CONTEXT
188
-
189
- # INSTRUCTION: Based on the provided market context, analyze and identify up to three plausible market scenarios.
190
- # For each scenario, determine its name (e.g., "Moderate Downturn"), the general market direction ("up" or "down"), a major trigger point that could cause the scenario to unfold, and a list of sectors that would be significantly impacted. Each 'sector_impact' list should have less than or equal to 4 sectors.
191
-
192
- # OUTPUT FORMAT: Provide the analysis in JSON format with the following structure.
193
- # Use the sector names provided:
194
- {Config.SECTORS}
195
-
196
- # EXAMPLE:
197
- ```json
198
- {{
199
- "market_scenarios": {{
200
- "scenario1": {{
201
- "name": "Moderate Downturn",
202
- "direction": "down",
203
- "trigger": "Interest rate hike",
204
- "sector_impact": [
205
- "Financials",
206
- "Energy"
207
- ]
208
- }},
209
- "scenario2": {{
210
- "name": "Bullish Growth",
211
- "direction": "up",
212
- "trigger": "Successful vaccine rollout",
213
- "sector_impact": [
214
- "Health Care",
215
- "Information Technology"
216
- ]
217
- }}
218
- }}
219
- }}
220
- ```
221
  """
222
 
223
- with st.spinner("Generating market scenarios..."):
224
- try:
225
- scenario_response = get_response(chat_session, scenario_prompt)
226
- json_output = extract_json_content(scenario_response.text)
227
- scenario_data = json.loads(json_output)
228
- os.makedirs(os.path.dirname(Config.SCENARIO_OUTPUT_FILE), exist_ok=True)
229
- with open(Config.SCENARIO_OUTPUT_FILE, "w") as f:
230
- json.dump(scenario_data, f, indent=4)
231
- st.success(f"Market scenarios saved to '{Config.SCENARIO_OUTPUT_FILE}'")
232
- except json.JSONDecodeError:
233
- st.error("Error: Could not decode the output from the model into JSON format.")
234
- return False
235
- except Exception as e:
236
- st.error(f"Error: {e}")
237
- return False
238
-
239
-
240
- # Simulation
241
- with open(Config.SCENARIO_OUTPUT_FILE) as f:
242
- scenario_data = json.load(f)
243
-
244
- with open(Config.OUTPUT_FILE) as f:
245
- portfolio_data = json.load(f)
246
- saved_dataframes = load_dataframes(Config.SAVED_DATA_FRAMES_FILE)
247
- if not saved_dataframes:
248
- return False
249
-
250
- # Placeholder for storing results
251
- scenario_results = {}
252
-
253
- # Process each scenario
254
- for scenario_name, scenario_details in scenario_data["market_scenarios"].items():
255
- impacted_sectors = scenario_details["sector_impact"]
256
-
257
- # Filter assets in the impacted sectors
258
- relevant_assets = [
259
- symbol
260
- for symbol, details in portfolio_data["assets"].items()
261
- if details["sector"] in impacted_sectors
262
- ]
263
-
264
- # Calculate magnitudes for the scenario
265
- sector_magnitudes = {}
266
- for symbol in relevant_assets:
267
- df = saved_dataframes[symbol]
268
- sector = portfolio_data["assets"][symbol]["sector"]
269
-
270
- # Calculate magnitude as the absolute difference between first and last Close price
271
- magnitude = abs(df["Close"].iloc[-2] - df["Close"].iloc[-1])
272
-
273
- # Aggregate by sector
274
- if sector not in sector_magnitudes:
275
- sector_magnitudes[sector] = 0
276
- sector_magnitudes[sector] += magnitude
277
-
278
- # Calculate aggregated magnitude for the scenario
279
- aggregated_magnitude = sum(sector_magnitudes.values())
280
-
281
- # Store results
282
- scenario_results[scenario_name] = {
283
- "individual_magnitudes": sector_magnitudes,
284
- "aggregated_magnitude": aggregated_magnitude,
285
- }
286
-
287
- # Display results
288
- st.write("## Scenario Analysis")
289
- for scenario_name, results in scenario_results.items():
290
- st.write(f"### Scenario: {scenario_name}")
291
- st.write("Individual Sector Magnitudes:")
292
- for sector, magnitude in results["individual_magnitudes"].items():
293
- st.write(f" {sector}: {magnitude:.2f}")
294
- st.write(f"Aggregated Magnitude: {results['aggregated_magnitude']:.2f}")
295
-
296
- # Integrate calculated results into scenario data
297
- for scenario_id, results in scenario_results.items():
298
- # Update the sector impacts to include individual magnitudes
299
- scenario_data["market_scenarios"][scenario_id]["sector_impact"] = results["individual_magnitudes"]
300
- # Update aggregated magnitude
301
- scenario_data["market_scenarios"][scenario_id]["aggregated_magnitude"] = results["aggregated_magnitude"]
302
-
303
- # Save the updated scenario data to a local JSON file
304
- os.makedirs(os.path.dirname(Config.UPDATED_SCENARIO_FILE), exist_ok=True)
305
- with open(Config.UPDATED_SCENARIO_FILE, "w") as file:
306
- json.dump(scenario_data, file, indent=4)
307
 
308
- st.success(f"Updated scenario data saved to '{Config.UPDATED_SCENARIO_FILE}' successfully!")
 
 
 
 
 
 
 
 
 
309
 
310
- # Run Monte Carlo simulation
311
- with st.spinner("Running Monte Carlo simulation..."):
312
- simulation_results = monte_carlo_simulation(portfolio_data, scenario_data)
313
 
314
- # Save simulation results to a local JSON file
315
- os.makedirs(os.path.dirname(Config.SIMULATION_RESULTS_FILE), exist_ok=True)
316
- with open(Config.SIMULATION_RESULTS_FILE, "w") as file:
317
  json.dump(simulation_results, file, indent=4)
 
318
 
319
- st.success(f"Simulation results saved to '{Config.SIMULATION_RESULTS_FILE}' successfully!")
320
-
321
- # Display simulation results
322
- st.write("## Simulation Results")
323
- for scenario_name, results in simulation_results.items():
324
- st.write(f"### Scenario: {scenario_name}")
325
- st.write(f" Average Return: {results['average_return']:.4f}")
326
- st.write(f" Std Dev Return: {results['std_dev_return']:.4f}")
327
- st.write(" Return Percentiles:")
328
- for percentile, value in results["percentiles"].items():
329
- st.write(f" {percentile}th: {value:.4f}")
330
- st.write("-" * 40)
331
-
332
- return True
333
-
334
-
335
- def main():
336
- st.title("Portfolio Analysis App")
337
- # Create output directory if it doesn't exist
338
- if not os.path.exists(Config.OUTPUT_DIR):
339
- os.makedirs(Config.OUTPUT_DIR)
340
- # File upload
341
- uploaded_file = st.file_uploader("Upload your portfolio JSON file", type=["json"])
342
-
343
- if uploaded_file is not None:
344
- try:
345
- # Save the uploaded file to the data folder
346
- file_path = os.path.join("data", uploaded_file.name)
347
- with open(file_path, "wb") as f:
348
- f.write(uploaded_file.read())
349
- st.success(f"File uploaded successfully: {uploaded_file.name} to {file_path}")
350
- stock_data = load_stock_data(file_path)
351
- except Exception as e:
352
- st.error(f"Error processing uploaded file: {e}")
353
- return
354
-
355
-
356
- if stock_data:
357
- if process_data(stock_data):
358
- st.write("## Download Output Files")
359
- # Download button for portfolio.json
360
- with open(Config.OUTPUT_FILE, "rb") as f:
361
- st.download_button(
362
- label="Download Portfolio Output (portfolio.json)",
363
- data=f,
364
- file_name="portfolio.json",
365
- mime="application/json",
366
- )
367
-
368
- # Download button for scenario.json
369
- with open(Config.SCENARIO_OUTPUT_FILE, "rb") as f:
370
- st.download_button(
371
- label="Download Scenario Output (scenario.json)",
372
- data=f,
373
- file_name="scenario.json",
374
- mime="application/json",
375
- )
376
- # Download button for updated_scenario_data.json
377
- with open(Config.UPDATED_SCENARIO_FILE, "rb") as f:
378
- st.download_button(
379
- label="Download Updated Scenario (updated_scenario_data.json)",
380
- data=f,
381
- file_name="updated_scenario_data.json",
382
- mime="application/json",
383
- )
384
-
385
- # Download button for simulation_results.json
386
- with open(Config.SIMULATION_RESULTS_FILE, "rb") as f:
387
- st.download_button(
388
- label="Download Simulation Results (simulation_results.json)",
389
- data=f,
390
- file_name="simulation_results.json",
391
- mime="application/json",
392
- )
393
- else:
394
- st.error("Error occurred during processing.")
395
-
396
- if __name__ == "__main__":
397
- main()
 
 
1
  import os
2
  import json
3
  import pickle
4
+ import time
5
+ import streamlit as st
6
  from dotenv import load_dotenv
 
 
 
7
  from portfolio import (
8
  fetch_stock_data,
9
  store_stock_data,
 
18
  get_response,
19
  extract_json_content
20
  )
21
+ import asyncio
22
+ import google.generativeai as genai
23
  from simluation_data import monte_carlo_simulation
 
 
 
 
24
 
25
  # Load environment variables from .env
26
  load_dotenv()
27
 
28
+ # Streamlit UI
29
+ st.title("Stock Portfolio Analysis")
30
+
31
+ uploaded_file = st.file_uploader("Upload JSON file", type=["json"])
32
+
33
+ if uploaded_file is not None:
34
+ with st.spinner("Loading data..."):
35
+ time.sleep(2) # Simulating loading time
36
+ stock_data = json.load(uploaded_file)
37
+ st.success("Data loaded successfully!")
38
+
39
+ # Configuration Class
40
+ class Config:
41
+ ALPHA_VANTAGE_API_KEY = os.getenv("ALPHA_VANTAGE_API_KEY")
42
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
43
+ GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
44
+ STOCK_DATA_DIR = "stock_data_NSE"
45
+ OUTPUT_FILE = "output_files/portfolio.json"
46
+ SCENARIO_OUTPUT_FILE = "output_files/scenario.json"
47
+ SECTORS = [
48
+ "Communication Services",
49
+ "Consumer Discretionary",
50
+ "Consumer Staples",
51
+ "Energy",
52
+ "Financials",
53
+ "Health Care",
54
+ "Industrials",
55
+ "Information Technology",
56
+ "Materials",
57
+ "Real Estate",
58
+ "Utilities"
59
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
+ # Fetch stock data
62
+ st.write("Fetching stock data...")
 
63
  stock_symbols = [value["symbol"] for value in stock_data.values()]
64
+ stock_dfs = fetch_stock_data(stock_symbols)
65
+ st.success("Stock data fetched successfully!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ # Save data
68
+ st.write("Storing stock data...")
69
+ store_stock_data(stock_dfs)
70
+ st.success("Stock data stored successfully!")
71
 
72
+ # Load last price
73
+ extracted_data = load_stock_data_and_extract_price(Config.STOCK_DATA_DIR)
 
74
 
75
+ # Merge extracted price with main dictionary
 
 
 
 
76
  merged_stock_data = merge_stock_data_with_price(stock_data, extracted_data)
77
 
78
+ # Generate prompt for LLM
79
  formatted_prompt = generate_prompt(merged_stock_data)
80
+ st.write("Generated Prompt:", formatted_prompt)
81
+
82
+ # Invoke LLM
83
+ st.write("Invoking LLM...")
84
+ try:
85
+ portfolio_output = invoke_llm_for_portfolio(formatted_prompt)
86
+ st.success("LLM invocation successful!")
87
+ st.json(portfolio_output)
88
+ except Exception as e:
89
+ st.error(f"An error occurred: {e}")
90
 
91
+ # Save portfolio output
92
+ portfolio_to_json(portfolio_output)
 
 
 
 
 
 
 
 
 
 
93
 
94
+ # Market scenarios extraction
95
  url = "https://www.livemint.com/market/stock-market-news/page-7"
96
+ st.write("Extracting market scenarios...")
97
+ context_data = asyncio.run(extract_text_from_website(url))
98
+ st.success("Market context extracted successfully!")
 
99
 
100
+ # Generate scenario prompt
101
  scenario_prompt = f"""
102
  # TASK: Analyze market context and identify potential market scenarios.
103
+ ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  """
105
 
106
+ chat_session = configure_generative_ai()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
+ try:
109
+ scenario_response = get_response(chat_session, scenario_prompt)
110
+ json_output = extract_json_content(scenario_response.text)
111
+ scenario_data = json.loads(json_output)
112
+ os.makedirs(os.path.dirname(Config.SCENARIO_OUTPUT_FILE), exist_ok=True)
113
+ with open(Config.SCENARIO_OUTPUT_FILE, "w") as f:
114
+ json.dump(scenario_data, f, indent=4)
115
+ st.success("Market scenarios saved successfully!")
116
+ except Exception as e:
117
+ st.error(f"Error: {e}")
118
 
119
+ # Monte Carlo Simulation
120
+ st.write("Running Monte Carlo Simulation...")
121
+ simulation_results = monte_carlo_simulation(portfolio_output, scenario_data)
122
 
123
+ # Save simulation results
124
+ simulation_results_file = "output_files/simulation_results.json"
125
+ with open(simulation_results_file, "w") as file:
126
  json.dump(simulation_results, file, indent=4)
127
+ st.success("Monte Carlo Simulation completed!")
128
 
129
+ # Download Output Files
130
+ st.write("Download Output Files")
131
+ for file in [Config.OUTPUT_FILE, Config.SCENARIO_OUTPUT_FILE, simulation_results_file]:
132
+ with open(file, "rb") as f:
133
+ st.download_button(label=f"Download {file.split('/')[-1]}", data=f, file_name=file.split('/')[-1])