Spaces:
Sleeping
Sleeping
create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import requests
|
| 3 |
+
from typing import Dict, Any
|
| 4 |
+
import snowflake.connector
|
| 5 |
+
import openai
|
| 6 |
+
import gradio as gr
|
| 7 |
+
|
| 8 |
+
def get_financial_data(ticker: str, api_key: str, period: str = 'annual') -> Dict[str, Any]:
|
| 9 |
+
base_url = "https://financialmodelingprep.com/api/v3/"
|
| 10 |
+
endpoints = {
|
| 11 |
+
"profile": f"profile/{ticker}?apikey={api_key}",
|
| 12 |
+
"balance_sheet": f"balance-sheet-statement/{ticker}?period={period}&apikey={api_key}",
|
| 13 |
+
"income_statement": f"income-statement/{ticker}?period={period}&apikey={api_key}"
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
results = {}
|
| 17 |
+
|
| 18 |
+
for key, endpoint in endpoints.items():
|
| 19 |
+
url = base_url + endpoint
|
| 20 |
+
response = requests.get(url)
|
| 21 |
+
if response.status_code == 200:
|
| 22 |
+
data = response.json()
|
| 23 |
+
if data:
|
| 24 |
+
if key == "profile":
|
| 25 |
+
results[key] = data[0]
|
| 26 |
+
elif key == "balance_sheet":
|
| 27 |
+
results[key] = data[0] # Get the most recent balance sheet statement
|
| 28 |
+
elif key == "income_statement":
|
| 29 |
+
results[key] = data[0] # Get the most recent income statement
|
| 30 |
+
else:
|
| 31 |
+
results[key] = None
|
| 32 |
+
else:
|
| 33 |
+
raise Exception(f"Failed to fetch data from {key} endpoint for ticker {ticker}. HTTP Status Code: {response.status_code}")
|
| 34 |
+
|
| 35 |
+
return results
|
| 36 |
+
|
| 37 |
+
def get_proprietary_indicators(ticker: str) -> str:
|
| 38 |
+
connection = snowflake.connector.connect(
|
| 39 |
+
user=os.getenv('SNOWFLAKE_USER'),
|
| 40 |
+
password=os.getenv('SNOWFLAKE_PASSWORD'),
|
| 41 |
+
account=os.getenv('SNOWFLAKE_ACCOUNT'),
|
| 42 |
+
warehouse=os.getenv('SNOWFLAKE_WAREHOUSE'),
|
| 43 |
+
database=os.getenv('SNOWFLAKE_DATABASE')
|
| 44 |
+
)
|
| 45 |
+
query = f"""
|
| 46 |
+
SELECT prompt
|
| 47 |
+
FROM researchdata.TS_INDICATORS_FOR_GPT_PROMPT_SVIEW
|
| 48 |
+
WHERE SYMBOL = '{ticker}'
|
| 49 |
+
"""
|
| 50 |
+
cursor = connection.cursor()
|
| 51 |
+
cursor.execute(query)
|
| 52 |
+
result = cursor.fetchone()
|
| 53 |
+
connection.close()
|
| 54 |
+
|
| 55 |
+
if result:
|
| 56 |
+
return result[0]
|
| 57 |
+
else:
|
| 58 |
+
return "No proprietary indicators available for this ticker."
|
| 59 |
+
|
| 60 |
+
def format_for_gpt_prompt(financial_data: Dict[str, Any], proprietary_indicators: str) -> str:
|
| 61 |
+
profile = financial_data.get('profile', {})
|
| 62 |
+
balance_sheet = financial_data.get('balance_sheet', {})
|
| 63 |
+
income_statement = financial_data.get('income_statement', {})
|
| 64 |
+
|
| 65 |
+
company_name = profile.get('companyName', 'N/A')
|
| 66 |
+
company_description = profile.get('description', 'N/A')
|
| 67 |
+
ticker = profile.get('symbol', 'N/A')
|
| 68 |
+
market_cap = profile.get('mktCap', 'N/A')
|
| 69 |
+
ceo = profile.get('ceo', 'N/A')
|
| 70 |
+
beta = profile.get('beta', 'N/A')
|
| 71 |
+
|
| 72 |
+
financial_data_str = f"""
|
| 73 |
+
Balance Sheet:
|
| 74 |
+
Total Assets: {balance_sheet.get('totalAssets', 'N/A')}
|
| 75 |
+
Total Liabilities: {balance_sheet.get('totalLiabilities', 'N/A')}
|
| 76 |
+
Total Equity: {balance_sheet.get('totalEquity', 'N/A')}
|
| 77 |
+
Cash and Cash Equivalents: {balance_sheet.get('cashAndCashEquivalents', 'N/A')}
|
| 78 |
+
Cash and Short Term Investments: {balance_sheet.get('cashAndShortTermInvestments', 'N/A')}
|
| 79 |
+
Inventory: {balance_sheet.get('inventory', 'N/A')}
|
| 80 |
+
Net Receivables: {balance_sheet.get('netReceivables', 'N/A')}
|
| 81 |
+
Total Current Assets: {balance_sheet.get('totalCurrentAssets', 'N/A')}
|
| 82 |
+
Total Current Liabilities: {balance_sheet.get('totalCurrentLiabilities', 'N/A')}
|
| 83 |
+
Long Term Debt: {balance_sheet.get('longTermDebt', 'N/A')}
|
| 84 |
+
Short Term Debt: {balance_sheet.get('shortTermDebt', 'N/A')}
|
| 85 |
+
Total Debt: {balance_sheet.get('totalDebt', 'N/A')}
|
| 86 |
+
Property, Plant, and Equipment Net: {balance_sheet.get('propertyPlantEquipmentNet', 'N/A')}
|
| 87 |
+
Deferred Revenue: {balance_sheet.get('deferredRevenue', 'N/A')}
|
| 88 |
+
Accumulated Other Comprehensive Income Loss: {balance_sheet.get('accumulatedOtherComprehensiveIncomeLoss', 'N/A')}
|
| 89 |
+
Retained Earnings: {balance_sheet.get('retainedEarnings', 'N/A')}
|
| 90 |
+
Total Non-Current Assets: {balance_sheet.get('totalNonCurrentAssets', 'N/A')}
|
| 91 |
+
Total Non-Current Liabilities: {balance_sheet.get('totalNonCurrentLiabilities', 'N/A')}
|
| 92 |
+
Goodwill and Intangible Assets: {balance_sheet.get('goodwillAndIntangibleAssets', 'N/A')}
|
| 93 |
+
|
| 94 |
+
Income Statement:
|
| 95 |
+
Revenue: {income_statement.get('revenue', 'N/A')}
|
| 96 |
+
Cost of Revenue: {income_statement.get('costOfRevenue', 'N/A')}
|
| 97 |
+
Gross Profit: {income_statement.get('grossProfit', 'N/A')}
|
| 98 |
+
Gross Profit Ratio: {income_statement.get('grossProfitRatio', 'N/A')}
|
| 99 |
+
Operating Income: {income_statement.get('operatingIncome', 'N/A')}
|
| 100 |
+
Operating Income Ratio: {income_statement.get('operatingIncomeRatio', 'N/A')}
|
| 101 |
+
Net Income: {income_statement.get('netIncome', 'N/A')}
|
| 102 |
+
Net Income Ratio: {income_statement.get('netIncomeRatio', 'N/A')}
|
| 103 |
+
EBITDA: {income_statement.get('ebitda', 'N/A')}
|
| 104 |
+
EBITDA Ratio: {income_statement.get('ebitdaratio', 'N/A')}
|
| 105 |
+
Earnings Per Share (EPS): {income_statement.get('eps', 'N/A')}
|
| 106 |
+
Diluted EPS: {income_statement.get('epsdiluted', 'N/A')}
|
| 107 |
+
Cost and Expenses: {income_statement.get('costAndExpenses', 'N/A')}
|
| 108 |
+
Depreciation and Amortization: {income_statement.get('depreciationAndAmortization', 'N/A')}
|
| 109 |
+
Income Before Tax: {income_statement.get('incomeBeforeTax', 'N/A')}
|
| 110 |
+
Income Before Tax Ratio: {income_statement.get('incomeBeforeTaxRatio', 'N/A')}
|
| 111 |
+
Income Tax Expense: {income_statement.get('incomeTaxExpense', 'N/A')}
|
| 112 |
+
Operating Expenses: {income_statement.get('operatingExpenses', 'N/A')}
|
| 113 |
+
Research and Development Expenses: {income_statement.get('researchAndDevelopmentExpenses', 'N/A')}
|
| 114 |
+
Selling, General, and Administrative Expenses: {income_statement.get('sellingGeneralAndAdministrativeExpenses', 'N/A')}
|
| 115 |
+
Total Other Income Expenses Net: {income_statement.get('totalOtherIncomeExpensesNet', 'N/A')}
|
| 116 |
+
Weighted Average Shares Outstanding: {income_statement.get('weightedAverageShsOut', 'N/A')}
|
| 117 |
+
Weighted Average Shares Outstanding Diluted: {income_statement.get('weightedAverageShsOutDil', 'N/A')}
|
| 118 |
+
"""
|
| 119 |
+
|
| 120 |
+
prompt = f"""
|
| 121 |
+
You are an expert stock analyst AI that has been tasked with analyzing a specific company and providing an investment recommendation for potential investors. Start with a company description and include the ticker, CEO, Market Cap and beta. Then provide an analysis based on the information provided to you. Your analysis and recommendation should be based solely on the company information, financial data, and news articles provided to you. Do not make assumptions or incorporate any outside knowledge.
|
| 122 |
+
|
| 123 |
+
Here is the company you will be analyzing:
|
| 124 |
+
|
| 125 |
+
<company>
|
| 126 |
+
Name: {company_name} ({ticker})
|
| 127 |
+
Description: {company_description}
|
| 128 |
+
Market Cap: {market_cap}
|
| 129 |
+
CEO: {ceo}
|
| 130 |
+
Beta: {beta}
|
| 131 |
+
</company>
|
| 132 |
+
|
| 133 |
+
Please carefully review this background information on the company.
|
| 134 |
+
|
| 135 |
+
Next, here is some recent financial data on the company:
|
| 136 |
+
|
| 137 |
+
<financial_data>
|
| 138 |
+
{financial_data_str}
|
| 139 |
+
</financial_data>
|
| 140 |
+
|
| 141 |
+
Carefully analyze the key financial metrics and KPIs provided above, looking for significant trends, strengths and weaknesses. Consider metrics like revenue growth, profit margins, debt levels, etc.
|
| 142 |
+
|
| 143 |
+
Next, here are the proprietary indicators for the company:
|
| 144 |
+
|
| 145 |
+
<proprietary_indicators>
|
| 146 |
+
|
| 147 |
+
{proprietary_indicators}
|
| 148 |
+
|
| 149 |
+
</proprietary_indicators>
|
| 150 |
+
|
| 151 |
+
<reasoning>
|
| 152 |
+
|
| 153 |
+
Synthesize your analysis of the company background, financial data, and proprietary indicators here. Discuss the key factors that will likely impact the company's future stock price. Weigh the potential rewards of investing against the risks. Show your analytical thought process.
|
| 154 |
+
|
| 155 |
+
</reasoning>
|
| 156 |
+
|
| 157 |
+
<prediction>
|
| 158 |
+
|
| 159 |
+
Considering everything, what prediction would you make for this stock's return over the next 21 trading days? Provide a clear, justified recommendation based solely on the information provided. Do not hedge or equivocate.
|
| 160 |
+
|
| 161 |
+
</prediction>
|
| 162 |
+
|
| 163 |
+
Remember, your role is to be an objective, expert stock analyst. Explain your reasoning so that investors can understand the key factors driving your recommendation.
|
| 164 |
+
"""
|
| 165 |
+
|
| 166 |
+
return prompt
|
| 167 |
+
|
| 168 |
+
def generate_gpt_prompt(ticker: str, api_key: str) -> str:
|
| 169 |
+
financial_data = get_financial_data(ticker, api_key)
|
| 170 |
+
proprietary_indicators = get_proprietary_indicators(ticker)
|
| 171 |
+
return format_for_gpt_prompt(financial_data, proprietary_indicators)
|
| 172 |
+
|
| 173 |
+
def run_gpt_model(prompt: str, api_key: str) -> str:
|
| 174 |
+
openai.api_key = api_key
|
| 175 |
+
system_prompt = (
|
| 176 |
+
"You are an expert stock analyst with a high degree of familiarity with TradeSmith and InvestorPlace products and services. "
|
| 177 |
+
"You help subscribers of these businesses analyze stocks. "
|
| 178 |
+
"You speak concisely and your output should use line breaks after each sentence to keep the text within a readable width. "
|
| 179 |
+
)
|
| 180 |
+
|
| 181 |
+
response = openai.Completion.create(
|
| 182 |
+
model="gpt-4", # or another model
|
| 183 |
+
prompt=prompt,
|
| 184 |
+
max_tokens=1500,
|
| 185 |
+
temperature=0.7,
|
| 186 |
+
stream=False,
|
| 187 |
+
stop=None
|
| 188 |
+
)
|
| 189 |
+
|
| 190 |
+
return response['choices'][0]['text']
|
| 191 |
+
|
| 192 |
+
def analyze_stock(ticker: str) -> str:
|
| 193 |
+
fmp_api_key = os.getenv('FMP_API_KEY')
|
| 194 |
+
openai_api_key = os.getenv('OPENAI_API_KEY')
|
| 195 |
+
prompt = generate_gpt_prompt(ticker, fmp_api_key)
|
| 196 |
+
analysis = run_gpt_model(prompt, openai_api_key)
|
| 197 |
+
return analysis
|
| 198 |
+
|
| 199 |
+
# Gradio Interface
|
| 200 |
+
iface = gr.Interface(fn=analyze_stock, inputs="text", outputs="text", title="Stock Analysis GPT Model",
|
| 201 |
+
description="Enter a stock ticker to get an analysis from the GPT model.")
|
| 202 |
+
|
| 203 |
+
if __name__ == "__main__":
|
| 204 |
+
iface.launch()
|