Merge pull request #84 from aguzererler/copilot/standardize-env-variables

Standardize env/config loading: single entry point in `default_config.py`
This commit is contained in:
ahmet guzererler 2026-03-21 23:46:35 +01:00 committed by GitHub
commit d4a8ea38c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 44 deletions

View File

@ -11,15 +11,13 @@ ALPHA_VANTAGE_API_KEY=
# Free at https://finnhub.io — required for earnings/economic calendars and insider transactions
FINNHUB_API_KEY=
TRADINGAGENTS_RESULTS_DIR=./my_results
TRADINGAGENTS_MAX_DEBATE_ROUNDS=2
#TRADINGAGENTS_VENDOR_SCANNER_DATA=alpha_vantage
# ── Configuration overrides ──────────────────────────────────────────
# Any setting in DEFAULT_CONFIG (tradingagents/default_config.py) can be
# overridden with a TRADINGAGENTS_<KEY> environment variable.
# Unset or empty values are ignored (the hardcoded default is kept).
# Unset or empty values are ignored — the hardcoded default is kept.
#
# This file is the single source of truth for runtime configuration.
# Copy this file to .env and fill in the values you want to override.
# ── General ──────────────────────────────────────────────────────────
# TRADINGAGENTS_RESULTS_DIR=./results
@ -59,8 +57,8 @@ TRADINGAGENTS_MAX_DEBATE_ROUNDS=2
# TRADINGAGENTS_QUICK_THINK_OPENAI_REASONING_EFFORT=
# ── Debate & discussion settings ─────────────────────────────────────
# TRADINGAGENTS_MAX_DEBATE_ROUNDS=1 # bull/bear investment debate rounds (15)
# TRADINGAGENTS_MAX_RISK_DISCUSS_ROUNDS=1 # risk analyst discussion rounds (15)
# TRADINGAGENTS_MAX_DEBATE_ROUNDS=2 # bull/bear investment debate rounds (15)
# TRADINGAGENTS_MAX_RISK_DISCUSS_ROUNDS=2 # risk analyst discussion rounds (15)
# TRADINGAGENTS_MAX_RECUR_LIMIT=100 # LangGraph recursion limit
# ── Google NotebookLM sync (optional) ────────────────────────────────
@ -75,3 +73,18 @@ TRADINGAGENTS_MAX_DEBATE_ROUNDS=2
# TRADINGAGENTS_VENDOR_NEWS_DATA=yfinance
# TRADINGAGENTS_VENDOR_SCANNER_DATA=yfinance
# TRADINGAGENTS_VENDOR_CALENDAR_DATA=finnhub
# ── Portfolio Manager ─────────────────────────────────────────────────
# PostgreSQL connection string for Supabase (required for portfolio commands)
# SUPABASE_CONNECTION_STRING=postgresql://postgres.<project>:<password>@aws-1-<region>.pooler.supabase.com:6543/postgres
# Portfolio data directory (where JSON reports are stored)
# TRADINGAGENTS_PORTFOLIO_DATA_DIR=reports
# Portfolio constraint overrides
# TRADINGAGENTS_PM_MAX_POSITIONS=15 # maximum number of open positions
# TRADINGAGENTS_PM_MAX_POSITION_PCT=0.15 # max single position as fraction of portfolio
# TRADINGAGENTS_PM_MAX_SECTOR_PCT=0.35 # max sector concentration
# TRADINGAGENTS_PM_MIN_CASH_PCT=0.05 # minimum cash reserve
# TRADINGAGENTS_PM_DEFAULT_BUDGET=100000.0 # starting cash budget (USD)

View File

@ -8,8 +8,11 @@ from functools import wraps
from rich.console import Console
from dotenv import load_dotenv
# Load environment variables from .env file.
# Checks CWD first, then falls back to project root (relative to this script).
# Load API keys (OPENAI_API_KEY, GOOGLE_API_KEY, etc.) from the .env file
# before any network call is made. tradingagents.default_config also calls
# load_dotenv() at import time (for TRADINGAGENTS_* config vars), so these
# two calls are a defence-in-depth safety net for the CLI entry point.
# Order: CWD .env first, then the project-root .env as a fallback.
load_dotenv()
load_dotenv(Path(__file__).resolve().parent.parent / ".env")
from rich.panel import Panel

View File

@ -18,6 +18,9 @@ def _env(key: str, default=None):
``TRADINGAGENTS_MID_THINK_LLM=`` in a ``.env`` file is treated the
same as not setting it at all (preserving the ``None`` semantics for
"fall back to the parent setting").
This is the single source of truth for config env-var reading.
Import and reuse this helper instead of duplicating it elsewhere.
"""
val = os.getenv(f"TRADINGAGENTS_{key.upper()}")
if not val: # None or ""
@ -36,6 +39,17 @@ def _env_int(key: str, default=None):
return default
def _env_float(key: str, default=None):
"""Like :func:`_env` but coerces the value to ``float``."""
val = _env(key)
if val is None:
return default
try:
return float(val)
except (ValueError, TypeError):
return default
DEFAULT_CONFIG = {
"project_dir": os.path.abspath(os.path.join(os.path.dirname(__file__), ".")),
"results_dir": _env("RESULTS_DIR", "./reports"),

View File

@ -3,6 +3,10 @@
Integrates with the existing ``tradingagents/default_config.py`` pattern,
reading all portfolio settings from ``TRADINGAGENTS_<KEY>`` env vars.
All env-var reading is delegated to the shared helpers in
``tradingagents.default_config`` that module is the single entry point
for .env loading and the ``_env*`` helper functions.
Usage::
from tradingagents.portfolio.config import get_portfolio_config, validate_config
@ -16,40 +20,11 @@ from __future__ import annotations
import os
from dotenv import load_dotenv
load_dotenv()
def _env(key: str, default=None):
"""Read ``TRADINGAGENTS_<KEY>`` from the environment.
Matches the convention in ``tradingagents/default_config.py``.
"""
val = os.getenv(f"TRADINGAGENTS_{key.upper()}")
if not val:
return default
return val
def _env_float(key: str, default=None):
val = _env(key)
if val is None:
return default
try:
return float(val)
except (ValueError, TypeError):
return default
def _env_int(key: str, default=None):
val = _env(key)
if val is None:
return default
try:
return int(val)
except (ValueError, TypeError):
return default
# Importing default_config triggers its module-level load_dotenv() calls,
# which loads the .env file (CWD first, then project root) before we read
# any TRADINGAGENTS_* variables below. This is the single source of truth
# for .env loading — no separate load_dotenv() call needed here.
from tradingagents.default_config import _env, _env_float, _env_int
PORTFOLIO_CONFIG: dict = {