From fa54b7a77c09793f42b5f3226dd6064c262af1a0 Mon Sep 17 00:00:00 2001 From: Rohit Rushil Date: Mon, 25 Mar 2024 19:46:28 +0530 Subject: [PATCH 1/2] Added Support for Open AI --- OpenAI_Investor.ipynb | 302 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 OpenAI_Investor.ipynb diff --git a/OpenAI_Investor.ipynb b/OpenAI_Investor.ipynb new file mode 100644 index 0000000..a5a69e3 --- /dev/null +++ b/OpenAI_Investor.ipynb @@ -0,0 +1,302 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "view-in-github" + }, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "gQWLeJCFS6C4" + }, + "source": [ + "## claude-investor\n", + "By Matt Shumer (https://twitter.com/mattshumer_)\n", + "\n", + "Github repo: https://github.com/mshumer/gpt-investor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "rlKQLdG8v23g" + }, + "outputs": [], + "source": [ + "!pip install yfinance requests beautifulsoup4\n", + "!pip install openai" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "id": "50ZEVdt53Xkr" + }, + "outputs": [], + "source": [ + "from openai import AzureOpenAI, OpenAI\n", + "\n", + "API_KEY = \"\" # Replace with your OpenAI API or AzureOpenAI key\n", + "client = OpenAI(api_key = API_KEY)\n", + "\n", + "HOSTED_IN_AZURE_PLATFORM = True # Make it to True/False if your service is Azure Open AI or OpenAI respectively.\n", + "if(HOSTED_IN_AZURE_PLATFORM):\n", + " API_ENDPOINT= \"\"\n", + " API_MODEL=\"\"\n", + " API_VERSION=\"\"\n", + "\n", + " client = AzureOpenAI(api_key = API_KEY,api_version=API_VERSION,azure_endpoint=API_ENDPOINT)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "tg78Hup6xona" + }, + "outputs": [], + "source": [ + "import yfinance as yf\n", + "from datetime import datetime, timedelta\n", + "import requests\n", + "from bs4 import BeautifulSoup\n", + "import ast\n", + "import json\n", + "\n", + "\n", + "\n", + "def get_article_text(url):\n", + " try:\n", + " response = requests.get(url)\n", + " soup = BeautifulSoup(response.content, 'html.parser')\n", + " article_text = ' '.join([p.get_text() for p in soup.find_all('p')])\n", + " return article_text\n", + " except:\n", + " return \"Error retrieving article text.\"\n", + "\n", + "def get_stock_data(ticker, years):\n", + " end_date = datetime.now().date()\n", + " start_date = end_date - timedelta(days=years*365)\n", + "\n", + " stock = yf.Ticker(ticker)\n", + "\n", + " # Retrieve historical price data\n", + " hist_data = stock.history(start=start_date, end=end_date)\n", + "\n", + " # Retrieve balance sheet\n", + " balance_sheet = stock.balance_sheet\n", + "\n", + " # Retrieve financial statements\n", + " financials = stock.financials\n", + "\n", + " # Retrieve news articles\n", + " news = stock.news\n", + "\n", + " return hist_data, balance_sheet, financials, news\n", + "\n", + "def get_claude_comps_analysis(ticker, hist_data, balance_sheet, financials, news):\n", + " system_prompt = f\"You are a financial analyst assistant. Analyze the given data for {ticker} and suggest a few comparable companies to consider. Do so in a Python-parseable list.\"\n", + "\n", + " news = \"\"\n", + "\n", + " for article in news:\n", + " article_text = get_article_text(article['link'])\n", + " news = news + f\"\\n\\n---\\n\\nTitle: {article['title']}\\nText: {article_text}\"\n", + "\n", + " messages = [\n", + " {\"role\": \"user\", \"content\": f\"Historical price data:\\n{hist_data.tail().to_string()}\\n\\nBalance Sheet:\\n{balance_sheet.to_string()}\\n\\nFinancial Statements:\\n{financials.to_string()}\\n\\nNews articles:\\n{news.strip()}\\n\\n----\\n\\nNow, suggest a few comparable companies to consider, in a Python-parseable list. Return nothing but the list. Make sure the companies are in the form of their tickers.\"},\n", + " ]\n", + "\n", + "\n", + " response = client.chat.completions.create(model=API_MODEL, messages = messages)\n", + " response_text = response.choices[0].message.content\n", + "\n", + " return ast.literal_eval(response_text)\n", + "\n", + "def compare_companies(main_ticker, main_data, comp_ticker, comp_data):\n", + " system_prompt = f\"You are a financial analyst assistant. Compare the data of {main_ticker} against {comp_ticker} and provide a detailed comparison, like a world-class analyst would. Be measured and discerning. Truly think about the positives and negatives of each company. Be sure of your analysis. You are a skeptical investor.\"\n", + "\n", + " messages = [\n", + " {\"role\": \"user\", \"content\": f\"Data for {main_ticker}:\\n\\nHistorical price data:\\n{main_data['hist_data'].tail().to_string()}\\n\\nBalance Sheet:\\n{main_data['balance_sheet'].to_string()}\\n\\nFinancial Statements:\\n{main_data['financials'].to_string()}\\n\\n----\\n\\nData for {comp_ticker}:\\n\\nHistorical price data:\\n{comp_data['hist_data'].tail().to_string()}\\n\\nBalance Sheet:\\n{comp_data['balance_sheet'].to_string()}\\n\\nFinancial Statements:\\n{comp_data['financials'].to_string()}\\n\\n----\\n\\nNow, provide a detailed comparison of {main_ticker} against {comp_ticker}. Explain your thinking very clearly.\"},\n", + " ]\n", + "\n", + " response = client.chat.completions.create(model=API_MODEL, messages = messages)\n", + " response_text = response.choices[0].message.content\n", + "\n", + " return response_text\n", + "\n", + "def get_sentiment_analysis(ticker, news):\n", + " system_prompt = f\"You are a sentiment analysis assistant. Analyze the sentiment of the given news articles for {ticker} and provide a summary of the overall sentiment and any notable changes over time. Be measured and discerning. You are a skeptical investor.\"\n", + "\n", + " news_text = \"\"\n", + " for article in news:\n", + " article_text = get_article_text(article['link'])\n", + " timestamp = datetime.fromtimestamp(article['providerPublishTime']).strftime(\"%Y-%m-%d\")\n", + " news_text += f\"\\n\\n---\\n\\nDate: {timestamp}\\nTitle: {article['title']}\\nText: {article_text}\"\n", + "\n", + " messages = [\n", + " {\"role\": \"user\", \"content\": f\"News articles for {ticker}:\\n{news_text}\\n\\n----\\n\\nProvide a summary of the overall sentiment and any notable changes over time.\"},\n", + " ]\n", + "\n", + " response = client.chat.completions.create(model=API_MODEL, messages = messages)\n", + " response_text = response.choices[0].message.content\n", + "\n", + " return response_text\n", + "\n", + "def get_analyst_ratings(ticker):\n", + " stock = yf.Ticker(ticker)\n", + " recommendations = stock.recommendations\n", + " if recommendations is None or recommendations.empty:\n", + " return \"No analyst ratings available.\"\n", + "\n", + " latest_rating = recommendations.iloc[-1]\n", + "\n", + " firm = latest_rating.get('Firm', 'N/A')\n", + " to_grade = latest_rating.get('To Grade', 'N/A')\n", + " action = latest_rating.get('Action', 'N/A')\n", + "\n", + " rating_summary = f\"Latest analyst rating for {ticker}:\\nFirm: {firm}\\nTo Grade: {to_grade}\\nAction: {action}\"\n", + "\n", + " return rating_summary\n", + "\n", + "def get_industry_analysis(ticker):\n", + "\n", + " ### update to use search to find recent data!!\n", + "\n", + " stock = yf.Ticker(ticker)\n", + " industry = stock.info['industry']\n", + " sector = stock.info['sector']\n", + "\n", + " system_prompt = f\"You are an industry analysis assistant. Provide an analysis of the {industry} industry and {sector} sector, including trends, growth prospects, regulatory changes, and competitive landscape. Be measured and discerning. Truly think about the positives and negatives of the stock. Be sure of your analysis. You are a skeptical investor.\"\n", + "\n", + " messages = [\n", + " {\"role\": \"user\", \"content\": f\"Provide an analysis of the {industry} industry and {sector} sector.\"},\n", + " ]\n", + "\n", + " response = client.chat.completions.create(model=API_MODEL, messages = messages)\n", + " response_text = response.choices[0].message.content\n", + "\n", + " return response_text\n", + "\n", + "\n", + "def get_final_analysis(ticker, comparisons, sentiment_analysis, analyst_ratings, industry_analysis):\n", + " system_prompt = f\"You are a financial analyst providing a final investment recommendation for {ticker} based on the given data and analyses. Be measured and discerning. Truly think about the positives and negatives of the stock. Be sure of your analysis. You are a skeptical investor.\"\n", + "\n", + " messages = [\n", + " {\"role\": \"user\", \"content\": f\"Ticker: {ticker}\\n\\nComparative Analysis:\\n{json.dumps(comparisons, indent=2)}\\n\\nSentiment Analysis:\\n{sentiment_analysis}\\n\\nAnalyst Ratings:\\n{analyst_ratings}\\n\\nIndustry Analysis:\\n{industry_analysis}\\n\\nBased on the provided data and analyses, please provide a comprehensive investment analysis and recommendation for {ticker}. Consider the company's financial strength, growth prospects, competitive position, and potential risks. Provide a clear and concise recommendation on whether to buy, hold, or sell the stock, along with supporting rationale.\"},\n", + " ]\n", + "\n", + " response = client.chat.completions.create(model=API_MODEL, messages = messages)\n", + " response_text = response.choices[0].message.content\n", + "\n", + " return response_text\n", + "\n", + "def generate_ticker_ideas(industry):\n", + " system_prompt = f\"You are a financial analyst assistant. Generate a list of 5 ticker symbols for major companies in the {industry} industry, as a Python-parseable list.\"\n", + "\n", + " messages = [\n", + " {\"role\": \"user\", \"content\": f\"Please provide a list of 5 ticker symbols for major companies in the {industry} industry as a Python-parseable list. Only respond with the list, no other text.\"},\n", + " ]\n", + "\n", + " response = client.chat.completions.create(model=API_MODEL, messages = messages)\n", + " response_text = response.choices[0].message.content\n", + " \n", + " ticker_list = ast.literal_eval(response_text)\n", + " return [ticker.strip() for ticker in ticker_list]\n", + "\n", + "def get_current_price(ticker):\n", + " stock = yf.Ticker(ticker)\n", + " data = stock.history(period='1d', interval='1m')\n", + " return data['Close'][-1]\n", + "\n", + "def rank_companies(industry, analyses, prices):\n", + " system_prompt = f\"You are a financial analyst providing a ranking of companies in the {industry} industry based on their investment potential. Be discerning and sharp. Truly think about whether a stock is valuable or not. You are a skeptical investor.\"\n", + "\n", + " analysis_text = \"\\n\\n\".join(\n", + " f\"Ticker: {ticker}\\nCurrent Price: {prices.get(ticker, 'N/A')}\\nAnalysis:\\n{analysis}\"\n", + " for ticker, analysis in analyses.items()\n", + " )\n", + "\n", + " messages = [\n", + " {\"role\": \"user\", \"content\": f\"Industry: {industry}\\n\\nCompany Analyses:\\n{analysis_text}\\n\\nBased on the provided analyses, please rank the companies from most attractive to least attractive for investment. Provide a brief rationale for your ranking. In each rationale, include the current price (if available) and a price target.\"},\n", + " ]\n", + "\n", + " response = client.chat.completions.create(model=API_MODEL, messages = messages)\n", + " response_text = response.choices[0].message.content\n", + "\n", + " return response_text\n", + "\n", + "# User input\n", + "industry = input(\"Enter the industry to analyze: \")\n", + "\n", + "years = 1 # int(input(\"Enter the number of years for analysis: \"))\n", + "\n", + "# Generate ticker ideas for the industry\n", + "tickers = generate_ticker_ideas(industry)\n", + "print(f\"\\nTicker Ideas for {industry} Industry:\")\n", + "print(\", \".join(tickers))\n", + "\n", + "# Perform analysis for each company\n", + "analyses = {}\n", + "prices = {}\n", + "for ticker in tickers:\n", + " try:\n", + " print(f\"\\nAnalyzing {ticker}...\")\n", + " hist_data, balance_sheet, financials, news = get_stock_data(ticker, years)\n", + " main_data = {\n", + " 'hist_data': hist_data,\n", + " 'balance_sheet': balance_sheet,\n", + " 'financials': financials,\n", + " 'news': news\n", + " }\n", + " sentiment_analysis = get_sentiment_analysis(ticker, news)\n", + " analyst_ratings = get_analyst_ratings(ticker)\n", + " industry_analysis = get_industry_analysis(ticker)\n", + " final_analysis = get_final_analysis(ticker, {}, sentiment_analysis, analyst_ratings, industry_analysis)\n", + " analyses[ticker] = final_analysis\n", + " prices[ticker] = get_current_price(ticker)\n", + " except:\n", + " pass\n", + "\n", + "# Rank the companies based on their analyses\n", + "ranking = rank_companies(industry, analyses, prices)\n", + "print(f\"\\nRanking of Companies in the {industry} Industry:\")\n", + "print(ranking)" + ] + } + ], + "metadata": { + "colab": { + "authorship_tag": "ABX9TyPuI82WtCRP7mS26mCp9B+j", + "include_colab_link": true, + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.5" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} From 36d104e24b29c3d64158f7888ee9268cfc85607c Mon Sep 17 00:00:00 2001 From: Rohit Rushil Date: Tue, 26 Mar 2024 14:20:34 +0530 Subject: [PATCH 2/2] API model is included for openai too --- OpenAI_Investor.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenAI_Investor.ipynb b/OpenAI_Investor.ipynb index a5a69e3..c28c808 100644 --- a/OpenAI_Investor.ipynb +++ b/OpenAI_Investor.ipynb @@ -47,10 +47,11 @@ "API_KEY = \"\" # Replace with your OpenAI API or AzureOpenAI key\n", "client = OpenAI(api_key = API_KEY)\n", "\n", + "API_MODEL=\"\"\n", + "\n", "HOSTED_IN_AZURE_PLATFORM = True # Make it to True/False if your service is Azure Open AI or OpenAI respectively.\n", "if(HOSTED_IN_AZURE_PLATFORM):\n", " API_ENDPOINT= \"\"\n", - " API_MODEL=\"\"\n", " API_VERSION=\"\"\n", "\n", " client = AzureOpenAI(api_key = API_KEY,api_version=API_VERSION,azure_endpoint=API_ENDPOINT)\n",