趋势函数独立出来, 95分以上不退出

This commit is contained in:
zhangkun9038@dingtalk.com 2025-08-30 15:09:26 +08:00
parent 3109e1064d
commit 857e00bc19

View File

@ -2,8 +2,9 @@ import warnings
warnings.filterwarnings("ignore", category=UserWarning, module="pandas_ta")
import logging
import pandas as pd
from freqtrade.strategy import IStrategy
from pandas import DataFrame
from pandas import DataFrame, Series
import pandas_ta as ta
from freqtrade.persistence import Trade
import numpy as np
@ -120,44 +121,8 @@ class FreqaiPrimer(IStrategy):
(dataframe['open'] < dataframe['close'].shift(1))
)
# 计算各时间框架的趋势状态(牛/熊)
# 3m时间框架ema50下穿ema200为熊上穿为牛
dataframe['trend_3m'] = np.where(dataframe['ema_50_3m'] > dataframe['ema_200_3m'], 1, 0)
# 15m时间框架ema50下穿ema200为熊上穿为牛
dataframe['trend_15m'] = np.where(dataframe['ema_50_15m'] > dataframe['ema_200_15m'], 1, 0)
# 1h时间框架ema50下穿ema200为熊上穿为牛
dataframe['trend_1h_ema'] = np.where(dataframe['ema_50_1h'] > dataframe['ema_200_1h'], 1, 0)
# 计算熊牛得分0-100
# 权重3m熊牛权重1015m熊牛权重351h熊牛权重65
# 计算加权得分
dataframe['market_score'] = (
dataframe['trend_3m'] * 10 +
dataframe['trend_15m'] * 35 +
dataframe['trend_1h_ema'] * 65
)
# 确保得分在0-100范围内
dataframe['market_score'] = dataframe['market_score'].clip(lower=0, upper=100)
# 根据得分分类市场状态
dataframe['market_state'] = 'neutral'
dataframe.loc[dataframe['market_score'] > 70, 'market_state'] = 'strong_bull'
dataframe.loc[(dataframe['market_score'] > 50) & (dataframe['market_score'] <= 70), 'market_state'] = 'weak_bull'
dataframe.loc[(dataframe['market_score'] >= 30) & (dataframe['market_score'] <= 50), 'market_state'] = 'neutral'
dataframe.loc[(dataframe['market_score'] > 10) & (dataframe['market_score'] < 30), 'market_state'] = 'weak_bear'
dataframe.loc[dataframe['market_score'] <= 10, 'market_state'] = 'strong_bear'
# 记录当前的市场状态
if len(dataframe) > 0:
current_score = dataframe['market_score'].iloc[-1]
current_state = dataframe['market_state'].iloc[-1]
logger.info(f"[{metadata['pair']}] 熊牛得分: {current_score:.1f}, 市场状态: {current_state}")
logger.info(f"[{metadata['pair']}] 各时间框架趋势: 3m={'' if dataframe['trend_3m'].iloc[-1] == 1 else ''}, \
15m={'' if dataframe['trend_15m'].iloc[-1] == 1 else ''}, \
1h={'' if dataframe['trend_1h_ema'].iloc[-1] == 1 else ''}")
# 计算市场评分并更新到dataframe
market_score = self.calculate_market_score(dataframe, metadata)
# 调试:打印指标值(最后 5 行)
print(f"Pair: {metadata['pair']}, Last 5 rows:")
@ -166,6 +131,118 @@ class FreqaiPrimer(IStrategy):
'bullish_engulfing', 'volume', 'volume_ma']].tail(5))
return dataframe
def calculate_market_score(self, dataframe: DataFrame, metadata: dict) -> int:
"""
计算市场评分0-100的整数
参数:
- dataframe: 数据框
- metadata: 元数据
返回:
- int: 市场评分(0-100)
"""
# 确保数据框不为空
if len(dataframe) == 0:
return 50 # 默认返回中性分数
# 计算各时间框架的趋势状态0-100归一化
dataframe = self.calculate_timeframe_score(dataframe, '3m', 'ema_50_3m', 'ema_200_3m')
dataframe = self.calculate_timeframe_score(dataframe, '15m', 'ema_50_15m', 'ema_200_15m')
dataframe = self.calculate_timeframe_score(dataframe, '1h', 'ema_50_1h', 'ema_200_1h')
# 计算加权综合得分权重3m=1015m=351h=65
market_score = (
dataframe['trend_score_3m'].iloc[-1] * 10 +
dataframe['trend_score_15m'].iloc[-1] * 35 +
dataframe['trend_score_1h'].iloc[-1] * 65
)
# 确保得分在0-100范围内并转为整数
market_score = int(max(0, min(100, market_score)))
# 更新dataframe中的market_score和market_state列
dataframe['market_score'] = market_score
dataframe['market_state'] = self.classify_market_state(pd.Series([market_score]))
# 记录当前的市场状态
current_state = dataframe['market_state'].iloc[-1]
logger.info(f"[{metadata['pair']}] 熊牛得分: {market_score}, 市场状态: {current_state}")
# 获取各时间框架的趋势状态
trend_3m = 1 if dataframe['ema_50_3m'].iloc[-1] > dataframe['ema_200_3m'].iloc[-1] else 0
trend_15m = 1 if dataframe['ema_50_15m'].iloc[-1] > dataframe['ema_200_15m'].iloc[-1] else 0
trend_1h_ema = 1 if dataframe['ema_50_1h'].iloc[-1] > dataframe['ema_200_1h'].iloc[-1] else 0
logger.info(f"[{metadata['pair']}] 各时间框架趋势: 3m={'' if trend_3m == 1 else ''}, \
15m={'' if trend_15m == 1 else ''}, \
1h={'' if trend_1h_ema == 1 else ''}")
return market_score
def get_market_score(self, dataframe: DataFrame, metadata: dict) -> int:
"""
返回市场评分0-100的整数
参数:
- dataframe: 数据框
- metadata: 元数据
返回:
- int: 市场评分(0-100)
"""
# 确保数据框不为空
if len(dataframe) == 0:
return 50 # 默认返回中性分数
# 计算各时间框架的趋势
trend_3m = 1 if dataframe['ema_50_3m'].iloc[-1] > dataframe['ema_200_3m'].iloc[-1] else 0
trend_15m = 1 if dataframe['ema_50_15m'].iloc[-1] > dataframe['ema_200_15m'].iloc[-1] else 0
trend_1h_ema = 1 if dataframe['ema_50_1h'].iloc[-1] > dataframe['ema_200_1h'].iloc[-1] else 0
# 计算加权综合得分权重3m=1015m=351h=65
market_score = (
trend_3m * 10 +
trend_15m * 35 +
trend_1h_ema * 65
)
# 确保得分在0-100范围内并转为整数
market_score = int(max(0, min(100, market_score)))
return market_score
def calculate_timeframe_score(self, dataframe: DataFrame, timeframe: str, ema_short: str, ema_long: str) -> DataFrame:
"""
计算单个时间框架的趋势得分(0-100)
"""
# 基本趋势判断1为牛0为熊
column_name = f'trend_{timeframe}'
score_column = f'trend_score_{timeframe}'
dataframe[column_name] = np.where(dataframe[ema_short] > dataframe[ema_long], 1, 0)
# 将趋势值归一化为0-100分
dataframe[score_column] = dataframe[column_name] * 100
return dataframe
def classify_market_state(self, market_score: Series) -> Series:
"""
根据市场得分分类市场状态
"""
market_state = np.where(
market_score > 70, 'strong_bull',
np.where(
market_score > 50, 'weak_bull',
np.where(
market_score >= 30, 'neutral',
np.where(
market_score > 10, 'weak_bear',
'strong_bear'
)
)
)
)
return pd.Series(market_state, index=market_score.index)
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# 做多条件(放宽以增加入场信号)
@ -233,6 +310,9 @@ class FreqaiPrimer(IStrategy):
# 一般趋势条件熊牛得分50-70
normal_trend = (dataframe['market_score'] >= 50) & (dataframe['market_score'] <= 70)
# 极强劲趋势条件:熊牛得分>95此时不给退出信号
extreme_strong_trend = dataframe['market_score'] > 95
# 获取15m数据进行趋势确认
df_15m = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='15m')
@ -270,12 +350,16 @@ class FreqaiPrimer(IStrategy):
trend_reversal = merged_data['rsi_15m'] > 75
# 动态调整退出条件 - 提高ATR倍数以增加单笔盈利潜力
# 强劲趋势中大幅提高ATR倍数到5.5倍,充分利用趋势利润
dataframe.loc[strong_trend & ((dataframe['close'] > dataframe['open'] + dataframe['atr'] * 5.5) | (basic_exit & trend_reversal)), 'exit_long'] = 1
# 强劲趋势中大幅提高ATR倍数到5.5倍,充分利用趋势利润,但当趋势极强时不给退出信号
dataframe.loc[strong_trend & ~extreme_strong_trend & ((dataframe['close'] > dataframe['open'] + dataframe['atr'] * 5.5) | (basic_exit & trend_reversal)), 'exit_long'] = 1
# 一般趋势中提高到4倍ATR退出
dataframe.loc[normal_trend & ((dataframe['close'] > dataframe['open'] + dataframe['atr'] * 4) | basic_exit), 'exit_long'] = 1
# 记录极端强劲趋势阻止退出的情况
if len(dataframe[extreme_strong_trend]) > 0:
logger.info(f"[{metadata['pair']}] 熊牛得分>95处于极端强劲趋势不给出退出信号")
# 非趋势或弱势保持2倍ATR退出
# 记录退出决策日志