myTestFreqAI/temp_model_content.py
2026-02-18 02:21:36 +08:00

150 lines
7.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from freqtrade.freqai.prediction_models.ReinforcementLearner import ReinforcementLearner
from freqtrade.freqai.RL.Base5ActionRLEnv import Actions, Base5ActionRLEnv, Positions
import numpy as np
class MyCoolRLModel(ReinforcementLearner):
"""
用户创建的RL预测模型。
保存此文件到 `freqtrade/user_data/freqaimodels`
然后使用以下命令运行:
freqtrade trade --freqaimodel MyCoolRLModel --config config.json --strategy FreqaiPrimer
在这里,用户可以覆盖 `IFreqaiModel` 继承树中的任何函数。
对于RL来说最重要的是在这里覆盖 `MyRLEnv`,以定义自定义的
`calculate_reward()` 函数,或覆盖环境的任何其他部分。
此类还允许用户覆盖 IFreqaiModel 树中的任何其他部分。
例如,用户可以覆盖 `def fit()` 或 `def train()` 或 `def predict()`
以对这些过程进行精细控制。
另一个常见的覆盖可能是 `def data_cleaning_predict()`,用户可以
在这里对数据处理管道进行精细控制。
"""
class MyRLEnv(Base5ActionRLEnv):
"""
用户自定义环境。此类继承自 BaseEnvironment 和 gym.Env。
用户可以覆盖这些父类中的任何函数。下面是一个
用户自定义 `calculate_reward()` 函数的示例。
警告!
此函数是功能展示,旨在展示尽可能多的
环境控制功能。它还设计用于在小型计算机上快速运行。
这是一个基准,*不* 用于生产环境。
"""
def calculate_reward(self, action: int) -> float:
"""
奖励函数的示例。这是用户可能希望
注入自己创意的一个函数。
警告!
此函数是功能展示,旨在展示尽可能多的
环境控制功能。它还设计用于在小型计算机上快速运行。
这是一个基准,*不* 用于生产环境。
:param action: int = 智能体为当前K线做出的动作。
:return:
float = 给智能体当前步骤的奖励(用于优化
神经网络中的权重)
"""
# 首先,如果动作无效,则惩罚
if not self._is_valid(action):
self.tensorboard_log("invalid", category="actions")
return -2.0
# 获取核心状态数据
pnl = self.get_unrealized_profit() # 当前浮动盈亏 (百分比,如 0.01 代表 1%)
# 获取持仓时间 (K线数量)
trade_duration = self._current_tick - self._last_trade_tick
# 读取配置中的最大持仓时间,默认 100 根 K 线
max_trade_duration = self.rl_config.get("max_trade_duration_candles", 100)
# 奖励累加器
reward = 0.0
# =========================================================
# 场景 A: 决定入场 (Long Enter / Short Enter)
# =========================================================
if action in (Actions.Long_enter.value, Actions.Short_enter.value):
if self._position == Positions.Neutral:
# 【核心修改 1】入场不给奖励反而给微小的惩罚。
# 逻辑:开仓即产生手续费和滑点风险。
# 这迫使模型只有在预期收益远大于这个惩罚时才敢开仓。
return -0.05
# =========================================================
# 场景 B: 观望 (Neutral)
# =========================================================
if action == Actions.Neutral.value and self._position == Positions.Neutral:
# 【核心修改 2】空仓观望给 0 分,或者极小的惩罚。
# 之前的代码给 -1 分会导致模型为了避免扣分而强行开单Overtrading
# 对于 PEPE 这种币,大部分时间是垃圾时间,观望是正确的。
return 0.0
# =========================================================
# 场景 C: 持仓中 (Holding) - 每一根 K 线都会触发
# =========================================================
if self._position in (Positions.Short, Positions.Long):
# 如果当前动作是继续持有 (Neutral)
if action == Actions.Neutral.value:
# 1. 时间衰减惩罚:拿得越久,资金占用成本越高
time_penalty = -0.01 * (trade_duration / max_trade_duration)
reward += time_penalty
# 2. 浮动盈亏反馈 (关键!)
if pnl > 0:
# 浮盈:给予微弱的正反馈,鼓励拿住趋势
# 使用 log 函数让奖励增长平缓,避免模型过于贪婪而不止盈
reward += np.log(1 + pnl) * 0.5
else:
# 浮亏:给予沉重的打击!
# 逻辑:浮亏不仅是钱的损失,更是机会成本。
# pnl 是负数,这里会让 reward 变得很小。
# 例如 pnl -0.02, 惩罚会显著大于浮盈 0.02 的奖励
reward -= (abs(pnl) * 2.0)
# 3. 止损惩罚加速
# 如果浮亏超过 3%,给予额外的巨额惩罚,逼迫模型学会止损
if pnl < -0.03:
reward -= 1.0
# =========================================================
# 场景 D: 离场结算 (Exit)
# =========================================================
if (action == Actions.Long_exit.value and self._position == Positions.Long) or \
(action == Actions.Short_exit.value and self._position == Positions.Short):
# 基础因子
factor = 10.0
# 【核心修改 3】非线性结算奖励
if pnl > 0:
# 盈利:奖励 = PnL * 因子
# 如果这笔交易是大赚 (比如 > 2%),因子翻倍
if pnl > 0.02:
factor *= 2.0
# 最终奖励
total_reward = pnl * factor
# 额外奖励:如果这笔交易很快就赚了钱(高效率)
if trade_duration < (max_trade_duration * 0.2):
total_reward *= 1.5
return float(total_reward)
else:
# 亏损:惩罚 = PnL * 因子
# 亏损时的惩罚系数通常要比盈利系数大,模拟"损失厌恶"
# 这会让模型非常忌惮亏损离场
loss_factor = 15.0
return float(pnl * loss_factor)
return float(reward)