修复了很多问题, 需要进一步验证,所以单开一个分支
This commit is contained in:
parent
418559b51d
commit
eba5040214
162
doc/问题.md
Normal file
162
doc/问题.md
Normal file
@ -0,0 +1,162 @@
|
||||
好的,我来对 FreqAI 相关逻辑和变量进行全面排查。
|
||||
现在我整理出 FreqAI 相关逻辑的全面排查结果:
|
||||
|
||||
---
|
||||
|
||||
## **FreqAI 逻辑排查报告**
|
||||
|
||||
### **问题 1:pandas 废弃方法(第 333 行)** ⚠️
|
||||
|
||||
```python
|
||||
# 当前代码(废弃)
|
||||
dataframe["%-raw_price"] = dataframe["close"].fillna(method="ffill")
|
||||
|
||||
# 应改为
|
||||
dataframe["%-raw_price"] = dataframe["close"].ffill()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **问题 2:价格调整硬编码(第 666、830 行)** ⚠️
|
||||
|
||||
价格调整使用硬编码 `0.9833`(1.67%),**没有使用 hyperopt 可优化参数**:
|
||||
|
||||
```python
|
||||
# 第 666 行 - populate_entry_trend
|
||||
dataframe.loc[final_condition_updated, 'enter_price'] = dataframe.loc[final_condition_updated, 'close'] * 0.9833
|
||||
|
||||
# 第 830 行 - confirm_trade_entry
|
||||
adjusted_entry_price = rate * 0.9833
|
||||
```
|
||||
|
||||
**之前讨论过但未完成**:缺少 `entry_price_discount` 和 `exit_price_premium` 的 hyperopt 参数定义。
|
||||
|
||||
---
|
||||
|
||||
### **问题 3:`future_volatility` 列名不一致(第 912-913 行)** ⚠️
|
||||
|
||||
```python
|
||||
# 训练时设置的列名是:
|
||||
dataframe["&s-future_volatility"] = ... # 第 381 行
|
||||
|
||||
# 读取时的列名不一致:
|
||||
if '&s-future_volatility' in df.columns: # ✅ 正确
|
||||
future_vol_signal = float(last_row['&s-future_volatility'])
|
||||
elif '&-future_volatility' in df.columns: # ❌ 错误前缀,应该是 &s-
|
||||
future_vol_signal = float(last_row['&-future_volatility'])
|
||||
```
|
||||
|
||||
**第 913 行的 `&-future_volatility` 永远不会匹配到(前缀错误)**。
|
||||
|
||||
---
|
||||
|
||||
### **问题 4:entry_signal 列名备选项不一致(第 800-803 行)**
|
||||
|
||||
```python
|
||||
# 训练时设置:
|
||||
dataframe["&s-entry_signal"] = ... # 第 357 行
|
||||
|
||||
# 读取时备选列名不规范:
|
||||
if '&s-entry_signal' in df.columns: # ✅ 正确
|
||||
elif '&-entry_signal_prob' in df.columns: # ❓ 不规范
|
||||
elif '&-s-entry_signal_prob' in df.columns: # ❓ 不规范
|
||||
```
|
||||
|
||||
建议统一使用 FreqAI 标准前缀 `&s-`。
|
||||
|
||||
---
|
||||
|
||||
### **问题 5:止损参数与之前讨论的 72 分钟窗口不匹配(第 27 行)**
|
||||
|
||||
```python
|
||||
stoploss = -0.15 # 固定止损 -15%
|
||||
```
|
||||
|
||||
**之前讨论过**:72 分钟预测窗口,目标涨幅 1-2%,但止损 -15% 太宽松(风险收益比约 10:1)。
|
||||
|
||||
建
|
||||
现在汇总发现的所有问题:
|
||||
|
||||
---
|
||||
|
||||
## **FreqAI 相关逻辑排查报告**
|
||||
|
||||
### **🔴 问题1:pandas `fillna(method="ffill")` 废弃警告**
|
||||
**位置:** 第 333 行
|
||||
```python
|
||||
dataframe["%-raw_price"] = dataframe["close"].fillna(method="ffill")
|
||||
```
|
||||
**问题:** `fillna(method="ffill")` 在 pandas 2.0+ 中已废弃,会抛出 FutureWarning
|
||||
|
||||
---
|
||||
|
||||
### **🔴 问题2:入场价格硬编码,未使用 hyperopt 参数**
|
||||
**位置:** 第 666、828-830 行
|
||||
```python
|
||||
# 第 666 行 - populate_entry_trend
|
||||
dataframe.loc[final_condition_updated, 'enter_price'] = dataframe.loc[final_condition_updated, 'close'] * 0.9833
|
||||
|
||||
# 第 828-830 行 - confirm_trade_entry
|
||||
price_discount_percent = 1.67
|
||||
adjusted_entry_price = rate * 0.9833
|
||||
```
|
||||
**问题:**
|
||||
- 入场价格下调 1.67% 是硬编码的,无法通过 hyperopt 优化
|
||||
- 之前记忆中提到需要定义 `entry_price_discount` 和 `exit_price_premium` 为 hyperopt 参数,但代码中**缺少这两个参数定义**
|
||||
|
||||
---
|
||||
|
||||
### **🟡 问题3:FreqAI 列名备选逻辑可能永远不匹配**
|
||||
**位置:** 第 800-803、869-871、912-913 行
|
||||
```python
|
||||
# entry_signal 备选列名
|
||||
elif '&-entry_signal_prob' in df.columns: # 这个格式不正确
|
||||
elif '&-s-entry_signal_prob' in df.columns: # 这个格式也不正确
|
||||
|
||||
# exit_signal 备选列名
|
||||
elif '&-s-exit_signal_prob' in df.columns: # 格式不正确
|
||||
|
||||
# future_volatility 备选列名
|
||||
elif '&-future_volatility' in df.columns: # 格式不正确
|
||||
```
|
||||
**问题:** 这些备选列名格式与 FreqAI 实际输出的格式不匹配,会永远不被使用。FreqAI 输出的列名是 `&s-xxx`(训练目标)而不是 `&-xxx-prob`
|
||||
|
||||
---
|
||||
|
||||
### **🟡 问题4:trailing_stop 参数配置不完整**
|
||||
**位置:** 第 27-29 行
|
||||
```python
|
||||
stoploss = -0.15 # 固定止损 -15%
|
||||
trailing_stop = True
|
||||
trailing_stop_positive_offset = 0.005
|
||||
# 缺少 trailing_stop_positive 定义!
|
||||
```
|
||||
**问题:**
|
||||
- 定义了 `trailing_stop = True` 和 `trailing_stop_positive_offset`
|
||||
- 但 `trailing_stop_positive` 值只在 `@property` 中动态计算(第 220-229 行)
|
||||
- 如果 `_dataframe_cache` 为 None,会使用 `_trailing_stop_positive_default = 0.004`
|
||||
- 但类级别没有明确定义 `trailing_stop_positive = xxx`,可能导致 freqtrade 初始化时行为不确定
|
||||
|
||||
---
|
||||
|
||||
### **🟢 问题5:custom_entry_price / custom_exit_price 方法缺失**
|
||||
**位置:** 不存在
|
||||
**问题:**
|
||||
- 没有定义 `custom_entry_price` 和 `custom_exit_price` 方法
|
||||
- 当前入场价格是在 `populate_entry_trend` 中通过设置 `enter_price` 列实现的(第 666 行)
|
||||
- 这种方式**仅在回测中生效,实盘中不生效**
|
||||
- 根据记忆,之前已经发现 "live模式下价格调整策略未生效" 的问题
|
||||
|
||||
---
|
||||
|
||||
### **🟢 问题6:freqai_entry_up_percent / freqai_exit_down_percent 范围不一致**
|
||||
**位置:** 第 271-274 行 vs 之前的讨论
|
||||
```python
|
||||
freqai_entry_up_percent = DecimalParameter(0.3, 2.0, ...)
|
||||
freqai_exit_down_percent = DecimalParameter(0.3, 2.0, ...)
|
||||
```
|
||||
**问题:** 之前讨论过将范围改为 0.5-2.0% 匹配 72 分钟预测窗口,但当前代码仍是 0.3-2.0%
|
||||
|
||||
---
|
||||
|
||||
需要我逐个修复这些问题吗w
|
||||
@ -2,6 +2,7 @@ import warnings
|
||||
warnings.filterwarnings("ignore", category=UserWarning, module="pandas_ta")
|
||||
|
||||
import logging
|
||||
from typing import Optional
|
||||
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
|
||||
from pandas import DataFrame
|
||||
import pandas as pd
|
||||
@ -24,9 +25,11 @@ class FreqaiPrimer(IStrategy):
|
||||
# FreqAI 要求
|
||||
process_only_new_candles = True
|
||||
|
||||
stoploss = -0.15 # 固定止损 -15% (大幅放宽止损以承受更大波动)
|
||||
stoploss = -0.15 # 固定止损 -15%
|
||||
trailing_stop = True
|
||||
trailing_stop_positive_offset = 0.005 # 追踪止损偏移量 0.5% (更容易触发跟踪止盈)
|
||||
trailing_stop_positive = 0.004 # 跟踪止盈回调 0.4%
|
||||
trailing_stop_positive_offset = 0.005 # 追踪止损偏移量 0.5%
|
||||
trailing_only_offset_is_reached = True # 只有达到 offset 后才启用跟踪止盈
|
||||
|
||||
# 用于跟踪市场状态的数据框缓存
|
||||
_dataframe_cache = None
|
||||
@ -273,6 +276,10 @@ class FreqaiPrimer(IStrategy):
|
||||
# FreqAI 标签定义:exit_signal 的洛底下跌幅度(%)
|
||||
freqai_exit_down_percent = DecimalParameter(0.3, 2.0, decimals=2, default=0.5, optimize=True, load=True, space='buy')
|
||||
|
||||
# 入场/出场价格调整参数(实盘限价单)
|
||||
entry_price_discount = DecimalParameter(0.005, 0.025, decimals=3, default=0.0167, optimize=False, load=True, space='buy') # 入场下调比例,默认 1.67%
|
||||
exit_price_premium = DecimalParameter(0.005, 0.025, decimals=3, default=0.0167, optimize=False, load=True, space='sell') # 出场上调比例,默认 1.67%
|
||||
|
||||
# 定义可优化参数
|
||||
# 初始入场金额: 75.00
|
||||
|
||||
@ -330,7 +337,7 @@ class FreqaiPrimer(IStrategy):
|
||||
"""FreqAI 基础特征。"""
|
||||
dataframe["%-pct_change"] = dataframe["close"].pct_change().fillna(0)
|
||||
dataframe["%-raw_volume"] = dataframe["volume"].fillna(0)
|
||||
dataframe["%-raw_price"] = dataframe["close"].fillna(method="ffill")
|
||||
dataframe["%-raw_price"] = dataframe["close"].ffill()
|
||||
return dataframe
|
||||
|
||||
def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
|
||||
@ -661,9 +668,10 @@ class FreqaiPrimer(IStrategy):
|
||||
# 设置入场信号
|
||||
dataframe.loc[final_condition, 'enter_long'] = 1
|
||||
|
||||
# 设置入场价格:下调1.67%(使用乘法避免除零风险)
|
||||
# 设置入场价格:使用 hyperopt 参数调整下调比例
|
||||
final_condition_updated = dataframe['enter_long'] == 1
|
||||
dataframe.loc[final_condition_updated, 'enter_price'] = dataframe.loc[final_condition_updated, 'close'] * 0.9833
|
||||
discount_multiplier = 1.0 - self.entry_price_discount.value
|
||||
dataframe.loc[final_condition_updated, 'enter_price'] = dataframe.loc[final_condition_updated, 'close'] * discount_multiplier
|
||||
|
||||
# 增强调试信息
|
||||
#self.log_info(f"[{metadata['pair']}] 入场条件检查:")
|
||||
@ -794,20 +802,9 @@ class FreqaiPrimer(IStrategy):
|
||||
last_row = df.iloc[-1]
|
||||
entry_prob = None
|
||||
|
||||
# 优先使用 FreqAI 的 entry_signal 预测列
|
||||
# FreqAI 预测列名为 &s-entry_signal
|
||||
if '&s-entry_signal' in df.columns:
|
||||
entry_prob = float(last_row['&s-entry_signal'])
|
||||
elif '&-entry_signal_prob' in df.columns:
|
||||
entry_prob = float(last_row['&-entry_signal_prob'])
|
||||
elif '&-s-entry_signal_prob' in df.columns:
|
||||
entry_prob = float(last_row['&-s-entry_signal_prob'])
|
||||
elif '&-entry_signal' in df.columns:
|
||||
val = last_row['&-entry_signal']
|
||||
if isinstance(val, (int, float)):
|
||||
entry_prob = float(val)
|
||||
else:
|
||||
# 文本标签时,简单映射为 0/1
|
||||
entry_prob = 1.0 if str(val).lower() in ['entry', 'buy', '1'] else 0.0
|
||||
|
||||
if entry_prob is not None:
|
||||
# 确保概率在 [0, 1] 范围内(分类器输出可能有浮点误差)
|
||||
@ -824,11 +821,10 @@ class FreqaiPrimer(IStrategy):
|
||||
# 如果允许交易,更新最后一次入场时间并输出价格信息
|
||||
if allow_trade:
|
||||
self._last_entry_time[pair] = current_time
|
||||
# 计算实际入场价格下调比例(1.67%)
|
||||
# rate 是当前市场价格,enter_price = rate * 0.9833
|
||||
price_discount_percent = 1.67
|
||||
adjusted_entry_price = rate * 0.9833
|
||||
self.log_info(f"[{pair}] 允许入场 - 市场价: {rate:.8f}, 调整后入场价: {adjusted_entry_price:.8f}, 下调: {price_discount_percent}%")
|
||||
# 使用 hyperopt 参数计算实际入场价格
|
||||
discount_multiplier = 1.0 - self.entry_price_discount.value
|
||||
adjusted_entry_price = rate * discount_multiplier
|
||||
self.log_info(f"[{pair}] 允许入场 - 市场价: {rate:.8f}, 调整后入场价: {adjusted_entry_price:.8f}, 下调: {self.entry_price_discount.value:.2%}")
|
||||
|
||||
# 如果没有阻止因素,允许交易
|
||||
return allow_trade
|
||||
@ -863,20 +859,9 @@ class FreqaiPrimer(IStrategy):
|
||||
last_row = df.iloc[-1]
|
||||
exit_prob = None
|
||||
|
||||
# 优先使用 FreqAI 的 exit_signal 预测列
|
||||
# FreqAI 预测列名为 &s-exit_signal
|
||||
if '&s-exit_signal' in df.columns:
|
||||
exit_prob = float(last_row['&s-exit_signal'])
|
||||
elif '&-exit_signal_prob' in df.columns:
|
||||
exit_prob = float(last_row['&-exit_signal_prob'])
|
||||
elif '&-s-exit_signal_prob' in df.columns:
|
||||
exit_prob = float(last_row['&-s-exit_signal_prob'])
|
||||
elif '&-exit_signal' in df.columns:
|
||||
val = last_row['&-exit_signal']
|
||||
if isinstance(val, (int, float)):
|
||||
exit_prob = float(val)
|
||||
else:
|
||||
# 文本标签时,简单映射为 0/1
|
||||
exit_prob = 1.0 if str(val).lower() in ['exit', 'sell', '1'] else 0.0
|
||||
|
||||
if exit_prob is not None:
|
||||
# 确保概率在 [0, 1] 范围内(分类器输出可能有浮点误差)
|
||||
@ -905,12 +890,10 @@ class FreqaiPrimer(IStrategy):
|
||||
if current_profit <= 0.02:
|
||||
dynamic_threshold *= 0.8
|
||||
|
||||
# 新增:读取 AI 预测的未来波动率信号(极端化方案)
|
||||
# 读取 AI 预测的未来波动率信号
|
||||
future_vol_signal = None
|
||||
if '&s-future_volatility' in df.columns:
|
||||
future_vol_signal = float(last_row['&s-future_volatility'])
|
||||
elif '&-future_volatility' in df.columns:
|
||||
future_vol_signal = float(last_row['&-future_volatility'])
|
||||
|
||||
# 极端化逻辑:根据 AI 预测的未来波动率直接接管部分出场决策
|
||||
if future_vol_signal is not None and exit_reason == 'exit_signal':
|
||||
@ -1102,3 +1085,22 @@ class FreqaiPrimer(IStrategy):
|
||||
|
||||
return adjusted_stake
|
||||
|
||||
def custom_entry_price(self, pair: str, trade: Optional['Trade'], current_time: datetime,
|
||||
proposed_rate: float, entry_tag: Optional[str], side: str,
|
||||
**kwargs) -> float:
|
||||
"""
|
||||
实盘入场价格调整:使用 hyperopt 参数动态调整降价百分比
|
||||
"""
|
||||
discount_multiplier = 1.0 - self.entry_price_discount.value
|
||||
adjusted_price = proposed_rate * discount_multiplier
|
||||
return adjusted_price
|
||||
|
||||
def custom_exit_price(self, pair: str, trade: 'Trade', current_time: datetime,
|
||||
proposed_rate: float, exit_tag: Optional[str], side: str,
|
||||
**kwargs) -> float:
|
||||
"""
|
||||
实盘出场价格调整:使用 hyperopt 参数动态调整加价百分比
|
||||
"""
|
||||
premium_multiplier = 1.0 + self.exit_price_premium.value
|
||||
adjusted_price = proposed_rate * premium_multiplier
|
||||
return adjusted_price
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user