diff --git a/keras-ddpg.ipynb b/keras-ddpg.ipynb deleted file mode 100644 index 137d721..0000000 --- a/keras-ddpg.ipynb +++ /dev/null @@ -1,1547 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:38.432291Z", - "start_time": "2017-07-23T14:09:37.784671+08:00" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:__main__:__main__ logger started.\n" - ] - } - ], - "source": [ - "# plotting\n", - "%matplotlib inline\n", - "from matplotlib import pyplot as plt\n", - "import seaborn as sns\n", - "plt.style.use('ggplot')\n", - "\n", - "# numeric\n", - "import numpy as np\n", - "from numpy import random\n", - "import pandas as pd\n", - "\n", - "# utils\n", - "from tqdm import tqdm_notebook as tqdm\n", - "from collections import Counter\n", - "import tempfile\n", - "import logging\n", - "import time\n", - "import datetime\n", - "\n", - "# logging\n", - "logger = log = logging.getLogger(__name__)\n", - "log.setLevel(logging.INFO)\n", - "logging.basicConfig()\n", - "log.info('%s logger started.', __name__)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:54.958396Z", - "start_time": "2017-07-23T14:09:38.433930+08:00" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Using TensorFlow backend.\n" - ] - } - ], - "source": [ - "# reinforcement learning\n", - "import gym\n", - "from gym import error, spaces, utils\n", - "from gym.utils import seeding\n", - "\n", - "from keras.models import Sequential\n", - "from keras.layers import Flatten, Dense, Activation, BatchNormalization\n", - "from keras.optimizers import Adam\n", - "from keras.layers.advanced_activations import LeakyReLU\n", - "from keras.models import Sequential\n", - "from keras.layers import Flatten, Dense, Activation, BatchNormalization, Conv1D, InputLayer, Dropout, regularizers, Conv2D, Reshape\n", - "from keras.optimizers import Adam\n", - "from keras.layers.advanced_activations import LeakyReLU\n", - "from keras.activations import relu" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:54.990899Z", - "start_time": "2017-07-23T14:09:54.960526+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "import os\n", - "os.sys.path.append(os.path.abspath('.'))\n", - "%reload_ext autoreload\n", - "%autoreload 2" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:55.020046Z", - "start_time": "2017-07-23T14:09:54.993182+08:00" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "'outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f'" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "window_length = 50\n", - "batch_size=250\n", - "save_path= 'outputs/agent_portfolio-ddpg-keras/{}_weights.h5f'.format('2017-07-21_')\n", - "save_path" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Environment\n", - "\n", - "You can see the base environment class [here](https://github.com/openai/gym/blob/master/gym/core.py#L13) and openai's nice docs [here](https://gym.openai.com/docs). My environment is in `src/environments/portfolio.py` and the PortfolioEnvironment load a datasource and simulation subclass.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:55.050521Z", - "start_time": "2017-07-23T14:09:55.021418+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "from src.environments.portfolio import PortfolioEnv" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:55.223396Z", - "start_time": "2017-07-23T14:09:55.052342+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "df_train = pd.read_hdf('./data/poloniex_30m.hf',key='train')\n", - "env = PortfolioEnv(\n", - " df=df_train,\n", - " steps=1440, \n", - " scale=True, \n", - " augment=0.0000, # let just overfit first,\n", - " trading_cost=0, # let just overfit first,\n", - " window_length = window_length,\n", - " \n", - ")\n", - "env.seed = 0 \n", - "\n", - "df_test = pd.read_hdf('./data/poloniex_30m.hf',key='test')\n", - "env_test = PortfolioEnv(\n", - " df=df_test,\n", - " steps=1440, \n", - " scale=True, \n", - " augment=0.00,\n", - " trading_cost=0, # let just overfit first\n", - " window_length=window_length,\n", - ")\n", - "env_test.seed = 0 " - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-04T01:42:37.345932Z", - "start_time": "2017-07-04T09:42:37.328860+08:00" - }, - "collapsed": true - }, - "source": [ - "# Model\n", - "\n", - "arXiv:1612.01277 indicated that CNN's are just as effective. That's great because I like them, they are fast so I can try more things and see the results faster. So we will be using a CNN model.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:55.628200Z", - "start_time": "2017-07-23T14:09:55.225321+08:00" - }, - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "_________________________________________________________________\n", - "Layer (type) Output Shape Param # \n", - "=================================================================\n", - "input_1 (InputLayer) (None, 1, 5, 50, 3) 0 \n", - "_________________________________________________________________\n", - "reshape_1 (Reshape) (None, 5, 50, 3) 0 \n", - "_________________________________________________________________\n", - "conv2d_1 (Conv2D) (None, 5, 48, 2) 20 \n", - "_________________________________________________________________\n", - "batch_normalization_1 (Batch (None, 5, 48, 2) 8 \n", - "_________________________________________________________________\n", - "conv2d_2 (Conv2D) (None, 5, 1, 20) 1940 \n", - "_________________________________________________________________\n", - "batch_normalization_2 (Batch (None, 5, 1, 20) 80 \n", - "_________________________________________________________________\n", - "conv2d_3 (Conv2D) (None, 5, 1, 1) 21 \n", - "_________________________________________________________________\n", - "batch_normalization_3 (Batch (None, 5, 1, 1) 4 \n", - "_________________________________________________________________\n", - "flatten_1 (Flatten) (None, 5) 0 \n", - "_________________________________________________________________\n", - "dense_1 (Dense) (None, 6) 36 \n", - "_________________________________________________________________\n", - "activation_1 (Activation) (None, 6) 0 \n", - "=================================================================\n", - "Total params: 2,109\n", - "Trainable params: 2,063\n", - "Non-trainable params: 46\n", - "_________________________________________________________________\n", - "None\n", - "____________________________________________________________________________________________________\n", - "Layer (type) Output Shape Param # Connected to \n", - "====================================================================================================\n", - "observation_input (InputLayer) (None, 1, 5, 50, 3) 0 \n", - "____________________________________________________________________________________________________\n", - "reshape_2 (Reshape) (None, 5, 50, 3) 0 observation_input[0][0] \n", - "____________________________________________________________________________________________________\n", - "conv2d_4 (Conv2D) (None, 5, 48, 2) 20 reshape_2[0][0] \n", - "____________________________________________________________________________________________________\n", - "batch_normalization_4 (BatchNorm (None, 5, 48, 2) 8 conv2d_4[0][0] \n", - "____________________________________________________________________________________________________\n", - "conv2d_5 (Conv2D) (None, 5, 1, 20) 1940 batch_normalization_4[0][0] \n", - "____________________________________________________________________________________________________\n", - "batch_normalization_5 (BatchNorm (None, 5, 1, 20) 80 conv2d_5[0][0] \n", - "____________________________________________________________________________________________________\n", - "action_input (InputLayer) (None, 6) 0 \n", - "____________________________________________________________________________________________________\n", - "flatten_2 (Flatten) (None, 100) 0 batch_normalization_5[0][0] \n", - "____________________________________________________________________________________________________\n", - "concatenate_1 (Concatenate) (None, 106) 0 action_input[0][0] \n", - " flatten_2[0][0] \n", - "____________________________________________________________________________________________________\n", - "dense_2 (Dense) (None, 64) 6848 concatenate_1[0][0] \n", - "____________________________________________________________________________________________________\n", - "activation_2 (Activation) (None, 64) 0 dense_2[0][0] \n", - "____________________________________________________________________________________________________\n", - "batch_normalization_6 (BatchNorm (None, 64) 256 activation_2[0][0] \n", - "____________________________________________________________________________________________________\n", - "dense_3 (Dense) (None, 32) 2080 batch_normalization_6[0][0] \n", - "____________________________________________________________________________________________________\n", - "activation_3 (Activation) (None, 32) 0 dense_3[0][0] \n", - "____________________________________________________________________________________________________\n", - "batch_normalization_7 (BatchNorm (None, 32) 128 activation_3[0][0] \n", - "____________________________________________________________________________________________________\n", - "dense_4 (Dense) (None, 16) 528 batch_normalization_7[0][0] \n", - "____________________________________________________________________________________________________\n", - "activation_4 (Activation) (None, 16) 0 dense_4[0][0] \n", - "____________________________________________________________________________________________________\n", - "batch_normalization_8 (BatchNorm (None, 16) 64 activation_4[0][0] \n", - "____________________________________________________________________________________________________\n", - "dense_5 (Dense) (None, 1) 17 batch_normalization_8[0][0] \n", - "____________________________________________________________________________________________________\n", - "activation_5 (Activation) (None, 1) 0 dense_5[0][0] \n", - "====================================================================================================\n", - "Total params: 11,969\n", - "Trainable params: 11,701\n", - "Non-trainable params: 268\n", - "____________________________________________________________________________________________________\n", - "None\n" - ] - } - ], - "source": [ - "from keras.layers import Input, merge, Reshape\n", - "from keras.layers import concatenate, Conv2D\n", - "from keras.regularizers import l2, l1_l2\n", - "from keras.models import Model\n", - "\n", - "window_length=50\n", - "nb_actions=env.action_space.shape[0]\n", - "reg=1e-8\n", - "\n", - "# Simple CNN actor model\n", - "actor = Sequential()\n", - "actor.add(InputLayer(input_shape=(1,)+env.observation_space.shape))\n", - "actor.add(Reshape(env.observation_space.shape))\n", - "actor.add(Conv2D(\n", - " filters=2,\n", - " kernel_size=(1,3),\n", - " kernel_regularizer=l2(reg),\n", - " activation='elu'\n", - "))\n", - "actor.add(BatchNormalization()) # lets add batch norm to decrease training time\n", - "\n", - "actor.add(Conv2D(\n", - " filters=20,\n", - " kernel_size=(1,window_length-2),\n", - " kernel_regularizer=l2(reg),\n", - " activation='elu'\n", - "))\n", - "actor.add(BatchNormalization())\n", - "\n", - "actor.add(Conv2D(\n", - " filters=1,\n", - " kernel_size=(1,1),\n", - " kernel_regularizer=l2(reg),\n", - " activation='elu'\n", - "))\n", - "actor.add(BatchNormalization())\n", - "\n", - "actor.add(Flatten())\n", - "actor.add(Dense(\n", - " nb_actions, \n", - " kernel_regularizer=l2(reg)\n", - ")) # this adds cash bias\n", - "actor.add(Activation('softmax'))\n", - "print(actor.summary())\n", - "\n", - "# Lets have nice flexible critic so it can approximate the Q-function\n", - "action_input = Input(shape=(nb_actions,), name='action_input')\n", - "\n", - "observation_input = Input(shape=(1,)+env.observation_space.shape, name='observation_input')\n", - "y = Reshape(env.observation_space.shape)(observation_input)\n", - "\n", - "y = Conv2D(\n", - " filters=2,\n", - " kernel_size=(1,3),\n", - " kernel_regularizer=l2(reg),\n", - " activation='elu'\n", - ")(y)\n", - "y = BatchNormalization()(y) # lets add batch norm to decrease training time\n", - "\n", - "y = Conv2D(\n", - " filters=20,\n", - " kernel_size=(1,window_length-2),\n", - " kernel_regularizer=l2(reg),\n", - " activation='elu'\n", - ")(y)\n", - "y = BatchNormalization()(y)\n", - "\n", - "y = Flatten()(y)\n", - "\n", - "x = concatenate([action_input, y])\n", - "x = Dense(64)(x)\n", - "x = Activation('elu')(x)\n", - "x = BatchNormalization()(x)\n", - "\n", - "x = Dense(32)(x)\n", - "x = Activation('elu')(x)\n", - "x = BatchNormalization()(x)\n", - "\n", - "x = Dense(16)(x)\n", - "x = Activation('elu')(x)\n", - "x = BatchNormalization()(x)\n", - "\n", - "x = Dense(1)(x)\n", - "x = Activation('linear')(x)\n", - "critic = Model(inputs=[action_input, observation_input], outputs=x)\n", - "print(critic.summary())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Agent" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:55.660715Z", - "start_time": "2017-07-23T14:09:55.630064+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "# # prioritised experience memory, lets make the tensorforce one work for keras-rl\n", - "# # https://github.com/matthiasplappert/keras-rl/blob/master/rl/memory.py#L115\n", - "# # https://github.com/reinforceio/tensorforce/blob/master/tensorforce/core/memories/prioritized_replay.py\n", - "# from tensorforce.core.memories import PrioritizedReplay\n", - "# from collections import namedtuple\n", - "# Experience = namedtuple('Experience',\n", - "# 'state0, action, reward, state1, terminal1')\n", - "\n", - "\n", - "# class KRLPrioritizedReplay(PrioritizedReplay):\n", - "# def get_recent_state(self, current_observation):\n", - "# return current_observation\n", - "\n", - "# def sample(self, batch_size, batch_idxs=None):\n", - "# tensorforce_batch = super().get_batch(batch_size)\n", - "# experiences = []\n", - "# # now convert dict(states=states, actions=actions, rewards=rewards, terminals=terminals, internals=internals)\n", - "# # into Experience = namedtuple('Experience', 'state0, action, reward, state1, terminal1')\n", - "# for i in range(len(tensorforce_batch['states'])-1):\n", - "# experiences.append(\n", - "# Experience(\n", - "# state0=tensorforce_batch['states'][i],\n", - "# action=tensorforce_batch['action'][i],\n", - "# reward=tensorforce_batch['reward'][i],\n", - "# state1=tensorforce_batch['states'][i+1],\n", - "# terminal1=tensorforce_batch['terminals'][i+1],\n", - "# ))\n", - "# return experiences\n", - "\n", - "# def append(self, observation, action, reward, terminal, training=True):\n", - "# \"\"\"Backwards: Store most recent experience in memory.\"\"\"\n", - "# actions = dict([(name, action[i]) for i, name in enumerate(self.action_spec.keys())])\n", - "# states = dict([(name, state[i]) for i, name in enumerate(self.state_spec.keys())])\n", - "# return super().add_observation(\n", - "# state=states,\n", - "# action=actions,\n", - "# reward=reward,\n", - "# terminal=terminal,\n", - "# internal=[])\n", - "\n", - "# @property\n", - "# def nb_entries(self):\n", - "# return len(self.observations)\n", - "\n", - "# def get_config(self):\n", - "# config = {\n", - "# 'window_length': self.window_length,\n", - "# 'ignore_episode_boundaries': self.ignore_episode_boundaries,\n", - "# 'limit': self.limit\n", - "# }\n", - "# return config\n", - " \n", - " \n", - "# # test\n", - "# from tensorforce.config import Configuration\n", - "# # Configuration.from_json\n", - "# states={\n", - "# 'state':dict(shape=tuple(env.observation_space.shape), type='float'),\n", - "# }\n", - "# actions={'action' + str(n): dict(continuous=True) for n in range(env.action_space.shape[0])}\n", - "# config = Configuration(\n", - "# states=states,\n", - "# actions=actions,\n", - "# )\n", - "\n", - "# from rl.memory import SequentialMemory\n", - "# memory0 = SequentialMemory(limit=10000, window_length=1)\n", - "# memory1 = KRLPrioritizedReplay(\n", - "# capacity=10000,\n", - "# states_config=config.states,\n", - "# actions_config=config.actions,\n", - "# prioritization_weight=1.0\n", - "# )\n", - "\n", - "\n", - "# observation = np.zeros(states['state']['shape'])\n", - "# action = [0.5 for i in actions]\n", - "# reward=0.5\n", - "# terminal=False\n", - "\n", - "# for _ in range(10):\n", - "# memory0.append(observation, action, reward, terminal, training=True)\n", - "# state0 = memory0.get_recent_state(observation)\n", - "# sample0 = memory0.sample(1)\n", - "\n", - "\n", - "# for _ in range(10):\n", - "# memory1.append(observation, action, reward, terminal, training=True)\n", - "# state1 = memory1.get_recent_state(observation)\n", - "# sample1 = memory1.sample(1)\n", - "\n", - "# assert sample0==sample1\n", - "\n", - "\n", - "# TODO make batch return state1 https://github.com/matthiasplappert/keras-rl/blob/master/rl/memory.py#L153" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:57.619763Z", - "start_time": "2017-07-23T14:09:55.662424+08:00" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from rl.agents.ddpg import DDPGAgent\n", - "from rl.policy import BoltzmannQPolicy, EpsGreedyQPolicy, LinearAnnealedPolicy\n", - "from rl.memory import SequentialMemory\n", - "from rl.random import OrnsteinUhlenbeckProcess\n", - "\n", - "# We configure and compile our agent.\n", - "\n", - "# We are providing the last 50 steps so we don't need memory, use window_lenght=1 as placeholder\n", - "memory = SequentialMemory(limit=100000, window_length=1)\n", - "\n", - "random_process = OrnsteinUhlenbeckProcess(\n", - " size=nb_actions, theta=.15, mu=0., sigma=.1)\n", - "\n", - "agent = DDPGAgent(\n", - " nb_actions=nb_actions,\n", - " actor=actor,\n", - " critic=critic,\n", - " critic_action_input=action_input,\n", - " random_process=random_process,\n", - " memory=memory,\n", - " batch_size=batch_size,\n", - " nb_steps_warmup_critic=150,\n", - " nb_steps_warmup_actor=150, \n", - " gamma=.00, # discounted factor of zero as per paper\n", - " target_model_update=1e-3\n", - ")\n", - "\n", - "# agent.compile(Adam(lr=3e-5), metrics=['mse'])\n", - "# agent.compile(Adam(lr=1e-3), metrics=['mse'])\n", - "agent.compile(Adam(lr=.001, clipnorm=1.), metrics=['mae'])\n", - "agent" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:06:00.585378Z", - "start_time": "2017-07-23T14:06:00.562162+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Train" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:57.647349Z", - "start_time": "2017-07-23T14:09:57.621300+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "from src.callbacks.keras_rl_callbacks import TrainIntervalLoggerTQDMNotebook" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:57.675197Z", - "start_time": "2017-07-23T14:09:57.649151+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "def sharpe(returns, freq=30, rfr=0):\n", - " \"\"\"Given a set of returns, calculates naive (rfr=0) sharpe (eq 28) \"\"\"\n", - " return (np.sqrt(freq) * np.mean(returns-rfr)) / np.std(returns - rfr)\n", - "\n", - "\n", - "def MDD(returns):\n", - " \"\"\"Max drawdown.\"\"\"\n", - " peak = returns.max()\n", - " i = returns.argmax()\n", - " trough = returns[returns.argmax():].min()\n", - " return (trough-peak)/trough " - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:57.719372Z", - "start_time": "2017-07-23T14:09:57.676651+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "# # https://github.com/matthiasplappert/keras-rl/blob/master/rl/callbacks.py#L104\n", - "from rl.callbacks import TrainEpisodeLogger\n", - "class TrainEpisodeLoggerPortfolio(TrainEpisodeLogger):\n", - " \"\"\"Print custom stats every episode.\"\"\"\n", - " def __init__(self, log_intv):\n", - " super().__init__()\n", - " self.log_intv=log_intv\n", - " self.episode_metrics={} # custom metrics\n", - " def on_episode_end(self, episode, logs):\n", - " \n", - " # save custom metrics\n", - " df = pd.DataFrame(self.env.infos)\n", - " self.episode_metrics[episode]=dict(\n", - " max_drawdown=MDD(df.portfolio_value), \n", - " sharpe=sharpe(df.rate_of_return), \n", - " accumulated_portfolio_value=df.portfolio_value.iloc[-1],\n", - " mean_market_return=df.mean_market_returns.cumprod().iloc[-1],\n", - " cash_bias=df.weights.apply(lambda x:x[0]).mean()\n", - " )\n", - " \n", - " if episode%self.log_intv==0:\n", - " # print normal metrics\n", - " super().on_episode_end(episode, logs)\n", - " \n", - " # print custom metrics for last N episodes\n", - " df = pd.DataFrame(self.episode_metrics).T[-self.log_intv:] \n", - " for col in df.columns:\n", - " print('{name:25.25s}: {mean: 10.6f} [{min: 10.6f}, {max: 10.6f}]'.format(\n", - " name=df[col].name, \n", - " min=df[col].min(), \n", - " mean=df[col].mean(), \n", - " max=df[col].max(), \n", - " ))\n", - " print('') \n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:57.743581Z", - "start_time": "2017-07-23T14:09:57.720934+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "from rl.callbacks import ModelIntervalCheckpoint\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:09:58.248540Z", - "start_time": "2017-07-23T14:09:57.745131+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "agent.load_weights(save_path)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:52:21.893146Z", - "start_time": "2017-07-23T14:09:58.251708+08:00" - }, - "scrolled": true - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "80614523f9e043e6af2b7e4b618ee89b" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Training for 2000000.0 steps ...\n", - "Training for 2000000.0 steps ...\n", - "Interval 1 (0 steps performed)\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/wassname/.pyenv/versions/3.6.2/envs/jupyter3/lib/python3.6/site-packages/rl/memory.py:29: UserWarning: Not enough entries to sample without replacement. Consider increasing your warm-up phase to avoid oversampling!\n", - " warnings.warn('Not enough entries to sample without replacement. Consider increasing your warm-up phase to avoid oversampling!')\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " 1440/2000000.0: episode: 1, duration: 143.614s, episode steps: 1440, steps per second: 10, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.137 [-0.452, 1.292], mean observation: 0.998 [0.712, 1.470], loss: 0.000000, mean_absolute_error: 0.000081, mean_q: -0.000000\n", - "accumulated_portfolio_val: 1.600968 [ 1.600968, 1.600968]\n", - "cash_bias : 0.055785 [ 0.055785, 0.055785]\n", - "max_drawdown : -0.000012 [ -0.000012, -0.000012]\n", - "mean_market_return : 1.780263 [ 1.780263, 1.780263]\n", - "sharpe : 0.273345 [ 0.273345, 0.273345]\n", - "\n", - "6 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.214 - rate_of_return: 0.000 - cost: 0.000 - steps: 716.060 - cash_bias: 0.084 - mean_market_returns: 1.000\n", - "\n", - "Interval 2 (10000 steps performed)\n", - "Step 14400: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 15840/2000000.0: episode: 11, duration: 154.197s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.113 [-0.389, 1.390], mean observation: 1.003 [0.161, 1.260], loss: 0.000000, mean_absolute_error: 0.000130, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.539844 [ 0.622314, 2.917232]\n", - "cash_bias : 0.074561 [ 0.014525, 0.257970]\n", - "max_drawdown : -0.230909 [ -0.813084, 0.000000]\n", - "mean_market_return : 1.719105 [ 1.100545, 2.756727]\n", - "sharpe : 0.170035 [ -0.203324, 0.573459]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.093 - rate_of_return: 0.000 - cost: 0.000 - steps: 716.700 - cash_bias: 0.056 - mean_market_returns: 1.000\n", - "\n", - "Interval 3 (20000 steps performed)\n", - "Step 28800: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.104 - rate_of_return: 0.000 - cost: 0.000 - steps: 717.340 - cash_bias: 0.052 - mean_market_returns: 1.000\n", - "\n", - "Interval 4 (30000 steps performed)\n", - " 30240/2000000.0: episode: 21, duration: 154.002s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.187 [-0.460, 1.326], mean observation: 1.003 [0.161, 1.260], loss: 0.000000, mean_absolute_error: 0.000123, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.303334 [ 0.682009, 2.673402]\n", - "cash_bias : 0.055810 [ 0.004473, 0.106061]\n", - "max_drawdown : -0.449981 [ -0.967763, 0.000000]\n", - "mean_market_return : 1.385010 [ 0.537077, 2.168017]\n", - "sharpe : 0.068808 [ -0.176271, 0.403347]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.156 - rate_of_return: 0.000 - cost: 0.000 - steps: 717.980 - cash_bias: 0.065 - mean_market_returns: 1.000\n", - "\n", - "Interval 5 (40000 steps performed)\n", - "Step 43200: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 44640/2000000.0: episode: 31, duration: 154.952s, episode steps: 1440, steps per second: 9, episode reward: 0.001, mean reward: 0.000 [-0.000, 0.000], mean action: 0.217 [-0.370, 1.275], mean observation: 1.001 [0.738, 1.354], loss: 0.000000, mean_absolute_error: 0.000142, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.604728 [ 0.511029, 3.275131]\n", - "cash_bias : 0.076309 [ 0.004688, 0.154638]\n", - "max_drawdown : -0.355939 [ -1.156354, -0.006833]\n", - "mean_market_return : 1.550182 [ 0.807060, 2.433348]\n", - "sharpe : 0.168964 [ -0.306043, 0.459239]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.280 - rate_of_return: 0.000 - cost: 0.000 - steps: 718.620 - cash_bias: 0.065 - mean_market_returns: 1.000\n", - "\n", - "Interval 6 (50000 steps performed)\n", - "Step 57600: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 59040/2000000.0: episode: 41, duration: 154.396s, episode steps: 1440, steps per second: 9, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.166 [-0.241, 1.212], mean observation: 1.002 [0.111, 9.148], loss: 0.000000, mean_absolute_error: 0.000163, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.396377 [ 0.738922, 2.132834]\n", - "cash_bias : 0.062510 [ 0.000723, 0.242330]\n", - "max_drawdown : -0.360274 [ -1.024978, 0.000000]\n", - "mean_market_return : 1.229770 [ 0.471575, 2.254023]\n", - "sharpe : 0.141533 [ -0.055206, 0.398683]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.281 - rate_of_return: 0.000 - cost: 0.000 - steps: 719.260 - cash_bias: 0.078 - mean_market_returns: 1.000\n", - "\n", - "Interval 7 (60000 steps performed)\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.000] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.073 - rate_of_return: 0.000 - cost: 0.000 - steps: 719.900 - cash_bias: 0.065 - mean_market_returns: 1.000\n", - "\n", - "Interval 8 (70000 steps performed)\n", - "Step 72000: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 73440/2000000.0: episode: 51, duration: 154.574s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.222 [-0.306, 1.339], mean observation: 0.999 [0.614, 1.391], loss: 0.000000, mean_absolute_error: 0.000128, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.211679 [ 0.565041, 2.903645]\n", - "cash_bias : 0.070392 [ 0.011336, 0.148366]\n", - "max_drawdown : -0.457481 [ -1.260784, -0.014822]\n", - "mean_market_return : 1.467611 [ 0.948525, 2.186975]\n", - "sharpe : 0.025259 [ -0.325438, 0.415408]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.162 - rate_of_return: 0.000 - cost: 0.000 - steps: 720.540 - cash_bias: 0.054 - mean_market_returns: 1.000\n", - "\n", - "Interval 9 (80000 steps performed)\n", - "Step 86400: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 87840/2000000.0: episode: 61, duration: 153.218s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.201 [-0.415, 1.334], mean observation: 1.004 [0.708, 1.263], loss: 0.000000, mean_absolute_error: 0.000126, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.074394 [ 0.670507, 1.952374]\n", - "cash_bias : 0.052440 [ 0.003960, 0.103384]\n", - "max_drawdown : -0.420028 [ -0.677238, -0.136884]\n", - "mean_market_return : 1.496140 [ 1.054715, 2.573308]\n", - "sharpe : 0.033663 [ -0.211394, 0.415850]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.000] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.097 - rate_of_return: 0.000 - cost: 0.000 - steps: 721.180 - cash_bias: 0.055 - mean_market_returns: 1.000\n", - "\n", - "Interval 10 (90000 steps performed)\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.315 - rate_of_return: 0.000 - cost: 0.000 - steps: 721.820 - cash_bias: 0.076 - mean_market_returns: 1.000\n", - "\n", - "Interval 11 (100000 steps performed)\n", - "Step 100800: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 102240/2000000.0: episode: 71, duration: 155.829s, episode steps: 1440, steps per second: 9, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.111 [-0.499, 1.129], mean observation: 1.000 [0.692, 1.309], loss: 0.000000, mean_absolute_error: 0.000127, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.673929 [ 0.681020, 4.329943]\n", - "cash_bias : 0.067520 [ 0.020204, 0.121063]\n", - "max_drawdown : -0.300606 [ -0.682132, -0.008075]\n", - "mean_market_return : 1.714425 [ 0.639027, 2.667930]\n", - "sharpe : 0.155657 [ -0.197428, 0.457547]\n", - "\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.304 - rate_of_return: 0.000 - cost: 0.000 - steps: 722.460 - cash_bias: 0.078 - mean_market_returns: 1.000\n", - "\n", - "Interval 12 (110000 steps performed)\n", - "Step 115200: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 116640/2000000.0: episode: 81, duration: 157.071s, episode steps: 1440, steps per second: 9, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.122 [-0.510, 1.223], mean observation: 1.001 [0.766, 1.257], loss: 0.000000, mean_absolute_error: 0.000114, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.650479 [ 0.902475, 3.011151]\n", - "cash_bias : 0.055152 [ 0.008750, 0.161314]\n", - "max_drawdown : -0.231918 [ -0.710915, -0.009612]\n", - "mean_market_return : 1.664031 [ 1.137732, 2.347613]\n", - "sharpe : 0.187749 [ -0.040975, 0.570228]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.001, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.324 - rate_of_return: 0.000 - cost: 0.000 - steps: 723.100 - cash_bias: 0.049 - mean_market_returns: 1.000\n", - "\n", - "Interval 13 (120000 steps performed)\n", - "Step 129600: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - "7 episodes - episode_reward: 0.000 [-0.001, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.127 - rate_of_return: 0.000 - cost: 0.000 - steps: 723.740 - cash_bias: 0.044 - mean_market_returns: 1.000\n", - "\n", - "Interval 14 (130000 steps performed)\n", - " 131040/2000000.0: episode: 91, duration: 155.738s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.175 [-0.302, 1.153], mean observation: 1.000 [0.671, 1.591], loss: 0.000000, mean_absolute_error: 0.000127, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.409520 [ 0.324324, 3.522805]\n", - "cash_bias : 0.060188 [ 0.008142, 0.155611]\n", - "max_drawdown : -0.687866 [ -2.231040, -0.055638]\n", - "mean_market_return : 1.410228 [ 0.464480, 1.948426]\n", - "sharpe : 0.032007 [ -0.561108, 0.474860]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.076 - rate_of_return: 0.000 - cost: 0.000 - steps: 724.380 - cash_bias: 0.059 - mean_market_returns: 1.000\n", - "\n", - "Interval 15 (140000 steps performed)\n", - "Step 144000: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 145440/2000000.0: episode: 101, duration: 154.628s, episode steps: 1440, steps per second: 9, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.111 [-0.511, 1.415], mean observation: 0.997 [0.701, 1.309], loss: 0.000000, mean_absolute_error: 0.000120, mean_q: -0.000000\n", - "accumulated_portfolio_val: 1.592295 [ 0.912033, 3.716879]\n", - "cash_bias : 0.050177 [ 0.016184, 0.150076]\n", - "max_drawdown : -0.173310 [ -0.437019, -0.008034]\n", - "mean_market_return : 1.621685 [ 0.968087, 2.332413]\n", - "sharpe : 0.165663 [ -0.034720, 0.453113]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.266 - rate_of_return: 0.000 - cost: 0.000 - steps: 725.020 - cash_bias: 0.051 - mean_market_returns: 1.000\n", - "\n", - "Interval 16 (150000 steps performed)\n", - "Step 158400: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 159840/2000000.0: episode: 111, duration: 156.475s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.209 [-0.426, 1.412], mean observation: 1.001 [0.655, 1.391], loss: 0.000000, mean_absolute_error: 0.000118, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.103944 [ 0.483277, 2.266302]\n", - "cash_bias : 0.063553 [ 0.005678, 0.130800]\n", - "max_drawdown : -0.682551 [ -1.501750, -0.023903]\n", - "mean_market_return : 1.417357 [ 0.712143, 2.464358]\n", - "sharpe : 0.040257 [ -0.295146, 0.401358]\n", - "\n", - "7 episodes - episode_reward: -0.000 [-0.001, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: -0.000 - log_return: -0.000 - portfolio_value: 1.032 - rate_of_return: -0.000 - cost: 0.000 - steps: 725.660 - cash_bias: 0.061 - mean_market_returns: 1.000\n", - "\n", - "Interval 17 (160000 steps performed)\n", - "7 episodes - episode_reward: 0.000 [-0.001, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.118 - rate_of_return: 0.000 - cost: 0.000 - steps: 726.300 - cash_bias: 0.094 - mean_market_returns: 1.000\n", - "\n", - "Interval 18 (170000 steps performed)\n", - "Step 172800: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 174240/2000000.0: episode: 121, duration: 155.632s, episode steps: 1440, steps per second: 9, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.201 [-0.364, 1.224], mean observation: 1.004 [0.708, 1.300], loss: 0.000000, mean_absolute_error: 0.000126, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.361429 [ 0.415500, 3.049772]\n", - "cash_bias : 0.087971 [ 0.004965, 0.176772]\n", - "max_drawdown : -0.563874 [ -1.683407, -0.144767]\n", - "mean_market_return : 1.438910 [ 0.709600, 2.517806]\n", - "sharpe : 0.056662 [ -0.510887, 0.508393]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.280 - rate_of_return: 0.000 - cost: 0.000 - steps: 726.940 - cash_bias: 0.043 - mean_market_returns: 1.000\n", - "\n", - "Interval 19 (180000 steps performed)\n", - "Step 187200: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 188640/2000000.0: episode: 131, duration: 157.390s, episode steps: 1440, steps per second: 9, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.245 [-0.317, 1.364], mean observation: 1.000 [0.689, 1.290], loss: 0.000000, mean_absolute_error: 0.000134, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.479307 [ 0.813746, 2.443175]\n", - "cash_bias : 0.065195 [ 0.000871, 0.131656]\n", - "max_drawdown : -0.188725 [ -0.613543, -0.030680]\n", - "mean_market_return : 1.727947 [ 1.220552, 2.664248]\n", - "sharpe : 0.168444 [ -0.067438, 0.370268]\n", - "\n", - "6 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.154 - rate_of_return: 0.000 - cost: 0.000 - steps: 716.060 - cash_bias: 0.097 - mean_market_returns: 1.000\n", - "\n", - "Interval 20 (190000 steps performed)\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.000] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.095 - rate_of_return: 0.000 - cost: 0.000 - steps: 716.700 - cash_bias: 0.043 - mean_market_returns: 1.000\n", - "\n", - "Interval 21 (200000 steps performed)\n", - "Step 201600: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 203040/2000000.0: episode: 141, duration: 159.819s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.233 [-0.343, 1.422], mean observation: 1.005 [0.768, 1.593], loss: 0.000000, mean_absolute_error: 0.000116, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.018124 [ 0.786996, 1.276695]\n", - "cash_bias : 0.072116 [ 0.001237, 0.181439]\n", - "max_drawdown : -0.461058 [ -0.692068, -0.160085]\n", - "mean_market_return : 1.296681 [ 0.818533, 1.673034]\n", - "sharpe : 0.020294 [ -0.133181, 0.127568]\n", - "\n", - "7 episodes - episode_reward: -0.000 [-0.001, 0.000] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: -0.000 - log_return: -0.000 - portfolio_value: 0.891 - rate_of_return: -0.000 - cost: 0.000 - steps: 717.340 - cash_bias: 0.092 - mean_market_returns: 1.000\n", - "\n", - "Interval 22 (210000 steps performed)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Step 216000: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 217440/2000000.0: episode: 151, duration: 156.252s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.157 [-0.427, 1.438], mean observation: 1.000 [0.692, 1.309], loss: 0.000000, mean_absolute_error: 0.000115, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.008778 [ 0.380107, 1.715898]\n", - "cash_bias : 0.050137 [ 0.008341, 0.111793]\n", - "max_drawdown : -0.679917 [ -1.988953, -0.018552]\n", - "mean_market_return : 1.369305 [ 0.479848, 2.661585]\n", - "sharpe : 0.003775 [ -0.469765, 0.310177]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.218 - rate_of_return: 0.000 - cost: 0.000 - steps: 717.980 - cash_bias: 0.028 - mean_market_returns: 1.000\n", - "\n", - "Interval 23 (220000 steps performed)\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.000] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.088 - rate_of_return: 0.000 - cost: 0.000 - steps: 718.620 - cash_bias: 0.038 - mean_market_returns: 1.000\n", - "\n", - "Interval 24 (230000 steps performed)\n", - "Step 230400: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 231840/2000000.0: episode: 161, duration: 158.206s, episode steps: 1440, steps per second: 9, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.192 [-0.238, 1.314], mean observation: 1.004 [0.814, 1.204], loss: 0.000000, mean_absolute_error: 0.000097, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.329853 [ 0.825072, 2.817980]\n", - "cash_bias : 0.037348 [ 0.010543, 0.072086]\n", - "max_drawdown : -0.313557 [ -0.987901, 0.000000]\n", - "mean_market_return : 1.519909 [ 0.962282, 1.932404]\n", - "sharpe : 0.120740 [ -0.091849, 0.544711]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.237 - rate_of_return: 0.000 - cost: 0.000 - steps: 719.260 - cash_bias: 0.076 - mean_market_returns: 1.000\n", - "\n", - "Interval 25 (240000 steps performed)\n", - "Step 244800: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 246240/2000000.0: episode: 171, duration: 157.616s, episode steps: 1440, steps per second: 9, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.174 [-0.351, 1.287], mean observation: 1.005 [0.772, 1.171], loss: 0.000000, mean_absolute_error: 0.000113, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.743917 [ 0.686582, 3.563962]\n", - "cash_bias : 0.071791 [ 0.019372, 0.137682]\n", - "max_drawdown : -0.253929 [ -0.559316, 0.000000]\n", - "mean_market_return : 1.616138 [ 1.206802, 2.228054]\n", - "sharpe : 0.194453 [ -0.150149, 0.442472]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.244 - rate_of_return: 0.000 - cost: 0.000 - steps: 719.900 - cash_bias: 0.050 - mean_market_returns: 1.000\n", - "\n", - "Interval 26 (250000 steps performed)\n", - "Step 259200: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.199 - rate_of_return: 0.000 - cost: 0.000 - steps: 720.540 - cash_bias: 0.057 - mean_market_returns: 1.000\n", - "\n", - "Interval 27 (260000 steps performed)\n", - " 260640/2000000.0: episode: 181, duration: 159.232s, episode steps: 1440, steps per second: 9, episode reward: 0.001, mean reward: 0.000 [-0.000, 0.000], mean action: 0.177 [-0.388, 1.276], mean observation: 1.000 [0.652, 2.192], loss: 0.000000, mean_absolute_error: 0.000107, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.472506 [ 0.751669, 2.549381]\n", - "cash_bias : 0.049667 [ 0.003039, 0.108212]\n", - "max_drawdown : -0.331184 [ -0.656806, -0.000001]\n", - "mean_market_return : 1.549285 [ 0.913344, 2.250838]\n", - "sharpe : 0.153389 [ -0.129913, 0.479462]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: -0.000 - log_return: -0.000 - portfolio_value: 1.095 - rate_of_return: -0.000 - cost: 0.000 - steps: 721.180 - cash_bias: 0.056 - mean_market_returns: 1.000\n", - "\n", - "Interval 28 (270000 steps performed)\n", - "Step 273600: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 275040/2000000.0: episode: 191, duration: 135.114s, episode steps: 1440, steps per second: 11, episode reward: 0.001, mean reward: 0.000 [-0.000, 0.000], mean action: 0.196 [-0.325, 1.386], mean observation: 1.002 [0.834, 1.246], loss: 0.000000, mean_absolute_error: 0.000117, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.249325 [ 0.622860, 2.376732]\n", - "cash_bias : 0.052889 [ 0.007575, 0.127946]\n", - "max_drawdown : -0.348863 [ -0.625319, -0.016888]\n", - "mean_market_return : 1.470290 [ 0.980053, 2.360734]\n", - "sharpe : 0.076793 [ -0.218348, 0.417442]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.001, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.464 - rate_of_return: 0.000 - cost: 0.000 - steps: 721.820 - cash_bias: 0.050 - mean_market_returns: 1.000\n", - "\n", - "Interval 29 (280000 steps performed)\n", - "Step 288000: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 289440/2000000.0: episode: 201, duration: 136.367s, episode steps: 1440, steps per second: 11, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.051 [-0.551, 1.157], mean observation: 1.003 [0.859, 1.200], loss: 0.000000, mean_absolute_error: 0.000153, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.414417 [ 0.362143, 4.669730]\n", - "cash_bias : 0.060956 [ 0.001686, 0.145878]\n", - "max_drawdown : -0.650344 [ -2.284013, -0.006901]\n", - "mean_market_return : 1.478695 [ 0.844839, 2.160411]\n", - "sharpe : 0.061478 [ -0.230779, 0.446756]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.088 - rate_of_return: 0.000 - cost: 0.000 - steps: 722.460 - cash_bias: 0.057 - mean_market_returns: 1.000\n", - "\n", - "Interval 30 (290000 steps performed)\n", - "7 episodes - episode_reward: 0.000 [0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.347 - rate_of_return: 0.000 - cost: 0.000 - steps: 723.100 - cash_bias: 0.059 - mean_market_returns: 1.000\n", - "\n", - "Interval 31 (300000 steps performed)\n", - "Step 302400: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 303840/2000000.0: episode: 211, duration: 135.879s, episode steps: 1440, steps per second: 11, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.111 [-0.468, 1.377], mean observation: 1.001 [0.634, 1.520], loss: 0.000000, mean_absolute_error: 0.000111, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.849086 [ 0.977056, 4.642528]\n", - "cash_bias : 0.042548 [ 0.003128, 0.106676]\n", - "max_drawdown : -0.131930 [ -0.323132, -0.004361]\n", - "mean_market_return : 1.758276 [ 1.078446, 2.407408]\n", - "sharpe : 0.248120 [ 0.003693, 0.680368]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.128 - rate_of_return: 0.000 - cost: 0.000 - steps: 723.740 - cash_bias: 0.056 - mean_market_returns: 1.000\n", - "\n", - "Interval 32 (310000 steps performed)\n", - "Step 316800: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 318240/2000000.0: episode: 221, duration: 136.107s, episode steps: 1440, steps per second: 11, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.191 [-0.318, 1.400], mean observation: 0.998 [0.643, 1.194], loss: 0.000000, mean_absolute_error: 0.000105, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.500064 [ 0.816088, 2.653919]\n", - "cash_bias : 0.065018 [ 0.008605, 0.132558]\n", - "max_drawdown : -0.144981 [ -0.420598, -0.001803]\n", - "mean_market_return : 1.659575 [ 0.964269, 2.112969]\n", - "sharpe : 0.148274 [ -0.083965, 0.432461]\n", - "\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.181 - rate_of_return: 0.000 - cost: 0.000 - steps: 724.380 - cash_bias: 0.039 - mean_market_returns: 1.000\n", - "\n", - "Interval 33 (320000 steps performed)\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.397 - rate_of_return: 0.000 - cost: 0.000 - steps: 725.020 - cash_bias: 0.091 - mean_market_returns: 1.000\n", - "\n", - "Interval 34 (330000 steps performed)\n", - "Step 331200: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 332640/2000000.0: episode: 231, duration: 135.652s, episode steps: 1440, steps per second: 11, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.103 [-0.464, 1.124], mean observation: 1.001 [0.161, 1.203], loss: 0.000000, mean_absolute_error: 0.000115, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.611326 [ 0.721930, 3.470525]\n", - "cash_bias : 0.065767 [ 0.002808, 0.181059]\n", - "max_drawdown : -0.244778 [ -0.754503, -0.007988]\n", - "mean_market_return : 1.827194 [ 1.056890, 2.886001]\n", - "sharpe : 0.210246 [ -0.129261, 0.691669]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.000] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.085 - rate_of_return: 0.000 - cost: 0.000 - steps: 725.660 - cash_bias: 0.055 - mean_market_returns: 1.000\n", - "\n", - "Interval 35 (340000 steps performed)\n", - "Step 345600: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 347040/2000000.0: episode: 241, duration: 136.275s, episode steps: 1440, steps per second: 11, episode reward: -0.000, mean reward: -0.000 [-0.000, 0.000], mean action: 0.267 [-0.341, 1.438], mean observation: 1.004 [0.456, 2.151], loss: 0.000000, mean_absolute_error: 0.000124, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.042703 [ 0.724236, 1.446073]\n", - "cash_bias : 0.068539 [ 0.006466, 0.140450]\n", - "max_drawdown : -0.375756 [ -0.785553, -0.084511]\n", - "mean_market_return : 1.348965 [ 0.926066, 1.990632]\n", - "sharpe : 0.038176 [ -0.153207, 0.228258]\n", - "\n", - "7 episodes - episode_reward: -0.000 [-0.000, 0.000] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: -0.000 - log_return: -0.000 - portfolio_value: 1.015 - rate_of_return: 0.000 - cost: 0.000 - steps: 726.300 - cash_bias: 0.063 - mean_market_returns: 1.000\n", - "\n", - "Interval 36 (350000 steps performed)\n", - "Step 360000: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.387 - rate_of_return: 0.000 - cost: 0.000 - steps: 726.940 - cash_bias: 0.039 - mean_market_returns: 1.000\n", - "\n", - "Interval 37 (360000 steps performed)\n", - " 361440/2000000.0: episode: 251, duration: 140.229s, episode steps: 1440, steps per second: 10, episode reward: 0.001, mean reward: 0.000 [-0.000, 0.000], mean action: 0.135 [-0.399, 1.126], mean observation: 0.997 [0.546, 1.568], loss: 0.000000, mean_absolute_error: 0.000099, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.966579 [ 0.752484, 4.885108]\n", - "cash_bias : 0.050940 [ 0.009163, 0.182570]\n", - "max_drawdown : -0.333823 [ -0.716804, 0.000000]\n", - "mean_market_return : 1.759869 [ 1.010219, 2.592356]\n", - "sharpe : 0.165852 [ -0.157039, 0.536761]\n", - "\n", - "6 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.177 - rate_of_return: 0.000 - cost: 0.000 - steps: 716.060 - cash_bias: 0.049 - mean_market_returns: 1.000\n", - "\n", - "Interval 38 (370000 steps performed)\n", - "Step 374400: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 375840/2000000.0: episode: 261, duration: 144.367s, episode steps: 1440, steps per second: 10, episode reward: 0.001, mean reward: 0.000 [-0.000, 0.000], mean action: 0.191 [-0.396, 1.224], mean observation: 0.999 [0.643, 1.187], loss: 0.000000, mean_absolute_error: 0.000125, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.288407 [ 0.680923, 2.716030]\n", - "cash_bias : 0.052354 [ 0.001191, 0.139005]\n", - "max_drawdown : -0.418257 [ -0.764209, -0.041547]\n", - "mean_market_return : 1.341903 [ 0.856950, 2.055648]\n", - "sharpe : 0.065753 [ -0.232462, 0.390146]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.232 - rate_of_return: 0.000 - cost: 0.000 - steps: 716.700 - cash_bias: 0.066 - mean_market_returns: 1.000\n", - "\n", - "Interval 39 (380000 steps performed)\n", - "Step 388800: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - "7 episodes - episode_reward: 0.000 [-0.001, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.303 - rate_of_return: 0.000 - cost: 0.000 - steps: 717.340 - cash_bias: 0.036 - mean_market_returns: 1.000\n", - "\n", - "Interval 40 (390000 steps performed)\n", - " 390240/2000000.0: episode: 271, duration: 143.942s, episode steps: 1440, steps per second: 10, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.108 [-0.641, 1.264], mean observation: 1.002 [0.755, 1.263], loss: 0.000000, mean_absolute_error: 0.000112, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.723811 [ 0.385201, 5.610942]\n", - "cash_bias : 0.043433 [ 0.004003, 0.142150]\n", - "max_drawdown : -0.392580 [ -1.715767, 0.000000]\n", - "mean_market_return : 1.501531 [ 1.032789, 2.309168]\n", - "sharpe : 0.151012 [ -0.542208, 0.692122]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.361 - rate_of_return: 0.000 - cost: 0.000 - steps: 717.980 - cash_bias: 0.080 - mean_market_returns: 1.000\n", - "\n", - "Interval 41 (400000 steps performed)\n", - "Step 403200: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 404640/2000000.0: episode: 281, duration: 144.895s, episode steps: 1440, steps per second: 10, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.226 [-0.214, 1.242], mean observation: 1.004 [0.772, 1.171], loss: 0.000000, mean_absolute_error: 0.000143, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.513728 [ 0.808378, 2.553611]\n", - "cash_bias : 0.103367 [ 0.017398, 0.242475]\n", - "max_drawdown : -0.271351 [ -0.732514, 0.000000]\n", - "mean_market_return : 1.460818 [ 0.623337, 2.060393]\n", - "sharpe : 0.178757 [ -0.062625, 0.509070]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.000] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.137 - rate_of_return: 0.000 - cost: 0.000 - steps: 718.620 - cash_bias: 0.105 - mean_market_returns: 1.000\n", - "\n", - "Interval 42 (410000 steps performed)\n", - "Step 417600: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 419040/2000000.0: episode: 291, duration: 151.489s, episode steps: 1440, steps per second: 10, episode reward: 0.001, mean reward: 0.000 [-0.000, 0.000], mean action: 0.266 [-0.341, 1.448], mean observation: 1.000 [0.546, 1.568], loss: 0.000000, mean_absolute_error: 0.000112, mean_q: 0.000000\n", - "accumulated_portfolio_val: 1.669312 [ 0.501814, 3.970696]\n", - "cash_bias : 0.066472 [ 0.009597, 0.106474]\n", - "max_drawdown : -0.258452 [ -1.146341, -0.020658]\n", - "mean_market_return : 1.457950 [ 0.497242, 2.334777]\n", - "sharpe : 0.167086 [ -0.334699, 0.443108]\n", - "\n", - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.254 - rate_of_return: 0.000 - cost: 0.000 - steps: 719.260 - cash_bias: 0.061 - mean_market_returns: 1.000\n", - "\n", - "Interval 43 (420000 steps performed)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "7 episodes - episode_reward: 0.000 [-0.000, 0.001] - loss: 0.000 - mean_absolute_error: 0.000 - mean_q: 0.000 - reward: 0.000 - log_return: 0.000 - portfolio_value: 1.350 - rate_of_return: 0.000 - cost: 0.000 - steps: 719.900 - cash_bias: 0.030 - mean_market_returns: 1.000\n", - "\n", - "Interval 44 (430000 steps performed)\n", - "Step 432000: saving model to outputs/agent_portfolio-ddpg-keras/2017-07-21__weights.h5f\n", - " 433440/2000000.0: episode: 301, duration: 159.085s, episode steps: 1440, steps per second: 9, episode reward: 0.000, mean reward: 0.000 [-0.000, 0.000], mean action: 0.116 [-0.322, 1.201], mean observation: 1.004 [0.763, 1.483], loss: 0.000000, mean_absolute_error: 0.000104, mean_q: -0.000000\n", - "accumulated_portfolio_val: 1.528060 [ 0.945644, 2.593394]\n", - "cash_bias : 0.035942 [ 0.010315, 0.072050]\n", - "max_drawdown : -0.272870 [ -0.945046, 0.000000]\n", - "mean_market_return : 1.671359 [ 1.310089, 2.087434]\n", - "sharpe : 0.186077 [ 0.007315, 0.381425]\n", - "\n" - ] - } - ], - "source": [ - "history = agent.fit(env, \n", - " nb_steps=2e6, \n", - " visualize=False, \n", - " verbose=0,\n", - " callbacks=[\n", - " TrainIntervalLoggerTQDMNotebook(),\n", - " TrainEpisodeLoggerPortfolio(10),\n", - " ModelIntervalCheckpoint(save_path, 10*1440, 1)\n", - " ]\n", - " )\n", - "\n", - "# After training is done, we save the final weights.\n", - "agent.save_weights(save_path, overwrite=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "start_time": "2017-07-17T00:08:54.105Z" - }, - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-23T06:52:22.264835Z", - "start_time": "2017-07-23T14:52:21.895982+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [ - "agent.save_weights('outputs/agent_portfolio-ddpg-keras/agent_{}_weights.h5f'.format('portfolio-ddpg-keras-rl'), overwrite=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Test" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": { - "ExecuteTime": { - "start_time": "2017-07-23T06:09:37.800Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Testing for 1 episodes ...\n", - "Episode 1: reward: 0.001, steps: 7613\n", - "APV (Accumulated portfolio value): \t 181.388076\n", - "SR (Sharpe ratio): \t 0.262592\n", - "MDD (max drawdown): \t-37.740168%\n", - "MDR (mean_market_return): \t 27.985419\n", - "\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\nVVURCAT44IMP6O7upry8nK9//ev4/X4aGxt5+eWX8fl8TJ069aztt27dyq9//WuMMeTl5bF06VJK\nS0t54oknqKqq4s4776S5uZnvf//7PPXUUxQUFKTpmYqMbTpDFhlDDh8+zCOPPMKzzz5Lb28vv/3t\nb+nr62Pjxo089NBDfOtb32LixImDv79v3z527NjB2rVr+fa3v81tt93GM888g23bPPDAA+zYsYM9\ne/awceNGHnzwQYWxyAjSGbLIGHLVVVfh9XoBmDRpEsFgkNbWViorK6moqADg5ptv5qc//SkAv//9\n7+ns7GT16tWD+wgGgwSDQcaPH88999zD008/zZe+9KXBpUJFZGQokEXGEJ/PN/i9ZVkYYwa//oVt\nn+kYc12Xuro67rzzzsHbvb29gyuPtbW1MW7cOA4cOJCiZyDy2aUua5Exrrq6mra2Nt5//30Atm/f\nPnjfrFmz2L17N729vQC8+eabrF27FoADBw7Q0NDAU089xcDAAA0NDakuXeQzRWfIImNcfn4+Dz74\nIM899xyO45y1zOfVV1/NF7/4RZ544gksyyIQCLBy5UrC4TDr169n6dKlFBYWct999/HII49QXV3N\npZdemsZnIzJ2abUnERGRDKAuaxERkQygQBYREckACmQREZEMoEAWERHJAApkERGRDKBAFhERyQAK\nZBERkQzwf/nLg/lJ0dUGAAAAAElFTkSuQmCC\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# one big test\n", - "df_test = pd.read_hdf('./data/poloniex_30m.hf',key='test')\n", - "steps=len(df_test)-window_length-2\n", - "env_test = PortfolioEnv(\n", - " df=df_test,\n", - " steps=steps, \n", - " scale=True, \n", - " augment=0.00,\n", - " trading_cost=0, # let just overfit first\n", - " window_length=window_length,\n", - ")\n", - "env_test.seed = 0 \n", - "agent.test(env_test, nb_episodes=1, visualize=False)\n", - "\n", - "df = pd.DataFrame(env_test.infos)\n", - "df.index=df['index']\n", - "\n", - "s=sharpe(df.rate_of_return)\n", - "mdd=MDD(df.rate_of_return+1)\n", - "mean_market_return=df.mean_market_returns.cumprod().iloc[-1]\n", - "print('APV (Accumulated portfolio value): \\t{: 2.6f}'.format(df.portfolio_value.iloc[-1]))\n", - "print('SR (Sharpe ratio): \\t{: 2.6f}'.format( s))\n", - "print('MDD (max drawdown): \\t{: 2.6%}'.format( mdd))\n", - "print('MDR (mean_market_return): \\t{: 2.6f}'.format( mean_market_return))\n", - "print('')\n", - "\n", - "# show one run vs average market performance\n", - "df.portfolio_value.plot()\n", - "df.mean_market_returns.cumprod().plot(label='mean market performance')\n", - "plt.legend()\n", - "plt.title('test')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "start_time": "2017-07-23T06:09:37.802Z" - }, - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "index\n", - "2017-02-04 08:00:00 [1.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", - "2017-02-04 08:30:00 [0.00731654, 0.0315146, 0.938596, 0.00170927, ...\n", - "2017-02-04 09:00:00 [0.0190743, 0.0924498, 0.860992, 0.00979124, 0...\n", - "2017-02-04 09:30:00 [0.0421061, 0.105747, 0.763996, 0.0302245, 0.0...\n", - "2017-02-04 10:00:00 [0.0448445, 0.204392, 0.676664, 0.0264077, 0.0...\n", - "2017-02-04 10:30:00 [0.0150724, 0.0820092, 0.88418, 0.00701311, 0....\n", - "2017-02-04 11:00:00 [0.0027137, 0.00291277, 0.985919, 0.000439721,...\n", - "2017-02-04 11:30:00 [0.00245529, 0.00190385, 0.988684, 0.000299987...\n", - "2017-02-04 12:00:00 [0.012495, 0.0137654, 0.960403, 0.00298369, 0....\n", - "2017-02-04 12:30:00 [0.00887985, 0.0155681, 0.96558, 0.00264909, 0...\n", - "2017-02-04 13:00:00 [0.00138628, 0.000568855, 0.993987, 0.00014884...\n", - "2017-02-04 13:30:00 [0.00226571, 0.000596184, 0.989777, 0.00020279...\n", - "2017-02-04 14:00:00 [0.00510076, 0.0015662, 0.986997, 0.000913473,...\n", - "2017-02-04 14:30:00 [0.00499729, 0.000891129, 0.987513, 0.00079913...\n", - "2017-02-04 15:00:00 [0.00330657, 0.000744253, 0.984008, 0.00028483...\n", - "2017-02-04 15:30:00 [0.00504244, 0.00122503, 0.987346, 0.000861437...\n", - "2017-02-04 16:00:00 [0.00603806, 0.00176427, 0.983644, 0.00136241,...\n", - "2017-02-04 16:30:00 [0.00593073, 0.000980955, 0.983497, 0.00140895...\n", - "2017-02-04 17:00:00 [0.000978927, 5.34819e-05, 0.993371, 0.0001104...\n", - "2017-02-04 17:30:00 [0.000725933, 5.55188e-05, 0.995633, 9.02455e-...\n", - "2017-02-04 18:00:00 [0.00872449, 0.000740199, 0.964367, 0.00267535...\n", - "2017-02-04 18:30:00 [0.00294096, 8.40652e-05, 0.955607, 0.00052685...\n", - "2017-02-04 19:00:00 [0.00985842, 0.000853293, 0.946365, 0.00487395...\n", - "2017-02-04 19:30:00 [0.0455507, 0.00943991, 0.733956, 0.0260412, 0...\n", - "2017-02-04 20:00:00 [0.025255, 0.00212726, 0.828345, 0.0147995, 0....\n", - "2017-02-04 20:30:00 [0.00647224, 0.000479825, 0.918104, 0.00187611...\n", - "2017-02-04 21:00:00 [0.0111161, 0.00208928, 0.85762, 0.00476126, 0...\n", - "2017-02-04 21:30:00 [0.0554502, 0.0212292, 0.68057, 0.0461252, 0.0...\n", - "2017-02-04 22:00:00 [0.0753337, 0.0136912, 0.279902, 0.0709583, 0....\n", - "2017-02-04 22:30:00 [0.0735958, 0.0143229, 0.210053, 0.0655913, 0....\n", - " ... \n", - "2017-07-12 08:00:00 [0.0464826, 0.0128792, 0.567349, 0.00320219, 0...\n", - "2017-07-12 08:30:00 [0.00480704, 0.0107518, 0.97509, 0.00054515, 0...\n", - "2017-07-12 09:00:00 [0.0549109, 0.281625, 0.5499, 0.00573582, 0.02...\n", - "2017-07-12 09:30:00 [0.0701595, 0.256289, 0.454629, 0.0069373, 0.0...\n", - "2017-07-12 10:00:00 [0.0427816, 0.262798, 0.610358, 0.0050467, 0.0...\n", - "2017-07-12 10:30:00 [0.0210472, 0.207191, 0.730192, 0.00313533, 0....\n", - "2017-07-12 11:00:00 [0.00715757, 0.255563, 0.72485, 0.00231116, 0....\n", - "2017-07-12 11:30:00 [0.00732216, 0.278683, 0.700266, 0.00239698, 0...\n", - "2017-07-12 12:00:00 [0.00813648, 0.225097, 0.748938, 0.00273538, 0...\n", - "2017-07-12 12:30:00 [0.0269593, 0.125067, 0.777279, 0.00401272, 0....\n", - "2017-07-12 13:00:00 [0.013617, 0.121467, 0.833315, 0.00310375, 0.0...\n", - "2017-07-12 13:30:00 [0.0202058, 0.311773, 0.614919, 0.00628584, 0....\n", - "2017-07-12 14:00:00 [0.00724599, 0.247221, 0.725231, 0.00340057, 0...\n", - "2017-07-12 14:30:00 [0.011975, 0.422717, 0.543636, 0.00629002, 0.0...\n", - "2017-07-12 15:00:00 [0.00839538, 0.341551, 0.630233, 0.00339231, 0...\n", - "2017-07-12 15:30:00 [0.00763729, 0.409559, 0.563893, 0.00333864, 0...\n", - "2017-07-12 16:00:00 [0.00696272, 0.537374, 0.438245, 0.00325246, 0...\n", - "2017-07-12 16:30:00 [0.0023179, 0.602593, 0.386511, 0.00192056, 0....\n", - "2017-07-12 17:00:00 [0.00254063, 0.588255, 0.3998, 0.00209618, 0.0...\n", - "2017-07-12 17:30:00 [0.00296629, 0.715932, 0.268701, 0.00260783, 0...\n", - "2017-07-12 18:00:00 [0.00353033, 0.63522, 0.345774, 0.00326517, 0....\n", - "2017-07-12 18:30:00 [0.00279263, 0.690789, 0.294142, 0.00292665, 0...\n", - "2017-07-12 19:00:00 [0.00324621, 0.732645, 0.249484, 0.00356719, 0...\n", - "2017-07-12 19:30:00 [0.00530687, 0.658937, 0.309459, 0.0069109, 0....\n", - "2017-07-12 20:00:00 [0.004208, 0.334593, 0.640531, 0.00427205, 0.0...\n", - "2017-07-12 20:30:00 [0.00221838, 0.174532, 0.813577, 0.00175312, 0...\n", - "2017-07-12 21:00:00 [0.00405832, 0.291364, 0.685039, 0.00356134, 0...\n", - "2017-07-12 21:30:00 [0.00742337, 0.284458, 0.669148, 0.00608201, 0...\n", - "2017-07-12 22:00:00 [0.00949846, 0.363878, 0.574979, 0.00715907, 0...\n", - "2017-07-12 22:30:00 [0.00822912, 0.277757, 0.671306, 0.00718993, 0...\n", - "Name: weights, Length: 7614, dtype: object" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# The weights appear to be static, so the model hasn't learnt much :(\n", - "df = pd.DataFrame(env_test.infos)\n", - "df.index=df['index']\n", - "df.weights" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Testing for 1 episodes ...\n" - ] - } - ], - "source": [ - "# on the training interval\n", - "df_test = pd.read_hdf('./data/poloniex_30m.hf',key='train')\n", - "steps=len(df_test)-window_length-2\n", - "env_test = PortfolioEnv(\n", - " df=df_test,\n", - " steps=steps, \n", - " scale=True, \n", - " augment=0.00,\n", - " trading_cost=0, # let just overfit first\n", - " window_length=window_length,\n", - ")\n", - "env_test.seed = 0 \n", - "agent.test(env_test, nb_episodes=1, visualize=False)\n", - "\n", - "df = pd.DataFrame(env_test.infos)\n", - "df.index=df['index']\n", - "\n", - "s=sharpe(df.rate_of_return)\n", - "mdd=MDD(df.rate_of_return+1)\n", - "mean_market_return=df.mean_market_returns.cumprod().iloc[-1]\n", - "print('APV (Accumulated portfolio value): \\t{: 2.6f}'.format(df.portfolio_value.iloc[-1]))\n", - "print('SR (Sharpe ratio): \\t{: 2.6f}'.format( s))\n", - "print('MDD (max drawdown): \\t{: 2.6%}'.format( mdd))\n", - "print('MDR (mean_market_return): \\t{: 2.6f}'.format( mean_market_return))\n", - "print('')\n", - "\n", - "# show one run vs average market performance\n", - "df.portfolio_value.plot()\n", - "df.mean_market_returns.cumprod().plot(label='mean market performance')\n", - "plt.legend()\n", - "plt.title('training data')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "start_time": "2017-07-23T06:09:37.804Z" - } - }, - "outputs": [], - "source": [ - "# Lets evaluate a few 30 step intervals\n", - "df_test = pd.read_hdf('./data/poloniex_30m.hf',key='test')\n", - "env_test = PortfolioEnv(\n", - " df=df_test,\n", - " steps=30, \n", - " scale=True, \n", - " augment=0.00,\n", - " trading_cost=0, # let just overfit first\n", - " window_length=window_length,\n", - ")\n", - "env_test.seed = 0 \n", - "\n", - "for i in range(10):\n", - " agent.test(env_test, nb_episodes=1, visualize=False)\n", - " df = pd.DataFrame(env_test.infos)\n", - " s=sharpe(df.rate_of_return)\n", - " mdd=MDD(df.rate_of_return+1)\n", - " mean_market_return=df.mean_market_returns.cumprod().iloc[-1]\n", - " print('APV (Accumulated portfolio value): \\t{: 2.6f}'.format(df.portfolio_value.iloc[-1]))\n", - " print('MMR (mean_market_return): \\t{: 2.6f}'.format(mean_market_return)) \n", - " print('SR (Sharpe ratio): \\t{: 2.6f}'.format( s))\n", - " print('MDD (max drawdown): \\t{: 2.6%}'.format( mdd))\n", - " print('')\n", - " df.portfolio_value.plot(label=str(i))\n", - "plt.legend()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2017-07-19T00:26:16.847387Z", - "start_time": "2017-07-19T08:26:12.521925+08:00" - }, - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Visualise" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "ExecuteTime": { - "start_time": "2017-07-23T06:09:37.807Z" - } - }, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'history' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# history\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mdf_hist\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDataFrame\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhistory\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhistory\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mdf_hist\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mdf_hist\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'episodes'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdf_hist\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'history' is not defined" - ] - } - ], - "source": [ - "# history\n", - "df_hist = pd.DataFrame(history.history)\n", - "df_hist\n", - "df_hist['episodes'] = df_hist.index\n", - "\n", - "g = sns.jointplot(x=\"episodes\", y=\"episode_reward\", data=df_hist, kind=\"reg\", size=10)\n", - "plt.show()\n", - "\n", - "# g = sns.jointplot(x=\"episodes\", y=\"rewards\", data=history, kind=\"reg\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.2" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -}