第 8 章 · 05 强化学习交易


文档摘要

第 8 章 · 05 强化学习交易 本节摘要:强化学习(RL)是 FreqAI 里最强大也最复杂的范式。与回归/分类「给标签让模型学」不同,RL 让一个智能体(agent)在模拟交易环境里自己试错,靠奖励函数学会何时开仓、持有、平仓。本节讲清 RL 的基本概念(agent 与 environment)、三种动作空间环境(Base3/4/5ActionRLEnv)、奖励函数 的设计要点、与 Stable-Baselines3 的集成,以及 RL 特有的状态信息(state info)机制。RL 的门槛高于回归/分类,但它能学到回调难以表达的交易策略。 内容来源:原项目文档 ,源码 ,汉化并套用体系化模板。

第 8 章 · 05 强化学习交易

本节摘要:强化学习(RL)是 FreqAI 里最强大也最复杂的范式。与回归/分类「给标签让模型学」不同,RL 让一个智能体(agent)在模拟交易环境里自己试错,靠奖励函数学会何时开仓、持有、平仓。本节讲清 RL 的基本概念(agent 与 environment)、三种动作空间环境(Base3/4/5ActionRLEnv)、奖励函数 calculate_reward 的设计要点、与 Stable-Baselines3 的集成,以及 RL 特有的状态信息(state info)机制。RL 的门槛高于回归/分类,但它能学到回调难以表达的交易策略。

内容来源:原项目文档 docs/freqai-reinforcement-learning.md,源码 freqtrade/freqai/RL/,汉化并套用体系化模板。

⚠️ 风险提示:RL 智能体可能学到「欺骗」奖励函数的「取巧」行为,在不真正盈利的情况下拿高分。默认的奖励函数是功能展示,不是为实盘设计的。你必须自写奖励函数或用社区验证的方案,且充分 Dry-Run。

学习目标

阅读完本节,你应当能够:

  1. 解释 agentenvironment 的关系。
  2. 区分 Base3/4/5ActionRLEnv 三种动作空间。
  3. 理解 奖励函数 calculate_reward 的设计原则。
  4. 配置 rl_config 块和 Stable-Baselines3 模型。
  5. 说明 add_state_info 的作用与限制。

一、RL 基本概念:agent 在环境里试错

强化学习的两个主角:

  • Agent(智能体):做决策的角色,每一步从动作空间里选一个动作。
  • Environment(环境):模拟的交易世界,agent 在里面按 K 线一根根走,环境根据动作给奖励或惩罚。

训练循环如下:

与回归/分类的根本区别:RL 不需要标签——没有「正确答案是涨 2%」这种监督信号。取而代之的是奖励函数:你告诉 agent「赚钱奖励、亏钱惩罚、持仓太久扣分」,它自己摸索出能拿高分的交易策略。

💡 为什么 FreqAI + freqtrade 是 RL 的好搭档:RL 训练时能用「状态信息」(当前持仓、当前盈亏、持仓时长)来强化 agent。这些信息在 freqtrade 实盘里随手可得,而在纯研究框架里很难实时获取。FreqAI 把这套机制打通了。

二、三种动作空间环境

FreqAI 提供三个预制环境,区别在于 agent 能选几个动作:

环境 动作数 动作内容 适用
Base3ActionRLEnv 3 持有 / 做多 / 做空 最简单,也支持只做多(can_short=False)
Base4ActionRLEnv 4 做多 / 做空 / 持有中性 / 平仓 单独平仓动作
Base5ActionRLEnv 5 中性 / 多开 / 多平 / 空开 / 空平 最精细,多空各自独立平仓

以 Base5ActionRLEnv 为例,动作枚举:

class Actions(Enum): Neutral = 0 # 持有中性(空仓观望) Long_enter = 1 # 开多 Long_exit = 2 # 平多 Short_enter = 3 # 开空 Short_exit = 4 # 平空

