mirror of
https://github.com/wassname/rl-portfolio-management.git
synced 2026-09-09 16:40:08 +08:00
improving shift ans scale
This commit is contained in:
+1
-2
@@ -7,8 +7,7 @@ def random_shift(x, fraction):
|
||||
"""Apply a random shift to a pandas series."""
|
||||
min_x, max_x = np.min(x), np.max(x)
|
||||
m = np.random.uniform(-fraction, fraction, size=x.shape) + 1
|
||||
c = np.random.uniform(-fraction, fraction, size=x.shape) * x.std()
|
||||
return np.clip(x * m + c, min_x, max_x)
|
||||
return np.clip(x * m, min_x, max_x)
|
||||
|
||||
|
||||
def normalize(x):
|
||||
|
||||
@@ -24,22 +24,24 @@ class DataSrc(object):
|
||||
self.augument = augument
|
||||
self.scale = scale
|
||||
|
||||
df = df.copy()
|
||||
|
||||
# add return/y1 as last col
|
||||
pairs = df.columns.levels[0]
|
||||
for pair in pairs:
|
||||
x = df[pair].close
|
||||
df[pair, "return"] = (x + eps*2) / (x.shift() + eps)
|
||||
df[pair, "return"] = (x + eps) / (x.shift() + eps)
|
||||
df = df[1:]
|
||||
|
||||
# data processing
|
||||
if scale:
|
||||
# df = (df - df.mean(0) + eps) / (df.max(0) - df.min(0) + eps)
|
||||
df = df.apply(lambda x: normalize(x))
|
||||
# don't normalize return
|
||||
df = df.apply(
|
||||
lambda x: normalize(x) if x.name[1] != 'return' else x)
|
||||
|
||||
# get rid of NaN's
|
||||
df = df.fillna(method="pad")
|
||||
df.replace(np.nan, 0, inplace=True)
|
||||
df = df.fillna(method="pad")
|
||||
|
||||
self._data = df.copy()
|
||||
self.asset_names = self._data.columns.levels[0].tolist()
|
||||
@@ -64,8 +66,10 @@ class DataSrc(object):
|
||||
data = self._data[self.idx:self.idx + self.steps].copy()
|
||||
|
||||
# scale each run to the begining of the episode so they look the same
|
||||
# but not return
|
||||
if self.scale:
|
||||
data = data.apply(lambda x: scale_to_start(x))
|
||||
data = data.apply(
|
||||
lambda x: scale_to_start(x) if x.name[1] != 'return' else x)
|
||||
|
||||
# augument data to prevent overfitting
|
||||
data = data.apply(lambda x: random_shift(x, self.augument))
|
||||
|
||||
+26
-5
@@ -6,19 +6,29 @@ from src.environments.portfolio import PortfolioEnv
|
||||
def test_portfolio_env():
|
||||
df = pd.read_hdf('./data/poliniex_30m.hf', key='train')
|
||||
asset_names = df.columns.levels[0]
|
||||
# action
|
||||
w = np.random.random((len(asset_names)))
|
||||
w /= w.sum()
|
||||
|
||||
np.random.seed(0)
|
||||
env = PortfolioEnv(df=df)
|
||||
env.reset()
|
||||
obs, reward, done, info = env.step(w)
|
||||
|
||||
obs = env.reset()
|
||||
for _ in range(20):
|
||||
|
||||
w = np.random.random((len(asset_names)))
|
||||
w /= w.sum()
|
||||
|
||||
obs, reward, done, info = env.step(w)
|
||||
assert not done
|
||||
|
||||
df_info = pd.DataFrame(info)
|
||||
final_value = df_info.portfolio_value.iloc[-1]
|
||||
assert final_value > 0.75, 'should retain most value with 20 random steps'
|
||||
|
||||
|
||||
def test_portfolio_env_hold():
|
||||
df = pd.read_hdf('./data/poliniex_30m.hf', key='train')
|
||||
asset_names = df.columns.levels[0]
|
||||
|
||||
np.random.seed(0)
|
||||
env = PortfolioEnv(df=df)
|
||||
env.reset()
|
||||
for _ in range(5):
|
||||
@@ -27,3 +37,14 @@ def test_portfolio_env_hold():
|
||||
|
||||
df = pd.DataFrame(info)
|
||||
assert df.portfolio_value.iloc[-1] > 0.9999, 'portfolio should retain value if holding bitcoin'
|
||||
|
||||
|
||||
def test_return_not_scaled():
|
||||
df = pd.read_hdf('./data/poliniex_30m.hf', key='train')
|
||||
np.random.seed(0)
|
||||
env1 = PortfolioEnv(df=df, scale=True)
|
||||
np.random.seed(0)
|
||||
env0 = PortfolioEnv(df=df, scale=False)
|
||||
a = env0.src._data.xs('return', axis=1, level='Price').tail(5)
|
||||
b = env1.src._data.xs('return', axis=1, level='Price').tail(5)
|
||||
assert (a == b).all().all(), 'returns should not be scaled'
|
||||
|
||||
+3
-3
@@ -10,9 +10,9 @@ def test_random_shift():
|
||||
assert (s == s1).all(), 'should not do anything if given 0'
|
||||
|
||||
s2 = random_shift(s.copy(), 0.05)
|
||||
assert (s2 / s).max() > 1.0, 'should shift more than 0.00 given 0.05'
|
||||
assert (s2 / s).max() < 1.1, 'should shift less than 0.10 given 0.05'
|
||||
np.testing.assert_almost_equal((s2 / s).mean(), 1.00, 2)
|
||||
shift = (s2 / s)
|
||||
np.testing.assert_almost_equal(shift.mean(), 1.00, 2)
|
||||
np.testing.assert_almost_equal(shift.max(), 1.05, 2)
|
||||
|
||||
|
||||
def test_normalize():
|
||||
|
||||
Reference in New Issue
Block a user