TradingAgents/scripts/run_daily_discovery.py

146 lines
4.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Daily Discovery Runner — non-interactive script for cron/launchd scheduling.
Runs the full discovery pipeline (scan → filter → rank), saves recommendations,
and updates position tracking. Designed to run before market open (~8:30 AM ET).
Usage:
python scripts/run_daily_discovery.py # Uses defaults
python scripts/run_daily_discovery.py --date 2026-02-12 # Specific date
python scripts/run_daily_discovery.py --provider google # Override LLM provider
Scheduling (macOS launchd):
See the companion plist at scripts/com.tradingagents.discovery.plist
Scheduling (cron):
30 13 * * 1-5 cd /path/to/TradingAgents && .venv/bin/python scripts/run_daily_discovery.py >> logs/discovery_cron.log 2>&1
(13:30 UTC = 8:30 AM ET, weekdays only)
"""
import argparse
import os
import sys
from datetime import datetime
from pathlib import Path
# Ensure project root is on sys.path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))
os.chdir(ROOT)
from tradingagents.dataflows.config import set_config
from tradingagents.default_config import DEFAULT_CONFIG
from tradingagents.graph.discovery_graph import DiscoveryGraph
from tradingagents.utils.logger import get_logger
logger = get_logger("daily_discovery")
def parse_args():
parser = argparse.ArgumentParser(description="Run daily discovery pipeline")
parser.add_argument(
"--date",
default=datetime.now().strftime("%Y-%m-%d"),
help="Analysis date (YYYY-MM-DD), defaults to today",
)
parser.add_argument(
"--provider",
default=None,
help="LLM provider override (openai, google, anthropic)",
)
parser.add_argument(
"--shallow-model",
default=None,
help="Override quick_think_llm model name",
)
parser.add_argument(
"--deep-model",
default=None,
help="Override deep_think_llm model name",
)
parser.add_argument(
"--update-positions",
action="store_true",
default=True,
help="Update position tracking after discovery (default: True)",
)
parser.add_argument(
"--no-update-positions",
action="store_false",
dest="update_positions",
)
return parser.parse_args()
def run_discovery(args):
"""Run the discovery pipeline with the given arguments."""
config = DEFAULT_CONFIG.copy()
# Apply overrides
if args.provider:
config["llm_provider"] = args.provider.lower()
if args.shallow_model:
config["quick_think_llm"] = args.shallow_model
if args.deep_model:
config["deep_think_llm"] = args.deep_model
set_config(config)
# Create results directory
run_timestamp = datetime.now().strftime("%H_%M_%S")
results_dir = Path(config["results_dir"]) / "discovery" / args.date / f"run_{run_timestamp}"
results_dir.mkdir(parents=True, exist_ok=True)
config["discovery_run_dir"] = str(results_dir)
logger.info(f"Starting daily discovery for {args.date}")
logger.info(
f"Provider: {config['llm_provider']} | "
f"Shallow: {config['quick_think_llm']} | "
f"Deep: {config['deep_think_llm']}"
)
# Run discovery
graph = DiscoveryGraph(config=config)
result = graph.run(trade_date=args.date)
final_ranking = result.get("final_ranking", "No ranking available")
logger.info(f"Discovery complete. Results saved to {results_dir}")
return result
def update_positions():
"""Run position updates after discovery."""
try:
from scripts.update_positions import main as update_main
logger.info("Updating position tracking...")
update_main()
except Exception as e:
logger.error(f"Position update failed: {e}")
def main():
args = parse_args()
logger.info("=" * 60)
logger.info(f"DAILY DISCOVERY RUN — {datetime.now().isoformat()}")
logger.info("=" * 60)
try:
result = run_discovery(args)
if args.update_positions:
update_positions()
logger.info("Daily discovery completed successfully")
except Exception as e:
logger.error(f"Discovery failed: {e}", exc_info=True)
sys.exit(1)
if __name__ == "__main__":
main()