策略里直接拿 agent 输出的 &-action 整数做入场/出场:

def populate_entry_trend(self, df, metadata): enter_long_conditions = [df["do_predict"] == 1, df["&-action"] == 1] df.loc[reduce(lambda x, y: x & y, enter_long_conditions), ["enter_long", "enter_tag"]] = (1, "long") enter_short_conditions = [df["do_predict"] == 1, df["&-action"] == 3] df.loc[reduce(lambda x, y: x & y, enter_short_conditions), ["enter_short", "enter_tag"]] = (1, "short") return df def populate_exit_trend(self, df, metadata): df.loc[(df["do_predict"]==1) & (df["&-action"]==2), "exit_long"] = 1 # 平多 df.loc[(df["do_predict"]==1) & (df["&-action"]==4), "exit_short"] = 1 # 平空 return df

⚠️ 只做多的场景:只有 Base3ActionRLEnv 支持 can_short = False(把做多当入场、做空当出场)。Base4/Base5 默认需要能做空。

三、RL 策略的特殊写法

RL 策略的特征工程和回归一样,但标签不同——RL 不需要标签,set_freqai_targets 里只填一个中性的 &-action 占位:

def set_freqai_targets(self, dataframe, **kwargs): # RL 没有标签,这是占位,agent 会覆盖它 dataframe["&-action"] = 0 return dataframe

另外,RL 的训练环境需要原始 OHLCV 来驱动行情,所以必须在 feature_engineering_standard 里把原始价格传进去:

def feature_engineering_standard(self, dataframe, **kwargs): # RL 训练环境必需的原始价格 dataframe["%-raw_close"] = dataframe["close"] dataframe["%-raw_open"] = dataframe["open"] dataframe["%-raw_high"] = dataframe["high"] dataframe["%-raw_low"] = dataframe["low"] return dataframe

💡 这意味着 RL 策略的 feature_engineering_standard 要同时承担两个职责:给模型喂特征 + 给环境喂原始价格。别忘了 raw 系列。

四、奖励函数:RL 的灵魂

calculate_reward 决定 agent 学成什么样。这是 RL 最需要创造力、也最容易出问题的地方。内置的默认奖励函数(在 ReinforcementLearner.py 里)是功能展示,不是生产代码——它会故意展示很多环境控制特性,但不保证盈利。

奖励函数的核心原则:

  1. 连续可微分为佳:加一个大的负惩罚到罕见事件上,神经网络学不动。不如给常见事件加小的负惩罚。
  2. 随严重程度缩放:持仓越久惩罚越大(线性或指数),比「到点一次性重罚」更好学。
  3. 奖励要平衡:鼓励入场但不鼓励乱入场;鼓励盈利但不鼓励死扛。

一个自定义奖励函数的骨架(继承 Base5ActionRLEnv):

from freqtrade.freqai.prediction_models.ReinforcementLearner import ReinforcementLearner from freqtrade.freqai.RL.Base5ActionRLEnv import Actions, Base5ActionRLEnv, Positions class MyCoolRLModel(ReinforcementLearner): class MyRLEnv(Base5ActionRLEnv): def calculate_reward(self, action: int) -> float: if not self._is_valid(action): return -2 # 无效动作重罚 pnl = self.get_unrealized_profit() factor = 100 # 鼓励入场(RSI 低时更鼓励) if action in (Actions.Long_enter.value, Actions.Short_enter.value) \ and self._position == Positions.Neutral: return 25 # 不鼓励一直空仓 if action == Actions.Neutral.value and self._position == Positions.Neutral: return -1 # 持仓太久递增惩罚 trade_duration = self._current_tick - self._last_trade_tick max_trade_duration = self.rl_config.get('max_trade_duration_candles', 300) if self._position in (Positions.Short, Positions.Long) \ and action == Actions.Neutral.value: return -1 * trade_duration / max_trade_duration # 平仓时按盈亏给奖 if action == Actions.Long_exit.value and self._position == Positions.Long: return float(pnl * factor) if action == Actions.Short_exit.value and self._position == Positions.Short: return float(pnl * factor) return 0.

