feat: Add Anthropic LLM support and fix data vendor compatibility
- Switch to Anthropic Claude as LLM provider in main.py - Add get_google_global_news() wrapper for proper signature matching - Add get_fundamentals() to yfinance vendor - Register yfinance and google as vendors for fundamentals and global news - Make memory system fail gracefully when OpenAI embeddings unavailable
This commit is contained in:
parent
13b826a31d
commit
0bd3741e8a
12
main.py
12
main.py
|
|
@ -8,16 +8,18 @@ load_dotenv()
|
|||
|
||||
# Create a custom config
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
config["deep_think_llm"] = "gpt-4o-mini" # Use a different model
|
||||
config["quick_think_llm"] = "gpt-4o-mini" # Use a different model
|
||||
config["max_debate_rounds"] = 1 # Increase debate rounds
|
||||
config["llm_provider"] = "anthropic"
|
||||
config["deep_think_llm"] = "claude-sonnet-4-20250514"
|
||||
config["quick_think_llm"] = "claude-sonnet-4-20250514"
|
||||
config["backend_url"] = "https://api.anthropic.com"
|
||||
config["max_debate_rounds"] = 1 # debate rounds
|
||||
|
||||
# Configure data vendors (default uses yfinance and alpha_vantage)
|
||||
config["data_vendors"] = {
|
||||
"core_stock_apis": "yfinance", # Options: yfinance, alpha_vantage, local
|
||||
"technical_indicators": "yfinance", # Options: yfinance, alpha_vantage, local
|
||||
"fundamental_data": "alpha_vantage", # Options: openai, alpha_vantage, local
|
||||
"news_data": "alpha_vantage", # Options: openai, alpha_vantage, google, local
|
||||
"fundamental_data": "yfinance", # Options: openai, alpha_vantage, yfinance, local
|
||||
"news_data": "google", # Options: openai, alpha_vantage, google, local
|
||||
}
|
||||
|
||||
# Initialize with custom config
|
||||
|
|
|
|||
|
|
@ -46,25 +46,34 @@ class FinancialSituationMemory:
|
|||
|
||||
def get_memories(self, current_situation, n_matches=1):
|
||||
"""Find matching recommendations using OpenAI embeddings"""
|
||||
query_embedding = self.get_embedding(current_situation)
|
||||
try:
|
||||
# Skip if collection is empty
|
||||
if self.situation_collection.count() == 0:
|
||||
return []
|
||||
|
||||
results = self.situation_collection.query(
|
||||
query_embeddings=[query_embedding],
|
||||
n_results=n_matches,
|
||||
include=["metadatas", "documents", "distances"],
|
||||
)
|
||||
query_embedding = self.get_embedding(current_situation)
|
||||
|
||||
matched_results = []
|
||||
for i in range(len(results["documents"][0])):
|
||||
matched_results.append(
|
||||
{
|
||||
"matched_situation": results["documents"][0][i],
|
||||
"recommendation": results["metadatas"][0][i]["recommendation"],
|
||||
"similarity_score": 1 - results["distances"][0][i],
|
||||
}
|
||||
results = self.situation_collection.query(
|
||||
query_embeddings=[query_embedding],
|
||||
n_results=n_matches,
|
||||
include=["metadatas", "documents", "distances"],
|
||||
)
|
||||
|
||||
return matched_results
|
||||
matched_results = []
|
||||
for i in range(len(results["documents"][0])):
|
||||
matched_results.append(
|
||||
{
|
||||
"matched_situation": results["documents"][0][i],
|
||||
"recommendation": results["metadatas"][0][i]["recommendation"],
|
||||
"similarity_score": 1 - results["distances"][0][i],
|
||||
}
|
||||
)
|
||||
|
||||
return matched_results
|
||||
except Exception as e:
|
||||
# Return empty if embedding fails (e.g., no OpenAI quota)
|
||||
print(f"Memory lookup skipped (embedding unavailable): {e}")
|
||||
return []
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
|
|
@ -4,6 +4,16 @@ from dateutil.relativedelta import relativedelta
|
|||
from .googlenews_utils import getNewsData
|
||||
|
||||
|
||||
def get_google_global_news(
|
||||
curr_date: Annotated[str, "Current date in yyyy-mm-dd format"],
|
||||
look_back_days: Annotated[int, "Number of days to look back"] = 7,
|
||||
limit: Annotated[int, "Maximum number of articles to return"] = 5,
|
||||
) -> str:
|
||||
"""Wrapper for global news that uses Google News with market/economy query."""
|
||||
query = "stock+market+economy+finance"
|
||||
return get_google_news(query, curr_date, look_back_days)
|
||||
|
||||
|
||||
def get_google_news(
|
||||
query: Annotated[str, "Query to search with"],
|
||||
curr_date: Annotated[str, "Curr date in yyyy-mm-dd format"],
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ from typing import Annotated
|
|||
|
||||
# Import from vendor-specific modules
|
||||
from .local import get_YFin_data, get_finnhub_news, get_finnhub_company_insider_sentiment, get_finnhub_company_insider_transactions, get_simfin_balance_sheet, get_simfin_cashflow, get_simfin_income_statements, get_reddit_global_news, get_reddit_company_news
|
||||
from .y_finance import get_YFin_data_online, get_stock_stats_indicators_window, get_balance_sheet as get_yfinance_balance_sheet, get_cashflow as get_yfinance_cashflow, get_income_statement as get_yfinance_income_statement, get_insider_transactions as get_yfinance_insider_transactions
|
||||
from .google import get_google_news
|
||||
from .y_finance import get_YFin_data_online, get_stock_stats_indicators_window, get_balance_sheet as get_yfinance_balance_sheet, get_cashflow as get_yfinance_cashflow, get_income_statement as get_yfinance_income_statement, get_insider_transactions as get_yfinance_insider_transactions, get_fundamentals as get_yfinance_fundamentals
|
||||
from .google import get_google_news, get_google_global_news
|
||||
from .openai import get_stock_news_openai, get_global_news_openai, get_fundamentals_openai
|
||||
from .alpha_vantage import (
|
||||
get_stock as get_alpha_vantage_stock,
|
||||
|
|
@ -78,6 +78,7 @@ VENDOR_METHODS = {
|
|||
# fundamental_data
|
||||
"get_fundamentals": {
|
||||
"alpha_vantage": get_alpha_vantage_fundamentals,
|
||||
"yfinance": get_yfinance_fundamentals,
|
||||
"openai": get_fundamentals_openai,
|
||||
},
|
||||
"get_balance_sheet": {
|
||||
|
|
@ -104,6 +105,7 @@ VENDOR_METHODS = {
|
|||
},
|
||||
"get_global_news": {
|
||||
"openai": get_global_news_openai,
|
||||
"google": get_google_global_news,
|
||||
"local": get_reddit_global_news
|
||||
},
|
||||
"get_insider_sentiment": {
|
||||
|
|
|
|||
|
|
@ -383,6 +383,43 @@ def get_income_statement(
|
|||
return f"Error retrieving income statement for {ticker}: {str(e)}"
|
||||
|
||||
|
||||
def get_fundamentals(
|
||||
ticker: Annotated[str, "ticker symbol of the company"],
|
||||
curr_date: str = None
|
||||
):
|
||||
"""Get company fundamentals from yfinance."""
|
||||
try:
|
||||
ticker_obj = yf.Ticker(ticker.upper())
|
||||
info = ticker_obj.info
|
||||
|
||||
if not info:
|
||||
return f"No fundamental data found for symbol '{ticker}'"
|
||||
|
||||
# Extract key metrics (keep it concise to avoid context overflow)
|
||||
key_fields = [
|
||||
'longName', 'sector', 'industry', 'marketCap', 'enterpriseValue',
|
||||
'trailingPE', 'forwardPE', 'pegRatio', 'priceToBook', 'priceToSalesTrailing12Months',
|
||||
'profitMargins', 'operatingMargins', 'returnOnEquity', 'returnOnAssets',
|
||||
'revenueGrowth', 'earningsGrowth', 'currentRatio', 'debtToEquity',
|
||||
'totalRevenue', 'grossProfits', 'ebitda', 'netIncomeToCommon',
|
||||
'totalCash', 'totalDebt', 'freeCashflow',
|
||||
'dividendYield', 'payoutRatio', 'beta', 'fiftyTwoWeekHigh', 'fiftyTwoWeekLow',
|
||||
'targetMeanPrice', 'recommendationKey', 'numberOfAnalystOpinions'
|
||||
]
|
||||
|
||||
result = f"# Company Fundamentals for {ticker.upper()}\n"
|
||||
result += f"# Data retrieved on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
|
||||
|
||||
for field in key_fields:
|
||||
if field in info and info[field] is not None:
|
||||
result += f"{field}: {info[field]}\n"
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
return f"Error retrieving fundamentals for {ticker}: {str(e)}"
|
||||
|
||||
|
||||
def get_insider_transactions(
|
||||
ticker: Annotated[str, "ticker symbol of the company"]
|
||||
):
|
||||
|
|
|
|||
Loading…
Reference in New Issue