10.3 数据处理
Yahoo Finance是一个提供股票数据、财经新闻、财报等信息的网站,并且提供的数据是免费的。在FinRL中,使用类YahooDownloader从Yahoo Finance API获取数据。在使用 Yahoo Finance 的公共 API(无需提供用户身份验证)时,每个 IP 地址在一个小时内最多可以发送 2,000 次请求,或者每天最多可以发送 48,000 次请求。这是 Yahoo Finance 对于公共 API 使用的一种限制,旨在控制对其服务的访问频率,以维持平稳的服务运行。如果超过这个限制,可能会导致请求被拒绝或服务暂时不可用。因此,在使用 Yahoo Finance API 时,需要注意并遵循其调用限制。
10.3.1 准备数据
(1)使用print语句打印输出config_tickers.DOW_30_TICKER的值,该变量是FinRL库中预定义的标志着道琼斯指数成分股的股票代码列表。
print(config_tickers.DOW_30_TICKER)
执行后将显示Dow Jones Industrial Average指数的成分股票的代码:
['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)开始准备金融数据,以供后续的强化学习模型训练和分析使用。下面的代码将创建一个YahooFinanceProcessor的实例对象dp,然后使用该对象的download_data方法下载了指定时间范围内(从2008年1月1日到2021年10月31日)Dow Jones Industrial Average指数成分股的每日股票数据。下载的数据被存储在DataFrame对象df中。
dp = YahooFinanceProcessor()
df = dp.download_data(start_date = '2008-01-01',
end_date = '2021-10-31',
ticker_list = config_tickers.DOW_30_TICKER, time_interval='1D')
执行后会输出:
[*********************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
[*********************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
[*********************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: (101615, 9)
(3)通过df.head()显示DataFrame df 的前几行数据,目的是展示下载的金融数据的头部,以便查看数据的结构和内容。
df.head()
执行后会输出:
date open high low close adjcp volume tic day
0 2008-01-02 7.116786 7.152143 6.876786 6.958571 5.941450 1079178800 AAPL 2
1 2008-01-02 46.599998 47.040001 46.259998 46.599998 35.172192 7934400 AMGN 2
2 2008-01-02 52.090000 52.320000 50.790001 51.040001 40.326855 8053700 AXP 2
3 2008-01-02 87.570000 87.839996 86.000000 86.620003 63.481602 4303000 BA 2
4 2008-01-02 72.559998 72.669998 70.050003 70.629997 46.850491 6337800 CAT 2
通过这种方式,我们可以快速了解数据的格式,包括日期、股票代码以及相关的开盘价、最高价、最低价、收盘价和成交量等信息。这有助于确保数据被正确下载,并以适当的形式准备供后续分析和建模使用。
(4)通过df.shape获取DataFrame df 的形状,返回一个表示数据框维度的元组(行数,列数)。这行代码的目的是查看下载的金融数据的规模,即数据框中的行数和列数。
df.shape
通过df.shape,可以得知数据中有多少条记录(行数)和每个记录包含多少个特征(列数),从而更好地理解数据的规模和结构。执行后会输出:
(101615, 9)
10.3.2 数据预处理
数据预处理是训练高质量机器学习模型的关键步骤,在这一步需要检查缺失数据并进行特征工程,以将数据转换为适合模型训练的状态。本项目的数据预处理江湾城以下工作:
- 添加技术指标:在实际交易中,需要考虑各种信息,例如历史股价、当前持仓股票、技术指标等。本文演示了两个趋势跟踪技术指标:MACD和RSI。
- 添加紧急指数:风险厌恶反映了投资者是否选择保留资本,它还在面对不同市场波动水平时影响交易策略。为了在最坏的情况下控制风险,比如20010-2008年的金融危机,FinRL使用了金融紧急指数来衡量极端资产价格波动。
注意:风险厌恶是指个体或投资者对于面临潜在风险时的心理和行为倾向。在金融领域,风险厌恶通常表现为投资者更倾向于选择相对较低的风险投资,即使这可能意味着较低的收益。
1. 技术指标
(1)使用类FeatureEngineer对金融数据进行预处理和特征工程。通过设置参数use_technical_indicator=True,启用了技术指标(如MACD和RSI),为模型提供更多市场趋势和力量的信息。通过user_defined_feature = False禁用了风险紧急指数,表示不考虑极端波动对模型的影响。最后,通过preprocess_data方法对数据进行标准化和处理缺失值等操作,为后续的强化学习模型训练提供准备。这些步骤旨在提高模型的性能和对金融市场行为的理解。
fe = FeatureEngineer(
use_technical_indicator=True,
use_turbulence=False,
user_defined_feature = False)
df = fe.preprocess_data(df)
(2)获取数据框 df 的形状,返回一个表示数据框维度的元组(行数,列数)。
df.shape
上述代码的目的是查看数据经过预处理和特征工程后的规模,即数据框中的行数和列数。通过df.shape,可以确认处理后的数据的规模,确保数据准备步骤没有导致数据维度的意外变化。执行后会输出:
(97524, 17)
(3)通过如下代码显示 DataFrame df 的前几行数据,目的是展示经过预处理和特征工程后的数据的头部,以便查看数据的结构和内容。
df.head()
执行后会输出:
date open high low close adjcp volume tic day macd boll_ub boll_lb rsi_30 cci_30 dx_30 close_30_sma close_60_sma
0 2008-01-02 7.116786 7.152143 6.876786 6.958571 5.941450 1079178800 AAPL 2 0.0 6.964725 6.955632 100.0 -66.666667 100.0 6.958571 6.958571
3483 2008-01-02 46.599998 47.040001 46.259998 46.599998 35.172192 7934400 AMGN 2 0.0 6.964725 6.955632 100.0 -66.666667 100.0 46.599998 46.599998
6966 2008-01-02 52.090000 52.320000 50.790001 51.040001 40.326855 8053700 AXP 2 0.0 6.964725 6.955632 100.0 -66.666667 100.0 51.040001 51.040001
10449 2008-01-02 87.570000 87.839996 86.000000 86.620003 63.481602 4303000 BA 2 0.0 6.964725 6.955632 100.0 -66.666667 100.0 86.620003 86.620003
13932 2008-01-02 72.559998 72.669998 70.050003 70.629997 46.850491 6337800 CAT 2 0.0 6.964725 6.955632 100.0 -66.666667 100.0 70.629997 70.629997
2. 将协方差矩阵添加为状态
在金融建模的背景下,特别是在投资组合优化和风险管理中,协方差矩阵是一个关键的度量标准。它捕捉了投资组合中不同资产之间运动关系的程度,为整体风险和分散化提供了洞察。通过将协方差矩阵添加为状态,模型能能够更全面地理解不同资产之间的相互关系和依赖性。这有助于提高模型对整体市场风险和资产关联性的认识。
(1)如下代码将协方差矩阵作为状态加入数据集,实现了对金融数据的处理。通过对过去一年的股票收益率数据计算协方差矩阵,提取了相应的协方差和收益率信息,并将其添加到数据框中。这有助于模型更全面地理解股票之间的关联性和风险特征,为后续强化学习模型的训练提供更丰富的状态信息。
# 将协方差矩阵作为状态添加
df = df.sort_values(['date', 'tic'], ignore_index=True)
df.index = df.date.factorize()[0]
cov_list = [] # 存储协方差矩阵
return_list = [] # 存储收益率
# 回看窗口为一年
lookback = 252
for i in range(lookback, len(df.index.unique())):
# 提取过去一年的数据
data_lookback = df.loc[i - lookback:i, :]
price_lookback = data_lookback.pivot_table(index='date', columns='tic', values='close')
return_lookback = price_lookback.pct_change().dropna()
return_list.append(return_lookback)
# 计算协方差矩阵
covs = return_lookback.cov().values
cov_list.append(covs)
# 创建包含协方差矩阵和收益率的数据框
df_cov = pd.DataFrame({'date': df.date.unique()[lookback:], 'cov_list': cov_list, 'return_list': return_list})
df = df.merge(df_cov, on='date')
df = df.sort_values(['date', 'tic']).reset_index(drop=True)
(2)通过df.shape获取 DataFrame df 的形状,返回一个表示数据框维度的元组(行数,列数)。
df.shape
上述代码的目的是查看数据框 df 经过协方差矩阵添加后的规模,即数据框中的行数和列数。通过df.shape,你可以确认处理后的数据的规模,确保数据维度的正确性。执行后会输出:
(90468, 19)
(3)通过如下代码显示 DataFrame df 的前几行数据。这行代码的目的是展示经过协方差矩阵添加后的数据的头部,以便查看数据的结构和内容。通过这种方式,你可以快速了解处理后数据的格式,包括日期、股票代码、技术指标、协方差矩阵等信息。这有助于确保数据准备过程的正确性,为后续建模和分析提供良好的基础。
df.head()
执行后会输出:
date open high low close adjcp volume tic day macd boll_ub boll_lb rsi_30 cci_30 dx_30 close_30_sma close_60_sma cov_list return_list
0 2008-12-31 3.070357 3.133571 3.047857 3.048214 2.602662 607541200 AAPL 2 -0.097446 3.649552 2.895305 42.254771 -80.847207 16.129793 3.243631 3.375887 [[0.001348968986171653, 0.00042841264280825875... tic AAPL AMGN AXP ...
1 2008-12-31 57.110001 58.220001 57.060001 57.750000 43.587837 6287200 AMGN 2 0.216368 58.947401 56.388599 51.060614 51.895357 10.432018 56.671334 56.044333 [[0.001348968986171653, 0.00042841264280825875... tic AAPL AMGN AXP ...
2 2008-12-31 17.969999 18.750000 17.910000 18.549999 14.852879 9625600 AXP 2 -1.191668 23.723023 16.106977 42.521170 -74.811722 25.776759 20.030000 22.412000 [[0.001348968986171653, 0.00042841264280825875... tic AAPL AMGN AXP ...
3 2008-12-31 41.590000 43.049999 41.500000 42.669998 32.005894 5443100 BA 2 -0.391219 42.894634 38.486366 47.290375 157.922391 5.366299 40.432000 43.304500 [[0.001348968986171653, 0.00042841264280825875... tic AAPL AMGN AXP ...
4 2008-12-31 43.700001 45.099998 43.700001 44.669998 30.416977 6277400 CAT 2 0.979845 45.785565 38.404435 51.073052 98.904653 26.331746 40.266000 39.918333 [[0.001348968986171653, 0.00042841264280825875... tic AAPL AMGN AXP ...