From 903919cdee781cdfab4ab1ff53a6d113d5ac1c2e Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Sat, 23 Aug 2025 11:54:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AA=E5=9C=A8live=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- freqtrade/templates/freqaiprimer.py | 160 +++++++++++++++------------- 1 file changed, 83 insertions(+), 77 deletions(-) diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index ad515d23..9ce22e91 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -15,6 +15,7 @@ from pandas import DataFrame import pandas as pd from typing import Dict from freqtrade.strategy import (DecimalParameter, IStrategy, IntParameter) +from freqtrade.enums import RunMode from datetime import datetime logger = logging.getLogger(__name__) @@ -938,84 +939,89 @@ class FreqaiPrimer(IStrategy): # 获取最后一根K线的信号数据(避免重复记录) last_idx = enter_long_indices[-1] - try: - # 获取主机名 - hostname = socket.gethostname() - - # 将币对名从BTC/USDT格式转换为BTC-USDT格式 - pair_redis = pair.replace('/', '-') - - # 获取当前时间戳(毫秒) - timestamp_ms = int(time.time() * 1000) - - # 构建Redis key: ${主机名}_${币对名}_entry_${时间戳} - redis_key = f"{hostname}_{pair_redis}_entry_{timestamp_ms}" - - # 获取Redis客户端 - redis_client = self._get_redis_client() - if redis_client: - # 构建详细的条件分析 - detailed_conditions = [] - for name, value, operator, threshold, result in conditions_summary: - condition_detail = { - 'name': name, - 'value': float(value) if value is not None else None, - 'threshold': float(threshold) if threshold is not None else None, - 'operator': operator, - 'satisfied': bool(result) + # 只在live模式下记录Redis信号 + current_mode = self.config.get('runmode') + if current_mode == RunMode.LIVE: + try: + # 获取主机名 + hostname = socket.gethostname() + + # 将币对名从BTC/USDT格式转换为BTC-USDT格式 + pair_redis = pair.replace('/', '-') + + # 获取当前时间戳(毫秒) + timestamp_ms = int(time.time() * 1000) + + # 构建Redis key: ${主机名}_${币对名}_entry_${时间戳} + redis_key = f"{hostname}_{pair_redis}_entry_{timestamp_ms}" + + # 获取Redis客户端 + redis_client = self._get_redis_client() + if redis_client: + # 构建详细的条件分析 + detailed_conditions = [] + for name, value, operator, threshold, result in conditions_summary: + condition_detail = { + 'name': name, + 'value': float(value) if value is not None else None, + 'threshold': float(threshold) if threshold is not None else None, + 'operator': operator, + 'satisfied': bool(result) + } + detailed_conditions.append(condition_detail) + + # 准备要存储的详细信号数据 + signal_data = { + 'signal_strength': float(dataframe.loc[last_idx, 'signal_strength']) if 'signal_strength' in dataframe.columns else 0.0, + 'entry_tag': str(dataframe.loc[last_idx, 'entry_tag']) if 'entry_tag' in dataframe.columns else str(entry_tag), + 'trend_score': float(trend_score), + 'market_regime': str(market_regime), + 'timestamp': timestamp_ms, + 'pair': str(pair), + 'hostname': str(hostname), + 'immediate_entry': bool(dataframe.loc[last_idx, 'immediate_entry']) if 'immediate_entry' in dataframe.columns else False, + 'conditions_analysis': { + 'total_conditions': len(conditions_summary), + 'satisfied_count': sum(1 for _, _, _, _, result in conditions_summary if result), + 'failed_count': sum(1 for _, _, _, _, result in conditions_summary if not result), + 'detailed_conditions': detailed_conditions + }, + 'current_market_data': { + 'close_price': float(dataframe.loc[last_idx, 'close']), + 'ema50': float(dataframe.loc[last_idx, 'ema50']) if 'ema50' in dataframe.columns else None, + 'ema200': float(dataframe.loc[last_idx, 'ema200']) if 'ema200' in dataframe.columns else None, + 'bb_lower': float(dataframe.loc[last_idx, 'bb_lowerband']) if 'bb_lowerband' in dataframe.columns else None, + 'bb_upper': float(dataframe.loc[last_idx, 'bb_upperband']) if 'bb_upperband' in dataframe.columns else None, + 'rsi': float(dataframe.loc[last_idx, 'rsi']) if 'rsi' in dataframe.columns else None, + 'volume': float(dataframe.loc[last_idx, 'volume']) if 'volume' in dataframe.columns else None + }, + 'strategy_parameters': { + 'buy_threshold_min': float(self.buy_threshold_min), + 'buy_threshold_max': float(self.buy_threshold_max), + 'trend_bullish_threshold': int(self.TREND_BULLISH_THRESHOLD), + 'trend_bearish_threshold': int(self.TREND_BEARISH_THRESHOLD), + 'green_channel_discount': float(self.GREEN_CHANNEL_DISCOUNT), + 'entry_discount_bull_normal': float(self.entry_discount_bull_normal.value), + 'entry_discount_ranging': float(self.entry_discount_ranging.value), + 'entry_discount_bearish': float(self.entry_discount_bearish.value) + } } - detailed_conditions.append(condition_detail) - - # 准备要存储的详细信号数据 - signal_data = { - 'signal_strength': float(dataframe.loc[last_idx, 'signal_strength']) if 'signal_strength' in dataframe.columns else 0.0, - 'entry_tag': str(dataframe.loc[last_idx, 'entry_tag']) if 'entry_tag' in dataframe.columns else str(entry_tag), - 'trend_score': float(trend_score), - 'market_regime': str(market_regime), - 'timestamp': timestamp_ms, - 'pair': str(pair), - 'hostname': str(hostname), - 'immediate_entry': bool(dataframe.loc[last_idx, 'immediate_entry']) if 'immediate_entry' in dataframe.columns else False, - 'conditions_analysis': { - 'total_conditions': len(conditions_summary), - 'satisfied_count': sum(1 for _, _, _, _, result in conditions_summary if result), - 'failed_count': sum(1 for _, _, _, _, result in conditions_summary if not result), - 'detailed_conditions': detailed_conditions - }, - 'current_market_data': { - 'close_price': float(dataframe.loc[last_idx, 'close']), - 'ema50': float(dataframe.loc[last_idx, 'ema50']) if 'ema50' in dataframe.columns else None, - 'ema200': float(dataframe.loc[last_idx, 'ema200']) if 'ema200' in dataframe.columns else None, - 'bb_lower': float(dataframe.loc[last_idx, 'bb_lowerband']) if 'bb_lowerband' in dataframe.columns else None, - 'bb_upper': float(dataframe.loc[last_idx, 'bb_upperband']) if 'bb_upperband' in dataframe.columns else None, - 'rsi': float(dataframe.loc[last_idx, 'rsi']) if 'rsi' in dataframe.columns else None, - 'volume': float(dataframe.loc[last_idx, 'volume']) if 'volume' in dataframe.columns else None - }, - 'strategy_parameters': { - 'buy_threshold_min': float(self.buy_threshold_min), - 'buy_threshold_max': float(self.buy_threshold_max), - 'trend_bullish_threshold': int(self.TREND_BULLISH_THRESHOLD), - 'trend_bearish_threshold': int(self.TREND_BEARISH_THRESHOLD), - 'green_channel_discount': float(self.GREEN_CHANNEL_DISCOUNT), - 'entry_discount_bull_normal': float(self.entry_discount_bull_normal.value), - 'entry_discount_ranging': float(self.entry_discount_ranging.value), - 'entry_discount_bearish': float(self.entry_discount_bearish.value) - } - } - - # 将信号数据序列化为JSON字符串 - signal_json = json.dumps(signal_data, ensure_ascii=False, indent=2) - - # 存储到Redis,设置300天过期时间(25920000秒) - redis_client.setex(redis_key, 25920000, signal_json) - - logger.info(f"[Redis] ✅ 实际入场信号已记录: {redis_key}, 信号强度: {signal_data['signal_strength']:.2f}, 趋势: {signal_data['entry_tag']}") - - else: - logger.debug(f"[Redis] ⚠️ Redis客户端不可用,跳过记录: {pair}") - - except Exception as e: - logger.error(f"[Redis] ❌ 记录入场信号失败: {e}") + + # 将信号数据序列化为JSON字符串 + signal_json = json.dumps(signal_data, ensure_ascii=False, indent=2) + + # 存储到Redis,设置300天过期时间(25920000秒) + redis_client.setex(redis_key, 25920000, signal_json) + + logger.info(f"[Redis] ✅ Live模式 - 实际入场信号已记录: {redis_key}, 信号强度: {signal_data['signal_strength']:.2f}, 趋势: {signal_data['entry_tag']}") + + else: + logger.debug(f"[Redis] ⚠️ Redis客户端不可用,跳过记录: {pair}") + + except Exception as e: + logger.error(f"[Redis] ❌ Live模式 - 记录入场信号失败: {e}") + else: + logger.debug(f"[Redis] ℹ️ 非Live模式({current_mode}),跳过Redis记录: {pair}") # 输出每个条件的状态 logger.info(f"[{pair}] === 买入条件检查 ===")