(13-3-01)DDPG算法综合实战:基于强化学习的股票交易策略

13.3  DDPG算法综合实战:基于强化学习的股票交易策略

传统的股票交易策略通常依赖于技术分析、基本面分析和人工决策,在本节的内容中,将介绍一个综合实例,展示使用深度强化学习(DRL)方法来构建和测试一个自动化股票交易策略的过程。本项目通过引入深度强化学习,旨在自动化这一过程,从而提高交易效率并最大化投资回报。

实例13-3:深度强化学习股票交易策略(源码路径:daima\13\chatgpt-trading.ipynb

13.3.1  项目介绍

本项目旨在展示如何利用深度强化学习(DRL)方法构建和测试一个自动化股票交易策略,通过将股票交易过程建模为马尔可夫决策过程(MDP),将交易目标定义为一个最大化问题,并使用DRL算法来训练智能代理程序,使其能够在交易环境中进行决策。

本项目的关键功能和亮点如下:

  1. 数据获取:使用Yahoo Finance API获取单一股票的历史价格和成交量数据。
  2. 数据预处理:对获取的数据进行处理,包括添加技术指标和风险度量,以供DRL模型使用。
  3. 环境设计:创建交易环境,包括状态空间、行动空间和奖励函数,以模拟股票交易过程。
  4. DRL算法实施:使用A2C、PPO、DDPG等DRL算法,对智能代理程序进行训练和验证。
  5. 回测策略性能:通过回测工具评估不同算法的性能,包括夏普比率、年化回报率和最大回撤等指标。
  6. 与市场指数比较:将策略的性能与市场指数(如道琼斯工业平均指数)进行比较,以确定策略的相对表现。

本项目为有兴趣探索自动化股票交易策略的人提供了一个有用的实例,演示了如何使用深度强化学习来构建、训练和评估交易策略的过程。本项目突出了深度强化学习在金融领域的应用潜力,以及如何使用FinRL库简化开发和测试过程。通过这个项目,我们可以更好地理解如何优化股票交易策略,提高投资回报率,并降低风险。

13.3.2  准备开发环境

本项目用到了多个Python库,其中核心库是FinRL-Library。FinRL-Library(金融强化学习库)是一个用于金融市场数据分析和交易的开源 Python 库,它专注于应用强化学习方法来解决金融领域的问题,特别是股票和加密货币市场的自动化交易。

(1)在本地安装FinRL-Library,安装命令如下所示:

pip install git+https://github.com/AI4Finance-LLC/FinRL-Library.git

(2)通过如下命令安装wrds:

pip install wrds

(3)希望在安装时忽略任何警告信息。

import warnings
warnings.filterwarnings("ignore")

(4)导入一些必要的库和模块,用于实现金融市场的数据分析和交易操作。具体代码如下所示。

# 导入必要的库
import pandas as pd  # 用于数据处理
import numpy as np   # 用于数值计算
import matplotlib   # 用于绘图
import matplotlib.pyplot as plt  # 用于绘制图表
import datetime  # 用于日期和时间处理

# 魔术命令,将图表嵌入到Jupyter Notebook中
%matplotlib inline

# 导入一些自定义配置和模块
from finrl.config_tickers import DOW_30_TICKER  # 导入道琼斯30成分股的配置信息
from finrl.meta.preprocessor.yahoodownloader import YahooDownloader  # 导入Yahoo Finance数据下载器
from finrl.meta.preprocessor.preprocessors import FeatureEngineer, data_split  # 导入特征工程和数据拆分的模块
from finrl.meta.env_stock_trading.env_stocktrading import StockTradingEnv  # 导入股票交易环境
from finrl.agents.stablebaselines3.models import DRLAgent, DRLEnsembleAgent  # 导入强化学习代理模型
from finrl.plot import backtest_stats, backtest_plot, get_daily_return, get_baseline  # 导入绘图和回测统计相关的模块

# 导入pprint函数,用于美观地打印数据结构
from pprint import pprint

# 将自定义模块的路径添加到系统路径,以便正确导入它们
import sys
sys.path.append("../FinRL-Library")

(5)创建一个目录,用于保存训练后的强化学习模型,具体实现代码如下所示。

import os
from finrl.main import check_and_make_directories
from finrl.config import (
    DATA_SAVE_DIR,
    TRAINED_MODEL_DIR,
    TENSORBOARD_LOG_DIR,
    RESULTS_DIR,
    INDICATORS,
    TRAIN_START_DATE,
    TRAIN_END_DATE,
    TEST_START_DATE,
    TEST_END_DATE,
    TRADE_START_DATE,
    TRADE_END_DATE,
)

check_and_make_directories([DATA_SAVE_DIR, TRAINED_MODEL_DIR, TENSORBOARD_LOG_DIR, RESULTS_DIR])

上述代码的功能如下:

  1. 从finrl.main中导入函数check_and_make_directories。
  2. 从finrl.config中导入一系列常量和配置信息,包括数据保存目录、训练模型目录、TensorBoard日志目录、结果目录、指标、训练和测试日期范围等。
  3. 最后,调用函数check_and_make_directories,该函数用于检查并创建指定的目录,以确保在执行后续的操作时,这些目录存在。

13.3.3  下载数据

本项目所使用的股票数据来源于Yahoo Finance,这是一个提供股票数据、财经新闻、财报等信息的网站,里面的所有数据都是免费的。FinRL使用一个名为YahooDownloader的类来从Yahoo Finance API中获取数据。在使用公共API(无需身份验证)时,每个IP地址每小时限制为2,000次请求(或每天总共最多48,000次请求),具体说明如下所示:

class YahooDownloader:
    提供了从Yahoo Finance API中检索每日股票数据的方法

    属性
    ----------
        start_date : str
            数据的起始日期(从config.py中修改)
        end_date : str
            数据的结束日期(从config.py中修改)
        ticker_list : list
            股票代号列表(从config.py中修改)

    方法
    -------
    fetch_data()
        从Yahoo API获取数据

(1)通过如下代码打印输出道琼斯30成分股的配置信息:

print(DOW_30_TICKER)

执行后会输出:

['AXP', 'AMGN', 'AAPL', 'BA', 'CAT', 'CSCO', 'CVX', 'GS', 'HD', 'HON', 'IBM', 'INTC', 'JNJ', 'KO', 'JPM', 'MCD', 'MMM', 'MRK', 'MSFT', 'NKE', 'PG', 'TRV', 'UNH', 'CRM', 'VZ', 'V', 'WBA', 'WMT', 'DIS', 'DOW']

(2)设置指定的日期范围,然后使用类YahooDownloader从Yahoo Finance API下载这些范围内的指定股票的数据。具体实现代码如下所示。

TRAIN_START_DATE = '2009-04-01'
TRAIN_END_DATE = '2021-01-01'
TEST_START_DATE = '2021-01-01'
TEST_END_DATE = '2022-06-01'

df = YahooDownloader(start_date = TRAIN_START_DATE,
                     end_date = TEST_END_DATE,
                     ticker_list = DOW_30_TICKER).fetch_data()

在上述代码中,使用设置的日期范围和DOW_30_TICKER(道琼斯30成分股的配置信息)作为参数,调用了YahooDownloade中的方法fetch_data()来下载相应的股票数据。下载的数据将存储在DataFrame对象df中。执行后会输出:

[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
......
Shape of DataFrame:  (96942, 8)

注意:下载的数据将包括从训练开始日期到测试结束日期的股票价格和相关信息,以供后续的分析和交易模型训练使用。

(3)显示DataFrame df 的前几行数据,以便可以查看和了解下载的股票数据的格式和内容。具体实现代码如下所示。

df.head()

执行后会输出:

date open high low close volume tic day

0 2009-04-01 3.717500 3.892857 3.710357 3.308904 589372000 AAPL 2

1 2009-04-01 48.779999 48.930000 47.099998 36.228390 10850100 AMGN 2

2 2009-04-01 13.340000 14.640000 13.080000 11.732112 27701800 AXP 2

3 2009-04-01 34.520000 35.599998 34.209999 26.850748 9288800 BA 2

4 2009-04-01 27.500000 29.520000 27.440001 19.820396 15308300 CAT 2

(4)查看DataFrame df 的末尾几行数据,具体实现代码如下所示。

df.tail()

执行后会输出:

date open high low close volume tic day

96937 2022-05-31 503.619995 504.109985 495.660004 491.949829 4003100 UNH 1

96938 2022-05-31 210.380005 214.350006 209.110001 211.322540 9586400 V 1

96939 2022-05-31 51.259998 51.560001 50.849998 49.042248 25016600 VZ 1

96940 2022-05-31 43.480000 44.270000 43.049999 42.811333 8192000 WBA 1

96941 2022-05-31 127.459999 129.899994 127.419998 127.591217 12304100 WMT 1

(5)查看DataFrame df 的形状(行数和列数),具体实现代码如下所示。

df.shape

执行后会输出:

(96942, 8)

(6)按日期和股票代号('date' 和 'tic' 列)对DataFrame df 进行排序,并查看前几行数据。具体实现代码如下所示。

df.sort_values(['date','tic']).head()

执行后会输出:

date open high low close volume tic day

0 2009-04-01 3.717500 3.892857 3.710357 3.308904 589372000 AAPL 2

1 2009-04-01 48.779999 48.930000 47.099998 36.228390 10850100 AMGN 2

2 2009-04-01 13.340000 14.640000 13.080000 11.732112 27701800 AXP 2

3 2009-04-01 34.520000 35.599998 34.209999 26.850748 9288800 BA 2

4 2009-04-01 27.500000 29.520000 27.440001 19.820396 15308300 CAT 2

(7)查看DataFrame df 中唯一的股票代号数量,具体实现代码如下所示。

len(df.tic.unique())

执行后会输出:

30

(8)查看每个股票代号在DataFrame df 中出现的次数,具体实现代码如下所示。

df.tic.value_counts()

执行后会输出:

AAPL    3315
AMGN    3315
WMT     3315
WBA     3315
VZ      3315
V       3315
UNH     3315
TRV     3315
PG      3315
NKE     3315
MSFT    3315
MRK     3315
MMM     3315
MCD     3315
KO      3315
JPM     3315
JNJ     3315
INTC    3315
IBM     3315
HON     3315
HD      3315
GS      3315
DIS     3315
CVX     3315
CSCO    3315
CRM     3315
CAT     3315
BA      3315
AXP     3315
DOW      807
Name: tic, dtype: int64

13.3.4  数据预处理

数据预处理是训练高质量机器学习模型的关键步骤,开发者需要检查缺失数据并进行特征工程,以将数据转化为适合模型训练的状态。在本项目中需要添加如下两个功能:

  1. 添加技术指标:在实际交易中,需要考虑各种信息,例如历史股价、当前持有股份、技术指标等。在本文中,我们演示了两个趋势跟踪技术指标:MACD 和 RSI。
  2. 添加动荡指数:风险厌恶程度反映了投资者是否选择保留资本。它还会影响在面对不同市场波动水平时的交易策略。为了在最坏的情况下控制风险,例如2007年至2008年的金融危机,FinRL采用了衡量极端资产价格波动的金融动荡指数。

(1)使用类FeatureEngineer进行特征工程处理,旨在准备数据以供后续的机器学习模型训练使用,确保数据质量和一致性。具体实现代码如下所示。

fe = FeatureEngineer(use_technical_indicator=True,
                     tech_indicator_list = INDICATORS,
                     use_turbulence=True,
                     user_defined_feature = False)

processed = fe.preprocess_data(df)
processed = processed.copy()
processed = processed.fillna(0)
processed = processed.replace(np.inf,0)

(2)使用sample()方法查看processed数据框中的随机样本,具体实现代码如下所示。

processed.sample(5)

执行后会输出:

	date	open	high	low	close	volume	tic	day	macd	boll_ub	boll_lb	rsi_30	cci_30	dx_30	close_30_sma	close_60_sma	turbulence
20648	2012-01-27	15.869286	16.017143	15.848929	13.616767	299709200	AAPL	4	0.333539	13.611045	12.181263	64.308950	145.852788	54.469561	12.581282	12.174724	26.745756
29227	2013-04-03	62.410000	62.750000	61.619999	53.086536	10140400	UNH	2	1.180346	52.138797	43.794426	69.621207	320.638691	67.961482	47.381937	47.454954	25.558744
73435	2019-04-24	121.349998	121.430000	118.089996	99.647766	22115000	CVX	2	-0.589889	107.941694	99.396927	45.944631	-161.852682	22.159747	104.114838	102.183287	22.350485
17687	2011-08-30	36.240002	36.490002	36.070000	21.325922	13111100	VZ	1	0.048063	21.669226	19.589475	52.227553	70.067351	0.231436	20.852927	21.028263	34.251243
18895	2011-10-28	34.259998	34.490002	34.195000	24.295948	17307400	KO	4	0.018255	24.360143	22.863088	53.045607	64.954077	3.154018	23.832205	23.950548	34.166534

13.3.5  构建环境

考虑到自动化股票交易任务的随机性和交互性质,金融任务通常被建模为马尔可夫决策过程(MDP)问题。训练过程涉及观察股票价格的变化、采取行动和计算奖励,以便使代理根据奖励来调整其策略。通过与环境的交互,交易代理将随着时间的推移制定出一种最大化回报的交易策略。

在本项目中,交易环境基于OpenAI Gym框架,根据时间驱动模拟的原则,模拟实时股票市场,使用真实市场数据。行动空间描述了代理与环境互动的允许行动,一个行动通常包括三个动作:{-1, 0, 1},其中 -1、0、1 分别表示卖出、持有和买入一股。此外,一个行动可以涉及多份股份。我们使用一个行动空间 {-k,…,-1, 0, 1, …, k},其中 k 表示要购买的股份数量,-k 表示要卖出的股份数量。例如,“购买 10 股 AAPL”或“卖出 10 股 AAPL”分别表示 10 或 -10 股。连续行动空间需要被标准化到 [-1, 1] 范围内,因为策略是在高斯分布上定义的,需要被标准化并对称化。

(1)计算与股票交易环境相关的一些维度信息,并打印出结果。具体实现代码如下所示。

stock_dimension = len(processed.tic.unique())
state_space = 1 + 2*stock_dimension + len(INDICATORS)*stock_dimension
print(f"Stock Dimension: {stock_dimension}, State Space: {state_space}")

对上述代码的具体说明如下:

  1. stock_dimension 表示股票的维度,它通过计算processed数据框中不同股票代号的数量来获得,即不同的股票数量。
  2. state_space 表示状态空间的维度,它是一个复杂的计算,包括3个组成部分:其中1表示一个时间步(t),2 * stock_dimension表示每只股票的持有股份数和现金余额的维度,len(INDICATORS) * stock_dimension表示每只股票的技术指标的维度。
  3. 最后,使用函数print()将股票维度和状态空间维度打印出来,以便查看这些信息。执行后会输出:
Stock Dimension: 29, State Space: 291

这些维度信息对于建立和训练股票交易的强化学习模型非常重要,因为它们确定了模型的输入和输出空间的大小。

(2)定义一个名为env_kwargs的字典,其中包含了用于配置股票交易环境的各种参数,不同的参数值可以影响模型的训练和行为。这些参数用于配置股票交易环境,以便在强化学习训练中使用。具体实现代码如下所示。

env_kwargs = {
    "hmax": 100, 
    "initial_amount": 1000000, 
    "buy_cost_pct": 0.001, 
    "sell_cost_pct": 0.001, 
    "state_space": state_space, 
    "stock_dim": stock_dimension, 
    "tech_indicator_list": INDICATORS,
    "action_space": stock_dimension, 
    "reward_scaling": 1e-4,
    "print_verbosity":5
    
}

对各个参数的具体说明如下:

  1. "hmax":每个交易周期(episode)的最大时间步数,这里设置为100。
  2. "initial_amount":初始资金金额,这里设置为1000000。
  3. "buy_cost_pct":购买股票时的交易成本百分比,这里设置为0.001,表示0.1%。
  4. "sell_cost_pct":卖出股票时的交易成本百分比,这里同样设置为0.001。
  5. "state_space":状态空间的维度,之前计算的结果。
  6. "stock_dim":股票维度,之前计算的结果。
  7. "tech_indicator_list":技术指标列表,包括用于特征工程的指标。
  8. "action_space":行动空间的维度,等于股票维度。
  9. "reward_scaling":奖励缩放因子,这里设置为1e-4,用于调整奖励的大小。
  10. "print_verbosity":打印详细信息的级别,这里设置为5,表示较详细的打印输出。

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值