diff --git a/.env.sample b/.env.sample new file mode 100644 index 00000000..f3b5792f --- /dev/null +++ b/.env.sample @@ -0,0 +1,6 @@ +# Finnhub API Key +FINNHUB_API_KEY="YOUR_FINNHUB_API_KEY" + +# OpenAI API Key +OPENAI_API_KEY="YOUR_OPENAI_API_KEY" +BACKEND_URL="https://api.openai.com/v1" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4ebf99e3..c3c6254e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ eval_results/ eval_data/ *.egg-info/ .env +.vscode/ +results/ diff --git a/README.md b/README.md index cac18691..8bb7039e 100644 --- a/README.md +++ b/README.md @@ -114,15 +114,15 @@ pip install -r requirements.txt ### Required APIs -You will also need the FinnHub API for financial data. All of our code is implemented with the free tier. +You will need API keys from FinnHub and OpenAI. You can provide them by creating a `.env` file in the root of the project. Rename the `.env.sample` file to `.env` and add your API keys: + ```bash -export FINNHUB_API_KEY=$YOUR_FINNHUB_API_KEY +# .env +FINNHUB_API_KEY="YOUR_FINNHUB_API_KEY" +OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` -You will need the OpenAI API for all the agents. -```bash -export OPENAI_API_KEY=$YOUR_OPENAI_API_KEY -``` +The application will automatically load these keys. Alternatively, you can still use environment variables if you prefer. ### CLI Usage diff --git a/cli/main.py b/cli/main.py index 64616ee1..fe575dae 100644 --- a/cli/main.py +++ b/cli/main.py @@ -20,6 +20,8 @@ from rich import box from rich.align import Align from rich.rule import Rule +from dotenv import load_dotenv +load_dotenv() from tradingagents.graph.trading_graph import TradingAgentsGraph from tradingagents.default_config import DEFAULT_CONFIG from cli.models import AnalystType @@ -394,7 +396,7 @@ def update_display(layout, spinner_text=None): def get_user_selections(): """Get all user selections before starting the analysis display.""" # Display ASCII art welcome message - with open("./cli/static/welcome.txt", "r") as f: + with open("./cli/static/welcome.txt", "r", encoding="utf-8") as f: welcome_ascii = f.read() # Create welcome box content @@ -764,7 +766,7 @@ def run_analysis(): func(*args, **kwargs) timestamp, message_type, content = obj.messages[-1] content = content.replace("\n", " ") # Replace newlines with spaces - with open(log_file, "a") as f: + with open(log_file, "a", encoding="utf-8") as f: f.write(f"{timestamp} [{message_type}] {content}\n") return wrapper @@ -775,7 +777,7 @@ def run_analysis(): func(*args, **kwargs) timestamp, tool_name, args = obj.tool_calls[-1] args_str = ", ".join(f"{k}={v}" for k, v in args.items()) - with open(log_file, "a") as f: + with open(log_file, "a", encoding="utf-8") as f: f.write(f"{timestamp} [Tool Call] {tool_name}({args_str})\n") return wrapper @@ -788,7 +790,7 @@ def run_analysis(): content = obj.report_sections[section_name] if content: file_name = f"{section_name}.md" - with open(report_dir / file_name, "w") as f: + with open(report_dir / file_name, "w", encoding="utf-8") as f: f.write(content) return wrapper diff --git a/requirements.txt b/requirements.txt index a6154cd2..f57b352f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,3 +24,5 @@ rich questionary langchain_anthropic langchain-google-genai + +python-dotenv diff --git a/tradingagents/agents/utils/memory.py b/tradingagents/agents/utils/memory.py index 69b8ab8c..e9315ab4 100644 --- a/tradingagents/agents/utils/memory.py +++ b/tradingagents/agents/utils/memory.py @@ -1,3 +1,4 @@ +import os import chromadb from chromadb.config import Settings from openai import OpenAI @@ -5,11 +6,14 @@ from openai import OpenAI class FinancialSituationMemory: def __init__(self, name, config): - if config["backend_url"] == "http://localhost:11434/v1": + backend_url = os.environ.get("BACKEND_URL", config.get("backend_url")) + api_key = os.environ.get("OPENAI_API_KEY", config.get("openai_api_key")) + + if backend_url == "http://localhost:11434/v1": self.embedding = "nomic-embed-text" else: self.embedding = "text-embedding-3-small" - self.client = OpenAI(base_url=config["backend_url"]) + self.client = OpenAI(base_url=backend_url, api_key=api_key) self.chroma_client = chromadb.Client(Settings(allow_reset=True)) self.situation_collection = self.chroma_client.create_collection(name=name) diff --git a/tradingagents/default_config.py b/tradingagents/default_config.py index 089e9c24..ddd85965 100644 --- a/tradingagents/default_config.py +++ b/tradingagents/default_config.py @@ -1,4 +1,8 @@ import os +from dotenv import load_dotenv + +# Load environment variables from .env file +load_dotenv() DEFAULT_CONFIG = { "project_dir": os.path.abspath(os.path.join(os.path.dirname(__file__), ".")), @@ -12,7 +16,7 @@ DEFAULT_CONFIG = { "llm_provider": "openai", "deep_think_llm": "o4-mini", "quick_think_llm": "gpt-4o-mini", - "backend_url": "https://api.openai.com/v1", + "backend_url": os.getenv("BACKEND_URL", "https://api.openai.com/v1"), # Debate and discussion settings "max_debate_rounds": 1, "max_risk_discuss_rounds": 1, diff --git a/tradingagents/graph/trading_graph.py b/tradingagents/graph/trading_graph.py index 80a29e53..1b890716 100644 --- a/tradingagents/graph/trading_graph.py +++ b/tradingagents/graph/trading_graph.py @@ -48,6 +48,12 @@ class TradingAgentsGraph: self.debug = debug self.config = config or DEFAULT_CONFIG + # Override config with environment variables if set + self.config["backend_url"] = os.environ.get("BACKEND_URL", self.config.get("backend_url")) + self.config["OPENAI_API_KEY"] = os.environ.get("OPENAI_API_KEY", self.config.get("OPENAI_API_KEY")) + self.config["deep_think_llm"] = os.environ.get("DEEP_THINK_LLM", self.config.get("deep_think_llm")) + self.config["quick_think_llm"] = os.environ.get("QUICK_THINK_LLM", self.config.get("quick_think_llm")) + # Update the interface's config set_config(self.config)