From 2cdea6557fecb07e0332a9c705ec30501423b744 Mon Sep 17 00:00:00 2001 From: Yi Dong Date: Tue, 30 Jun 2020 10:59:56 -0700 Subject: [PATCH 1/5] handles mutliple GPU xgboost --- gquant/dataframe_flow/_node_flow.py | 2 +- .../strategy/xgboostStrategyNode.py | 126 +++--- .../plugin_nodes/transform/indicatorNode.py | 1 + notebooks/04_portfolio_trade.ipynb | 198 +++++---- notebooks/06_xgboost_trade.ipynb | 397 +++++++++++++++--- 5 files changed, 520 insertions(+), 204 deletions(-) diff --git a/gquant/dataframe_flow/_node_flow.py b/gquant/dataframe_flow/_node_flow.py index 3eac2a43..3d97d1fd 100644 --- a/gquant/dataframe_flow/_node_flow.py +++ b/gquant/dataframe_flow/_node_flow.py @@ -673,9 +673,9 @@ def get_pout(out_dict, port): return output_df def decorate_process(self): - import time def timer(*argv): + import time start = time.time() result = self.process(*argv) end = time.time() diff --git a/gquant/plugin_nodes/strategy/xgboostStrategyNode.py b/gquant/plugin_nodes/strategy/xgboostStrategyNode.py index 4a5c8262..09cf93e6 100644 --- a/gquant/plugin_nodes/strategy/xgboostStrategyNode.py +++ b/gquant/plugin_nodes/strategy/xgboostStrategyNode.py @@ -1,41 +1,12 @@ from gquant.dataframe_flow import Node import datetime import cudf +import dask_cudf import xgboost as xgb -from numba import cuda -import math -import numpy as np - -__all__ = ['XGBoostStrategyNode'] +import dask -@cuda.jit -def signal_kernel(signal_arr, out_arr, arr_len): - i = cuda.grid(1) - if i == 0: - out_arr[i] = np.nan - if i < arr_len - 1: - if math.isnan(signal_arr[i]): - out_arr[i + 1] = np.nan - elif signal_arr[i] < 0.0: - # shift 1 time to make sure no peeking into the future - out_arr[i + 1] = -1.0 - else: - out_arr[i + 1] = 1.0 - - -def compute_signal(signal): - signal_arr = signal.to_gpu_array() - out_arr = cuda.device_array_like(signal_arr) - number_of_threads = 256 - array_len = len(signal) - number_of_blocks = (array_len + ( - number_of_threads - 1)) // number_of_threads - signal_kernel[(number_of_blocks,), - (number_of_threads,)](signal_arr, - out_arr, - array_len) - return out_arr +__all__ = ['XGBoostStrategyNode'] class XGBoostStrategyNode(Node): @@ -57,7 +28,8 @@ class XGBoostStrategyNode(Node): """ def columns_setup(self): - self.required = {'datetime': 'date'} + self.required = {'datetime': 'date', + "asset": "int64"} self.retention = self.conf['no_feature'] self.retention['signal'] = 'float64' @@ -92,25 +64,81 @@ def process(self, inputs): dxgb_params.update(self.conf['xgboost_parameters']) input_df = inputs[0] model_df = input_df - if 'train_date' in self.conf: - train_date = datetime.datetime.strptime(self.conf['train_date'], # noqa: F841, E501 - '%Y-%m-%d') - model_df = model_df.query('datetime<@train_date') train_cols = set(model_df.columns) - set( self.conf['no_feature'].keys()) train_cols = list(train_cols - set([self.conf['target']])) - train = model_df[train_cols] - target = model_df[self.conf['target']] - dmatrix = xgb.DMatrix(train, label=target) - bst = xgb.train(dxgb_params, dmatrix, - num_boost_round=num_of_rounds) - # make inferences - infer_dmatrix = xgb.DMatrix(input_df[train_cols]) - prediction = cudf.Series(bst.predict(infer_dmatrix), - nan_as_null=False).astype('float64') - signal = compute_signal(prediction) - signal = cudf.Series(signal, index=input_df.index) - input_df['signal'] = signal + + if isinstance(input_df, dask_cudf.DataFrame): + # get the client + client = dask.distributed.client.default_client() + if 'train_date' in self.conf: + train_date = datetime.datetime.strptime(self.conf['train_date'], # noqa: F841, E501 + '%Y-%m-%d') + model_df = model_df[model_df.datetime < train_date] + train = model_df[train_cols] + target = model_df[self.conf['target']] + dmatrix = xgb.dask.DaskDMatrix(client, train, label=target) + bst = xgb.dask.train(client, dxgb_params, dmatrix, + num_boost_round=num_of_rounds) + + tree_booster = bst['booster'] + + def predict(dask_df): + cudf_df = dask_df + infer_dmatrix = xgb.DMatrix(cudf_df[train_cols]) + prediction = cudf.Series(tree_booster.predict(infer_dmatrix), + nan_as_null=False, + index=cudf_df.index + ).astype('float64') + cudf_df['signal'] = prediction + # here we need to remove the first day of prediction + cudf_df['tmp'] = (cudf_df['asset'] - + cudf_df['asset'].shift(1)).fillna(1) + cudf_df['tmp'] = (cudf_df['tmp'] != 0).astype('int32') + # cudf_df['tmp'][cudf_df['tmp'] == 1] = None + tmp = cudf_df['tmp'] + cudf_df['tmp'] = tmp.where(tmp != 1, None) + cudf_df = cudf_df.dropna(subset=['tmp']) + cudf_df = cudf_df.drop('tmp') + return cudf_df + delayed_fun = dask.delayed(predict) + delayedObj = [delayed_fun(dask_cudf.from_delayed(delayed)) for delayed in input_df.to_delayed()] # noqa E501 + input_df = dask_cudf.from_delayed(delayedObj) + + elif isinstance(input_df, cudf.DataFrame): + if 'train_date' in self.conf: + train_date = datetime.datetime.strptime(self.conf['train_date'], # noqa: F841, E501 + '%Y-%m-%d') + model_df = model_df.query('datetime<@train_date') + train = model_df[train_cols] + target = model_df[self.conf['target']] + dmatrix = xgb.DMatrix(train, label=target) + bst = xgb.train(dxgb_params, dmatrix, + num_boost_round=num_of_rounds) + # make inferences + infer_dmatrix = xgb.DMatrix(input_df[train_cols]) + + prediction = cudf.Series(bst.predict(infer_dmatrix), + nan_as_null=False, + index=input_df.index).astype('float64') + input_df['signal'] = prediction + # here we need to remove the first day of prediction + input_df['tmp'] = (input_df['asset'] - + input_df['asset'].shift(1)).fillna(1) + input_df['tmp'] = (input_df['tmp'] != 0).astype('int32') + # input_df['tmp'][input_df['tmp'] == 1] = None + tmp = input_df['tmp'] + input_df['tmp'] = tmp.where(tmp != 1, None) + input_df = input_df.dropna(subset=['tmp']) + input_df = input_df.drop('tmp') + + # convert the signal to trading action + # 1 is buy and -1 is sell + # It predicts the tomorrow's return (shift -1) + # We shift 1 for trading actions so that it acts on the second day + input_df['signal'] = (( + input_df['signal'] >= 0).astype('float') * 2 - 1).shift(1) + # remove the bad datapints input_df = input_df.dropna() remaining = list(self.conf['no_feature'].keys()) + ['signal'] diff --git a/gquant/plugin_nodes/transform/indicatorNode.py b/gquant/plugin_nodes/transform/indicatorNode.py index 9fac56c1..81b2d57f 100644 --- a/gquant/plugin_nodes/transform/indicatorNode.py +++ b/gquant/plugin_nodes/transform/indicatorNode.py @@ -5,6 +5,7 @@ class IndicatorNode(Node): def columns_setup(self): + self.delayed_process = True self.required = {'indicator': 'int32'} self.addition = {} indicators = self.conf['indicators'] diff --git a/notebooks/04_portfolio_trade.ipynb b/notebooks/04_portfolio_trade.ipynb index 74bb435a..d88cac96 100644 --- a/notebooks/04_portfolio_trade.ipynb +++ b/notebooks/04_portfolio_trade.ipynb @@ -265,28 +265,28 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:sort process time:0.144s\n", - "id:add_return process time:0.401s\n", - "id:add_indicator process time:0.046s\n", - "id:volume_mean process time:0.106s\n", - "id:rename_mean_volume process time:0.002s\n", - "id:left_merge_mean_volume process time:0.026s\n", - "id:max_returns process time:0.022s\n", + "id:sort process time:0.145s\n", + "id:add_return process time:0.204s\n", + "id:add_indicator process time:0.044s\n", + "id:volume_mean process time:0.069s\n", + "id:rename_mean_volume process time:0.001s\n", + "id:left_merge_mean_volume process time:0.049s\n", + "id:max_returns process time:0.019s\n", "id:rename_max_return process time:0.001s\n", - "id:left_merge_max_return process time:0.038s\n", - "id:min_returns process time:0.022s\n", + "id:left_merge_max_return process time:0.028s\n", + "id:min_returns process time:0.023s\n", "id:rename_min_return process time:0.001s\n", - "id:left_merge_min_return process time:0.037s\n", - "id:filter_value process time:0.323s\n", - "id:drop_columns process time:0.009s\n", - "id:sort_2 process time:0.049s\n", - "id:exp_strategy process time:0.936s\n", - "id:backtest process time:0.038s\n", - "id:portfolio_opt process time:0.039s\n", + "id:left_merge_min_return process time:0.040s\n", + "id:filter_value process time:0.256s\n", + "id:drop_columns process time:0.008s\n", + "id:sort_2 process time:0.046s\n", + "id:exp_strategy process time:0.882s\n", + "id:backtest process time:0.004s\n", + "id:portfolio_opt process time:0.041s\n", "id:sharpe_ratio process time:0.001s\n", - "id:cumlative_return process time:2.063s\n", - "CPU times: user 5.36 s, sys: 1.09 s, total: 6.45 s\n", - "Wall time: 6.6 s\n" + "id:cumlative_return process time:1.980s\n", + "CPU times: user 4.85 s, sys: 1.33 s, total: 6.18 s\n", + "Wall time: 6.36 s\n" ] } ], @@ -351,7 +351,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b7479ffb4ae24389b92e15aa48847969", + "model_id": "20aa3c7cbf9645b2b72ac0b94a5afc91", "version_major": 2, "version_minor": 0 }, @@ -402,29 +402,29 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:load_csv_data process time:88.344s\n", - "id:sort process time:5.336s\n", - "id:add_return process time:20.408s\n", - "id:add_indicator process time:6.722s\n", - "id:volume_mean process time:0.347s\n", - "id:rename_mean_volume process time:0.002s\n", - "id:left_merge_mean_volume process time:4.962s\n", - "id:max_returns process time:0.346s\n", + "id:load_csv_data process time:92.288s\n", + "id:sort process time:5.315s\n", + "id:add_return process time:20.407s\n", + "id:add_indicator process time:6.698s\n", + "id:volume_mean process time:0.342s\n", + "id:rename_mean_volume process time:0.001s\n", + "id:left_merge_mean_volume process time:4.522s\n", + "id:max_returns process time:0.342s\n", "id:rename_max_return process time:0.001s\n", - "id:left_merge_max_return process time:4.598s\n", - "id:min_returns process time:0.347s\n", - "id:rename_min_return process time:0.002s\n", - "id:left_merge_min_return process time:4.709s\n", - "id:filter_value process time:0.928s\n", + "id:left_merge_max_return process time:4.632s\n", + "id:min_returns process time:0.344s\n", + "id:rename_min_return process time:0.001s\n", + "id:left_merge_min_return process time:4.714s\n", + "id:filter_value process time:0.919s\n", "id:drop_columns process time:0.068s\n", - "id:sort_2 process time:1.100s\n", - "id:exp_strategy process time:11.242s\n", + "id:sort_2 process time:1.096s\n", + "id:exp_strategy process time:10.986s\n", "id:backtest process time:0.025s\n", - "id:portfolio_opt process time:0.300s\n", + "id:portfolio_opt process time:0.299s\n", "id:sharpe_ratio process time:0.001s\n", - "id:cumlative_return process time:0.077s\n", - "CPU times: user 2min 23s, sys: 6.82 s, total: 2min 30s\n", - "Wall time: 2min 29s\n" + "id:cumlative_return process time:0.022s\n", + "CPU times: user 2min 26s, sys: 6.42 s, total: 2min 33s\n", + "Wall time: 2min 33s\n" ] } ], @@ -452,7 +452,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "4a7bd2cb99cf4984ace62f15e687d992", + "model_id": "9eccab9b2ba74bf7b266b79711121fbd", "version_major": 2, "version_minor": 0 }, @@ -501,7 +501,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -512,8 +512,8 @@ "\n", "

Client

\n", "\n", "\n", "\n", @@ -528,10 +528,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 11, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -543,7 +543,7 @@ "\n", "cluster = LocalCUDACluster()\n", "client = Client(cluster)\n", - "client" + "client\n" ] }, { @@ -557,33 +557,63 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import dask.dataframe as dd\n", + "import os\n", + "\n", + "os.makedirs('many-small', exist_ok=True)\n", + "dd.from_pandas(cpu_input_cached.set_index('asset'), npartitions=8).reset_index().to_csv('many-small/*.csv', index=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 73, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "19277162\n", + "3844749\n" + ] + }, { "data": { "text/plain": [ - "['/Projects/gQuant/notebooks/many-small/0.csv',\n", - " '/Projects/gQuant/notebooks/many-small/1.csv',\n", - " '/Projects/gQuant/notebooks/many-small/2.csv',\n", - " '/Projects/gQuant/notebooks/many-small/3.csv',\n", - " '/Projects/gQuant/notebooks/many-small/4.csv',\n", - " '/Projects/gQuant/notebooks/many-small/5.csv',\n", - " '/Projects/gQuant/notebooks/many-small/6.csv',\n", - " '/Projects/gQuant/notebooks/many-small/7.csv']" + "" ] }, - "execution_count": 12, + "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "import dask.dataframe as dd\n", - "import os\n", - "\n", - "os.makedirs('many-small', exist_ok=True)\n", - "dd.from_pandas(cpu_input_cached.set_index('asset'), npartitions=8).reset_index().to_csv('many-small/*.csv', index=False)" + "import dask_cudf\n", + "import dask\n", + "import datetime\n", + "e = dask_cudf.read_csv('/Projects/gQuant/notebooks/many-small/*.csv', dtype={\n", + " 'asset':\"int64\",\n", + " \"datetime\":\"date\",\n", + " \"open\":\"float64\",\n", + " \"close\":\"float64\",\n", + " \"high\":\"float64\",\n", + " \"low\":\"float64\",\n", + " \"volume\":\"float64\"\n", + "})\n", + "train_date = datetime.datetime.strptime('2000-01-01', '%Y-%m-%d')\n", + "#e.datetime.dtype\n", + "print(len(e))\n", + "print(len(e[e.datetime < train_date]))\n", + "#<1000000\n", + "#train_date\n", + "#y = e.compute()\n", + "len(dask_cudf.from_delayed(e.to_delayed()[2]))\n", + "e.datetime.shift(1)" ] }, { @@ -595,30 +625,30 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "id:load_csv_data process time:0.031s\n", - "id:volume_mean process time:0.472s\n", - "id:rename_mean_volume process time:0.012s\n", - "id:left_merge_mean_volume process time:0.159s\n", - "id:max_returns process time:0.055s\n", + "id:load_csv_data process time:0.038s\n", + "id:volume_mean process time:0.130s\n", + "id:rename_mean_volume process time:0.013s\n", + "id:left_merge_mean_volume process time:0.044s\n", + "id:max_returns process time:0.054s\n", "id:rename_max_return process time:0.012s\n", - "id:left_merge_max_return process time:0.026s\n", - "id:min_returns process time:0.046s\n", - "id:rename_min_return process time:0.013s\n", - "id:left_merge_min_return process time:0.025s\n", - "id:filter_value process time:0.046s\n", - "id:backtest process time:0.037s\n", - "id:portfolio_opt process time:0.420s\n", - "id:sharpe_ratio process time:8.605s\n", - "id:cumlative_return process time:12.172s\n", - "CPU times: user 51.5 s, sys: 1.41 s, total: 52.9 s\n", - "Wall time: 2min 12s\n" + "id:left_merge_max_return process time:0.025s\n", + "id:min_returns process time:0.057s\n", + "id:rename_min_return process time:0.014s\n", + "id:left_merge_min_return process time:0.027s\n", + "id:filter_value process time:0.051s\n", + "id:backtest process time:0.047s\n", + "id:portfolio_opt process time:0.120s\n", + "id:sharpe_ratio process time:5.304s\n", + "id:cumlative_return process time:7.507s\n", + "CPU times: user 42.7 s, sys: 1.36 s, total: 44.1 s\n", + "Wall time: 1min 11s\n" ] } ], @@ -630,7 +660,7 @@ " \"conf\": {\"path\": \"many-small\"}},\n", " 'filter_value': {\"conf\": [{\"column\": \"volume_mean\", \"min\": min_volume},\n", " {\"column\": \"returns_max\", \"max\": max_rate},\n", - " {\"column\": \"returns_min\", \"min\": min_rate}]}}, profile=True)\n", + " {\"column\": \"returns_min\", \"min\": min_rate}]}}, profile=True)\n", "\n", "dask_input_cached = o_dask[2] # 'load_csv_data' node output\n", "dask_strategy_cached = o_dask[3] # 'sort_2' node output" @@ -638,18 +668,18 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "4fa119d3734b4620a80178a2390e53aa", + "model_id": "53094e3d2a9c4694b0eee8c8b4eb1b74", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale()), Axis(label='Time', …" + "Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale(), side='left'), Axis(l…" ] }, "metadata": {}, @@ -687,13 +717,13 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "68552bff4fda44f4b71dfad32f284236", + "model_id": "eaf284d85c8d417bb8ea1a0c9c6df2e3", "version_major": 2, "version_minor": 0 }, diff --git a/notebooks/06_xgboost_trade.ipynb b/notebooks/06_xgboost_trade.ipynb index b20fcef1..ac0e96d1 100644 --- a/notebooks/06_xgboost_trade.ipynb +++ b/notebooks/06_xgboost_trade.ipynb @@ -210,7 +210,8 @@ " \"\"\"\n", "\n", " def columns_setup(self):\n", - " self.required = {'datetime': 'date'}\n", + " self.required = {'datetime': 'date',\n", + " \"asset\": \"int64\"}\n", " self.retention = self.conf['no_feature']\n", " self.retention['signal'] = 'float64'\n", "\n", @@ -245,25 +246,81 @@ " dxgb_params.update(self.conf['xgboost_parameters'])\n", " input_df = inputs[0]\n", " model_df = input_df\n", - " if 'train_date' in self.conf:\n", - " train_date = datetime.datetime.strptime(self.conf['train_date'], # noqa: F841, E501\n", - " '%Y-%m-%d')\n", - " model_df = model_df.query('datetime<@train_date')\n", " train_cols = set(model_df.columns) - set(\n", " self.conf['no_feature'].keys())\n", " train_cols = list(train_cols - set([self.conf['target']]))\n", - " train = model_df[train_cols]\n", - " target = model_df[self.conf['target']]\n", - " dmatrix = xgb.DMatrix(train, label=target)\n", - " bst = xgb.train(dxgb_params, dmatrix,\n", - " num_boost_round=num_of_rounds)\n", - " # make inferences\n", - " infer_dmatrix = xgb.DMatrix(input_df[train_cols])\n", - " prediction = cudf.Series(bst.predict(infer_dmatrix),\n", - " nan_as_null=False).astype('float64')\n", - " signal = compute_signal(prediction)\n", - " signal = cudf.Series(signal, index=input_df.index)\n", - " input_df['signal'] = signal\n", + "\n", + " if isinstance(input_df, dask_cudf.DataFrame):\n", + " # get the client\n", + " client = dask.distributed.client.default_client()\n", + " if 'train_date' in self.conf:\n", + " train_date = datetime.datetime.strptime(self.conf['train_date'], # noqa: F841, E501\n", + " '%Y-%m-%d')\n", + " model_df = model_df[model_df.datetime < train_date]\n", + " train = model_df[train_cols]\n", + " target = model_df[self.conf['target']]\n", + " dmatrix = xgb.dask.DaskDMatrix(client, train, label=target)\n", + " bst = xgb.dask.train(client, dxgb_params, dmatrix,\n", + " num_boost_round=num_of_rounds)\n", + "\n", + " tree_booster = bst['booster']\n", + "\n", + " def predict(dask_df):\n", + " cudf_df = dask_df\n", + " infer_dmatrix = xgb.DMatrix(cudf_df[train_cols])\n", + " prediction = cudf.Series(tree_booster.predict(infer_dmatrix),\n", + " nan_as_null=False,\n", + " index=cudf_df.index\n", + " ).astype('float64')\n", + " cudf_df['signal'] = prediction\n", + " # here we need to remove the first day of prediction\n", + " cudf_df['tmp'] = (cudf_df['asset'] -\n", + " cudf_df['asset'].shift(1)).fillna(1)\n", + " cudf_df['tmp'] = (cudf_df['tmp'] != 0).astype('int32')\n", + " # cudf_df['tmp'][cudf_df['tmp'] == 1] = None\n", + " tmp = cudf_df['tmp']\n", + " cudf_df['tmp'] = tmp.where(tmp != 1, None)\n", + " cudf_df = cudf_df.dropna(subset=['tmp'])\n", + " cudf_df = cudf_df.drop('tmp')\n", + " return cudf_df\n", + " delayed_fun = dask.delayed(predict)\n", + " delayedObj = [delayed_fun(dask_cudf.from_delayed(delayed)) for delayed in input_df.to_delayed()] # noqa E501\n", + " input_df = dask_cudf.from_delayed(delayedObj)\n", + "\n", + " elif isinstance(input_df, cudf.DataFrame):\n", + " if 'train_date' in self.conf:\n", + " train_date = datetime.datetime.strptime(self.conf['train_date'], # noqa: F841, E501\n", + " '%Y-%m-%d')\n", + " model_df = model_df.query('datetime<@train_date')\n", + " train = model_df[train_cols]\n", + " target = model_df[self.conf['target']]\n", + " dmatrix = xgb.DMatrix(train, label=target)\n", + " bst = xgb.train(dxgb_params, dmatrix,\n", + " num_boost_round=num_of_rounds)\n", + " # make inferences\n", + " infer_dmatrix = xgb.DMatrix(input_df[train_cols])\n", + "\n", + " prediction = cudf.Series(bst.predict(infer_dmatrix),\n", + " nan_as_null=False,\n", + " index=input_df.index).astype('float64')\n", + " input_df['signal'] = prediction\n", + " # here we need to remove the first day of prediction\n", + " input_df['tmp'] = (input_df['asset'] -\n", + " input_df['asset'].shift(1)).fillna(1)\n", + " input_df['tmp'] = (input_df['tmp'] != 0).astype('int32')\n", + " # input_df['tmp'][input_df['tmp'] == 1] = None\n", + " tmp = input_df['tmp']\n", + " input_df['tmp'] = tmp.where(tmp != 1, None)\n", + " input_df = input_df.dropna(subset=['tmp'])\n", + " input_df = input_df.drop('tmp')\n", + "\n", + " # convert the signal to trading action\n", + " # 1 is buy and -1 is sell\n", + " # It predicts the tomorrow's return (shift -1)\n", + " # We shift 1 for trading actions so that it acts on the second day\n", + " input_df['signal'] = ((\n", + " input_df['signal'] >= 0).astype('float') * 2 - 1).shift(1)\n", + "\n", " # remove the bad datapints\n", " input_df = input_df.dropna()\n", " remaining = list(self.conf['no_feature'].keys()) + ['signal']\n", @@ -340,32 +397,32 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:node_sort process time:0.143s\n", - "id:node_addReturn process time:0.446s\n", - "id:node_addIndicator process time:0.051s\n", - "id:node_volumeMean process time:0.109s\n", + "id:node_sort process time:0.146s\n", + "id:node_addReturn process time:0.207s\n", + "id:node_addIndicator process time:0.045s\n", + "id:node_volumeMean process time:0.060s\n", "id:node_renameMeanVolume process time:0.001s\n", - "id:node_leftMergeMeanVolume process time:2.698s\n", - "id:node_maxReturns process time:0.024s\n", + "id:node_leftMergeMeanVolume process time:0.025s\n", + "id:node_maxReturns process time:0.020s\n", "id:node_renameMaxReturn process time:0.001s\n", - "id:node_leftMergeMaxReturn process time:0.028s\n", - "id:node_minReturns process time:0.024s\n", + "id:node_leftMergeMaxReturn process time:0.034s\n", + "id:node_minReturns process time:0.023s\n", "id:node_renameMinReturn process time:0.001s\n", - "id:node_leftMergeMinReturn process time:0.036s\n", - "id:node_filterValue process time:0.332s\n", - "id:node_dropColumns process time:0.008s\n", - "id:node_sort2 process time:0.060s\n", - "id:node_technical_indicator process time:3.803s\n", - "id:node_xgboost_strategy process time:5.160s\n", - "id:node_backtest process time:0.006s\n", - "id:node_training_df process time:0.203s\n", - "id:node_portOpt2 process time:0.032s\n", + "id:node_leftMergeMinReturn process time:0.037s\n", + "id:node_filterValue process time:0.271s\n", + "id:node_dropColumns process time:0.012s\n", + "id:node_sort2 process time:0.046s\n", + "id:node_technical_indicator process time:2.909s\n", + "id:node_xgboost_strategy process time:4.778s\n", + "id:node_backtest process time:0.004s\n", + "id:node_training_df process time:0.281s\n", + "id:node_portOpt2 process time:0.029s\n", "id:node_sharpe_training process time:0.001s\n", - "id:node_cumlativeReturn_training process time:2.228s\n", - "id:node_testing_df process time:0.061s\n", - "id:node_portOpt1 process time:0.025s\n", + "id:node_cumlativeReturn_training process time:1.947s\n", + "id:node_testing_df process time:0.050s\n", + "id:node_portOpt1 process time:0.023s\n", "id:node_sharpe_testing process time:0.001s\n", - "id:node_cumlativeReturn_testing process time:2.452s\n" + "id:node_cumlativeReturn_testing process time:2.152s\n" ] } ], @@ -398,12 +455,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "50de025275284986b59b9b002d1285f8", + "model_id": "eefaf83a94704ef2aaecb7730395f9c4", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "VBox(children=(Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale(), side=…" + "VBox(children=(Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale()), Axis…" ] }, "metadata": {}, @@ -435,13 +492,154 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Clearly, 3 feautres is way too little here. gQuant implmented 36 technical indicators. We can change the configuration of node_technical_indicator node to include more features." + "The XGBoost model does a good job to predict the next day of return. It overfits in the training dataset and gets Sharpe Ratio of 5 as shown in the figure above. In the testing period, it gets Sharpe Ratio of 1.\n", + "\n", + "The example model runs in a single GPU because of the small dataset. But in real world, the dataset usually is so large that it doesn't fit in a single GPU. Luckily, the XGBoost library natively supports multiple nodes and multiple GPU training by using Dask. You can scale out the computation using Dask dataframe.\n", + "\n", + "To show how easy it is to do distributed computation, let's run the above exmaple in the Dask environment for educational purpose. \n", + "\n", + "First, let's start the Dask environment:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "

Client

\n", + "\n", + "
\n", + "

Cluster

\n", + "
    \n", + "
  • Workers: 4
  • \n", + "
  • Cores: 4
  • \n", + "
  • Memory: 270.39 GB
  • \n", + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Start the Dask local cluster environment for distrubuted computation\n", + "from dask_cuda import LocalCUDACluster\n", + "from dask.distributed import Client\n", + "\n", + "cluster = LocalCUDACluster()\n", + "client = Client(cluster)\n", + "client\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To run the whole workflow, simply change the input node type to `DaskCsvStockLoader` and run the graph again. Here we look at the testing results:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "id:node_csvdata process time:0.026s\n", + "id:node_volumeMean process time:0.103s\n", + "id:node_renameMeanVolume process time:0.013s\n", + "id:node_leftMergeMeanVolume process time:0.046s\n", + "id:node_maxReturns process time:0.051s\n", + "id:node_renameMaxReturn process time:0.010s\n", + "id:node_leftMergeMaxReturn process time:0.027s\n", + "id:node_minReturns process time:0.062s\n", + "id:node_renameMinReturn process time:0.017s\n", + "id:node_leftMergeMinReturn process time:0.028s\n", + "id:node_filterValue process time:0.043s\n", + "id:node_xgboost_strategy process time:44.884s\n", + "id:node_backtest process time:0.047s\n", + "id:node_testing_df process time:0.241s\n", + "id:node_portOpt1 process time:0.121s\n", + "id:node_sharpe_testing process time:17.549s\n", + "id:node_cumlativeReturn_testing process time:19.883s\n" + ] + } + ], + "source": [ + "action = \"load\" if os.path.isfile('./.cache/node_csvdata.hdf5') else \"save\"\n", + "\n", + "replace_spec={'node_filterValue': {\"conf\": [{\"column\": \"volume_mean\", \"min\": min_volume},\n", + " {\"column\": \"returns_max\", \"max\": max_rate},\n", + " {\"column\": \"returns_min\", \"min\": min_rate}]},\n", + " 'node_csvdata': {\"type\": \"DaskCsvStockLoader\",\n", + " \"conf\": {\"path\": \"many-small\"}}}\n", + "o_gpu = task_graph.run(\n", + " outputs=['node_sharpe_testing', 'node_cumlativeReturn_testing'],\n", + " replace=replace_spec, profile=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5722516d292a49a991d4f839788a99d2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale()), Axis(label='Time', …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "figure_width = '1200px'\n", + "figure_height = '400px'\n", + "sharpe_number = o_gpu[0]\n", + "cum_return_test = o_gpu[1]\n", + "cum_return_test.layout.height = figure_height\n", + "cum_return_test.layout.width = figure_width\n", + "cum_return_test.title = 'Testing P & L %.3f' % (sharpe_number)\n", + "cum_return_test" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Clearly, 3 feautres is way too little here. gQuant implmented 36 technical indicators. We can change the configuration of node_technical_indicator node to include more features." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, "outputs": [], "source": [ "chaikin_para0 = 10\n", @@ -573,30 +771,30 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "id:node_technical_indicator process time:4.281s\n", - "id:node_xgboost_strategy process time:9.202s\n", + "id:node_technical_indicator process time:3.692s\n", + "id:node_xgboost_strategy process time:42.967s\n", "id:node_backtest process time:0.004s\n", - "id:node_training_df process time:0.060s\n", - "id:node_portOpt2 process time:0.028s\n", + "id:node_training_df process time:0.081s\n", + "id:node_portOpt2 process time:0.040s\n", "id:node_sharpe_training process time:0.001s\n", - "id:node_cumlativeReturn_training process time:2.107s\n", - "id:node_testing_df process time:0.054s\n", - "id:node_portOpt1 process time:0.027s\n", + "id:node_cumlativeReturn_training process time:2.322s\n", + "id:node_testing_df process time:0.059s\n", + "id:node_portOpt1 process time:0.028s\n", "id:node_sharpe_testing process time:0.001s\n", - "id:node_cumlativeReturn_testing process time:2.119s\n" + "id:node_cumlativeReturn_testing process time:2.387s\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "079b407b3c4c41428c44ba81eda3a78c", + "model_id": "42740b0d54814d21aa34dc2073f6b2ca", "version_major": 2, "version_minor": 0 }, @@ -611,6 +809,7 @@ "source": [ "replace_spec['node_technical_indicator'] = {\"conf\": indicator_conf}\n", "replace_spec['node_sort2'] = {\"load\": cached_sort}\n", + "\n", "o_gpu = task_graph.run(\n", " outputs=outlist,\n", " replace=replace_spec, profile=True)\n", @@ -621,7 +820,71 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We get Sharpe Raio of `1.93` in the testing dataset, not bad!" + "We get Sharpe Ratio of `1.93` in the testing dataset, not bad!\n", + "\n", + "Using `min_volume=400.0`, it selects 1558 stocks. Setting a lower threshhold, it can include more stocks for the backtesting and hence increase the Sharpe Ratio. But it runs out of memory of single GPU. We have shown Dask can help to break down the large task into small tasks and schedule them a distributed environment. So we can handle dataset of any sizes in this way:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "id:node_csvdata process time:0.022s\n", + "id:node_volumeMean process time:0.105s\n", + "id:node_renameMeanVolume process time:0.012s\n", + "id:node_leftMergeMeanVolume process time:0.045s\n", + "id:node_maxReturns process time:0.053s\n", + "id:node_renameMaxReturn process time:0.022s\n", + "id:node_leftMergeMaxReturn process time:0.023s\n", + "id:node_minReturns process time:0.061s\n", + "id:node_renameMinReturn process time:0.011s\n", + "id:node_leftMergeMinReturn process time:0.028s\n", + "id:node_filterValue process time:0.253s\n", + "id:node_xgboost_strategy process time:70.237s\n", + "id:node_backtest process time:0.047s\n", + "id:node_testing_df process time:0.070s\n", + "id:node_portOpt1 process time:0.122s\n", + "id:node_sharpe_testing process time:41.744s\n" + ] + } + ], + "source": [ + "min_volume = 4.0\n", + "min_rate = -10.0\n", + "max_rate = 10.0\n", + "replace_spec={}\n", + "replace_spec['node_technical_indicator'] = {\"conf\": indicator_conf}\n", + "replace_spec['node_filterValue']={\"conf\": [{\"column\": \"volume_mean\", \"min\": min_volume},\n", + " {\"column\": \"returns_max\", \"max\": max_rate},\n", + " {\"column\": \"returns_min\", \"min\": min_rate}]}\n", + "replace_spec['node_technical_indicator'] = {\"conf\": indicator_conf}\n", + "replace_spec['node_csvdata'] = {\"type\": \"DaskCsvStockLoader\",\n", + " \"conf\": {\"path\": \"many-small\"}}\n", + "\n", + "o_gpu = task_graph.run(\n", + " outputs=['node_sharpe_testing', 'node_cumlativeReturn_testing'],\n", + " replace=replace_spec, profile=True)\n", + "\n", + "figure_width = '1200px'\n", + "figure_height = '400px'\n", + "sharpe_number = o_gpu[0]\n", + "cum_return_test = o_gpu[1]\n", + "cum_return_test.layout.height = figure_height\n", + "cum_return_test.layout.width = figure_width\n", + "cum_return_test.title = 'Testing P & L %.3f' % (sharpe_number)\n", + "cum_return_test" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We get Sharpe Ratio of `4.7` in the testing dataset. This is a great improvement!" ] }, { @@ -636,26 +899,20 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f2c589837c6a4f9c8849b545d6f2ed04", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(VBox(children=(IntRangeSlider(value=(10, 20), continuous_update=False, description='Chaikin', m…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import plotutils\n", + "min_volume = 400.0\n", + "min_rate = -10.0\n", + "max_rate = 10.0\n", + "replace_spec={}\n", + "replace_spec['node_technical_indicator'] = {\"conf\": indicator_conf}\n", + "replace_spec['node_filterValue']={\"conf\": [{\"column\": \"volume_mean\", \"min\": min_volume},\n", + " {\"column\": \"returns_max\", \"max\": max_rate},\n", + " {\"column\": \"returns_min\", \"min\": min_rate}]}\n", + "replace_spec['node_sort2'] = {\"load\": cached_sort}\n", "plotutils.getXGBoostWidget(replace_spec, task_graph, outlist, plot_figures)" ] }, @@ -695,5 +952,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } From 87dad6d1c5a7721eba6e4774eab8742d969dfc88 Mon Sep 17 00:00:00 2001 From: yidong72 <43824965+yidong72@users.noreply.github.com> Date: Thu, 2 Jul 2020 22:29:40 -0400 Subject: [PATCH 2/5] [REVIEW] Multiple gpu xgboost - Dask performance fix (#91) * improve the dask performance --- gquant/dataframe_flow/_node_flow.py | 54 +++- .../strategy/xgboostStrategyNode.py | 52 +--- notebooks/04_portfolio_trade.ipynb | 150 +++++---- notebooks/06_xgboost_trade.ipynb | 289 ++++++++++-------- 4 files changed, 308 insertions(+), 237 deletions(-) diff --git a/gquant/dataframe_flow/_node_flow.py b/gquant/dataframe_flow/_node_flow.py index 3d97d1fd..f636812b 100644 --- a/gquant/dataframe_flow/_node_flow.py +++ b/gquant/dataframe_flow/_node_flow.py @@ -124,6 +124,41 @@ def __translate_column(self, columns): return output + def __delayed_call_noports(self, inputs): + + def get_pout(df_out): + '''Used for delayed unpacking.''' + if isinstance(df_out, cudf.DataFrame): + # Needed for the same reason as __make_copy. To prevent columns + # addition in the input data frames. In python everything is + # by reference value and dataframes are mutable. + # Handle the case when dask_cudf.DataFrames are source frames + # which appear as cudf.DataFrame in a dask-delayed function. + return df_out.copy(deep=False) + + return df_out + + # handle the dask dataframe automatically + # use the to_delayed interface + # TODO, currently only handles first input is dask_cudf df + i_df = inputs[0] + rest = inputs[1:] + if isinstance(i_df, dask_cudf.DataFrame): + output_df_dly_list = [] + for input_dly in i_df.to_delayed(): + inputs_ = [input_dly] + rest + output_df_dly = dask.delayed(self.decorate_process())(inputs_) + output_df_dly_per = output_df_dly.persist() + df_out = dask.delayed(get_pout)(output_df_dly_per) + output_df_dly_list.append(df_out.persist()) + + output_df = dask_cudf.from_delayed(output_df_dly_list) + + else: + output_df = self.decorate_process()(inputs) + + return output_df + def columns_flow(self): """ Flow the graph to determine the input output dataframe column names and @@ -406,7 +441,7 @@ def __valide(self, node_output, ref_cols): cudf_types_tuple = (cudf.DataFrame, dask_cudf.DataFrame) if out_type in cudf_types_tuple: - if len(out_val) == 0 and out_optional: + if len(out_val.columns) == 0 and out_optional: continue if out_type in cudf_types_tuple: @@ -439,6 +474,10 @@ def __input_columns_ready(self): if iport not in self.input_columns: return False + if (self._using_ports() and len(self._get_input_ports( + )) != 0 and len(self.inputs) == 0): + return False + return True def __get_input_df(self): @@ -711,18 +750,7 @@ def __call__(self, inputs_data): else: output_df = self.decorate_process()(inputs) else: - # handle the dask dataframe automatically - # use the to_delayed interface - # TODO, currently only handles first input is dask_cudf df - i_df = inputs[0] - rest = inputs[1:] - if isinstance(i_df, dask_cudf.DataFrame): - d_fun = dask.delayed(self.decorate_process()) - output_df = dask_cudf.from_delayed([ - d_fun([item] + rest) - for item in i_df.to_delayed()]) - else: - output_df = self.decorate_process()(inputs) + output_df = self.__delayed_call_noports(inputs) if self.uid != OUTPUT_ID and output_df is None: raise Exception("None output") diff --git a/gquant/plugin_nodes/strategy/xgboostStrategyNode.py b/gquant/plugin_nodes/strategy/xgboostStrategyNode.py index 09cf93e6..c9f796eb 100644 --- a/gquant/plugin_nodes/strategy/xgboostStrategyNode.py +++ b/gquant/plugin_nodes/strategy/xgboostStrategyNode.py @@ -81,30 +81,12 @@ def process(self, inputs): bst = xgb.dask.train(client, dxgb_params, dmatrix, num_boost_round=num_of_rounds) - tree_booster = bst['booster'] - - def predict(dask_df): - cudf_df = dask_df - infer_dmatrix = xgb.DMatrix(cudf_df[train_cols]) - prediction = cudf.Series(tree_booster.predict(infer_dmatrix), - nan_as_null=False, - index=cudf_df.index - ).astype('float64') - cudf_df['signal'] = prediction - # here we need to remove the first day of prediction - cudf_df['tmp'] = (cudf_df['asset'] - - cudf_df['asset'].shift(1)).fillna(1) - cudf_df['tmp'] = (cudf_df['tmp'] != 0).astype('int32') - # cudf_df['tmp'][cudf_df['tmp'] == 1] = None - tmp = cudf_df['tmp'] - cudf_df['tmp'] = tmp.where(tmp != 1, None) - cudf_df = cudf_df.dropna(subset=['tmp']) - cudf_df = cudf_df.drop('tmp') - return cudf_df - delayed_fun = dask.delayed(predict) - delayedObj = [delayed_fun(dask_cudf.from_delayed(delayed)) for delayed in input_df.to_delayed()] # noqa E501 - input_df = dask_cudf.from_delayed(delayedObj) - + dtrain = xgb.dask.DaskDMatrix(client, input_df[train_cols]) + prediction = xgb.dask.predict(client, bst, dtrain).persist() + pred_df = dask_cudf.from_dask_dataframe( + prediction.to_dask_dataframe()) + pred_df.index = input_df.index + input_df['signal'] = pred_df elif isinstance(input_df, cudf.DataFrame): if 'train_date' in self.conf: train_date = datetime.datetime.strptime(self.conf['train_date'], # noqa: F841, E501 @@ -115,22 +97,20 @@ def predict(dask_df): dmatrix = xgb.DMatrix(train, label=target) bst = xgb.train(dxgb_params, dmatrix, num_boost_round=num_of_rounds) - # make inferences infer_dmatrix = xgb.DMatrix(input_df[train_cols]) - prediction = cudf.Series(bst.predict(infer_dmatrix), nan_as_null=False, - index=input_df.index).astype('float64') + index=input_df.index + ).astype('float64') input_df['signal'] = prediction - # here we need to remove the first day of prediction - input_df['tmp'] = (input_df['asset'] - - input_df['asset'].shift(1)).fillna(1) - input_df['tmp'] = (input_df['tmp'] != 0).astype('int32') - # input_df['tmp'][input_df['tmp'] == 1] = None - tmp = input_df['tmp'] - input_df['tmp'] = tmp.where(tmp != 1, None) - input_df = input_df.dropna(subset=['tmp']) - input_df = input_df.drop('tmp') + + input_df['tmp'] = (input_df['asset'] - + input_df['asset'].shift(1)).fillna(1) + input_df['tmp'] = (input_df['tmp'] != 0).astype('int32') + tmp = input_df['tmp'] + input_df['tmp'] = tmp.where(tmp != 1, None) + input_df = input_df.dropna(subset=['tmp']) + input_df = input_df.drop('tmp', axis=1) # convert the signal to trading action # 1 is buy and -1 is sell diff --git a/notebooks/04_portfolio_trade.ipynb b/notebooks/04_portfolio_trade.ipynb index d88cac96..3b4fa69d 100644 --- a/notebooks/04_portfolio_trade.ipynb +++ b/notebooks/04_portfolio_trade.ipynb @@ -265,28 +265,28 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:sort process time:0.145s\n", - "id:add_return process time:0.204s\n", - "id:add_indicator process time:0.044s\n", - "id:volume_mean process time:0.069s\n", + "id:sort process time:0.148s\n", + "id:add_return process time:0.192s\n", + "id:add_indicator process time:0.049s\n", + "id:volume_mean process time:0.060s\n", "id:rename_mean_volume process time:0.001s\n", - "id:left_merge_mean_volume process time:0.049s\n", + "id:left_merge_mean_volume process time:0.030s\n", "id:max_returns process time:0.019s\n", "id:rename_max_return process time:0.001s\n", - "id:left_merge_max_return process time:0.028s\n", - "id:min_returns process time:0.023s\n", + "id:left_merge_max_return process time:0.026s\n", + "id:min_returns process time:0.022s\n", "id:rename_min_return process time:0.001s\n", "id:left_merge_min_return process time:0.040s\n", - "id:filter_value process time:0.256s\n", - "id:drop_columns process time:0.008s\n", - "id:sort_2 process time:0.046s\n", - "id:exp_strategy process time:0.882s\n", + "id:filter_value process time:0.312s\n", + "id:drop_columns process time:0.007s\n", + "id:sort_2 process time:0.053s\n", + "id:exp_strategy process time:0.910s\n", "id:backtest process time:0.004s\n", "id:portfolio_opt process time:0.041s\n", "id:sharpe_ratio process time:0.001s\n", - "id:cumlative_return process time:1.980s\n", - "CPU times: user 4.85 s, sys: 1.33 s, total: 6.18 s\n", - "Wall time: 6.36 s\n" + "id:cumlative_return process time:2.019s\n", + "CPU times: user 4.96 s, sys: 1.17 s, total: 6.13 s\n", + "Wall time: 6.27 s\n" ] } ], @@ -351,12 +351,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "20aa3c7cbf9645b2b72ac0b94a5afc91", + "model_id": "6daf7202b3df4e94b0895510a169594c", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale(), side='left'), Axis(l…" + "Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale()), Axis(label='Time', …" ] }, "metadata": {}, @@ -402,29 +402,29 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:load_csv_data process time:92.288s\n", - "id:sort process time:5.315s\n", - "id:add_return process time:20.407s\n", - "id:add_indicator process time:6.698s\n", - "id:volume_mean process time:0.342s\n", + "id:load_csv_data process time:89.438s\n", + "id:sort process time:5.394s\n", + "id:add_return process time:20.824s\n", + "id:add_indicator process time:6.737s\n", + "id:volume_mean process time:0.345s\n", "id:rename_mean_volume process time:0.001s\n", - "id:left_merge_mean_volume process time:4.522s\n", - "id:max_returns process time:0.342s\n", + "id:left_merge_mean_volume process time:4.569s\n", + "id:max_returns process time:0.346s\n", "id:rename_max_return process time:0.001s\n", - "id:left_merge_max_return process time:4.632s\n", - "id:min_returns process time:0.344s\n", + "id:left_merge_max_return process time:4.699s\n", + "id:min_returns process time:0.345s\n", "id:rename_min_return process time:0.001s\n", - "id:left_merge_min_return process time:4.714s\n", - "id:filter_value process time:0.919s\n", + "id:left_merge_min_return process time:4.826s\n", + "id:filter_value process time:0.931s\n", "id:drop_columns process time:0.068s\n", - "id:sort_2 process time:1.096s\n", - "id:exp_strategy process time:10.986s\n", + "id:sort_2 process time:1.105s\n", + "id:exp_strategy process time:11.040s\n", "id:backtest process time:0.025s\n", - "id:portfolio_opt process time:0.299s\n", + "id:portfolio_opt process time:0.310s\n", "id:sharpe_ratio process time:0.001s\n", - "id:cumlative_return process time:0.022s\n", - "CPU times: user 2min 26s, sys: 6.42 s, total: 2min 33s\n", - "Wall time: 2min 33s\n" + "id:cumlative_return process time:0.021s\n", + "CPU times: user 2min 24s, sys: 6.42 s, total: 2min 31s\n", + "Wall time: 2min 31s\n" ] } ], @@ -452,7 +452,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "9eccab9b2ba74bf7b266b79711121fbd", + "model_id": "85e3e0c218b54867aa88e8efdfcb0378", "version_major": 2, "version_minor": 0 }, @@ -501,7 +501,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -512,8 +512,8 @@ "\n", "

Client

\n", "\n", "\n", "\n", @@ -528,10 +528,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 24, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -557,9 +557,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "['/Projects/gQuant/notebooks/many-small/0.csv',\n", + " '/Projects/gQuant/notebooks/many-small/1.csv',\n", + " '/Projects/gQuant/notebooks/many-small/2.csv',\n", + " '/Projects/gQuant/notebooks/many-small/3.csv',\n", + " '/Projects/gQuant/notebooks/many-small/4.csv',\n", + " '/Projects/gQuant/notebooks/many-small/5.csv',\n", + " '/Projects/gQuant/notebooks/many-small/6.csv',\n", + " '/Projects/gQuant/notebooks/many-small/7.csv']" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "import dask.dataframe as dd\n", "import os\n", @@ -570,7 +588,7 @@ }, { "cell_type": "code", - "execution_count": 73, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -587,7 +605,7 @@ "" ] }, - "execution_count": 73, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -625,30 +643,30 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "id:load_csv_data process time:0.038s\n", - "id:volume_mean process time:0.130s\n", - "id:rename_mean_volume process time:0.013s\n", - "id:left_merge_mean_volume process time:0.044s\n", - "id:max_returns process time:0.054s\n", - "id:rename_max_return process time:0.012s\n", - "id:left_merge_max_return process time:0.025s\n", - "id:min_returns process time:0.057s\n", - "id:rename_min_return process time:0.014s\n", + "id:load_csv_data process time:0.028s\n", + "id:volume_mean process time:0.253s\n", + "id:rename_mean_volume process time:0.011s\n", + "id:left_merge_mean_volume process time:0.294s\n", + "id:max_returns process time:0.252s\n", + "id:rename_max_return process time:0.030s\n", + "id:left_merge_max_return process time:0.027s\n", + "id:min_returns process time:0.224s\n", + "id:rename_min_return process time:0.011s\n", "id:left_merge_min_return process time:0.027s\n", - "id:filter_value process time:0.051s\n", - "id:backtest process time:0.047s\n", - "id:portfolio_opt process time:0.120s\n", - "id:sharpe_ratio process time:5.304s\n", - "id:cumlative_return process time:7.507s\n", - "CPU times: user 42.7 s, sys: 1.36 s, total: 44.1 s\n", - "Wall time: 1min 11s\n" + "id:filter_value process time:0.076s\n", + "id:backtest process time:0.236s\n", + "id:portfolio_opt process time:0.135s\n", + "id:sharpe_ratio process time:0.225s\n", + "id:cumlative_return process time:2.758s\n", + "CPU times: user 10.3 s, sys: 463 ms, total: 10.8 s\n", + "Wall time: 17.5 s\n" ] } ], @@ -660,7 +678,7 @@ " \"conf\": {\"path\": \"many-small\"}},\n", " 'filter_value': {\"conf\": [{\"column\": \"volume_mean\", \"min\": min_volume},\n", " {\"column\": \"returns_max\", \"max\": max_rate},\n", - " {\"column\": \"returns_min\", \"min\": min_rate}]}}, profile=True)\n", + " {\"column\": \"returns_min\", \"min\": min_rate}]}}, profile=True)\n", "\n", "dask_input_cached = o_dask[2] # 'load_csv_data' node output\n", "dask_strategy_cached = o_dask[3] # 'sort_2' node output" @@ -668,18 +686,18 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "53094e3d2a9c4694b0eee8c8b4eb1b74", + "model_id": "593d8d7bd86b49bfa2f431d5f36608d4", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale(), side='left'), Axis(l…" + "Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale()), Axis(label='Time', …" ] }, "metadata": {}, @@ -717,13 +735,13 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "eaf284d85c8d417bb8ea1a0c9c6df2e3", + "model_id": "9b8a889a00424555aa3af1f61ac7c9a3", "version_major": 2, "version_minor": 0 }, diff --git a/notebooks/06_xgboost_trade.ipynb b/notebooks/06_xgboost_trade.ipynb index ac0e96d1..c1cf9db8 100644 --- a/notebooks/06_xgboost_trade.ipynb +++ b/notebooks/06_xgboost_trade.ipynb @@ -263,30 +263,16 @@ " bst = xgb.dask.train(client, dxgb_params, dmatrix,\n", " num_boost_round=num_of_rounds)\n", "\n", - " tree_booster = bst['booster']\n", - "\n", - " def predict(dask_df):\n", - " cudf_df = dask_df\n", - " infer_dmatrix = xgb.DMatrix(cudf_df[train_cols])\n", - " prediction = cudf.Series(tree_booster.predict(infer_dmatrix),\n", - " nan_as_null=False,\n", - " index=cudf_df.index\n", - " ).astype('float64')\n", - " cudf_df['signal'] = prediction\n", - " # here we need to remove the first day of prediction\n", - " cudf_df['tmp'] = (cudf_df['asset'] -\n", - " cudf_df['asset'].shift(1)).fillna(1)\n", - " cudf_df['tmp'] = (cudf_df['tmp'] != 0).astype('int32')\n", - " # cudf_df['tmp'][cudf_df['tmp'] == 1] = None\n", - " tmp = cudf_df['tmp']\n", - " cudf_df['tmp'] = tmp.where(tmp != 1, None)\n", - " cudf_df = cudf_df.dropna(subset=['tmp'])\n", - " cudf_df = cudf_df.drop('tmp')\n", - " return cudf_df\n", - " delayed_fun = dask.delayed(predict)\n", - " delayedObj = [delayed_fun(dask_cudf.from_delayed(delayed)) for delayed in input_df.to_delayed()] # noqa E501\n", - " input_df = dask_cudf.from_delayed(delayedObj)\n", - "\n", + " # tree_booster = bst['booster']\n", + " # delayed_fun = dask.delayed(delay_predict)\n", + " # delayedObj = [delayed_fun(delayed, tree_booster, train_cols) for delayed in input_df.to_delayed()] # noqa E501\n", + " # input_df = dask_cudf.from_delayed(delayedObj)\n", + " dtrain = xgb.dask.DaskDMatrix(client, input_df[train_cols])\n", + " prediction = xgb.dask.predict(client, bst, dtrain).persist()\n", + " pred_df = dask_cudf.from_dask_dataframe(\n", + " prediction.to_dask_dataframe())\n", + " pred_df.index = input_df.index\n", + " input_df['signal'] = pred_df\n", " elif isinstance(input_df, cudf.DataFrame):\n", " if 'train_date' in self.conf:\n", " train_date = datetime.datetime.strptime(self.conf['train_date'], # noqa: F841, E501\n", @@ -297,22 +283,20 @@ " dmatrix = xgb.DMatrix(train, label=target)\n", " bst = xgb.train(dxgb_params, dmatrix,\n", " num_boost_round=num_of_rounds)\n", - " # make inferences\n", " infer_dmatrix = xgb.DMatrix(input_df[train_cols])\n", - "\n", " prediction = cudf.Series(bst.predict(infer_dmatrix),\n", " nan_as_null=False,\n", - " index=input_df.index).astype('float64')\n", + " index=input_df.index\n", + " ).astype('float64')\n", " input_df['signal'] = prediction\n", - " # here we need to remove the first day of prediction\n", - " input_df['tmp'] = (input_df['asset'] -\n", - " input_df['asset'].shift(1)).fillna(1)\n", - " input_df['tmp'] = (input_df['tmp'] != 0).astype('int32')\n", - " # input_df['tmp'][input_df['tmp'] == 1] = None\n", - " tmp = input_df['tmp']\n", - " input_df['tmp'] = tmp.where(tmp != 1, None)\n", - " input_df = input_df.dropna(subset=['tmp'])\n", - " input_df = input_df.drop('tmp')\n", + "\n", + " input_df['tmp'] = (input_df['asset'] -\n", + " input_df['asset'].shift(1)).fillna(1)\n", + " input_df['tmp'] = (input_df['tmp'] != 0).astype('int32')\n", + " tmp = input_df['tmp']\n", + " input_df['tmp'] = tmp.where(tmp != 1, None)\n", + " input_df = input_df.dropna(subset=['tmp'])\n", + " input_df = input_df.drop('tmp', axis=1)\n", "\n", " # convert the signal to trading action\n", " # 1 is buy and -1 is sell\n", @@ -397,37 +381,39 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:node_sort process time:0.146s\n", - "id:node_addReturn process time:0.207s\n", - "id:node_addIndicator process time:0.045s\n", - "id:node_volumeMean process time:0.060s\n", + "id:node_sort process time:0.142s\n", + "id:node_addReturn process time:0.209s\n", + "id:node_addIndicator process time:0.050s\n", + "id:node_volumeMean process time:0.065s\n", "id:node_renameMeanVolume process time:0.001s\n", - "id:node_leftMergeMeanVolume process time:0.025s\n", + "id:node_leftMergeMeanVolume process time:0.042s\n", "id:node_maxReturns process time:0.020s\n", "id:node_renameMaxReturn process time:0.001s\n", - "id:node_leftMergeMaxReturn process time:0.034s\n", - "id:node_minReturns process time:0.023s\n", + "id:node_leftMergeMaxReturn process time:0.028s\n", + "id:node_minReturns process time:0.024s\n", "id:node_renameMinReturn process time:0.001s\n", - "id:node_leftMergeMinReturn process time:0.037s\n", - "id:node_filterValue process time:0.271s\n", - "id:node_dropColumns process time:0.012s\n", - "id:node_sort2 process time:0.046s\n", - "id:node_technical_indicator process time:2.909s\n", - "id:node_xgboost_strategy process time:4.778s\n", - "id:node_backtest process time:0.004s\n", - "id:node_training_df process time:0.281s\n", - "id:node_portOpt2 process time:0.029s\n", + "id:node_leftMergeMinReturn process time:0.039s\n", + "id:node_filterValue process time:0.268s\n", + "id:node_dropColumns process time:0.008s\n", + "id:node_sort2 process time:0.050s\n", + "id:node_technical_indicator process time:2.911s\n", + "id:node_xgboost_strategy process time:4.622s\n", + "id:node_backtest process time:0.007s\n", + "id:node_training_df process time:0.296s\n", + "id:node_portOpt2 process time:0.032s\n", "id:node_sharpe_training process time:0.001s\n", - "id:node_cumlativeReturn_training process time:1.947s\n", - "id:node_testing_df process time:0.050s\n", - "id:node_portOpt1 process time:0.023s\n", + "id:node_cumlativeReturn_training process time:1.992s\n", + "id:node_testing_df process time:0.053s\n", + "id:node_portOpt1 process time:0.022s\n", "id:node_sharpe_testing process time:0.001s\n", - "id:node_cumlativeReturn_testing process time:2.152s\n" + "id:node_cumlativeReturn_testing process time:2.125s\n", + "CPU times: user 52.4 s, sys: 2.32 s, total: 54.7 s\n", + "Wall time: 14.9 s\n" ] } ], "source": [ - "\n", + "%%time\n", "action = \"load\" if os.path.isfile('./.cache/node_csvdata.hdf5') else \"save\"\n", "outlist = ['node_sharpe_training','node_cumlativeReturn_training', 'node_sharpe_testing', 'node_cumlativeReturn_testing']\n", "replace_spec={'node_filterValue': {\"conf\": [{\"column\": \"volume_mean\", \"min\": min_volume},\n", @@ -455,7 +441,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "eefaf83a94704ef2aaecb7730395f9c4", + "model_id": "fa3b59bfb8b1438d94f28f7c9295f126", "version_major": 2, "version_minor": 0 }, @@ -514,7 +500,7 @@ "\n", "

Client

\n", "\n", "\n", @@ -530,7 +516,7 @@ "" ], "text/plain": [ - "" + "" ] }, "execution_count": 10, @@ -564,27 +550,34 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:node_csvdata process time:0.026s\n", - "id:node_volumeMean process time:0.103s\n", - "id:node_renameMeanVolume process time:0.013s\n", - "id:node_leftMergeMeanVolume process time:0.046s\n", - "id:node_maxReturns process time:0.051s\n", - "id:node_renameMaxReturn process time:0.010s\n", - "id:node_leftMergeMaxReturn process time:0.027s\n", - "id:node_minReturns process time:0.062s\n", - "id:node_renameMinReturn process time:0.017s\n", - "id:node_leftMergeMinReturn process time:0.028s\n", - "id:node_filterValue process time:0.043s\n", - "id:node_xgboost_strategy process time:44.884s\n", - "id:node_backtest process time:0.047s\n", - "id:node_testing_df process time:0.241s\n", - "id:node_portOpt1 process time:0.121s\n", - "id:node_sharpe_testing process time:17.549s\n", - "id:node_cumlativeReturn_testing process time:19.883s\n" + "id:node_csvdata process time:0.029s\n", + "id:node_volumeMean process time:0.401s\n", + "id:node_renameMeanVolume process time:0.011s\n", + "id:node_leftMergeMeanVolume process time:0.337s\n", + "id:node_maxReturns process time:0.205s\n", + "id:node_renameMaxReturn process time:0.033s\n", + "id:node_leftMergeMaxReturn process time:0.032s\n", + "id:node_minReturns process time:0.293s\n", + "id:node_renameMinReturn process time:0.024s\n", + "id:node_leftMergeMinReturn process time:0.031s\n", + "id:node_filterValue process time:0.068s\n", + "id:node_xgboost_strategy process time:13.928s\n", + "id:node_backtest process time:0.163s\n", + "id:node_training_df process time:0.314s\n", + "id:node_portOpt2 process time:0.131s\n", + "id:node_sharpe_training process time:0.244s\n", + "id:node_cumlativeReturn_training process time:2.776s\n", + "id:node_testing_df process time:0.078s\n", + "id:node_portOpt1 process time:0.116s\n", + "id:node_sharpe_testing process time:0.218s\n", + "id:node_cumlativeReturn_testing process time:2.989s\n", + "CPU times: user 19 s, sys: 953 ms, total: 20 s\n", + "Wall time: 45.6 s\n" ] } ], "source": [ + "%%time\n", "action = \"load\" if os.path.isfile('./.cache/node_csvdata.hdf5') else \"save\"\n", "\n", "replace_spec={'node_filterValue': {\"conf\": [{\"column\": \"volume_mean\", \"min\": min_volume},\n", @@ -593,7 +586,7 @@ " 'node_csvdata': {\"type\": \"DaskCsvStockLoader\",\n", " \"conf\": {\"path\": \"many-small\"}}}\n", "o_gpu = task_graph.run(\n", - " outputs=['node_sharpe_testing', 'node_cumlativeReturn_testing'],\n", + " outputs=['node_sharpe_training','node_cumlativeReturn_training', 'node_sharpe_testing', 'node_cumlativeReturn_testing'],\n", " replace=replace_spec, profile=True)" ] }, @@ -605,12 +598,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "5722516d292a49a991d4f839788a99d2", + "model_id": "5abf39fcb16c4014b732a810cf4663cf", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale()), Axis(label='Time', …" + "VBox(children=(Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale()), Axis…" ] }, "metadata": {}, @@ -618,14 +611,7 @@ } ], "source": [ - "figure_width = '1200px'\n", - "figure_height = '400px'\n", - "sharpe_number = o_gpu[0]\n", - "cum_return_test = o_gpu[1]\n", - "cum_return_test.layout.height = figure_height\n", - "cum_return_test.layout.width = figure_width\n", - "cum_return_test.title = 'Testing P & L %.3f' % (sharpe_number)\n", - "cum_return_test" + "plot_figures(o_gpu)" ] }, { @@ -779,22 +765,40 @@ "output_type": "stream", "text": [ "id:node_technical_indicator process time:3.692s\n", - "id:node_xgboost_strategy process time:42.967s\n", - "id:node_backtest process time:0.004s\n", - "id:node_training_df process time:0.081s\n", - "id:node_portOpt2 process time:0.040s\n", + "id:node_xgboost_strategy process time:41.486s\n", + "id:node_backtest process time:0.005s\n", + "id:node_training_df process time:0.082s\n", + "id:node_portOpt2 process time:0.039s\n", "id:node_sharpe_training process time:0.001s\n", - "id:node_cumlativeReturn_training process time:2.322s\n", - "id:node_testing_df process time:0.059s\n", - "id:node_portOpt1 process time:0.028s\n", + "id:node_cumlativeReturn_training process time:2.340s\n", + "id:node_testing_df process time:0.056s\n", + "id:node_portOpt1 process time:0.025s\n", "id:node_sharpe_testing process time:0.001s\n", - "id:node_cumlativeReturn_testing process time:2.387s\n" + "id:node_cumlativeReturn_testing process time:2.384s\n", + "CPU times: user 50.2 s, sys: 3.46 s, total: 53.7 s\n", + "Wall time: 50.2 s\n" ] - }, + } + ], + "source": [ + "%%time\n", + "replace_spec['node_technical_indicator'] = {\"conf\": indicator_conf}\n", + "replace_spec['node_sort2'] = {\"load\": cached_sort}\n", + "\n", + "o_gpu = task_graph.run(\n", + " outputs=outlist,\n", + " replace=replace_spec, profile=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "42740b0d54814d21aa34dc2073f6b2ca", + "model_id": "cfd1053b94bb42b08675522f2739e8b6", "version_major": 2, "version_minor": 0 }, @@ -807,12 +811,6 @@ } ], "source": [ - "replace_spec['node_technical_indicator'] = {\"conf\": indicator_conf}\n", - "replace_spec['node_sort2'] = {\"load\": cached_sort}\n", - "\n", - "o_gpu = task_graph.run(\n", - " outputs=outlist,\n", - " replace=replace_spec, profile=True)\n", "plot_figures(o_gpu)" ] }, @@ -827,7 +825,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -835,25 +833,33 @@ "output_type": "stream", "text": [ "id:node_csvdata process time:0.022s\n", - "id:node_volumeMean process time:0.105s\n", - "id:node_renameMeanVolume process time:0.012s\n", - "id:node_leftMergeMeanVolume process time:0.045s\n", - "id:node_maxReturns process time:0.053s\n", - "id:node_renameMaxReturn process time:0.022s\n", - "id:node_leftMergeMaxReturn process time:0.023s\n", - "id:node_minReturns process time:0.061s\n", - "id:node_renameMinReturn process time:0.011s\n", - "id:node_leftMergeMinReturn process time:0.028s\n", - "id:node_filterValue process time:0.253s\n", - "id:node_xgboost_strategy process time:70.237s\n", - "id:node_backtest process time:0.047s\n", + "id:node_volumeMean process time:0.407s\n", + "id:node_renameMeanVolume process time:0.024s\n", + "id:node_leftMergeMeanVolume process time:0.274s\n", + "id:node_maxReturns process time:0.081s\n", + "id:node_renameMaxReturn process time:0.024s\n", + "id:node_leftMergeMaxReturn process time:0.029s\n", + "id:node_minReturns process time:0.363s\n", + "id:node_renameMinReturn process time:0.012s\n", + "id:node_leftMergeMinReturn process time:0.029s\n", + "id:node_filterValue process time:0.255s\n", + "id:node_xgboost_strategy process time:40.088s\n", + "id:node_backtest process time:0.145s\n", + "id:node_training_df process time:0.127s\n", + "id:node_portOpt2 process time:0.126s\n", + "id:node_sharpe_training process time:0.210s\n", + "id:node_cumlativeReturn_training process time:2.863s\n", "id:node_testing_df process time:0.070s\n", - "id:node_portOpt1 process time:0.122s\n", - "id:node_sharpe_testing process time:41.744s\n" + "id:node_portOpt1 process time:0.113s\n", + "id:node_sharpe_testing process time:0.226s\n", + "id:node_cumlativeReturn_testing process time:2.890s\n", + "CPU times: user 22.3 s, sys: 1.24 s, total: 23.5 s\n", + "Wall time: 1min 12s\n" ] } ], "source": [ + "%%time\n", "min_volume = 4.0\n", "min_rate = -10.0\n", "max_rate = 10.0\n", @@ -867,7 +873,7 @@ " \"conf\": {\"path\": \"many-small\"}}\n", "\n", "o_gpu = task_graph.run(\n", - " outputs=['node_sharpe_testing', 'node_cumlativeReturn_testing'],\n", + " outputs=['node_sharpe_training','node_cumlativeReturn_training', 'node_sharpe_testing', 'node_cumlativeReturn_testing'],\n", " replace=replace_spec, profile=True)\n", "\n", "figure_width = '1200px'\n", @@ -880,6 +886,30 @@ "cum_return_test" ] }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f2f2e7ebe5854a3980c882cf6c094e79", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Figure(axes=[Axis(label='Cumulative return', orientation='vertical', scale=LinearScale()), Axis…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_figures(o_gpu)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -899,9 +929,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "49fbb4fd22864b7a8f04fd0234687e81", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(VBox(children=(IntRangeSlider(value=(10, 20), continuous_update=False, description='Chaikin', m…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import plotutils\n", "min_volume = 400.0\n", From 7a0c0984c2f81f65e48a109b915d5bfff164c48b Mon Sep 17 00:00:00 2001 From: yidong72 <43824965+yidong72@users.noreply.github.com> Date: Tue, 7 Jul 2020 19:02:31 -0400 Subject: [PATCH 3/5] [REVIEW] Update RAPIDS to version 0.14 (#92) * migrate to the RAPIDS v0.14 * fixed the indicator notebook * fixed #88 * release candidate 0.5 --- docker/build.sh | 2 +- gquant/dataframe_flow/task.py | 4 + gquant/plugin_nodes/analysis/barPlotNode.py | 40 +++- gquant/plugin_nodes/analysis/cumReturnNode.py | 20 +- gquant/plugin_nodes/analysis/linePlotNode.py | 21 +- notebooks/01_tutorial.ipynb | 76 ++++---- notebooks/02_single_stock_trade.ipynb | 6 +- notebooks/03_simple_dask_example.ipynb | 32 ++- notebooks/04_portfolio_trade.ipynb | 114 +++++------ notebooks/06_xgboost_trade.ipynb | 184 +++++++++--------- notebooks/07_fractional_differencing.ipynb | 20 +- notebooks/cuIndicator/indicator_demo.ipynb | 49 +++-- notebooks/cuIndicator/rsi_perf.ipynb | 37 ++-- .../viz/accumulation_distribution.py | 24 ++- notebooks/cuIndicator/viz/admi.py | 31 +-- .../cuIndicator/viz/average_true_range.py | 25 ++- notebooks/cuIndicator/viz/bollinger_bands.py | 41 ++-- notebooks/cuIndicator/viz/ch_oscillator.py | 32 +-- .../viz/commodity_channel_index.py | 20 +- notebooks/cuIndicator/viz/coppock_curve.py | 20 +- notebooks/cuIndicator/viz/donchian_channel.py | 18 +- notebooks/cuIndicator/viz/ease_of_movement.py | 21 +- notebooks/cuIndicator/viz/ewa.py | 19 +- notebooks/cuIndicator/viz/force_index.py | 16 +- notebooks/cuIndicator/viz/keltner_channel.py | 44 ++++- notebooks/cuIndicator/viz/kst_oscillator.py | 25 ++- notebooks/cuIndicator/viz/ma.py | 15 +- notebooks/cuIndicator/viz/macd.py | 43 ++-- notebooks/cuIndicator/viz/mass_index.py | 32 +-- notebooks/cuIndicator/viz/momentum.py | 16 +- notebooks/cuIndicator/viz/money_flow_index.py | 21 +- .../cuIndicator/viz/on_balance_volume.py | 22 ++- notebooks/cuIndicator/viz/parabolic_sar.py | 92 +++++---- notebooks/cuIndicator/viz/rate_of_change.py | 21 +- notebooks/cuIndicator/viz/rsi.py | 18 +- .../viz/stochastic_oscillator_d.py | 24 ++- .../viz/stochastic_oscillator_k.py | 18 +- notebooks/cuIndicator/viz/trix.py | 17 +- .../cuIndicator/viz/true_strength_index.py | 34 ++-- .../cuIndicator/viz/ultimate_oscillator.py | 19 +- notebooks/cuIndicator/viz/vortex_indicator.py | 21 +- setup.py | 2 +- 42 files changed, 843 insertions(+), 513 deletions(-) diff --git a/docker/build.sh b/docker/build.sh index 9f3d96e7..0862ff01 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -33,7 +33,7 @@ echo -e "\nPlease, select your cuda version:\n" \ read -p "Enter your option and hit return [1]-4: " CUDA_VERSION -RAPIDS_VERSION="0.13" +RAPIDS_VERSION="0.14" CUDA_VERSION=${CUDA_VERSION:-1} case $CUDA_VERSION in diff --git a/gquant/dataframe_flow/task.py b/gquant/dataframe_flow/task.py index db0d40f9..61040907 100644 --- a/gquant/dataframe_flow/task.py +++ b/gquant/dataframe_flow/task.py @@ -3,6 +3,7 @@ import copy from .taskSpecSchema import TaskSpecSchema from ._node import _Node +from pathlib import Path __all__ = ['Task'] @@ -62,6 +63,9 @@ def get_node_obj(self, replace=None, profile=False, tgraph_mixin=False): if modulepath is not None: spec = importlib.util.spec_from_file_location(node_id, modulepath) + modulename = Path(modulepath).stem + spec = importlib.util.spec_from_file_location( + modulename, modulepath) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) NodeClass = getattr(mod, node_type) diff --git a/gquant/plugin_nodes/analysis/barPlotNode.py b/gquant/plugin_nodes/analysis/barPlotNode.py index 71787fb1..3b15bfb2 100644 --- a/gquant/plugin_nodes/analysis/barPlotNode.py +++ b/gquant/plugin_nodes/analysis/barPlotNode.py @@ -1,5 +1,8 @@ from gquant.dataframe_flow import Node from bqplot import Axis, LinearScale, DateScale, Figure, OHLC, Bars, Tooltip +import cupy as cp +import cudf +import dask_cudf class BarPlotNode(Node): @@ -39,16 +42,33 @@ def process(self, inputs): ax_y = Axis(label='Price', scale=sc, orientation='vertical', tick_format='0.0f') # Construct the marks - ohlc = OHLC(x=stock['datetime'][::stride], - y=stock[['open', 'high', 'low', 'close']] - .as_gpu_matrix()[::stride, :], - marker='candle', scales={'x': dt_scale, 'y': sc}, - format='ohlc', stroke='blue', - display_legend=True, labels=[label]) - bar = Bars(x=stock['datetime'][::stride], - y=stock['volume'][::stride], - scales={'x': dt_scale, 'y': sc2}, - padding=0.2) + if (isinstance(stock, + cudf.DataFrame) or isinstance(stock, + dask_cudf.DataFrame)): + ohlc = OHLC(x=stock['datetime'][::stride].to_array(), + y=cp.asnumpy(stock[['open', + 'high', + 'low', + 'close']].values[::stride, :]), + marker='candle', scales={'x': dt_scale, 'y': sc}, + format='ohlc', stroke='blue', + display_legend=True, labels=[label]) + bar = Bars(x=stock['datetime'][::stride].to_array(), + y=stock['volume'][::stride].to_array(), + scales={'x': dt_scale, 'y': sc2}, + padding=0.2) + else: + ohlc = OHLC(x=stock['datetime'][::stride], + y=stock[['open', + 'high', + 'low', 'close']].values[::stride, :], + marker='candle', scales={'x': dt_scale, 'y': sc}, + format='ohlc', stroke='blue', + display_legend=True, labels=[label]) + bar = Bars(x=stock['datetime'][::stride], + y=stock['volume'][::stride], + scales={'x': dt_scale, 'y': sc2}, + padding=0.2) def_tt = Tooltip(fields=['x', 'y'], formats=['%Y-%m-%d', '.2f']) bar.tooltip = def_tt bar.interactions = { diff --git a/gquant/plugin_nodes/analysis/cumReturnNode.py b/gquant/plugin_nodes/analysis/cumReturnNode.py index ab17aa54..f9eb3ad9 100644 --- a/gquant/plugin_nodes/analysis/cumReturnNode.py +++ b/gquant/plugin_nodes/analysis/cumReturnNode.py @@ -1,6 +1,7 @@ from gquant.dataframe_flow import Node from bqplot import Axis, LinearScale, DateScale, Figure, Lines, PanZoom import dask_cudf +import cudf class CumReturnNode(Node): @@ -39,10 +40,21 @@ def process(self, inputs): orientation='vertical') xax = Axis(label='Time', scale=date_co, orientation='horizontal') panzoom_main = PanZoom(scales={'x': [date_co]}) - line = Lines(x=input_df['datetime'][::stride], - y=(input_df['strategy_returns'].cumsum())[::stride], - scales={'x': date_co, 'y': linear_co}, - colors=['blue'], labels=[label], display_legend=True) + if (isinstance(input_df, + cudf.DataFrame) or isinstance(input_df, + dask_cudf.DataFrame)): + line = Lines(x=input_df['datetime'][::stride].to_array(), + y=(input_df[ + 'strategy_returns'].cumsum())[ + ::stride].to_array(), + scales={'x': date_co, 'y': linear_co}, + colors=['blue'], labels=[label], display_legend=True) + else: + line = Lines(x=input_df['datetime'][::stride], + y=(input_df[ + 'strategy_returns'].cumsum())[::stride], + scales={'x': date_co, 'y': linear_co}, + colors=['blue'], labels=[label], display_legend=True) new_fig = Figure(marks=[line], axes=[yax, xax], title='P & L', interaction=panzoom_main) return new_fig diff --git a/gquant/plugin_nodes/analysis/linePlotNode.py b/gquant/plugin_nodes/analysis/linePlotNode.py index f6021362..c04844c0 100644 --- a/gquant/plugin_nodes/analysis/linePlotNode.py +++ b/gquant/plugin_nodes/analysis/linePlotNode.py @@ -1,5 +1,7 @@ from gquant.dataframe_flow import Node from bqplot import Axis, LinearScale, DateScale, Figure, Lines, PanZoom +import cudf +import dask_cudf class LinePlotNode(Node): @@ -38,10 +40,21 @@ def process(self, inputs): col_name = line['column'] label_name = line['label'] color = line['color'] - line = Lines(x=input_df['datetime'][::stride], - y=input_df[col_name][::stride], - scales={'x': date_co, 'y': linear_co}, colors=[color], - labels=[label_name], display_legend=True) + if (isinstance(input_df, + cudf.DataFrame) or isinstance(input_df, + dask_cudf.DataFrame)): + line = Lines(x=input_df['datetime'][::stride].to_array(), + y=input_df[col_name][::stride].to_array(), + scales={'x': date_co, 'y': linear_co}, + colors=[color], + labels=[label_name], display_legend=True) + else: + line = Lines(x=input_df['datetime'][::stride], + y=input_df[col_name][::stride], + scales={'x': date_co, 'y': linear_co}, + colors=[color], + labels=[label_name], display_legend=True) + lines.append(line) new_fig = Figure(marks=lines, axes=[yax, xax], title=self.conf['title'], interaction=panzoom_main) diff --git a/notebooks/01_tutorial.ipynb b/notebooks/01_tutorial.ipynb index ac630d15..457c5f6a 100644 --- a/notebooks/01_tutorial.ipynb +++ b/notebooks/01_tutorial.ipynb @@ -347,17 +347,17 @@ "text": [ "Output of build task graph are instances of each task in a dictionary:\n", "\n", - "load_csv_data: \n", - "min_volume: \n", - "sort: \n", - "add_return: \n", - "stock_symbol: \n", - "volume_mean: \n", - "return_mean: \n", - "left_merge_1: \n", - "left_merge_2: \n", - "output_csv_1: \n", - "output_csv_2: \n", + "load_csv_data: \n", + "min_volume: \n", + "sort: \n", + "add_return: \n", + "stock_symbol: \n", + "volume_mean: \n", + "return_mean: \n", + "left_merge_1: \n", + "left_merge_2: \n", + "output_csv_1: \n", + "output_csv_2: \n", "\n" ] } @@ -453,16 +453,16 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:load_csv_data process time:3.874s\n", - "id:min_volume process time:0.199s\n", - "id:sort process time:0.125s\n", - "id:add_return process time:0.221s\n", - "id:volume_mean process time:0.050s\n", - "id:return_mean process time:0.045s\n", - "id:stock_symbol process time:0.015s\n", - "id:left_merge_1 process time:0.003s\n", + "id:load_csv_data process time:3.238s\n", + "id:min_volume process time:0.148s\n", + "id:sort process time:0.121s\n", + "id:add_return process time:0.071s\n", + "id:volume_mean process time:0.046s\n", + "id:return_mean process time:0.046s\n", + "id:stock_symbol process time:0.013s\n", + "id:left_merge_1 process time:0.002s\n", "id:output_csv_1 process time:0.020s\n", - "id:left_merge_2 process time:0.003s\n", + "id:left_merge_2 process time:0.002s\n", "id:output_csv_2 process time:0.020s\n" ] } @@ -496,11 +496,11 @@ "3 869592 56.041766 SP\n", "4 869349 91.161991 VIIX\n", "... ... ... ...\n", - "3679 5890 1386.894587 DRI\n", - "3680 5891 164.916612 DRL\n", - "3681 5893 336.161817 DRQ\n", - "3682 5896 453.901682 DSL\n", - "3683 5897 82.365824 DSM\n", + "3679 7471 271.103524 NTT\n", + "3680 7477 2820.509550 NUE\n", + "3681 7482 527.433401 NUS\n", + "3682 7484 230.687129 NUV\n", + "3683 7487 232.201717 NVO\n", "\n", "[3684 rows x 3 columns]\n", "\n", @@ -512,11 +512,11 @@ "3 869592 0.000502 SP\n", "4 708893 -0.000588 UCP\n", "... ... ... ...\n", - "3679 23748 0.001471 FBHS\n", - "3680 23750 -0.000059 BUI\n", - "3681 23752 0.006837 TEAR\n", - "3682 23755 0.000506 PUK\n", - "3683 23762 0.003529 TPLM\n", + "3679 6072 0.000109 EVT\n", + "3680 6073 0.000731 EW\n", + "3681 6089 0.000211 EXC\n", + "3682 6090 -0.000227 EXG\n", + "3683 6093 0.000657 EXP\n", "\n", "[3684 rows x 3 columns]\n" ] @@ -701,8 +701,8 @@ "output_type": "stream", "text": [ "Using in-memory dataframes for load:\n", - "CPU times: user 51 ms, sys: 804 µs, total: 51.8 ms\n", - "Wall time: 49.8 ms\n" + "CPU times: user 48.1 ms, sys: 0 ns, total: 48.1 ms\n", + "Wall time: 46 ms\n" ] } ], @@ -726,8 +726,8 @@ "output_type": "stream", "text": [ "Using cached dataframes on disk for load:\n", - "CPU times: user 61 ms, sys: 716 µs, total: 61.7 ms\n", - "Wall time: 59.2 ms\n" + "CPU times: user 54.4 ms, sys: 0 ns, total: 54.4 ms\n", + "Wall time: 51.5 ms\n" ] } ], @@ -751,7 +751,7 @@ "output_type": "stream", "text": [ "Re-running dataframes calculations instead of using load:\n", - "CPU times: user 873 ms, sys: 691 ms, total: 1.56 s\n", + "CPU times: user 1.11 s, sys: 482 ms, total: 1.6 s\n", "Wall time: 1.63 s\n" ] } @@ -781,8 +781,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 50.5 ms, sys: 8.23 ms, total: 58.8 ms\n", - "Wall time: 56.2 ms\n" + "CPU times: user 50.4 ms, sys: 3.54 ms, total: 54 ms\n", + "Wall time: 51.2 ms\n" ] } ], @@ -940,5 +940,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/notebooks/02_single_stock_trade.ipynb b/notebooks/02_single_stock_trade.ipynb index 6b341fd3..53e67b2f 100644 --- a/notebooks/02_single_stock_trade.ipynb +++ b/notebooks/02_single_stock_trade.ipynb @@ -179,7 +179,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "bef20587c5a94adbae804f78392f53b7", + "model_id": "d3289c128ab54c55862a10029b51c0a1", "version_major": 2, "version_minor": 0 }, @@ -220,7 +220,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "80e2670f612249d3ae3bb8957f34f9fd", + "model_id": "df4a18e06a4e4eb9a6d98a028f92bdcb", "version_major": 2, "version_minor": 0 }, @@ -252,7 +252,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ddef9aedb65e4bf4af3380b1e0209f27", + "model_id": "10e4f95d5b99405bb5f8eccd3b766c0e", "version_major": 2, "version_minor": 0 }, diff --git a/notebooks/03_simple_dask_example.ipynb b/notebooks/03_simple_dask_example.ipynb index c7cccf85..af7883ba 100644 --- a/notebooks/03_simple_dask_example.ipynb +++ b/notebooks/03_simple_dask_example.ipynb @@ -24,8 +24,8 @@ "\n", "

Client

\n", "\n", "\n", "\n", @@ -40,7 +40,7 @@ "" ], "text/plain": [ - "" + "" ] }, "execution_count": 2, @@ -148,14 +148,6 @@ "\n", "[19277162 rows x 7 columns]\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/opt/conda/envs/rapids/lib/python3.6/site-packages/fsspec/implementations/local.py:33: FutureWarning: The default value of auto_mkdir=True has been deprecated and will be changed to auto_mkdir=False by default in a future release.\n", - " FutureWarning,\n" - ] } ], "source": [ @@ -229,7 +221,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -250,17 +242,17 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "id:node_csvdata_dask process time:0.041s\n", - "id:node_minVolume process time:0.860s\n", - "id:node_volumeMean process time:0.110s\n", - "id:node_outputCsv process time:1.560s\n" + "id:node_csvdata_dask process time:0.029s\n", + "id:node_minVolume process time:0.815s\n", + "id:node_volumeMean process time:0.180s\n", + "id:node_outputCsv process time:0.209s\n" ] } ], @@ -270,7 +262,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -376,7 +368,7 @@ "[3684 rows x 2 columns]" ] }, - "execution_count": 9, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -413,5 +405,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/notebooks/04_portfolio_trade.ipynb b/notebooks/04_portfolio_trade.ipynb index 3b4fa69d..52bf02a4 100644 --- a/notebooks/04_portfolio_trade.ipynb +++ b/notebooks/04_portfolio_trade.ipynb @@ -265,28 +265,28 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:sort process time:0.148s\n", - "id:add_return process time:0.192s\n", - "id:add_indicator process time:0.049s\n", - "id:volume_mean process time:0.060s\n", + "id:sort process time:0.143s\n", + "id:add_return process time:0.208s\n", + "id:add_indicator process time:0.036s\n", + "id:volume_mean process time:0.064s\n", "id:rename_mean_volume process time:0.001s\n", - "id:left_merge_mean_volume process time:0.030s\n", - "id:max_returns process time:0.019s\n", + "id:left_merge_mean_volume process time:0.024s\n", + "id:max_returns process time:0.033s\n", "id:rename_max_return process time:0.001s\n", "id:left_merge_max_return process time:0.026s\n", - "id:min_returns process time:0.022s\n", + "id:min_returns process time:0.023s\n", "id:rename_min_return process time:0.001s\n", - "id:left_merge_min_return process time:0.040s\n", - "id:filter_value process time:0.312s\n", - "id:drop_columns process time:0.007s\n", - "id:sort_2 process time:0.053s\n", - "id:exp_strategy process time:0.910s\n", - "id:backtest process time:0.004s\n", - "id:portfolio_opt process time:0.041s\n", + "id:left_merge_min_return process time:0.041s\n", + "id:filter_value process time:0.277s\n", + "id:drop_columns process time:0.012s\n", + "id:sort_2 process time:0.046s\n", + "id:exp_strategy process time:1.047s\n", + "id:backtest process time:0.005s\n", + "id:portfolio_opt process time:0.038s\n", "id:sharpe_ratio process time:0.001s\n", - "id:cumlative_return process time:2.019s\n", - "CPU times: user 4.96 s, sys: 1.17 s, total: 6.13 s\n", - "Wall time: 6.27 s\n" + "id:cumlative_return process time:0.024s\n", + "CPU times: user 3.41 s, sys: 859 ms, total: 4.27 s\n", + "Wall time: 4.4 s\n" ] } ], @@ -351,7 +351,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6daf7202b3df4e94b0895510a169594c", + "model_id": "efd06170871d465ea1bb416f9454c55e", "version_major": 2, "version_minor": 0 }, @@ -402,28 +402,28 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:load_csv_data process time:89.438s\n", - "id:sort process time:5.394s\n", - "id:add_return process time:20.824s\n", - "id:add_indicator process time:6.737s\n", - "id:volume_mean process time:0.345s\n", - "id:rename_mean_volume process time:0.001s\n", - "id:left_merge_mean_volume process time:4.569s\n", - "id:max_returns process time:0.346s\n", + "id:load_csv_data process time:89.588s\n", + "id:sort process time:5.362s\n", + "id:add_return process time:20.858s\n", + "id:add_indicator process time:6.764s\n", + "id:volume_mean process time:0.360s\n", + "id:rename_mean_volume process time:0.002s\n", + "id:left_merge_mean_volume process time:4.585s\n", + "id:max_returns process time:0.342s\n", "id:rename_max_return process time:0.001s\n", - "id:left_merge_max_return process time:4.699s\n", + "id:left_merge_max_return process time:4.678s\n", "id:min_returns process time:0.345s\n", "id:rename_min_return process time:0.001s\n", - "id:left_merge_min_return process time:4.826s\n", - "id:filter_value process time:0.931s\n", - "id:drop_columns process time:0.068s\n", - "id:sort_2 process time:1.105s\n", - "id:exp_strategy process time:11.040s\n", + "id:left_merge_min_return process time:4.887s\n", + "id:filter_value process time:0.921s\n", + "id:drop_columns process time:0.067s\n", + "id:sort_2 process time:1.117s\n", + "id:exp_strategy process time:11.110s\n", "id:backtest process time:0.025s\n", - "id:portfolio_opt process time:0.310s\n", + "id:portfolio_opt process time:0.309s\n", "id:sharpe_ratio process time:0.001s\n", "id:cumlative_return process time:0.021s\n", - "CPU times: user 2min 24s, sys: 6.42 s, total: 2min 31s\n", + "CPU times: user 2min 25s, sys: 6.59 s, total: 2min 31s\n", "Wall time: 2min 31s\n" ] } @@ -452,7 +452,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "85e3e0c218b54867aa88e8efdfcb0378", + "model_id": "a73b777d37f14d6aab09385a54dce880", "version_major": 2, "version_minor": 0 }, @@ -512,8 +512,8 @@ "\n", "

Client

\n", "\n", "\n", "\n", @@ -528,7 +528,7 @@ "" ], "text/plain": [ - "" + "" ] }, "execution_count": 11, @@ -650,23 +650,23 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:load_csv_data process time:0.028s\n", - "id:volume_mean process time:0.253s\n", - "id:rename_mean_volume process time:0.011s\n", - "id:left_merge_mean_volume process time:0.294s\n", - "id:max_returns process time:0.252s\n", - "id:rename_max_return process time:0.030s\n", - "id:left_merge_max_return process time:0.027s\n", - "id:min_returns process time:0.224s\n", - "id:rename_min_return process time:0.011s\n", - "id:left_merge_min_return process time:0.027s\n", - "id:filter_value process time:0.076s\n", - "id:backtest process time:0.236s\n", - "id:portfolio_opt process time:0.135s\n", - "id:sharpe_ratio process time:0.225s\n", - "id:cumlative_return process time:2.758s\n", - "CPU times: user 10.3 s, sys: 463 ms, total: 10.8 s\n", - "Wall time: 17.5 s\n" + "id:load_csv_data process time:0.016s\n", + "id:volume_mean process time:0.339s\n", + "id:rename_mean_volume process time:0.007s\n", + "id:left_merge_mean_volume process time:0.158s\n", + "id:max_returns process time:0.148s\n", + "id:rename_max_return process time:0.007s\n", + "id:left_merge_max_return process time:0.018s\n", + "id:min_returns process time:0.153s\n", + "id:rename_min_return process time:0.008s\n", + "id:left_merge_min_return process time:0.021s\n", + "id:filter_value process time:0.021s\n", + "id:backtest process time:0.269s\n", + "id:portfolio_opt process time:0.101s\n", + "id:sharpe_ratio process time:0.185s\n", + "id:cumlative_return process time:0.212s\n", + "CPU times: user 7.48 s, sys: 343 ms, total: 7.82 s\n", + "Wall time: 14.9 s\n" ] } ], @@ -692,7 +692,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "593d8d7bd86b49bfa2f431d5f36608d4", + "model_id": "43c06cb5be434fe195ac02731767684e", "version_major": 2, "version_minor": 0 }, @@ -741,7 +741,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "9b8a889a00424555aa3af1f61ac7c9a3", + "model_id": "8d4120af2a83432eaae2041ee90f5921", "version_major": 2, "version_minor": 0 }, diff --git a/notebooks/06_xgboost_trade.ipynb b/notebooks/06_xgboost_trade.ipynb index c1cf9db8..9f2bafbb 100644 --- a/notebooks/06_xgboost_trade.ipynb +++ b/notebooks/06_xgboost_trade.ipynb @@ -67,7 +67,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "0.13.0a+4804.g6158033.dirty\n" + "0.14.0\n" ] } ], @@ -263,10 +263,6 @@ " bst = xgb.dask.train(client, dxgb_params, dmatrix,\n", " num_boost_round=num_of_rounds)\n", "\n", - " # tree_booster = bst['booster']\n", - " # delayed_fun = dask.delayed(delay_predict)\n", - " # delayedObj = [delayed_fun(delayed, tree_booster, train_cols) for delayed in input_df.to_delayed()] # noqa E501\n", - " # input_df = dask_cudf.from_delayed(delayedObj)\n", " dtrain = xgb.dask.DaskDMatrix(client, input_df[train_cols])\n", " prediction = xgb.dask.predict(client, bst, dtrain).persist()\n", " pred_df = dask_cudf.from_dask_dataframe(\n", @@ -381,34 +377,34 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:node_sort process time:0.142s\n", - "id:node_addReturn process time:0.209s\n", - "id:node_addIndicator process time:0.050s\n", + "id:node_sort process time:0.153s\n", + "id:node_addReturn process time:0.191s\n", + "id:node_addIndicator process time:0.044s\n", "id:node_volumeMean process time:0.065s\n", "id:node_renameMeanVolume process time:0.001s\n", - "id:node_leftMergeMeanVolume process time:0.042s\n", - "id:node_maxReturns process time:0.020s\n", + "id:node_leftMergeMeanVolume process time:0.036s\n", + "id:node_maxReturns process time:0.018s\n", "id:node_renameMaxReturn process time:0.001s\n", - "id:node_leftMergeMaxReturn process time:0.028s\n", - "id:node_minReturns process time:0.024s\n", + "id:node_leftMergeMaxReturn process time:0.025s\n", + "id:node_minReturns process time:0.023s\n", "id:node_renameMinReturn process time:0.001s\n", - "id:node_leftMergeMinReturn process time:0.039s\n", - "id:node_filterValue process time:0.268s\n", - "id:node_dropColumns process time:0.008s\n", - "id:node_sort2 process time:0.050s\n", - "id:node_technical_indicator process time:2.911s\n", - "id:node_xgboost_strategy process time:4.622s\n", - "id:node_backtest process time:0.007s\n", - "id:node_training_df process time:0.296s\n", - "id:node_portOpt2 process time:0.032s\n", + "id:node_leftMergeMinReturn process time:0.043s\n", + "id:node_filterValue process time:0.284s\n", + "id:node_dropColumns process time:0.012s\n", + "id:node_sort2 process time:0.046s\n", + "id:node_technical_indicator process time:4.268s\n", + "id:node_xgboost_strategy process time:5.592s\n", + "id:node_backtest process time:0.004s\n", + "id:node_training_df process time:0.137s\n", + "id:node_portOpt2 process time:0.028s\n", "id:node_sharpe_training process time:0.001s\n", - "id:node_cumlativeReturn_training process time:1.992s\n", - "id:node_testing_df process time:0.053s\n", - "id:node_portOpt1 process time:0.022s\n", + "id:node_cumlativeReturn_training process time:0.024s\n", + "id:node_testing_df process time:0.015s\n", + "id:node_portOpt1 process time:0.021s\n", "id:node_sharpe_testing process time:0.001s\n", - "id:node_cumlativeReturn_testing process time:2.125s\n", - "CPU times: user 52.4 s, sys: 2.32 s, total: 54.7 s\n", - "Wall time: 14.9 s\n" + "id:node_cumlativeReturn_testing process time:0.024s\n", + "CPU times: user 50.9 s, sys: 2.06 s, total: 53 s\n", + "Wall time: 13.1 s\n" ] } ], @@ -441,7 +437,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "fa3b59bfb8b1438d94f28f7c9295f126", + "model_id": "ad34f35de352469eb84c89fce108f893", "version_major": 2, "version_minor": 0 }, @@ -500,8 +496,8 @@ "\n", "

Client

\n", "\n", "\n", "\n", @@ -516,7 +512,7 @@ "" ], "text/plain": [ - "" + "" ] }, "execution_count": 10, @@ -550,29 +546,29 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:node_csvdata process time:0.029s\n", - "id:node_volumeMean process time:0.401s\n", - "id:node_renameMeanVolume process time:0.011s\n", - "id:node_leftMergeMeanVolume process time:0.337s\n", - "id:node_maxReturns process time:0.205s\n", - "id:node_renameMaxReturn process time:0.033s\n", - "id:node_leftMergeMaxReturn process time:0.032s\n", - "id:node_minReturns process time:0.293s\n", - "id:node_renameMinReturn process time:0.024s\n", - "id:node_leftMergeMinReturn process time:0.031s\n", - "id:node_filterValue process time:0.068s\n", - "id:node_xgboost_strategy process time:13.928s\n", - "id:node_backtest process time:0.163s\n", - "id:node_training_df process time:0.314s\n", - "id:node_portOpt2 process time:0.131s\n", - "id:node_sharpe_training process time:0.244s\n", - "id:node_cumlativeReturn_training process time:2.776s\n", - "id:node_testing_df process time:0.078s\n", - "id:node_portOpt1 process time:0.116s\n", - "id:node_sharpe_testing process time:0.218s\n", - "id:node_cumlativeReturn_testing process time:2.989s\n", - "CPU times: user 19 s, sys: 953 ms, total: 20 s\n", - "Wall time: 45.6 s\n" + "id:node_csvdata process time:0.021s\n", + "id:node_volumeMean process time:0.375s\n", + "id:node_renameMeanVolume process time:0.009s\n", + "id:node_leftMergeMeanVolume process time:0.084s\n", + "id:node_maxReturns process time:0.155s\n", + "id:node_renameMaxReturn process time:0.012s\n", + "id:node_leftMergeMaxReturn process time:0.018s\n", + "id:node_minReturns process time:0.037s\n", + "id:node_renameMinReturn process time:0.020s\n", + "id:node_leftMergeMinReturn process time:0.018s\n", + "id:node_filterValue process time:0.017s\n", + "id:node_xgboost_strategy process time:14.271s\n", + "id:node_backtest process time:0.065s\n", + "id:node_training_df process time:0.031s\n", + "id:node_portOpt2 process time:0.078s\n", + "id:node_sharpe_training process time:0.183s\n", + "id:node_cumlativeReturn_training process time:0.230s\n", + "id:node_testing_df process time:0.026s\n", + "id:node_portOpt1 process time:0.109s\n", + "id:node_sharpe_testing process time:0.206s\n", + "id:node_cumlativeReturn_testing process time:0.237s\n", + "CPU times: user 13.5 s, sys: 683 ms, total: 14.2 s\n", + "Wall time: 39.7 s\n" ] } ], @@ -598,7 +594,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "5abf39fcb16c4014b732a810cf4663cf", + "model_id": "a7e0030608684773bb5f33b5987e13cc", "version_major": 2, "version_minor": 0 }, @@ -764,19 +760,19 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:node_technical_indicator process time:3.692s\n", - "id:node_xgboost_strategy process time:41.486s\n", - "id:node_backtest process time:0.005s\n", - "id:node_training_df process time:0.082s\n", - "id:node_portOpt2 process time:0.039s\n", - "id:node_sharpe_training process time:0.001s\n", - "id:node_cumlativeReturn_training process time:2.340s\n", - "id:node_testing_df process time:0.056s\n", - "id:node_portOpt1 process time:0.025s\n", - "id:node_sharpe_testing process time:0.001s\n", - "id:node_cumlativeReturn_testing process time:2.384s\n", - "CPU times: user 50.2 s, sys: 3.46 s, total: 53.7 s\n", - "Wall time: 50.2 s\n" + "id:node_technical_indicator process time:5.504s\n", + "id:node_xgboost_strategy process time:40.547s\n", + "id:node_backtest process time:0.004s\n", + "id:node_training_df process time:0.020s\n", + "id:node_portOpt2 process time:0.036s\n", + "id:node_sharpe_training process time:0.002s\n", + "id:node_cumlativeReturn_training process time:0.026s\n", + "id:node_testing_df process time:0.036s\n", + "id:node_portOpt1 process time:0.027s\n", + "id:node_sharpe_testing process time:0.002s\n", + "id:node_cumlativeReturn_testing process time:0.025s\n", + "CPU times: user 46.2 s, sys: 3.12 s, total: 49.3 s\n", + "Wall time: 46.3 s\n" ] } ], @@ -798,7 +794,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "cfd1053b94bb42b08675522f2739e8b6", + "model_id": "e6be0949c0f445a4986078cb618d8f66", "version_major": 2, "version_minor": 0 }, @@ -832,29 +828,29 @@ "name": "stdout", "output_type": "stream", "text": [ - "id:node_csvdata process time:0.022s\n", - "id:node_volumeMean process time:0.407s\n", - "id:node_renameMeanVolume process time:0.024s\n", - "id:node_leftMergeMeanVolume process time:0.274s\n", - "id:node_maxReturns process time:0.081s\n", - "id:node_renameMaxReturn process time:0.024s\n", - "id:node_leftMergeMaxReturn process time:0.029s\n", - "id:node_minReturns process time:0.363s\n", - "id:node_renameMinReturn process time:0.012s\n", - "id:node_leftMergeMinReturn process time:0.029s\n", - "id:node_filterValue process time:0.255s\n", - "id:node_xgboost_strategy process time:40.088s\n", - "id:node_backtest process time:0.145s\n", - "id:node_training_df process time:0.127s\n", - "id:node_portOpt2 process time:0.126s\n", - "id:node_sharpe_training process time:0.210s\n", - "id:node_cumlativeReturn_training process time:2.863s\n", - "id:node_testing_df process time:0.070s\n", - "id:node_portOpt1 process time:0.113s\n", - "id:node_sharpe_testing process time:0.226s\n", - "id:node_cumlativeReturn_testing process time:2.890s\n", - "CPU times: user 22.3 s, sys: 1.24 s, total: 23.5 s\n", - "Wall time: 1min 12s\n" + "id:node_csvdata process time:0.014s\n", + "id:node_volumeMean process time:0.339s\n", + "id:node_renameMeanVolume process time:0.019s\n", + "id:node_leftMergeMeanVolume process time:0.199s\n", + "id:node_maxReturns process time:0.130s\n", + "id:node_renameMaxReturn process time:0.010s\n", + "id:node_leftMergeMaxReturn process time:0.017s\n", + "id:node_minReturns process time:0.140s\n", + "id:node_renameMinReturn process time:0.010s\n", + "id:node_leftMergeMinReturn process time:0.016s\n", + "id:node_filterValue process time:0.237s\n", + "id:node_xgboost_strategy process time:38.422s\n", + "id:node_backtest process time:0.049s\n", + "id:node_training_df process time:0.028s\n", + "id:node_portOpt2 process time:0.088s\n", + "id:node_sharpe_training process time:0.191s\n", + "id:node_cumlativeReturn_training process time:0.225s\n", + "id:node_testing_df process time:0.010s\n", + "id:node_portOpt1 process time:0.078s\n", + "id:node_sharpe_testing process time:0.209s\n", + "id:node_cumlativeReturn_testing process time:0.224s\n", + "CPU times: user 15.1 s, sys: 1.02 s, total: 16.1 s\n", + "Wall time: 1min 4s\n" ] } ], @@ -894,7 +890,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "f2f2e7ebe5854a3980c882cf6c094e79", + "model_id": "ba5009ac42c2487b9239be3a0eb36096", "version_major": 2, "version_minor": 0 }, @@ -935,7 +931,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "49fbb4fd22864b7a8f04fd0234687e81", + "model_id": "95c0f229db7d463d994ee9cf8dffb287", "version_major": 2, "version_minor": 0 }, diff --git a/notebooks/07_fractional_differencing.ipynb b/notebooks/07_fractional_differencing.ipynb index 64af72fe..4765cd78 100644 --- a/notebooks/07_fractional_differencing.ipynb +++ b/notebooks/07_fractional_differencing.ipynb @@ -415,10 +415,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "array size 100000, Ensemble: time 0.404 s, gQuant GPU Time 0.483 s, gQuant CPU Time 0.742, speed up 0.84, speed up vs CPU 1.54, error 0.0000 \n", - "array size 1000000, Ensemble: time 0.085 s, gQuant GPU Time 0.007 s, gQuant CPU Time 0.042, speed up 12.07, speed up vs CPU 5.98, error 0.0000 \n", - "array size 10000000, Ensemble: time 0.774 s, gQuant GPU Time 0.010 s, gQuant CPU Time 0.287, speed up 78.79, speed up vs CPU 29.26, error 0.0000 \n", - "array size 100000000, Ensemble: time 6.987 s, gQuant GPU Time 0.052 s, gQuant CPU Time 2.533, speed up 133.71, speed up vs CPU 48.47, error 0.0000 \n" + "array size 100000, Ensemble: time 0.440 s, gQuant GPU Time 0.601 s, gQuant CPU Time 0.811, speed up 0.73, speed up vs CPU 1.35, error 0.0000 \n", + "array size 1000000, Ensemble: time 0.077 s, gQuant GPU Time 0.011 s, gQuant CPU Time 0.035, speed up 6.75, speed up vs CPU 3.11, error 0.0000 \n", + "array size 10000000, Ensemble: time 0.734 s, gQuant GPU Time 0.015 s, gQuant CPU Time 0.277, speed up 49.20, speed up vs CPU 18.56, error 0.0000 \n", + "array size 100000000, Ensemble: time 6.987 s, gQuant GPU Time 0.072 s, gQuant CPU Time 2.611, speed up 96.83, speed up vs CPU 36.20, error 0.0000 \n" ] } ], @@ -630,13 +630,13 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "04598428378f472b8082afae88dd699f", + "model_id": "2588c9fbcbb648e0941d3a1cb469bf3b", "version_major": 2, "version_minor": 0 }, @@ -679,7 +679,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -735,13 +735,13 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "62ff240e01f24dc28e2fa8f74be67832", + "model_id": "d0384d05ae654f5a98f1c95b95ef9476", "version_major": 2, "version_minor": 0 }, @@ -811,5 +811,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/notebooks/cuIndicator/indicator_demo.ipynb b/notebooks/cuIndicator/indicator_demo.ipynb index 757fcff5..694ada4e 100644 --- a/notebooks/cuIndicator/indicator_demo.ipynb +++ b/notebooks/cuIndicator/indicator_demo.ipynb @@ -26,7 +26,7 @@ ], "source": [ "! ((test ! -f '../data/stock_price_hist.csv.gz' || test ! -f '../data/security_master.csv.gz') && \\\n", - " cd ../.. && bash download_data.sh) || echo \"Dataset is already present. No need to re-download it.\"" + " cd ../.. && bash download_data.sh) || echo \"Dataset is already present. No need to re-download it.\" " ] }, { @@ -40,7 +40,8 @@ "import datetime\n", "import ipywidgets as widgets\n", "import numpy as np\n", - "import pandas as pd" + "import pandas as pd\n", + "import cupy as cp" ] }, { @@ -49,7 +50,7 @@ "metadata": {}, "outputs": [], "source": [ - "import sys; sys.path.append('../..')\n", + "import sys; sys.path.insert(0, '../..')\n", "\n", "from gquant.dataframe_flow import TaskSpecSchema\n", "\n", @@ -126,7 +127,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "f3a3621fc2104f31b96493bbe902121c", + "model_id": "8e5aeebdbace4dfea6243eea66b13fde", "version_major": 2, "version_minor": 0 }, @@ -159,9 +160,9 @@ " ax_x = Axis(label='Date', scale=dt_scale)\n", " ax_y = Axis(label='Price', scale=sc, orientation='vertical', tick_format='0.0f')\n", " # Construct the marks\n", - " ohlc = OHLC(x=stock.datetime, y=stock[['open','high','low', 'close']].as_gpu_matrix(), marker='candle', scales={'x': dt_scale, 'y': sc}, format='ohlc',\n", + " ohlc = OHLC(x=stock.datetime.to_array(), y=cp.asnumpy(stock[['open','high','low', 'close']].values), marker='candle', scales={'x': dt_scale, 'y': sc}, format='ohlc',\n", " stroke='blue', display_legend=True, labels=[selected])\n", - " bar = Bars(x=stock.datetime, y=stock.volume, \n", + " bar = Bars(x=stock.datetime.to_array(), y=stock.volume.to_array(), \n", " scales={'x': dt_scale, 'y': sc2}, padding=0.2)\n", " def_tt = Tooltip(fields=['x', 'y'], formats=['%Y-%m-%d', '.2f'])\n", " bar.tooltip = def_tt\n", @@ -183,11 +184,11 @@ " \n", " def update_graph(stock):\n", " with bar.hold_trait_notifications() as bc, ohlc.hold_trait_notifications() as oc:\n", - " ohlc.y = stock[['open','high','low', 'close']].as_gpu_matrix()\n", - " ohlc.x = stock.datetime\n", + " ohlc.y = cp.asnumpy(stock[['open','high','low', 'close']].values)\n", + " ohlc.x = stock.datetime.to_array()\n", " \n", - " bar.y = stock.volume\n", - " bar.x = stock.datetime\n", + " bar.y = stock.volume.to_array()\n", + " bar.x = stock.datetime.to_array()\n", " \n", " sc.min = stock.close.min() - 0.3 * (stock.close.max() - stock.close.min()) \n", " sc.max = stock.close.max()\n", @@ -202,8 +203,8 @@ " \n", " def stock_selection(*stock):\n", " this_stock_store[0] = one_stock(df, list_stocks[stock_selector.value])\n", - " year_selector.min = this_stock_store[0].Dte.to_array().min().astype(datetime.datetime).year\n", - " year_selector.max = this_stock_store[0].Dte.to_array().max().astype(datetime.datetime).year\n", + " year_selector.min = this_stock_store[0].datetime.dt.year.min()\n", + " year_selector.max = this_stock_store[0].datetime.dt.year.max()\n", " stock = slice_stock(this_stock_store[0], year_selector.value)\n", " ohlc.labels = [stock_selector.value]\n", " update_graph(stock)\n", @@ -211,8 +212,8 @@ " def update_figure_(stock, objects):\n", " line = objects[0]\n", " with line.hold_trait_notifications():\n", - " line.y = stock['out']\n", - " line.x = stock.datetime\n", + " line.y = stock['out'].to_array()\n", + " line.x = stock.datetime.to_array()\n", " \n", " def add_new_indicator(new_fig):\n", " # add new figure\n", @@ -297,7 +298,7 @@ " from viz.force_index import get_para_widgets, get_parameters, process_outputs, create_figure, indicator_fun\n", "\n", " elif indicator_selector.value=='Keltner Channel':\n", - " from viz.keltner_channel import get_para_widgets, get_parameters, process_outputs, create_figure, indicator_fun \n", + " from viz.keltner_channel import get_para_widgets, get_parameters, process_outputs, create_figure, indicator_fun, update_figure \n", "\n", " elif indicator_selector.value=='KST Oscillator':\n", " from viz.kst_oscillator import get_para_widgets, get_parameters, process_outputs, create_figure, indicator_fun\n", @@ -316,7 +317,7 @@ " elif indicator_selector.value=='Money Flow Index':\n", " from viz.money_flow_index import get_para_widgets, get_parameters, process_outputs, create_figure, indicator_fun\n", "\n", - " elif indicator_selector.value=='On Balance volume':\n", + " elif indicator_selector.value=='On Balance Volume':\n", " from viz.on_balance_volume import get_para_widgets, get_parameters, process_outputs, create_figure, indicator_fun\n", "\n", " elif indicator_selector.value=='Parabolic SAR':\n", @@ -410,7 +411,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "dd37ad79dadd4362a1266fda125ee788", + "model_id": "66e9569cfac342c6a53d5e56330d1cd8", "version_major": 2, "version_minor": 0 }, @@ -426,6 +427,20 @@ "out" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/notebooks/cuIndicator/rsi_perf.ipynb b/notebooks/cuIndicator/rsi_perf.ipynb index 06739601..ea91691f 100644 --- a/notebooks/cuIndicator/rsi_perf.ipynb +++ b/notebooks/cuIndicator/rsi_perf.ipynb @@ -37,7 +37,8 @@ "from numba import njit\n", "from numba import prange\n", "import math\n", - "from dateutil import relativedelta" + "from dateutil import relativedelta\n", + "import cupy as cp" ] }, { @@ -207,7 +208,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -265,7 +266,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -337,13 +338,13 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ebc595e4f7854d299f2b6fbd43f0ad94", + "model_id": "a3f8d7d9764542e885dcd698db01361a", "version_major": 2, "version_minor": 0 }, @@ -379,9 +380,9 @@ " # Construct the marks\n", " tdp = stock.Dte.shape[0]\n", " skips = tdp // plot_dp\n", - " ohlc = OHLC(x=stock.Dte[::skips], y=stock[['Open','High','Low', 'Close']].as_gpu_matrix()[::skips, :], marker='candle', scales={'x': dt_scale, 'y': sc}, format='ohlc',\n", + " ohlc = OHLC(x=stock.Dte[::skips].to_array(), y=cp.asnumpy(stock[['Open','High','Low', 'Close']].values[::skips, :]), marker='candle', scales={'x': dt_scale, 'y': sc}, format='ohlc',\n", " stroke='blue', display_legend=True, labels=[selected])\n", - " bar = Bars(x=stock.Dte[::skips], y=stock.Volume[::skips], \n", + " bar = Bars(x=stock.Dte[::skips].to_array(), y=stock.Volume[::skips].to_array(), \n", " scales={'x': dt_scale, 'y': sc2}, padding=0.2)\n", " def_tt = Tooltip(fields=['x', 'y'], formats=['%Y-%m-%d', '.2f'])\n", " bar.tooltip = def_tt\n", @@ -405,11 +406,11 @@ " with bar.hold_trait_notifications() as bc, ohlc.hold_trait_notifications() as oc:\n", " tdp = stock.Dte.shape[0]\n", " skips = tdp // plot_dp\n", - " ohlc.y = stock[['Open','High','Low', 'Close']].as_gpu_matrix()[::skips, :]\n", - " ohlc.x = stock.Dte[::skips]\n", + " ohlc.y = cp.asnumpy(stock[['Open','High','Low', 'Close']].values[::skips, :])\n", + " ohlc.x = stock.Dte[::skips].to_array()\n", " \n", - " bar.y = stock.Volume[::skips]\n", - " bar.x = stock.Dte[::skips]\n", + " bar.y = stock.Volume[::skips].to_array()\n", + " bar.x = stock.Dte[::skips].to_array()\n", " \n", " sc.min = stock.Close.min() - 0.3 * (stock.Close.max() - stock.Close.min()) \n", " sc.max = stock.Close.max()\n", @@ -436,8 +437,8 @@ " with line.hold_trait_notifications():\n", " tdp = stock.Dte.shape[0]\n", " skips = tdp // plot_dp\n", - " line.y = stock['out'][::skips]\n", - " line.x = stock.Dte[::skips]\n", + " line.y = stock['out'][::skips].to_array()\n", + " line.x = stock.Dte[::skips].to_array()\n", " \n", " def add_new_indicator(new_fig):\n", " # add new figure\n", @@ -516,7 +517,7 @@ " skips = tdp // plot_dp\n", " sc_co = LinearScale()\n", " ax_y = Axis(label='RSI(GPU)', scale=sc_co, orientation='vertical')\n", - " new_line = Lines(x=stock.Dte[::skips], y=stock['out'][::skips], scales={'x': dt_scale, 'y': sc_co}, colors=[CATEGORY20[color_id[0]]])\n", + " new_line = Lines(x=stock.Dte[::skips].to_array(), y=stock['out'][::skips].to_array(), scales={'x': dt_scale, 'y': sc_co}, colors=[CATEGORY20[color_id[0]]])\n", " new_fig = Figure(marks=[new_line], axes=[ax_y])\n", " new_fig.layout.height = indicator_figure_height\n", " new_fig.layout.width = figure_width \n", @@ -549,7 +550,7 @@ " skips = tdp // plot_dp\n", " sc_co = LinearScale()\n", " ax_y = Axis(label='RSI(CPU)', scale=sc_co, orientation='vertical')\n", - " new_line = Lines(x=stock.Dte[::skips], y=stock['out'][::skips], scales={'x': dt_scale, 'y': sc_co}, colors=[CATEGORY20[color_id[0]]])\n", + " new_line = Lines(x=stock.Dte[::skips].to_array(), y=stock['out'][::skips].to_array(), scales={'x': dt_scale, 'y': sc_co}, colors=[CATEGORY20[color_id[0]]])\n", " new_fig = Figure(marks=[new_line], axes=[ax_y])\n", " new_fig.layout.height = indicator_figure_height\n", " new_fig.layout.width = figure_width \n", @@ -628,18 +629,18 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ef7aeb5f807c4854a8b553a2b0db8dac", + "model_id": "834a805dbdc14be4a88ef21abc228589", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "Output(layout=Layout(border='1px solid black'), outputs=({'name': 'stdout', 'text': \" Date: Wed, 8 Jul 2020 20:09:37 -0700 Subject: [PATCH 4/5] Fix mortgage e2e example for rapids 0.14. --- .../mortgage_e2e_gquant.ipynb | 406 ++++++++++-------- .../mortgage_gquant_plugins.py | 70 +-- 2 files changed, 263 insertions(+), 213 deletions(-) diff --git a/notebooks/mortgage_e2e_gquant/mortgage_e2e_gquant.ipynb b/notebooks/mortgage_e2e_gquant/mortgage_e2e_gquant.ipynb index e2151847..45c491a3 100644 --- a/notebooks/mortgage_e2e_gquant/mortgage_e2e_gquant.ipynb +++ b/notebooks/mortgage_e2e_gquant/mortgage_e2e_gquant.ipynb @@ -44,7 +44,7 @@ { "data": { "text/plain": [ - "1821" + "0" ] }, "execution_count": 1, @@ -278,14 +278,13 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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pqmpyaqrq+XTgoOD2d69e/vUbsfOxMPt9tajdq56mqk7Hfel+fM39orauXrU+9GTdXnllVcYALZ27VqWmprK2tvb/3IduTRt2jS2ZcsWhbRdXl7OALDExESFtN8XOjo6DACTSCRd5jk5OXUpNnr6We5tofTnI2+vv/46A8CuXbv2RNmnTp2qkEKJtuXBvy13kMlkzNDQkP3nP//pc1v/8z//w+zs7PohVe80NzczZ2dnNm3aNNba2spZDkIIGS66XKPU0NAAfX39vp7R1y8ePHiA+vp6yGQy6OnpdbkOKSMjAwBQUFAgf80bb7yBpqYmfPnllwCA/Px8nD9/vtP1B71pt4OWltagWNf6+nq89957cHJygoGBgXy5N998E8Af17oMhO7ej56uy/79+3H48GEUFRXB19cXurq6CAoKQmRk5ICsQ0/o6+ujvr5eIW3X1tYCAAwMDBTSfm89ePAAEokE6urq0NbW7jLfxMSky/K93b56Sk9Pr9PvHdd0dVzb87jsinivaVseGttyBx6PB0NDQ/n21xetra2cXleorq6OI0eOIDMzE//61784y0EIIcNFl0JpzJgxuH37NgdRulJTU4O+vj5UVFTQ1tYG9scRsC4Pb29v+WueffZZWFlZ4d///jcePHiATz/9FGvXroWOjk6f2h1s6yoQCLBjxw6sXbsW+fn5kMlkYIzhs88+A4AuNyB83NDSSkpKaG1t7TK9rq5O4evC4/Hwwgsv4MyZM6irq8Px48fBGENISEi/jkjVH27dugULCwuFtG1paQklJSUUFhYqpP3eUlNTg46ODlpaWnD//v0u8/988fpg2r4el10R98eibXlobMsdmpqaUFJSAmtr6z631dbWxvkALI6Ojvj000+xc+dOXLhwgdMshBAy1HUplHx9fZGVlTVgdxd/nI4hmZOTk7vM27VrF6ytrTsN2ayiooLNmzejqqoKn376KY4ePYpNmzb1ud2B8KSZpFIpkpOTYWZmhk2bNsHY2Fi+89Tc3Nxt25qamp12niZMmICvv/5a/ru5uTlKS0s7vaaiogJ3795V6LoAfxylyc3NBQCoqqrC399fPiLXyZMne9W/Ily/fh0FBQXw8/NTSPs6OjqYNWsWfvzxR4W03xdz584F8McIag+rrq7u9t+KwbR9PSp7RUUF8vPzFdInbcuDe1t+WEREBKRSKQIC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50wgELBvvvmG71L6TTNimqurKzt06BBTKBSspKSEPf3008zFxYUVFxdrrd/TDfsalZWVzM/Pj/n6+rIjR44wuVzOamtr2ZdffsksLS21Bo148MEHGQD2v//7v6y6upo1NzezX3/9lXl5eTEA7JdfftFqe/78+UwqlbKbN2+ylJQUZmpqyrKzs/vcb3/dazCHb775hgG46+P8+fNar+np/Zw3b163fUVERDArKyutZXeOeqdQKLRGvdu5c2ev+nz55ZcZAPb777/36v24U0/t8vWZYIyxZ555hgFgn3zyCVMqlezGjRvskUceYe7u7ncdzGEgPt9SqZRFRESwrKws1trayiorK9nWrVsZALZ9+/Z+vceDQXZ2NpPJZGzhwoVMrVbrpc/58+ez+fPn66Wve5k4cSLbuHEj32UQQsiAoKBEdOrVV19lAoGAbd68mbW3t/NdTr/U1NSw5557jvn4+DCRSMRcXV3ZypUrWW5uLrfO+fPnu93x705tbS174YUXmK+vLxOJRMzJyYnNnTu3y05udXU1W79+PfP09GQikYi5uLiwJ554gm3evJlr//ZRxK5fv86mTZvGrKysmKenJ/vss8/61W9faIar7u5x57DbixYt6nVQ6u79fPXVV7khkW9//POf/2Tnzp3rsvz111/n+r7zdyiVStm8efPYqVOnuHV66pMx1mX5okWLev0e7d+//56hkK/PhFwuZ2vXrmWurq5MLBaz8PBwlpaWxsLCwrj2Xn75ZZ18vjMzM9n69etZQEAAs7S0ZPb29mzSpEls165drLOzs9fv72By8OBBJpVK2ZQpU5hCodBbv3FxcczExIT3qRjUajWztrZmu3fv5rUOQggZKALG7rionZAB9s0332DDhg0YMWIEdu7ciYkTJ/JdEiGEDJjKykps2rQJ33//PZ544gl8+eWXeru0FADa29vh4eGBjRs34rXXXtNbv3fKzc3FqFGjkJaW1mVESkIIMUR0jxLRuTVr1uDSpUtwcHDA5MmTsWzZMr0NY0wIIbpSX1+P1157DX5+fjhz5gwOHjyIb775Rq8hCfhjRMZHHnkEP/zwg177vVNWVhaEQiGNeEcIMRoUlIheDB8+HL/++isOHDiAvLw8jB49GosWLcLJkye7jNRFCCGDWV5eHp599ll4eXnhiy++wJYtW5CTk4PIyEjeanrkkUdw/fp1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\n", "text/plain": [ "" ] }, - "execution_count": 4, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ @@ -312,8 +311,16 @@ "name": "stdout", "output_type": "stream", "text": [ - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q1.txt_0\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q1.txt\n" + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q1.txt_0\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q1.txt\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/envs/rapids/lib/python3.6/site-packages/cudf/core/join/join.py:354: UserWarning: can't safely cast column from right with type int64 to float32, upcasting to float64\n", + " \"right\", dtype_r, dtype_l, libcudf_join_type\n" ] } ], @@ -354,24 +361,54 @@ "output_type": "stream", "text": [ "Mortgage Workflow Ouput CUDF Dataframe:\n", - " servicer interest_rate current_actual_upb loan_age remaining_months_to_legal_maturity adj_remaining_months_to_maturity msa ... relocation_mortgage_indicator\n", - "0 -1.0 8.0 74319.0 12.0 348.0 347.0 0.0 ... -1.0\n", - "1 -1.0 8.0 73635.48 24.0 336.0 335.0 0.0 ... -1.0\n", - "2 -1.0 8.0 72795.41 36.0 324.0 322.0 0.0 ... -1.0\n", - "3 -1.0 8.0 -1.0 1.0 359.0 358.0 0.0 ... -1.0\n", - "4 -1.0 8.0 74264.14 13.0 347.0 346.0 0.0 ... -1.0\n", - "5 -1.0 8.0 73576.06 25.0 335.0 334.0 0.0 ... -1.0\n", - "6 -1.0 8.0 72680.39 37.0 323.0 320.0 0.0 ... -1.0\n", - "7 -1.0 8.0 -1.0 2.0 358.0 357.0 0.0 ... -1.0\n", - "8 -1.0 8.0 74208.91 14.0 346.0 345.0 0.0 ... -1.0\n", - "9 -1.0 8.0 73516.25 26.0 334.0 333.0 0.0 ... -1.0\n", - "[9094668 more rows]\n", - "[38 more columns]\n" + " servicer interest_rate current_actual_upb loan_age \\\n", + "0 -1.0 8.375 -1.000000 5.0 \n", + "1 -1.0 8.375 65612.929688 17.0 \n", + "2 -1.0 8.375 65029.691406 29.0 \n", + "3 -1.0 8.375 64395.671875 41.0 \n", + "4 -1.0 8.375 63706.460938 53.0 \n", + "\n", + " remaining_months_to_legal_maturity adj_remaining_months_to_maturity \\\n", + "0 355.0 355.0 \n", + "1 343.0 342.0 \n", + "2 331.0 330.0 \n", + "3 319.0 318.0 \n", + "4 307.0 306.0 \n", + "\n", + " msa current_loan_delinquency_status mod_flag zero_balance_code ... \\\n", + "0 12100.0 0.0 0.0 -1.0 ... \n", + "1 12100.0 0.0 0.0 -1.0 ... \n", + "2 12100.0 0.0 0.0 -1.0 ... \n", + "3 12100.0 0.0 0.0 -1.0 ... \n", + "4 12100.0 0.0 0.0 -1.0 ... \n", + "\n", + " property_type num_units occupancy_status property_state zip \\\n", + "0 -1.0 -1.0 -1.0 -1.0 -1.0 \n", + "1 -1.0 -1.0 -1.0 -1.0 -1.0 \n", + "2 -1.0 -1.0 -1.0 -1.0 -1.0 \n", + "3 -1.0 -1.0 -1.0 -1.0 -1.0 \n", + "4 -1.0 -1.0 -1.0 -1.0 -1.0 \n", + "\n", + " mortgage_insurance_percent product_type coborrow_credit_score \\\n", + "0 -1.0 -1.0 -1.0 \n", + "1 -1.0 -1.0 -1.0 \n", + "2 -1.0 -1.0 -1.0 \n", + "3 -1.0 -1.0 -1.0 \n", + "4 -1.0 -1.0 -1.0 \n", + "\n", + " mortgage_insurance_type relocation_mortgage_indicator \n", + "0 -1.0 -1.0 \n", + "1 -1.0 -1.0 \n", + "2 -1.0 -1.0 \n", + "3 -1.0 -1.0 \n", + "4 -1.0 -1.0 \n", + "\n", + "[5 rows x 46 columns]\n" ] } ], "source": [ - "print('Mortgage Workflow Ouput CUDF Dataframe:\\n', final_perf_acq_df)" + "print('Mortgage Workflow Ouput CUDF Dataframe:\\n', final_perf_acq_df.head())" ] }, { @@ -390,8 +427,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "pid, process_name, used_gpu_memory [MiB]\n", - "8165, /home/avolkov/progs/python_installs/miniconda3/envs/py36-rapids/bin/python, 1863 MiB\n" + "pid, process_name, used_gpu_memory [MiB]\r\n", + "30682, [Not Found], 2211 MiB\r\n" ] } ], @@ -415,8 +452,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "pid, process_name, used_gpu_memory [MiB]\n", - "8165, /home/avolkov/progs/python_installs/miniconda3/envs/py36-rapids/bin/python, 207 MiB\n" + "pid, process_name, used_gpu_memory [MiB]\r\n", + "30682, [Not Found], 581 MiB\r\n" ] } ], @@ -494,14 +531,13 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] }, - "execution_count": 9, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ @@ -575,7 +611,6 @@ " 'n_gpus': ngpus,\n", " # 'distributed_dask': True,\n", " 'loss': 'ls',\n", - " # 'objective': 'gpu:reg:linear',\n", " 'objective': 'reg:squarederror',\n", " 'max_features': 'auto',\n", " 'criterion': 'friedman_mse',\n", @@ -636,73 +671,86 @@ "name": "stdout", "output_type": "stream", "text": [ - "mortgage_workflow_runner:INFO: TRYING TO LOAD 12 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q1.txt_0\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q1.txt\n", - "mortgage_workflow_runner:INFO: LOADED 1 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q2.txt_0\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q2.txt\n", - "mortgage_workflow_runner:INFO: LOADED 2 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q3.txt_0\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q3.txt\n", - "mortgage_workflow_runner:INFO: LOADED 3 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q4.txt_1\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q4.txt\n", - "mortgage_workflow_runner:INFO: LOADED 4 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q4.txt_0\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q4.txt\n", - "mortgage_workflow_runner:INFO: LOADED 5 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q1.txt_1\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q1.txt\n", - "mortgage_workflow_runner:INFO: LOADED 6 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q1.txt_0\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q1.txt\n", - "mortgage_workflow_runner:INFO: LOADED 7 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_1_1\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", - "mortgage_workflow_runner:INFO: LOADED 8 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_1_0\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", - "mortgage_workflow_runner:INFO: LOADED 9 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_0_1\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", - "mortgage_workflow_runner:INFO: LOADED 10 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_0_0\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", - "mortgage_workflow_runner:INFO: LOADED 11 FRAMES\n", - "perfdata:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q3.txt_1_1\n", - "acqdata:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q3.txt\n", - "mortgage_workflow_runner:INFO: LOADED 12 FRAMES\n", - "mortgage_workflow_runner:INFO: HOST RAM (MB) TOTAL 128904; USED 17461; FREE 93503\n", - "mortgage_workflow_runner:INFO: RUN PYTHON GARBAGE COLLECTION TO MAYBE CLEAR CPU AND GPU MEMORY\n", - "mortgage_workflow_runner:INFO: HOST RAM (MB) TOTAL 128904; USED 17460; FREE 93504\n", - "mortgage_workflow_runner:INFO: USING ARROW\n", - "mortgage_workflow_runner:INFO: ARROW TO PANDAS\n", - "mortgage_workflow_runner:INFO: HOST RAM (MB) TOTAL 128904; USED 32872; FREE 78092\n", - "xgb_trainer:INFO: JUST BEFORE DMATRIX\n", - "xgb_trainer:INFO: HOST RAM (MB) TOTAL 128904; USED 17559; FREE 93405\n", - "xgb_trainer:INFO: CREATING DMATRIX\n" + "mortgage_gquant_plugins:INFO: TRYING TO LOAD 12 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q1.txt_0\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q1.txt\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "/home/avolkov/progs/python_installs/miniconda3/envs/py36-rapids/lib/python3.6/site-packages/xgboost-0.83.dev0-py3.6.egg/xgboost/core.py:604: FutureWarning: Series.base is deprecated and will be removed in a future version\n", - " if getattr(data, 'base', None) is not None and \\\n" + "/opt/conda/envs/rapids/lib/python3.6/site-packages/cudf/core/join/join.py:354: UserWarning: can't safely cast column from right with type int64 to float32, upcasting to float64\n", + " \"right\", dtype_r, dtype_l, libcudf_join_type\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "xgb_trainer:INFO: JUST AFTER DMATRIX\n", - "xgb_trainer:INFO: HOST RAM (MB) TOTAL 128904; USED 63791; FREE 47174\n", - "xgb_trainer:INFO: CLEAR MEMORY JUST BEFORE XGBOOST TRAINING\n", - "xgb_trainer:INFO: HOST RAM (MB) TOTAL 128904; USED 48713; FREE 62252\n", - "xgb_trainer:INFO: RUNNING XGBOOST TRAINING\n", + "mortgage_gquant_plugins:INFO: LOADED 1 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q2.txt_0\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q2.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 2 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q3.txt_0\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q3.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 3 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q4.txt_1\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q4.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 4 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2000Q4.txt_0\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2000Q4.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 5 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q1.txt_1\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q1.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 6 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q1.txt_0\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q1.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 7 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_1_1\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 8 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_1_0\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 9 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_0_1\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 10 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_0_0\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 11 FRAMES\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/perf/Performance_2001Q3.txt_1_1\n", + "mortgage_gquant_plugins:INFO: LOADING: ./mortgage_data/acq/Acquisition_2001Q3.txt\n", + "mortgage_gquant_plugins:INFO: LOADED 12 FRAMES\n", + "mortgage_gquant_plugins:INFO: HOST RAM (MB) TOTAL 257852; USED 19401; FREE 205546\n", + "mortgage_gquant_plugins:INFO: RUN PYTHON GARBAGE COLLECTION TO MAYBE CLEAR CPU AND GPU MEMORY\n", + "mortgage_gquant_plugins:INFO: HOST RAM (MB) TOTAL 257852; USED 19401; FREE 205546\n", + "mortgage_gquant_plugins:INFO: USING ARROW\n", + "mortgage_gquant_plugins:INFO: ARROW TO PANDAS\n", + "mortgage_gquant_plugins:INFO: HOST RAM (MB) TOTAL 257852; USED 34611; FREE 190336\n", + "mortgage_gquant_plugins:INFO: JUST BEFORE DMATRIX\n", + "mortgage_gquant_plugins:INFO: HOST RAM (MB) TOTAL 257852; USED 19417; FREE 205530\n", + "mortgage_gquant_plugins:INFO: CREATING DMATRIX\n", + "mortgage_gquant_plugins:INFO: JUST AFTER DMATRIX\n", + "mortgage_gquant_plugins:INFO: HOST RAM (MB) TOTAL 257852; USED 50655; FREE 174292\n", + "mortgage_gquant_plugins:INFO: CLEAR MEMORY JUST BEFORE XGBOOST TRAINING\n", + "mortgage_gquant_plugins:INFO: HOST RAM (MB) TOTAL 257852; USED 50652; FREE 174295\n", + "mortgage_gquant_plugins:INFO: RUNNING XGBOOST TRAINING\n", + "[02:37:08] WARNING: /conda/conda-bld/xgboost_1585677082603/work/include/xgboost/generic_parameters.h:36: \n", + "n_gpus: \n", + "\tDeprecated. Single process multi-GPU training is no longer supported.\n", + "\tPlease switch to distributed training with one process per GPU.\n", + "\tThis can be done using Dask or Spark. See documentation for details.\n", + "[02:37:08] WARNING: /conda/conda-bld/xgboost_1585677082603/work/src/learner.cc:328: \n", + "Parameters: { criterion, loss, max_features, nround, verbose } might not be used.\n", + "\n", + " This may not be accurate due to some parameters are only used in language bindings but\n", + " passed down to XGBoost core. Or some parameters are not used but slip through this\n", + " verification. Please open an issue if you find above cases.\n", + "\n", + "\n", "XGBOOST BOOSTER:\n", - " \n" + " \n" ] } ], @@ -814,11 +862,11 @@ "output_type": "stream", "text": [ " total used free shared buff/cache available\n", - "Mem: 128904 49537 61426 6327 17940 69574\n", + "Mem: 257852 51376 173570 17648 32906 185356\n", "Swap: 0 0 0\n", "\n", "pid, process_name, used_gpu_memory [MiB]\n", - "8165, /home/avolkov/progs/python_installs/miniconda3/envs/py36-rapids/bin/python, 11071 MiB\n" + "30682, [Not Found], 11999 MiB\n" ] } ], @@ -853,16 +901,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "env: NCCL_P2P_DISABLE=1\n", "\n", "HOST RAM\n", " total used free shared buff/cache available\n", - "Mem: 128904 2140 108824 6325 17938 116973\n", + "Mem: 257852 19469 205479 17646 32904 217265\n", "Swap: 0 0 0\n", "\n", "GPU STATUS\n", "pid, process_name, used_gpu_memory [MiB]\n", - "8165, /home/avolkov/progs/python_installs/miniconda3/envs/py36-rapids/bin/python, 239 MiB\n", + "30682, [Not Found], 2645 MiB\n", "\n", "\n", "\n", @@ -875,25 +922,25 @@ "\n", "\n", "\n", "\n", "\n", "
\n", - "

Client

\n", - "
\n", - "

Cluster

\n", - "
    \n", - "
  • Workers: 2
  • \n", - "
  • Cores: 8
  • \n", - "
  • Memory: 256.00 GB
  • \n", + "

    Cluster

    \n", + "
      \n", + "
    • Workers: 4
    • \n", + "
    • Cores: 16
    • \n", + "
    • Memory: 512.00 GB
    • \n", "
    \n", "
" ], "text/plain": [ - "" + "" ] }, "execution_count": 12, @@ -904,7 +951,7 @@ "source": [ "# Disable NCCL P2P. Only necessary for versions of NCCL < 2.4\n", "# https://rapidsai.github.io/projects/cudf/en/0.8.0/dask-xgb-10min.html#Disable-NCCL-P2P.-Only-necessary-for-versions-of-NCCL-%3C-2.4\n", - "%env NCCL_P2P_DISABLE=1\n", + "# %env NCCL_P2P_DISABLE=1\n", "\n", "# CLEAN MEMORY FROM RUN BEFORE\n", "import gc\n", @@ -965,14 +1012,13 @@ "outputs": [ { "data": { - "image/png": "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nmp6PT5+QNvve+/evYiOjgYAHDlyBNHR0dixY0en49FZLU8zjp3paBy//PJLWFlZcSeCVVdXIzY2FkZGRggJCQHw6P9h48aN8PT0RF1dHVavXg07OzsEBwdzC/ruDAN0Pg/05HsYCHx9fXH27Fls27YNn3zyCdasWdPxjYrb29bx2WefEY/Ho+PHj/feBhgdio+Pp/Hjx1NDQwMREclkMrKzs9Pa5hweHk4LFy7kugMDA2np0qVct7e3N129epWIiOrr62nixInca9u3b9faBvn+++/T7t27e1RjeXk5LVu2jABQTEwMpaamUk1NDY0fP548PT1p/fr1lJ2dTbW1tRQaGkqenp5a7//iiy8oNDSUmpubiYiooqKCvLy8aPLkyaRWqykhIYF8fX3JyMiItmzZQrt376bg4GAqLS2lWbNmkbu7u1Z7RUVFxOfz6f79+0REtHz5cgJAY8aMoQ0bNnRrmnWnjW3bttEPP/xARI/2Bfj5+ZGTkxPV1dV1e9otXryYTExMuPc0NzeTi4sLTZ06VWu4+fPn07179556enXn+66oqCAA9PHHH2v1z8zMbLPNuatannQcu9LZOE6fPp2cnZ21hh85ciRNmDCBiIgkEglNnTqVAND69espKyuL0tLSyNTUlBYtWtTtYYg6nwc6q3GgO336NBkbG1NsbGy7r7cJZ4lEQnw+n7Zv397nxfWHuro6EggEdODAAa3+c+fO1QrnKVOm0Keffsp1R0VFUUBAABE9+kcwMDCgf/3rX9zrx44d455r/lnFYjG9//77dOLEiSeq9auvviIAlJGRwfXbsmULAaC0tDSu3+bNmwkAlZeXExGRVColPp9PP/74o1Z733//PQGgffv2ERHRqlWrCADduXNHa7j2wnnjxo3k4uLCdefm5hIA2rVrF9evs2nWnTZKS0vJ0dFRa8fyhx9+SADo4MGDXU0uzsWLFwkAxcfHc/02bNhAJiYm9PDhQyIiamhooNdff52Inn56def77m44d7eWno5jd3U0jq+99lqbcJ4wYQIXzkREH3zwAQGgiooKrt/EiRPJy8ur28N0Zx7oqMZnwRdffEHm5uZUXFzc5rU2mzXOnj0LANiwYcPTrb/riStXrkAikWDkyJFa/R8/PvXixYv44IMP0NjYiO+++w43btzgrhdrbGyMiIgIbNiwATExMXj48CFee+21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\n", + "image/png": "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\n", "text/plain": [ "" ] }, - "execution_count": 13, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ @@ -1004,6 +1050,7 @@ "\n", "# Use RAPIDS Memory Manager. Seems to work fine without it.\n", "use_rmm = False\n", + "# using RMM not working with rapids 0.14. Getting out-of-memory error.\n", "\n", "# Clean up intermediate dataframes in the xgboost training task.\n", "delete_dataframes = True\n", @@ -1059,7 +1106,6 @@ " 'n_gpus': 1,\n", " 'distributed_dask': True,\n", " 'loss': 'ls',\n", - " # 'objective': 'gpu:reg:linear',\n", " 'objective': 'reg:squarederror',\n", " 'max_features': 'auto',\n", " 'criterion': 'friedman_mse',\n", @@ -1107,89 +1153,79 @@ "name": "stdout", "output_type": "stream", "text": [ - "dask_mortgage_workflow_runner:INFO: TRYING TO LOAD 18 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: SPLIT MORTGAGE DATA INTO 2 CHUNKS AMONGST 2 WORKERS\n", - "dask_mortgage_workflow_runner:INFO: 14:37:24.186 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 RUNNING MORTGAGE gQUANT DataframeFlow\n", - "dask_mortgage_workflow_runner:INFO: 14:37:24.187 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 NCCL_P2P_DISABLE: 1\n", - "dask_mortgage_workflow_runner:INFO: 14:37:24.187 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 CUDA_VISIBLE_DEVICES: 1,0\n", - "dask_mortgage_workflow_runner:INFO: 14:37:26.555 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2000Q1.txt_0\n", - "dask_mortgage_workflow_runner:INFO: 14:37:33.357 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2000Q1.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:35.427 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 1 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:35.437 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2000Q2.txt_0\n", - "dask_mortgage_workflow_runner:INFO: 14:37:39.116 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2000Q2.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:40.510 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 2 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:40.519 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2000Q3.txt_0\n", - "dask_mortgage_workflow_runner:INFO: 14:37:44.204 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2000Q3.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:45.829 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 3 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:45.838 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2000Q4.txt_1\n", - "dask_mortgage_workflow_runner:INFO: 14:37:46.917 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2000Q4.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:47.546 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 4 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:47.555 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2000Q4.txt_0\n", - "dask_mortgage_workflow_runner:INFO: 14:37:51.655 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2000Q4.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:53.308 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 5 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:53.851 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2001Q1.txt_1\n", - "dask_mortgage_workflow_runner:INFO: 14:37:57.086 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2001Q1.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:58.362 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 6 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:58.482 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2001Q1.txt_0\n", - "dask_mortgage_workflow_runner:INFO: 14:38:02.956 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2001Q1.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:38:04.534 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 7 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:38:04.566 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_1_1\n", - "dask_mortgage_workflow_runner:INFO: 14:38:07.979 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:38:09.330 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 8 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:38:09.446 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_1_0\n", - "dask_mortgage_workflow_runner:INFO: 14:38:13.713 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 1 LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:38:15.459 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 9 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:38:15.502 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 HOST RAM (MB) TOTAL 128904; USED 21174; FREE 89201\n", - "dask_mortgage_workflow_runner:INFO: 14:38:15.503 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 RUN PYTHON GARBAGE COLLECTION TO MAYBE CLEAR CPU AND GPU MEMORY\n", - "dask_mortgage_workflow_runner:INFO: 14:38:15.672 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 HOST RAM (MB) TOTAL 128904; USED 21169; FREE 89194\n", - "dask_mortgage_workflow_runner:INFO: 14:38:15.672 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 USING ARROW\n", - "dask_mortgage_workflow_runner:INFO: 14:38:15.672 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 ARROW TO PANDAS\n", - "dask_mortgage_workflow_runner:INFO: 14:38:17.698 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 HOST RAM (MB) TOTAL 128904; USED 33039; FREE 77243\n", - "dask_mortgage_workflow_runner:INFO: 14:37:24.186 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 RUNNING MORTGAGE gQUANT DataframeFlow\n", - "dask_mortgage_workflow_runner:INFO: 14:37:24.187 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 NCCL_P2P_DISABLE: 1\n", - "dask_mortgage_workflow_runner:INFO: 14:37:24.187 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 CUDA_VISIBLE_DEVICES: 0,1\n", - "dask_mortgage_workflow_runner:INFO: 14:37:26.550 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_0_1\n", - "dask_mortgage_workflow_runner:INFO: 14:37:32.901 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:34.969 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 1 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:34.980 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q2.txt_0_0\n", - "dask_mortgage_workflow_runner:INFO: 14:37:39.675 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q2.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:41.514 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 2 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:41.525 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q3.txt_1_1\n", - "dask_mortgage_workflow_runner:INFO: 14:37:44.327 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q3.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:45.528 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 3 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:45.538 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q3.txt_1_0\n", - "dask_mortgage_workflow_runner:INFO: 14:37:50.258 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q3.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:37:52.073 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 4 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:37:52.083 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q3.txt_0_1\n", - "dask_mortgage_workflow_runner:INFO: 14:38:10.848 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q3.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:38:12.093 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 5 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:38:12.388 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q3.txt_0_0\n", - "dask_mortgage_workflow_runner:INFO: 14:38:49.168 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q3.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:38:51.039 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 6 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:38:51.122 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q4.txt_1_1\n", - "dask_mortgage_workflow_runner:INFO: 14:39:34.755 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q4.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:39:42.022 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 7 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:39:42.076 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q4.txt_1_0\n", - "dask_mortgage_workflow_runner:INFO: 14:40:26.012 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q4.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:40:27.790 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 8 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:40:27.933 distributed.worker.csv_mortgage_performance_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/perf/Performance_2001Q4.txt_0_1\n", - "dask_mortgage_workflow_runner:INFO: 14:41:07.497 distributed.worker.csv_mortgage_acquisition_data_loader:INFO: WORKER 0 LOADING: ./mortgage_data/acq/Acquisition_2001Q4.txt\n", - "dask_mortgage_workflow_runner:INFO: 14:41:09.174 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 9 FRAMES\n", - "dask_mortgage_workflow_runner:INFO: 14:41:09.228 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 HOST RAM (MB) TOTAL 128904; USED 27832; FREE 78652\n", - "dask_mortgage_workflow_runner:INFO: 14:41:09.228 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 RUN PYTHON GARBAGE COLLECTION TO MAYBE CLEAR CPU AND GPU MEMORY\n", - "dask_mortgage_workflow_runner:INFO: 14:41:09.401 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 HOST RAM (MB) TOTAL 128904; USED 27832; FREE 78652\n", - "dask_mortgage_workflow_runner:INFO: 14:41:09.401 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 USING ARROW\n", - "dask_mortgage_workflow_runner:INFO: 14:41:09.402 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 ARROW TO PANDAS\n", - "dask_mortgage_workflow_runner:INFO: 14:41:10.497 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 HOST RAM (MB) TOTAL 128904; USED 40387; FREE 66097\n", - "dask_mortgage_workflow_runner:INFO: CLIENT INFO WHO HAS WHAT: {'mortgage_workflow_runner-524827d9eaa91df247185e42269277ca': ('tcp://10.31.229.79:38589',), 'mortgage_workflow_runner-a7b9d85ab42a72e0d3f7488f4b84b6af': ('tcp://10.31.229.79:36823',)}\n", - "dask_xgb_trainer:INFO: CREATING DMATRIX SERIALLY ACROSS 2 WORKERS\n", - "dask_xgb_trainer:INFO: 14:41:10.779 distributed.worker.make_xgb_dmatrix:INFO: CREATING DMATRIX ON WORKER 1\n", - "dask_xgb_trainer:INFO: 14:42:25.666 distributed.worker.make_xgb_dmatrix:INFO: CREATING DMATRIX ON WORKER 0\n", - "dask_xgb_trainer:INFO: JUST AFTER DMATRIX\n", - "dask_xgb_trainer:INFO: HOST RAM (MB) TOTAL 128904; USED 77221; FREE 39151\n", - "dask_xgb_trainer:INFO: RUNNING XGBOOST TRAINING USING DASK-XGBOOST\n", + "mortgage_gquant_plugins:INFO: TRYING TO LOAD 18 FRAMES\n", + "mortgage_gquant_plugins:INFO: SPLIT MORTGAGE DATA INTO 4 CHUNKS AMONGST 4 WORKERS\n", + "mortgage_gquant_plugins:INFO: 02:41:10.089 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 RUNNING MORTGAGE gQUANT DataframeFlow\n", + "mortgage_gquant_plugins:INFO: 02:41:10.089 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 NCCL_P2P_DISABLE: None\n", + "mortgage_gquant_plugins:INFO: 02:41:10.089 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 CUDA_VISIBLE_DEVICES: 2,3,0,1\n", + "mortgage_gquant_plugins:INFO: 02:41:16.118 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 LOADED 1 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:19.498 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 LOADED 2 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:23.012 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 LOADED 3 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:24.835 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 LOADED 4 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:24.870 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 HOST RAM (MB) TOTAL 257852; USED 38471; FREE 186414\n", + "mortgage_gquant_plugins:INFO: 02:41:24.871 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 RUN PYTHON GARBAGE COLLECTION TO MAYBE CLEAR CPU AND GPU MEMORY\n", + "mortgage_gquant_plugins:INFO: 02:41:25.041 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 HOST RAM (MB) TOTAL 257852; USED 38475; FREE 186410\n", + "mortgage_gquant_plugins:INFO: 02:41:25.041 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 USING ARROW\n", + "mortgage_gquant_plugins:INFO: 02:41:25.042 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 ARROW TO PANDAS\n", + "mortgage_gquant_plugins:INFO: 02:41:25.468 distributed.worker.mortgage_workflow_runner:INFO: WORKER 2 HOST RAM (MB) TOTAL 257852; USED 43685; FREE 181202\n", + "mortgage_gquant_plugins:INFO: 02:41:10.089 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 RUNNING MORTGAGE gQUANT DataframeFlow\n", + "mortgage_gquant_plugins:INFO: 02:41:10.089 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 NCCL_P2P_DISABLE: None\n", + "mortgage_gquant_plugins:INFO: 02:41:10.089 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 CUDA_VISIBLE_DEVICES: 1,2,3,0\n", + "mortgage_gquant_plugins:INFO: 02:41:16.243 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 1 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:19.526 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 2 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:23.473 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 3 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:27.126 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 LOADED 4 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:27.164 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 HOST RAM (MB) TOTAL 257852; USED 41239; FREE 183648\n", + "mortgage_gquant_plugins:INFO: 02:41:27.164 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 RUN PYTHON GARBAGE COLLECTION TO MAYBE CLEAR CPU AND GPU MEMORY\n", + "mortgage_gquant_plugins:INFO: 02:41:27.312 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 HOST RAM (MB) TOTAL 257852; USED 41240; FREE 183647\n", + "mortgage_gquant_plugins:INFO: 02:41:27.312 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 USING ARROW\n", + "mortgage_gquant_plugins:INFO: 02:41:27.312 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 ARROW TO PANDAS\n", + "mortgage_gquant_plugins:INFO: 02:41:27.785 distributed.worker.mortgage_workflow_runner:INFO: WORKER 1 HOST RAM (MB) TOTAL 257852; USED 46689; FREE 178198\n", + "mortgage_gquant_plugins:INFO: 02:41:10.089 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 RUNNING MORTGAGE gQUANT DataframeFlow\n", + "mortgage_gquant_plugins:INFO: 02:41:10.090 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 NCCL_P2P_DISABLE: None\n", + "mortgage_gquant_plugins:INFO: 02:41:10.090 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 CUDA_VISIBLE_DEVICES: 3,0,1,2\n", + "mortgage_gquant_plugins:INFO: 02:41:17.106 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 LOADED 1 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:21.031 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 LOADED 2 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:25.869 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 LOADED 3 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:29.327 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 LOADED 4 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:29.365 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 HOST RAM (MB) TOTAL 257852; USED 43586; FREE 181299\n", + "mortgage_gquant_plugins:INFO: 02:41:29.365 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 RUN PYTHON GARBAGE COLLECTION TO MAYBE CLEAR CPU AND GPU MEMORY\n", + "mortgage_gquant_plugins:INFO: 02:41:29.526 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 HOST RAM (MB) TOTAL 257852; USED 43585; FREE 181300\n", + "mortgage_gquant_plugins:INFO: 02:41:29.527 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 USING ARROW\n", + "mortgage_gquant_plugins:INFO: 02:41:29.527 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 ARROW TO PANDAS\n", + "mortgage_gquant_plugins:INFO: 02:41:29.976 distributed.worker.mortgage_workflow_runner:INFO: WORKER 3 HOST RAM (MB) TOTAL 257852; USED 48757; FREE 176130\n", + "mortgage_gquant_plugins:INFO: 02:41:10.089 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 RUNNING MORTGAGE gQUANT DataframeFlow\n", + "mortgage_gquant_plugins:INFO: 02:41:10.090 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 NCCL_P2P_DISABLE: None\n", + "mortgage_gquant_plugins:INFO: 02:41:10.090 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 CUDA_VISIBLE_DEVICES: 0,1,2,3\n", + "mortgage_gquant_plugins:INFO: 02:41:16.837 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 1 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:20.215 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 2 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:24.826 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 3 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:29.293 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 4 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:33.649 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 5 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:37.860 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 LOADED 6 FRAMES\n", + "mortgage_gquant_plugins:INFO: 02:41:37.905 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 HOST RAM (MB) TOTAL 257852; USED 47258; FREE 177629\n", + "mortgage_gquant_plugins:INFO: 02:41:37.905 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 RUN PYTHON GARBAGE COLLECTION TO MAYBE CLEAR CPU AND GPU MEMORY\n", + "mortgage_gquant_plugins:INFO: 02:41:38.064 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 HOST RAM (MB) TOTAL 257852; USED 47251; FREE 177635\n", + "mortgage_gquant_plugins:INFO: 02:41:38.064 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 USING ARROW\n", + "mortgage_gquant_plugins:INFO: 02:41:38.065 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 ARROW TO PANDAS\n", + "mortgage_gquant_plugins:INFO: 02:41:38.750 distributed.worker.mortgage_workflow_runner:INFO: WORKER 0 HOST RAM (MB) TOTAL 257852; USED 56152; FREE 168735\n", + "mortgage_gquant_plugins:INFO: CLIENT INFO WHO HAS WHAT: {'mortgage_workflow_runner-ccd2e5e0da5960f43d2e97cbded0b089': ('tcp://127.0.0.1:36637',), 'mortgage_workflow_runner-01accb2a90d0a94baa9f24078e31d40d': ('tcp://127.0.0.1:41533',), 'mortgage_workflow_runner-c29a28e04bc5511f09ff7dfa69383dd8': ('tcp://127.0.0.1:33385',), 'mortgage_workflow_runner-cc066a7bbc6a9bebd480baf50550173c': ('tcp://127.0.0.1:38656',)}\n", + "mortgage_gquant_plugins:INFO: CREATING DMATRIX SERIALLY ACROSS 4 WORKERS\n", + "mortgage_gquant_plugins:INFO: 02:41:39.082 distributed.worker.make_xgb_dmatrix:INFO: CREATING DMATRIX ON WORKER 2\n", + "mortgage_gquant_plugins:INFO: 02:42:10.270 distributed.worker.make_xgb_dmatrix:INFO: CREATING DMATRIX ON WORKER 1\n", + "mortgage_gquant_plugins:INFO: 02:42:45.807 distributed.worker.make_xgb_dmatrix:INFO: CREATING DMATRIX ON WORKER 3\n", + "mortgage_gquant_plugins:INFO: 02:43:20.788 distributed.worker.make_xgb_dmatrix:INFO: CREATING DMATRIX ON WORKER 0\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mortgage_gquant_plugins:INFO: JUST AFTER DMATRIX\n", + "mortgage_gquant_plugins:INFO: HOST RAM (MB) TOTAL 257852; USED 97439; FREE 127448\n", + "mortgage_gquant_plugins:INFO: RUNNING XGBOOST TRAINING USING DASK-XGBOOST\n", "XGBOOST BOOSTER:\n", - " \n" + " \n" ] } ], @@ -1265,7 +1301,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.6.10" } }, "nbformat": 4, diff --git a/notebooks/mortgage_e2e_gquant/mortgage_gquant_plugins.py b/notebooks/mortgage_e2e_gquant/mortgage_gquant_plugins.py index 6483cd00..1d36f8b5 100644 --- a/notebooks/mortgage_e2e_gquant/mortgage_gquant_plugins.py +++ b/notebooks/mortgage_e2e_gquant/mortgage_gquant_plugins.py @@ -226,8 +226,8 @@ def process(self, inputs): col_names_path = self.conf['csvfile_names'] cols_dtypes = OrderedDict([ - ('seller_name', 'category'), - ('new', 'category'), + ('seller_name', 'int32'), + ('new', 'int32'), ]) cols = list(cols_dtypes.keys()) dtypes = list(cols_dtypes.values()) @@ -601,10 +601,12 @@ def _null_workaround(df): ''' for column, data_type in df.dtypes.items(): if str(data_type) == "category": - df[column] = df[column].astype('int32').fillna(-1) + df[column] = df[column]\ + .astype('int32').fillna(np.dtype(np.int32).type(-1)) if str(data_type) in \ ['int8', 'int16', 'int32', 'int64', 'float32', 'float64']: - df[column] = df[column].fillna(np.dtype(data_type).type(-1)) + df[column] = df[column]\ + .fillna(np.dtype(data_type).type(-1)).astype(data_type) return df @@ -706,8 +708,8 @@ class JoinFinalPerfAcqClean(Node): if itype in ('float64', 'int32', 'int64',): cols_dtypes[icol] = 'float32' - # The only exception is delinquency_12 which remains int32 - cols_dtypes.update({'delinquency_12': 'int32'}) + # The only exception is delinquency_12 which becomes int8 + cols_dtypes.update({'delinquency_12': 'int8'}) for col in _drop_list: cols_dtypes.pop(col) @@ -718,20 +720,27 @@ def columns_setup(self): self.retention = self.cols_dtypes @classmethod - def __last_mile_cleaning(cls, df): + def __last_mile_cleaning(cls, df, cols_to_keep=tuple()): drop_list = cls._drop_list for column in drop_list: + if column in cols_to_keep: + continue + if column not in df.columns: + continue df.drop_column(column) + for col, dtype in df.dtypes.iteritems(): if str(dtype) == 'category': df[col] = df[col].cat.codes df[col] = df[col].astype('float32') - df['delinquency_12'] = df['delinquency_12'] > 0 - df['delinquency_12'] = \ - df['delinquency_12'].fillna(False).astype('int32') + + if 'delinquency_12' in df.columns: + df['delinquency_12'] = df['delinquency_12'] > 0 + df['delinquency_12'] = \ + df['delinquency_12'].fillna(False).astype('int8') + for column in df.columns: - df[column] = \ - df[column].fillna(np.dtype(str(df[column].dtype)).type(-1)) + df[column] = df[column].fillna(-1) # return df.to_arrow(preserve_index=False) return df @@ -745,6 +754,13 @@ def process(self, inputs): perf_df = _null_workaround(perf_df) acq_df = _null_workaround(acq_df) + cols_to_keep = ('loan_id', 'seller_name',) + perf_df = self.__last_mile_cleaning(perf_df, cols_to_keep=cols_to_keep) + # cleaning acq_df causes out of memory error during merge!? rapids 0.14 + # acq_df = self.__last_mile_cleaning(acq_df, cols_to_keep=cols_to_keep) + + acq_df['seller_name'] = acq_df['seller_name'].astype('category') + perf_acq_df = perf_df.merge( acq_df, how='left', on=['loan_id'], type='hash') @@ -1061,28 +1077,24 @@ def process(self, inputs): # This is needed if distributing workflows to workers. def initialize_rmm_pool(): - from librmm_cffi import librmm_config as rmm_cfg - - rmm_cfg.use_pool_allocator = True - # set to 2GiB. Default is 1/2 total GPU memory - # rmm_cfg.initial_pool_size = 2 << 30 - # rmm_cfg.initial_pool_size = 2 << 5 - # rmm_cfg.initial_pool_size = 2 << 33 - import cudf - return cudf.rmm.initialize() + import rmm + return rmm.reinitialize( + pool_allocator=True, # default is False + managed_memory=False + ) def initialize_rmm_no_pool(): - from librmm_cffi import librmm_config as rmm_cfg - - rmm_cfg.use_pool_allocator = False - import cudf - return cudf.rmm.initialize() + import rmm + return rmm.reinitialize( + pool_allocator=False, # default is False + managed_memory=False + ) def finalize_rmm(): - import cudf - return cudf.rmm.finalize() + import rmm + return rmm.rmm.librmm.rmm_finalize() def print_distributed_dask_hijacked_logs(wlogs, logger, filters=None): @@ -1298,6 +1310,8 @@ def process(self, inputs): mortgage_feat_df_delinq_df_pandas_futures = inputs[0] + # TODO: Update to xgb.dask.DaskDMatrix and xgb.dask.train API. Refer to + # https://medium.com/rapids-ai/a-new-official-dask-api-for-xgboost-e8b10f3d1eb7 def make_xgb_dmatrix( mortgage_feat_df_delinq_df_pandas_tuple, delete_dataframes=None): From 5d539704aa9ac522ec20c5a650d96cf3e55a8d44 Mon Sep 17 00:00:00 2001 From: Yi Dong Date: Fri, 10 Jul 2020 11:12:33 -0700 Subject: [PATCH 5/5] added the change log --- CHANGELOG.md | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..39f76a10 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,148 @@ +# Changelog + +## [0.5](https://github.com/rapidsai/gQuant/tree/0.5) (2020-07-10) + +[Full Changelog](https://github.com/rapidsai/gQuant/compare/0.4.1...0.5) + +**Implemented enhancements:** + +- \[FEA\] csvStockLoader.py and stockNameLoader.py - Use cudf.read\_csv\(\) insteand of pandas.read\_csv\(\) [\#24](https://github.com/rapidsai/gQuant/issues/24) + +**Fixed bugs:** + +- \[BUG\] Using a UDF via Series.rolling.apply\(\) results in KeyError in numba [\#88](https://github.com/rapidsai/gQuant/issues/88) +- \[BUG\] download\_data.sh seems to do not be in containers anymore [\#66](https://github.com/rapidsai/gQuant/issues/66) + +**Closed issues:** + +- \[FEA\] Conda resolves too slow in the latest versions of the container [\#67](https://github.com/rapidsai/gQuant/issues/67) +- \[FEA\] Comprehensive refactoring of indicator\_demo.ipynb notebook [\#46](https://github.com/rapidsai/gQuant/issues/46) +- \[FEA\] Rename viz\_graph\(\) to viz\(\), save\_taskgraph\(\) to save\(\) [\#34](https://github.com/rapidsai/gQuant/issues/34) + +**Merged pull requests:** + +- \[REVIEW\] Fix mortgage e2e example for rapids 0.14. [\#93](https://github.com/rapidsai/gQuant/pull/93) ([avolkov1](https://github.com/avolkov1)) +- \[REVIEW\] Update RAPIDS to version 0.14 [\#92](https://github.com/rapidsai/gQuant/pull/92) ([yidong72](https://github.com/yidong72)) +- \[REVIEW\]Multiple gpu xgboost - Dask performance fix [\#91](https://github.com/rapidsai/gQuant/pull/91) ([yidong72](https://github.com/yidong72)) +- \[REVIEW\]Mutliple GPU xgboost [\#90](https://github.com/rapidsai/gQuant/pull/90) ([yidong72](https://github.com/yidong72)) + +## [0.4.1](https://github.com/rapidsai/gQuant/tree/0.4.1) (2020-05-26) + +[Full Changelog](https://github.com/rapidsai/gQuant/compare/0.4...0.4.1) + +**Merged pull requests:** + +- \[REVIEW\] hot fix for 0.4 release [\#86](https://github.com/rapidsai/gQuant/pull/86) ([yidong72](https://github.com/yidong72)) +- \[REVIEW\] fix the cuIndicator notebook and RSI perf notebook [\#85](https://github.com/rapidsai/gQuant/pull/85) ([yidong72](https://github.com/yidong72)) +- Add cuda102 docker support and update version against development branch [\#84](https://github.com/rapidsai/gQuant/pull/84) ([jbaron](https://github.com/jbaron)) + +## [0.4](https://github.com/rapidsai/gQuant/tree/0.4) (2020-05-19) + +[Full Changelog](https://github.com/rapidsai/gQuant/compare/v0.2...0.4) + +**Implemented enhancements:** + +- \[REVIEW\]Feature adding fractional differencing computation [\#56](https://github.com/rapidsai/gQuant/pull/56) ([yidong72](https://github.com/yidong72)) + +**Fixed bugs:** + +- \[BUG\] Dask computation fails with 0.8 build script [\#28](https://github.com/rapidsai/gQuant/issues/28) + +**Closed issues:** + +- \[FEA\] Add cuda 10.1.2 support [\#64](https://github.com/rapidsai/gQuant/issues/64) +- \[FEA\] Use RAPIDS 0.9 container in build.sh [\#54](https://github.com/rapidsai/gQuant/issues/54) +- \[FEA\] Rename notebook to notebooks [\#50](https://github.com/rapidsai/gQuant/issues/50) +- \[FEA\] Add Jupyterlab extension to display GPU usage [\#49](https://github.com/rapidsai/gQuant/issues/49) +- \[FEA\] Merge develop branch to master [\#47](https://github.com/rapidsai/gQuant/issues/47) +- \[FEA\] implement the fractional difference operation [\#42](https://github.com/rapidsai/gQuant/issues/42) + +**Merged pull requests:** + +- \[REVIEW\] merge develop to master and release it as 0.4 [\#82](https://github.com/rapidsai/gQuant/pull/82) ([yidong72](https://github.com/yidong72)) +- \[REVIEW\]update to latest version of RAPIDS 0.13 [\#81](https://github.com/rapidsai/gQuant/pull/81) ([yidong72](https://github.com/yidong72)) +- fixed the gamma computation error [\#79](https://github.com/rapidsai/gQuant/pull/79) ([doyend](https://github.com/doyend)) +- \[REVIEW\]asian barrier option tutorial [\#77](https://github.com/rapidsai/gQuant/pull/77) ([yidong72](https://github.com/yidong72)) +- \[REVIEW\] upgrade to RAPIDS 0.11 [\#76](https://github.com/rapidsai/gQuant/pull/76) ([yidong72](https://github.com/yidong72)) +- \[skip ci\] Merge CI Scripts [\#75](https://github.com/rapidsai/gQuant/pull/75) ([avolkov1](https://github.com/avolkov1)) +- \[REVIEW\] Add CI scripts and conda recipe [\#74](https://github.com/rapidsai/gQuant/pull/74) ([raydouglass](https://github.com/raydouglass)) +- \[WIP\] CUQ-36: fix typechecking nodes multi input dataframes [\#68](https://github.com/rapidsai/gQuant/pull/68) ([avolkov1](https://github.com/avolkov1)) +- \[REVIEW\] Upgrade to RAPIDS 0.10 [\#63](https://github.com/rapidsai/gQuant/pull/63) ([yidong72](https://github.com/yidong72)) +- \[REVIEW\] stable master merge [\#62](https://github.com/rapidsai/gQuant/pull/62) ([yidong72](https://github.com/yidong72)) +- \[REVIEW\]upgrade to RAPIDS 0.9, FIX the rebase problem [\#61](https://github.com/rapidsai/gQuant/pull/61) ([yidong72](https://github.com/yidong72)) +- Revert "\[REVIEW\]upgrade to RAPIDS 0.9" [\#59](https://github.com/rapidsai/gQuant/pull/59) ([yidong72](https://github.com/yidong72)) +- Revert "\[REVIEW\]upgrade to RAPIDS 0.9" [\#58](https://github.com/rapidsai/gQuant/pull/58) ([avolkov1](https://github.com/avolkov1)) +- \[REVIEW\]upgrade to RAPIDS 0.9 [\#57](https://github.com/rapidsai/gQuant/pull/57) ([yidong72](https://github.com/yidong72)) +- \[REVIEW\] change the text for notebook 05 [\#55](https://github.com/rapidsai/gQuant/pull/55) ([yidong72](https://github.com/yidong72)) +- Fix \#50b - Rename notebook folder to notebooks [\#52](https://github.com/rapidsai/gQuant/pull/52) ([miguelusque](https://github.com/miguelusque)) +- Fix \#50 - Rename notebook folder to notebooks [\#51](https://github.com/rapidsai/gQuant/pull/51) ([miguelusque](https://github.com/miguelusque)) + +## [v0.2](https://github.com/rapidsai/gQuant/tree/v0.2) (2019-08-16) + +[Full Changelog](https://github.com/rapidsai/gQuant/compare/v0.1...v0.2) + +**Implemented enhancements:** + +- \[FEA\] Refactor 04\_portfolio\_trade.ipynb notebook [\#39](https://github.com/rapidsai/gQuant/issues/39) +- \[FEA\] Refactor notebook 01\_tutorial.ipynb [\#35](https://github.com/rapidsai/gQuant/issues/35) +- \[FEA\] Add error message \(or warning\) if replace node does not exist [\#32](https://github.com/rapidsai/gQuant/issues/32) +- \[FEA\] Add new issue templates [\#26](https://github.com/rapidsai/gQuant/issues/26) +- \[FEA\] cuIndicator notebook plot widget is too complicated [\#17](https://github.com/rapidsai/gQuant/issues/17) + +**Fixed bugs:** + +- \[BUG\] Remove debug info from barPlotNode.py and cumReturnNode.py [\#40](https://github.com/rapidsai/gQuant/issues/40) +- \[BUG\] 04\_portfolio\_trade.ipynb - Number of filtered stocks differs from text [\#23](https://github.com/rapidsai/gQuant/issues/23) + +**Merged pull requests:** + +- Fix \#17 - cuIndicator notebook plot widget is too complicated \(WIP\) [\#45](https://github.com/rapidsai/gQuant/pull/45) ([miguelusque](https://github.com/miguelusque)) +- Fix \#39 - Refactor 04\_portfolio\_trade.ipynb notebook [\#44](https://github.com/rapidsai/gQuant/pull/44) ([miguelusque](https://github.com/miguelusque)) +- Merge develop to master [\#43](https://github.com/rapidsai/gQuant/pull/43) ([yidong72](https://github.com/yidong72)) +- Fix \#40 - Remove debug info [\#41](https://github.com/rapidsai/gQuant/pull/41) ([miguelusque](https://github.com/miguelusque)) +- Update mortgage example using TaskGraph API. [\#38](https://github.com/rapidsai/gQuant/pull/38) ([avolkov1](https://github.com/avolkov1)) +- fixed the issue 32 [\#37](https://github.com/rapidsai/gQuant/pull/37) ([yidong72](https://github.com/yidong72)) +- Fix \#35 - Refactor 01\_tutorial.ipynb notebook [\#36](https://github.com/rapidsai/gQuant/pull/36) ([miguelusque](https://github.com/miguelusque)) +- Fix \#26b - Add new issue templates [\#30](https://github.com/rapidsai/gQuant/pull/30) ([miguelusque](https://github.com/miguelusque)) +- Revert "fix \#26 - Add new issues template" [\#29](https://github.com/rapidsai/gQuant/pull/29) ([yidong72](https://github.com/yidong72)) +- Fix \#26 - Add new issues template [\#27](https://github.com/rapidsai/gQuant/pull/27) ([miguelusque](https://github.com/miguelusque)) +- added workflow class [\#22](https://github.com/rapidsai/gQuant/pull/22) ([yidong72](https://github.com/yidong72)) +- Fix \#19b - Combine OS/Cuda versions user input [\#21](https://github.com/rapidsai/gQuant/pull/21) ([miguelusque](https://github.com/miguelusque)) +- Fix \#19 - build.sh - Move pip dependencies to conda dependencies [\#20](https://github.com/rapidsai/gQuant/pull/20) ([miguelusque](https://github.com/miguelusque)) +- Fix \#13, \#14, \#16 in cuIndicator.ipynb notebook [\#18](https://github.com/rapidsai/gQuant/pull/18) ([miguelusque](https://github.com/miguelusque)) +- update the build.sh [\#15](https://github.com/rapidsai/gQuant/pull/15) ([yidong72](https://github.com/yidong72)) +- Feature xgb notebook [\#11](https://github.com/rapidsai/gQuant/pull/11) ([yidong72](https://github.com/yidong72)) +- CUQ-5: Mortgage example using gQuant. [\#10](https://github.com/rapidsai/gQuant/pull/10) ([avolkov1](https://github.com/avolkov1)) +- CUQ-5: Mortgage example using gQuant. [\#9](https://github.com/rapidsai/gQuant/pull/9) ([avolkov1](https://github.com/avolkov1)) +- Feature indicator node [\#8](https://github.com/rapidsai/gQuant/pull/8) ([yidong72](https://github.com/yidong72)) +- Feature mulit assets indicator [\#7](https://github.com/rapidsai/gQuant/pull/7) ([yidong72](https://github.com/yidong72)) +- Update build.sh [\#6](https://github.com/rapidsai/gQuant/pull/6) ([phogan-nvidia](https://github.com/phogan-nvidia)) +- Feature environment [\#5](https://github.com/rapidsai/gQuant/pull/5) ([yidong72](https://github.com/yidong72)) + +## [v0.1](https://github.com/rapidsai/gQuant/tree/v0.1) (2019-08-13) + +[Full Changelog](https://github.com/rapidsai/gQuant/compare/e4a967fc9e3289fdbfa37e7a7b84887579332b42...v0.1) + +**Implemented enhancements:** + +- \[FEA\] build.sh - Move pip dependencies to conda dependencies [\#19](https://github.com/rapidsai/gQuant/issues/19) + +**Fixed bugs:** + +- \[BUG\] Update build.sh to 0.7 until issue \#28 is fixed [\#31](https://github.com/rapidsai/gQuant/issues/31) +- \[BUG\] cuIndicator.ipyng - Wrong series names [\#16](https://github.com/rapidsai/gQuant/issues/16) +- \[BUG\] cuIndicator.ipynb - Runtime error in cell \#3 - Missing file [\#14](https://github.com/rapidsai/gQuant/issues/14) +- \[BUG\] cuIndicator.ipynb - Incorrect path to dataset [\#13](https://github.com/rapidsai/gQuant/issues/13) + +**Merged pull requests:** + +- Revert "gQuant34 - Update build.sh to make use of RAPIDS v0.8 container" [\#33](https://github.com/rapidsai/gQuant/pull/33) ([yidong72](https://github.com/yidong72)) +- gQuant34 - Update build.sh to make use of RAPIDS v0.8 container [\#12](https://github.com/rapidsai/gQuant/pull/12) ([miguelusque](https://github.com/miguelusque)) +- Synch master with develop [\#4](https://github.com/rapidsai/gQuant/pull/4) ([avolkov1](https://github.com/avolkov1)) +- added unit tests for the cuindicator [\#3](https://github.com/rapidsai/gQuant/pull/3) ([yidong72](https://github.com/yidong72)) +- CUQ-21: Improving tutorials for gQuant [\#2](https://github.com/rapidsai/gQuant/pull/2) ([avolkov1](https://github.com/avolkov1)) +- Add download script and instructions in the readme [\#1](https://github.com/rapidsai/gQuant/pull/1) ([yidong72](https://github.com/yidong72)) + + + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*