Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
AI4Finance-Foundation
GitHub Repository: AI4Finance-Foundation/FinRL
Path: blob/master/finrl/agents/portfolio_optimization/utils.py
732 views
1
from __future__ import annotations
2
3
from collections import deque
4
from random import randint
5
from random import random
6
7
import numpy as np
8
from torch.utils.data.dataset import IterableDataset
9
10
11
class PVM:
12
def __init__(self, capacity, portfolio_size):
13
"""Initializes portfolio vector memory.
14
15
Args:
16
capacity: Max capacity of memory.
17
portfolio_size: Portfolio size.
18
"""
19
# initially, memory will have the same actions
20
self.capacity = capacity
21
self.portfolio_size = portfolio_size
22
self.reset()
23
24
def reset(self):
25
self.memory = [np.array([1] + [0] * self.portfolio_size, dtype=np.float32)] * (
26
self.capacity + 1
27
)
28
self.index = 0 # initial index to retrieve data
29
30
def retrieve(self):
31
last_action = self.memory[self.index]
32
self.index = 0 if self.index == self.capacity else self.index + 1
33
return last_action
34
35
def add(self, action):
36
self.memory[self.index] = action
37
38
39
class ReplayBuffer:
40
def __init__(self, capacity):
41
"""Initializes replay buffer.
42
43
Args:
44
capacity: Max capacity of buffer.
45
"""
46
self.buffer = deque(maxlen=capacity)
47
48
def __len__(self):
49
"""Represents the size of the buffer
50
51
Returns:
52
Size of the buffer.
53
"""
54
return len(self.buffer)
55
56
def append(self, experience):
57
"""Append experience to buffer. When buffer is full, it pops
58
an old experience.
59
60
Args:
61
experience: experience to be saved.
62
"""
63
self.buffer.append(experience)
64
65
def sample(self):
66
"""Sample from replay buffer. All data from replay buffer is
67
returned and the buffer is cleared.
68
69
Returns:
70
Sample of batch_size size.
71
"""
72
buffer = list(self.buffer)
73
self.buffer.clear()
74
return buffer
75
76
77
class RLDataset(IterableDataset):
78
def __init__(self, buffer):
79
"""Initializes reinforcement learning dataset.
80
81
Args:
82
buffer: replay buffer to become iterable dataset.
83
84
Note:
85
It's a subclass of pytorch's IterableDataset,
86
check https://pytorch.org/docs/stable/data.html#torch.utils.data.IterableDataset
87
"""
88
self.buffer = buffer
89
90
def __iter__(self):
91
"""Iterates over RLDataset.
92
93
Returns:
94
Every experience of a sample from replay buffer.
95
"""
96
yield from self.buffer.sample()
97
98
99
def apply_portfolio_noise(portfolio, epsilon=0.0):
100
"""Apply noise to portfolio distribution considering its constrains.
101
102
Arg:
103
portfolio: initial portfolio distribution.
104
epsilon: maximum rebalancing.
105
106
Returns:
107
New portolio distribution with noise applied.
108
"""
109
portfolio_size = portfolio.shape[0]
110
new_portfolio = portfolio.copy()
111
for i in range(portfolio_size):
112
target_index = randint(0, portfolio_size - 1)
113
difference = epsilon * random()
114
# check constrains
115
max_diff = min(new_portfolio[i], 1 - new_portfolio[target_index])
116
difference = min(difference, max_diff)
117
# apply difference
118
new_portfolio[i] -= difference
119
new_portfolio[target_index] += difference
120
return new_portfolio
121
122