你可以从 self.raw_features 读取特征值来设计更聪明的奖励:

rsi_now = self.raw_features[f"%-rsi-period_10_shift-1_{pair}_{self.config['timeframe']}"].iloc[self._current_tick] if rsi_now < 40: factor = 40 / rsi_now # RSI 越低越鼓励入场

⚠️ 环境不是真实回测:RL 训练环境是高度简化的,不含 custom_exitcustom_stoploss、杠杆控制等复杂策略逻辑。它是一个「原始市场」,agent 靠奖励函数自学止盈止损。所以 agent 在环境里的表现 ≠ 真实回测表现,两者都要验证。

五、rl_config 配置块

RL 的专属配置在 freqai.rl_config:

"rl_config": { "train_cycles": 25, "add_state_info": true, "max_trade_duration_candles": 300, "max_training_drawdown_pct": 0.02, "cpu_count": 8, "model_type": "PPO", "policy_type": "MlpPolicy", "model_reward_parameters": { "rr": 1, "profit_aim": 0.025 } }

关键参数:

参数 含义
train_cycles agent 在环境里循环训练多少轮(乘以数据点数)
model_type Stable-Baselines3 的算法:PPOA2CDQNTRPOARSRecurrentPPOMaskablePPO
policy_type 策略网络结构,默认 MlpPolicy
net_arch 网络架构,默认 [128, 128](两个 128 单位共享隐层)
max_trade_duration_candles 引导 agent 别持仓超过这个长度(在奖励函数里用)
max_training_drawdown_pct 训练中允许的最大回撤,超过就重置环境
add_state_info 把持仓时长、当前盈亏、持仓方向加入特征(只 dry/live,回测自动关)
cpu_count RL 训练线程数
randomize_starting_position 随机化 episode 起点防过拟合
drop_ohlc_from_features 不把归一化 OHLC 传给 agent(OHLC 仍驱动环境)

💡 持续学习:RL 特别适合开 continual_learning: true——新模型从上一个模型继续训练,而不是每次从零开始。这能让 agent 累积经验。

六、监控与自定义日志

RL 受益于训练指标追踪。FreqAI 集成了 Tensorboard:

tensorboard --logdir user_data/models/unique-id # 浏览器访问 127.0.0.1:6006

环境内置了 self.tensorboard_log(),每个 step 自动记录 agent 动作分布。你也可以在 calculate_reward 里加自定义计数:

def calculate_reward(self, action: int) -> float: if not self._is_valid(action): self.tensorboard_log("invalid") # 计数无效动作次数 return -2

如果是浮点指标,传第二个参数:self.tensorboard_log("float_metric", 0.23)

本节要点回顾

  1. RL 双主角:Agent 在 environment 里按 K 线试错,靠奖励函数自学交易策略;不需要标签。
  2. 三种环境:Base3(最简,支持只做多)、Base4(单独平仓)、Base5(多空独立平仓,最精细)。
  3. 策略写法:set_freqai_targets&-action=0 占位;feature_engineering_standard 必须传 raw OHLCV 驱动环境。
  4. 奖励函数是灵魂:连续可微、随严重度缩放、平衡入场与持仓;默认奖励函数非生产级,必须自写。
  5. rl_config:train_cyclesmodel_type(PPO 等)、max_training_drawdown_pctadd_state_info(只 dry/live)。
  6. 环境≠真实回测:RL 训练环境是简化的,不含复杂回调;agent 学的是奖励驱动下的策略,实盘表现要单独验证。

下一节,我们看自定义模型开发——怎么继承 BaseRegressionModel/BaseClassifierModel,实现 fit/train/predict,注册到 user_data/freqaimodels/--freqaimodel 找到它。


发布者: 作者: 灏天文库 转发
评论区 (0)
U