海底暴风雪

富在术数不在劳身,利在局势不在力耕

freqai 强化学习基础学习

普通现货交易的简单强化学习配置

配置文件

强化学习的配置需要在基础的配置上添加freqai的配置,并在freqai配置内添加RL配置

// freqai的配置,freqai大致分为两种,
// 一种是普通ai,这种AI还是要进行特征值的提取,也就是使用talib库提取一些交易的特征值,然后给到数据帧,
// 另一种是强化学习ai,这种ai要提前配置好行动的空间,也就是所能进行的操作,以及编写合适的激励函数,同时也需要进行特诊的选取,但是也可以使用基础特征
"freqai": {
    // 启用feqai,如果有配置,但是不启用也不会运行
    "enabled": true,
    // 保留旧模型数量,这里是2个,为0不会删除旧模型
    "purge_old_models": 2,
    // 训练数据时长
    "train_period_days": 15,
    // 回测数据时长
    "backtest_period_days": 7,
    // 参数指定在“实时”模式下模型应该多久重新训练一次。值为0可能意味着不在实时运行模式下自动重新训练模型。
    "live_retrain_hours": 0,
    // 模型标识,可以在不同的配置文件配置,但是如果不同的配置文件配置相同的配置,可能会冲突
    "identifier": "unique-id",
    "feature_parameters": {
        // 这个字段定义了数据采集的时间框架。在这个例子中,它包括"3m"(3分钟),"15m"(15分钟),和"1h"(1小时)。这意味着系统将从这三个不同的时间段获取数据,可能用于分析或预测目的。
        "include_timeframes": [
            "3m",
            "15m",
            "1h"
        ],
        // 这个字段是用于指定交易对的列表。例如,"BTC/USDT:USDT"可能表示比特币(BTC)对美元稳定币(USDT)的交易对,且这个配置可能是用来指定用于相关性分析的货币对。这种设置有助于定位哪些货币对之间的动态需要分析。
        "include_corr_pairlist": [
            "BTC/USDT:USDT",
            "ETH/USDT:USDT"
        ],
        // 这个字段表示用于标记或训练模型的蜡烛图(K线图)的数量。在这里的20可能意味着每个数据点或“标签”代表连续20个蜡烛图的时间段。
        "label_period_candles": 20,
        // 这个配置项表示在分析中包括移位的蜡烛图的数量。在这里的2可能意味着除了当前的蜡烛图外,系统还会考虑前两个(或其他数量的)蜡烛图,这有助于分析趋势和模式。
        "include_shifted_candles": 2,
        // 这是一个与趋势强度指标(Directional Indicator,DI)有关的阈值。0.9的值可能表示只有当DI指标高于0.9时,某些操作或判断才会被触发。这通常用于识别市场趋势的强度。
        "DI_threshold": 0.9,
        // 这个值(在这里是0.9)用于平衡或调整某些计算中的权重。它可能与数据点的重要性或某些特征的影响力有关,用于影响模型的决策或输出
        "weight_factor": 0.9,
        // 表示是否应用主成分分析(PCA)。PCA是一种统计技术,用于减少数据集的维度,同时保留大部分变异性。
        "principal_component_analysis": false,
        // 这个配置项指的是使用支持向量机(Support Vector Machine, SVM)来移除异常值。在这里,true表明将启用SVM算法来识别并可能排除那些被视为异常的数据点。在金融市场数据分析中,异常值可能是由于市场噪音或不寻常的市场事件造成的,这些异常值如果不处理可能会扭曲模型的预测或分析结果。
        "use_SVM_to_remove_outliers": true,
        // 这个配置项是一个数组,包含数值10和20,这些数值可能代表用于计算某些技术指标的蜡烛图(K线图)周期的长度。在技术分析中,指标(如移动平均线、相对强弱指数RSI等)通常基于一定数量的历史数据点计算得出。在这种情况下,10和20可能指的是分别使用10个和20个蜡烛图数据点来计算这些指标。这有助于捕捉到不同时间范围内的市场动态。
        "indicator_periods_candles": [
            10,
            20
        ],
        // 这可能是一个布尔值或数字,用于指示是否应该生成和展示特征重要性的图表。特征重要性图表可以帮助理解哪些输入特征对模型预测影响最大。
        "plot_feature_importances": 0
    },
    "data_split_parameters": {
        // 这个参数定义了用于测试模型的数据集的大小比例。例如,0.33意味着33%的数据将用于测试,其余的用于训练模型。
        "test_size": 0.33,
        // 这通常是一个整数,用于确保数据分割的可重复性。指定一个特定的数值可以确保每次运行配置时,数据的分割方式都是相同的。
        "random_state": 1
    },
    // 这个字段目前为空,可能用于指定模型训练过程中的各种参数,如学习率、迭代次数、正则化参数等。由于它是空的,模型训练可能使用默认的参数设置。
    "model_training_parameters": {},
    "rl_config": {
        // 这个参数指定了训练周期的数量。在这种情况下,25可能意味着模型将经历25个完整的训练周期,每个周期包括多次尝试和学习以优化其性能。
        "train_cycles": 25,
        // 这个参数设置为true表示在训练过程中,将会向模型添加额外的状态信息。这可能意味着除了基本的输入数据之外,还会包括一些额外的上下文或环境信息,以帮助模型更好地理解和学习。
        "add_state_info": true,
        // 这个参数设定了交易的最大持续时间,以蜡烛图(K线图)的数量来计算。在这里,300可能意味着每个交易最多持续300个蜡烛图的时间。这有助于限制交易的时间范围,避免长时间持有可能导致风险的交易。
        "max_trade_duration_candles": 300,
        // 这个参数设置了训练过程中允许的最大回撤百分比。0.02表示允许的最大回撤是资本的2%。这是一种风险管理措施,旨在防止模型在训练过程中承担过多的风险。
        "max_training_drawdown_pct": 0.02,
        // 这个参数设置了用于训练模型的CPU核心数量。8表示将使用8个CPU核心。这与模型训练的计算效率有关。
        "cpu_count": 8,
        // 这里指定了强化学习模型的类型,PPO代表Proximal Policy Optimization,这是一种流行的强化学习算法,适用于处理复杂的环境和大量的状态空间。
        "model_type": "PPO",
        // MlpPolicy指的是多层感知器策略,这是一种基于神经网络的策略,用于在强化学习中做出决策。多层感知器是一种常见的神经网络结构,适用于处理各种问题。
        "policy_type": "MlpPolicy",

        "model_reward_parameters": {
            // 这个参数的具体含义可能依赖于上下文,但一般来说,它可能代表奖励比率或类似的指标,用于调整模型在学习过程中对不同结果的奖励
            "rr": 1,
            // 这个参数设定了模型在交易中的目标利润率。0.025表示目标是实现2.5%的利润。
            "profit_aim": 0.025
        }
    }
},

