├── README.md ├── backtest_metrics ├── Baseline and Metrics.ipynb ├── Retraining and Metrics.ipynb └── utils.py ├── backtest_veroft ├── Overfit Probability.ipynb ├── Testing Routines.ipynb └── readme.md ├── bars-labels-diff ├── "Normal" bars.ipynb ├── Differentiation.ipynb ├── Features analysis.ipynb ├── Labeling.ipynb ├── Training Fractional.ipynb ├── Training.ipynb ├── bars.py └── tick_bars.csv ├── feature_importance ├── Time Series Feature Importance.ipynb ├── test.txt └── utils.py └── proba_backtest ├── Combinatorial Cross Validation.ipynb ├── Stochastic Simulations.ipynb ├── readme.md └── utils.py /README.md: -------------------------------------------------------------------------------- 1 | # Advanced-Deep-Trading 2 | 3 | Experiments based on the Lopez de Prado book "Advances in financial machine learning": https://www.wiley.com/en-us/Advances+in+Financial+Machine+Learning-p-9781119482086. Rethinking "normal" machine learning from areas like CV, NLP and others in order to make it work with data with stochastic nature like financial time series. 4 | -------------------------------------------------------------------------------- /backtest_metrics/utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | def getDailyVol(close, span0=100): 5 | # daily vol, reindexed to close 6 | df0=close.index.searchsorted(close.index-pd.Timedelta(days=1)) 7 | df0=df0[df0>0] 8 | df0=pd.Series(close.index[df0-1], index=close.index[close.shape[0]-df0.shape[0]:]) 9 | df0=close.loc[df0.index]/close.loc[df0.values].values-1 # daily returns 10 | df0=df0.ewm(span=span0).std() 11 | return df0 12 | 13 | def get_meta_barier(future_window, last_close, min_ret, tp, sl, vertical_zero = True): 14 | ''' 15 | From https://github.com/Rachnog/Advanced-Deep-Trading/blob/master/bars-labels-diff/Labeling.ipynb 16 | ''' 17 | if vertical_zero: 18 | min_ret_situation = [0, 0, 0] 19 | else: 20 | min_ret_situation = [0, 0] 21 | 22 | 23 | differences = np.array([(fc - last_close) / last_close for fc in future_window]) 24 | 25 | # Are there gonna be fluctuations within min_ret??? 26 | min_ret_ups = np.where((differences >= min_ret) == True)[0] 27 | min_ret_downs = np.where((differences < -min_ret) == True)[0] 28 | 29 | if (len(min_ret_ups) == 0) and (len(min_ret_downs) == 0): 30 | if vertical_zero: 31 | min_ret_situation[2] = 1 32 | else: 33 | if differences[-1] > 0: 34 | min_ret_situation[0] = 1 35 | else: 36 | min_ret_situation[1] = 1 37 | else: 38 | if len(min_ret_ups) == 0: min_ret_ups = [np.inf] 39 | if len(min_ret_downs) == 0: min_ret_downs = [np.inf] 40 | 41 | if min_ret_ups[0] < min_ret_downs[0]: 42 | min_ret_situation[0] = 1 43 | else: 44 | min_ret_situation[1] = 1 45 | 46 | # Take profit and stop losses indices 47 | take_profit = np.where((differences >= tp) == True)[0] 48 | stop_loss = np.where((differences < sl) == True)[0] 49 | 50 | # Fluctuation directions coincide with take profit / stop loss actions? 51 | if min_ret_situation[0] == 1 and len(take_profit) != 0: 52 | take_action = 1 53 | elif min_ret_situation[1] == 1 and len(stop_loss) != 0: 54 | take_action = 1 55 | else: 56 | take_action = 0. 57 | 58 | return min_ret_situation, take_action, [take_profit, stop_loss] -------------------------------------------------------------------------------- /backtest_veroft/Overfit Probability.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stderr", 10 | "output_type": "stream", 11 | "text": [ 12 | "/usr/local/lib/python3.7/site-packages/pandas_datareader/compat/__init__.py:7: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.\n", 13 | " from pandas.util.testing import assert_frame_equal\n" 14 | ] 15 | } 16 | ], 17 | "source": [ 18 | "from pandas_datareader import data as datareader\n", 19 | "import matplotlib.pyplot as plt\n", 20 | "import pandas as pd\n", 21 | "import numpy as np\n", 22 | "from datetime import timedelta, datetime\n", 23 | "import math\n", 24 | "import random\n", 25 | "from itertools import combinations\n", 26 | "import scipy.stats as ss" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 2, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "import tensorflow as tf\n", 36 | "from sklearn.ensemble import RandomForestClassifier\n", 37 | "from sklearn.ensemble import BaggingClassifier\n", 38 | "from sklearn.metrics import confusion_matrix, classification_report, accuracy_score\n", 39 | "from sklearn.metrics import r2_score, matthews_corrcoef, f1_score, mean_absolute_error\n", 40 | "from sklearn.model_selection import BaseCrossValidator" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 3, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "import shap" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 4, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "from mlfinlab.microstructural_features import get_roll_measure, get_roll_impact\n", 59 | "from mlfinlab.microstructural_features import get_corwin_schultz_estimator, get_bekker_parkinson_vol\n", 60 | "from mlfinlab.microstructural_features import get_bar_based_kyle_lambda, get_bar_based_amihud_lambda, get_bar_based_hasbrouck_lambda\n", 61 | "from ta import add_all_ta_features\n", 62 | "from ta.utils import dropna\n", 63 | "from mlfinlab.features.fracdiff import frac_diff_ffd\n", 64 | "from utils import get_meta_barier, getDailyVol" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 5, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "from mlfinlab.backtest_statistics import sharpe_ratio\n", 74 | "from mlfinlab.backtest_statistics import probabilistic_sharpe_ratio\n", 75 | "from mlfinlab.backtest_statistics import deflated_sharpe_ratio\n", 76 | "from mlfinlab.backtest_statistics import information_ratio\n", 77 | "from mlfinlab.backtest_statistics import minimum_track_record_length\n", 78 | "from mlfinlab.backtest_statistics import drawdown_and_time_under_water" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 6, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "from yahoofinancials import YahooFinancials" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 7, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "import warnings\n", 97 | "warnings.filterwarnings('ignore')\n", 98 | "np.random.seed(0)" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "# Modeling and Training Routines" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 8, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "def create_model():\n", 115 | " clf=RandomForestClassifier(n_estimators=1,\n", 116 | " criterion='entropy',\n", 117 | " bootstrap=False,\n", 118 | " class_weight='balanced_subsample')\n", 119 | " clf=BaggingClassifier(base_estimator=clf,\n", 120 | " n_estimators=100,\n", 121 | " max_features=1.)\n", 122 | " return clf" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 9, 128 | "metadata": {}, 129 | "outputs": [], 130 | "source": [ 131 | "def train_and_evaluate_n_times(X_train, Y_train, X_test, Y_test):\n", 132 | " mmcs, pred_prs = [], []\n", 133 | " for n in range(N_SAMPLES):\n", 134 | "\n", 135 | " clf = create_model()\n", 136 | "\n", 137 | " clf.fit(X_train, Y_train)\n", 138 | " pred = clf.predict(X_test)\n", 139 | " pred_pr = clf.predict_proba(X_test)[:, 1]\n", 140 | "\n", 141 | " mmcs.append(matthews_corrcoef(Y_test, pred))\n", 142 | " pred_prs.append(pred_pr)\n", 143 | " return mmcs, pred_prs\n", 144 | "\n", 145 | "def visualize_mmcs(mmcs):\n", 146 | " plt.figure()\n", 147 | " plt.title(str(np.mean(mmcs)))\n", 148 | " plt.hist(mmcs)\n", 149 | " plt.axvline(np.mean(mmcs), color = 'red')\n", 150 | " plt.show()\n", 151 | " \n", 152 | "def backtest_predictions(pred_prs, P_test):\n", 153 | " bagging_strategies, bagging_returns = [], []\n", 154 | " for pred_pr in pred_prs:\n", 155 | " signal = [-(1-p) if p <= 0.5 else p for p in pred_pr]\n", 156 | " bagging_strategies.append((signal * P_test).cumsum())\n", 157 | " bagging_returns.append(signal * P_test)\n", 158 | " return bagging_strategies, bagging_returns\n", 159 | "\n", 160 | "def visualize_backtests(bagging_strategies, P_test):\n", 161 | " plt.figure(figsize = (15, 5))\n", 162 | " for strategy in bagging_strategies:\n", 163 | " plt.plot(strategy, color = 'grey', ls = '--', lw=0.5)\n", 164 | " plt.plot(P_test.cumsum(), lw = 3, label = 'Benchmark')\n", 165 | " plt.plot(np.array(bagging_strategies).mean(axis=0), lw = 3, label = 'Strategy')\n", 166 | " plt.legend()\n", 167 | " plt.show()" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "# Dataset Routines" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 10, 180 | "metadata": {}, 181 | "outputs": [], 182 | "source": [ 183 | "def ohclv_to_features(data):\n", 184 | " \n", 185 | " try:\n", 186 | " frac_diff_series = frac_diff_ffd(pd.DataFrame(np.log(data['close'])), 0.7, thresh=1e-4)\n", 187 | " except:\n", 188 | " print('Not calculated')\n", 189 | " frac_diff_series = pd.DataFrame(np.log(data['close'])).pct_change()\n", 190 | " \n", 191 | " # Add all ta features\n", 192 | " technical_features = add_all_ta_features(\n", 193 | " data, open=\"open\", high=\"high\", low=\"low\", close=\"close\", volume=\"volume\")\n", 194 | " \n", 195 | " data['feat_tech_volume_cmf'] = technical_features['volume_cmf']\n", 196 | " data['feat_tech_volatility_dcl'] = technical_features['volatility_dcl']\n", 197 | " data['feat_tech_trend_macd_diff'] = technical_features['trend_macd_diff']\n", 198 | " data['feat_tech_trend_vortex_ind_diff'] = technical_features['trend_vortex_ind_diff']\n", 199 | " data['feat_tech_momentum_stoch_signal'] = technical_features['momentum_stoch_signal']\n", 200 | " data['feat_tech_momentum_tsi'] = technical_features['momentum_tsi']\n", 201 | " \n", 202 | " data['feat_afml_roll_measure'] = get_roll_measure(data['close'], WINDOW)\n", 203 | " data['feat_afml_roll_impact'] = get_roll_impact(data['close'], data['volume'], WINDOW)\n", 204 | " data['feat_afml_corwin_schultz'] = get_corwin_schultz_estimator(data['high'], data['low'], WINDOW)\n", 205 | " data['feat_afml_bekker_parkinson_vol'] = get_bekker_parkinson_vol(data['high'], data['low'], WINDOW)\n", 206 | " data['feat_afml_kyle_lambda'] = get_bar_based_kyle_lambda(data['close'], data['volume'], WINDOW)\n", 207 | " data['feat_afml_amihud_lambda'] = get_bar_based_amihud_lambda(data['close'], data['volume'], WINDOW)\n", 208 | " data['feat_afml_hasbrouck_lambda'] = get_bar_based_hasbrouck_lambda(data['close'], data['volume'], WINDOW)\n", 209 | " \n", 210 | " data['feat_stat_min_frac_close'] = frac_diff_series.rolling(WINDOW).min()\n", 211 | " data['feat_stat_max_frac_close'] = frac_diff_series.rolling(WINDOW).max()\n", 212 | " data['feat_stat_mean_frac_close'] = frac_diff_series.rolling(WINDOW).mean()\n", 213 | " data['feat_stat_std_frac_close'] = frac_diff_series.rolling(WINDOW).std()\n", 214 | " data['feat_stat_skew_frac_close'] = frac_diff_series.rolling(WINDOW).skew()\n", 215 | " data['feat_stat_kurt_frac_close'] = frac_diff_series.rolling(WINDOW).kurt()\n", 216 | " data['feat_stat_autocorr_frac_close'] = frac_diff_series.rolling(WINDOW).apply(lambda x: x.autocorr(), raw=False)\n", 217 | " \n", 218 | " FEATURE_COLUMNS = [d for d in data.columns if 'feat_' in d]\n", 219 | " dataset = data[FEATURE_COLUMNS]\n", 220 | " \n", 221 | " dataset_normalized = {}\n", 222 | " for feature_column in dataset.columns:\n", 223 | " feature_i = dataset[feature_column]\n", 224 | " feature_i_norm = (feature_i - feature_i.rolling(WINDOW).mean()) / feature_i.rolling(WINDOW).std()\n", 225 | " dataset_normalized[feature_column] = feature_i_norm\n", 226 | " dataset_normalized = pd.DataFrame(\n", 227 | " dataset_normalized, index = dataset.index\n", 228 | " )\n", 229 | " \n", 230 | " dataset = dataset_normalized\n", 231 | " dataset['close'] = data['close']\n", 232 | " dataset = dataset.replace([np.inf, -np.inf], np.nan)\n", 233 | " dataset = dataset.dropna()\n", 234 | " \n", 235 | " return dataset" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": 11, 241 | "metadata": {}, 242 | "outputs": [], 243 | "source": [ 244 | "def createXY(inputs, outputs, training=False): \n", 245 | " \n", 246 | " def flatten_features_window(x):\n", 247 | " mean = x.mean(axis=1)\n", 248 | " std = x.std(axis=1)\n", 249 | " low = x.min(axis=1)\n", 250 | " high = x.max(axis=1)\n", 251 | " open_f = x[:, 0]\n", 252 | " close_f = x[:, -1]\n", 253 | " return close_f\n", 254 | " \n", 255 | " X, Y, P, T = [], [], [], []\n", 256 | " \n", 257 | " # FIXED IID ASSUMPTION (up to some point)\n", 258 | " if training:\n", 259 | " SKIP = WINDOW + HORIZON\n", 260 | " else:\n", 261 | " SKIP = 1\n", 262 | " \n", 263 | " for i in range(INPUT_WINDOW, len(inputs)-HORIZON, SKIP):\n", 264 | "\n", 265 | " if INPUT_WINDOW > 1:\n", 266 | " window = inputs[i-INPUT_WINDOW:i].values\n", 267 | " else:\n", 268 | " window = inputs.iloc[i].values\n", 269 | " future = (outputs[i+HORIZON] - outputs[i]) / outputs[i]\n", 270 | " future_binary = 1.0 if future > 0 else 0.0\n", 271 | "\n", 272 | " X.append(window)\n", 273 | " Y.append(future_binary)\n", 274 | " P.append(future)\n", 275 | " T.append(outputs.index[i+HORIZON])\n", 276 | "\n", 277 | " X, Y, P = np.array(X), np.array(Y), np.array(P)\n", 278 | " \n", 279 | " if INPUT_WINDOW > 1:\n", 280 | " X = flatten_features_window(X)\n", 281 | " return X, Y, P, T" 282 | ] 283 | }, 284 | { 285 | "cell_type": "markdown", 286 | "metadata": {}, 287 | "source": [ 288 | "# Metrics Routines" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": 12, 294 | "metadata": {}, 295 | "outputs": [], 296 | "source": [ 297 | "def ar1(x):\n", 298 | " return np.corrcoef(x[:-1], x[1:])[0,1]\n", 299 | "\n", 300 | "def autocorr_penalty(x):\n", 301 | " n = len(x)\n", 302 | " p = np.abs(ar1(x))\n", 303 | " return np.sqrt(1 + 2*np.sum([((n - i)/n)*p**i for i in range(1,n)]))\n", 304 | "\n", 305 | "def smart_sharpe(x):\n", 306 | " return (np.mean(x)/(np.std(x, ddof=1) * autocorr_penalty(x)) * np.sqrt(252))\n", 307 | "\n", 308 | "def calculate_all_metrics(benchmark_returns, strategy_returns, dates_array):\n", 309 | " \n", 310 | " res = {}\n", 311 | " \n", 312 | " benchmark_sharpe = sharpe_ratio(benchmark_returns, entries_per_year=252)\n", 313 | " benchmark_sharpe_smart = smart_sharpe(benchmark_returns)\n", 314 | " strategy_sharpe = sharpe_ratio(strategy_returns, entries_per_year=252)\n", 315 | " strategy_sharpe_smart = smart_sharpe(strategy_returns)\n", 316 | " psr = probabilistic_sharpe_ratio(strategy_sharpe, benchmark_sharpe, len(benchmark_returns))\n", 317 | " all_strategy_sharpes = []\n", 318 | " for r in bagging_returns:\n", 319 | " sr_i = sharpe_ratio(r, entries_per_year=252)\n", 320 | " all_strategy_sharpes.append(sr_i)\n", 321 | " dsr = deflated_sharpe_ratio(strategy_sharpe, all_strategy_sharpes, len(benchmark_returns))\n", 322 | " ir = information_ratio(strategy_returns, benchmark=np.mean(benchmark_returns), entries_per_year=252)\n", 323 | " mtrl = minimum_track_record_length(strategy_sharpe, benchmark_sharpe)\n", 324 | "\n", 325 | " res['benchmark_mean_returns'] = np.mean(benchmark_returns)\n", 326 | " res['strategy_mean_returns'] = np.mean(strategy_returns) \n", 327 | " res['benchmark_sharpe'] = benchmark_sharpe\n", 328 | " res['benchmark_sharpe_smart'] = benchmark_sharpe_smart\n", 329 | " res['strategy_sharpe'] = strategy_sharpe\n", 330 | " res['strategy_sharpe_smart'] = strategy_sharpe_smart\n", 331 | " res['probabilistic_sharpe_ratio'] = psr\n", 332 | " res['deflated_sharpe_ratio'] = dsr\n", 333 | " res['information_ratio'] = ir\n", 334 | " res['minimum_track_record_length'] = mtrl\n", 335 | "\n", 336 | " return res\n", 337 | "\n", 338 | "def calculate_important_features(dataset_train, cutoff_up = 0, cutoff_down = 3, visualize = False):\n", 339 | "\n", 340 | " X_train, Y_train, P_train, T_train = createXY(dataset_train[FEATURE_COLUMNS], dataset_train['close'], training=True)\n", 341 | " X_train_df = pd.DataFrame(X_train, columns = FEATURE_COLUMNS)\n", 342 | " clf = RandomForestClassifier(n_estimators=100, class_weight='balanced_subsample', criterion='entropy')\n", 343 | " clf.fit(X_train_df, Y_train)\n", 344 | " explainer = shap.TreeExplainer(clf)\n", 345 | " shap_values = explainer.shap_values(X_train_df)\n", 346 | " fi0 = np.abs(shap_values[0]).mean(axis=0)\n", 347 | " fi1 = np.abs(shap_values[1]).mean(axis=0)\n", 348 | " fi = fi0 + fi1\n", 349 | " imp = pd.DataFrame({\n", 350 | " 'feature': X_train_df.columns.tolist(),\n", 351 | " 'mean': fi\n", 352 | " })\n", 353 | " imp = imp.set_index('feature')\n", 354 | " \n", 355 | " if visualize:\n", 356 | " imp.sort_values('mean').plot.barh()\n", 357 | " \n", 358 | " return imp, imp.sort_values('mean')[::-1][cutoff_up:-cutoff_down].index.values.tolist()" 359 | ] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "execution_count": 13, 364 | "metadata": {}, 365 | "outputs": [], 366 | "source": [ 367 | "def calculate_all_metrics(benchmark_returns, strategy_returns, dates_array, mmcs, pred_prs):\n", 368 | " \n", 369 | " res = {}\n", 370 | " strategy_returns_mean = strategy_returns.mean(axis=0)\n", 371 | " \n", 372 | " benchmark_sharpe = sharpe_ratio(benchmark_returns, entries_per_year=252)\n", 373 | " benchmark_sharpe_smart = smart_sharpe(benchmark_returns)\n", 374 | " strategy_sharpe = sharpe_ratio(strategy_returns_mean, entries_per_year=252)\n", 375 | " strategy_sharpe_smart = smart_sharpe(strategy_returns_mean)\n", 376 | " psr = probabilistic_sharpe_ratio(strategy_sharpe, benchmark_sharpe, len(benchmark_returns))\n", 377 | " all_strategy_sharpes = []\n", 378 | " for r in strategy_returns:\n", 379 | " sr_i = sharpe_ratio(r, entries_per_year=252)\n", 380 | " all_strategy_sharpes.append(sr_i)\n", 381 | " dsr = deflated_sharpe_ratio(strategy_sharpe, all_strategy_sharpes, len(benchmark_returns))\n", 382 | " ir = information_ratio(strategy_returns_mean, benchmark=np.mean(benchmark_returns), entries_per_year=252)\n", 383 | " mtrl = minimum_track_record_length(strategy_sharpe, benchmark_sharpe)\n", 384 | " \n", 385 | " df_for_ddn = pd.DataFrame.from_dict({'Date': dates_array, \n", 386 | " 'Benchmark': benchmark_returns,\n", 387 | " 'Strategy': strategy_returns_mean})\n", 388 | " df_for_ddn = df_for_ddn.set_index('Date')\n", 389 | " df_for_ddn['Cumulative_Benchmark'] = df_for_ddn.Benchmark.cumsum().round(2)\n", 390 | " df_for_ddn['Cumulative_Strategy'] = df_for_ddn.Strategy.cumsum().round(2)\n", 391 | " df_for_ddn['HighValue_Benchmark'] = df_for_ddn['Cumulative_Benchmark'].cummax()\n", 392 | " df_for_ddn['HighValue_Strategy'] = df_for_ddn['Cumulative_Strategy'].cummax()\n", 393 | " df_for_ddn['Drawdown_Benchmark'] = df_for_ddn['Cumulative_Benchmark'] - df_for_ddn['HighValue_Benchmark']\n", 394 | " df_for_ddn['Drawdown_Strategy'] = df_for_ddn['Cumulative_Strategy'] - df_for_ddn['HighValue_Strategy']\n", 395 | "\n", 396 | " res['benchmark_mean_returns'] = np.mean(benchmark_returns)\n", 397 | " res['strategy_mean_returns'] = np.mean(strategy_returns) \n", 398 | " res['benchmark_sharpe'] = benchmark_sharpe\n", 399 | " res['benchmark_sharpe_smart'] = benchmark_sharpe_smart\n", 400 | " res['strategy_sharpe'] = strategy_sharpe\n", 401 | " res['strategy_sharpe_smart'] = strategy_sharpe_smart\n", 402 | " res['probabilistic_sharpe_ratio'] = psr\n", 403 | " res['deflated_sharpe_ratio'] = dsr\n", 404 | " res['information_ratio'] = ir\n", 405 | " res['minimum_track_record_length'] = mtrl\n", 406 | " res['benchmark_drawdown'] = df_for_ddn['Drawdown_Benchmark'].quantile(.05)\n", 407 | " res['strategy_drawdown'] = df_for_ddn['Drawdown_Strategy'].quantile(.05)\n", 408 | " res['mmc_mean'] = np.mean(mmcs)\n", 409 | " res['mmc_std'] = np.std(mmcs)\n", 410 | " res['mmc_sharpe'] = res['mmc_mean'] / res['mmc_std']\n", 411 | " res['model_certainty'] = abs(np.array(np.mean(pred_prs)) - 0.5) / 0.5\n", 412 | "\n", 413 | " return res" 414 | ] 415 | }, 416 | { 417 | "cell_type": "markdown", 418 | "metadata": {}, 419 | "source": [ 420 | "# Data reading" 421 | ] 422 | }, 423 | { 424 | "cell_type": "code", 425 | "execution_count": 14, 426 | "metadata": {}, 427 | "outputs": [], 428 | "source": [ 429 | "TICKER = 'DB'" 430 | ] 431 | }, 432 | { 433 | "cell_type": "code", 434 | "execution_count": 15, 435 | "metadata": {}, 436 | "outputs": [], 437 | "source": [ 438 | "aapl_yf = yahoo_financials_tech = YahooFinancials([TICKER])\n", 439 | "data = aapl_yf.get_historical_price_data('2000-01-01', '2020-08-01', 'daily')" 440 | ] 441 | }, 442 | { 443 | "cell_type": "code", 444 | "execution_count": 16, 445 | "metadata": { 446 | "scrolled": true 447 | }, 448 | "outputs": [], 449 | "source": [ 450 | "data = pd.DataFrame(data[TICKER]['prices'])\n", 451 | "data = data.set_index('formatted_date')\n", 452 | "data_original = data.dropna()" 453 | ] 454 | }, 455 | { 456 | "cell_type": "markdown", 457 | "metadata": {}, 458 | "source": [ 459 | "# Data Preparation" 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": 17, 465 | "metadata": {}, 466 | "outputs": [], 467 | "source": [ 468 | "WINDOW = 14\n", 469 | "INPUT_WINDOW = 1 # REDUCED THE CONTEXT\n", 470 | "HORIZON = 1\n", 471 | "N_SAMPLES = 25" 472 | ] 473 | }, 474 | { 475 | "cell_type": "code", 476 | "execution_count": 18, 477 | "metadata": {}, 478 | "outputs": [], 479 | "source": [ 480 | "dataset = ohclv_to_features(data_original)" 481 | ] 482 | }, 483 | { 484 | "cell_type": "code", 485 | "execution_count": 19, 486 | "metadata": {}, 487 | "outputs": [], 488 | "source": [ 489 | "FEATURE_COLUMNS = [d for d in dataset.columns if 'feat_' in d]" 490 | ] 491 | }, 492 | { 493 | "cell_type": "markdown", 494 | "metadata": {}, 495 | "source": [ 496 | "# CPCV Generation" 497 | ] 498 | }, 499 | { 500 | "cell_type": "code", 501 | "execution_count": 20, 502 | "metadata": {}, 503 | "outputs": [], 504 | "source": [ 505 | "class CPCV(BaseCrossValidator):\n", 506 | " # TODO: add purge \"holes\" !!!\n", 507 | " def __init__(self, X, N, k):\n", 508 | " self.X = X\n", 509 | " self.N = N\n", 510 | " self.k = k\n", 511 | "\n", 512 | " def generate_eras(self):\n", 513 | " # assuming exact division, we will cut-off small piece of time series\n", 514 | " # in the very beginning\n", 515 | " return np.array(sum([\n", 516 | " [i] * (len(self.X) // self.N) for i in range(self.N)\n", 517 | " ], []\n", 518 | " )\n", 519 | " )\n", 520 | " \n", 521 | " def split(self, X=None, y=None, groups=None):\n", 522 | " # removing first m items from time series\n", 523 | " eras = self.generate_eras()\n", 524 | " len_diff = abs(len(self.X) - len(eras))\n", 525 | " comb = list(combinations(range(self.N), self.N-self.k))\n", 526 | " all_splits = range(self.N)\n", 527 | "\n", 528 | " for combination in comb:\n", 529 | " train_indices, test_indices = [], []\n", 530 | " for c in combination:\n", 531 | " indices_train = list(np.where(eras == c)[0])\n", 532 | " train_indices.extend(indices_train)\n", 533 | " for t in list(set(all_splits) - set(combination)):\n", 534 | " indices_test = list(np.where(eras == t)[0])\n", 535 | " test_indices.extend(indices_test)\n", 536 | " yield(train_indices, test_indices) \n", 537 | " \n", 538 | " def get_n_splits(self):\n", 539 | " comb = combinations(range(self.N), self.N-self.k)\n", 540 | " return len(list(comb))" 541 | ] 542 | }, 543 | { 544 | "cell_type": "markdown", 545 | "metadata": {}, 546 | "source": [ 547 | "# Probability of strategy overfit" 548 | ] 549 | }, 550 | { 551 | "cell_type": "code", 552 | "execution_count": 66, 553 | "metadata": { 554 | "scrolled": true 555 | }, 556 | "outputs": [ 557 | { 558 | "name": "stdout", 559 | "output_type": "stream", 560 | "text": [ 561 | "processing split 1 / 35\n", 562 | "processing split 2 / 35\n", 563 | "processing split 3 / 35\n", 564 | "processing split 4 / 35\n", 565 | "processing split 5 / 35\n", 566 | "processing split 6 / 35\n", 567 | "processing split 7 / 35\n", 568 | "processing split 8 / 35\n", 569 | "processing split 9 / 35\n", 570 | "processing split 10 / 35\n", 571 | "processing split 11 / 35\n", 572 | "processing split 12 / 35\n", 573 | "processing split 13 / 35\n", 574 | "processing split 14 / 35\n", 575 | "processing split 15 / 35\n", 576 | "processing split 16 / 35\n", 577 | "processing split 17 / 35\n", 578 | "processing split 18 / 35\n", 579 | "processing split 19 / 35\n", 580 | "processing split 20 / 35\n", 581 | "processing split 21 / 35\n", 582 | "processing split 22 / 35\n", 583 | "processing split 23 / 35\n", 584 | "processing split 24 / 35\n", 585 | "processing split 25 / 35\n", 586 | "processing split 26 / 35\n", 587 | "processing split 27 / 35\n", 588 | "processing split 28 / 35\n", 589 | "processing split 29 / 35\n", 590 | "processing split 30 / 35\n", 591 | "processing split 31 / 35\n", 592 | "processing split 32 / 35\n", 593 | "processing split 33 / 35\n", 594 | "processing split 34 / 35\n", 595 | "processing split 35 / 35\n", 596 | "CPU times: user 18min 52s, sys: 12.5 s, total: 19min 5s\n", 597 | "Wall time: 21min 53s\n" 598 | ] 599 | } 600 | ], 601 | "source": [ 602 | "%%time\n", 603 | "\n", 604 | "N = 7\n", 605 | "k = 3\n", 606 | "\n", 607 | "cpcv = CPCV(dataset, N, k)\n", 608 | "\n", 609 | "ALL_P_TESTS_OOS = []\n", 610 | "ALL_RETURNS_OOS = []\n", 611 | "ALL_DATES_OOS = []\n", 612 | "ALL_MMCS_OOS, ALL_PREDS_OOS = [], []\n", 613 | "FEATURE_IMPORTANCES_OOS = []\n", 614 | "\n", 615 | "ALL_P_TESTS_IS = []\n", 616 | "ALL_RETURNS_IS = []\n", 617 | "ALL_DATES_IS = []\n", 618 | "ALL_MMCS_IS, ALL_PREDS_IS = [], []\n", 619 | "FEATURE_IMPORTANCES_IS = []\n", 620 | "\n", 621 | "for e, (train_ids, test_ids) in enumerate(cpcv.split()):\n", 622 | " print('processing split', e+1, '/', cpcv.get_n_splits())\n", 623 | " \n", 624 | " dataset_train, dataset_test = dataset.iloc[train_ids], dataset.iloc[test_ids]\n", 625 | " imp, IMPORTANT_FEATURES = calculate_important_features(dataset_train)\n", 626 | " \n", 627 | " X_train, Y_train, P_train, T_train = createXY(dataset_train[FEATURE_COLUMNS], dataset_train['close'], training=True)\n", 628 | " X_test, Y_test, P_test, T_test = createXY(dataset_test[FEATURE_COLUMNS], dataset_test['close'])\n", 629 | " \n", 630 | " mmcs, pred_prs = train_and_evaluate_n_times(X_train, Y_train, X_test, Y_test)\n", 631 | " bagging_strategies, bagging_returns = backtest_predictions(pred_prs, P_test)\n", 632 | " \n", 633 | " ALL_RETURNS_OOS.append(np.array(bagging_returns))\n", 634 | " ALL_P_TESTS_OOS.append(P_test)\n", 635 | " ALL_DATES_OOS.append(T_test)\n", 636 | " ALL_MMCS_OOS.append(mmcs)\n", 637 | " ALL_PREDS_OOS.append(pred_prs)\n", 638 | " FEATURE_IMPORTANCES_OOS.append(imp)\n", 639 | " \n", 640 | " mmcs_is, pred_prs_is = train_and_evaluate_n_times(X_train, Y_train, X_train, Y_train)\n", 641 | " bagging_strategies_is, bagging_returns_is = backtest_predictions(pred_prs_is, P_train) \n", 642 | " \n", 643 | " ALL_RETURNS_IS.append(np.array(bagging_returns_is))\n", 644 | " ALL_P_TESTS_IS.append(P_train)\n", 645 | " ALL_DATES_IS.append(T_train)\n", 646 | " ALL_MMCS_IS.append(mmcs_is)\n", 647 | " ALL_PREDS_IS.append(pred_prs_is)\n", 648 | " FEATURE_IMPORTANCES_IS.append(imp)" 649 | ] 650 | }, 651 | { 652 | "cell_type": "code", 653 | "execution_count": 67, 654 | "metadata": {}, 655 | "outputs": [], 656 | "source": [ 657 | "df_results_is = []\n", 658 | "for b_ret, s_ret, dates, mmcs, preds, fis in zip(ALL_P_TESTS_IS, \n", 659 | " ALL_RETURNS_IS, \n", 660 | " ALL_DATES_IS, \n", 661 | " ALL_MMCS_IS,\n", 662 | " ALL_PREDS_IS,\n", 663 | " FEATURE_IMPORTANCES_IS):\n", 664 | " res = calculate_all_metrics(\n", 665 | " np.array(b_ret), \n", 666 | " np.array(s_ret), \n", 667 | " [datetime.strptime(date, \"%Y-%m-%d\").date() for date in dates],\n", 668 | " mmcs, \n", 669 | " fis\n", 670 | " )\n", 671 | " df_results_is.append(res)\n", 672 | "df_results_is = pd.DataFrame(df_results_is)" 673 | ] 674 | }, 675 | { 676 | "cell_type": "code", 677 | "execution_count": 68, 678 | "metadata": {}, 679 | "outputs": [], 680 | "source": [ 681 | "df_results_oos = []\n", 682 | "for b_ret, s_ret, dates, mmcs, preds, fis in zip(ALL_P_TESTS_OOS, \n", 683 | " ALL_RETURNS_OOS, \n", 684 | " ALL_DATES_OOS, \n", 685 | " ALL_MMCS_OOS, \n", 686 | " ALL_PREDS_OOS, \n", 687 | " FEATURE_IMPORTANCES_OOS):\n", 688 | " res = calculate_all_metrics(\n", 689 | " np.array(b_ret), \n", 690 | " np.array(s_ret), \n", 691 | " [datetime.strptime(date, \"%Y-%m-%d\").date() for date in dates],\n", 692 | " mmcs, \n", 693 | " fis\n", 694 | " )\n", 695 | " df_results_oos.append(res)\n", 696 | "df_results_oos = pd.DataFrame(df_results_oos)" 697 | ] 698 | }, 699 | { 700 | "cell_type": "code", 701 | "execution_count": 69, 702 | "metadata": {}, 703 | "outputs": [], 704 | "source": [ 705 | "w_c_is = df_results_is['strategy_sharpe']\n", 706 | "w_c_oos = df_results_oos['strategy_sharpe']" 707 | ] 708 | }, 709 | { 710 | "cell_type": "markdown", 711 | "metadata": {}, 712 | "source": [ 713 | "# Regression" 714 | ] 715 | }, 716 | { 717 | "cell_type": "code", 718 | "execution_count": 80, 719 | "metadata": {}, 720 | "outputs": [ 721 | { 722 | "data": { 723 | "image/png": "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uvnmm3XTTTdp7969+vOf/6zKykrNm1fzC+P999/Xd77zHS1ZskS7d+9WYWGhHn/8ca1du1aS9IMf/EBz5sxRSUmJSktLNXPmzHqvceryqdu3b9eqVavUq1evs6795MmTZ30MgKBG8F577TWlpqZqypQpkqTk5GQtXrxYTz31lD755BM99thjysvL09ChQyVJF1xwgRYuXKif/exnkmpWy0tPT48dLysrq95rNLV86rx58zR48GANHz48tljTyy+/rCuuuEKXX365rrrqqtjz8+fP1+TJkzVixAhNnjxZBQUFuvHGGzV69GhdeumlsdX2JOmZZ55RTk5ObCGn6upqVVdXKy8vT4MGDVJWVpYWL17ckt2JdoigRvB27typYcOGnfZcz549lZGRobfffrvB/bXLkErSnDlzNGbMGI0bN06LFy/WRx99VO81zrR86vHjxzV8+HBt3bpVo0aN0hNPPCFJGjlypN544w299dZbmjRpkhYuXBj7mV27dukPf/iDnnuuZsHJzZs364UXXtC2bdu0YsUKFRUVqbS0VMuXL9cf//hHlZSUKDk5WcuWLVNJSYkOHjyoHTt2aPv27bFfUOi8CGp0eFOmTFFpaakmTpyoTZs2afjw4bG1QmqdafnUrl27avz48ZKkYcOGxT4tpqysTNdee62ysrK0aNGi2C8GSZowYYK6desW27766qvVp08fdevWTTfffLMKCwu1YcMGFRcX6+tf/7qGDBmiDRs2aN++fbrkkku0b98+zZw5U+vWrVPPnj0T3EMIHUGN4A0cOFDFxcWnPXf06FH99a9/1Ze//OUG9xcXF+uyyy6LbX/xi1/UXXfdpRdffFFdunTRjh076r1O7fKpixYt0gMPPKDVq1dLklJSUmKf+p2cnBwbd545c6ZmzJih7du36/HHH48tiyrVXxq17qeGm5ncXXfeeadKSkpUUlKiPXv2aP78+erdu7e2bt2q0aNHa8mSJbr77rub22XoYAhqBC83N1effPKJfvvb30qSqqurNXfuXOXl5encc8/V9OnTVVBQEFsLuqKiQj/60Y903333SZLWrVunqqoqSTVvPFZUVOjiiy8+7TXiWT61ro8//jh2nKeffvqMbV999VUdOXJEf/vb37R69WqNGDFCubm5WrlypQ4fPixJOnLkiN599119+OGHikQiuuWWW7RgwQJt2bKl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\n", 724 | "text/plain": [ 725 | "
" 726 | ] 727 | }, 728 | "metadata": { 729 | "needs_background": "light" 730 | }, 731 | "output_type": "display_data" 732 | } 733 | ], 734 | "source": [ 735 | "plt.figure()\n", 736 | "plt.hist(w_c_is.values, label = 'IS Sharpes', alpha = 0.55)\n", 737 | "plt.hist(w_c_oos.values, label = 'OOS Sharpes', alpha = 0.55)\n", 738 | "plt.legend()\n", 739 | "plt.show()" 740 | ] 741 | }, 742 | { 743 | "cell_type": "code", 744 | "execution_count": 70, 745 | "metadata": {}, 746 | "outputs": [], 747 | "source": [ 748 | "import statsmodels.api as sm" 749 | ] 750 | }, 751 | { 752 | "cell_type": "code", 753 | "execution_count": 71, 754 | "metadata": {}, 755 | "outputs": [], 756 | "source": [ 757 | "Y = w_c_oos\n", 758 | "X = w_c_is\n", 759 | "X = sm.add_constant(X)\n", 760 | "model = sm.OLS(Y,X)\n", 761 | "results = model.fit()" 762 | ] 763 | }, 764 | { 765 | "cell_type": "code", 766 | "execution_count": 72, 767 | "metadata": {}, 768 | "outputs": [ 769 | { 770 | "data": { 771 | "text/html": [ 772 | "\n", 773 | "\n", 774 | "\n", 775 | " \n", 776 | "\n", 777 | "\n", 778 | " \n", 779 | "\n", 780 | "\n", 781 | " \n", 782 | "\n", 783 | "\n", 784 | " \n", 785 | "\n", 786 | "\n", 787 | " \n", 788 | "\n", 789 | "\n", 790 | " \n", 791 | "\n", 792 | "\n", 793 | " \n", 794 | "\n", 795 | "\n", 796 | " \n", 797 | "\n", 798 | "\n", 799 | " \n", 800 | "\n", 801 | "
OLS Regression Results
Dep. Variable: strategy_sharpe R-squared: 0.021
Model: OLS Adj. R-squared: -0.009
Method: Least Squares F-statistic: 0.7108
Date: Sun, 29 Nov 2020 Prob (F-statistic): 0.405
Time: 20:19:20 Log-Likelihood: -4.2922
No. Observations: 35 AIC: 12.58
Df Residuals: 33 BIC: 15.70
Df Model: 1
Covariance Type: nonrobust
\n", 802 | "\n", 803 | "\n", 804 | " \n", 805 | "\n", 806 | "\n", 807 | " \n", 808 | "\n", 809 | "\n", 810 | " \n", 811 | "\n", 812 | "
coef std err t P>|t| [0.025 0.975]
const 0.3459 0.428 0.809 0.424 -0.524 1.216
strategy_sharpe -0.0236 0.028 -0.843 0.405 -0.080 0.033
\n", 813 | "\n", 814 | "\n", 815 | " \n", 816 | "\n", 817 | "\n", 818 | " \n", 819 | "\n", 820 | "\n", 821 | " \n", 822 | "\n", 823 | "\n", 824 | " \n", 825 | "\n", 826 | "
Omnibus: 0.349 Durbin-Watson: 1.318
Prob(Omnibus): 0.840 Jarque-Bera (JB): 0.496
Skew: 0.191 Prob(JB): 0.780
Kurtosis: 2.560 Cond. No. 138.


Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified." 827 | ], 828 | "text/plain": [ 829 | "\n", 830 | "\"\"\"\n", 831 | " OLS Regression Results \n", 832 | "==============================================================================\n", 833 | "Dep. Variable: strategy_sharpe R-squared: 0.021\n", 834 | "Model: OLS Adj. R-squared: -0.009\n", 835 | "Method: Least Squares F-statistic: 0.7108\n", 836 | "Date: Sun, 29 Nov 2020 Prob (F-statistic): 0.405\n", 837 | "Time: 20:19:20 Log-Likelihood: -4.2922\n", 838 | "No. Observations: 35 AIC: 12.58\n", 839 | "Df Residuals: 33 BIC: 15.70\n", 840 | "Df Model: 1 \n", 841 | "Covariance Type: nonrobust \n", 842 | "===================================================================================\n", 843 | " coef std err t P>|t| [0.025 0.975]\n", 844 | "-----------------------------------------------------------------------------------\n", 845 | "const 0.3459 0.428 0.809 0.424 -0.524 1.216\n", 846 | "strategy_sharpe -0.0236 0.028 -0.843 0.405 -0.080 0.033\n", 847 | "==============================================================================\n", 848 | "Omnibus: 0.349 Durbin-Watson: 1.318\n", 849 | "Prob(Omnibus): 0.840 Jarque-Bera (JB): 0.496\n", 850 | "Skew: 0.191 Prob(JB): 0.780\n", 851 | "Kurtosis: 2.560 Cond. No. 138.\n", 852 | "==============================================================================\n", 853 | "\n", 854 | "Warnings:\n", 855 | "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n", 856 | "\"\"\"" 857 | ] 858 | }, 859 | "execution_count": 72, 860 | "metadata": {}, 861 | "output_type": "execute_result" 862 | } 863 | ], 864 | "source": [ 865 | "results.summary()" 866 | ] 867 | }, 868 | { 869 | "cell_type": "code", 870 | "execution_count": 75, 871 | "metadata": {}, 872 | "outputs": [], 873 | "source": [ 874 | "x = np.arange(np.min(w_c_is), np.max(w_c_is), 0.5)\n", 875 | "y = 0.3459 + -0.0236 * x" 876 | ] 877 | }, 878 | { 879 | "cell_type": "code", 880 | "execution_count": 90, 881 | "metadata": {}, 882 | "outputs": [ 883 | { 884 | "data": { 885 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAEGCAYAAAB7DNKzAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nO3deXhU5fXA8e8hLGHfpRBQkCWyJCSQUJFVBKGCQkHqghXcxbpXLNSqqFhosaJUlPorCq4oFIHihrIUUVQSFoHILmoCshPABAnJ+f1xZyaTZDKZrDNJzud55snMvXfmnpkEzrzLPa+oKsYYY0x+qgQ7AGOMMaHNEoUxxhi/LFEYY4zxyxKFMcYYvyxRGGOM8atqsAMoaU2aNNHWrVsHOwxjjClXEhMTj6hqU1/7KlyiaN26NQkJCcEOwxhjyhUR+T6/fUHtehKRISKyQ0R2i8jEfI75nYgkicg2EXmrrGM0xpjKLmgtChEJA2YBg4BkYL2ILFXVJK9j2gOTgF6qelxEzgtOtMYYU3kFs0XRA9itqntV9SwwHxie65jbgFmqehxAVQ+VcYzGGFPpBXOMIgL40etxMvDrXMd0ABCRz4EwYLKqfpT7hUTkduB2gPPPP79UgjV5ZWRkkJyczJkzZ4IdijEmQOHh4bRs2ZJq1aoF/JxQH8yuCrQH+gMtgTUiEqWqJ7wPUtWXgZcB4uLirHhVGUlOTqZu3bq0bt0aEQl2OMaYAqgqR48eJTk5mTZt2gT8vGAmihSgldfjlq5t3pKBr1Q1A/hORHbiJI71ZRNiaFq8MYXpH+9g/4l0WjSoyYTBkYyIjSjzOM6cOWNJwphyRERo3Lgxhw8fLtTzgjlGsR5oLyJtRKQ6cC2wNNcxi3FaE4hIE5yuqL1lGWSoWbwxhUmLtpByIh0FUk6kM2nRFhZvzJ1jy4YlCWPKl6L8mw1aolDVc8DdwMfAt8C7qrpNRJ4Ukatch30MHBWRJGAVMEFVjwYn4tAw/eMdpGdk5tiWnpHJ9I93BCkiY0xFF9TrKFT1A1XtoKptVfVp17bHVHWp676q6oOq2klVo1R1fjDjDQX7T6QXantFFxYWRkxMDF26dOHKK6/kxIkTBT+pjDz22GN8+umnxX6duXPncvfddxfqOX/961+Lfd7i2rdvH126dAEgLS2NMWPGEBUVRZcuXejduzenT58u8XO2bt2aI0eO5NmemprKjTfeSLt27Wjbti033ngjqampnv3btm1jwIABREZG0r59e5566inca/UcPHiQYcOG0bVrVzp16sQVV1zh89xPP/00nTt3Jjo6mpiYGL766iu/MZUnVuupnGnRoGahtld0NWvWZNOmTWzdupVGjRoxa9asYr/muXPnSiAyePLJJxk4cGCJvFZhhUKi8Pb888/TrFkztmzZwtatW5kzZ06hZt0U1y233MKFF17I7t272bNnD23atOHWW28FID09nauuuoqJEyeyY8cONm/ezBdffMGLL74IOAl/0KBBbN68maSkJKZNm5bn9detW8eyZcvYsGED33zzDZ9++imtWrXKc1xhldTfYnFZoihnJgyOpGa1sBzbalYLY8LgyCBFFDp69uxJSoozVrNnzx6GDBlC9+7d6dOnD9u3b/dsv/jii4mKiuIvf/kLderUAWD16tX06dOHq666ik6dOpGZmcmECROIj48nOjqaf/3rXwAcOHCAvn37eloxn332GZmZmYwbN44uXboQFRXFjBkzABg3bhwLFy4EYMWKFcTGxhIVFcXNN9/ML7/8AjjfNh9//HG6detGVFSUJ87cfvzxR/r370/79u154oknPNvfeOMNevToQUxMDHfccQeZmZlMnDiR9PR0YmJiGDNmDNOnT2fmzJkAPPDAAwwYMACAlStXMmbMGACWL19Oz5496RoTy5ArR/DljmS2HzjJqs+/pF+/fnTv3p3Bgwdz4MABAPr378+f/vQnevToQYcOHfjss8/8/m4OHDhARET2hIvIyEhq1KiR57jx48cTFxdH586defzxxz3b8/ucjh49yuWXX07nzp259dZb8bVi5+7du0lMTOTRRx/1bHvsscdISEhgz549vPXWW/Tq1YvLL78cgFq1avHCCy94EsKBAwdo2bKl57nR0dE+31+TJk0876lJkya0aNHCs/+f//xnnti//vprevbsSWxsLJdccgk7djjdx3PnzuWqq65iwIABXHbZZaxevZq+ffsydOhQIiMjufPOO8nKygKyf2/dunVj9OjRnlbaxIkT6dSpE9HR0Tz00EP5/2ICpaoV6ta9e3et6N7bkKyXTF2hrf+0TC+ZukLf25AclDiSkpJybujXL+9t1ixn388/+97/6qvO/sOH8+4LQO3atVVV9dy5c3r11Vfrhx9+qKqqAwYM0J07d6qq6pdffqmXXnqpqqoOHTpU33rrLVVVfemllzzPX7VqldaqVUv37t2rqqr/+te/9KmnnlJV1TNnzmj37t117969+swzz+iUKVM85zx58qQmJCTowIEDPTEdP35cVVXHjh2rCxYs0PT0dG3ZsqXu2LFDVVV///vf64wZM1RV9YILLtCZM2eqquqsWbP0lltuyfMeX331Vf3Vr36lR44c0bS0NO3cubOuX79ek5KSdNiwYXr27FlVVR0/frzOmzcvx+eiqrpu3Tq9+uqrVVW1d+/eGh8fr2fPntXJkyfr7Nmz9fDhw9qnTx/98dAx3ZJ8Qu+b9LiO/+MkTdh7SLt276E79zl/X/Pnz9ebbrpJVVX79eunDz74oKqqvv/++3rZZZflifu7777Tzp07q6rqxo0btWnTpnrxxRfrI4884vnd5Hb06FHPZ9uvXz/dvHmz38/pnnvu0SeeeEJVVZctW6aAHj58OMdrLlmyREeMGJHnXCNGjNAlS5boAw88oM8991ye/Q0aNNDU1FT96KOPtH79+tq/f3+dMmWKpqSk5Dn21KlT2rVrV23fvr2OHz9eV69e7dmXX+ypqamakZGhqqqffPKJjhw5UlWd33dERITns1i1apXWqFFD9+zZo+fOndOBAwfqggULPL+306dPq6rqtGnT9IknntAjR45ohw4dNCsrS1Wz/x695fm3q6pAgubz/2qoX0dhfBgRGxGU6bChyP3NOSUlhY4dOzJo0CBOnz7NF198wejRoz3Hub/Br1u3jsWLFwNw/fXX5/i21aNHD8/c8uXLl/PNN994WgSpqans2rWL+Ph4br75ZjIyMhgxYgQxMTFceOGF7N27l3vuuYehQ4d6vpm67dixgzZt2tChQwcAxo4dy6xZs7j//vsBGDlyJADdu3dn0aJFPt/noEGDaNy4sef4tWvXUrVqVRITE4mPj/d8Fuedl7fKTffu3UlMTOTkyZPUqFGDbt26kZCQwGeffcbMmTP58ssvSUpKYlD/fihKRkYG0d3i2bdnF7t3fMtVV/yGGtWqkJmZSfPmzT2v6x33vn37/P6eYmJi2Lt3L8uXL+fTTz8lPj6edevW0bFjxxzHvfvuu7z88sucO3eOAwcOkJSU5PkG7+tzWrNmjef+0KFDadiwod84imLw4MHs3buXjz76iA8//JDY2Fi2bt1K06bZhVbr1KlDYmIin332GatWreKaa65h2rRpjBs3Lt/YU1NTGTt2LLt27UJEyMjI8LzeoEGDaNSokedxjx49uPDCCwG47rrrWLt2LeHh4SQlJdGrVy8Azp49S8+ePalfvz7h4eHccsstDBs2jGHDhhX7M7BEYUrO6tX576tVy//+Jk3878+He4wiLS2NwYMHM2vWLMaNG0eDBg3YtGlToV6rdu3anvuqyj//+U8GDx6c57g1a9bw/vvvM27cOB588EFuvPFGNm/ezMcff8zs2bN59913eeWVVwI+r7u7IiwsLN8+6dxTGkUEVWXs2LFMnTrV7+tXq1aNNm3aMHfuXC655BKio6NZtWoVu3fvpmPHjuzZs4dBgwYxafpLOZ6369tttO1wEa8vWU50ywZFittbnTp1GDlyJCNHjqRKlSp88MEHORLFd999xzPPPMP69etp2LAh48aNy3HVf2HP59apUyc2bdpEVlYWVao4ve1ZWVls2rSJTp06cejQIdasWZPjOXv37qVOnTrUq1cPgEaNGnH99ddz/fXXM2zYMNasWcOoUaNyPCcsLIz+/fvTv39/oqKimDdvnidR+Ir90Ucf5dJLL+W9995j37599O/f3/Na3n+LkP/vf9CgQbz99tt53vPXX3/NihUrWLhwIS+88AIrV64M+PPyxcYoTIVQq1YtZs6cyT/+8Q9q1apFmzZtWLBgAeD8p79582YALr74Yv7zn/8AMH9+/pPoBg8ezEsvveT5lrdz505+/vlnvv/+e5o1a8Ztt93GrbfeyoYNGzhy5AhZWVmMGjWKKVOmsGHDhhyvFRkZyb59+9i9ezcAr7/+Ov369SvU+/vkk084duwY6enpLF68mF69enHZZZexcOFCDh1ySqAdO3aM7793KkVXq1YtxzfUPn368Mwzz9C3b1/69OnD7NmziY2NRUS4+OKL+fzzzznww3cApKX9zL69u2ndtj3Hjx5h20anbH9GRgbbtm0rVNxun3/+OcePHwecb75JSUlccMEFOY45efIktWvXpn79+hw8eJAPP/ywwNft27cvb73lFJX+8MMPPefw1q5dO2JjY5kyZYpn25QpU+jWrRvt2rVjzJgxrF271jNDLT09nXvvvZeHH34YcMZy0tLSADh16hR79uzJUypox44d7Nq1y/N406ZNed5fbqmpqZ5x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\n", 886 | "text/plain": [ 887 | "
" 888 | ] 889 | }, 890 | "metadata": { 891 | "needs_background": "light" 892 | }, 893 | "output_type": "display_data" 894 | } 895 | ], 896 | "source": [ 897 | "plt.figure()\n", 898 | "plt.scatter(w_c_is, w_c_oos, label = 'Backtests IS vs OOS Sharpes')\n", 899 | "plt.plot(x, y, color = 'red', ls = '--', label = 'Regression between IS and OOS Sharpes')\n", 900 | "plt.xlabel('Sharpe ratios IS')\n", 901 | "plt.ylabel('Sharpe ratios OOS')\n", 902 | "plt.legend()\n", 903 | "plt.show()" 904 | ] 905 | }, 906 | { 907 | "cell_type": "markdown", 908 | "metadata": {}, 909 | "source": [ 910 | "# Logits" 911 | ] 912 | }, 913 | { 914 | "cell_type": "code", 915 | "execution_count": 81, 916 | "metadata": {}, 917 | "outputs": [], 918 | "source": [ 919 | "n_star = np.argmax(w_c_is)\n", 920 | "w_c = (ss.rankdata(w_c_oos) - n_star) / len(w_c_oos)\n", 921 | "w_c = w_c + np.abs(np.min(w_c))" 922 | ] 923 | }, 924 | { 925 | "cell_type": "code", 926 | "execution_count": 82, 927 | "metadata": {}, 928 | "outputs": [], 929 | "source": [ 930 | "y_c = np.log(w_c / (1 - w_c))\n", 931 | "y_c[y_c==-np.inf] = 0" 932 | ] 933 | }, 934 | { 935 | "cell_type": "code", 936 | "execution_count": 84, 937 | "metadata": {}, 938 | "outputs": [ 939 | { 940 | "data": { 941 | "text/plain": [ 942 | "0.6507251193096577" 943 | ] 944 | }, 945 | "execution_count": 84, 946 | "metadata": {}, 947 | "output_type": "execute_result" 948 | } 949 | ], 950 | "source": [ 951 | "y_c_neg = y_c[y_c < 0]\n", 952 | "y_c_neg = (y_c_neg - y_c_neg.min()) / (y_c_neg.max() - y_c_neg.min())\n", 953 | "pbo = np.mean(y_c_neg)\n", 954 | "pbo" 955 | ] 956 | }, 957 | { 958 | "cell_type": "code", 959 | "execution_count": 88, 960 | "metadata": {}, 961 | "outputs": [ 962 | { 963 | "data": { 964 | "image/png": "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\n", 965 | "text/plain": [ 966 | "
" 967 | ] 968 | }, 969 | "metadata": { 970 | "needs_background": "light" 971 | }, 972 | "output_type": "display_data" 973 | } 974 | ], 975 | "source": [ 976 | "plt.figure()\n", 977 | "plt.hist(y_c, label = 'Logits $w_c$, PBO = ' + str(np.round(pbo, 2)))\n", 978 | "plt.legend()\n", 979 | "plt.show()" 980 | ] 981 | }, 982 | { 983 | "cell_type": "markdown", 984 | "metadata": {}, 985 | "source": [ 986 | "# Strategy risk" 987 | ] 988 | }, 989 | { 990 | "cell_type": "code", 991 | "execution_count": 106, 992 | "metadata": {}, 993 | "outputs": [], 994 | "source": [ 995 | "def binHR(sl, pt, n, tSR):\n", 996 | " a = (n + tSR**2) * (pt - sl)**2\n", 997 | " b = (2*n*sl - tSR**2*(pt-sl))*(pt-sl)\n", 998 | " c = n*sl**2\n", 999 | " p = (-b + (b**2 - 4*a*c)**0.5) / (2.*a)\n", 1000 | " return p" 1001 | ] 1002 | }, 1003 | { 1004 | "cell_type": "code", 1005 | "execution_count": 107, 1006 | "metadata": {}, 1007 | "outputs": [], 1008 | "source": [ 1009 | "def probFailure(ret, freq, tSR):\n", 1010 | " # Derive probability that strategy may fail\n", 1011 | " rPos, rNeg = ret[ret>0].mean(), ret[ret<=0].mean()\n", 1012 | " p = ret[ret>0].shape[0] / float(ret.shape[0])\n", 1013 | " thresP = binHR(rNeg, rPos, freq, tSR)\n", 1014 | " risk = ss.norm.cdf(thresP, p, p*(1-p)) # approximation to bootstrap\n", 1015 | " return risk" 1016 | ] 1017 | }, 1018 | { 1019 | "cell_type": "code", 1020 | "execution_count": 136, 1021 | "metadata": { 1022 | "scrolled": true 1023 | }, 1024 | "outputs": [], 1025 | "source": [ 1026 | "failure_probs = []\n", 1027 | "for returns in ALL_RETURNS_OOS:\n", 1028 | " some_returns = returns.mean(axis=0)\n", 1029 | " pf = probFailure(some_returns, 260, 0.0)\n", 1030 | " failure_probs.append(pf)" 1031 | ] 1032 | }, 1033 | { 1034 | "cell_type": "code", 1035 | "execution_count": 137, 1036 | "metadata": {}, 1037 | "outputs": [ 1038 | { 1039 | "data": { 1040 | "image/png": "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DBgwgJycHF566aXoulatjpw98tDUs4eMHDmShQsXRttPnjyZfv368e677/LMM8+Qn59Pbm4uP/jBD6ioqDhie9nZ2dx6661HTJU7fvx4brjhBs455xxuvfVWCgsLOffcc+nbty+jR4+O3oADqqYNyM3NpU+fPrVOyjVs2DA2bdpEbm4uixcvrnNbNaf3rW7Lli1kZWVFn/ft2/ew7+GYMWM488wzueqqqzh08eRdd93FwIED6dOnDxMnToy+XnM/h/qal5fH6aefHj3ar6io4Kc//SkDBw6kb9++/O53vzuib0uXLqVnz5706NGDFi1acPnllx/2Mzyk+vTIY8aMYf78+STiIk8VdAmdPZ7BHs8IOkZc9u/fH52Cd/To0WRkZPCnP/2JlStXsmDBAiZPntzgf+j79u3jnHPOYdWqVdE/69955x0KCwtJTU2tdTpg+OdUuZMmTYpOnwtVsysuWbKE++67j6uvvpq7776b1atXk5OTw5133hltV1JSQmFhIf/7v//Ltddee8T2586dy9e//nUKCwu58MILj7qtQ9P7Tp48+bBt3HjjjVx33XUMHjyYX//612zevDm67q9//Su//e1v+fDDD9mwYQPvvFM1lDZp0iSWLVvGBx98wP79+w8blqm5n6KiIpYuXcqrr77KDTfcQGlpKU888QStW7dm2bJlLFu2jMcee4zPPvvssFybNm2ia9eu0edZWVls2rTpiO9B9XZpaWm0bt06egeqxtCQi4RO15SquxBtrDz2L9+vOeRSVlbGz3/+cxYtWkRKSgqbNm1i69atdOzYsd7bTk1N5bLLLgNg/vz5rFixIjpJ1v79+4+YwfGQ6lPlVh/fHjt2LKmpqezevZtdu3ZFJ+8aN24cY8eOPeL9F110EXv27GHXrl20aVP7zyLWtuq6td7w4cPZsGEDb7zxBq+//jr9+/ePfqaQn58fPXrPzc2lqKiIQYMGsWDBAu655x5KSkrYuXMnvXv35tvf/nat+/nOd75DSkoKvXr1okePHnz88ce8+eabrF69OjrR2e7du1m7di3du3evNWMQVNAldHqnfQ7AxoPHfkGv6dlnn2X79u2sWLGC9PR0srOzKS0trbN9WloalZWV0efV22ZkZETHzd2dcePG8d///d8xM9Q2VS40bKrd2p7Xx9H22bZtW6688kquvPJKRo4cyaJFi2jX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\n", 1041 | "text/plain": [ 1042 | "
" 1043 | ] 1044 | }, 1045 | "metadata": { 1046 | "needs_background": "light" 1047 | }, 1048 | "output_type": "display_data" 1049 | } 1050 | ], 1051 | "source": [ 1052 | "plt.figure()\n", 1053 | "plt.hist(failure_probs, label = 'Failure prob for Sharpe 0.0')\n", 1054 | "plt.axvline(0.5, ls = '--', color = 'grey', label = '50% probability')\n", 1055 | "plt.legend()\n", 1056 | "plt.show()" 1057 | ] 1058 | }, 1059 | { 1060 | "cell_type": "code", 1061 | "execution_count": 120, 1062 | "metadata": {}, 1063 | "outputs": [ 1064 | { 1065 | "data": { 1066 | "text/plain": [ 1067 | "35" 1068 | ] 1069 | }, 1070 | "execution_count": 120, 1071 | "metadata": {}, 1072 | "output_type": "execute_result" 1073 | } 1074 | ], 1075 | "source": [ 1076 | "len(ALL_RETURNS_OOS)" 1077 | ] 1078 | } 1079 | ], 1080 | "metadata": { 1081 | "kernelspec": { 1082 | "display_name": "Python 3", 1083 | "language": "python", 1084 | "name": "python3" 1085 | }, 1086 | "language_info": { 1087 | "codemirror_mode": { 1088 | "name": "ipython", 1089 | "version": 3 1090 | }, 1091 | "file_extension": ".py", 1092 | "mimetype": "text/x-python", 1093 | "name": "python", 1094 | "nbconvert_exporter": "python", 1095 | "pygments_lexer": "ipython3", 1096 | "version": "3.7.6" 1097 | } 1098 | }, 1099 | "nbformat": 4, 1100 | "nbformat_minor": 2 1101 | } 1102 | -------------------------------------------------------------------------------- /backtest_veroft/Testing Routines.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "import pandas as pd\n", 11 | "import matplotlib.pylab as plt" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "# Targeting Sharpe ratio as a function of # of bets" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 2, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "out = []\n", 28 | "p = 0.55\n", 29 | "\n", 30 | "for i in np.arange(1e5):\n", 31 | " rnd = np.random.binomial(n=1, p=p)\n", 32 | " x = (1 if rnd==1 else -1)\n", 33 | " out.append(x)" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 3, 39 | "metadata": {}, 40 | "outputs": [ 41 | { 42 | "data": { 43 | "text/plain": [ 44 | "(0.09794, 0.9951923213128203, 0.09841313874970542)" 45 | ] 46 | }, 47 | "execution_count": 3, 48 | "metadata": {}, 49 | "output_type": "execute_result" 50 | } 51 | ], 52 | "source": [ 53 | "np.mean(out), np.std(out), np.mean(out) / np.std(out)" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "# Computing the implied precision" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 4, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "def binHR(sl, pt, n, tSR):\n", 70 | " a = (n + tSR**2) * (pt - sl)**2\n", 71 | " b = (2*n*sl - tSR**2*(pt-sl))*(pt-sl)\n", 72 | " c = n*sl**2\n", 73 | " p = (-b + (b**2 - 4*a*c)**0.5) / (2.*a)\n", 74 | " return p" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 5, 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "data": { 84 | "text/plain": [ 85 | "0.6844497543078034" 86 | ] 87 | }, 88 | "execution_count": 5, 89 | "metadata": {}, 90 | "output_type": "execute_result" 91 | } 92 | ], 93 | "source": [ 94 | "binHR(-0.025, 0.02, 52, 2)" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "# Computing the implied betting frequency" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 9, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "def binN(sl, pt, p, tSR):\n", 111 | " freq=(tSR*(pt-sl))**2*p*(1-p)/((pt-sl)*p+sl)**2 # possible extraneous\n", 112 | " if not np.isclose(binHR(sl,pt,freq,tSR), p):return\n", 113 | " return freq" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 10, 119 | "metadata": {}, 120 | "outputs": [ 121 | { 122 | "data": { 123 | "text/plain": [ 124 | "486.00000000000085" 125 | ] 126 | }, 127 | "execution_count": 10, 128 | "metadata": {}, 129 | "output_type": "execute_result" 130 | } 131 | ], 132 | "source": [ 133 | "binN(-0.025, 0.02, 0.6, 2)" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "# Calculating the strategy risk in practice" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 11, 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [ 149 | "import scipy.stats as ss" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 67, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "def mix_gaussians(mu1, mu2, sigma1, sigma2, prob1, n):\n", 159 | " r1 = np.random.normal(mu1, sigma1, size = int(n * prob1))\n", 160 | " r2 = np.random.normal(mu2, sigma2, size = int(n) - r1.shape[0])\n", 161 | " ret = np.append(r1, r2, axis=0)\n", 162 | " np.random.shuffle(ret)\n", 163 | " return ret" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": 80, 169 | "metadata": {}, 170 | "outputs": [ 171 | { 172 | "data": { 173 | "image/png": "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\n", 174 | "text/plain": [ 175 | "
" 176 | ] 177 | }, 178 | "metadata": { 179 | "needs_background": "light" 180 | }, 181 | "output_type": "display_data" 182 | } 183 | ], 184 | "source": [ 185 | "r = mix_gaussians(0.05, -0.1, 0.1, 0.75, 0.85, 2600)\n", 186 | "\n", 187 | "plt.figure()\n", 188 | "plt.plot(r.cumsum())\n", 189 | "plt.show()" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 81, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "def probFailure(ret, freq, tSR):\n", 199 | " # Derive probability that strategy may fail\n", 200 | " rPos, rNeg = ret[ret>0].mean(), ret[ret<=0].mean()\n", 201 | " p = ret[ret>0].shape[0] / float(ret.shape[0])\n", 202 | " thresP = binHR(rNeg, rPos, freq, tSR)\n", 203 | " risk = ss.norm.cdf(thresP, p, p*(1-p)) # approximation to bootstrap\n", 204 | " return risk" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": 82, 210 | "metadata": {}, 211 | "outputs": [ 212 | { 213 | "data": { 214 | "text/plain": [ 215 | "0.47936643039537374" 216 | ] 217 | }, 218 | "execution_count": 82, 219 | "metadata": {}, 220 | "output_type": "execute_result" 221 | } 222 | ], 223 | "source": [ 224 | "probFailure(r, freq = 260, tSR = 2.0)" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": {}, 231 | "outputs": [], 232 | "source": [] 233 | } 234 | ], 235 | "metadata": { 236 | "kernelspec": { 237 | "display_name": "Python 3", 238 | "language": "python", 239 | "name": "python3" 240 | }, 241 | "language_info": { 242 | "codemirror_mode": { 243 | "name": "ipython", 244 | "version": 3 245 | }, 246 | "file_extension": ".py", 247 | "mimetype": "text/x-python", 248 | "name": "python", 249 | "nbconvert_exporter": "python", 250 | "pygments_lexer": "ipython3", 251 | "version": "3.7.6" 252 | } 253 | }, 254 | "nbformat": 4, 255 | "nbformat_minor": 2 256 | } 257 | -------------------------------------------------------------------------------- /backtest_veroft/readme.md: -------------------------------------------------------------------------------- 1 | The scripts to evaluate backtest probability 2 | -------------------------------------------------------------------------------- /bars-labels-diff/Differentiation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import pandas as pd\n", 12 | "import numpy as np\n", 13 | "import matplotlib.pylab as plt\n", 14 | "import datetime" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 5, 20 | "metadata": { 21 | "collapsed": true, 22 | "scrolled": true 23 | }, 24 | "outputs": [], 25 | "source": [ 26 | "data_raw = pd.read_csv('IVE_tickbidask.txt', header=None, names=['Date','Time','Price','Bid','Ask','Size'])" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 6, 32 | "metadata": { 33 | "collapsed": true 34 | }, 35 | "outputs": [], 36 | "source": [ 37 | "data = data_raw.iloc[:100000]" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 7, 43 | "metadata": {}, 44 | "outputs": [ 45 | { 46 | "name": "stderr", 47 | "output_type": "stream", 48 | "text": [ 49 | "/anaconda2/lib/python2.7/site-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: \n", 50 | "A value is trying to be set on a copy of a slice from a DataFrame.\n", 51 | "Try using .loc[row_indexer,col_indexer] = value instead\n", 52 | "\n", 53 | "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n", 54 | " \"\"\"Entry point for launching an IPython kernel.\n" 55 | ] 56 | } 57 | ], 58 | "source": [ 59 | "data['DateTime'] = pd.to_datetime(data['Date'] + ' ' + data['Time'])\n", 60 | "data = data.drop(columns = ['Date', 'Time'])\n", 61 | "data = data.set_index('DateTime')" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 8, 67 | "metadata": { 68 | "collapsed": true 69 | }, 70 | "outputs": [], 71 | "source": [ 72 | "from scipy import stats\n", 73 | "from bars import *" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 10, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | " close high low open volume\n", 86 | "DateTime \n", 87 | "2009-09-28 09:47:22 51.06 51.07 50.71 50.79 30044\n", 88 | "2009-09-28 09:54:38 51.13 51.15 51.06 51.06 28975\n", 89 | "2009-09-28 10:00:15 51.21 51.21 51.08 51.13 32841\n", 90 | "2009-09-28 10:05:50 51.21 51.28 51.20 51.21 33764\n", 91 | "2009-09-28 10:15:13 51.25 51.29 51.19 51.22 37104\n" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "bars = TickBarSeries(data)\n", 97 | "tick_bars = bars.process_ticks(frequency = 100)\n", 98 | "print tick_bars.head()" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 11, 104 | "metadata": { 105 | "collapsed": true 106 | }, 107 | "outputs": [], 108 | "source": [ 109 | "from statsmodels.tsa.stattools import adfuller" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 12, 115 | "metadata": { 116 | "collapsed": true 117 | }, 118 | "outputs": [], 119 | "source": [ 120 | "def getWeights(d,size):\n", 121 | " w=[1.]\n", 122 | " for k in range(1,size):\n", 123 | " w_=-w[-1]/k*(d-k+1)\n", 124 | " w.append(w_)\n", 125 | " w=np.array(w[::-1]).reshape(-1,1)\n", 126 | " return w\n", 127 | "\n", 128 | "def fracDiff(series,d,thres=.001):\n", 129 | "\n", 130 | " #1) Compute weights for the longest series\n", 131 | " w=getWeights(d,series.shape[0])\n", 132 | " #2) Determine initial calcs to be skipped based on weight-loss threshold\n", 133 | " w_=np.cumsum(abs(w))\n", 134 | " w_/=w_[-1]\n", 135 | " skip=w_[w_>thres].shape[0]\n", 136 | " #3) Apply weights to values\n", 137 | " df={}\n", 138 | " for name in series.columns:\n", 139 | " seriesF,df_=series[[name]].fillna(method='ffill').dropna(),pd.Series()\n", 140 | " for iloc in range(skip,seriesF.shape[0]):\n", 141 | " loc=seriesF.index[iloc]\n", 142 | " if not np.isfinite(series.loc[loc,name]):continue # exclude NAs\n", 143 | " df_[loc]=np.dot(w[-(iloc+1):,:].T,seriesF.loc[:loc])[0,0]\n", 144 | " df[name]=df_.copy(deep=True)\n", 145 | " df=pd.concat(df,axis=1)\n", 146 | " return df\n" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "# Differentiation for tick bars" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 13, 159 | "metadata": { 160 | "scrolled": true 161 | }, 162 | "outputs": [ 163 | { 164 | "ename": "KeyboardInterrupt", 165 | "evalue": "", 166 | "output_type": "error", 167 | "traceback": [ 168 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 169 | "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", 170 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0md\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0.0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2.1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0.1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mts1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlog\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtick_bars\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mts2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfracDiff\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mts1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0md\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mcorr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcorrcoef\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mts1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mts2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'close'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mts2\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'close'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 171 | "\u001b[0;32m\u001b[0m in \u001b[0;36mfracDiff\u001b[0;34m(series, d, thres)\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0mloc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mseriesF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0miloc\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misfinite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mseries\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;32mcontinue\u001b[0m \u001b[0;31m# exclude NAs\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 24\u001b[0;31m \u001b[0mdf_\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mw\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miloc\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mT\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mseriesF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 25\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdf_\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdeep\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconcat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 172 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/series.pyc\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m 937\u001b[0m \u001b[0;31m# do the setitem\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 938\u001b[0m \u001b[0mcacher_needs_updating\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_check_is_chained_assignment_possible\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 939\u001b[0;31m \u001b[0msetitem\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 940\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcacher_needs_updating\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 941\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_maybe_update_cacher\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 173 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/series.pyc\u001b[0m in \u001b[0;36msetitem\u001b[0;34m(key, value)\u001b[0m\n\u001b[1;32m 913\u001b[0m \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 914\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 915\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 916\u001b[0m \u001b[0;32mreturn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 917\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 174 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/indexing.pyc\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m 187\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_apply_if_callable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mobj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 188\u001b[0m \u001b[0mindexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_setitem_indexer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 189\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_setitem_with_indexer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindexer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 190\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 191\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_validate_key\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 175 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/indexing.pyc\u001b[0m in \u001b[0;36m_setitem_with_indexer\u001b[0;34m(self, indexer, value)\u001b[0m\n\u001b[1;32m 403\u001b[0m \u001b[0;31m# GH12246\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 404\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_unique\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 405\u001b[0;31m \u001b[0mnew_indexer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mindex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_indexer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnew_index\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 406\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mnew_indexer\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 407\u001b[0m return self._setitem_with_indexer(new_indexer,\n", 176 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/indexes/base.pyc\u001b[0m in \u001b[0;36mget_indexer\u001b[0;34m(self, target, method, limit, tolerance)\u001b[0m\n\u001b[1;32m 3220\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget_indexer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmethod\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlimit\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtolerance\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3221\u001b[0m \u001b[0mmethod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmissing\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclean_reindex_fill_method\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3222\u001b[0;31m \u001b[0mtarget\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_ensure_index\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtarget\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3223\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mtolerance\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3224\u001b[0m \u001b[0mtolerance\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_convert_tolerance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtolerance\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 177 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/indexes/base.pyc\u001b[0m in \u001b[0;36m_ensure_index\u001b[0;34m(index_like, copy)\u001b[0m\n\u001b[1;32m 4972\u001b[0m \u001b[0mindex_like\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindex_like\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4973\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 4974\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mIndex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindex_like\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4975\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4976\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 178 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/indexes/base.pyc\u001b[0m in \u001b[0;36m__new__\u001b[0;34m(cls, data, dtype, copy, name, fastpath, tupleize_cols, **kwargs)\u001b[0m\n\u001b[1;32m 415\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 416\u001b[0m return DatetimeIndex(subarr, copy=copy,\n\u001b[0;32m--> 417\u001b[0;31m name=name, **kwargs)\n\u001b[0m\u001b[1;32m 418\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mlibts\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mOutOfBoundsDatetime\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 419\u001b[0m \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 179 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/indexes/datetimes.pyc\u001b[0m in \u001b[0;36m__new__\u001b[0;34m(cls, data, freq, start, end, periods, tz, normalize, closed, ambiguous, dayfirst, yearfirst, dtype, copy, name, verify_integrity)\u001b[0m\n\u001b[1;32m 446\u001b[0m \u001b[0msubarr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msubarr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mview\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_NS_DTYPE\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 447\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 448\u001b[0;31m \u001b[0msubarr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcls\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_simple_new\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msubarr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfreq\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfreq\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtz\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtz\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 449\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mdtype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 450\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mis_dtype_equal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msubarr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 180 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/indexes/datetimes.pyc\u001b[0m in \u001b[0;36m_simple_new\u001b[0;34m(cls, values, name, freq, tz, dtype, **kwargs)\u001b[0m\n\u001b[1;32m 641\u001b[0m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 642\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 643\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mis_object_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 644\u001b[0m return cls(values, name=name, freq=freq, tz=tz,\n\u001b[1;32m 645\u001b[0m dtype=dtype, **kwargs).values\n", 181 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/dtypes/common.pyc\u001b[0m in \u001b[0;36mis_object_dtype\u001b[0;34m(arr_or_dtype)\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0marr_or_dtype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 117\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 118\u001b[0;31m \u001b[0mtipo\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_get_dtype_type\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marr_or_dtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 119\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0missubclass\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtipo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mobject_\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 120\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", 182 | "\u001b[0;32m/anaconda2/lib/python2.7/site-packages/pandas/core/dtypes/common.pyc\u001b[0m in \u001b[0;36m_get_dtype_type\u001b[0;34m(arr_or_dtype)\u001b[0m\n\u001b[1;32m 1861\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marr_or_dtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mPeriodDtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1862\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mPeriodDtypeType\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1863\u001b[0;31m \u001b[0;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marr_or_dtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstring_types\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1864\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_categorical_dtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marr_or_dtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1865\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mCategoricalDtypeType\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", 183 | "\u001b[0;31mKeyboardInterrupt\u001b[0m: " 184 | ] 185 | } 186 | ], 187 | "source": [ 188 | "corrs, adfs = [], []\n", 189 | "\n", 190 | "for d in np.arange(0.0, 2.1, 0.1):\n", 191 | " ts1 = np.log(tick_bars)\n", 192 | " ts2 = fracDiff(ts1, d)\n", 193 | "\n", 194 | " corr = np.corrcoef(ts1.loc[ts2.index,'close'],ts2['close'])[0,1]\n", 195 | " adf = adfuller(ts2.close)[0]\n", 196 | "\n", 197 | " corrs.append(corr)\n", 198 | " adfs.append(adf)" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "metadata": { 205 | "collapsed": true, 206 | "scrolled": true 207 | }, 208 | "outputs": [], 209 | "source": [ 210 | "stats = pd.DataFrame({\n", 211 | " 'd': np.arange(0.0, 2.1, 0.1),\n", 212 | " 'corr': corrs,\n", 213 | " 'adfs': adfs\n", 214 | "})\n", 215 | "stats.index = stats['d']" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": { 222 | "collapsed": true 223 | }, 224 | "outputs": [], 225 | "source": [ 226 | "stats[['corr', 'adfs']].plot(secondary_y='adfs')\n", 227 | "plt.show()" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": 335, 233 | "metadata": {}, 234 | "outputs": [ 235 | { 236 | "data": { 237 | "text/plain": [ 238 | "-18.301437043431015" 239 | ] 240 | }, 241 | "execution_count": 335, 242 | "metadata": {}, 243 | "output_type": "execute_result" 244 | } 245 | ], 246 | "source": [ 247 | "adfuller(tick_bars.close.diff().fillna(1e-5))[0]" 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "# Exercises" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": 157, 260 | "metadata": { 261 | "collapsed": true 262 | }, 263 | "outputs": [], 264 | "source": [ 265 | "gauss = np.random.normal(0, 1, 1000)" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 158, 271 | "metadata": {}, 272 | "outputs": [ 273 | { 274 | "data": { 275 | "image/png": "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\nrkJggg==\n", 276 | "text/plain": [ 277 | "
" 278 | ] 279 | }, 280 | "metadata": {}, 281 | "output_type": "display_data" 282 | } 283 | ], 284 | "source": [ 285 | "plt.figure()\n", 286 | "plt.plot(gauss)\n", 287 | "plt.show()" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": 159, 293 | "metadata": {}, 294 | "outputs": [ 295 | { 296 | "data": { 297 | "text/plain": [ 298 | "(-30.721619887470883,\n", 299 | " 0.0,\n", 300 | " 0,\n", 301 | " 999,\n", 302 | " {'1%': -3.4369127451400474,\n", 303 | " '10%': -2.568312754566378,\n", 304 | " '5%': -2.864437475834273},\n", 305 | " 2766.951680753896)" 306 | ] 307 | }, 308 | "execution_count": 159, 309 | "metadata": {}, 310 | "output_type": "execute_result" 311 | } 312 | ], 313 | "source": [ 314 | "adfuller(gauss)" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 161, 320 | "metadata": {}, 321 | "outputs": [ 322 | { 323 | "data": { 324 | "text/plain": [ 325 | "(-1.6300726870515139,\n", 326 | " 0.4674526661720234,\n", 327 | " 0,\n", 328 | " 999,\n", 329 | " {'1%': -3.4369127451400474,\n", 330 | " '10%': -2.568312754566378,\n", 331 | " '5%': -2.864437475834273},\n", 332 | " 2765.4906005929283)" 333 | ] 334 | }, 335 | "execution_count": 161, 336 | "metadata": {}, 337 | "output_type": "execute_result" 338 | } 339 | ], 340 | "source": [ 341 | "adfuller(np.cumsum(gauss))" 342 | ] 343 | }, 344 | { 345 | "cell_type": "code", 346 | "execution_count": 164, 347 | "metadata": {}, 348 | "outputs": [ 349 | { 350 | "data": { 351 | "text/plain": [ 352 | "(-14.66133248162864,\n", 353 | " 3.377743248351254e-27,\n", 354 | " 14,\n", 355 | " 983,\n", 356 | " {'1%': -3.4370198458812156,\n", 357 | " '10%': -2.568337912084273,\n", 358 | " '5%': -2.864484708707697},\n", 359 | " 2829.3679503081694)" 360 | ] 361 | }, 362 | "execution_count": 164, 363 | "metadata": {}, 364 | "output_type": "execute_result" 365 | } 366 | ], 367 | "source": [ 368 | "adfuller(np.diff(np.diff(np.cumsum(gauss))))" 369 | ] 370 | } 371 | ], 372 | "metadata": { 373 | "kernelspec": { 374 | "display_name": "Python 2", 375 | "language": "python", 376 | "name": "python2" 377 | }, 378 | "language_info": { 379 | "codemirror_mode": { 380 | "name": "ipython", 381 | "version": 2 382 | }, 383 | "file_extension": ".py", 384 | "mimetype": "text/x-python", 385 | "name": "python", 386 | "nbconvert_exporter": "python", 387 | "pygments_lexer": "ipython2", 388 | "version": "2.7.14" 389 | } 390 | }, 391 | "nbformat": 4, 392 | "nbformat_minor": 2 393 | } 394 | -------------------------------------------------------------------------------- /bars-labels-diff/Labeling.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import pandas as pd\n", 12 | "import numpy as np\n", 13 | "import matplotlib.pylab as plt\n", 14 | "import datetime" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# Data loading" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 2, 27 | "metadata": { 28 | "collapsed": true 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "data_raw = pd.read_csv('IVE_tickbidask.txt', header=None, names=['Date','Time','Price','Bid','Ask','Size'])" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 3, 38 | "metadata": { 39 | "collapsed": true 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "data = data_raw#.iloc[:100000]" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 7, 49 | "metadata": { 50 | "collapsed": true 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "data['DateTime'] = pd.to_datetime(data['Date'] + ' ' + data['Time'])\n", 55 | "data = data.drop(columns = ['Date', 'Time'])\n", 56 | "data = data.set_index('DateTime')" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 8, 62 | "metadata": { 63 | "collapsed": true 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "from scipy import stats\n", 68 | "from bars import *" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 9, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stdout", 78 | "output_type": "stream", 79 | "text": [ 80 | " open high low close volume\n", 81 | "DateTime \n", 82 | "2009-09-28 09:40:00 50.7900 50.85 50.7100 50.81 9197\n", 83 | "2009-09-28 09:50:00 50.8100 51.12 50.7833 51.07 26447\n", 84 | "2009-09-28 10:00:00 51.0988 51.15 51.0800 51.12 53716\n", 85 | "2009-09-28 10:10:00 51.1500 51.29 51.1500 51.27 47673\n", 86 | "2009-09-28 10:20:00 51.2800 51.29 51.2100 51.21 30631\n" 87 | ] 88 | } 89 | ], 90 | "source": [ 91 | "bars = BarSeries(data)\n", 92 | "time_bars = bars.process_ticks(frequency='10Min')\n", 93 | "print time_bars.head()" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 10, 99 | "metadata": {}, 100 | "outputs": [ 101 | { 102 | "name": "stdout", 103 | "output_type": "stream", 104 | "text": [ 105 | " close high low open volume\n", 106 | "DateTime \n", 107 | "2009-09-28 09:47:22 51.06 51.07 50.71 50.79 30044\n", 108 | "2009-09-28 09:54:38 51.13 51.15 51.06 51.06 28975\n", 109 | "2009-09-28 10:00:15 51.21 51.21 51.08 51.13 32841\n", 110 | "2009-09-28 10:05:50 51.21 51.28 51.20 51.21 33764\n", 111 | "2009-09-28 10:15:13 51.25 51.29 51.19 51.22 37104\n" 112 | ] 113 | } 114 | ], 115 | "source": [ 116 | "bars = TickBarSeries(data)\n", 117 | "tick_bars = bars.process_ticks(frequency = 100)\n", 118 | "print tick_bars.head()" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "# Fixed horizon" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 96, 131 | "metadata": { 132 | "collapsed": true, 133 | "scrolled": true 134 | }, 135 | "outputs": [], 136 | "source": [ 137 | "WINDOW = 180\n", 138 | "HORIZON = 60\n", 139 | "T = 0.025\n", 140 | "\n", 141 | "labels = []\n", 142 | "for i in range(WINDOW, 10000, 1):\n", 143 | " window = tick_bars.iloc[i-WINDOW:i]\n", 144 | " now = tick_bars.close[i]\n", 145 | " future = tick_bars.close[i+HORIZON]\n", 146 | " ret = (future - now) / now\n", 147 | " \n", 148 | " if ret > T:\n", 149 | " labels.append(1)\n", 150 | " elif ret < -T:\n", 151 | " labels.append(-1)\n", 152 | " else:\n", 153 | " labels.append(0)" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 97, 159 | "metadata": {}, 160 | "outputs": [ 161 | { 162 | "data": { 163 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAD8CAYAAAB+UHOxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAFsxJREFUeJzt3X+QXeV93/H3xyjg2GktCbYqlrAl\nj1W7uB1jugFSd5IYOUKQjkWnmMrThDVVRklK0qQ/pob6D7XYTO1OpzRMa1KNUSycFEyUeFATEioL\nmExnAkbYGBsI1gIhSAW0QUCaMCYW/vaP+yy5lnfZe6W7d8Hn/ZrZuc/5nuec85xzpf3sPefce1NV\nSJK65w1LPQBJ0tIwACSpowwASeooA0CSOsoAkKSOMgAkqaMMAEnqKANAkjrKAJCkjlq21AN4Naed\ndlqtXbt2qYchSa8r9913359W1cRC/V7TAbB27Vr279+/1MOQpNeVJE8M0s9TQJLUUQaAJHXUQAGQ\n5F8meTDJN5LclOSNSdYluSfJdJIvJDm59T2lTU+3+Wv71nNVqz+S5ILF2SVJ0iAWDIAkq4F/AUxW\n1d8BTgK2AJ8Grq2qdwLPAVvbIluB51r92taPJGe25d4DbAI+k+Sk0e6OJGlQg54CWgb8YJJlwJuA\np4Dzgd1t/i7g4tbe3KZp8zckSavfXFUvVdXjwDRwzonvgiTpeCwYAFV1CPjPwJ/Q+8X/AnAf8HxV\nHW3dDgKrW3s18GRb9mjrf2p/fY5lJEljNsgpoBX0/npfB7wVeDO9UziLIsm2JPuT7J+ZmVmszUhS\n5w1yCuiDwONVNVNV3wZ+G3g/sLydEgJYAxxq7UPAGQBt/luAZ/vrcyzziqraUVWTVTU5MbHg+xgk\nScdpkAD4E+C8JG9q5/I3AA8BdwKXtD5TwK2tvadN0+bfUb0vHt4DbGl3Ca0D1gNfHs1uSJKGteA7\ngavqniS7ga8AR4GvAjuA3wVuTvLJVruhLXID8Pkk08ARenf+UFUPJrmFXngcBa6oqpdHvD/qmK2f\nu3ephzB2N3z0h5d6CPo+MdBHQVTVdmD7MeXHmOMunqr6FvDhedZzDXDNkGOUJC0C3wksSR1lAEhS\nRxkAktRRBoAkdZQBIEkdZQBIUkcZAJLUUQaAJHWUASBJHWUASFJHGQCS1FEGgCR1lAEgSR1lAEhS\nRxkAktRRBoAkdZQBIEkdtWAAJHlXkvv7fv4syS8nWZlkb5ID7XFF658k1yWZTvJAkrP71jXV+h9I\nMjX/ViVJi23BAKiqR6rqrKo6C/h7wIvAF4ErgX1VtR7Y16YBLqT3he/rgW3A9QBJVtL7Wslz6X2V\n5PbZ0JAkjd+wp4A2AI9W1RPAZmBXq+8CLm7tzcCN1XM3sDzJ6cAFwN6qOlJVzwF7gU0nvAeSpOMy\nbABsAW5q7VVV9VRrPw2sau3VwJN9yxxstfnqkqQlMHAAJDkZ+BDwm8fOq6oCahQDSrItyf4k+2dm\nZkaxSknSHIZ5BXAh8JWqeqZNP9NO7dAeD7f6IeCMvuXWtNp89e9SVTuqarKqJicmJoYYniRpGMME\nwEf4q9M/AHuA2Tt5poBb++qXtbuBzgNeaKeKbgc2JlnRLv5ubDVJ0hJYNkinJG8GfgL42b7yp4Bb\nkmwFngAubfXbgIuAaXp3DF0OUFVHknwCuLf1u7qqjpzwHkiSjstAAVBVfwGcekztWXp3BR3bt4Ar\n5lnPTmDn8MOUJI2a7wSWpI4yACSpowwASeooA0CSOsoAkKSOMgAkqaMMAEnqKANAkjrKAJCkjjIA\nJKmjDABJ6igDQJI6ygCQpI4yACSpowwASeooA0CSOsoAkKSOMgAkqaMGCoAky5PsTvJHSR5O8iNJ\nVibZm+RAe1zR+ibJdUmmkzyQ5Oy+9Uy1/geSTM2/RUnSYhv0FcCvAL9fVe8G3gs8DFwJ7Kuq9cC+\nNg1wIbC+/WwDrgdIshLYDpwLnANsnw0NSdL4LRgASd4C/ChwA0BV/WVVPQ9sBna1bruAi1t7M3Bj\n9dwNLE9yOnABsLeqjlTVc8BeYNNI90aSNLBBXgGsA2aAX0vy1SSfTfJmYFVVPdX6PA2sau3VwJN9\nyx9stfnq3yXJtiT7k+yfmZkZbm8kSQMbJACWAWcD11fV+4C/4K9O9wBQVQXUKAZUVTuqarKqJicm\nJkaxSknSHAYJgIPAwaq6p03vphcIz7RTO7THw23+IeCMvuXXtNp8dUnSElgwAKrqaeDJJO9qpQ3A\nQ8AeYPZOning1tbeA1zW7gY6D3ihnSq6HdiYZEW7+Lux1SRJS2DZgP1+EfiNJCcDjwGX0wuPW5Js\nBZ4ALm19bwMuAqaBF1tfqupIkk8A97Z+V1fVkZHshSRpaAMFQFXdD0zOMWvDHH0LuGKe9ewEdg4z\nQEnS4vCdwJLUUQaAJHWUASBJHWUASFJHGQCS1FEGgCR1lAEgSR1lAEhSRxkAktRRBoAkdZQBIEkd\nZQBIUkcZAJLUUQaAJHWUASBJHWUASFJHGQCS1FEDBUCSP07y9ST3J9nfaiuT7E1yoD2uaPUkuS7J\ndJIHkpzdt56p1v9Akqn5tidJWnzDvAL4QFWdVVWzXw15JbCvqtYD+9o0wIXA+vazDbgeeoEBbAfO\nBc4Bts+GhiRp/E7kFNBmYFdr7wIu7qvfWD13A8uTnA5cAOytqiNV9RywF9h0AtuXJJ2AQQOggP+d\n5L4k21ptVVU91dpPA6taezXwZN+yB1ttvrokaQksG7DfP6iqQ0n+BrA3yR/1z6yqSlKjGFALmG0A\nb3vb20axSknSHAZ6BVBVh9rjYeCL9M7hP9NO7dAeD7fuh4Az+hZf02rz1Y/d1o6qmqyqyYmJieH2\nRpI0sAUDIMmbk/y12TawEfgGsAeYvZNnCri1tfcAl7W7gc4DXminim4HNiZZ0S7+bmw1SdISGOQU\n0Crgi0lm+//Pqvr9JPcCtyTZCjwBXNr63wZcBEwDLwKXA1TVkSSfAO5t/a6uqiMj2xNJ0lAWDICq\negx47xz1Z4ENc9QLuGKede0Edg4/TEnSqPlOYEnqKANAkjrKAJCkjjIAJKmjDABJ6igDQJI6ygCQ\npI4yACSpowwASeooA0CSOsoAkKSOMgAkqaMMAEnqKANAkjrKAJCkjjIAJKmjDABJ6qiBAyDJSUm+\nmuR32vS6JPckmU7yhSQnt/opbXq6zV/bt46rWv2RJBeMemckSYMb5hXALwEP901/Gri2qt4JPAds\nbfWtwHOtfm3rR5IzgS3Ae4BNwGeSnHRiw5ckHa+BAiDJGuAngc+26QDnA7tbl13Axa29uU3T5m9o\n/TcDN1fVS1X1OL0vjT9nFDshSRreoK8A/ivwb4HvtOlTgeer6mibPgisbu3VwJMAbf4Lrf8r9TmW\nkSSN2YIBkOQfAoer6r4xjIck25LsT7J/ZmZmHJuUpE4a5BXA+4EPJflj4GZ6p35+BVieZFnrswY4\n1NqHgDMA2vy3AM/21+dY5hVVtaOqJqtqcmJiYugdkiQNZsEAqKqrqmpNVa2ldxH3jqr6p8CdwCWt\n2xRwa2vvadO0+XdUVbX6lnaX0DpgPfDlke2JJGkoyxbuMq+PATcn+STwVeCGVr8B+HySaeAIvdCg\nqh5McgvwEHAUuKKqXj6B7UuSTsBQAVBVdwF3tfZjzHEXT1V9C/jwPMtfA1wz7CAlSaPnO4ElqaMM\nAEnqKANAkjrKAJCkjjIAJKmjDABJ6igDQJI6ygCQpI4yACSpowwASeooA0CSOsoAkKSOMgAkqaMM\nAEnqKANAkjrKAJCkjjIAJKmjFgyAJG9M8uUkX0vyYJL/0OrrktyTZDrJF5Kc3OqntOnpNn9t37qu\navVHklywWDslSVrYIK8AXgLOr6r3AmcBm5KcB3wauLaq3gk8B2xt/bcCz7X6ta0fSc6k9/3A7wE2\nAZ9JctIod0aSNLgFA6B6/rxN/kD7KeB8YHer7wIubu3NbZo2f0OStPrNVfVSVT0OTDPHdwpLksZj\noGsASU5Kcj9wGNgLPAo8X1VHW5eDwOrWXg08CdDmvwCc2l+fYxlJ0pgNFABV9XJVnQWsofdX+7sX\na0BJtiXZn2T/zMzMYm1GkjpvqLuAqup54E7gR4DlSZa1WWuAQ619CDgDoM1/C/Bsf32OZfq3saOq\nJqtqcmJiYpjhSZKGMMhdQBNJlrf2DwI/ATxMLwguad2mgFtbe0+bps2/o6qq1be0u4TWAeuBL49q\nRyRJw1m2cBdOB3a1O3beANxSVb+T5CHg5iSfBL4K3ND63wB8Psk0cITenT9U1YNJbgEeAo4CV1TV\ny6PdHUnSoBYMgKp6AHjfHPXHmOMunqr6FvDhedZ1DXDN8MOUJI2a7wSWpI4yACSpowwASeooA0CS\nOsoAkKSOMgAkqaMMAEnqKANAkjrKAJCkjjIAJKmjDABJ6igDQJI6ygCQpI4yACSpowwASeooA0CS\nOsoAkKSOMgAkqaMG+VL4M5LcmeShJA8m+aVWX5lkb5ID7XFFqyfJdUmmkzyQ5Oy+dU21/geSTM23\nTUnS4hvkFcBR4F9X1ZnAecAVSc4ErgT2VdV6YF+bBrgQWN9+tgHXQy8wgO3AufS+S3j7bGhIksZv\nwQCoqqeq6iut/f+Ah4HVwGZgV+u2C7i4tTcDN1bP3cDyJKcDFwB7q+pIVT0H7AU2jXRvJEkDG+oa\nQJK1wPuAe4BVVfVUm/U0sKq1VwNP9i12sNXmqx+7jW1J9ifZPzMzM8zwJElDGDgAkvwQ8FvAL1fV\nn/XPq6oCahQDqqodVTVZVZMTExOjWKUkaQ4DBUCSH6D3y/83quq3W/mZdmqH9ni41Q8BZ/QtvqbV\n5qtLkpbAIHcBBbgBeLiq/kvfrD3A7J08U8CtffXL2t1A5wEvtFNFtwMbk6xoF383tpokaQksG6DP\n+4GfBr6e5P5W+3fAp4BbkmwFngAubfNuAy4CpoEXgcsBqupIkk8A97Z+V1fVkZHshSRpaAsGQFX9\nHyDzzN4wR/8CrphnXTuBncMMUJK0OHwnsCR1lAEgSR1lAEhSRxkAktRRBoAkdZQBIEkdZQBIUkcZ\nAJLUUQaAJHWUASBJHWUASFJHGQCS1FEGgCR1lAEgSR1lAEhSRxkAktRRBoAkddQg3wm8M8nhJN/o\nq61MsjfJgfa4otWT5Lok00keSHJ23zJTrf+BJFNzbUuSND6DvAL4HLDpmNqVwL6qWg/sa9MAFwLr\n28824HroBQawHTgXOAfYPhsakqSlMch3Av9BkrXHlDcDP97au4C7gI+1+o3te4HvTrI8yemt797Z\nL4FPspdeqNx0wnvwKrZ+7t6FO30fueGjP7zUQ5D0OnK81wBWVdVTrf00sKq1VwNP9vU72Grz1SVJ\nS+SELwK3v/ZrBGMBIMm2JPuT7J+ZmRnVaiVJxzjeAHimndqhPR5u9UPAGX391rTafPXvUVU7qmqy\nqiYnJiaOc3iSpIUcbwDsAWbv5JkCbu2rX9buBjoPeKGdKrod2JhkRbv4u7HVJElLZMGLwEluoncR\n97QkB+ndzfMp4JYkW4EngEtb99uAi4Bp4EXgcoCqOpLkE8DsVdmrZy8IS9JCunZDB4znpo5B7gL6\nyDyzNszRt4Ar5lnPTmDnUKOTJC0a3wksSR1lAEhSRxkAktRRBoAkdZQBIEkdZQBIUkcZAJLUUQaA\nJHWUASBJHWUASFJHGQCS1FEGgCR1lAEgSR1lAEhSRxkAktRRBoAkdZQBIEkdNfYASLIpySNJppNc\nOe7tS5J6xhoASU4C/jtwIXAm8JEkZ45zDJKknnG/AjgHmK6qx6rqL4Gbgc1jHoMkifEHwGrgyb7p\ng60mSRqzVNX4NpZcAmyqqp9p0z8NnFtVv9DXZxuwrU2+C3jkBDZ5GvCnJ7D8YnFcw3Fcw3Fcw/l+\nHNfbq2pioU7LjnPlx+sQcEbf9JpWe0VV7QB2jGJjSfZX1eQo1jVKjms4jms4jms4XR7XuE8B3Qus\nT7IuycnAFmDPmMcgSWLMrwCq6miSXwBuB04CdlbVg+McgySpZ9yngKiq24DbxrS5kZxKWgSOaziO\naziOazidHddYLwJLkl47/CgISeqo13UAJPlwkgeTfCfJvFfL5/v4iXYx+p5W/0K7MD2Kca1MsjfJ\ngfa4Yo4+H0hyf9/Pt5Jc3OZ9LsnjffPOGte4Wr+X+7a9p6++lMfrrCR/2J7vB5L8k755Iz1eC31c\nSZJT2v5Pt+Oxtm/eVa3+SJILTmQcxzGuf5XkoXZ89iV5e9+8OZ/TMY3ro0lm+rb/M33zptrzfiDJ\n1JjHdW3fmL6Z5Pm+eYt5vHYmOZzkG/PMT5Lr2rgfSHJ237zRHq+qet3+AH+b3nsF7gIm5+lzEvAo\n8A7gZOBrwJlt3i3Altb+VeDnRzSu/wRc2dpXAp9eoP9K4Ajwpjb9OeCSRTheA40L+PN56kt2vIC/\nBaxv7bcCTwHLR328Xu3fS1+ffw78amtvAb7Q2me2/qcA69p6ThrjuD7Q92/o52fH9WrP6ZjG9VHg\nv82x7Ergsfa4orVXjGtcx/T/RXo3pSzq8Wrr/lHgbOAb88y/CPg9IMB5wD2Ldbxe168Aqurhqlro\njWJzfvxEkgDnA7tbv13AxSMa2ua2vkHXewnwe1X14oi2P59hx/WKpT5eVfXNqjrQ2v8XOAws+EaX\n4zDIx5X0j3c3sKEdn83AzVX1UlU9Dky39Y1lXFV1Z9+/obvpvc9msZ3Ix7tcAOytqiNV9RywF9i0\nROP6CHDTiLb9qqrqD+j9wTefzcCN1XM3sDzJ6SzC8XpdB8CA5vv4iVOB56vq6DH1UVhVVU+19tPA\nqgX6b+F7//Fd017+XZvklDGP641J9ie5e/a0FK+h45XkHHp/1T3aVx7V8Rrk40pe6dOOxwv0js9i\nftTJsOveSu+vyFlzPafjHNc/bs/P7iSzbwZ9TRyvdqpsHXBHX3mxjtcg5hv7yI/X2G8DHVaSLwF/\nc45ZH6+qW8c9nlmvNq7+iaqqJPPeatWS/e/Se2/ErKvo/SI8md6tYB8Drh7juN5eVYeSvAO4I8nX\n6f2SO24jPl6fB6aq6jutfNzH6/tRkp8CJoEf6yt/z3NaVY/OvYaR+1/ATVX1UpKfpffq6fwxbXsQ\nW4DdVfVyX20pj9fYvOYDoKo+eIKrmO/jJ56l99JqWfsr7ns+luJ4x5XkmSSnV9VT7RfW4VdZ1aXA\nF6vq233rnv1r+KUkvwb8m3GOq6oOtcfHktwFvA/4LZb4eCX568Dv0gv/u/vWfdzHaw4LflxJX5+D\nSZYBb6H372mQZRdzXCT5IL1Q/bGqemm2Ps9zOopfaIN8vMuzfZOfpXfNZ3bZHz9m2btGMKaBxtVn\nC3BFf2ERj9cg5hv7yI9XF04BzfnxE9W7qnInvfPvAFPAqF5R7GnrG2S933Pusf0SnD3vfjEw590C\nizGuJCtmT6EkOQ14P/DQUh+v9tx9kd650d3HzBvl8Rrk40r6x3sJcEc7PnuALendJbQOWA98+QTG\nMtS4krwP+B/Ah6rqcF99zud0jOM6vW/yQ8DDrX07sLGNbwWwke9+Jbyo42pjeze9C6p/2FdbzOM1\niD3AZe1uoPOAF9ofOaM/XqO+wj3OH+Af0TsP9hLwDHB7q78VuK2v30XAN+kl+Mf76u+g9x90GvhN\n4JQRjetUYB9wAPgSsLLVJ4HP9vVbSy/V33DM8ncAX6f3i+zXgR8a17iAv9+2/bX2uPW1cLyAnwK+\nDdzf93PWYhyvuf690Dul9KHWfmPb/+l2PN7Rt+zH23KPABeO+N/7QuP6Uvt/MHt89iz0nI5pXP8R\neLBt/07g3X3L/rN2HKeBy8c5rjb974FPHbPcYh+vm+jdxfZter+/tgI/B/xcmx96X5z1aNv+ZN+y\nIz1evhNYkjqqC6eAJElzMAAkqaMMAEnqKANAkjrKAJCkjjIAJKmjDABJ6igDQJI66v8Db1mxargo\nR3IAAAAASUVORK5CYII=\n", 164 | "text/plain": [ 165 | "
" 166 | ] 167 | }, 168 | "metadata": {}, 169 | "output_type": "display_data" 170 | } 171 | ], 172 | "source": [ 173 | "plt.figure()\n", 174 | "plt.hist(labels, bins = 5, alpha = 0.7)\n", 175 | "plt.show()" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "# Volatility horizon" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": 98, 188 | "metadata": { 189 | "collapsed": true, 190 | "scrolled": true 191 | }, 192 | "outputs": [], 193 | "source": [ 194 | "labels = []\n", 195 | "for i in range(WINDOW, 10000, 1):\n", 196 | " window = tick_bars.iloc[i-WINDOW:i]\n", 197 | " now = tick_bars.close[i]\n", 198 | " future = tick_bars.close[i+HORIZON]\n", 199 | " ret = (future - now) / now\n", 200 | " \n", 201 | " window_abs_returns = np.abs(window.close.pct_change())\n", 202 | " Ti = np.std(window_abs_returns) + np.mean(window_abs_returns)\n", 203 | " \n", 204 | " if ret > Ti:\n", 205 | " labels.append(1)\n", 206 | " elif ret < -Ti:\n", 207 | " labels.append(-1)\n", 208 | " else:\n", 209 | " labels.append(0)" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": 99, 215 | "metadata": {}, 216 | "outputs": [ 217 | { 218 | "data": { 219 | "image/png": "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\nrkJggg==\n", 220 | "text/plain": [ 221 | "
" 222 | ] 223 | }, 224 | "metadata": {}, 225 | "output_type": "display_data" 226 | } 227 | ], 228 | "source": [ 229 | "plt.figure()\n", 230 | "plt.hist(labels, bins = 5, alpha = 0.7)\n", 231 | "plt.show()" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "# Meta labeling" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 167, 244 | "metadata": { 245 | "collapsed": true 246 | }, 247 | "outputs": [], 248 | "source": [ 249 | "def get_meta_barier(future_window, last_close, min_ret, tp, sl, vertical_zero = False):\n", 250 | " '''\n", 251 | " XXX\n", 252 | " '''\n", 253 | " if vertical_zero:\n", 254 | " min_ret_situation = [0, 0, 0]\n", 255 | " else:\n", 256 | " min_ret_situation = [0, 0]\n", 257 | " \n", 258 | " \n", 259 | " differences = np.array([(fc - last_close) / last_close for fc in future_window])\n", 260 | " \n", 261 | " # Are there gonna be fluctuations within min_ret???\n", 262 | " min_ret_ups = np.where((differences >= min_ret) == True)[0]\n", 263 | " min_ret_downs = np.where((differences < -min_ret) == True)[0]\n", 264 | " \n", 265 | " if (len(min_ret_ups) == 0) and (len(min_ret_downs) == 0):\n", 266 | " if vertical_zero:\n", 267 | " min_ret_situation[2] = 1\n", 268 | " else:\n", 269 | " if differences[-1] > 0:\n", 270 | " min_ret_situation[0] = 1\n", 271 | " else:\n", 272 | " min_ret_situation[1] = 1 \n", 273 | " else:\n", 274 | " if len(min_ret_ups) == 0: min_ret_ups = [np.inf]\n", 275 | " if len(min_ret_downs) == 0: min_ret_downs = [np.inf]\n", 276 | " if min_ret_ups[0] > min_ret_downs[0]:\n", 277 | " min_ret_situation[0] = 1\n", 278 | " else:\n", 279 | " min_ret_situation[1] = 1\n", 280 | " \n", 281 | " # Take profit and stop losses indices\n", 282 | " take_profit = np.where((differences >= tp) == True)[0]\n", 283 | " stop_loss = np.where((differences < sl) == True)[0]\n", 284 | " \n", 285 | " # Fluctuation directions coincide with take profit / stop loss actions?\n", 286 | " if min_ret_situation[0] == 1 and len(take_profit) != 0:\n", 287 | " take_action = 1\n", 288 | " elif min_ret_situation[1] == 1 and len(stop_loss) != 0:\n", 289 | " take_action = 1\n", 290 | " else:\n", 291 | " take_action = 0.\n", 292 | " \n", 293 | " return min_ret_situation, take_action" 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": 202, 299 | "metadata": { 300 | "collapsed": true 301 | }, 302 | "outputs": [], 303 | "source": [ 304 | "WINDOW = 180\n", 305 | "HORIZON = 60\n", 306 | "\n", 307 | "TIs = []\n", 308 | "# MIN_RET = 0.01\n", 309 | "TP = 0.015\n", 310 | "SL = -0.015\n", 311 | "\n", 312 | "X, Y, Y2 = [], [], []\n", 313 | "for i in range(WINDOW, 10000, 1):\n", 314 | " window = tick_bars.iloc[i-WINDOW:i]\n", 315 | " now = tick_bars.close[i]\n", 316 | " future_window = tick_bars.close[i:i+HORIZON]\n", 317 | " \n", 318 | " window_abs_returns = np.abs(window.close.pct_change())\n", 319 | " Ti = np.std(window_abs_returns) + np.mean(window_abs_returns)\n", 320 | " \n", 321 | " min_ret_situation, take_action = get_meta_barier(future_window, now, Ti, TP, SL, True)\n", 322 | " X.append(window.close)\n", 323 | " Y.append(min_ret_situation)\n", 324 | " Y2.append(take_action)\n", 325 | " TIs.append(Ti)" 326 | ] 327 | }, 328 | { 329 | "cell_type": "code", 330 | "execution_count": 203, 331 | "metadata": {}, 332 | "outputs": [ 333 | { 334 | "data": { 335 | "image/png": "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\nrkJggg==\n", 336 | "text/plain": [ 337 | "
" 338 | ] 339 | }, 340 | "metadata": {}, 341 | "output_type": "display_data" 342 | } 343 | ], 344 | "source": [ 345 | "plt.figure()\n", 346 | "plt.hist(Y2, bins = 5, alpha = 0.7)\n", 347 | "plt.show()" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 204, 353 | "metadata": {}, 354 | "outputs": [ 355 | { 356 | "data": { 357 | "image/png": "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\n", 358 | "text/plain": [ 359 | "
" 360 | ] 361 | }, 362 | "metadata": {}, 363 | "output_type": "display_data" 364 | } 365 | ], 366 | "source": [ 367 | "plt.figure()\n", 368 | "plt.hist([np.argmax(y) for y in Y], bins = 5, alpha = 0.7)\n", 369 | "plt.show()" 370 | ] 371 | }, 372 | { 373 | "cell_type": "code", 374 | "execution_count": null, 375 | "metadata": { 376 | "collapsed": true 377 | }, 378 | "outputs": [], 379 | "source": [] 380 | } 381 | ], 382 | "metadata": { 383 | "kernelspec": { 384 | "display_name": "Python 2", 385 | "language": "python", 386 | "name": "python2" 387 | }, 388 | "language_info": { 389 | "codemirror_mode": { 390 | "name": "ipython", 391 | "version": 2 392 | }, 393 | "file_extension": ".py", 394 | "mimetype": "text/x-python", 395 | "name": "python", 396 | "nbconvert_exporter": "python", 397 | "pygments_lexer": "ipython2", 398 | "version": "2.7.14" 399 | } 400 | }, 401 | "nbformat": 4, 402 | "nbformat_minor": 2 403 | } 404 | -------------------------------------------------------------------------------- /bars-labels-diff/bars.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import datetime 4 | 5 | class BarSeries(object): 6 | ''' 7 | Base class for resampling ticks dataframe into OHLC(V) 8 | using different schemes. This particular class implements 9 | standard time bars scheme. 10 | See: https://www.wiley.com/en-it/Advances+in+Financial+Machine+Learning-p-9781119482086 11 | ''' 12 | 13 | def __init__(self, df, datetimecolumn = 'DateTime'): 14 | self.df = df 15 | self.datetimecolumn = datetimecolumn 16 | 17 | def process_column(self, column_name, frequency): 18 | return self.df[column_name].resample(frequency, label='right').ohlc() 19 | 20 | def process_volume(self, column_name, frequency): 21 | return self.df[column_name].resample(frequency, label='right').sum() 22 | 23 | def process_ticks(self, price_column = 'Price', volume_column = 'Size', frequency = '15Min'): 24 | price_df = self.process_column(price_column, frequency) 25 | volume_df = self.process_volume(volume_column, frequency) 26 | price_df['volume'] = volume_df 27 | return price_df 28 | 29 | 30 | class TickBarSeries(BarSeries): 31 | ''' 32 | Class for generating tick bars based on bid-ask-size dataframe 33 | ''' 34 | def __init__(self, df, datetimecolumn = 'DateTime', volume_column = 'Size'): 35 | self.volume_column = volume_column 36 | super(TickBarSeries, self).__init__(df, datetimecolumn) 37 | 38 | def process_column(self, column_name, frequency): 39 | res = [] 40 | for i in range(frequency, len(self.df), frequency): 41 | sample = self.df.iloc[i-frequency:i] 42 | v = sample[self.volume_column].values.sum() 43 | o = sample[column_name].values.tolist()[0] 44 | h = sample[column_name].values.max() 45 | l = sample[column_name].values.min() 46 | c = sample[column_name].values.tolist()[-1] 47 | d = sample.index.values[-1] 48 | 49 | res.append({ 50 | self.datetimecolumn: d, 51 | 'open': o, 52 | 'high': h, 53 | 'low': l, 54 | 'close': c, 55 | 'volume': v 56 | }) 57 | 58 | res = pd.DataFrame(res).set_index(self.datetimecolumn) 59 | return res 60 | 61 | 62 | def process_ticks(self, price_column = 'Price', volume_column = 'Size', frequency = '15Min'): 63 | price_df = self.process_column(price_column, frequency) 64 | return price_df 65 | 66 | 67 | class VolumeBarSeries(BarSeries): 68 | ''' 69 | Class for generating volume bars based on bid-ask-size dataframe 70 | ''' 71 | def __init__(self, df, datetimecolumn = 'DateTime', volume_column = 'Size'): 72 | self.volume_column = volume_column 73 | super(VolumeBarSeries, self).__init__(df, datetimecolumn) 74 | 75 | def process_column(self, column_name, frequency): 76 | res = [] 77 | buf = [] 78 | start_index = 0. 79 | volume_buf = 0. 80 | for i in range(len(self.df[column_name])): 81 | 82 | pi = self.df[column_name].iloc[i] 83 | vi = self.df[self.volume_column].iloc[i] 84 | di = self.df.index.values[i] 85 | 86 | buf.append(pi) 87 | volume_buf += vi 88 | 89 | if volume_buf >= frequency: 90 | 91 | o = buf[0] 92 | h = np.max(buf) 93 | l = np.min(buf) 94 | c = buf[-1] 95 | 96 | res.append({ 97 | self.datetimecolumn: di, 98 | 'open': o, 99 | 'high': h, 100 | 'low': l, 101 | 'close': c, 102 | 'volume': volume_buf 103 | }) 104 | 105 | buf, volume_buf = [], 0. 106 | 107 | res = pd.DataFrame(res).set_index(self.datetimecolumn) 108 | return res 109 | 110 | def process_ticks(self, price_column = 'Price', volume_column = 'Size', frequency = '15Min'): 111 | price_df = self.process_column(price_column, frequency) 112 | return price_df 113 | 114 | 115 | 116 | class DollarBarSeries(BarSeries): 117 | ''' 118 | Class for generating "dollar" bars based on bid-ask-size dataframe 119 | ''' 120 | def __init__(self, df, datetimecolumn = 'DateTime', volume_column = 'Size'): 121 | self.volume_column = volume_column 122 | super(DollarBarSeries, self).__init__(df, datetimecolumn) 123 | 124 | def process_column(self, column_name, frequency): 125 | res = [] 126 | buf, vbuf = [], [] 127 | start_index = 0. 128 | dollar_buf = 0. 129 | for i in range(len(self.df[column_name])): 130 | 131 | pi = self.df[column_name].iloc[i] 132 | vi = self.df[self.volume_column].iloc[i] 133 | di = self.df.index.values[i] 134 | 135 | dvi = pi * vi 136 | buf.append(pi) 137 | vbuf.append(vi) 138 | dollar_buf += dvi 139 | 140 | if dollar_buf >= frequency: 141 | 142 | o = buf[0] 143 | h = np.max(buf) 144 | l = np.min(buf) 145 | c = buf[-1] 146 | v = np.sum(vbuf) 147 | 148 | res.append({ 149 | self.datetimecolumn: di, 150 | 'open': o, 151 | 'high': h, 152 | 'low': l, 153 | 'close': c, 154 | 'volume': v, 155 | 'dollar': dollar_buf 156 | }) 157 | 158 | buf, vbuf, dollar_buf = [], [], 0. 159 | 160 | res = pd.DataFrame(res).set_index(self.datetimecolumn) 161 | return res 162 | 163 | def process_ticks(self, price_column = 'Price', volume_column = 'Size', frequency = '15Min'): 164 | price_df = self.process_column(price_column, frequency) 165 | return price_df 166 | 167 | 168 | class ImbalanceTickBarSeries(BarSeries): 169 | ''' 170 | Class for generating imbalance tick bars based on bid-ask-size dataframe 171 | ''' 172 | def __init__(self, df, datetimecolumn = 'DateTime', volume_column = 'Size'): 173 | self.volume_column = volume_column 174 | super(ImbalanceTickBarSeries, self).__init__(df, datetimecolumn) 175 | 176 | def get_bt(self, data): 177 | s = np.sign(np.diff(data)) 178 | for i in range(1, len(s)): 179 | if s[i] == 0: 180 | s[i] = s[i-1] 181 | return s 182 | 183 | def get_theta_t(self, bt): 184 | return np.sum(bt) 185 | 186 | def ewma(self, data, window): 187 | 188 | alpha = 2 /(window + 1.0) 189 | alpha_rev = 1-alpha 190 | 191 | scale = 1/alpha_rev 192 | n = data.shape[0] 193 | 194 | r = np.arange(n) 195 | scale_arr = scale**r 196 | offset = data[0]*alpha_rev**(r+1) 197 | pw0 = alpha*alpha_rev**(n-1) 198 | 199 | mult = data*pw0*scale_arr 200 | cumsums = mult.cumsum() 201 | out = offset + cumsums*scale_arr[::-1] 202 | return out 203 | 204 | def process_column(self, column_name, initital_T = 100, min_bar = 10, max_bar = 1000): 205 | init_bar = self.df[:initital_T][column_name].values.tolist() 206 | 207 | ts = [initital_T] 208 | bts = [bti for bti in self.get_bt(init_bar)] 209 | res = [] 210 | 211 | buf_bar, vbuf, T = [], [], 0. 212 | for i in range(initital_T, len(self.df)): 213 | 214 | 215 | di = self.df.index.values[i] 216 | 217 | buf_bar.append(self.df[column_name].iloc[i]) 218 | bt = self.get_bt(buf_bar) 219 | theta_t = self.get_theta_t(bt) 220 | 221 | try: 222 | e_t = self.ewma(np.array(ts), initital_T / 10)[-1] 223 | e_bt = self.ewma(np.array(bts), initital_T)[-1] 224 | except: 225 | e_t = np.mean(ts) 226 | e_bt = np.mean(bts) 227 | finally: 228 | if np.isnan(e_bt): 229 | e_bt = np.mean(bts[int(len(bts) * 0.9):]) 230 | if np.isnan(e_t): 231 | e_t = np.mean(ts[int(len(ts) * 0.9):]) 232 | 233 | 234 | condition = np.abs(theta_t) >= e_t * np.abs(e_bt) 235 | 236 | 237 | if (condition or len(buf_bar) > max_bar) and len(buf_bar) >= min_bar: 238 | 239 | o = buf_bar[0] 240 | h = np.max(buf_bar) 241 | l = np.min(buf_bar) 242 | c = buf_bar[-1] 243 | v = np.sum(vbuf) 244 | 245 | res.append({ 246 | self.datetimecolumn: di, 247 | 'open': o, 248 | 'high': h, 249 | 'low': l, 250 | 'close': c, 251 | 'volume': v 252 | }) 253 | 254 | ts.append(T) 255 | for b in bt: 256 | bts.append(b) 257 | 258 | buf_bar = [] 259 | vbuf = [] 260 | T = 0. 261 | else: 262 | vbuf.append(self.df[self.volume_column].iloc[i]) 263 | T += 1 264 | 265 | res = pd.DataFrame(res).set_index(self.datetimecolumn) 266 | return res 267 | 268 | def process_ticks(self, price_column = 'Price', volume_column = 'Size', init = 100, min_bar = 10, max_bar = 1000): 269 | price_df = self.process_column(price_column, init, min_bar, max_bar) 270 | return price_df -------------------------------------------------------------------------------- /feature_importance/test.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /feature_importance/utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | def getDailyVol(close, span0=100): 5 | # daily vol, reindexed to close 6 | df0=close.index.searchsorted(close.index-pd.Timedelta(days=1)) 7 | df0=df0[df0>0] 8 | df0=pd.Series(close.index[df0-1], index=close.index[close.shape[0]-df0.shape[0]:]) 9 | df0=close.loc[df0.index]/close.loc[df0.values].values-1 # daily returns 10 | df0=df0.ewm(span=span0).std() 11 | return df0 12 | 13 | def get_meta_barier(future_window, last_close, min_ret, tp, sl, vertical_zero = True): 14 | ''' 15 | From https://github.com/Rachnog/Advanced-Deep-Trading/blob/master/bars-labels-diff/Labeling.ipynb 16 | ''' 17 | if vertical_zero: 18 | min_ret_situation = [0, 0, 0] 19 | else: 20 | min_ret_situation = [0, 0] 21 | 22 | 23 | differences = np.array([(fc - last_close) / last_close for fc in future_window]) 24 | 25 | # Are there gonna be fluctuations within min_ret??? 26 | min_ret_ups = np.where((differences >= min_ret) == True)[0] 27 | min_ret_downs = np.where((differences < -min_ret) == True)[0] 28 | 29 | if (len(min_ret_ups) == 0) and (len(min_ret_downs) == 0): 30 | if vertical_zero: 31 | min_ret_situation[2] = 1 32 | else: 33 | if differences[-1] > 0: 34 | min_ret_situation[0] = 1 35 | else: 36 | min_ret_situation[1] = 1 37 | else: 38 | if len(min_ret_ups) == 0: min_ret_ups = [np.inf] 39 | if len(min_ret_downs) == 0: min_ret_downs = [np.inf] 40 | # if min_ret_ups[0] > min_ret_downs[0]: 41 | 42 | if min_ret_ups[0] < min_ret_downs[0]: 43 | min_ret_situation[0] = 1 44 | else: 45 | min_ret_situation[1] = 1 46 | 47 | # Take profit and stop losses indices 48 | take_profit = np.where((differences >= tp) == True)[0] 49 | stop_loss = np.where((differences < sl) == True)[0] 50 | 51 | # Fluctuation directions coincide with take profit / stop loss actions? 52 | if min_ret_situation[0] == 1 and len(take_profit) != 0: 53 | take_action = 1 54 | elif min_ret_situation[1] == 1 and len(stop_loss) != 0: 55 | take_action = 1 56 | else: 57 | take_action = 0. 58 | 59 | return min_ret_situation, take_action, [take_profit, stop_loss] -------------------------------------------------------------------------------- /proba_backtest/readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /proba_backtest/utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | def getDailyVol(close, span0=100): 5 | # daily vol, reindexed to close 6 | df0=close.index.searchsorted(close.index-pd.Timedelta(days=1)) 7 | df0=df0[df0>0] 8 | df0=pd.Series(close.index[df0-1], index=close.index[close.shape[0]-df0.shape[0]:]) 9 | df0=close.loc[df0.index]/close.loc[df0.values].values-1 # daily returns 10 | df0=df0.ewm(span=span0).std() 11 | return df0 12 | 13 | def get_meta_barier(future_window, last_close, min_ret, tp, sl, vertical_zero = True): 14 | ''' 15 | From https://github.com/Rachnog/Advanced-Deep-Trading/blob/master/bars-labels-diff/Labeling.ipynb 16 | ''' 17 | if vertical_zero: 18 | min_ret_situation = [0, 0, 0] 19 | else: 20 | min_ret_situation = [0, 0] 21 | 22 | 23 | differences = np.array([(fc - last_close) / last_close for fc in future_window]) 24 | 25 | # Are there gonna be fluctuations within min_ret??? 26 | min_ret_ups = np.where((differences >= min_ret) == True)[0] 27 | min_ret_downs = np.where((differences < -min_ret) == True)[0] 28 | 29 | if (len(min_ret_ups) == 0) and (len(min_ret_downs) == 0): 30 | if vertical_zero: 31 | min_ret_situation[2] = 1 32 | else: 33 | if differences[-1] > 0: 34 | min_ret_situation[0] = 1 35 | else: 36 | min_ret_situation[1] = 1 37 | else: 38 | if len(min_ret_ups) == 0: min_ret_ups = [np.inf] 39 | if len(min_ret_downs) == 0: min_ret_downs = [np.inf] 40 | 41 | if min_ret_ups[0] < min_ret_downs[0]: 42 | min_ret_situation[0] = 1 43 | else: 44 | min_ret_situation[1] = 1 45 | 46 | # Take profit and stop losses indices 47 | take_profit = np.where((differences >= tp) == True)[0] 48 | stop_loss = np.where((differences < sl) == True)[0] 49 | 50 | # Fluctuation directions coincide with take profit / stop loss actions? 51 | if min_ret_situation[0] == 1 and len(take_profit) != 0: 52 | take_action = 1 53 | elif min_ret_situation[1] == 1 and len(stop_loss) != 0: 54 | take_action = 1 55 | else: 56 | take_action = 0. 57 | 58 | return min_ret_situation, take_action, [take_profit, stop_loss] --------------------------------------------------------------------------------