Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
import pandas as pd
|
| 3 |
import plotly.express as px
|
|
@@ -7,10 +8,14 @@ import numpy as np
|
|
| 7 |
import ast
|
| 8 |
from pagination import paginator
|
| 9 |
import style as cs
|
| 10 |
-
# from ragfile2 import result
|
| 11 |
import random
|
| 12 |
import time
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
|
| 16 |
# Utils Functions
|
|
@@ -66,65 +71,67 @@ def convert_str_to_list(string):
|
|
| 66 |
# If the string cannot be converted to a list, return it as is
|
| 67 |
return string
|
| 68 |
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
col1, col2 = title_container.columns([0.2, 0.8], gap='medium')
|
| 73 |
-
col1.image("logo.png")
|
| 74 |
-
|
| 75 |
-
|
|
|
|
| 76 |
c1, c2 = col2.columns([0.5, 0.5], gap="large")
|
| 77 |
c1.markdown("Powered by GenInstigators")
|
| 78 |
-
|
| 79 |
-
#
|
| 80 |
-
# <div style='background-color:#b43c42; color:#ffffff; padding:8px; border-radius:3px; font-size:12px''>
|
| 81 |
-
# <strong>Disclaimer:</strong> For demo purpose, the tool is currently populated with 10 months (Nov 2020 - Aug 2021) news and historical data of oil sector (OGDC) from PSX.
|
| 82 |
-
# This data is intended to illustrate the tool's functionality and is not intended for actual investment decisions.
|
| 83 |
-
# </div>
|
| 84 |
-
# """, unsafe_allow_html=True)
|
| 85 |
-
# Load data
|
| 86 |
data_file_path = r"technicalRecommendation.csv" # Update this with your file path
|
| 87 |
data = pd.read_csv(data_file_path)
|
| 88 |
|
| 89 |
# Convert 'Date' column to datetime format
|
| 90 |
data['Date'] = pd.to_datetime(data['Date'])
|
| 91 |
-
# print(data.shape, data.columns)
|
| 92 |
|
| 93 |
-
|
| 94 |
-
date_limit = pd.to_datetime(data['Date'].max())
|
|
|
|
|
|
|
| 95 |
current_date = pd.to_datetime('2021-08-12')
|
| 96 |
|
| 97 |
# Create Tabs
|
| 98 |
-
market_analysis, news_analysis, final_recs, chat
|
| 99 |
-
"Ask AI Advisor", "Ask AI Advisor 2"])
|
| 100 |
|
| 101 |
with market_analysis:
|
| 102 |
st.header("Market Analysis", help = "This module provides market analysis for the following day based on the current date.")
|
| 103 |
# st.write("This module provides market analysis for the following day based on the current date.")
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
col1, col2 = date_container.columns([0.5, 0.5], gap='medium')
|
| 108 |
# start_date = col1.date_input('Start Date', value=default_start_date, min_value=data['Date'].min(), max_value=date_limit)
|
| 109 |
end_date = col1.date_input("Current Date", value=current_date, min_value=data['Date'].min(), max_value=date_limit)
|
| 110 |
-
|
| 111 |
-
|
|
|
|
| 112 |
end_date = pd.to_datetime(end_date)
|
| 113 |
data2 = data[data['Date'].between(start_date, end_date)]
|
| 114 |
|
| 115 |
# Dropdown for selecting the indicator
|
| 116 |
selected_indicator = st.selectbox("Select an Indicator", ['EMA 9', 'EMA 55', 'MACD', 'RSI'])
|
|
|
|
| 117 |
# Dropdown for selecting the Number of Signal Days
|
| 118 |
num_signals = st.selectbox("Signals to Show", ['None', 'All', 'Last 5 Days', 'Last 15 Days', 'Last 20 Days'])
|
|
|
|
|
|
|
| 119 |
data2.rename(columns={'Close_price': 'Close Price', 'EMA_9': 'EMA 9', 'EMA_55': 'EMA 55'}, inplace=True)
|
| 120 |
-
|
|
|
|
| 121 |
if selected_indicator == 'EMA 9':
|
| 122 |
# Plot close price and EMA 9
|
| 123 |
fig = px.line(data2, x='Date', y=['Close Price', 'EMA 9'], title='Close Price vs EMA 9',
|
| 124 |
labels={'Date': 'Date', 'value': 'Price in Rs.', 'variable': 'Type'})
|
| 125 |
fig.update_traces(selector=dict(type='scatter'))
|
| 126 |
-
|
|
|
|
| 127 |
if num_signals != 'None':
|
|
|
|
| 128 |
strong_buy_dates, strong_sell_dates, strong_hold_dates = signals_to_plot(
|
| 129 |
selected_indicator=selected_indicator,
|
| 130 |
num_signals=num_signals,
|
|
@@ -371,32 +378,21 @@ with news_analysis:
|
|
| 371 |
news = events[events['Date'].between(start_date, end_date, inclusive='both')]
|
| 372 |
news = news[['Date', 'Raw_Headline', 'Bold_KW', 'Feature', 'Raw_News', 'Sources', 'Urls']]
|
| 373 |
|
| 374 |
-
# pos_news = plot_sub_pos[['Date', 'Raw_Headline', 'Bold_KW', 'Feature', 'Raw_News', 'Sources', 'Urls']]
|
| 375 |
-
# neg_news = plot_sub_neg[['Date', 'Raw_Headline', 'Bold_KW', 'Feature', 'Raw_News', 'Sources', 'Urls']]
|
| 376 |
|
| 377 |
-
|
| 378 |
-
# pos_news[col] = pos_news[col].apply(convert_str_to_list)
|
| 379 |
-
# neg_news[col] = neg_news[col].apply(convert_str_to_list)
|
| 380 |
# Extract only the date part
|
| 381 |
news['Date'] = news['Date'].dt.date
|
| 382 |
-
|
| 383 |
-
# pos_news['Date'] = pos_news['Date'].dt.date
|
| 384 |
# Sort DataFrame based on the 'Date' column in descending order
|
| 385 |
news = news.sort_values(by='Date', ascending=False)
|
| 386 |
-
|
| 387 |
-
# pos_news = pos_news.sort_values(by='Date', ascending=False)
|
| 388 |
|
| 389 |
# Reset index to reflect the new order
|
| 390 |
news.reset_index(drop=True, inplace=True)
|
| 391 |
-
|
| 392 |
-
# neg_news.reset_index(drop=True, inplace=True)
|
| 393 |
st.subheader("News Events")
|
| 394 |
-
|
| 395 |
-
# st.table(news)
|
| 396 |
dates = list(news['Date'].unique())
|
| 397 |
-
|
| 398 |
-
# dates_pos = list(pos_news['Date'].unique())
|
| 399 |
-
# dates = dates_pos + dates_neg
|
| 400 |
dates = np.sort(dates)
|
| 401 |
# Reverse the array to have the latest date at index 0
|
| 402 |
dates = dates[::-1]
|
|
@@ -431,206 +427,14 @@ with news_analysis:
|
|
| 431 |
# st.divider()
|
| 432 |
with st.expander("Oil Sector Features"):
|
| 433 |
st.write(set(features))
|
| 434 |
-
|
| 435 |
-
# filtered_news = pos_news[pos_news['Date'] == date]
|
| 436 |
-
# print(filtered_news.shape)
|
| 437 |
-
# features = filtered_news['Feature'].sum()
|
| 438 |
-
# headlines = filtered_news['Raw_Headline'].sum()
|
| 439 |
-
# news_list = filtered_news['Raw_News'].sum()
|
| 440 |
-
# sources = filtered_news['Sources'].sum()
|
| 441 |
-
# urls = filtered_news['Urls'].sum()
|
| 442 |
-
|
| 443 |
-
# main_container = st.container(height = 250, border=True)
|
| 444 |
-
# # main_container.write(f"Date: {date}")
|
| 445 |
-
|
| 446 |
-
# col1, col2 = main_container.columns([0.7, 0.3], gap='medium')
|
| 447 |
-
|
| 448 |
-
# # Merge lists of headlines into a single list
|
| 449 |
-
# for index, headline in enumerate(headlines):
|
| 450 |
-
# col1.page_link(urls[index], label=f"**:blue[{headline}]**")
|
| 451 |
-
# # col1.write(f"<span style='font-size: large;'><b><u>{headline}</u></b></span>", unsafe_allow_html=True)
|
| 452 |
-
# col1.write(f"<span style='font-size: small;'>By {sources[index]}</span><br>", unsafe_allow_html=True)
|
| 453 |
-
# with col1:
|
| 454 |
-
# with st.expander("Show Full Article"):
|
| 455 |
-
# st.write(news_list[index])
|
| 456 |
-
|
| 457 |
-
# with col2:
|
| 458 |
-
# # st.divider()
|
| 459 |
-
# with st.expander("Oil Sector Features"):
|
| 460 |
-
# st.write(set(features))
|
| 461 |
-
|
| 462 |
-
# if date in dates_neg:
|
| 463 |
-
# filtered_news = neg_news[neg_news['Date'] == date]
|
| 464 |
-
# print(filtered_news.shape)
|
| 465 |
-
# features = filtered_news['Feature'].sum()
|
| 466 |
-
# headlines = filtered_news['Raw_Headline'].sum()
|
| 467 |
-
# news_list = filtered_news['Raw_News'].sum()
|
| 468 |
-
# sources = filtered_news['Sources'].sum()
|
| 469 |
-
# urls = filtered_news['Urls'].sum()
|
| 470 |
-
|
| 471 |
-
# main_container = st.container(height = 250, border=True)
|
| 472 |
-
# # main_container.write(f"Date: {date}")
|
| 473 |
-
|
| 474 |
-
# col1, col2 = main_container.columns([0.7, 0.3], gap='medium')
|
| 475 |
-
|
| 476 |
-
# # Merge lists of headlines into a single list
|
| 477 |
-
# for index, headline in enumerate(headlines):
|
| 478 |
-
# col1.page_link(urls[index], label=f"**:blue[{headline}]**")
|
| 479 |
-
# # col1.write(f"<span style='font-size: large;'><b><u>{headline}</u></b></span>", unsafe_allow_html=True)
|
| 480 |
-
# col1.write(f"<span style='font-size: small;'>By {sources[index]}</span><br>", unsafe_allow_html=True)
|
| 481 |
-
# with col1:
|
| 482 |
-
# with st.expander("Show Full Article"):
|
| 483 |
-
# st.write(news_list[index])
|
| 484 |
-
|
| 485 |
-
# with col2:
|
| 486 |
-
# # st.divider()
|
| 487 |
-
# with st.expander("Oil Sector Features"):
|
| 488 |
-
# st.write(set(features))
|
| 489 |
|
| 490 |
st.markdown("""
|
| 491 |
<div style='background-color:#b43c42; color:#ffffff; padding:8px; border-radius:3px; font-size:12px''>
|
| 492 |
<strong>Disclaimer:</strong> For demo purpose, the tool is currently populated with 10 months (Nov 2020 - Aug 2021) news and historical data of oil sector from PSX.
|
| 493 |
This data is intended to illustrate the tool's functionality and is not intended for actual investment decisions.
|
| 494 |
</div>
|
| 495 |
-
""", unsafe_allow_html=True)
|
| 496 |
-
# with trade_recs:
|
| 497 |
-
# st.header("Trading Recommendations")
|
| 498 |
-
|
| 499 |
-
# # Create the line trace for stock prices
|
| 500 |
-
# # Dropdown for selecting the indicator
|
| 501 |
-
# selected_indicator = st.selectbox("Indicator to Show", ['EMA 9', 'EMA 55', 'MACD', 'RSI'])
|
| 502 |
-
# if selected_indicator == 'EMA 9':
|
| 503 |
-
# column = 'EMA9_Signal'
|
| 504 |
-
# hover_text = '%{x}<br>Close: %{y}<br> EMA9_Signal: %{customdata}<br>'
|
| 505 |
-
# elif selected_indicator == 'EMA 55':
|
| 506 |
-
# column = 'EMA55_Signal'
|
| 507 |
-
# hover_text = '%{x}<br>Close: %{y}<br> EMA55_Signal: %{customdata}<br>'
|
| 508 |
-
# elif selected_indicator == 'MACD':
|
| 509 |
-
# column = 'MACD_Signals'
|
| 510 |
-
# hover_text = '%{x}<br>Close: %{y}<br> MACD_Signal: %{customdata}<br>'
|
| 511 |
-
# elif selected_indicator == 'RSI':
|
| 512 |
-
# column = 'RSI_Signals'
|
| 513 |
-
# hover_text = '%{x}<br>Close: %{y}<br> RSI_Signal: %{customdata}<br>'
|
| 514 |
-
# line_stock = go.Scatter(x=events['Date'], y=events['Price'], mode='lines', name='OGDCL Close Price',
|
| 515 |
-
# line=dict(dash='solid',color=cs.close_line_color, width=2), # color='royalblue'
|
| 516 |
-
# text=[column],
|
| 517 |
-
# # hovertext=events['FeatureSentiment'],
|
| 518 |
-
# customdata=events[column],
|
| 519 |
-
# hovertemplate=hover_text,
|
| 520 |
-
# # hoverlabel=dict(font=dict(color=events
|
| 521 |
-
# # ['FeatureSentiment'].apply(lambda x: 'red' if x == 'Negative' else 'blue' if x == 'Neutral' else 'green'))), # Customize the line style, color, and width
|
| 522 |
-
# )
|
| 523 |
-
# # Create dummy traces for the legend
|
| 524 |
-
# dummy_positive = go.Scatter(x=[None], y=[None], mode='lines', name='Positive Impacts',
|
| 525 |
-
# marker=dict(color=cs.pos_impacts_color, size=15), showlegend=True,
|
| 526 |
-
# # visible='legendonly'
|
| 527 |
-
# )
|
| 528 |
-
# dummy_negative = go.Scatter(x=[None], y=[None], mode='lines', name='Negative Impacts',
|
| 529 |
-
# marker=dict(color=cs.neg_impacts_color, size=15), showlegend=True,
|
| 530 |
-
# # visible='legendonly'
|
| 531 |
-
# )
|
| 532 |
-
|
| 533 |
-
# fontsize = 12
|
| 534 |
-
# annotations = []
|
| 535 |
-
# # Create annotations for the Positive points
|
| 536 |
-
# for index, row in plot_sub_pos.iterrows():
|
| 537 |
-
# annotation1 = dict(x=row['Date'], y=row['Price'], text = row['Positive_Impacts'],
|
| 538 |
-
# showarrow=True, arrowhead=0, # arrowcolor='black',
|
| 539 |
-
# ax=10, ay=-20, # Dynamic offset
|
| 540 |
-
# font=dict(size=fontsize, color=cs.pos_impacts_color),
|
| 541 |
-
# )
|
| 542 |
-
# annotations.append(annotation1)
|
| 543 |
-
|
| 544 |
-
# # Create annotations for the Negative points
|
| 545 |
-
# for index, row in plot_sub_neg.iterrows():
|
| 546 |
-
# annotation2 = dict(x=row['Date'], y=row['Price'], text = row['Negative_Impacts'],
|
| 547 |
-
# showarrow=True, arrowhead=0, arrowcolor=cs.close_line_color,
|
| 548 |
-
# ax=10, ay=-20, # Dynamic offset
|
| 549 |
-
# font=dict(size=fontsize, color=cs.neg_impacts_color),
|
| 550 |
-
# )
|
| 551 |
-
# annotations.append(annotation2)
|
| 552 |
-
|
| 553 |
-
# # Create the layout
|
| 554 |
-
# title = 'OGDCL Close Price w.r.t. News Impacts'
|
| 555 |
-
# layout = go.Layout(
|
| 556 |
-
# title=title,
|
| 557 |
-
# xaxis=dict(
|
| 558 |
-
# title='Date',
|
| 559 |
-
# tickformat='%b %d, %Y',
|
| 560 |
-
# # gridcolor='lightgray',
|
| 561 |
-
# range=[start_date, end_date],
|
| 562 |
-
# # tickvals=list(range(dateA, dateB, 3)),
|
| 563 |
-
# ),
|
| 564 |
-
# yaxis=dict(
|
| 565 |
-
# title='OGDCL Close Price',
|
| 566 |
-
# # gridcolor='lightgray',
|
| 567 |
-
# range=[90, 120],
|
| 568 |
-
# tickvals=list(range(90, 120, 5)),
|
| 569 |
-
# ),
|
| 570 |
-
# # plot_bgcolor='rgba(245, 245, 245, 0.8)',
|
| 571 |
-
# # paper_bgcolor='white',
|
| 572 |
-
# # hoverlabel=dict(
|
| 573 |
-
# # bgcolor='white',
|
| 574 |
-
# # font=dict(color='black'),
|
| 575 |
-
# # ),
|
| 576 |
-
# annotations=annotations,
|
| 577 |
-
# )
|
| 578 |
-
|
| 579 |
-
# # Add all traces to the figure
|
| 580 |
-
# figure = go.Figure(data=[line_stock, dummy_negative, dummy_positive], layout=layout)
|
| 581 |
-
# # figure.update_traces(mode="markers+lines")
|
| 582 |
-
# figure.update_layout(
|
| 583 |
-
# title={
|
| 584 |
-
# 'text': title,
|
| 585 |
-
# 'x': 0.5,
|
| 586 |
-
# 'y': 0.95,
|
| 587 |
-
# 'xanchor': 'center',
|
| 588 |
-
# 'yanchor': 'top',
|
| 589 |
-
# 'font': dict(size=12),
|
| 590 |
-
# },
|
| 591 |
-
# hovermode='closest',
|
| 592 |
-
# margin=dict(l=40, r=40, t=80, b=40),
|
| 593 |
-
# )
|
| 594 |
-
# figure.update_xaxes(
|
| 595 |
-
# rangeslider_visible=True,
|
| 596 |
-
# rangeselector=dict(
|
| 597 |
-
# buttons=list([
|
| 598 |
-
# dict(count=1, label="1m", step="month", stepmode="backward"),
|
| 599 |
-
# dict(count=6, label="6m", step="month", stepmode="backward"),
|
| 600 |
-
# dict(count=1, label="YTD", step="year", stepmode="todate"),
|
| 601 |
-
# dict(count=1, label="1y", step="year", stepmode="backward"),
|
| 602 |
-
# dict(step="all")
|
| 603 |
-
# ])
|
| 604 |
-
# )
|
| 605 |
-
# )
|
| 606 |
-
# st.plotly_chart(figure)
|
| 607 |
-
# if 'Trading_Recommendations\r' in events.columns:
|
| 608 |
-
# events.rename(columns={'Trading_Recommendations\r': 'Trading_Recommendations'}, inplace=True)
|
| 609 |
-
|
| 610 |
-
# print(events.columns)
|
| 611 |
-
# trade_recs = events[['Date', 'Trading_Recommendations']]
|
| 612 |
-
# # Extract date component from the datetime column
|
| 613 |
-
# trade_recs['Date'] = trade_recs['Date'].dt.date
|
| 614 |
-
# # Convert back to Dictionaries from strings
|
| 615 |
-
# trade_recs['Trading_Recommendations'] = trade_recs['Trading_Recommendations'].apply(convert_str_to_list)
|
| 616 |
-
# dates = list(trade_recs['Date'].unique())
|
| 617 |
-
# dates = np.sort(dates)
|
| 618 |
-
# # Reverse the array to have the latest date at index 0
|
| 619 |
-
# dates = dates[::-1]
|
| 620 |
-
# num_dates = len(dates)
|
| 621 |
-
# items_per_page = min(num_dates, 5)
|
| 622 |
-
# for i, date in paginator("Select Page Number", dates, items_per_page=items_per_page, on_sidebar=False, ukey='trade_pages'):
|
| 623 |
-
# st.write(f'<span style="font-size: large;"><b>Date:</b> <u>{date}</u></span>', unsafe_allow_html=True)
|
| 624 |
-
|
| 625 |
-
# filtered_trades = trade_recs[trade_recs['Date'] == date]
|
| 626 |
-
# filtered_trades.reset_index(inplace=True)
|
| 627 |
-
# rec = filtered_trades['Trading_Recommendations'][0]
|
| 628 |
-
# print(type(rec), rec)
|
| 629 |
-
# trade_container = st.container(border=False)
|
| 630 |
-
# trade_container.write(rec)
|
| 631 |
-
|
| 632 |
-
# # st.write(trade_recs)
|
| 633 |
-
|
| 634 |
|
| 635 |
|
| 636 |
with final_recs:
|
|
@@ -775,104 +579,9 @@ with final_recs:
|
|
| 775 |
</div>
|
| 776 |
""", unsafe_allow_html=True)
|
| 777 |
|
|
|
|
| 778 |
with chat:
|
| 779 |
-
st.header("Chat with AI Stock Advisor")
|
| 780 |
|
| 781 |
-
from langchain.indexes import VectorstoreIndexCreator
|
| 782 |
-
from langchain.chains import RetrievalQA
|
| 783 |
-
from langchain.llms import OpenAI
|
| 784 |
-
from langchain_community.document_loaders import CSVLoader
|
| 785 |
-
from langchain_text_splitters import RecursiveCharacterTextSplitter
|
| 786 |
-
# from langchain_community.text_splitter import RecursiveCharacterTextSplitter
|
| 787 |
-
from langchain_community.embeddings import HuggingFaceInstructEmbeddings
|
| 788 |
-
from langchain_community.vectorstores import FAISS
|
| 789 |
-
from langchain_community.llms import HuggingFaceHub
|
| 790 |
-
from langchain_core.prompts import PromptTemplate
|
| 791 |
-
|
| 792 |
-
def get_answer(text):
|
| 793 |
-
text = response['result']
|
| 794 |
-
helpful_answer_index = text.find('Helpful Answer:')
|
| 795 |
-
if helpful_answer_index != -1:
|
| 796 |
-
helpful_answer = text[helpful_answer_index + len('Helpful Answer:'):].strip()
|
| 797 |
-
print(helpful_answer)
|
| 798 |
-
else:
|
| 799 |
-
print("No helpful answer found.")
|
| 800 |
-
return helpful_answer
|
| 801 |
-
|
| 802 |
-
# Streamed response emulator
|
| 803 |
-
def response_generator(answer):
|
| 804 |
-
response = answer
|
| 805 |
-
for word in response.split():
|
| 806 |
-
yield word + " "
|
| 807 |
-
time.sleep(0.05)
|
| 808 |
-
|
| 809 |
-
print("Libraries imported")
|
| 810 |
-
|
| 811 |
-
loader = CSVLoader("Events_SameDay.csv",encoding='iso-8859-1')
|
| 812 |
-
print("CSV imported")
|
| 813 |
-
|
| 814 |
-
# Create an index using the loaded documents
|
| 815 |
-
try:
|
| 816 |
-
index_creator = VectorstoreIndexCreator()
|
| 817 |
-
print("index_creator Created")
|
| 818 |
-
|
| 819 |
-
docsearch = index_creator.from_loaders([loader])
|
| 820 |
-
print("DB Created")
|
| 821 |
-
|
| 822 |
-
repo_id = "mistralai/Mistral-7B-Instruct-v0.1"
|
| 823 |
-
llm = HuggingFaceHub(repo_id=repo_id, model_kwargs={"temperature": 0.1, "max_new_tokens": 1024})
|
| 824 |
-
print("MistralAi Loaded")
|
| 825 |
-
|
| 826 |
-
prompt_temp="As a financial expert for stock market, if user is asking for trading recommendation, then you need to generate trading signal recommendations utilizing insights from two approaches. One is the technical indicators signals EMA55, RSI, EMA9, and MACD (all ranging from -3 to 3, where –3 is strong sell, -2 is moderate sell, -1 is weak sell, 0 is for hold, 1 is for weak buy, 2 is for moderate buy and 3 is for strong buy) from the respective signal while other insight is from news impacts (either positive or negative between -5 to 5). Provide your recommendation with balanced approach if news impact is too much positive or negative, technical indicator can be ignored and buy or sell suggestion based on news impact can be given. On the contrary, if technical indicators are opposite to news impact, a hold position is a reasonable suggestion. If technical indicators are all positive along news impact, strong buy signal can be generated. If technical indicators and news impact are all negative a strong sell signal can be generated. If news impact is too low, then generate recommendation based on technical indicator specially with more weightage to ema 55 in all the technical indicators. Your response should cover all technical aspects including the analysis of technical indicators as well as covering the news sentiments. Also cover some logical financial rational as well as the explanations."
|
| 827 |
-
# Create a question-answering chain using the index
|
| 828 |
-
chain = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=docsearch.vectorstore.as_retriever(), input_key="question")
|
| 829 |
-
print("Chain Created")
|
| 830 |
-
|
| 831 |
-
# Initialize chat history
|
| 832 |
-
if "messages" not in st.session_state:
|
| 833 |
-
st.session_state.messages = []
|
| 834 |
-
|
| 835 |
-
# Display chat messages from history on app rerun
|
| 836 |
-
for message in st.session_state.messages:
|
| 837 |
-
with st.chat_message(message["role"]):
|
| 838 |
-
st.markdown(message["content"])
|
| 839 |
-
|
| 840 |
-
# Accept user input
|
| 841 |
-
if prompt := st.chat_input("Enter your query here."):
|
| 842 |
-
# Add user message to chat history
|
| 843 |
-
st.session_state.messages.append({"role": "user", "content": prompt})
|
| 844 |
-
# Display user message in chat message container
|
| 845 |
-
with st.chat_message("user"):
|
| 846 |
-
st.markdown(prompt)
|
| 847 |
-
|
| 848 |
-
# question = query
|
| 849 |
-
print(f"User Question: {prompt}")
|
| 850 |
-
response = chain({"question": prompt})
|
| 851 |
-
print("Answer generated")
|
| 852 |
-
result = get_answer(response['result'])
|
| 853 |
-
print("helpful answer extracted")
|
| 854 |
-
|
| 855 |
-
# Display assistant response in chat message container
|
| 856 |
-
with st.chat_message("assistant"):
|
| 857 |
-
response = st.write_stream(response_generator(result))
|
| 858 |
-
# Add assistant response to chat history
|
| 859 |
-
st.session_state.messages.append({"role": "assistant", "content": response})
|
| 860 |
-
except Exception as e:
|
| 861 |
-
print(f"error type: {type(e)}")
|
| 862 |
-
if hasattr(e, 'message') and 'You exceeded your current quota' in e.message:
|
| 863 |
-
st.markdown(':red[Insufficient Quota]')
|
| 864 |
-
st.write(f'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.')
|
| 865 |
-
|
| 866 |
-
else:
|
| 867 |
-
st.markdown(f"An Error Occured: \n {e}")
|
| 868 |
-
|
| 869 |
-
with chat2:
|
| 870 |
-
from langchain_community.document_loaders import CSVLoader
|
| 871 |
-
from langchain_community.embeddings import HuggingFaceInstructEmbeddings
|
| 872 |
-
from langchain_community.vectorstores import FAISS
|
| 873 |
-
from langchain_community.llms import HuggingFaceHub
|
| 874 |
-
from langchain_core.prompts import PromptTemplate
|
| 875 |
-
from langchain.chains import RetrievalQA
|
| 876 |
|
| 877 |
st.header("Chat with AI Stock Advisor")
|
| 878 |
|
|
@@ -916,21 +625,23 @@ with chat2:
|
|
| 916 |
input_key="question",
|
| 917 |
chain_type_kwargs={"prompt": sys_prompt})
|
| 918 |
|
| 919 |
-
|
| 920 |
-
|
| 921 |
-
|
| 922 |
-
|
| 923 |
-
|
| 924 |
-
|
| 925 |
-
|
| 926 |
-
|
|
|
|
|
|
|
| 927 |
|
| 928 |
# Accept user input
|
| 929 |
if prompt := st.chat_input("Enter your query here.", key='input2'):
|
| 930 |
# Add user message to chat history
|
| 931 |
st.session_state.messages.append({"role": "user", "content": prompt})
|
| 932 |
# Display user message in chat message container
|
| 933 |
-
with
|
| 934 |
st.markdown(prompt)
|
| 935 |
|
| 936 |
# question = query
|
|
@@ -941,7 +652,7 @@ with chat2:
|
|
| 941 |
print("helpful answer extracted")
|
| 942 |
|
| 943 |
# Display assistant response in chat message container
|
| 944 |
-
with
|
| 945 |
response = st.write_stream(response_generator(result))
|
| 946 |
# Add assistant response to chat history
|
| 947 |
st.session_state.messages.append({"role": "assistant", "content": response})
|
|
|
|
| 1 |
+
# Import Necessary Libraries
|
| 2 |
import streamlit as st
|
| 3 |
import pandas as pd
|
| 4 |
import plotly.express as px
|
|
|
|
| 8 |
import ast
|
| 9 |
from pagination import paginator
|
| 10 |
import style as cs
|
|
|
|
| 11 |
import random
|
| 12 |
import time
|
| 13 |
+
from langchain_community.document_loaders import CSVLoader
|
| 14 |
+
from langchain_community.embeddings import HuggingFaceInstructEmbeddings
|
| 15 |
+
from langchain_community.vectorstores import FAISS
|
| 16 |
+
from langchain_community.llms import HuggingFaceHub
|
| 17 |
+
from langchain_core.prompts import PromptTemplate
|
| 18 |
+
from langchain.chains import RetrievalQA
|
| 19 |
|
| 20 |
|
| 21 |
# Utils Functions
|
|
|
|
| 71 |
# If the string cannot be converted to a list, return it as is
|
| 72 |
return string
|
| 73 |
|
| 74 |
+
|
| 75 |
+
# Add Title and Logo
|
| 76 |
+
title_container = st.container(border=False) # Create a container to hold the tile and logo
|
| 77 |
+
col1, col2 = title_container.columns([0.2, 0.8], gap='medium') # Create columns to display logo and title side-by-side
|
| 78 |
+
col1.image("logo.png") # Add logo to the 1st column
|
| 79 |
+
col2.title("AI Equity Advisor") # Add title to the 2nd column
|
| 80 |
+
|
| 81 |
+
# Add credits below the title
|
| 82 |
c1, c2 = col2.columns([0.5, 0.5], gap="large")
|
| 83 |
c1.markdown("Powered by GenInstigators")
|
| 84 |
+
|
| 85 |
+
# Load Technical Data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
data_file_path = r"technicalRecommendation.csv" # Update this with your file path
|
| 87 |
data = pd.read_csv(data_file_path)
|
| 88 |
|
| 89 |
# Convert 'Date' column to datetime format
|
| 90 |
data['Date'] = pd.to_datetime(data['Date'])
|
|
|
|
| 91 |
|
| 92 |
+
# Set date limit for end date picker
|
| 93 |
+
date_limit = pd.to_datetime(data['Date'].max())
|
| 94 |
+
|
| 95 |
+
# Set default current date
|
| 96 |
current_date = pd.to_datetime('2021-08-12')
|
| 97 |
|
| 98 |
# Create Tabs
|
| 99 |
+
market_analysis, news_analysis, final_recs, chat = st.tabs(["Market Analysis", "News Analysis", "GenAI Recommendations", "Ask AI Advisor"])
|
|
|
|
| 100 |
|
| 101 |
with market_analysis:
|
| 102 |
st.header("Market Analysis", help = "This module provides market analysis for the following day based on the current date.")
|
| 103 |
# st.write("This module provides market analysis for the following day based on the current date.")
|
| 104 |
+
|
| 105 |
+
# Add date picker
|
| 106 |
+
date_container = st.container(border=False)
|
| 107 |
col1, col2 = date_container.columns([0.5, 0.5], gap='medium')
|
| 108 |
# start_date = col1.date_input('Start Date', value=default_start_date, min_value=data['Date'].min(), max_value=date_limit)
|
| 109 |
end_date = col1.date_input("Current Date", value=current_date, min_value=data['Date'].min(), max_value=date_limit)
|
| 110 |
+
|
| 111 |
+
# Filter data based on the date selected by the user
|
| 112 |
+
start_date = pd.to_datetime(data['Date'].min())
|
| 113 |
end_date = pd.to_datetime(end_date)
|
| 114 |
data2 = data[data['Date'].between(start_date, end_date)]
|
| 115 |
|
| 116 |
# Dropdown for selecting the indicator
|
| 117 |
selected_indicator = st.selectbox("Select an Indicator", ['EMA 9', 'EMA 55', 'MACD', 'RSI'])
|
| 118 |
+
|
| 119 |
# Dropdown for selecting the Number of Signal Days
|
| 120 |
num_signals = st.selectbox("Signals to Show", ['None', 'All', 'Last 5 Days', 'Last 15 Days', 'Last 20 Days'])
|
| 121 |
+
|
| 122 |
+
# Rename columns to maintain naming convention
|
| 123 |
data2.rename(columns={'Close_price': 'Close Price', 'EMA_9': 'EMA 9', 'EMA_55': 'EMA 55'}, inplace=True)
|
| 124 |
+
|
| 125 |
+
# Plot Close Price vs the indicator selected by the user
|
| 126 |
if selected_indicator == 'EMA 9':
|
| 127 |
# Plot close price and EMA 9
|
| 128 |
fig = px.line(data2, x='Date', y=['Close Price', 'EMA 9'], title='Close Price vs EMA 9',
|
| 129 |
labels={'Date': 'Date', 'value': 'Price in Rs.', 'variable': 'Type'})
|
| 130 |
fig.update_traces(selector=dict(type='scatter'))
|
| 131 |
+
|
| 132 |
+
# Plot buy/sell signals
|
| 133 |
if num_signals != 'None':
|
| 134 |
+
# get signal values using the signals_to_plot function
|
| 135 |
strong_buy_dates, strong_sell_dates, strong_hold_dates = signals_to_plot(
|
| 136 |
selected_indicator=selected_indicator,
|
| 137 |
num_signals=num_signals,
|
|
|
|
| 378 |
news = events[events['Date'].between(start_date, end_date, inclusive='both')]
|
| 379 |
news = news[['Date', 'Raw_Headline', 'Bold_KW', 'Feature', 'Raw_News', 'Sources', 'Urls']]
|
| 380 |
|
|
|
|
|
|
|
| 381 |
|
|
|
|
|
|
|
|
|
|
| 382 |
# Extract only the date part
|
| 383 |
news['Date'] = news['Date'].dt.date
|
| 384 |
+
|
|
|
|
| 385 |
# Sort DataFrame based on the 'Date' column in descending order
|
| 386 |
news = news.sort_values(by='Date', ascending=False)
|
| 387 |
+
|
|
|
|
| 388 |
|
| 389 |
# Reset index to reflect the new order
|
| 390 |
news.reset_index(drop=True, inplace=True)
|
| 391 |
+
|
|
|
|
| 392 |
st.subheader("News Events")
|
| 393 |
+
|
|
|
|
| 394 |
dates = list(news['Date'].unique())
|
| 395 |
+
|
|
|
|
|
|
|
| 396 |
dates = np.sort(dates)
|
| 397 |
# Reverse the array to have the latest date at index 0
|
| 398 |
dates = dates[::-1]
|
|
|
|
| 427 |
# st.divider()
|
| 428 |
with st.expander("Oil Sector Features"):
|
| 429 |
st.write(set(features))
|
| 430 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 431 |
|
| 432 |
st.markdown("""
|
| 433 |
<div style='background-color:#b43c42; color:#ffffff; padding:8px; border-radius:3px; font-size:12px''>
|
| 434 |
<strong>Disclaimer:</strong> For demo purpose, the tool is currently populated with 10 months (Nov 2020 - Aug 2021) news and historical data of oil sector from PSX.
|
| 435 |
This data is intended to illustrate the tool's functionality and is not intended for actual investment decisions.
|
| 436 |
</div>
|
| 437 |
+
""", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
|
| 439 |
|
| 440 |
with final_recs:
|
|
|
|
| 579 |
</div>
|
| 580 |
""", unsafe_allow_html=True)
|
| 581 |
|
| 582 |
+
|
| 583 |
with chat:
|
|
|
|
| 584 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 585 |
|
| 586 |
st.header("Chat with AI Stock Advisor")
|
| 587 |
|
|
|
|
| 625 |
input_key="question",
|
| 626 |
chain_type_kwargs={"prompt": sys_prompt})
|
| 627 |
|
| 628 |
+
chat_container = st.container(height = 300, border=False)
|
| 629 |
+
with chat_container:
|
| 630 |
+
# Initialize chat history
|
| 631 |
+
if "messages" not in st.session_state:
|
| 632 |
+
st.session_state.messages = []
|
| 633 |
+
|
| 634 |
+
# Display chat messages from history on app rerun
|
| 635 |
+
for message in st.session_state.messages:
|
| 636 |
+
with st.chat_message(message["role"]):
|
| 637 |
+
st.markdown(message["content"])
|
| 638 |
|
| 639 |
# Accept user input
|
| 640 |
if prompt := st.chat_input("Enter your query here.", key='input2'):
|
| 641 |
# Add user message to chat history
|
| 642 |
st.session_state.messages.append({"role": "user", "content": prompt})
|
| 643 |
# Display user message in chat message container
|
| 644 |
+
with chat_container.chat_message("user"):
|
| 645 |
st.markdown(prompt)
|
| 646 |
|
| 647 |
# question = query
|
|
|
|
| 652 |
print("helpful answer extracted")
|
| 653 |
|
| 654 |
# Display assistant response in chat message container
|
| 655 |
+
with chat_container.chat_message("assistant"):
|
| 656 |
response = st.write_stream(response_generator(result))
|
| 657 |
# Add assistant response to chat history
|
| 658 |
st.session_state.messages.append({"role": "assistant", "content": response})
|