├── Guided Tour of Machine Learning in Finance ├── Coursera MTNWSAWJRAPB.pdf ├── linear_regress_m1_ex2_v4-newV.ipynb └── Computing Gradients using TensorFlow.ipynb ├── README.md └── Reinforcement Learning in Finance └── discrete_black_scholes_m3_ex1_v3.ipynb /Guided Tour of Machine Learning in Finance/Coursera MTNWSAWJRAPB.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushMandhyan/ML-RL-for-Finance/HEAD/Guided Tour of Machine Learning in Finance/Coursera MTNWSAWJRAPB.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ML-RL-for-Finance 2 | Code (Jupyter Notebooks) for Coursera - [Machine Learning and Reinforcement Learning in Finance Specialization](https://www.coursera.org/specializations/machine-learning-reinforcement-finance) 3 | 4 | This repository contains all the code I write as part of this Specialization. 5 | 6 | ## Guided Tour of Machine Learning in Finance 7 | 1. [Euclidean Distance Calculation](Guided%20Tour%20of%20Machine%20Learning%20in%20Finance/Euclidian_Distance_m1_ex1_v4-newV.ipynb) 8 | 2. [Linear Regression](Guided%20Tour%20of%20Machine%20Learning%20in%20Finance/linear_regress_m1_ex2_v4-newV.ipynb) 9 | 3. [Tobit Regression](Guided%20Tour%20of%20Machine%20Learning%20in%20Finance/Tobit_regression_m1_ex3_v4-newV.ipynb) 10 | 4. [Bank defaults prediction using FDIC dataset](Guided%20Tour%20of%20Machine%20Learning%20in%20Finance/Bank_failure_m1_ex4_v4-newV.ipynb) 11 | 12 | ## Fundamentals of Machine Learning in Finance 13 | 1. [Random Forests And Decision Trees](Fundamentals%20of%20Machine%20Learning%20in%20Finance/Bank_failure_rand_forests_m2_ex2.ipynb) 14 | 2. [Eigen Portfolio construction via PCA](Fundamentals%20of%20Machine%20Learning%20in%20Finance/pca_eigen_portfolios_m2_ex3.ipynb) 15 | 3. [Data Visualization with t-SNE](Fundamentals%20of%20Machine%20Learning%20in%20Finance/DJI_tSNE_m2_ex4_corrected.ipynb) 16 | 4. [Absorption Ratio via PCA](Fundamentals%20of%20Machine%20Learning%20in%20Finance/absorp_ratio_m2_ex5.ipynb) 17 | 18 | ## Reinforcement Learning in Finance 19 | 1. [Discrete-time Black Scholes model](Reinforcement%20Learning%20in%20Finance/discrete_black_scholes_m3_ex1_v3.ipynb) 20 | 2. [QLBS Model Implementation](Reinforcement%20Learning%20in%20Finance/dp_qlbs_oneset_m3_ex2_v3.ipynb) 21 | 3. [Fitted Q-Iteration](Reinforcement%20Learning%20in%20Finance/dp_qlbs_oneset_m3_ex3_v4.ipynb) 22 | 4. IRL Market Model Calibration 23 | 24 | ## Overview of Advanced Methods of Reinforcement Learning in Finance 25 | -------------------------------------------------------------------------------- /Guided Tour of Machine Learning in Finance/linear_regress_m1_ex2_v4-newV.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Linear Regression\n", 8 | "\n", 9 | "Welcome to your second assignment. This exercise gives you a brief introduction to linear regression. The exercise is to be implemented in Python. Even if you've used Python before, this will help familiarize you with functions we'll need. \n", 10 | "\n", 11 | "**Instructions:**\n", 12 | "- You will be using Python 3.\n", 13 | "- Avoid using for-loops and while-loops, unless you are explicitly told to do so.\n", 14 | "- Do not modify the (# GRADED FUNCTION [function name]) comment in some cells. Your work would not be graded if you change this. Each cell containing that comment should only contain one function.\n", 15 | "- After coding your function, run the cell right below it to check if your result is correct.\n", 16 | "- The token generated by Coursera (COURSERA_TOKEN) expires every 30 minutes. It is advisable to always work with the most recent generated token so as to avoid any submission related errors. If you receive such error messages, rerun the cells containing your code and the GRADED FUNCTION in the same order. \n", 17 | "\n", 18 | "\n", 19 | "**After this assignment you will:**\n", 20 | "- Be able to implement linear regression model using statsmodels, scikit-learn, and tensorflow\n", 21 | "- Work with simulated non-linear dataset\n", 22 | "- Compare model performance (quality of fit) of both models\n", 23 | "\n", 24 | "- - The blue button \"Submit Assignment\" does not work. After running all the cells, please go directly to Assignment-> My submission to see your results.\n", 25 | "\n", 26 | "Let's get started!" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "## About iPython Notebooks ##\n", 34 | "\n", 35 | "iPython Notebooks are interactive coding environments embedded in a webpage. You will be using iPython notebooks in this class. You only need to write code between the ### START CODE HERE ### and ### END CODE HERE ### comments. After writing your code, you can run the cell by either pressing \"SHIFT\"+\"ENTER\" or by clicking on \"Run Cell\" (denoted by a play symbol) in the upper bar of the notebook. \n", 36 | "\n", 37 | "We will often specify \"(≈ X lines of code)\" in the comments to tell you about how much code you need to write. It is just a rough estimate, so don't feel bad if your code is longer or shorter." 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 1, 43 | "metadata": { 44 | "collapsed": true 45 | }, 46 | "outputs": [], 47 | "source": [ 48 | "import os\n", 49 | "import numpy as np\n", 50 | "\n", 51 | "import sys\n", 52 | "sys.path.append(\"..\")\n", 53 | "import grading\n", 54 | "\n", 55 | "try:\n", 56 | " import matplotlib.pyplot as plt\n", 57 | " %matplotlib inline\n", 58 | "except: pass\n", 59 | "\n", 60 | "import pandas as pd\n", 61 | "\n", 62 | "import tensorflow as tf\n", 63 | "from tensorflow.python.layers import core as core_layers\n", 64 | "try:\n", 65 | " from mpl_toolkits.mplot3d import Axes3D\n", 66 | "except: pass" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 2, 72 | "metadata": { 73 | "collapsed": true 74 | }, 75 | "outputs": [], 76 | "source": [ 77 | "### ONLY FOR GRADING. DO NOT EDIT ###\n", 78 | "submissions=dict()\n", 79 | "assignment_key=\"QNZTAPW2Eeeg_w5MCivhhg\" \n", 80 | "all_parts=[\"dtA5d\", \"2inmf\", \"FCpek\",\"78aDd\",\"qlQVj\"]\n", 81 | "### ONLY FOR GRADING. DO NOT EDIT ###" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 3, 87 | "metadata": { 88 | "collapsed": true 89 | }, 90 | "outputs": [], 91 | "source": [ 92 | "COURSERA_TOKEN = \"2xUa6cwEA4CwGozr\"# the key provided to the Student under his/her email on submission page\n", 93 | "COURSERA_EMAIL = \"aayushmandhyan@hotmail.co.uk\"# the email" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 4, 99 | "metadata": { 100 | "collapsed": true 101 | }, 102 | "outputs": [], 103 | "source": [ 104 | "def reset_graph(seed=42):\n", 105 | " \"\"\"\n", 106 | " Utility function to reset current tensorflow computation graph\n", 107 | " and set the random seed \n", 108 | " \"\"\"\n", 109 | " # to make results reproducible across runs\n", 110 | " tf.reset_default_graph()\n", 111 | " tf.set_random_seed(seed)\n", 112 | " np.random.seed(seed)" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": { 118 | "collapsed": true 119 | }, 120 | "source": [ 121 | "## We use artificial data for the following two specifications of regression:\n", 122 | "\n", 123 | "### Linear Regression\n", 124 | "\n", 125 | "$ y(x) = a + b_1 \\cdot X_1 + b_2 \\cdot X_2 + b_3 \\cdot X_3 + \\sigma \\cdot \\varepsilon $ \n", 126 | "\n", 127 | "where $ \\varepsilon \\sim N(0, 1) $ is a Gaussian noise, and $ \\sigma $ is its volatility, \n", 128 | "with the following choice of parameters:\n", 129 | "\n", 130 | "$ a = 1.0 $\n", 131 | "\n", 132 | "$ b_1, b_2, b_3 = (0.5, 0.2, 0.1) $\n", 133 | "\n", 134 | "$ \\sigma = 0.1 $\n", 135 | "\n", 136 | "$ X_1, X_2, X_3 $ will be uniformally distributed in $ [-1,1] $\n", 137 | "\n", 138 | "### Non-Linear Regression\n", 139 | "\n", 140 | "$ y(x) = a + w_{00} \\cdot X_1 + w_{01} \\cdot X_2 + w_{02} \\cdot X_3 + + w_{10} \\cdot X_1^2 \n", 141 | "+ w_{11} \\cdot X_2^2 + w_{12} \\cdot X_3^2 + \\sigma \\cdot \\varepsilon $ \n", 142 | "\n", 143 | "where\n", 144 | "\n", 145 | "$ w = [[1.0, 0.5, 0.2],[0.5, 0.3, 0.15]] $\n", 146 | "\n", 147 | "and the rest of parameters is as above, with the same values of $ X_i $" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": { 153 | "collapsed": true 154 | }, 155 | "source": [ 156 | "### Generate Data" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 5, 162 | "metadata": {}, 163 | "outputs": [ 164 | { 165 | "data": { 166 | "text/plain": [ 167 | "((7500, 3), (7500, 1))" 168 | ] 169 | }, 170 | "execution_count": 5, 171 | "metadata": {}, 172 | "output_type": "execute_result" 173 | } 174 | ], 175 | "source": [ 176 | "def generate_data(n_points=10000, n_features=3, use_nonlinear=True, \n", 177 | " noise_std=0.1, train_test_split = 4):\n", 178 | " \"\"\"\n", 179 | " Arguments:\n", 180 | " n_points - number of data points to generate\n", 181 | " n_features - a positive integer - number of features\n", 182 | " use_nonlinear - if True, generate non-linear data\n", 183 | " train_test_split - an integer - what portion of data to use for testing\n", 184 | " \n", 185 | " Return:\n", 186 | " X_train, Y_train, X_test, Y_test, n_train, n_features\n", 187 | " \"\"\"\n", 188 | " \n", 189 | " # Linear data or non-linear data?\n", 190 | " if use_nonlinear:\n", 191 | " weights = np.array([[1.0, 0.5, 0.2],[0.5, 0.3, 0.15]])\n", 192 | " else:\n", 193 | " weights = np.array([1.0, 0.5, 0.2])\n", 194 | " \n", 195 | "\n", 196 | " \n", 197 | " bias = np.ones(n_points).reshape((-1,1))\n", 198 | " low = - np.ones((n_points,n_features),'float')\n", 199 | " high = np.ones((n_points,n_features),'float')\n", 200 | " \n", 201 | " np.random.seed(42)\n", 202 | " X = np.random.uniform(low=low, high=high)\n", 203 | " \n", 204 | " np.random.seed(42)\n", 205 | " noise = np.random.normal(size=(n_points, 1))\n", 206 | " noise_std = 0.1\n", 207 | " \n", 208 | " if use_nonlinear:\n", 209 | " Y = (weights[0,0] * bias + np.dot(X, weights[0, :]).reshape((-1,1)) + \n", 210 | " np.dot(X*X, weights[1, :]).reshape([-1,1]) +\n", 211 | " noise_std * noise)\n", 212 | " else:\n", 213 | " Y = (weights[0] * bias + np.dot(X, weights[:]).reshape((-1,1)) + \n", 214 | " noise_std * noise)\n", 215 | " \n", 216 | " n_test = int(n_points/train_test_split)\n", 217 | " n_train = n_points - n_test\n", 218 | " \n", 219 | " X_train = X[:n_train,:]\n", 220 | " Y_train = Y[:n_train].reshape((-1,1))\n", 221 | "\n", 222 | " X_test = X[n_train:,:]\n", 223 | " Y_test = Y[n_train:].reshape((-1,1))\n", 224 | " \n", 225 | " return X_train, Y_train, X_test, Y_test, n_train, n_features\n", 226 | "\n", 227 | "X_train, Y_train, X_test, Y_test, n_train, n_features = generate_data(use_nonlinear=False)\n", 228 | "X_train.shape, Y_train.shape" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "### Linear Regression with Numpy" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": 6, 241 | "metadata": { 242 | "collapsed": true 243 | }, 244 | "outputs": [], 245 | "source": [ 246 | "# GRADED FUNCTION: numpy_lin_regress\n", 247 | "def numpy_lin_regress(X_train, Y_train):\n", 248 | " \"\"\"\n", 249 | " numpy_lin_regress - Implements linear regression model using numpy module\n", 250 | " Arguments:\n", 251 | " X_train - np.array of size (n by k) where n is number of observations \n", 252 | " of independent variables and k is number of variables\n", 253 | " Y_train - np.array of size (n by 1) where n is the number of observations of dependend variable\n", 254 | " \n", 255 | " Return:\n", 256 | " np.array of size (k+1 by 1) of regression coefficients\n", 257 | " \"\"\"\n", 258 | " ### START CODE HERE ### (≈ 3 lines of code)\n", 259 | " \n", 260 | " # number of features\n", 261 | " no_of_features = X_train.shape[1]\n", 262 | " # add the column of ones\n", 263 | " X = np.hstack((np.ones(len(X_train)).reshape((-1,1)), X_train))\n", 264 | " \n", 265 | " theta_numpy = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), Y_train)\n", 266 | " \n", 267 | " # default answer, replace this\n", 268 | " # theta_numpy = np.array([0.] * (ndim + 1)) \n", 269 | " ### END CODE HERE ###\n", 270 | " return theta_numpy" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": 7, 276 | "metadata": {}, 277 | "outputs": [ 278 | { 279 | "name": "stdout", 280 | "output_type": "stream", 281 | "text": [ 282 | "Submission successful, please check on the coursera grader page for the status\n" 283 | ] 284 | }, 285 | { 286 | "data": { 287 | "text/plain": [ 288 | "array([ 0.99946227, 0.99579039, 0.499198 , 0.20019798])" 289 | ] 290 | }, 291 | "execution_count": 7, 292 | "metadata": {}, 293 | "output_type": "execute_result" 294 | } 295 | ], 296 | "source": [ 297 | "### GRADED PART (DO NOT EDIT) ###\n", 298 | "theta_numpy = numpy_lin_regress(X_train, Y_train)\n", 299 | "part_1 = list(theta_numpy.squeeze())\n", 300 | "try:\n", 301 | " part1 = \" \".join(map(repr, part_1))\n", 302 | "except TypeError:\n", 303 | " part1 = repr(part_1)\n", 304 | "submissions[all_parts[0]]=part1\n", 305 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:1],all_parts,submissions)\n", 306 | "theta_numpy.squeeze()\n", 307 | "### GRADED PART (DO NOT EDIT) ###" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "### Linear Regression with Sklearn" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 8, 320 | "metadata": { 321 | "collapsed": true 322 | }, 323 | "outputs": [], 324 | "source": [ 325 | "# GRADED FUNCTION: sklearn_lin_regress\n", 326 | "def sklearn_lin_regress(X_train, Y_train):\n", 327 | " \"\"\"\n", 328 | " Arguments:\n", 329 | " X_train - np.array of size (n by k) where n is number of observations \n", 330 | " of independent variables and k is number of variables\n", 331 | " Y_train - np.array of size (n by 1) where n is the number of observations of dependend variable\n", 332 | " \n", 333 | " Return:\n", 334 | " np.array of size (k+1 by 1) of regression coefficients\n", 335 | " \"\"\" \n", 336 | " from sklearn.linear_model import LinearRegression\n", 337 | " lin_reg = LinearRegression()\n", 338 | " ### START CODE HERE ### (≈ 3 lines of code)\n", 339 | " # use lin_reg to fit training data\n", 340 | " lin_reg.fit(X_train, Y_train)\n", 341 | " theta_sklearn = []\n", 342 | " theta_sklearn = np.r_[lin_reg.intercept_.reshape(-1,1), lin_reg.coef_.T]\n", 343 | " ### END CODE HERE ###\n", 344 | " return theta_sklearn" 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "execution_count": 9, 350 | "metadata": {}, 351 | "outputs": [ 352 | { 353 | "name": "stdout", 354 | "output_type": "stream", 355 | "text": [ 356 | "Submission successful, please check on the coursera grader page for the status\n" 357 | ] 358 | }, 359 | { 360 | "data": { 361 | "text/plain": [ 362 | "array([ 0.99946227, 0.99579039, 0.499198 , 0.20019798])" 363 | ] 364 | }, 365 | "execution_count": 9, 366 | "metadata": {}, 367 | "output_type": "execute_result" 368 | } 369 | ], 370 | "source": [ 371 | "### GRADED PART (DO NOT EDIT) ###\n", 372 | "theta_sklearn = sklearn_lin_regress(X_train, Y_train)\n", 373 | "part_2 = list(theta_sklearn.squeeze())\n", 374 | "try:\n", 375 | " part2 = \" \".join(map(repr, part_2))\n", 376 | "except TypeError:\n", 377 | " part2 = repr(part_2)\n", 378 | "submissions[all_parts[1]]=part2\n", 379 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:2],all_parts,submissions)\n", 380 | "theta_sklearn.squeeze()\n", 381 | "### GRADED PART (DO NOT EDIT) ###" 382 | ] 383 | }, 384 | { 385 | "cell_type": "markdown", 386 | "metadata": {}, 387 | "source": [ 388 | "### Linear Regression with Tensorflow" 389 | ] 390 | }, 391 | { 392 | "cell_type": "code", 393 | "execution_count": 10, 394 | "metadata": { 395 | "collapsed": true 396 | }, 397 | "outputs": [], 398 | "source": [ 399 | "# GRADED FUNCTION: tf_lin_regress\n", 400 | "def tf_lin_regress(X_train, Y_train):\n", 401 | " \"\"\"\n", 402 | " Arguments:\n", 403 | " X_train - np.array of size (n by k) where n is number of observations \n", 404 | " of independent variables and k is number of variables\n", 405 | " Y_train - np.array of size (n by 1) where n is the number of observations of dependend variable\n", 406 | " \n", 407 | " Return:\n", 408 | " np.array of size (k+1 by 1) of regression coefficients\n", 409 | " \"\"\"\n", 410 | " ### START CODE HERE ### (≈ 7-8 lines of code)\n", 411 | " # add the column of ones\n", 412 | " X_np = np.hstack((np.ones(len(X_train)).reshape(-1,1), X_train))\n", 413 | " X = tf.constant(X_np, dtype=tf.float32, name='X')\n", 414 | " Y = tf.constant(Y_train, dtype=tf.float32, name='Y')\n", 415 | " XT = tf.transpose(X)\n", 416 | " # define theta for later evaluation\n", 417 | " theta = tf.matmul(tf.matmul(tf.matrix_inverse(tf.matmul(XT, X)), XT), Y)\n", 418 | " ### END CODE HERE ###\n", 419 | " with tf.Session() as sess:\n", 420 | " theta_value = theta.eval()\n", 421 | " return theta_value" 422 | ] 423 | }, 424 | { 425 | "cell_type": "code", 426 | "execution_count": 11, 427 | "metadata": {}, 428 | "outputs": [ 429 | { 430 | "name": "stdout", 431 | "output_type": "stream", 432 | "text": [ 433 | "Submission successful, please check on the coursera grader page for the status\n" 434 | ] 435 | }, 436 | { 437 | "data": { 438 | "text/plain": [ 439 | "array([ 0.99946201, 0.99579054, 0.49919799, 0.20019798], dtype=float32)" 440 | ] 441 | }, 442 | "execution_count": 11, 443 | "metadata": {}, 444 | "output_type": "execute_result" 445 | } 446 | ], 447 | "source": [ 448 | "### GRADED PART (DO NOT EDIT) ###\n", 449 | "theta_tf = tf_lin_regress(X_train, Y_train)\n", 450 | "part_3 = list(theta_tf.squeeze())\n", 451 | "try:\n", 452 | " part3 = \" \".join(map(repr, part_3))\n", 453 | "except TypeError:\n", 454 | " part3 = repr(part_3)\n", 455 | "submissions[all_parts[2]]=part3\n", 456 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:3],all_parts,submissions)\n", 457 | "theta_tf.squeeze()\n", 458 | "### GRADED PART (DO NOT EDIT) ###" 459 | ] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "execution_count": 14, 464 | "metadata": { 465 | "collapsed": true 466 | }, 467 | "outputs": [], 468 | "source": [ 469 | "class LinRegressNormalEq:\n", 470 | " \"\"\"\n", 471 | " class LinRegressNormalEq - implements normal equation, maximum likelihood estimator (MLE) solution\n", 472 | " \"\"\"\n", 473 | " def __init__(self, n_features, learning_rate=0.05, L=0):\n", 474 | " import math as m\n", 475 | " # input placeholders\n", 476 | " self.X = tf.placeholder(tf.float32, [None, n_features], name=\"X\") \n", 477 | " self.Y = tf.placeholder(tf.float32, [None, 1], name=\"Y\")\n", 478 | " \n", 479 | " # regression parameters for the analytical solution using the Normal equation\n", 480 | " self.theta_in = tf.placeholder(tf.float32, [n_features+1,None])\n", 481 | "\n", 482 | " # Augmented data matrix is obtained by adding a column of ones to the data matrix\n", 483 | " data_plus_bias = tf.concat([tf.ones([tf.shape(self.X)[0], 1]), self.X], axis=1)\n", 484 | " \n", 485 | " XT = tf.transpose(data_plus_bias)\n", 486 | " \n", 487 | " #############################################\n", 488 | " # The normal equation for Linear Regression\n", 489 | " \n", 490 | " self.theta = tf.matmul(tf.matmul(\n", 491 | " tf.matrix_inverse(tf.matmul(XT, data_plus_bias)), XT), self.Y)\n", 492 | " \n", 493 | " # mean square error in terms of theta = theta_in\n", 494 | " self.lr_mse = tf.reduce_mean(tf.square(\n", 495 | " tf.matmul(data_plus_bias, self.theta_in) - self.Y))\n", 496 | " \n", 497 | " #############################################\n", 498 | " # Estimate the model using the Maximum Likelihood Estimation (MLE)\n", 499 | " \n", 500 | " # regression parameters for the Maximum Likelihood method\n", 501 | " # Note that there are n_features+2 parameters, as one is added for the intercept, \n", 502 | " # and another one for the std of noise \n", 503 | " self.weights = tf.Variable(tf.random_normal([n_features+2, 1]))\n", 504 | " \n", 505 | " # prediction from the model\n", 506 | " self.output = tf.matmul(data_plus_bias, self.weights[:-1, :])\n", 507 | "\n", 508 | " gauss = tf.distributions.Normal(loc=0.0, scale=1.0)\n", 509 | "\n", 510 | " # Standard deviation of the Gaussian noise is modelled as a square of the \n", 511 | " # last model weight\n", 512 | " sigma = 0.0001 + tf.square(self.weights[-1]) \n", 513 | " \n", 514 | " # though a constant sqrt(2*pi) is not needed to find the best parameters, here we keep it\n", 515 | " # to get the value of the log-LL right \n", 516 | " pi = tf.constant(m.pi)\n", 517 | " \n", 518 | " log_LL = tf.log(0.00001 + (1/( tf.sqrt(2*pi)*sigma)) * gauss.prob((self.Y - self.output) / sigma )) \n", 519 | " self.loss = - tf.reduce_mean(log_LL)\n", 520 | " \n", 521 | " self.train_step = (tf.train.AdamOptimizer(learning_rate).minimize(self.loss), -self.loss)" 522 | ] 523 | }, 524 | { 525 | "cell_type": "code", 526 | "execution_count": 18, 527 | "metadata": {}, 528 | "outputs": [], 529 | "source": [ 530 | "# GRADED FUNCTION: run_normal_eq\n", 531 | "def run_normal_eq(X_train, Y_train, X_test, Y_test, learning_rate=0.05):\n", 532 | " \"\"\"\n", 533 | " Implements normal equation using tensorflow, trains the model using training data set\n", 534 | " Tests the model quality by computing mean square error (MSE) of the test data set\n", 535 | " \n", 536 | " Arguments:\n", 537 | " X_train - np.array of size (n by k) where n is number of observations \n", 538 | " of independent variables and k is number of variables\n", 539 | " Y_train - np.array of size (n by 1) where n is the number of observations of dependend variable\n", 540 | " \n", 541 | " X_test - np.array of size (n by k) where n is number of observations \n", 542 | " of independent variables and k is number of variables\n", 543 | " Y_test - np.array of size (n by 1) where n is the number of observations of dependend variable\n", 544 | " \n", 545 | " \n", 546 | " Return a tuple of:\n", 547 | " - np.array of size (k+1 by 1) of regression coefficients\n", 548 | " - mean square error (MSE) of the test data set\n", 549 | " - mean square error (MSE) of the training data set\n", 550 | " \"\"\"\n", 551 | " # create an instance of the Linear Regression model class \n", 552 | " n_features = X_train.shape[1]\n", 553 | " model = LinRegressNormalEq(n_features=n_features, learning_rate=learning_rate)\n", 554 | "\n", 555 | " ### START CODE HERE ### (≈ 10-15 lines of code)\n", 556 | " # train the model\n", 557 | " \n", 558 | " # Normal equation for Linear Regression\n", 559 | " with tf.Session() as sess:\n", 560 | " sess.run(tf.global_variables_initializer())\n", 561 | " \n", 562 | " theta_value = sess.run(model.theta, feed_dict={model.X: X_train, model.Y: Y_train})\n", 563 | " lr_mse_train = sess.run(model.lr_mse, feed_dict={model.X: X_train, model.Y: Y_train, model.theta_in:theta_value})\n", 564 | " lr_mse_test = sess.run(model.lr_mse, feed_dict={model.X:X_test, model.Y:Y_test, model.theta_in:theta_value})\n", 565 | " \n", 566 | " ### END CODE HERE ###\n", 567 | " return theta_value, lr_mse_train, lr_mse_test\n", 568 | "\n", 569 | "### (DO NOT EDIT) ###\n", 570 | "theta_value, lr_mse_train, lr_mse_test = run_normal_eq(X_train, Y_train, X_test, Y_test)\n", 571 | "### (DO NOT EDIT) ###" 572 | ] 573 | }, 574 | { 575 | "cell_type": "code", 576 | "execution_count": 19, 577 | "metadata": {}, 578 | "outputs": [ 579 | { 580 | "name": "stdout", 581 | "output_type": "stream", 582 | "text": [ 583 | "Submission successful, please check on the coursera grader page for the status\n" 584 | ] 585 | }, 586 | { 587 | "data": { 588 | "text/plain": [ 589 | "array([ 0.99946201, 0.99579054, 0.49919799, 0.20019798], dtype=float32)" 590 | ] 591 | }, 592 | "execution_count": 19, 593 | "metadata": {}, 594 | "output_type": "execute_result" 595 | } 596 | ], 597 | "source": [ 598 | "### GRADED PART (DO NOT EDIT) ###\n", 599 | "part_4 = list(theta_value.squeeze())\n", 600 | "try:\n", 601 | " part4 = \" \".join(map(repr, part_4))\n", 602 | "except TypeError:\n", 603 | " part4 = repr(part_4)\n", 604 | "submissions[all_parts[3]]=part4\n", 605 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:4],all_parts,submissions)\n", 606 | "theta_value.squeeze()\n", 607 | "### GRADED PART (DO NOT EDIT) ###" 608 | ] 609 | }, 610 | { 611 | "cell_type": "code", 612 | "execution_count": 20, 613 | "metadata": { 614 | "collapsed": true 615 | }, 616 | "outputs": [], 617 | "source": [ 618 | "# GRADED FUNCTION: run_mle# GRADED \n", 619 | "def run_mle(X_train, Y_train, X_test, Y_test, learning_rate=0.05, num_iter=5000):\n", 620 | " \"\"\"\n", 621 | " Maximum likelihood Estimate (MLE)\n", 622 | " Tests the model quality by computing mean square error (MSE) of the test data set\n", 623 | " \n", 624 | " Arguments:\n", 625 | " X_train - np.array of size (n by k) where n is number of observations \n", 626 | " of independent variables and k is number of variables\n", 627 | " Y_train - np.array of size (n by 1) where n is the number of observations of dependend variable\n", 628 | " \n", 629 | " X_test - np.array of size (n by k) where n is number of observations \n", 630 | " of independent variables and k is number of variables\n", 631 | " Y_test - np.array of size (n by 1) where n is the number of observations of dependend variable\n", 632 | " \n", 633 | " \n", 634 | " Return a tuple of:\n", 635 | " - np.array of size (k+1 by 1) of regression coefficients\n", 636 | " - mean square error (MSE) of the test data set\n", 637 | " - mean square error (MSE) of the training data set\n", 638 | " \"\"\"\n", 639 | " # create an instance of the Linear Regression model class \n", 640 | " n_features = X_train.shape[1]\n", 641 | " model = LinRegressNormalEq(n_features=n_features, learning_rate=learning_rate)\n", 642 | " \n", 643 | " # train the model\n", 644 | " with tf.Session() as sess:\n", 645 | " sess.run(tf.global_variables_initializer())\n", 646 | "\n", 647 | " # Now train the MLE parameters \n", 648 | " for _ in range(num_iter):\n", 649 | " (_ , loss), weights = sess.run((model.train_step, model.weights), feed_dict={\n", 650 | " model.X: X_train,\n", 651 | " model.Y: Y_train\n", 652 | " })\n", 653 | "\n", 654 | " # make test_prediction\n", 655 | " Y_test_predicted = sess.run(model.output, feed_dict={model.X: X_test})\n", 656 | "\n", 657 | " # output std sigma is a square of the last weight\n", 658 | " std_model = weights[-1]**2 \n", 659 | " sess.close()\n", 660 | " return weights[0:-1].squeeze(), loss, std_model\n", 661 | "\n", 662 | "weights, loss, std_model = run_mle(X_train, Y_train, X_test, Y_test)" 663 | ] 664 | }, 665 | { 666 | "cell_type": "code", 667 | "execution_count": 21, 668 | "metadata": {}, 669 | "outputs": [ 670 | { 671 | "name": "stdout", 672 | "output_type": "stream", 673 | "text": [ 674 | "Submission successful, please check on the coursera grader page for the status\n" 675 | ] 676 | }, 677 | { 678 | "data": { 679 | "text/plain": [ 680 | "array([ 0.99945581, 0.9957872 , 0.49920145, 0.20020762], dtype=float32)" 681 | ] 682 | }, 683 | "execution_count": 21, 684 | "metadata": {}, 685 | "output_type": "execute_result" 686 | } 687 | ], 688 | "source": [ 689 | "### GRADED PART (DO NOT EDIT) ###\n", 690 | "part_5 = list(weights.squeeze())\n", 691 | "try:\n", 692 | " part5 = \" \".join(map(repr, part_5))\n", 693 | "except TypeError:\n", 694 | " part5 = repr(part_5)\n", 695 | "submissions[all_parts[4]]=part5\n", 696 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:5],all_parts,submissions)\n", 697 | "weights.squeeze()\n", 698 | "### GRADED PART (DO NOT EDIT) ###" 699 | ] 700 | }, 701 | { 702 | "cell_type": "code", 703 | "execution_count": null, 704 | "metadata": { 705 | "collapsed": true 706 | }, 707 | "outputs": [], 708 | "source": [] 709 | } 710 | ], 711 | "metadata": { 712 | "anaconda-cloud": {}, 713 | "celltoolbar": "Edit Metadata", 714 | "coursera": { 715 | "course_slug": "guided-tour-machine-learning-finance" 716 | }, 717 | "kernelspec": { 718 | "display_name": "Python 3", 719 | "language": "python", 720 | "name": "python3" 721 | }, 722 | "language_info": { 723 | "codemirror_mode": { 724 | "name": "ipython", 725 | "version": 3 726 | }, 727 | "file_extension": ".py", 728 | "mimetype": "text/x-python", 729 | "name": "python", 730 | "nbconvert_exporter": "python", 731 | "pygments_lexer": "ipython3", 732 | "version": "3.6.2" 733 | } 734 | }, 735 | "nbformat": 4, 736 | "nbformat_minor": 1 737 | } 738 | -------------------------------------------------------------------------------- /Reinforcement Learning in Finance/discrete_black_scholes_m3_ex1_v3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Discrete-Time Black Scholes\n", 8 | "Welcome to your 1st assignment in Reinforcement Learning in Finance. This exercise will introduce Black-Scholes model as viewed through the lens of pricing an option as discrete-time replicating portfolio of stock and bond.\n", 9 | "\n", 10 | "**Instructions:**\n", 11 | "- You will be using Python 3.\n", 12 | "- Avoid using for-loops and while-loops, unless you are explicitly told to do so.\n", 13 | "- Do not modify the (# GRADED FUNCTION [function name]) comment in some cells. Your work would not be graded if you change this. Each cell containing that comment should only contain one function.\n", 14 | "- After coding your function, run the cell right below it to check if your result is correct.\n", 15 | "\n", 16 | "\n", 17 | "Let's get started!" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "## About iPython Notebooks ##\n", 25 | "\n", 26 | "iPython Notebooks are interactive coding environments embedded in a webpage. You will be using iPython notebooks in this class. You only need to write code between the ### START CODE HERE ### and ### END CODE HERE ### comments. After writing your code, you can run the cell by either pressing \"SHIFT\"+\"ENTER\" or by clicking on \"Run Cell\" (denoted by a play symbol) in the upper bar of the notebook. \n", 27 | "\n", 28 | "We will often specify \"(≈ X lines of code)\" in the comments to tell you about how much code you need to write. It is just a rough estimate, so don't feel bad if your code is longer or shorter." 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 1, 34 | "metadata": { 35 | "collapsed": true 36 | }, 37 | "outputs": [], 38 | "source": [ 39 | "import numpy as np\n", 40 | "import matplotlib.pyplot as plt\n", 41 | "%matplotlib inline\n", 42 | "\n", 43 | "from numpy.random import standard_normal, seed\n", 44 | "\n", 45 | "import scipy.stats as stats\n", 46 | "from scipy.stats import norm\n", 47 | "\n", 48 | "import sys\n", 49 | "\n", 50 | "sys.path.append(\"..\")\n", 51 | "import grading\n", 52 | "\n", 53 | "import datetime \n", 54 | "import time\n", 55 | "import bspline\n", 56 | "import bspline.splinelab as splinelab" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 2, 62 | "metadata": { 63 | "collapsed": true 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "### ONLY FOR GRADING. DO NOT EDIT ###\n", 68 | "submissions=dict()\n", 69 | "assignment_key=\"J_L65CoiEeiwfQ53m1Mlug\" \n", 70 | "all_parts=[\"9jLRK\",\"YoMns\",\"Wc3NN\",\"fcl3r\"]\n", 71 | "### ONLY FOR GRADING. DO NOT EDIT ###" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 3, 77 | "metadata": { 78 | "collapsed": true 79 | }, 80 | "outputs": [], 81 | "source": [ 82 | "COURSERA_TOKEN = 'Ds9SJM3BAzTskaXL' # the key provided to the Student under his/her email on submission page\n", 83 | "COURSERA_EMAIL = 'aayushmandhyan@hotmail.co.uk'# the email" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 4, 89 | "metadata": { 90 | "collapsed": true 91 | }, 92 | "outputs": [], 93 | "source": [ 94 | "# The Black-Scholes prices\n", 95 | "def bs_put(t, S0, K, r, sigma, T):\n", 96 | " d1 = (np.log(S0/K) + (r + 1/2 * sigma**2) * (T-t)) / sigma / np.sqrt(T-t)\n", 97 | " d2 = (np.log(S0/K) + (r - 1/2 * sigma**2) * (T-t)) / sigma / np.sqrt(T-t)\n", 98 | " price = K * np.exp(-r * (T-t)) * norm.cdf(-d2) - S0 * norm.cdf(-d1)\n", 99 | " return price\n", 100 | "\n", 101 | "def bs_call(t, S0, K, r, sigma, T):\n", 102 | " d1 = (np.log(S0/K) + (r + 1/2 * sigma**2) * (T-t)) / sigma / np.sqrt(T-t)\n", 103 | " d2 = (np.log(S0/K) + (r - 1/2 * sigma**2) * (T-t)) / sigma / np.sqrt(T-t)\n", 104 | " price = S0 * norm.cdf(d1) - K * np.exp(-r * (T-t)) * norm.cdf(d2)\n", 105 | " return price\n", 106 | "\n", 107 | "def d1(S0, K, r, sigma, T):\n", 108 | " return (np.log(S0/K) + (r + sigma**2 / 2) * T)/(sigma * np.sqrt(T))\n", 109 | " \n", 110 | "def d2(S0, K, r, sigma, T):\n", 111 | " return (np.log(S0 / K) + (r - sigma**2 / 2) * T) / (sigma * np.sqrt(T))\n", 112 | " " 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "Simulate $N_{MC}$ stock price sample paths with $T$ steps by the classical Black-Sholes formula.\n", 120 | "\n", 121 | "$$dS_t=\\mu S_tdt+\\sigma S_tdW_t\\quad\\quad S_{t+1}=S_te^{\\left(\\mu-\\frac{1}{2}\\sigma^2\\right)\\Delta t+\\sigma\\sqrt{\\Delta t}Z}$$\n", 122 | "\n", 123 | "where $Z$ is a standard normal random variable.\n", 124 | "\n", 125 | "MC paths are simulated by GeneratePaths() method of DiscreteBlackScholes class." 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "### Part 1\n", 133 | "\n", 134 | "\n", 135 | "Class DiscreteBlackScholes implements the above calculations with class variables to math symbols mapping of:\n", 136 | "\n", 137 | "$$\\Delta S_t=S_{t+1} - e^{-r\\Delta t} S_t\\space \\quad t=T-1,...,0$$\n", 138 | " \n", 139 | "**Instructions:**\n", 140 | "Some portions of code in DiscreteBlackScholes have bee taken out. You are to implement the missing portions of code in DiscreteBlackScholes class.\n", 141 | "\n", 142 | "$$\\Pi_t=e^{-r\\Delta t}\\left[\\Pi_{t+1}-u_t \\Delta S_t\\right]\\quad t=T-1,...,0$$\n", 143 | "\n", 144 | "- implement DiscreteBlackScholes.function_A_vec() method\n", 145 | "$$A_{nm}^{\\left(t\\right)}=\\sum_{k=1}^{N_{MC}}{\\Phi_n\\left(X_t^k\\right)\\Phi_m\\left(X_t^k\\right)\\left(\\Delta\\hat{S}_t^k\\right)^2}\\quad\\quad$$ \n", 146 | "\n", 147 | "- implement DiscreteBlackScholes.function_B_vec() method\n", 148 | "$$B_n^{\\left(t\\right)}=\\sum_{k=1}^{N_{MC}}{\\Phi_n\\left(X_t^k\\right)\\left[\\hat\\Pi_{t+1}^k\\Delta\\hat{S}_t^k+\\frac{1}{2\\gamma\\lambda}\\Delta S_t^k\\right]}$$\n", 149 | "- implement DiscreteBlackScholes.gen_paths() method using the following relation:\n", 150 | "$$S_{t+1}=S_te^{\\left(\\mu-\\frac{1}{2}\\sigma^2\\right)\\Delta t+\\sigma\\sqrt{\\Delta t}Z}$$\n", 151 | "where $Z \\sim N(0,1)$\n", 152 | "- implement parts of DiscreteBlackScholes.roll_backward()\n", 153 | " - DiscreteBlackScholes.bVals corresponds to $B_t$ and is computed as $$B_t = e^{-r\\Delta t}\\left[B_{t+1} + (u_{t+1} - u_t)S_{t+1}\\right]\\quad t=T-1,...,0$$\n", 154 | " \n", 155 | "DiscreteBlackScholes.opt_hedge corresponds to $\\phi_t$ and is computed as \n", 156 | " $$\\phi_t=\\mathbf A_t^{-1}\\mathbf B_t$$" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 5, 162 | "metadata": { 163 | "collapsed": true 164 | }, 165 | "outputs": [], 166 | "source": [ 167 | "class DiscreteBlackScholes:\n", 168 | " \"\"\"\n", 169 | " Class implementing discrete Black Scholes\n", 170 | " DiscreteBlackScholes is class for pricing and hedging under\n", 171 | " the real-world measure for a one-dimensional Black-Scholes setting\n", 172 | " \"\"\"\n", 173 | "\n", 174 | " def __init__(self,\n", 175 | " s0,\n", 176 | " strike,\n", 177 | " vol,\n", 178 | " T,\n", 179 | " r,\n", 180 | " mu,\n", 181 | " numSteps,\n", 182 | " numPaths):\n", 183 | " \"\"\"\n", 184 | " :param s0: initial price of the underlying\n", 185 | " :param strike: option strike\n", 186 | " :param vol: volatility\n", 187 | " :param T: time to maturity, in years\n", 188 | " :param r: risk-free rate,\n", 189 | " :param mu: real drift, asset drift\n", 190 | " :param numSteps: number of time steps\n", 191 | " :param numPaths: number of Monte Carlo paths\n", 192 | " \"\"\"\n", 193 | " self.s0 = s0\n", 194 | " self.strike = strike\n", 195 | " self.vol = vol\n", 196 | " self.T = T\n", 197 | " self.r = r\n", 198 | " self.mu = mu\n", 199 | " self.numSteps = numSteps\n", 200 | " self.numPaths = numPaths\n", 201 | "\n", 202 | " self.dt = self.T / self.numSteps # time step\n", 203 | " self.gamma = np.exp(-r * self.dt) # discount factor for one time step, i.e. gamma in the QLBS paper\n", 204 | "\n", 205 | " self.sVals = np.zeros((self.numPaths, self.numSteps + 1), 'float') # matrix of stock values\n", 206 | "\n", 207 | " # initialize half of the paths with stock price values ranging from 0.5 to 1.5 of s0\n", 208 | " # the other half of the paths start with s0\n", 209 | " half_paths = int(numPaths / 2)\n", 210 | "\n", 211 | " if False:\n", 212 | " # Grau (2010) \"Applications of Least-Squares Regressions to Pricing and Hedging of Financial Derivatives\"\n", 213 | " self.sVals[:, 0] = (np.hstack((np.linspace(0.5 * s0, 1.5 * s0, half_paths),\n", 214 | " s0 * np.ones(half_paths, 'float')))).T\n", 215 | "\n", 216 | " self.sVals[:, 0] = s0 * np.ones(numPaths, 'float')\n", 217 | " self.optionVals = np.zeros((self.numPaths, self.numSteps + 1), 'float') # matrix of option values\n", 218 | " self.intrinsicVals = np.zeros((self.numPaths, self.numSteps + 1), 'float')\n", 219 | "\n", 220 | " self.bVals = np.zeros((self.numPaths, self.numSteps + 1), 'float') # matrix of cash position values\n", 221 | " self.opt_hedge = np.zeros((self.numPaths, self.numSteps + 1),\n", 222 | " 'float') # matrix of optimal hedges calculated from cross-sectional information F_t\n", 223 | " self.X = None\n", 224 | " self.data = None # matrix of features, i.e. self.X as sum of basis functions\n", 225 | " self.delta_S_hat = None\n", 226 | "\n", 227 | " # coef = 1.0/(2 * gamma * risk_lambda)\n", 228 | " # override it by zero to have pure risk hedge\n", 229 | " self.coef = 0.\n", 230 | "\n", 231 | " def gen_paths(self):\n", 232 | " \"\"\"\n", 233 | " A simplest path generator\n", 234 | " \"\"\"\n", 235 | " np.random.seed(42)\n", 236 | " # Spline basis of order p on knots k\n", 237 | "\n", 238 | " ### START CODE HERE ### (≈ 3-4 lines of code)\n", 239 | " # self.sVals = your code goes here ...\n", 240 | " # for-loop or while loop is allowed heres\n", 241 | " Z = np.random.normal(0, 1, size=(self.numSteps+1, self.numPaths)).T\n", 242 | " for t in range(self.numSteps):\n", 243 | " self.sVals[:, t+1] = self.sVals[:, t] * np.exp( (self.mu - 1/2 * self.vol ** 2)*self.dt + (self.vol * np.sqrt(self.dt) * Z[:, t+1]))\n", 244 | "\n", 245 | " ### END CODE HERE ###\n", 246 | "\n", 247 | " # like in QLBS\n", 248 | " delta_S = self.sVals[:, 1:] - np.exp(self.r * self.dt) * self.sVals[:, :self.numSteps]\n", 249 | " self.delta_S_hat = np.apply_along_axis(lambda x: x - np.mean(x), axis=0, arr=delta_S)\n", 250 | "\n", 251 | " # state variable\n", 252 | " # delta_t here is due to their conventions\n", 253 | " self.X = - (self.mu - 0.5 * self.vol ** 2) * np.arange(self.numSteps + 1) * self.dt + np.log(self.sVals)\n", 254 | "\n", 255 | " X_min = np.min(np.min(self.X))\n", 256 | " X_max = np.max(np.max(self.X))\n", 257 | "\n", 258 | " print('X.shape = ', self.X.shape)\n", 259 | " print('X_min, X_max = ', X_min, X_max)\n", 260 | "\n", 261 | " p = 4 # order of spline (as-is; 3 = cubic, 4: B-spline?)\n", 262 | " ncolloc = 12\n", 263 | " tau = np.linspace(X_min, X_max, ncolloc) # These are the sites to which we would like to interpolate\n", 264 | "\n", 265 | " # k is a knot vector that adds endpoints repeats as appropriate for a spline of order p\n", 266 | " # To get meaningful results, one should have ncolloc >= p+1\n", 267 | " k = splinelab.aptknt(tau, p)\n", 268 | " basis = bspline.Bspline(k, p)\n", 269 | "\n", 270 | " num_basis = ncolloc # len(k) #\n", 271 | " self.data = np.zeros((self.numSteps + 1, self.numPaths, num_basis))\n", 272 | "\n", 273 | " print('num_basis = ', num_basis)\n", 274 | " print('dim self.data = ', self.data.shape)\n", 275 | "\n", 276 | " # fill it, expand function in finite dimensional space\n", 277 | " # in neural network the basis is the neural network itself\n", 278 | " t_0 = time.time()\n", 279 | " for ix in np.arange(self.numSteps + 1):\n", 280 | " x = self.X[:, ix]\n", 281 | " self.data[ix, :, :] = np.array([basis(el) for el in x])\n", 282 | " t_end = time.time()\n", 283 | " print('\\nTime Cost of basis expansion:', t_end - t_0, 'seconds')\n", 284 | "\n", 285 | " def function_A_vec(self, t, reg_param=1e-3):\n", 286 | " \"\"\"\n", 287 | " function_A_vec - compute the matrix A_{nm} from Eq. (52) (with a regularization!)\n", 288 | " Eq. (52) in QLBS Q-Learner in the Black-Scholes-Merton article\n", 289 | "\n", 290 | " Arguments:\n", 291 | " t - time index, a scalar, an index into time axis of data_mat\n", 292 | " reg_param - a scalar, regularization parameter\n", 293 | "\n", 294 | " Return:\n", 295 | " - np.array, i.e. matrix A_{nm} of dimension num_basis x num_basis\n", 296 | " \"\"\"\n", 297 | " X_mat = self.data[t, :, :]\n", 298 | " num_basis_funcs = X_mat.shape[1]\n", 299 | " this_dS = self.delta_S_hat[:, t]\n", 300 | " hat_dS2 = (this_dS ** 2).reshape(-1, 1)\n", 301 | " A_mat = np.dot(X_mat.T, X_mat * hat_dS2) + reg_param * np.eye(num_basis_funcs)\n", 302 | " return A_mat\n", 303 | "\n", 304 | " def function_B_vec(self, t, Pi_hat):\n", 305 | " \"\"\"\n", 306 | " function_B_vec - compute vector B_{n} from Eq. (52) QLBS Q-Learner in the Black-Scholes-Merton article\n", 307 | "\n", 308 | " Arguments:\n", 309 | " t - time index, a scalar, an index into time axis of delta_S_hat\n", 310 | " Pi_hat - pandas.DataFrame of dimension N_MC x T of portfolio values\n", 311 | " Return:\n", 312 | " B_vec - np.array() of dimension num_basis x 1\n", 313 | " \"\"\"\n", 314 | " tmp = Pi_hat * self.delta_S_hat[:, t] + self.coef * (np.exp((self.mu - self.r) * self.dt)) * self.sVals[:, t]\n", 315 | " X_mat = self.data[t, :, :] # matrix of dimension N_MC x num_basis\n", 316 | "\n", 317 | " B_vec = np.dot(X_mat.T, tmp)\n", 318 | " return B_vec\n", 319 | "\n", 320 | " def seed_intrinsic(self, strike=None, cp='P'):\n", 321 | " \"\"\"\n", 322 | " initilaize option value and intrinsic value for each node\n", 323 | " \"\"\"\n", 324 | " if strike is not None:\n", 325 | " self.strike = strike\n", 326 | "\n", 327 | " if cp == 'P':\n", 328 | " # payoff function at maturity T: max(K - S(T),0) for all paths\n", 329 | " self.optionVals = np.maximum(self.strike - self.sVals[:, -1], 0).copy()\n", 330 | " # payoff function for all paths, at all time slices\n", 331 | " self.intrinsicVals = np.maximum(self.strike - self.sVals, 0).copy()\n", 332 | " elif cp == 'C':\n", 333 | " # payoff function at maturity T: max(S(T) -K,0) for all paths\n", 334 | " self.optionVals = np.maximum(self.sVals[:, -1] - self.strike, 0).copy()\n", 335 | " # payoff function for all paths, at all time slices\n", 336 | " self.intrinsicVals = np.maximum(self.sVals - self.strike, 0).copy()\n", 337 | " else:\n", 338 | " raise Exception('Invalid parameter: %s'% cp)\n", 339 | "\n", 340 | " self.bVals[:, -1] = self.intrinsicVals[:, -1]\n", 341 | "\n", 342 | " def roll_backward(self):\n", 343 | " \"\"\"\n", 344 | " Roll the price and optimal hedge back in time starting from maturity\n", 345 | " \"\"\"\n", 346 | "\n", 347 | " for t in range(self.numSteps - 1, -1, -1):\n", 348 | "\n", 349 | " # determine the expected portfolio value at the next time node\n", 350 | " piNext = self.bVals[:, t+1] + self.opt_hedge[:, t+1] * self.sVals[:, t+1]\n", 351 | " pi_hat = piNext - np.mean(piNext)\n", 352 | "\n", 353 | " A_mat = self.function_A_vec(t)\n", 354 | " B_vec = self.function_B_vec(t, pi_hat)\n", 355 | " phi = np.dot(np.linalg.inv(A_mat), B_vec)\n", 356 | " self.opt_hedge[:, t] = np.dot(self.data[t, :, :], phi)\n", 357 | "\n", 358 | " ### START CODE HERE ### (≈ 1-2 lines of code)\n", 359 | " # implement code to update self.bVals\n", 360 | " # self.bVals[:,t] = your code goes here ....\n", 361 | " self.bVals[:, t] = np.exp(-self.r * self.dt) * (self.bVals[:, t+1] + (self.opt_hedge[:, t+1] - self.opt_hedge[:, t])*self.sVals[:, t+1])\n", 362 | " \n", 363 | "\n", 364 | " ### END CODE HERE ###\n", 365 | "\n", 366 | " # calculate the initial portfolio value\n", 367 | " initPortfolioVal = self.bVals[:, 0] + self.opt_hedge[:, 0] * self.sVals[:, 0]\n", 368 | "\n", 369 | " # use only the second half of the paths generated with paths starting from S0\n", 370 | " optionVal = np.mean(initPortfolioVal)\n", 371 | " optionValVar = np.std(initPortfolioVal)\n", 372 | " delta = np.mean(self.opt_hedge[:, 0])\n", 373 | "\n", 374 | " return optionVal, delta, optionValVar" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": 6, 380 | "metadata": {}, 381 | "outputs": [ 382 | { 383 | "name": "stdout", 384 | "output_type": "stream", 385 | "text": [ 386 | "X.shape = (100, 253)\n", 387 | "X_min, X_max = 4.10743882917 5.16553756345\n", 388 | "num_basis = 12\n", 389 | "dim self.data = (253, 100, 12)\n", 390 | "\n", 391 | "Time Cost of basis expansion: 5.537452459335327 seconds\n" 392 | ] 393 | }, 394 | { 395 | "data": { 396 | "text/plain": [ 397 | "" 398 | ] 399 | }, 400 | "execution_count": 6, 401 | "metadata": {}, 402 | "output_type": "execute_result" 403 | }, 404 | { 405 | "data": { 406 | "image/png": "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\nAAAASUVORK5CYII=\n", 407 | "text/plain": [ 408 | "" 409 | ] 410 | }, 411 | "metadata": {}, 412 | "output_type": "display_data" 413 | } 414 | ], 415 | "source": [ 416 | "np.random.seed(42)\n", 417 | "strike_k = 95\n", 418 | "test_vol = 0.2\n", 419 | "test_mu = 0.03\n", 420 | "dt = 0.01\n", 421 | "rfr = 0.05\n", 422 | "num_paths = 100\n", 423 | "num_periods = 252\n", 424 | "\n", 425 | "hMC = DiscreteBlackScholes(100, strike_k, test_vol, 1., rfr, test_mu, num_periods, num_paths)\n", 426 | "hMC.gen_paths()\n", 427 | "\n", 428 | "t = hMC.numSteps - 1\n", 429 | "piNext = hMC.bVals[:, t+1] + 0.1 * hMC.sVals[:, t+1]\n", 430 | "pi_hat = piNext - np.mean(piNext)\n", 431 | "\n", 432 | "A_mat = hMC.function_A_vec(t)\n", 433 | "B_vec = hMC.function_B_vec(t, pi_hat)\n", 434 | "phi = np.dot(np.linalg.inv(A_mat), B_vec)\n", 435 | "opt_hedge = np.dot(hMC.data[t, :, :], phi)\n", 436 | "\n", 437 | "# plot the results\n", 438 | "fig = plt.figure(figsize=(12,4))\n", 439 | "ax1 = fig.add_subplot(121)\n", 440 | "\n", 441 | "ax1.scatter(hMC.sVals[:,t], pi_hat)\n", 442 | "ax1.set_title(r'Expected $\\Pi_0$ vs. $S_t$')\n", 443 | "ax1.set_xlabel(r'$S_t$')\n", 444 | "ax1.set_ylabel(r'$\\Pi_0$')" 445 | ] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "execution_count": 7, 450 | "metadata": {}, 451 | "outputs": [ 452 | { 453 | "name": "stdout", 454 | "output_type": "stream", 455 | "text": [ 456 | "Submission successful, please check on the coursera grader page for the status\n" 457 | ] 458 | }, 459 | { 460 | "data": { 461 | "text/plain": [ 462 | "array([ 0.81274895, -3.49043554, 0.69994334, 1.61239986, -0.25153316,\n", 463 | " -3.19082265, 0.8848621 , -2.0380868 , 0.45033564, 3.74872863,\n", 464 | " -0.6568227 , 1.74148929, 0.94314331, -4.19716113, 1.72135256,\n", 465 | " -0.66188482, 6.95675041, -2.20512677, -0.14942482, 0.30067272,\n", 466 | " 3.33419402, 0.68536713, 1.65097153, 2.69898611, 1.22528159,\n", 467 | " 1.47188744, -2.48129898, -0.37360224, 0.81064666, -1.05269459,\n", 468 | " 0.02476551, -1.88267258, 0.11748169, -0.9038195 , 0.69753811,\n", 469 | " -0.54805029, 1.97594593, -0.44331403, 0.62134931, -1.86191032,\n", 470 | " -3.21226413, 2.24508097, -2.23451292, -0.13488281, 3.64364848,\n", 471 | " -0.11270281, -1.15582237, -3.30169455, 1.74454841, -1.10425448,\n", 472 | " 2.10192819, 1.80570507, -1.68587001, -1.42113397, -2.70292006,\n", 473 | " 0.79454199, -2.05396827, 3.13973887, -1.08786662, 0.42347686,\n", 474 | " 1.32787012, 0.55924965, -3.54140814, -3.70258632, 2.14853641,\n", 475 | " 1.11495458, 3.69639676, 0.62864736, -2.62282995, -0.05315552,\n", 476 | " 1.05789698, 1.8023196 , -3.35217374, -2.30436466, -2.68609519,\n", 477 | " 0.95284884, -1.35963013, -0.56273408, -0.08311276, 0.79044269,\n", 478 | " 0.46247485, -1.04921463, -2.18122285, 1.82920128, 1.05635272,\n", 479 | " 0.90161346, -1.93870347, -0.37549305, -1.96383274, 1.9772888 ,\n", 480 | " -1.37386984, 0.95230068, 0.88842589, -1.42214528, -2.60256696,\n", 481 | " -1.53509699, 4.47491253, 4.87735375, -0.19068803, -1.08711941])" 482 | ] 483 | }, 484 | "execution_count": 7, 485 | "metadata": {}, 486 | "output_type": "execute_result" 487 | } 488 | ], 489 | "source": [ 490 | "### GRADED PART (DO NOT EDIT) ###\n", 491 | "\n", 492 | "part_1 = list(pi_hat)\n", 493 | "try:\n", 494 | " part1 = \" \".join(map(repr, part_1))\n", 495 | "except TypeError:\n", 496 | " part1 = repr(part_1)\n", 497 | "submissions[all_parts[0]]=part1\n", 498 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:1],all_parts,submissions)\n", 499 | "pi_hat\n", 500 | "### GRADED PART (DO NOT EDIT) ###" 501 | ] 502 | }, 503 | { 504 | "cell_type": "code", 505 | "execution_count": 8, 506 | "metadata": {}, 507 | "outputs": [ 508 | { 509 | "name": "stdout", 510 | "output_type": "stream", 511 | "text": [ 512 | "X.shape = (50000, 7)\n", 513 | "X_min, X_max = 2.96880459823 6.37164911461\n", 514 | "num_basis = 12\n", 515 | "dim self.data = (7, 50000, 12)\n", 516 | "\n", 517 | "Time Cost of basis expansion: 59.87417483329773 seconds\n", 518 | "Option value = 13.1083498903\n", 519 | "Option value variance = 5.17079676287\n", 520 | "Option delta = -0.356133676933\n", 521 | "BS value 13.1458939003\n" 522 | ] 523 | } 524 | ], 525 | "source": [ 526 | "# input parameters\n", 527 | "s0 = 100.0\n", 528 | "strike = 100.0\n", 529 | "r = 0.05\n", 530 | "mu = 0.07 # 0.05\n", 531 | "vol = 0.4\n", 532 | "T = 1.0\n", 533 | "\n", 534 | "# Simulation Parameters\n", 535 | "numPaths = 50000 # number of Monte Carlo trials\n", 536 | "numSteps = 6\n", 537 | "\n", 538 | "# create the class object\n", 539 | "hMC = DiscreteBlackScholes(s0, strike, vol, T, r, mu, numSteps, numPaths)\n", 540 | "\n", 541 | "# calculation\n", 542 | "hMC.gen_paths()\n", 543 | "hMC.seed_intrinsic()\n", 544 | "option_val, delta, option_val_variance = hMC.roll_backward()\n", 545 | "bs_call_value = bs_put(0, s0, K=strike, r=r, sigma=vol, T=T)\n", 546 | "print('Option value = ', option_val)\n", 547 | "print('Option value variance = ', option_val_variance)\n", 548 | "print('Option delta = ', delta) \n", 549 | "print('BS value', bs_call_value)" 550 | ] 551 | }, 552 | { 553 | "cell_type": "code", 554 | "execution_count": 9, 555 | "metadata": {}, 556 | "outputs": [ 557 | { 558 | "name": "stdout", 559 | "output_type": "stream", 560 | "text": [ 561 | "Submission successful, please check on the coursera grader page for the status\n" 562 | ] 563 | }, 564 | { 565 | "data": { 566 | "text/plain": [ 567 | "13.108349890270032" 568 | ] 569 | }, 570 | "execution_count": 9, 571 | "metadata": {}, 572 | "output_type": "execute_result" 573 | } 574 | ], 575 | "source": [ 576 | "### GRADED PART (DO NOT EDIT) ###\n", 577 | "part2 = str(option_val)\n", 578 | "submissions[all_parts[1]]=part2\n", 579 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:2],all_parts,submissions)\n", 580 | "option_val\n", 581 | "### GRADED PART (DO NOT EDIT) ###" 582 | ] 583 | }, 584 | { 585 | "cell_type": "code", 586 | "execution_count": 10, 587 | "metadata": {}, 588 | "outputs": [ 589 | { 590 | "name": "stdout", 591 | "output_type": "stream", 592 | "text": [ 593 | "X.shape = (50000, 7)\n", 594 | "X_min, X_max = 2.96880459823 6.37164911461\n", 595 | "num_basis = 12\n", 596 | "dim self.data = (7, 50000, 12)\n", 597 | "\n", 598 | "Time Cost of basis expansion: 57.72551369667053 seconds\n" 599 | ] 600 | }, 601 | { 602 | "data": { 603 | "text/plain": [ 604 | "array([ 6.70326307, 8.59543726, 10.74614496, 13.1458939 ,\n", 605 | " 15.78197485, 18.63949388])" 606 | ] 607 | }, 608 | "execution_count": 10, 609 | "metadata": {}, 610 | "output_type": "execute_result" 611 | } 612 | ], 613 | "source": [ 614 | "strikes = np.linspace(85, 110, 6)\n", 615 | "results = [None] * len(strikes)\n", 616 | "bs_prices = np.zeros(len(strikes))\n", 617 | "bs_deltas = np.zeros(len(strikes))\n", 618 | "numPaths = 50000\n", 619 | "hMC = DiscreteBlackScholes(s0, strike, vol, T, r, mu, numSteps, numPaths)\n", 620 | "hMC.gen_paths()\n", 621 | "for ix, k_strike in enumerate(strikes):\n", 622 | " hMC.seed_intrinsic(k_strike)\n", 623 | " results[ix] = hMC.roll_backward()\n", 624 | " bs_prices[ix] = bs_put(0, s0, K=k_strike, r=r, sigma=vol, T=T)\n", 625 | " bs_deltas[ix] = norm.cdf(d1(s0, K=k_strike, r=r, sigma=vol, T=T)) - 1\n", 626 | "bs_prices" 627 | ] 628 | }, 629 | { 630 | "cell_type": "code", 631 | "execution_count": 11, 632 | "metadata": { 633 | "collapsed": true 634 | }, 635 | "outputs": [], 636 | "source": [ 637 | "mc_prices = np.array([x[0] for x in results])\n", 638 | "mc_deltas = np.array([x[1] for x in results])\n", 639 | "price_variances = np.array([x[-1] for x in results])\n", 640 | "prices_diff = mc_prices - bs_prices\n", 641 | "deltas_diff = mc_deltas - bs_deltas\n", 642 | "# price_variances" 643 | ] 644 | }, 645 | { 646 | "cell_type": "code", 647 | "execution_count": 12, 648 | "metadata": {}, 649 | "outputs": [ 650 | { 651 | "name": "stdout", 652 | "output_type": "stream", 653 | "text": [ 654 | "Submission successful, please check on the coursera grader page for the status\n" 655 | ] 656 | }, 657 | { 658 | "data": { 659 | "text/plain": [ 660 | "array([-0.03641513, -0.0403414 , -0.03996596, -0.03754401, -0.03240004,\n", 661 | " -0.02997067])" 662 | ] 663 | }, 664 | "execution_count": 12, 665 | "metadata": {}, 666 | "output_type": "execute_result" 667 | } 668 | ], 669 | "source": [ 670 | "### GRADED PART (DO NOT EDIT) ###\n", 671 | "\n", 672 | "part_3 = list(prices_diff)\n", 673 | "try:\n", 674 | " part3 = \" \".join(map(repr, part_3))\n", 675 | "except TypeError:\n", 676 | " part3 = repr(part_3)\n", 677 | "submissions[all_parts[2]]=part3\n", 678 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:3],all_parts,submissions)\n", 679 | "prices_diff\n", 680 | "### GRADED PART (DO NOT EDIT) ###" 681 | ] 682 | }, 683 | { 684 | "cell_type": "code", 685 | "execution_count": 13, 686 | "metadata": {}, 687 | "outputs": [ 688 | { 689 | "name": "stdout", 690 | "output_type": "stream", 691 | "text": [ 692 | "Submission successful, please check on the coursera grader page for the status\n" 693 | ] 694 | }, 695 | { 696 | "data": { 697 | "text/plain": [ 698 | "array([ 0.01279805, 0.01416023, 0.01532697, 0.01645686, 0.01715332,\n", 699 | " 0.01780665])" 700 | ] 701 | }, 702 | "execution_count": 13, 703 | "metadata": {}, 704 | "output_type": "execute_result" 705 | } 706 | ], 707 | "source": [ 708 | "### GRADED PART (DO NOT EDIT) ###\n", 709 | "part_4 = list(deltas_diff)\n", 710 | "try:\n", 711 | " part4 = \" \".join(map(repr, part_4))\n", 712 | "except TypeError:\n", 713 | " part4= repr(part_4)\n", 714 | "submissions[all_parts[3]]=part4\n", 715 | "grading.submit(COURSERA_EMAIL, COURSERA_TOKEN, assignment_key,all_parts[:4],all_parts,submissions)\n", 716 | "deltas_diff\n", 717 | "### GRADED PART (DO NOT EDIT) ###" 718 | ] 719 | } 720 | ], 721 | "metadata": { 722 | "coursera": { 723 | "course_slug": "reinforcement-learning-in-finance" 724 | }, 725 | "kernelspec": { 726 | "display_name": "Python 3", 727 | "language": "python", 728 | "name": "python3" 729 | }, 730 | "language_info": { 731 | "codemirror_mode": { 732 | "name": "ipython", 733 | "version": 3 734 | }, 735 | "file_extension": ".py", 736 | "mimetype": "text/x-python", 737 | "name": "python", 738 | "nbconvert_exporter": "python", 739 | "pygments_lexer": "ipython3", 740 | "version": "3.6.2" 741 | } 742 | }, 743 | "nbformat": 4, 744 | "nbformat_minor": 2 745 | } 746 | -------------------------------------------------------------------------------- /Guided Tour of Machine Learning in Finance/Computing Gradients using TensorFlow.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 3, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "#importing libraries\n", 10 | "import numpy as np\n", 11 | "import os\n", 12 | "import matplotlib\n", 13 | "import matplotlib.pyplot as plt\n", 14 | "import time\n", 15 | "import tensorflow as tf\n", 16 | "\n", 17 | "%matplotlib inline" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 4, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "#utility function to reset graph\n", 27 | "def reset_graph(seed=42):\n", 28 | " tf.reset_default_graph()\n", 29 | " tf.set_random_seed(seed)\n", 30 | " np.random.seed(seed)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "# Creating & Running a Graph" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "Define a composite function $f(w) = exp(w_{20} + w_{21}.exp(w_{10} + w_{11}.exp(w_{00} + w_{01}.x)))$" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 5, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "#implementing above function in tensorflow\n", 54 | "def eq(w, x):\n", 55 | " f0 = tf.exp(w[0,0] + w[0,1]*w)\n", 56 | " f1 = tf.exp(w[1,0] + w[1,1]*f0)\n", 57 | " f2 = tf.exp(w[2,0] + w[2,1]*f1)\n", 58 | " \n", 59 | " return f2, f1, f0" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 27, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "#fancier implementation for the function with name scope\n", 69 | "def eq(w, x):\n", 70 | " with tf.name_scope('f0_level') as scope0:\n", 71 | " f0 = tf.exp(w[0,0] + w[0,1]*w)\n", 72 | " with tf.name_scope('f1_level') as scope1:\n", 73 | " f1 = tf.exp(w[1,0] + w[1,1]*f0)\n", 74 | " with tf.name_scope('f2_level') as scope2:\n", 75 | " f2 = tf.exp(w[2,0] + w[2,1]*f1)\n", 76 | " \n", 77 | " return f2, f1, f0" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 10, 83 | "metadata": {}, 84 | "outputs": [ 85 | { 86 | "data": { 87 | "text/plain": [ 88 | "array([[0., 1.],\n", 89 | " [0., 1.],\n", 90 | " [0., 1.]])" 91 | ] 92 | }, 93 | "execution_count": 10, 94 | "metadata": {}, 95 | "output_type": "execute_result" 96 | } 97 | ], 98 | "source": [ 99 | "# w0 is the point at which we want to compute the derivative\n", 100 | "w0 = np.vstack((np.zeros(3), np.ones(3))).T\n", 101 | "w0" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "# Computing gradients using TensorFlow" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 28, 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "data": { 118 | "text/plain": [ 119 | "[]" 120 | ] 121 | }, 122 | "execution_count": 28, 123 | "metadata": {}, 124 | "output_type": "execute_result" 125 | } 126 | ], 127 | "source": [ 128 | "reset_graph()\n", 129 | "\n", 130 | "#define and initialize variables\n", 131 | "w = tf.Variable(w0, name='w', dtype=tf.float32)\n", 132 | "x = tf.Variable(1.0, name='x', dtype=tf.float32, trainable=False)\n", 133 | "\n", 134 | "#define nodes for the values of the function at layers\n", 135 | "f2, f1, f0 = eq(w, x)\n", 136 | "\n", 137 | "#define node for the gradients by tensorflow's autodiff\n", 138 | "gradient_function = tf.gradients(f2, w)\n", 139 | "\n", 140 | "gradient_function" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 29, 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "name": "stdout", 150 | "output_type": "stream", 151 | "text": [ 152 | "Computation time: 0.0405173.2 sec\n", 153 | "Funciton Values: [array([[1.5154261e+01, 3.8142730e+06],\n", 154 | " [1.5154261e+01, 3.8142730e+06],\n", 155 | " [1.5154261e+01, 3.8142730e+06]], dtype=float32), array([[ 2.7182817, 15.154261 ],\n", 156 | " [ 2.7182817, 15.154261 ],\n", 157 | " [ 2.7182817, 15.154261 ]], dtype=float32), array([[1. , 2.7182817],\n", 158 | " [1. , 2.7182817],\n", 159 | " [1. , 2.7182817]], dtype=float32)]\n", 160 | "Gradients: [array([[4.7137046e+08, 6.2849376e+08],\n", 161 | " [1.7340763e+08, 6.2849389e+08],\n", 162 | " [1.1442905e+07, 3.3053101e+08]], dtype=float32)]\n" 163 | ] 164 | } 165 | ], 166 | "source": [ 167 | "#a node for the initializer\n", 168 | "init = tf.global_variables_initializer()\n", 169 | "\n", 170 | "#run session\n", 171 | "t = time.time()\n", 172 | "\n", 173 | "with tf.Session() as sess:\n", 174 | " sess.run(init)\n", 175 | " gradients, function_values = sess.run([gradient_function, [f2, f1, f0]])\n", 176 | " \n", 177 | "print('Computation time: %f3.2 sec' %(time.time()-t))\n", 178 | "print('Funciton Values: ',function_values)\n", 179 | "print('Gradients: ',gradients)" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "# Visualizing above graph" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 25, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "#function for visualizing graph with Jupyter\n", 196 | "\n", 197 | "from IPython.display import clear_output, Image, display, HTML\n", 198 | "\n", 199 | "def strip_consts(graph_def, max_const_size=32):\n", 200 | " \"\"\"Strip large constant values from graph_def.\"\"\"\n", 201 | " strip_def = tf.GraphDef()\n", 202 | " for n0 in graph_def.node:\n", 203 | " n = strip_def.node.add()\n", 204 | " n.MergeFrom(n0)\n", 205 | " if n.op == 'Const':\n", 206 | " tensor = n.attr['value'].tensor\n", 207 | " size = len(tensor.tensor_content)\n", 208 | " if size > max_const_size:\n", 209 | " tensor.tensor_content = b\"\"%size\n", 210 | " return strip_def\n", 211 | "\n", 212 | "def show_graph(graph_def, max_const_size=32):\n", 213 | " \"\"\"Visualize tensorflow graph.\"\"\"\n", 214 | " if hasattr(graph_def, 'as_graph_def'):\n", 215 | " graph_def = graph_def.as_graph_def()\n", 216 | " strip_def = strip_consts(graph_def, max_const_size=max_const_size)\n", 217 | " code = \"\"\"\n", 218 | " \n", 222 | " \n", 223 | "
\n", 224 | " \n", 225 | "
\n", 226 | " \"\"\".format(data=repr(str(strip_def)), id='graph'+str(np.random.rand()))\n", 227 | " \n", 228 | " iframe = \"\"\"\"\"\".format(code.replace('\"', '"'))\n", 229 | " display(HTML(iframe))" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": 31, 235 | "metadata": {}, 236 | "outputs": [ 237 | { 238 | "data": { 239 | "text/html": [ 240 | "" 250 | ], 251 | "text/plain": [ 252 | "" 253 | ] 254 | }, 255 | "metadata": {}, 256 | "output_type": "display_data" 257 | } 258 | ], 259 | "source": [ 260 | "show_graph(tf.get_default_graph())" 261 | ] 262 | } 263 | ], 264 | "metadata": { 265 | "kernelspec": { 266 | "display_name": "Python 3", 267 | "language": "python", 268 | "name": "python3" 269 | }, 270 | "language_info": { 271 | "codemirror_mode": { 272 | "name": "ipython", 273 | "version": 3 274 | }, 275 | "file_extension": ".py", 276 | "mimetype": "text/x-python", 277 | "name": "python", 278 | "nbconvert_exporter": "python", 279 | "pygments_lexer": "ipython3", 280 | "version": "3.6.6" 281 | } 282 | }, 283 | "nbformat": 4, 284 | "nbformat_minor": 2 285 | } 286 | --------------------------------------------------------------------------------