策略文件

强化学习的策略文件是在普通策略文件上拓展来的。主要是新增几个freqai取特征数据的方法。

以下文件是在普通的策略文件基础上进行更改的

# 通常指的是在策略或机器人开始正常运行之前需要初始化或加载的蜡烛图(K线图)的数量。蜡烛图是金融交易中用于表示价格变动的一种图表,显示了在特定时间段内的开盘价、收盘价、最高价和最低价。
    startup_candle_count: int = 20

    # 填充指标
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # 运行freqai需要在填充指标时运行
        dataframe = self.freqai.start(dataframe, metadata, self)

        return dataframe

    # 这个参数通常与特征工程相关。特征工程是机器学习和数据科学中的一个重要环节,涉及从原始数据中提取、选择和转换特征,以便更好地适应模型和提高模型性能。
    def feature_engineering_expand_all(self, dataframe: DataFrame, period, **kwargs) -> DataFrame:

        # 其中的特征参数key必须以%号开始,就是一下格式
        dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
        dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
        dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
        dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
        dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)

        return dataframe

    # 基础特征
    #  这个配置项可能指的是执行基础级别的特征工程操作。在数据科学和机器学习中,特征工程包括从原始数据中提取有用的信息以及转换数据以便更好地适应模型。"基础"可能意味着进行一些常见和简单的操作,如计算一些基本统计量(如均值、标准差)、简单的数据转换(如对数转换)、处理缺失值等。
    def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs) -> DataFrame:
        # 特征数据key的格式也是要以%开始,在freqai Rl中,必须要填充几个基本数据,
        # 几个基本数据,后续添加
        dataframe["%-pct-change"] = dataframe["close"].pct_change()
        dataframe["%-raw_volume"] = dataframe["volume"]
        dataframe["%-raw_price"] = dataframe["close"]
        return dataframe

    # 这可能指一种标准化的特征工程过程,可能包括对数据进行规范化或标准化处理。例如,将所有数值特征缩放到相同的范围或分布,使得模型更容易处理。这是许多机器学习模型所需的一个重要步骤,特别是对于那些对输入特征的尺度敏感的模型。
    def feature_engineering_standard(self, dataframe: DataFrame, **kwargs) -> DataFrame:
        
        dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
        dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25


        # 在强化学习中,必须在这个函数中添加下面几项, 其余的feature_engineering_*中大的技术指标都可以不要
        dataframe["%-raw_close"] = dataframe["close"]
        dataframe["%-raw_open"] = dataframe["open"]
        dataframe["%-raw_high"] = dataframe["high"]
        dataframe["%-raw_low"] = dataframe["low"]
        return dataframe

    # 这个配置项可能涉及设置特定的目标或标签,用于freqai(可能是频率分析或某种AI模型的简称)的训练。在机器学习中,"目标"通常指模型需要预测的变量。例如,在股票市场的预测模型中,目标可能是未来的价格变动或股票的买卖信号。这个设置可能涉及定义这些目标的特定参数或标准,如预测的时间范围、所需的准确率等。
    def set_freqai_targets(self, dataframe: DataFrame, **kwargs) -> DataFrame:
        # 在freqai RL中,不需要设置targets,但是依然需要添加这个函数
       
        dataframe["&-s_close"] = (
            dataframe["close"]
            .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
            .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
            .mean()
            / dataframe["close"]
            - 1
            )
        return dataframe

freqaimodel文件

在基础的frreqai中,可以使用官方的model,其中提供了预测器和分类器。但是在freqai RL中则需要重新编写freqaiRL的 action空间与奖励函数等

在5Action的基础上有gpt辅助编写的奖励函数
myfreqaimodel.py

import numpy as np
from freqtrade.freqai.prediction_models.ReinforcementLearner import ReinforcementLearner
from freqtrade.freqai.RL.Base5ActionRLEnv import Actions, Base5ActionRLEnv, Positions
import numpy as np
class MyActionRLEnv(ReinforcementLearner):
    # 继承了Base5ActionRLEnv
    class MyRLEnv(Base5ActionRLEnv):
        def calculate_reward(self, action: int) -> float:
            # 基础判断:如果行动无效,则给予惩罚
            if not self._is_valid(action):
                return -2

            # 获取未实现盈亏
            pnl = self.get_unrealized_profit()

            # 使用对数函数调整因子
            factor = np.log(100 + abs(pnl)) if pnl != 0 else 0
            factor *= np.sign(pnl)

            # 进入交易的奖励机制
            if action in (Actions.Long_enter.value, Actions.Short_enter.value) and self._position == Positions.Neutral:
                return 25 * factor

            # 不进入交易的惩罚
            if action == Actions.Neutral.value and self._position == Positions.Neutral:
                return -1

            # 交易持续时间奖励/惩罚的非线性调整
            max_trade_duration = self.rl_config.get('max_trade_duration_candles', 300)
            trade_duration = self._current_tick - self._last_trade_tick
            if trade_duration <= max_trade_duration:
                duration_factor = 1.5
            else:
                # 指数衰减
                duration_factor = 0.5 * np.exp(-(trade_duration - max_trade_duration) / 50)

            # 保持交易状态的惩罚
            if self._position in (Positions.Short, Positions.Long) and action == Actions.Neutral.value:
                return -1 * trade_duration / max_trade_duration * duration_factor

            # 关闭长/短仓位的奖励
            if action in (Actions.Long_exit.value, Actions.Short_exit.value) and \
            (self._position == Positions.Long or self._position == Positions.Short):
                if pnl > self.profit_aim * self.rr:
                    win_reward_factor = self.rl_config['model_reward_parameters'].get('win_reward_factor', 2)
                    factor *= win_reward_factor
                return pnl * factor

            return 0.

        # ... 其他部分保持不变 ...

搜索

文章分类