diff --git a/bot.py b/bot.py index 241d5ea..4ae111c 100644 --- a/bot.py +++ b/bot.py @@ -13,6 +13,7 @@ from services import ( place_order, market_open, positions_snapshot, + account_snapshot, qdrant_similar, qdrant_add_memory, trilium_log, @@ -43,6 +44,12 @@ def curate_cycle(): def run_cycle(): db = SessionLocal() try: + acct = account_snapshot() + # If paper credentials are invalid/missing, avoid flooding failed decisions. + if settings.paper_mode and not acct.get('id'): + trilium_log('Bot paused: paper auth invalid', 'Paper mode enabled but Alpaca paper account auth failed. Skipping run_cycle to avoid false failures.') + return + if not market_open() and not (settings.paper_mode and settings.force_paper_trades): return spent = _daily_spent(db) @@ -149,9 +156,36 @@ def run_cycle(): def start_scheduler(): - scheduler.add_job(curate_cycle, "interval", minutes=settings.curate_interval_minutes, id="curate_cycle", replace_existing=True) + scheduler.add_job( + curate_cycle, + "interval", + minutes=settings.curate_interval_minutes, + id="curate_cycle", + replace_existing=True, + coalesce=True, + max_instances=1, + misfire_grace_time=120, + ) if settings.trade_interval_minutes and settings.trade_interval_minutes > 0: - scheduler.add_job(run_cycle, "interval", minutes=settings.trade_interval_minutes, id="trade_cycle", replace_existing=True) + scheduler.add_job( + run_cycle, + "interval", + minutes=settings.trade_interval_minutes, + id="trade_cycle", + replace_existing=True, + coalesce=True, + max_instances=1, + misfire_grace_time=120, + ) else: - scheduler.add_job(run_cycle, "interval", hours=settings.trade_interval_hours, id="trade_cycle", replace_existing=True) + scheduler.add_job( + run_cycle, + "interval", + hours=settings.trade_interval_hours, + id="trade_cycle", + replace_existing=True, + coalesce=True, + max_instances=1, + misfire_grace_time=120, + ) scheduler.start()