146 lines
4.2 KiB
Python
Executable File
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()
|