Update app.py
Browse files
app.py
CHANGED
|
@@ -106,7 +106,7 @@ class StockAdviserUI:
|
|
| 106 |
|
| 107 |
def _setup_header(self):
|
| 108 |
st.markdown("<h1 class='main-header'>Stock Analysis with Generative AI</h1>", unsafe_allow_html=True)
|
| 109 |
-
st.markdown("<h3 class='main-header'>using RAG</h3>", unsafe_allow_html=True)
|
| 110 |
with st.expander("Available Historical Demo Companies"):
|
| 111 |
st.markdown("""
|
| 112 |
For Demo purpose, historical data is available only for the below companies:
|
|
@@ -219,6 +219,91 @@ class StockAdviser:
|
|
| 219 |
self.config.models.embedding_model = embedding_model
|
| 220 |
return self.config.models
|
| 221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
def get_symbol(self, user_question):
|
| 223 |
qna_system_message = """
|
| 224 |
You are an assistant to a financial services firm who finds the 'nse company symbol' (assigned to the company in the provided stock market)) of the company in the question provided.
|
|
@@ -258,8 +343,7 @@ class StockAdviser:
|
|
| 258 |
return cmp_tkr
|
| 259 |
|
| 260 |
|
| 261 |
-
def process_historical_data(self,
|
| 262 |
-
cmp_tr = self.get_symbol(user_question)
|
| 263 |
|
| 264 |
# Initialize ChromaDB Database
|
| 265 |
chroma_db = DBStorage(hugg)
|
|
@@ -274,8 +358,7 @@ class StockAdviser:
|
|
| 274 |
|
| 275 |
return cmp_tr
|
| 276 |
|
| 277 |
-
def display_charts(self,cmp_tr,sentiment_response):
|
| 278 |
-
sentiment = self._extract_between(sentiment_response, "Overall Sentiment:", "Overall Justification:").strip()
|
| 279 |
|
| 280 |
days = 365
|
| 281 |
|
|
@@ -318,18 +401,21 @@ class StockAdviser:
|
|
| 318 |
# Display volume chart
|
| 319 |
st.plotly_chart(self.visualizer.create_volume_chart(df, cmp_tr))
|
| 320 |
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
|
|
|
|
|
|
|
|
|
| 333 |
|
| 334 |
def get_nse_stock_data(self,symbol, days):
|
| 335 |
"""
|
|
@@ -623,6 +709,34 @@ class StockAdviser:
|
|
| 623 |
|
| 624 |
return base_prompt + example_analysis + response_format + common_format + citation_format + instr + instr2, dcument
|
| 625 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 626 |
|
| 627 |
def main(hugg):
|
| 628 |
adviser = StockAdviser()
|
|
@@ -635,62 +749,62 @@ def main(hugg):
|
|
| 635 |
)
|
| 636 |
|
| 637 |
with st.sidebar:
|
| 638 |
-
|
| 639 |
st.markdown("""
|
| 640 |
<div style="background-color: #2d2d2d; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(255, 255, 255, 0.1);">
|
| 641 |
-
<h2 style="color: #e6e6e6; text-align:
|
| 642 |
-
<p style="font-size: 16px; color: #
|
| 643 |
-
This application provides investment managers with daily insights into
|
| 644 |
-
|
| 645 |
-
<
|
| 646 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 647 |
</p>
|
| 648 |
-
<p style="font-size: 16px; color: #
|
| 649 |
-
|
| 650 |
-
|
| 651 |
-
|
| 652 |
-
sentiment-driven market.
|
| 653 |
</p>
|
| 654 |
</div>
|
| 655 |
-
|
| 656 |
""", unsafe_allow_html=True)
|
|
|
|
| 657 |
# Sidebar Footer (Floating Footer)
|
| 658 |
st.sidebar.markdown("""
|
| 659 |
-
<div style="position: fixed; bottom:
|
| 660 |
-
<p style="color: #cccccc; font-size: 14px;">
|
| 661 |
Developed by: <a href="https://www.linkedin.com/in/karthikeyen92/" target="_blank" style="color: #4DA8DA; text-decoration: none;">Karthikeyen Packirisamy</a>
|
| 662 |
</p>
|
| 663 |
</div>
|
| 664 |
""", unsafe_allow_html=True)
|
| 665 |
-
|
| 666 |
|
| 667 |
|
| 668 |
# Main content
|
| 669 |
cmp_tr = "NOTICKER"
|
| 670 |
st.header("Ask a question")
|
| 671 |
-
user_question = st.text_input("
|
| 672 |
-
|
| 673 |
-
col1, col2 = st.columns(2)
|
| 674 |
-
|
| 675 |
-
with col1:
|
| 676 |
-
if user_question:
|
| 677 |
-
st.markdown("<h3 class='little-header'>Historical Analysis</h3>", unsafe_allow_html=True)
|
| 678 |
-
with st.container():
|
| 679 |
-
cmp_tr = adviser.process_historical_data(user_question, hugg)
|
| 680 |
-
|
| 681 |
-
with col2:
|
| 682 |
-
if user_question:
|
| 683 |
-
st.markdown("<h3 class='little-header'>Real-Time Analysis</h3>", unsafe_allow_html=True)
|
| 684 |
-
with st.container():
|
| 685 |
-
sentiment_response = adviser.process_realtime_data(cmp_tr, hugg)
|
| 686 |
-
|
| 687 |
-
if (str(cmp_tr) != "NOTICKER"):
|
| 688 |
-
with st.container():
|
| 689 |
-
if user_question:
|
| 690 |
-
adviser.display_charts(cmp_tr,sentiment_response)
|
| 691 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 692 |
st.markdown("---")
|
| 693 |
-
st.markdown("<p style='text-align: center; color: #666;'>© 2024
|
| 694 |
|
| 695 |
if __name__ == "__main__":
|
| 696 |
hugg = os.getenv("IS_HUGG") == "True"
|
|
|
|
| 106 |
|
| 107 |
def _setup_header(self):
|
| 108 |
st.markdown("<h1 class='main-header'>Stock Analysis with Generative AI</h1>", unsafe_allow_html=True)
|
| 109 |
+
st.markdown("<h3 class='main-header'>using Agents and RAG</h3>", unsafe_allow_html=True)
|
| 110 |
with st.expander("Available Historical Demo Companies"):
|
| 111 |
st.markdown("""
|
| 112 |
For Demo purpose, historical data is available only for the below companies:
|
|
|
|
| 219 |
self.config.models.embedding_model = embedding_model
|
| 220 |
return self.config.models
|
| 221 |
|
| 222 |
+
def stock_agent(self, user_question):
|
| 223 |
+
functions=[
|
| 224 |
+
{
|
| 225 |
+
"name":"get_advise",
|
| 226 |
+
"description":"Get only advise on a NSE stock",
|
| 227 |
+
"parameters":{
|
| 228 |
+
"type":"object",
|
| 229 |
+
"properties":{
|
| 230 |
+
"company":{
|
| 231 |
+
"type":"string",
|
| 232 |
+
"description":"Please find the 'nse company symbol' of the company in the question provided. In case of an invalid company, return 'NOTICKER'.",
|
| 233 |
+
},
|
| 234 |
+
|
| 235 |
+
},
|
| 236 |
+
"required":["company"]
|
| 237 |
+
},
|
| 238 |
+
},
|
| 239 |
+
{
|
| 240 |
+
"name":"get_stats",
|
| 241 |
+
"description":"Get only statistics/status on a NSE stock",
|
| 242 |
+
"parameters":{
|
| 243 |
+
"type":"object",
|
| 244 |
+
"properties":{
|
| 245 |
+
"company":{
|
| 246 |
+
"type":"string",
|
| 247 |
+
"description":"Please find the 'nse company symbol' of the company in the question provided. In case of an invalid company, return 'NOTICKER'.",
|
| 248 |
+
},
|
| 249 |
+
|
| 250 |
+
},
|
| 251 |
+
"required":["company"]
|
| 252 |
+
},
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"name":"get_adv_stats",
|
| 256 |
+
"description":"Get both advise and statistics/status on a NSE stock",
|
| 257 |
+
"parameters":{
|
| 258 |
+
"type":"object",
|
| 259 |
+
"properties":{
|
| 260 |
+
"company":{
|
| 261 |
+
"type":"string",
|
| 262 |
+
"description":"Please find the 'nse company symbol' of the company in the question provided. In case of an invalid company, return 'NOTICKER'.",
|
| 263 |
+
},
|
| 264 |
+
|
| 265 |
+
},
|
| 266 |
+
"required":["company"]
|
| 267 |
+
},
|
| 268 |
+
},
|
| 269 |
+
{
|
| 270 |
+
"name":"get_none",
|
| 271 |
+
"description":"Get details other than advise or statistics/status on a NSE stock",
|
| 272 |
+
"parameters":{
|
| 273 |
+
"type":"object",
|
| 274 |
+
"properties":{
|
| 275 |
+
"company":{
|
| 276 |
+
"type":"string",
|
| 277 |
+
"description":"""
|
| 278 |
+
For any queries other than advise or statistics/status on a NSE stock, only return "NOTICKER".
|
| 279 |
+
""",
|
| 280 |
+
},
|
| 281 |
+
|
| 282 |
+
},
|
| 283 |
+
"required":["company"]
|
| 284 |
+
},
|
| 285 |
+
}
|
| 286 |
+
]
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
initial_response = self.client.chat.completions.create(
|
| 290 |
+
model=self.config.azure_config["model_deployment"],
|
| 291 |
+
messages=[
|
| 292 |
+
{"role": "system", "content": "You are a helpful assistant to understand the context of input query on NSE stock advise and statistics."},
|
| 293 |
+
{"role": "user", "content": user_question}
|
| 294 |
+
],
|
| 295 |
+
functions=functions
|
| 296 |
+
)
|
| 297 |
+
|
| 298 |
+
print (initial_response)
|
| 299 |
+
function_name = initial_response.choices[0].message.function_call.name
|
| 300 |
+
function_argument = json.loads(initial_response.choices[0].message.function_call.arguments)
|
| 301 |
+
company= function_argument['company']
|
| 302 |
+
print(function_name)
|
| 303 |
+
print(company)
|
| 304 |
+
return function_name
|
| 305 |
+
|
| 306 |
+
|
| 307 |
def get_symbol(self, user_question):
|
| 308 |
qna_system_message = """
|
| 309 |
You are an assistant to a financial services firm who finds the 'nse company symbol' (assigned to the company in the provided stock market)) of the company in the question provided.
|
|
|
|
| 343 |
return cmp_tkr
|
| 344 |
|
| 345 |
|
| 346 |
+
def process_historical_data(self, cmp_tr, hugg = False):
|
|
|
|
| 347 |
|
| 348 |
# Initialize ChromaDB Database
|
| 349 |
chroma_db = DBStorage(hugg)
|
|
|
|
| 358 |
|
| 359 |
return cmp_tr
|
| 360 |
|
| 361 |
+
def display_charts(self,cmp_tr,sentiment_response="none"):
|
|
|
|
| 362 |
|
| 363 |
days = 365
|
| 364 |
|
|
|
|
| 401 |
# Display volume chart
|
| 402 |
st.plotly_chart(self.visualizer.create_volume_chart(df, cmp_tr))
|
| 403 |
|
| 404 |
+
if sentiment_response != "none":
|
| 405 |
+
sentiment = self._extract_between(sentiment_response, "Overall Sentiment:", "Overall Justification:").strip()
|
| 406 |
+
|
| 407 |
+
# Display sentiment gauge (simulate sentiment score)
|
| 408 |
+
# Generating random score for Demo purpose
|
| 409 |
+
if sentiment == "Negative":
|
| 410 |
+
sentiment_score = np.random.uniform(-1, -0.75)
|
| 411 |
+
elif sentiment == "Neutral":
|
| 412 |
+
sentiment_score = np.random.uniform(-0.75, 0.25)
|
| 413 |
+
elif sentiment == "Positive":
|
| 414 |
+
sentiment_score = np.random.uniform(0.25, 1)
|
| 415 |
+
else:
|
| 416 |
+
sentiment_score = 0
|
| 417 |
+
|
| 418 |
+
st.plotly_chart(self.visualizer.create_sentiment_gauge(sentiment_score))
|
| 419 |
|
| 420 |
def get_nse_stock_data(self,symbol, days):
|
| 421 |
"""
|
|
|
|
| 709 |
|
| 710 |
return base_prompt + example_analysis + response_format + common_format + citation_format + instr + instr2, dcument
|
| 711 |
|
| 712 |
+
def get_advise(user_question,adviser,cmp_tr,sentiment_response,hugg):
|
| 713 |
+
col1, col2 = st.columns(2)
|
| 714 |
+
with col1:
|
| 715 |
+
if user_question:
|
| 716 |
+
st.markdown("<h3 class='little-header'>Historical Analysis</h3>", unsafe_allow_html=True)
|
| 717 |
+
with st.container():
|
| 718 |
+
adviser.process_historical_data(cmp_tr, hugg)
|
| 719 |
+
|
| 720 |
+
with col2:
|
| 721 |
+
if user_question:
|
| 722 |
+
st.markdown("<h3 class='little-header'>Real-Time Analysis</h3>", unsafe_allow_html=True)
|
| 723 |
+
with st.container():
|
| 724 |
+
sentiment_response = adviser.process_realtime_data(cmp_tr, hugg)
|
| 725 |
+
|
| 726 |
+
return sentiment_response
|
| 727 |
+
|
| 728 |
+
def get_stats(user_question,adviser,cmp_tr,sentiment_response,hugg):
|
| 729 |
+
if (str(cmp_tr) != "NOTICKER"):
|
| 730 |
+
with st.container():
|
| 731 |
+
if user_question:
|
| 732 |
+
adviser.display_charts(cmp_tr,sentiment_response)
|
| 733 |
+
|
| 734 |
+
def get_adv_stats(user_question,adviser,cmp_tr,sentiment_response,hugg):
|
| 735 |
+
sentiment_response = get_advise(user_question,adviser,cmp_tr,sentiment_response,hugg)
|
| 736 |
+
get_stats(user_question,adviser,cmp_tr,sentiment_response,hugg)
|
| 737 |
+
|
| 738 |
+
def get_none(user_question,adviser,cmp_tr,sentiment_response,hugg):
|
| 739 |
+
st.write("Please enter a valid NSE stock enquiry.")
|
| 740 |
|
| 741 |
def main(hugg):
|
| 742 |
adviser = StockAdviser()
|
|
|
|
| 749 |
)
|
| 750 |
|
| 751 |
with st.sidebar:
|
| 752 |
+
# About the Application (Main Area)
|
| 753 |
st.markdown("""
|
| 754 |
<div style="background-color: #2d2d2d; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(255, 255, 255, 0.1);">
|
| 755 |
+
<h2 style="color: #e6e6e6; text-align: center;">About the Application</h2>
|
| 756 |
+
<p style="font-size: 16px; color: #d9d9d9; line-height: 1.6; text-align: justify;">
|
| 757 |
+
This application provides <span style="color: #80b1c1;"><strong>investment managers</strong></span> with daily insights into
|
| 758 |
+
<span style="color: #d3b673;"><strong>social media</strong></span> and <span style="color: #d3b673;"><strong>news sentiment</strong></span> surrounding
|
| 759 |
+
specific <span style="color: #80b1c1;"><strong>stocks and companies</strong></span>. By analyzing posts and articles across major platforms
|
| 760 |
+
such as <strong style="color: #b0b0b0;">Reddit</strong>, <strong style="color: #b0b0b0;">YouTube</strong>, <strong style="color: #b0b0b0;">Tumblr</strong>,
|
| 761 |
+
<strong style="color: #b0b0b0;">Google News</strong>, <strong style="color: #b0b0b0;">Financial Times</strong>, <strong style="color: #b0b0b0;">Bloomberg</strong>,
|
| 762 |
+
<strong style="color: #b0b0b0;">Reuters</strong>, and <strong style="color: #b0b0b0;">Wall Street Journal</strong> (WSJ), it detects shifts in public
|
| 763 |
+
and media opinion that may impact stock performance.
|
| 764 |
+
</p>
|
| 765 |
+
<p style="font-size: 16px; color: #d9d9d9; line-height: 1.6; text-align: justify;">
|
| 766 |
+
Additionally, sources like <span style="color: #80b1c1;"><strong>Serper</strong></span> provide data from
|
| 767 |
+
<span style="color: #d3b673;"><strong>StockNews</strong></span>, <span style="color: #d3b673;"><strong>Yahoo Finance</strong></span>,
|
| 768 |
+
<span style="color: #d3b673;"><strong>Insider Monkey</strong></span>, <span style="color: #d3b673;"><strong>Investor's Business Daily</strong></span>,
|
| 769 |
+
and others. Using advanced <span style="color: #80b1c1;"><strong>AI techniques</strong></span>, the application generates a
|
| 770 |
+
<span style="color: #d3b673;"><strong>sentiment report</strong></span> that serves as a leading indicator, helping managers make informed,
|
| 771 |
+
timely adjustments to their positions. With daily updates and <span style="color: #d3b673;"><strong>historical trend analysis</strong></span>,
|
| 772 |
+
it empowers users to stay ahead in a fast-paced, sentiment-driven market.
|
| 773 |
</p>
|
| 774 |
+
<p style="font-size: 16px; color: #d9d9d9; line-height: 1.6; text-align: justify;">
|
| 775 |
+
The application also utilizes <span style="color: #80b1c1;"><strong>intelligent agent functions</strong></span> to determine the type of query input
|
| 776 |
+
by the user. It assesses whether the query seeks <span style="color: #d3b673;"><strong>stock statistics</strong></span>,
|
| 777 |
+
<span style="color: #d3b673;"><strong>sentiment-analyzed advice</strong></span>, both, or is unrelated, providing the most relevant response accordingly.
|
|
|
|
| 778 |
</p>
|
| 779 |
</div>
|
|
|
|
| 780 |
""", unsafe_allow_html=True)
|
| 781 |
+
|
| 782 |
# Sidebar Footer (Floating Footer)
|
| 783 |
st.sidebar.markdown("""
|
| 784 |
+
<div style="position: fixed; bottom: 25px; background-color: #1f1f1f; padding: 1px; border-radius: 15px; text-align: center;">
|
| 785 |
+
<p style="color: #cccccc; font-size: 14px; text-align: center; margin: 0;">
|
| 786 |
Developed by: <a href="https://www.linkedin.com/in/karthikeyen92/" target="_blank" style="color: #4DA8DA; text-decoration: none;">Karthikeyen Packirisamy</a>
|
| 787 |
</p>
|
| 788 |
</div>
|
| 789 |
""", unsafe_allow_html=True)
|
| 790 |
+
|
| 791 |
|
| 792 |
|
| 793 |
# Main content
|
| 794 |
cmp_tr = "NOTICKER"
|
| 795 |
st.header("Ask a question")
|
| 796 |
+
user_question = st.text_input("Please ask statistical or advice or both related questions on a NSE stock.", key="user_question")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 797 |
|
| 798 |
+
if user_question.strip():
|
| 799 |
+
cmp_tr = adviser.get_symbol(user_question)
|
| 800 |
+
sentiment_response = "none"
|
| 801 |
+
|
| 802 |
+
agent_function = adviser.stock_agent(user_question)
|
| 803 |
+
getattr(sys.modules[__name__], agent_function)(user_question,adviser,cmp_tr,sentiment_response,hugg)
|
| 804 |
+
|
| 805 |
+
# get_adv_stats(user_question,adviser,cmp_tr,sentiment_response,hugg)
|
| 806 |
st.markdown("---")
|
| 807 |
+
st.markdown("<p style='text-align: center; color: #666;'>© 2024 Karthikeyen</p>", unsafe_allow_html=True)
|
| 808 |
|
| 809 |
if __name__ == "__main__":
|
| 810 |
hugg = os.getenv("IS_HUGG") == "True"
|