From 096315379809bdc81a606de82e14b01946143de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80?= <78488229+viktor138irk@users.noreply.github.com> Date: Fri, 8 May 2026 04:41:02 +0900 Subject: [PATCH] Use all synced CoinEx markets in monitor rotation --- app/monitor.py | 66 ++++++++++---------------------------------------- 1 file changed, 13 insertions(+), 53 deletions(-) diff --git a/app/monitor.py b/app/monitor.py index bfe1bd8..0d43343 100644 --- a/app/monitor.py +++ b/app/monitor.py @@ -36,6 +36,7 @@ class SignalMonitor: 'last_error': self.last_error, 'last_run_at': self.last_run_at.isoformat() if self.last_run_at else None, 'rules_synced': self.rules_synced, + 'markets_count': len(self.ai_bot.markets), } async def loop(self, session_factory, interval_seconds: int = 10) -> None: @@ -63,9 +64,12 @@ class SignalMonitor: self.last_run_at = datetime.now(timezone.utc) if not self.rules_synced: try: - result = await self.market_rules.sync(db, self.ai_bot.markets) + result = await self.market_rules.sync(db, None) + active_markets = self.market_rules.active_markets(db, fallback=self.ai_bot.markets) + if active_markets: + self.ai_bot.markets = active_markets self.rules_synced = True - self.write_log(db, 'success', 'coinex_rules_synced', f'Синхронизированы лимиты и комиссии CoinEx: {result["synced"]} рынков.') + self.write_log(db, 'success', 'coinex_rules_synced', f'Синхронизированы лимиты и комиссии CoinEx: {result["synced"]} рынков. Активных рынков в работе: {len(self.ai_bot.markets)}.') except Exception as exc: # noqa: BLE001 self.write_log(db, 'warning', 'coinex_rules_sync_failed', f'Не удалось синхронизировать лимиты CoinEx: {exc}') @@ -78,22 +82,14 @@ class SignalMonitor: self.write_log(db, 'warning', 'emergency_stop', 'Аварийная остановка активна. Новые сделки не открываются.') return self.status() - self.write_log(db, 'info', 'scan_started', 'Сканирую рынки по ротации, пропускаю пары с уже открытой сделкой.') + self.write_log(db, 'info', 'scan_started', f'Сканирую рынки по ротации: {len(self.ai_bot.markets)} активных CoinEx-маркетов, пары с открытой сделкой пропускаю.') decision = await self.ai_bot.make_decision(db, None, skip_open_positions=True) data = decision_to_dict(decision) self.last_market = decision.market self.last_action = decision.action self.last_score = decision.score action_ru = {'buy': 'покупка', 'sell': 'продажа', 'hold': 'ожидание'}.get(decision.action, decision.action) - self.write_log( - db, - 'info', - 'signal_found', - f'Найден сигнал: {decision.market}, действие: {action_ru}, оценка AI: {decision.score:.1f}/100.', - market=decision.market, - action=decision.action, - score=decision.score, - ) + self.write_log(db, 'info', 'signal_found', f'Найден сигнал: {decision.market}, действие: {action_ru}, оценка AI: {decision.score:.1f}/100.', market=decision.market, action=decision.action, score=decision.score) if state.trade_mode == 'demo' and decision.action == 'buy' and decision.score >= state.min_signal_score: price = float(data['indicators']['last_price']) @@ -104,15 +100,7 @@ class SignalMonitor: db.commit() self.legacy_bot.snapshot_history(db) self.last_status = f'Открыта демо-сделка BUY {trade.market}' - self.write_log( - db, - 'success', - 'demo_order_opened', - f'Открыта демо-сделка: BUY {trade.market}, сумма {trade.quote_amount:.2f} USDT, цена {trade.price:.8f}. {rule_message}', - market=trade.market, - action=trade.side, - score=decision.score, - ) + self.write_log(db, 'success', 'demo_order_opened', f'Открыта демо-сделка: BUY {trade.market}, сумма {trade.quote_amount:.2f} USDT, цена {trade.price:.8f}. {rule_message}', market=trade.market, action=trade.side, score=decision.score) elif state.trade_mode == 'demo' and decision.action == 'sell' and decision.score >= state.min_signal_score: price = float(data['indicators']['last_price']) if self.demo_service.has_open_position(db, decision.market): @@ -124,27 +112,11 @@ class SignalMonitor: self.last_status = 'SELL сигнал без открытой позиции' self.write_log(db, 'info', 'sell_without_position', f'SELL сигнал по {decision.market}, но открытой позиции нет — пропускаю.', market=decision.market, action='sell', score=decision.score) elif state.trade_mode == 'live' and decision.action in {'buy', 'sell'} and decision.score >= state.min_signal_score: - self.last_status = 'Найден live-сигнал, ожидает live adapter' - self.write_log( - db, - 'warning', - 'live_signal_waiting', - f'Live-сигнал найден: {decision.market}, {action_ru}, оценка {decision.score:.1f}. Перед live-ордером нужно сверить доступный баланс/позицию через API CoinEx.', - market=decision.market, - action=decision.action, - score=decision.score, - ) + self.last_status = 'Live-сигнал готов к исполнению' + self.write_log(db, 'warning', 'live_signal_ready', f'Live-сигнал найден: {decision.market}, {action_ru}, оценка {decision.score:.1f}. Требуется live-order adapter CoinEx: сверить баланс и отправить ордер.', market=decision.market, action=decision.action, score=decision.score) else: self.last_status = 'Сигнал слабый, сделка не открыта' - self.write_log( - db, - 'info', - 'signal_skipped', - f'Сделка пропущена: {decision.market}, оценка {decision.score:.1f}, минимум {state.min_signal_score:.1f}.', - market=decision.market, - action=decision.action, - score=decision.score, - ) + self.write_log(db, 'info', 'signal_skipped', f'Сделка пропущена: {decision.market}, оценка {decision.score:.1f}, минимум {state.min_signal_score:.1f}.', market=decision.market, action=decision.action, score=decision.score) return self.status() def write_log(self, db: Session, level: str, event: str, message: str, market: str = '', action: str = '', score: float = 0.0) -> None: @@ -153,16 +125,4 @@ class SignalMonitor: def recent_logs(self, db: Session, limit: int = 100) -> list[dict[str, Any]]: rows = db.query(BotLog).order_by(BotLog.id.desc()).limit(limit).all() - return [ - { - 'id': row.id, - 'level': row.level, - 'event': row.event, - 'message': row.message, - 'market': row.market, - 'action': row.action, - 'score': row.score, - 'created_at': row.created_at.isoformat(), - } - for row in rows - ] + return [{'id': row.id, 'level': row.level, 'event': row.event, 'message': row.message, 'market': row.market, 'action': row.action, 'score': row.score, 'created_at': row.created_at.isoformat()} for row in rows]