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:
commit
d4a8ea38c1
29
.env.example
29
.env.example
|
|
@ -11,15 +11,13 @@ ALPHA_VANTAGE_API_KEY=
|
||||||
# Free at https://finnhub.io — required for earnings/economic calendars and insider transactions
|
# Free at https://finnhub.io — required for earnings/economic calendars and insider transactions
|
||||||
FINNHUB_API_KEY=
|
FINNHUB_API_KEY=
|
||||||
|
|
||||||
TRADINGAGENTS_RESULTS_DIR=./my_results
|
|
||||||
TRADINGAGENTS_MAX_DEBATE_ROUNDS=2
|
|
||||||
|
|
||||||
#TRADINGAGENTS_VENDOR_SCANNER_DATA=alpha_vantage
|
|
||||||
|
|
||||||
# ── Configuration overrides ──────────────────────────────────────────
|
# ── Configuration overrides ──────────────────────────────────────────
|
||||||
# Any setting in DEFAULT_CONFIG (tradingagents/default_config.py) can be
|
# Any setting in DEFAULT_CONFIG (tradingagents/default_config.py) can be
|
||||||
# overridden with a TRADINGAGENTS_<KEY> environment variable.
|
# 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 ──────────────────────────────────────────────────────────
|
# ── General ──────────────────────────────────────────────────────────
|
||||||
# TRADINGAGENTS_RESULTS_DIR=./results
|
# TRADINGAGENTS_RESULTS_DIR=./results
|
||||||
|
|
@ -59,8 +57,8 @@ TRADINGAGENTS_MAX_DEBATE_ROUNDS=2
|
||||||
# TRADINGAGENTS_QUICK_THINK_OPENAI_REASONING_EFFORT=
|
# TRADINGAGENTS_QUICK_THINK_OPENAI_REASONING_EFFORT=
|
||||||
|
|
||||||
# ── Debate & discussion settings ─────────────────────────────────────
|
# ── Debate & discussion settings ─────────────────────────────────────
|
||||||
# TRADINGAGENTS_MAX_DEBATE_ROUNDS=1 # bull/bear investment debate rounds (1–5)
|
# TRADINGAGENTS_MAX_DEBATE_ROUNDS=2 # bull/bear investment debate rounds (1–5)
|
||||||
# TRADINGAGENTS_MAX_RISK_DISCUSS_ROUNDS=1 # risk analyst discussion rounds (1–5)
|
# TRADINGAGENTS_MAX_RISK_DISCUSS_ROUNDS=2 # risk analyst discussion rounds (1–5)
|
||||||
# TRADINGAGENTS_MAX_RECUR_LIMIT=100 # LangGraph recursion limit
|
# TRADINGAGENTS_MAX_RECUR_LIMIT=100 # LangGraph recursion limit
|
||||||
|
|
||||||
# ── Google NotebookLM sync (optional) ────────────────────────────────
|
# ── Google NotebookLM sync (optional) ────────────────────────────────
|
||||||
|
|
@ -75,3 +73,18 @@ TRADINGAGENTS_MAX_DEBATE_ROUNDS=2
|
||||||
# TRADINGAGENTS_VENDOR_NEWS_DATA=yfinance
|
# TRADINGAGENTS_VENDOR_NEWS_DATA=yfinance
|
||||||
# TRADINGAGENTS_VENDOR_SCANNER_DATA=yfinance
|
# TRADINGAGENTS_VENDOR_SCANNER_DATA=yfinance
|
||||||
# TRADINGAGENTS_VENDOR_CALENDAR_DATA=finnhub
|
# 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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,11 @@ from functools import wraps
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
# Load environment variables from .env file.
|
# Load API keys (OPENAI_API_KEY, GOOGLE_API_KEY, etc.) from the .env file
|
||||||
# Checks CWD first, then falls back to project root (relative to this script).
|
# 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()
|
||||||
load_dotenv(Path(__file__).resolve().parent.parent / ".env")
|
load_dotenv(Path(__file__).resolve().parent.parent / ".env")
|
||||||
from rich.panel import Panel
|
from rich.panel import Panel
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ def _env(key: str, default=None):
|
||||||
``TRADINGAGENTS_MID_THINK_LLM=`` in a ``.env`` file is treated the
|
``TRADINGAGENTS_MID_THINK_LLM=`` in a ``.env`` file is treated the
|
||||||
same as not setting it at all (preserving the ``None`` semantics for
|
same as not setting it at all (preserving the ``None`` semantics for
|
||||||
"fall back to the parent setting").
|
"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()}")
|
val = os.getenv(f"TRADINGAGENTS_{key.upper()}")
|
||||||
if not val: # None or ""
|
if not val: # None or ""
|
||||||
|
|
@ -36,6 +39,17 @@ def _env_int(key: str, default=None):
|
||||||
return default
|
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 = {
|
DEFAULT_CONFIG = {
|
||||||
"project_dir": os.path.abspath(os.path.join(os.path.dirname(__file__), ".")),
|
"project_dir": os.path.abspath(os.path.join(os.path.dirname(__file__), ".")),
|
||||||
"results_dir": _env("RESULTS_DIR", "./reports"),
|
"results_dir": _env("RESULTS_DIR", "./reports"),
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,10 @@
|
||||||
Integrates with the existing ``tradingagents/default_config.py`` pattern,
|
Integrates with the existing ``tradingagents/default_config.py`` pattern,
|
||||||
reading all portfolio settings from ``TRADINGAGENTS_<KEY>`` env vars.
|
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::
|
Usage::
|
||||||
|
|
||||||
from tradingagents.portfolio.config import get_portfolio_config, validate_config
|
from tradingagents.portfolio.config import get_portfolio_config, validate_config
|
||||||
|
|
@ -16,40 +20,11 @@ from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
# Importing default_config triggers its module-level load_dotenv() calls,
|
||||||
|
# which loads the .env file (CWD first, then project root) before we read
|
||||||
load_dotenv()
|
# 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
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
PORTFOLIO_CONFIG: dict = {
|
PORTFOLIO_CONFIG: dict = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue