我正在尝试实施强化算法(蒙特卡洛政策梯度),以便每天优化 94 只股票的投资组合(我有合适的历史数据来实现这一点)。这个想法如下:每天,神经网络的输入包括以下内容:
- 94 只股票中每只股票过去 20 天的历史每日回报(每日动量)
- 当前的投资组合权重向量(94 个权重)
因此状态由 1974 维向量表示。神经网络应该返回一个 94 维的动作向量,该向量也是要投资的(理想)投资组合权重的向量。允许使用负权重(空头头寸),并且投资组合权重的总和应为 1。由于动作空间是连续的,我试图通过 Reinforce 算法来解决它。奖励由投资组合每日回报减去交易成本给出。这是一个代码片段:
class Policy(nn.Module):
def __init__(self, s_size=1974, h_size=400, a_size=94):
super().__init__()
self.fc1 = nn.Linear(s_size, h_size)
self.fc2 = nn.Linear(h_size, a_size)
self.state_size = 1974
self.action_size = 94
def forward(self, x):
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
def act(self, state):
state = torch.from_numpy(state).float().unsqueeze(0).to(device)
means = self.forward(state).cpu()
m = MultivariateNormal(means,torch.diag(torch.Tensor(np.repeat(1e-8,94))))
action = m.sample()
action[0] = action[0]/sum(action[0])
return action[0], m.log_prob(action)
请注意,为了确保投资组合权重(动作张量的条目)总和为 1,我将除以它们的总和。另请注意,我正在从对角线项极小的多元正态分布中进行采样,因为我希望网络的行为尽可能具有确定性。(我可能应该使用类似于 DDPG 的东西,但我想尝试更简单的解决方案开始)。
训练部分如下所示:
optimizer = optim.Adam(policy.parameters(), lr=1e-3)
def reinforce(n_episodes=10000, max_t=10000, gamma=1.0, print_every=1):
scores_deque = deque(maxlen=100)
scores = []
for i_episode in range(1, n_episodes+1):
saved_log_probs = []
rewards = []
state = env.reset()
for t in range(max_t):
action, log_prob = policy.act(state)
saved_log_probs.append(log_prob)
state, reward, done, _ = env.step(action.detach().flatten().numpy())
rewards.append(reward)
if done:
break
scores_deque.append(sum(rewards))
scores.append(sum(rewards))
discounts = [gamma**i for i in range(len(rewards)+1)]
R = sum([a*b for a,b in zip(discounts, rewards)])
policy_loss = []
for log_prob in saved_log_probs:
policy_loss.append(-log_prob * R)
policy_loss = torch.cat(policy_loss).sum()
optimizer.zero_grad()
policy_loss.backward()
optimizer.step()
if i_episode % print_every == 10:
print('Episode {}\tAverage Score: {:.2f}'.format(i_episode, np.mean(scores_deque)))
print(scores[-1])
return scores, scores_deque
scores, scores_deque = reinforce()
不幸的是,即使在调整学习率之后,训练期间也没有收敛,所以我的问题如下:我的方法有什么明显的错误吗?如果有,我应该如何解决这个问题?