打造一个投资组合管理的金融强化学习环境

今天继续金融强化学习环境。

网上的金融学习环境不少,但都太过于“业余”,或者离样的投资还差得太远。我一直觉得投资组合应该是必要的,不做投资组合,要控制回撤实在太难了,加上低相关多资产组合,对于投资而言,低层逻辑就是成立的。再加上一些规则也好,模型也罢,或者强化学习的加持,争取提升收益率。

所以,强化学习我也希望能够做投资组合。在finRL-meta里有投资组合分配的环境,今天结合咱们自己的AI量化平台,打造一个金融“投资组合管理”的学习环境。

from abc import ABC

import gym
import numpy as np
from gym import spaces


class FinanceEnv(gym.Env, ABC):
def __init__(self, symbols, df_features, df_returns, initial_amount=1000000):
super(FinanceEnv, self).__init__() # 正则化,和=1,长度就是组合里的证券数量 self.action_space = spaces.Box(low=0, high=1, shape=(len(symbols),)) self.observation_space = spaces.Box( low=-np.inf, high=np.inf, shape=(len(symbols), len(df_features.columns)), dtype=np.float64 ) #print(self.observation_space) self.dates = list(df_features.index) self.df_features = df_features self.df_returns = df_returns self.initial_amount = initial_amount self.portfolio_value = initial_amount self.index = 0 def reset(self): self.index = 0 self.portfolio_value = self.initial_amount df = self.df_features.loc[self.dates[0]] print(df.values.shape) return df.values def step(self, actions): done = False if self.index >= len(self.dates) - 1: done = True print(self.reward) return self.state, self.reward, done, {} self.index += 1 weights = self.softmax_normalization(actions) df_return = np.array(self.df_returns.loc[self.dates[self.index]]['return']) port_return = sum(df_return * np.array(weights)) self.portfolio_value = self.portfolio_value * (1 + port_return) df = self.df_features.loc[self.dates[self.index], :] self.state = df.values self.reward = self.portfolio_value * 1.0 return self.state, self.reward, done, {} def softmax_normalization(self, actions): numerator = np.exp(actions) denominator = np.sum(np.exp(actions)) softmax_output = numerator / denominator return softmax_outputif __name__ == '__main__': from stable_baselines3.common.env_checker import check_env from stable_baselines3 import A2C from engine.datafeed.dataloader import Dataloader symbols = ['399006.SZ', '000300.SH'] names = [] fields = [] features = [] fields += ['Slope($close,20)'] names += ['mom_slope'] features += ['mom_slope'] fields += ['KF($mom_slope)'] names += ['kf_mom_slope'] features += ['kf_mom_slope'] fields += ["$close/Ref($close,1) - 1"] names += ['return'] loader = Dataloader(symbols, names, fields, load_from_cache=True) data = loader.data data = data[data.index > '2010-06-02'] df_features = data[names] df_return = data[['return']] print(df_features) env = FinanceEnv(symbols, df_features, df_return) # check_env(env) model = A2C("MlpPolicy", env) model.learn(total_timesteps=100000)

1、继承自gym.Env。

2、定义动作与状态空间,都是gym.spaces 对象。

动作空间就是投资组合里的symbol数量,因为我们给出的是证券的仓位占比;而状态空间是symbol行*特征列——也就是所有证券的因子值。

3、重点实现step与reset两个函数

Step就是传入一个动作,并计算reward,返回新的state。

Reset是环境重置初始化。

4、step函数:

传入的参数actions是各标的的权重,按actions归一化为和为1的向量,计算新的投资组合收益率,计算新的组合价值。这里把组合市值作为环境的reward,当然我们还可以计算夏普比,最大回撤等。

代码和数据已经上传至星球,有任何问题请在星球群里讨论。

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/104201
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2024 年 7 月 29 日
下一篇 2024 年 7 月 29 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注