Exploring the Parameter Space ******************************** Expand models to check the full range of inputs and see how it impacts the outputs. Resources ============ - :download:`Slides - Exploring the Parameter Space ` - :download:`Lecture Notes - Exploring the Parameter Space ` - :download:`Dynamic Salary Retirement Model - Excel ` - :download:`Python Dicts, List Comprehensions, and Imports ` - :download:`Dictionaries, List Comprehensions, and Imports Labs ` - `Guide to Python Imports `_ - :download:`Sensitivity Analysis ` - :download:`Dynamic Salary Retirement Model - Python ` Introduction to Parameter Exploration ======================================== .. youtube:: IVC38ksxNfI :height: 315 :width: 80% :align: center | Notes -------- - If you've merely done a calculation, you have a single answer and can't learn any more about the problem without redoing the calculations - Instead because we are building models which can flexibly take any input and convert that into the appropriate output, it opens up a lot of possible extensions to the model - This is our main focus for a large portion of the course: how can we extend any financial model to get a greater understanding of the underlying problem - Sensitivity analysis is useful to understand how the full range of possible inputs affects the main results of your model - Scenario analysis allows analyzing outcomes in example situations - Monte Carlo Simulation allows assigning outputs to a probability distribution, which helps you understand the risk of your result Transcript ------------- .. raw:: html
| Introduction to Sensitivity Analysis ======================================= .. youtube:: dMpQNAnIhJQ :height: 315 :width: 80% :align: center | Notes -------- - The formal definition of sensitivity analysis may seem complicated, but all we are doing is running the model multiple times with different inputs and showing the outputs - A key component of sensitivity analysis is the visualization, as now that there are many different outputs it is much easier to draw meaning from them when visualized Transcript ------------- .. raw:: html
| Sensitivity Analysis in Excel ================================ .. youtube:: 1wECF1RjsNM :height: 315 :width: 80% :align: center | Notes -------- - Data tables in Excel allow calculating a cell multiple times, changing some other cell. This is perfect for sensitivity analysis if we target an output cell and change an input cell - One-way data tables change one input at a time, two-way data tables change two inputs at a time - You are basically limited to changing two inputs at once, without doing some clever hacks - Visualization rule of thumb: graph one-way data tables and use conditional formatting for two-way - Conditional formatting changes the format of cells based on conditions, such as putting the largest numbers in green and the smallest in red - Row input cell means that your inputs are going horizontally in a row. Column input cell means that your inputs going vertically in a column. For one-way data tables, you will use only one of the two. For two-way data tables, you will use both Resources ------------ - :download:`Dynamic Salary Retirement Model - Excel ` Transcript ------------- .. raw:: html
| Using Python Dictionaries ============================ .. youtube:: 6Q8LvUQmykE :height: 315 :width: 80% :align: center | Notes -------- - There are three ways to loop through dictionaries: through the keys (the default), through the values (.values()), and through both at once (.items()) - If you want one way to do it, just always loop through the items as you have access to both the key and the value at once - Combine dictionaries using update. Add items to dictionaries with brackets and assignment. Remove items from dictionaries with pop Resources ------------ - :download:`Python Dicts, List Comprehensions, and Imports ` - :download:`Dictionaries, List Comprehensions, and Imports Labs ` Transcript ------------- .. raw:: html
| Python List Comprehensions - Convenient List Building ======================================================== .. youtube:: 6GpCoTG704o :height: 315 :width: 80% :align: center | Notes -------- - List comprehensions are an example of "syntactic sugar," or a feature of a programming language which is not necessary but makes things easier (makes the programming experience "sweeter") - They allow us to write simple loops made to create lists with only a single line of code Resources ------------ - :download:`Python Dicts, List Comprehensions, and Imports ` - :download:`Dictionaries, List Comprehensions, and Imports Labs ` Transcript ------------- .. raw:: html
| Python Imports and Installing Packages ========================================= .. youtube:: xSX8sg7Twqw :height: 315 :width: 80% :align: center | Notes -------- - Import can be used for third-party and built-in packages, but also for your own code offloaded into separate files - I had you install Anaconda to get Python because it includes most of the Python packages we would want to use pre-installed. So we haven't had to install any package up to now - With more than 250k packages out there and only about 200 installed in Anaconda, the time will come when you need to install something - It will even happen in this course because we will use some packages I have created Resources ------------ - :download:`Python Dicts, List Comprehensions, and Imports ` - `Guide to Python Imports `_ Transcript ------------- .. raw:: html
  • 00:03: hey everyone
  • 00:03: nick dear burst here teaching you
  • 00:05: financial modeling today we're going to
  • 00:07: be talking about
  • 00:09: imports in python and installing python
  • 00:12: packages this is part of our lecture
  • 00:15: segment on exploring the parameter space
  • 00:17: with sensitivity analysis and the sub
  • 00:20: segment
  • 00:21: on additional python basics that we need
  • 00:24: to be able to
  • 00:25: attack sensitivity analysis in python
  • 00:30: so we're here in this extra python basic
  • 00:34: section
  • 00:34: of the sensitivity analysis lecture
  • 00:38: starting here with understanding imports
  • 00:41: in python
  • 00:43: so we've already used the import
  • 00:45: statement a little bit we've imported
  • 00:47: numpy we've
  • 00:48: imported pandas um
  • 00:51: and what that import is doing
  • 00:54: it is loading this external package
  • 00:58: which we can then use and
  • 01:02: that makes it sound and seem like these
  • 01:05: third-party packages
  • 01:06: numpy pandas and all the others that we
  • 01:09: can potentially use
  • 01:11: makes them sound like there's some kind
  • 01:12: of uh
  • 01:14: you know very structured special things
  • 01:17: um that you need to set it up in some
  • 01:19: really special way
  • 01:21: um but it's quite a bit simpler than
  • 01:23: that really it's
  • 01:24: they're just sets of python code and
  • 01:27: just a bunch of files
  • 01:29: and when you import it it's just loading
  • 01:31: the python code in those files
  • 01:34: into your notebook or wherever you're
  • 01:36: working
  • 01:38: and so just like the authors of numpy
  • 01:42: and pandas have written
  • 01:44: all these python files with functions
  • 01:47: and classes that you can use
  • 01:49: you can also write your own code and put
  • 01:52: them in python files
  • 01:54: and import your code from python files
  • 01:57: in the same exact way so the way that
  • 02:00: that works
  • 02:01: is you say import something
  • 02:04: what happens is python searches
  • 02:08: on your computer in certain spots to see
  • 02:11: if it can find
  • 02:12: uh something dot p y dot p
  • 02:15: y is a python file the plain text file
  • 02:19: with a dot py extension
  • 02:23: and so it's first it has a certain order
  • 02:26: that it goes and searches
  • 02:27: your computer in and the first place
  • 02:30: it's going to look
  • 02:31: is in your current folder
  • 02:34: so if you have right next to your
  • 02:37: jupiter notebook you have a something.py
  • 02:40: defined there and it has some functions
  • 02:42: there are classes in there
  • 02:44: when you import something it's going to
  • 02:46: bring in the code
  • 02:47: from that something.py
  • 02:51: file and then if
  • 02:54: it can't find any something there then
  • 02:56: it's going to go on
  • 02:57: and continue looking through the
  • 02:59: different locations that it has set up
  • 03:01: to search
  • 03:02: and beyond your current directory the
  • 03:05: main other locations are going to be
  • 03:08: a certain spot where it installs all
  • 03:10: your packages
  • 03:11: um and there's often a couple different
  • 03:15: spots that it can put the packages so
  • 03:16: those will be multiple different spots
  • 03:18: that it looks in
  • 03:19: and order so when you install a package
  • 03:22: it'll put it in this special spot
  • 03:25: so when you import then if you don't
  • 03:28: have a file defined with that name it'll
  • 03:30: go look
  • 03:30: where your packages are and then be able
  • 03:32: to import it from
  • 03:34: there so that is something to be
  • 03:37: mindful of because it does always look
  • 03:40: in the current directory first
  • 03:42: if you actually created a numpy.py
  • 03:45: file in the current directory then when
  • 03:48: you import numpy
  • 03:50: you're no longer getting the numpy
  • 03:51: package you're getting your
  • 03:53: numpy.py file and so that is something
  • 03:57: to be
  • 03:57: careful about that you don't want to
  • 04:00: define
  • 04:01: python files with the same names as
  • 04:04: packages that you might be meaning to
  • 04:06: import it could definitely cause a
  • 04:08: conflict
  • 04:12: so you can write your own custom code
  • 04:16: and you can then import it
  • 04:19: into your notebook later on so
  • 04:22: if you have any functions or classes
  • 04:24: that you create as
  • 04:26: as you're building out your models and
  • 04:28: you say hey that's actually a pretty
  • 04:30: generally useful thing that i just built
  • 04:32: i'm probably going to want to use that
  • 04:34: in my next model not just this model
  • 04:37: then you can take that function or take
  • 04:39: that class and you can offload it
  • 04:41: into the separate python file and then
  • 04:45: no matter how many notebooks you have
  • 04:46: you can just keep importing that same
  • 04:49: function or class in your notebook and
  • 04:52: then
  • 04:52: say that you wanted to add a new feature
  • 04:55: to that function
  • 04:56: it now gets a new default a new argument
  • 04:59: um and it can do additional things now
  • 05:03: um you make that change in one spot in
  • 05:06: your python file and that will carry
  • 05:08: through to all your notebooks that are
  • 05:10: using it
  • 05:11: so it goes even further in this code
  • 05:13: reuse direction
  • 05:15: to keep from having to repeat yourself
  • 05:19: so what happens
  • 05:23: when you import a file is it executes
  • 05:27: everything in that file so
  • 05:30: you can think of you know like executing
  • 05:33: a code cell
  • 05:34: in jupyter you can think of your python
  • 05:36: file as being the contents of one code
  • 05:39: cell
  • 05:40: and importing that file is the same as
  • 05:43: running
  • 05:43: that code cell so generally
  • 05:48: all that you want to have in there for
  • 05:50: the most part is going to be function
  • 05:51: and class
  • 05:52: definitions you don't want to generally
  • 05:54: be doing anything
  • 05:55: uh you just want the setup the
  • 05:57: definitions so that you
  • 05:59: can do something with those functions
  • 06:02: and classes
  • 06:03: um because uh
  • 06:06: weird things can happen if you you know
  • 06:09: are importing something multiple times
  • 06:11: and you're expecting it to do something
  • 06:13: python only imports it once and then
  • 06:16: it caches it so it doesn't have to keep
  • 06:17: importing it so
  • 06:19: you can run into unexpected behavior if
  • 06:21: you're trying to run logic
  • 06:23: when you import instead just have
  • 06:25: functions and classes
  • 06:27: for the most part and then
  • 06:31: then when you import it you'll have all
  • 06:33: those defines so that you can use them
  • 06:36: in your notebook
  • 06:39: and you know it's a little bit more
  • 06:41: advanced to go to the structure than
  • 06:42: just having everything all in one
  • 06:44: jupiter notebook of course
  • 06:46: but it is a more maintainable structure
  • 06:49: as you go to build larger and more
  • 06:52: complex models and as you go to build
  • 06:54: uh more and more different models where
  • 06:57: you might want to share
  • 06:58: code across your different models
  • 07:03: so it's a good thing to learn about
  • 07:07: you might not have to go there in this
  • 07:09: class
  • 07:10: [Music]
  • 07:12: as we get further in the course the
  • 07:14: fourth project in the course is the dcf
  • 07:16: model and the third project
  • 07:18: is a wac model which the whack is part
  • 07:21: of the dcf model and so i have seen
  • 07:24: students
  • 07:24: take their functions from the wac model
  • 07:26: and refactor them out
  • 07:28: into these separate python files and
  • 07:30: then use them
  • 07:31: in their dcf model so they don't have to
  • 07:33: like rewrite all the whack parts of the
  • 07:35: model so that's
  • 07:36: definitely a good application for this
  • 07:38: within this class
  • 07:40: but i'm mainly mentioning it here just
  • 07:42: so one that you understand
  • 07:44: what imports are and that they're not
  • 07:45: anything really special it's just
  • 07:48: running the contents of some file which
  • 07:50: has python code in it
  • 07:52: um and that's so also you can know about
  • 07:54: this as
  • 07:55: a way to grow into as you start to go
  • 07:58: and continue to apply this stuff
  • 08:00: out of the course and maybe you find
  • 08:02: your jupiter notebooks to be getting
  • 08:03: really long and unwieldy
  • 08:07: or maybe it's even just that you have a
  • 08:08: lot of code in your jupiter notebook and
  • 08:10: you really want it more focused on just
  • 08:12: the results
  • 08:13: and not showing so much code to the
  • 08:14: reader of the model
  • 08:16: for all these different use cases going
  • 08:18: to offloading your code
  • 08:20: into separate python files is a good
  • 08:24: solution
  • 08:27: so um as we mentioned
  • 08:31: these these packages that you can
  • 08:32: install all they are are just plain
  • 08:34: python files and defined functions and
  • 08:37: classes
  • 08:37: just like we've already learned how to
  • 08:39: do
  • 08:42: and going along with this course i had
  • 08:45: you install anaconda
  • 08:47: for your python distribution and that's
  • 08:49: because
  • 08:50: it comes with around 200 packages
  • 08:53: already pre-installed
  • 08:54: and it's most of the common ones that we
  • 08:56: would want to use so most of the time
  • 08:58: you don't need to install the package
  • 09:00: you already have it installed from
  • 09:01: anaconda
  • 09:03: but there's around 200 in anaconda and
  • 09:05: there's around
  • 09:07: 000 packages out there that you could
  • 09:10: potentially use
  • 09:11: huge number of packages and this is one
  • 09:14: of those things that makes python so
  • 09:16: great
  • 09:16: there's a package out there for
  • 09:18: everything that you could want to do
  • 09:19: essentially um it'll make your life so
  • 09:22: much easier just finding the correct
  • 09:24: package to work with instead of having
  • 09:26: to
  • 09:26: recreate everything yourself so
  • 09:31: you find this package you googled about
  • 09:33: it you landed on some github page or
  • 09:36: pipi page or something
  • 09:38: explaining what this package is now you
  • 09:40: say i want to use this
  • 09:41: what's the next step so um
  • 09:45: the way to do this is with pip pip
  • 09:48: is the python package installer um
  • 09:52: and it's very simple it's just pip
  • 09:55: install and then the name of the package
  • 09:57: and that
  • 09:57: installs the package for you now where
  • 10:00: do you run this
  • 10:01: that happens in the terminal so that
  • 10:04: anaconda prompt
  • 10:05: would be a good place to run that uh but
  • 10:08: jupiter does
  • 10:09: actually have a shortcut where you can
  • 10:11: run terminal commands
  • 10:13: instead of just python code and you do
  • 10:16: that by just putting an exclamation mark
  • 10:18: before whatever you're running in the
  • 10:20: cell and that says
  • 10:22: hey jupiter i'm trying to run something
  • 10:23: in a terminal not
  • 10:26: in as python code um
  • 10:29: and so that would be exclamation park
  • 10:32: pip install
  • 10:33: and then the name of the package to
  • 10:36: install it from
  • 10:37: jupiter and you only need to install a
  • 10:40: package once
  • 10:41: once you install it you have it on your
  • 10:43: computer for as long as you have python
  • 10:45: installed
  • 10:47: the only time that you might want to run
  • 10:49: this again is
  • 10:51: to upgrade the package you can add an
  • 10:53: upgrade flag into that
  • 10:55: we'll talk about that a little bit later
  • 10:56: in the course when we need to use that
  • 10:59: but generally install it once you have
  • 11:01: it and you can just use it you just have
  • 11:03: to import it in each session
  • 11:04: but then you can keep using it just like
  • 11:06: we have been using numpy or pandas or
  • 11:08: anything you have
  • 11:09: already installed
  • 11:12: um so let's look at a quick
  • 11:15: example of that so let's jump over to
  • 11:18: the jupiter
  • 11:19: notebook and this is the same one with
  • 11:22: all the other additional basics
  • 11:23: dictionaries list comprehensions
  • 11:25: here we're um imports and installing
  • 11:29: packages
  • 11:31: and so um the reason that we're getting
  • 11:34: to installing packages now
  • 11:36: in the course is because
  • 11:39: uh we're going to go and do sensitivity
  • 11:42: analysis
  • 11:43: with a purpose-built package which is
  • 11:45: made for that purpose
  • 11:48: and the reason this is not an anaconda
  • 11:50: is because
  • 11:51: i actually wrote this package um
  • 11:54: and it doesn't hasn't gotten popular
  • 11:57: enough yet to make its way into anaconda
  • 11:59: it's got a long way to go
  • 12:00: until it gets there maybe someday uh but
  • 12:02: until then
  • 12:03: we're going to have to just install it
  • 12:05: manually
  • 12:06: uh to be able to use it so
  • 12:10: that's uh what we have here
  • 12:13: is pip install sensitivity is the name
  • 12:16: of the package
  • 12:17: i was amazed that this name was
  • 12:19: available for me to take
  • 12:21: uh it was the perfect name for the
  • 12:23: package
  • 12:24: um and all you do
  • 12:27: is just exclamation mark pip install and
  • 12:30: then the name of the package
  • 12:31: so let's go ahead and try to run that
  • 12:34: and when you do these exclamation mark
  • 12:35: commands
  • 12:36: uh it does it looks like it's doing
  • 12:38: nothing for a long time and then it
  • 12:40: spits out the result
  • 12:41: all at once when it's done you don't see
  • 12:43: it like stream
  • 12:44: the result as you go if you're running
  • 12:46: in the terminal you would see all this
  • 12:48: stuff happen line by line and jupiter
  • 12:51: just spits it all out at the end
  • 12:53: um and so you're going to see probably a
  • 12:56: lot of requirement already satisfied
  • 12:59: that's fine just ignore that just scroll
  • 13:01: all the way down to the end
  • 13:04: and here it looks like i even uh
  • 13:08: i actually already had the package
  • 13:09: installed and so the first one
  • 13:12: up here was requirement already
  • 13:13: satisfied sensitivity
  • 13:16: um but if you uh
  • 13:19: pick some other package that you don't
  • 13:21: have
  • 13:23: and you should see this for sensitivity
  • 13:25: when you go to install it
  • 13:28: you're going to see at the end
  • 13:30: successfully installed
  • 13:32: and then the name of the package and
  • 13:34: then the version of the package
  • 13:36: and then you can start using that
  • 13:38: package as soon as you want
  • 13:40: um so with sensitivity i can go ahead
  • 13:43: and import sensitivity
  • 13:45: and then i would be able to use the
  • 13:47: package
  • 13:48: so make sure to run that with
  • 13:50: sensitivity
  • 13:51: not this other package and then go ahead
  • 13:54: and try the import
  • 13:55: you should see it just execute and the
  • 13:57: number change here
  • 13:58: and nothing else happen and that means
  • 14:02: that you have
  • 14:03: installed it correctly
  • 14:07: so that's a quick overview on
  • 14:10: imports in python and installing
  • 14:11: packages we're going to come back
  • 14:14: next time to start implementing
  • 14:16: sensitivity analysis
  • 14:18: in python using the sensitivity
  • 14:21: package so thanks for listening and see
  • 14:24: you next time
| Introduction to Sensitivity Analysis in Python ================================================= .. youtube:: AybxBMC7dzo :height: 315 :width: 80% :align: center | Notes -------- - With sensitivity analysis in Python, we can get DataFrames looking similar to the tables with conditional formatting we saw in Excel - We can also output hexbin plots which show the same graphically - Unlike Excel, we are not limited to analyzing two inputs at once, though it still makes sense to visualize the output in pairs of inputs - The basic setup with pure Python is fairly simple: use loops over the possible input values and call your model function in the loop, saving the output associated with the inputs. Changing multiple inputs at once means multiple nested loops. - Then you have to add the conditional formatting or hexbin plot - The sensitivity package reduces this all to a couple lines of code, regardless of how many inputs you want to look at Resources ------------ - :download:`Sensitivity Analysis ` Transcript ------------- .. raw:: html
  • 00:03: hey everyone
  • 00:04: nick dear bertis here teaching you
  • 00:05: financial modeling and today
  • 00:07: i'm going to be talking about
  • 00:08: sensitivity analysis
  • 00:10: in python this is part of our lecture on
  • 00:13: exploring the parameter space
  • 00:17: so we left off last time we had gone
  • 00:20: through some
  • 00:21: additional python basics that we were
  • 00:23: going to need to be able to carry out
  • 00:26: sensitivity analysis in python i was on
  • 00:30: list comprehensions dictionaries
  • 00:32: installing packages
  • 00:34: and now we're going to go ahead and
  • 00:36: actually implement sensitivity analysis
  • 00:40: so for sensitivity analysis in python
  • 00:43: we're looking at
  • 00:45: two main kinds of ways that we can
  • 00:47: visualize the output
  • 00:49: so the new one which is different from
  • 00:52: what we're able to do in excel
  • 00:53: is this hex bin plot that you see here
  • 00:56: and this is analogous to the conditional
  • 00:59: formatting
  • 01:00: on a table in excel only in graphical
  • 01:03: form
  • 01:04: so here uh it makes the regions
  • 01:08: of this two-dimensional area
  • 01:10: corresponding to the value of the
  • 01:12: outcome
  • 01:13: so you have your two different inputs on
  • 01:15: the two different axes
  • 01:16: and then your outcome is the color
  • 01:19: um and so here high years to retirement
  • 01:22: is red
  • 01:24: low years to retirement is green and
  • 01:25: getting darker green
  • 01:27: the more that it decreases so we can see
  • 01:30: clearly from this graph that
  • 01:33: as savings rate increases and as the
  • 01:35: person gets promoted more often
  • 01:37: then they're going to be able to retire
  • 01:38: sooner
  • 01:42: the other main output that we have is
  • 01:45: exactly what we have in excel which is a
  • 01:47: table with conditional formatting
  • 01:49: applied to it
  • 01:51: so this is showing the same information
  • 01:54: as the hexton plot only with each of the
  • 01:58: numbers
  • 01:58: in there as well uh so it's mostly a
  • 02:01: personal preference
  • 02:03: uh with which one you want to go with
  • 02:05: but these are the two main ways to
  • 02:08: look at the two inputs at once with
  • 02:10: sensitivity analysis and
  • 02:12: visualize that of course with one way
  • 02:14: then you can just plot that
  • 02:16: with a typical line plot
  • 02:20: so the process to carry out sensitivity
  • 02:23: analysis and python
  • 02:26: if you don't want to use any packages
  • 02:27: you just want to use pure python
  • 02:30: then it's basically you do a loop
  • 02:33: over each input that you want to
  • 02:36: examine so you might say i want to look
  • 02:39: at
  • 02:40: uh 30 40 50 savings rates
  • 02:44: and so it'd be like four save rate in
  • 02:47: 30 40 50 in a list um
  • 02:50: and then you run the model with uh each
  • 02:53: of those inputs
  • 02:54: passed in collect the results keep them
  • 02:57: associated
  • 02:58: with which inputs are related to those
  • 03:00: outputs
  • 03:01: and then put it all together to
  • 03:03: visualize
  • 03:06: um so then if you have more than one
  • 03:09: input
  • 03:10: you just go ahead and do additional
  • 03:12: loops and nest those loops
  • 03:14: within each other so for save rate and
  • 03:17: savings rates for
  • 03:18: uh number of promotions in
  • 03:21: uh you know two three four five
  • 03:25: something like that nested under each
  • 03:28: other
  • 03:29: and then nested under all the loops is
  • 03:32: where you actually run your model
  • 03:34: with each of those inputs again collect
  • 03:36: the outputs associate them with the
  • 03:38: inputs and then
  • 03:39: visualize it
  • 03:42: um then you know you start to look up
  • 03:45: more
  • 03:46: than two or three inputs at once and all
  • 03:47: of a sudden you're nested nested nested
  • 03:49: more and more and all these loops
  • 03:51: um and that can be pretty messy um
  • 03:55: so there is a way to resolve that there
  • 03:57: is a
  • 03:58: python has a built-in package called
  • 04:01: intertools
  • 04:02: tools for iteration which goes a little
  • 04:05: bit beyond
  • 04:06: just what the base language does
  • 04:10: and one of those basically allows you to
  • 04:13: do
  • 04:13: like a nested for loop but with only a
  • 04:16: single line of code so that's what this
  • 04:18: editor tools product is
  • 04:20: um and so you can use that to then
  • 04:23: collapse however many loops you would
  • 04:25: have onto one line um
  • 04:28: but then it's a little more difficult to
  • 04:30: understand what's going on there
  • 04:34: so i would if you're sticking with
  • 04:37: this approach for sensitivity analysis
  • 04:39: and we'll talk in a minute
  • 04:41: about a package we can use that makes
  • 04:43: all this much easier
  • 04:45: but with the pure python approach i
  • 04:47: would say two or three inputs at once
  • 04:49: just write out in the individual loops
  • 04:52: as you get more than that
  • 04:53: then you should consider using
  • 04:55: intertools.product
  • 04:57: as a replacement for the nested loops
  • 05:02: so here's an example of what that
  • 05:05: looks like the code that can make
  • 05:07: sensitivity analysis happen
  • 05:10: with just base python so
  • 05:13: here we're saying that we have a
  • 05:15: function called model and that's
  • 05:17: the function which runs our entire model
  • 05:20: so it takes the inputs
  • 05:21: and then it spits out the result of
  • 05:24: running the model
  • 05:25: so that can be you know calculating the
  • 05:27: years to retirement from the savings
  • 05:29: rate investment rate etc
  • 05:30: or any other model that you could
  • 05:32: possibly imagine
  • 05:35: as long as you can you can always
  • 05:37: represent the model as a function
  • 05:39: uh converting inputs to outputs and so
  • 05:42: if you do that
  • 05:43: then you can fit it into this structure
  • 05:44: just fine
  • 05:47: so we have two different inputs we're
  • 05:49: trying to examine here input one input
  • 05:51: two
  • 05:52: and for each of those we have two
  • 05:54: different values of
  • 05:56: the inputs that we wanna look at so for
  • 05:57: input one we wanna look at one and two
  • 06:00: input two we wanna look at four and five
  • 06:03: we set up a list to store all the
  • 06:05: results and then here we have the nested
  • 06:08: loop
  • 06:08: so we're going through each of these
  • 06:10: input lists getting an input
  • 06:12: out of each one and then within all the
  • 06:15: loops
  • 06:15: calling the model with each of the
  • 06:18: inputs then we get the result
  • 06:21: from the model and we associate the
  • 06:24: uh inputs with the output in the result
  • 06:28: here by creating a list of tuples
  • 06:31: where each tuple has everything grouped
  • 06:33: together
  • 06:35: then we create a data frame from that
  • 06:38: list of tuples
  • 06:39: and we can see the results of the
  • 06:41: sensitivity analysis here
  • 06:43: in the data frame of course this is not
  • 06:46: doing any visualization yet
  • 06:48: that part is going to be added on after
  • 06:50: this
  • 06:54: um so this
  • 06:58: was kind of the process which is out
  • 07:02: there
  • 07:02: this is what people are doing right now
  • 07:04: in general
  • 07:06: um and i thought that there should be a
  • 07:08: good package
  • 07:09: which makes this process easier
  • 07:12: especially
  • 07:13: you know not only doing this but then
  • 07:14: taking the result and visualizing it as
  • 07:16: well
  • 07:20: but i really couldn't find any tool out
  • 07:23: there which
  • 07:24: was built for this purpose
  • 07:27: i think a lot of that reason is because
  • 07:31: certainly a lot of financial
  • 07:34: institutions
  • 07:35: are already using python and they're
  • 07:37: building models out in python
  • 07:40: but for the most part these institutions
  • 07:44: are not going to be open sourcing their
  • 07:47: code they're just going to be keeping it
  • 07:49: within the company as their own
  • 07:51: intellectual property
  • 07:53: uh they want to have the rights to it
  • 07:55: and not anyone else
  • 07:56: and so i think there have been a lot of
  • 07:59: these tools created
  • 08:02: but they're just not out there for
  • 08:03: anyone to use they're within these
  • 08:05: banks and financial institutions that
  • 08:08: keep a close
  • 08:09: guard on the tools that they've
  • 08:10: developed
  • 08:13: so it really takes uh you know someone
  • 08:17: who both has the knowledge and uh
  • 08:21: is willing to be able to contribute
  • 08:24: to create an open source package without
  • 08:27: a lot
  • 08:28: of immediate benefit from it so
  • 08:31: a professor teaching a financial
  • 08:33: modeling course
  • 08:34: is kind of the ideal person to do that
  • 08:39: so and you know unlike in excel
  • 08:43: you can write add-ons for excel but
  • 08:45: that's kind of heavy weight
  • 08:47: um and in general people just use excel
  • 08:50: as is
  • 08:52: in python you have the base language but
  • 08:54: then you have all these additional 250
  • 08:57: 000
  • 08:57: packages open source packages which have
  • 08:59: been created to extend the functionality
  • 09:01: of python
  • 09:02: and it's really easy for anyone to
  • 09:05: create a package
  • 09:07: and contribute to the ecosystem create a
  • 09:10: tool that solves a problem
  • 09:12: so that nobody else has to continue
  • 09:14: solving the same problem in their own
  • 09:16: work
  • 09:18: so i went ahead and created the
  • 09:20: sensitivity package
  • 09:22: in python which simplifies this whole
  • 09:25: flow as well as the visualization
  • 09:27: of the results and makes this whole
  • 09:30: thing
  • 09:30: very easy so i took the time
  • 09:34: to kind of solve this once in a general
  • 09:36: way and now everyone in the world
  • 09:38: can benefit from my efforts
  • 09:42: so that is really uh the big power of
  • 09:45: python that anyone in the world can
  • 09:47: contribute and it can make everyone else
  • 09:49: and the world
  • 09:50: more productive so everyone's not
  • 09:53: reinventing the wheel all the time
  • 09:57: so let's look at an example with
  • 10:00: the sensitivity package
  • 10:03: so from sensitivity we're going to
  • 10:05: import sensitivity analyzer that's the
  • 10:08: main class which
  • 10:09: handles all this and then you create a
  • 10:12: dictionary
  • 10:14: where the keys of the dictionaries are
  • 10:15: the names of your
  • 10:17: inputs the arguments to the function
  • 10:19: your model function
  • 10:21: and the values are what
  • 10:24: each individual values of the inputs you
  • 10:28: want to look at
  • 10:28: so one and two for input one 4 and 5 for
  • 10:32: input 2.
  • 10:34: then you pass to sensitivity analyzer
  • 10:37: that dictionary of the inputs
  • 10:40: and your model function and that creates
  • 10:43: an instance of the sensitivity analyzer
  • 10:46: and then the df data frame
  • 10:50: attribute of the sensitivity analyzer
  • 10:52: already has the results
  • 10:54: of doing this nested loop
  • 10:57: and collecting all the results and
  • 10:59: everything that have been done here
  • 11:01: and we'll see in a minute here in the
  • 11:03: example that is also
  • 11:04: similarly easy to visualize all the
  • 11:07: results as well
  • 11:10: so let's go ahead and look at the
  • 11:13: jupiter example
  • 11:14: for all of this
  • 11:18: so the first thing that we're going to
  • 11:19: do is
  • 11:21: install the sensitivity package
  • 11:25: and so in this is something that you
  • 11:27: would run in a terminal but jupiter has
  • 11:29: this shortcut
  • 11:30: uh as mentioned in the video on
  • 11:32: installing packages
  • 11:34: that uh you put the exclamation mark
  • 11:36: that means run it
  • 11:37: in a terminal in the background and then
  • 11:39: we want to do pip install
  • 11:41: sensitivity and i'm going to go ahead
  • 11:44: and add in
  • 11:44: upgrade because i already have it
  • 11:47: installed and i know that i've released
  • 11:49: some updates for the package and i want
  • 11:51: to have all those updates here
  • 11:53: so i'm going to run that and it's going
  • 11:54: to look like it's doing nothing for a
  • 11:56: little bit and then eventually
  • 11:57: it will pop out all the output from the
  • 11:59: result
  • 12:00: as we see now and we can see
  • 12:05: that it successfully installed
  • 12:08: sensitivity
  • 12:10: as of making this video 0.2.5 is the
  • 12:12: current
  • 12:13: version um you may just get
  • 12:16: requirement already satisfied for
  • 12:18: everything if you already have the
  • 12:20: newest version
  • 12:22: um and then if you run that first you
  • 12:25: don't really have to do this step but
  • 12:26: i'm just going to go ahead and
  • 12:27: restart the kernel for good measure
  • 12:31: so now let's uh go through
  • 12:35: what the process looks like kind of the
  • 12:38: original way without the sensitivity
  • 12:39: package
  • 12:40: and then we'll go into how to use the
  • 12:42: sensitivity package
  • 12:45: um so i'm going to import pandas
  • 12:48: that we'll use for collecting the
  • 12:49: results and i'm defining the model
  • 12:52: function so again this can be absolutely
  • 12:55: anything
  • 12:56: it can be your full financial model
  • 12:59: here we're just taking one number to the
  • 13:02: power of another number
  • 13:03: it really doesn't matter what happens
  • 13:05: inside of here that's the beauty of
  • 13:07: using
  • 13:07: functions we can plug whatever
  • 13:11: functionality
  • 13:11: we want into this structure and it works
  • 13:14: exactly the same
  • 13:17: so when i run the model i can get a
  • 13:21: result from it
  • 13:24: so then if we want to look at three
  • 13:26: different values for x1 three different
  • 13:28: values for x2
  • 13:31: then when we look at the nested loop we
  • 13:33: can see
  • 13:35: that we get basically each combination
  • 13:38: each pairwise combination of the inputs
  • 13:43: so we get nine total cases from three
  • 13:47: cases for each
  • 13:50: then we can add in calculating the model
  • 13:53: running the model
  • 13:55: um so that's just calling the model
  • 13:57: function
  • 13:58: on the inputs from the loops
  • 14:01: and then uh getting the result and here
  • 14:04: we're just going to print out the result
  • 14:05: as the next step
  • 14:08: um and then after that let's collect the
  • 14:12: results
  • 14:13: so taking the same loop but now adding
  • 14:16: to it that
  • 14:17: instead of just printing the result i'm
  • 14:19: going to have an output list
  • 14:21: and i'm going to append to that a tuple
  • 14:25: which contains
  • 14:26: each of the inputs as well as the output
  • 14:29: and then we can see that we have each
  • 14:31: pair of inputs
  • 14:32: associated with the output
  • 14:39: then we can put that into a data frame
  • 14:42: so if we give a data frame a list of
  • 14:44: tuples and then the names of the columns
  • 14:46: it's able to create a data frame from
  • 14:48: that
  • 14:52: and then we can add some styling
  • 14:55: about the result so here i'm adding a
  • 14:59: red yellow green color map
  • 15:01: um to the y column the output column
  • 15:04: uh which is now showing the high results
  • 15:08: in green
  • 15:08: and the low results in red
  • 15:13: then the other way to go about it is to
  • 15:15: use a hexman plot
  • 15:17: um so that's also
  • 15:21: off of df.plot just like we had done for
  • 15:24: all the other plots with pandas
  • 15:27: and you give it x and y as your two
  • 15:31: input variables and then
  • 15:35: c that stands for color
  • 15:38: is going to be determined by the outcome
  • 15:40: variable
  • 15:42: and then this grid size says
  • 15:45: going in each direction how many um
  • 15:49: like blocks should there be this is like
  • 15:52: three by three
  • 15:53: blocks in the graph
  • 15:57: again we pass that color map
  • 16:00: red yellow green um
  • 16:03: and then this share x equals false
  • 16:07: makes all the formatting work correctly
  • 16:11: um so that's without the library
  • 16:15: and then with these color maps you can
  • 16:17: do underscore r
  • 16:19: to reverse the color map
  • 16:22: if it turns out that a low number of the
  • 16:25: result is a better thing
  • 16:26: like years to retirement we want to
  • 16:28: retire quicker so there you would want
  • 16:29: the reverse
  • 16:30: red yellow green color map
  • 16:34: but all this is a little bit involved
  • 16:36: it's not super complicated but
  • 16:37: there's a fair number of steps here so
  • 16:40: the sensitivity
  • 16:41: uh package is going to make this all
  • 16:43: easier
  • 16:44: so with the sensitivity package we set
  • 16:47: up that
  • 16:48: dictionary of the inputs and then we
  • 16:51: create
  • 16:52: the sensitivity analyzer
  • 16:55: and we pass to the sensitivity analyzer
  • 16:59: that dictionary as well as the model
  • 17:02: function
  • 17:03: and notice that there's no open close
  • 17:04: parenthesis here
  • 17:06: that's because we're passing the model
  • 17:09: function
  • 17:10: itself and not the result
  • 17:13: of calling the model function as soon as
  • 17:16: you put the parenthesis it's going to
  • 17:17: call it evaluate it return the result
  • 17:20: we want to pass the function itself so
  • 17:23: that sensitivity analyzer can use this
  • 17:25: function
  • 17:26: that we're passing to it
  • 17:30: um so you run sensitivity analyzer and
  • 17:33: you'll see
  • 17:33: this progress far go by here the model
  • 17:36: didn't take any time so it basically
  • 17:38: filled up immediately
  • 17:39: um 450 iterations per second
  • 17:43: um and you'll see a random nine
  • 17:45: iterations in total because we have
  • 17:47: three times three
  • 17:48: uh cases of inputs
  • 17:51: um so you know there's definitely a
  • 17:55: chance that you can
  • 17:56: put too many inputs here and you get a
  • 17:58: really huge number of cases
  • 18:00: and then you'll see this thing just
  • 18:01: taking forever and then you should
  • 18:02: reevaluate how many inputs you want to
  • 18:04: look at
  • 18:08: so then we've run sensitivity analyzer
  • 18:13: now we can get that same exact
  • 18:17: data frame which we had seen before but
  • 18:19: just it's already there
  • 18:21: ready for us we didn't have to go and
  • 18:23: calculate it
  • 18:25: and then for the plots
  • 18:29: we just do sa.plot and then we have that
  • 18:32: hexman plot
  • 18:33: easy as that and we can also get these
  • 18:38: styled data frames
  • 18:40: by doing sa.style dfs
  • 18:44: and that is going to give you the data
  • 18:46: frame
  • 18:47: with um conditional formatting applied
  • 18:50: to it
  • 18:52: and there are options that you can apply
  • 18:55: to
  • 18:56: the sensitivity analyzer as well to
  • 18:57: customize the output
  • 19:00: and so i'm going to do a few different
  • 19:03: things here
  • 19:05: so i'm going to give it some labels so
  • 19:07: that it'll change out x1 x2 for
  • 19:10: whatever names i want to call the inputs
  • 19:14: i'm going to pass grid size of three so
  • 19:16: that it makes larger
  • 19:18: blocks here reverse colors that was like
  • 19:22: adding underscore r
  • 19:23: to the color wrap before it just flips
  • 19:25: the color map
  • 19:27: then you can also pass a custom color
  • 19:29: map
  • 19:31: and if you want to know what are all the
  • 19:36: color maps you can use just google map
  • 19:38: plot lib color maps
  • 19:40: um that will take you to choosing color
  • 19:42: maps in matplotlib
  • 19:45: and you'll see all these different ones
  • 19:47: that you can pick
  • 19:50: so all these names on the left are
  • 19:52: things that you can pass
  • 19:54: to color map to get a different color
  • 19:56: map
  • 19:58: um and then uh
  • 20:01: yep that's all the options so then i'm
  • 20:04: going to run this and then plot and now
  • 20:06: we can see
  • 20:07: it has a large grid size it has the new
  • 20:09: color map it's reversed the color map
  • 20:11: and we see the labels coming in instead
  • 20:14: of the
  • 20:14: actual names of the arguments
  • 20:18: and we see that on the
  • 20:23: data frames as well
  • 20:26: um and
  • 20:30: the really beautiful thing about this
  • 20:32: library is you can keep adding more
  • 20:34: inputs
  • 20:34: that you're looking at and you really
  • 20:37: don't have to change your code
  • 20:39: at all it works in the exact same
  • 20:40: structure
  • 20:43: so here we have a second model it's got
  • 20:45: three inputs this time
  • 20:47: and now we've got our dictionary which
  • 20:50: has the three different
  • 20:52: inputs um and three different values of
  • 20:55: each
  • 20:56: so we run that this time we can see it
  • 20:58: ran 27 different
  • 21:00: cases three times three times three um
  • 21:04: and what we see when we plot it is that
  • 21:07: now we get
  • 21:08: three different plots all at once
  • 21:10: without having to do any extra effort
  • 21:12: we get x1 versus x2 we get x1 versus
  • 21:16: x3 and we get x2 versus x3 so we get all
  • 21:19: the different combinations of the
  • 21:21: different inputs
  • 21:22: and the relationships between them
  • 21:25: so really easy to run a lot of different
  • 21:27: inputs and visualize it all at once with
  • 21:30: just a couple lines of code
  • 21:33: and then we'll see the same thing with
  • 21:35: the style data frames
  • 21:37: um we'll get one verse two one verse
  • 21:41: three two verse three and as you
  • 21:43: continue to add more
  • 21:44: inputs you'll get all those combinations
  • 21:46: so it can become
  • 21:47: a lot of output really quickly
  • 21:51: um and if you need to look up
  • 21:54: any so this style data frames you can
  • 21:57: see i saved it into styled
  • 21:59: predict it does automatically print out
  • 22:02: the results
  • 22:03: even if you save it into a variable
  • 22:08: you'll see what we have here is actually
  • 22:10: a dictionary
  • 22:12: where the keys are tuples
  • 22:17: and the values are the style data frames
  • 22:20: so you can also look up
  • 22:22: reference any of the individual results
  • 22:25: that you want to
  • 22:26: look at
  • 22:32: so we can also do some additional
  • 22:34: styling
  • 22:36: we can change the number formatting of
  • 22:38: the results as well
  • 22:40: and you can pass this in either when you
  • 22:42: create the sensitivity
  • 22:43: analyzer at the beginning or to the
  • 22:46: style dfs
  • 22:49: command you can pass the number format
  • 22:52: and this number format works exactly the
  • 22:54: same as the
  • 22:55: pandas number formatting uh that we
  • 22:57: learned from the styling
  • 22:59: penis data frames lecture
  • 23:02: um where you basically put the same kind
  • 23:04: of string
  • 23:06: as like an f uh only you don't put the
  • 23:09: variable here
  • 23:10: you just put nothing there and then a
  • 23:11: colon and then the format
  • 23:13: code so you can see this is doing
  • 23:15: dollars and then
  • 23:16: uh formatted with commas and zero
  • 23:19: decimal places
  • 23:20: and we see that all coming here as well
  • 23:27: so that covers the introduction to
  • 23:30: sensitivity analysis
  • 23:31: in python we'll come back next time to
  • 23:35: add the sensitivity analysis into our
  • 23:37: existing dynamic salary retirement
  • 23:39: model so thanks for listening and see
  • 23:42: you next time
| Sensitivity Analysis in Python Example ========================================= .. youtube:: 7vACMHmUjYY :height: 315 :width: 80% :align: center | Notes -------- - Here we will focus only on using the sensitivity package rather than carrying everything out manually - We need to go back and add an optional argument to the model about whether it should print the results, otherwise we will have the results printed a huge number of times as we run the sensitivity analysis - The sensitivity package is made to work with functions where each input is passed separately, whereas our model function takes a single dataclass instance. To make our model function work with the sensitivity package, we need to create a wrapper function which takes the separate arguments, creates the dataclass from them, passes that into the model function and returns the result. You can copy my snippet to do this with your model. - List comprehensions are a nice easy way to specify values in a range, but you can also hard-code these lists - Be careful not to look at too many input values as execution could be very slow. The progress bar will tell you how many cases of the model you are running and show how long it is taking. - There are a number of options to customize the output from the library. You can change the names of the inputs and results, the color map, change direction of the colors, the grid size on the hexbin plots, and the number formatting in styled DataFrames. Resources ------------ - :download:`Dynamic Salary Retirement Model - Python ` Transcript ------------- .. raw:: html
  • 00:02: hey everyone
  • 00:03: nick diabetis here teaching you
  • 00:04: financial modeling today
  • 00:06: we're going to be looking at an example
  • 00:09: of adding sensitivity analysis
  • 00:11: to an existing model this is part of our
  • 00:14: segment
  • 00:15: on exploring the parameter space
  • 00:19: so we left off last time having done
  • 00:22: an introduction on sensitivity analysis
  • 00:25: in python and looked at some of the
  • 00:27: different outputs we were going to
  • 00:28: produce and approaches
  • 00:30: we could use and now we're coming to
  • 00:33: actually apply that to our existing
  • 00:35: dynamic salary retirement
  • 00:37: model so let's go ahead and jump over to
  • 00:41: that model
  • 00:42: so we can build this extension to the
  • 00:45: model out
  • 00:47: and you can find the um completed
  • 00:51: extension from this exercise on the
  • 00:54: course site
  • 00:55: and i would recommend that you take a
  • 00:57: look at that
  • 00:58: completed example as you go to
  • 01:02: work the lab exercise for this and to
  • 01:04: add sensitivity analysis to your own
  • 01:06: models in the future so
  • 01:12: um we're gonna add sensitivity analysis
  • 01:15: so we can go ahead
  • 01:16: and make that as an additional section
  • 01:19: down here
  • 01:19: sensitivity analysis
  • 01:26: um and you would want to put a
  • 01:28: description of
  • 01:29: what you're going to be analyzing why
  • 01:31: what are the takeaways
  • 01:32: um but i'm going to leave that out for
  • 01:35: now for a second time
  • 01:38: um and
  • 01:41: i know that i'm going to need to use the
  • 01:43: sensitivity analyzer so i'm going to go
  • 01:45: ahead
  • 01:45: and add that import up here
  • 01:49: from sensitivity import
  • 01:52: sensitivity analyzer um
  • 01:55: sometimes yep if you tab complete
  • 01:57: sometimes they will tap complete it for
  • 01:59: you so that
  • 02:00: worked out for me then i'm going to
  • 02:04: restart kernel
  • 02:05: and run all cells so that we have
  • 02:07: everything from the model
  • 02:09: defined and then can just work with it
  • 02:10: below for the sensitivity
  • 02:12: analysis
  • 02:15: um now
  • 02:19: we're ready to start building out the
  • 02:21: sensitivity analysis
  • 02:22: but one thing that you may notice about
  • 02:25: my existing model function used to
  • 02:27: retirement
  • 02:28: is when i call it it prints out
  • 02:32: output and when we go to do sensitivity
  • 02:35: analysis
  • 02:36: basically this function is going to get
  • 02:38: right a bunch of times
  • 02:40: with different inputs and
  • 02:44: um we're going to see that
  • 02:47: doing that without any changes we would
  • 02:50: get this whole print output
  • 02:52: for as many times as we're running the
  • 02:53: model and we could be running the model
  • 02:55: thousands of times
  • 02:57: so we don't want to get thousands of
  • 02:59: copies of this
  • 03:00: print output for the different output
  • 03:03: cases
  • 03:04: we're already going to be storing the
  • 03:05: main output that we want to look at
  • 03:07: separately so before we can even add the
  • 03:09: sensitivity analysis
  • 03:11: i'm going to go back and make a
  • 03:13: modification to the existing model
  • 03:16: to make it optional whether it prints
  • 03:18: out
  • 03:19: the results um
  • 03:22: so we've already talked about um
  • 03:26: optional arguments before
  • 03:29: we can add an optional argument here uh
  • 03:32: print output equals false so it defaults
  • 03:36: to it should not print any output
  • 03:39: and now i'm just going to go to each of
  • 03:41: the print statements and say if print
  • 03:42: output
  • 03:45: then it's going to print otherwise it's
  • 03:47: not going to print
  • 03:49: so i'm just going to do the same thing
  • 03:52: uh with each of these
  • 04:01: and i'm going to rerun that to redefine
  • 04:03: that function
  • 04:06: and now you'll see that when i run this
  • 04:09: i don't get
  • 04:09: any output there i just have the final
  • 04:12: answer
  • 04:12: storm and the variable well with this
  • 04:15: usage we do actually want to
  • 04:17: print the output so i'm going to put
  • 04:19: print output equals true
  • 04:21: and now we're back to exactly what we
  • 04:23: had before for the original model
  • 04:26: but we're also able to call the model
  • 04:29: without producing all that print output
  • 04:32: which is what we're going to need
  • 04:33: to go into sensitivity analysis
  • 04:37: so now the model is ready for us to go
  • 04:40: and add sensitivity analysis
  • 04:45: so now we want to use the sensitivity
  • 04:47: analyzer
  • 04:50: but there's one other thing we have to
  • 04:53: do
  • 04:54: to prepare the model function
  • 04:58: before we can pass it to the sensitivity
  • 05:00: analyzer
  • 05:01: the sensitivity analyzer is expecting to
  • 05:04: be able to pass
  • 05:04: each argument separately to the function
  • 05:07: but the way that we structure our models
  • 05:09: is we use a data class
  • 05:11: we pass only a single data class into
  • 05:13: the function
  • 05:14: and not each of the separate arguments
  • 05:17: so we have to create a function
  • 05:19: that will take the separate arguments
  • 05:21: construct the data class from those
  • 05:23: arguments
  • 05:24: and then pass the data class into the
  • 05:27: function
  • 05:28: and return the result of that function
  • 05:31: so that it's basically a wrapper
  • 05:32: around the model function which allows
  • 05:34: it to take the input separately
  • 05:36: rather than as a data class so
  • 05:39: we can write that function so i'm going
  • 05:41: to call that year's retirement
  • 05:45: separate args
  • 05:49: and i'll come back to the arguments
  • 05:50: section in a moment
  • 05:52: um and then what we're going to do is
  • 05:55: we're going to
  • 05:57: create an instance of model inputs i'll
  • 06:00: also
  • 06:00: come back to this in a moment and then
  • 06:03: we're going to return
  • 06:05: calling the original years retirement
  • 06:07: function
  • 06:08: on that data
  • 06:12: now what we're going to do for the
  • 06:14: arguments themselves
  • 06:16: there's actually a shortcut in python
  • 06:19: which just says
  • 06:20: let me take any number of keyword
  • 06:23: arguments
  • 06:24: keyword being where you say like
  • 06:26: starting salary equals
  • 06:28: ten thousand or uh promo raise equals
  • 06:31: five percent so we can take any number
  • 06:34: of those
  • 06:36: and then it will just take all those and
  • 06:38: be able to pass them into the model
  • 06:39: inputs
  • 06:40: so that um shortcut
  • 06:44: here is a star star
  • 06:48: on a variable name and the convention is
  • 06:50: to do star star
  • 06:52: quarks so that just says any number of
  • 06:55: keyword arguments
  • 06:56: it's going to take those and it's going
  • 06:58: to put them into a dictionary
  • 06:59: coming into the function you have a
  • 07:01: quarks dictionary
  • 07:03: um so let me just print that to make
  • 07:06: that clear
  • 07:09: and then doing it again here it spreads
  • 07:10: it back out into
  • 07:12: the keyword arguments so this will take
  • 07:15: keyword arguments and collect them into
  • 07:16: a dictionary
  • 07:17: and then this will take that dictionary
  • 07:19: and spread it back out into the keyword
  • 07:22: arguments
  • 07:23: um so not expecting everyone to fully
  • 07:26: understand what's going on there
  • 07:28: you don't have to understand it you can
  • 07:31: just copy my code snippet and
  • 07:33: change out the model function
  • 07:36: and the name of the function and you'll
  • 07:38: be good to go to use the sensitivity
  • 07:40: analyzer
  • 07:42: so to show what this is doing i'm going
  • 07:44: to call this and i'm going to say
  • 07:46: starting salary equals 10 000
  • 07:50: and you'll see from the print output
  • 07:53: that it
  • 07:55: prints out the
  • 07:59: starting salary in a dictionary
  • 08:02: with this as the value and
  • 08:07: you can add other arguments here 30
  • 08:09: promotion raise
  • 08:11: we can see that also comes into the
  • 08:13: dictionary
  • 08:16: and then we ultimately get the result
  • 08:20: from that
  • 08:25: so
  • 08:29: this is our wrapper for the function
  • 08:33: which then is able to
  • 08:37: call the model and return the result
  • 08:49: so now that we have that working
  • 08:54: then we can go on to
  • 08:58: the next step which is to actually uh
  • 09:01: use the sensitivity analyzer
  • 09:05: um that's something weird is going on
  • 09:09: here because no matter what
  • 09:10: inputs i'm putting i'm still getting uh
  • 09:13: 28 years to
  • 09:14: retirement um
  • 09:24: oh yeah i see the mistake here uh here
  • 09:27: and a lot of people may make these
  • 09:28: mistakes in their own models
  • 09:30: um here data was being passed to the
  • 09:33: function but here i used
  • 09:34: model data so it wasn't actually able to
  • 09:36: pick up the data which is being passed
  • 09:38: to the function it was just using the
  • 09:40: overall model data each time
  • 09:42: and so i'm going to make sure that that
  • 09:45: matches up with the function argument
  • 09:48: and now i'm going to restart and run
  • 09:51: this thing
  • 09:52: all again and now we should see a number
  • 09:55: other than 28 come up here hopefully
  • 09:59: yeah there we go now it's actually
  • 10:01: working if you make a million dollars
  • 10:03: off the bat then you'll be able to
  • 10:04: retire in only five years
  • 10:09: okay and then back without passing any
  • 10:12: arguments we're back to 28 so it looks
  • 10:14: like this is all working properly now
  • 10:19: um so next we want to create that
  • 10:22: dictionary
  • 10:23: of the inputs that we want to change
  • 10:26: around
  • 10:27: so i'm going to start it out simple and
  • 10:29: we'll expand on this
  • 10:31: so sensitivity values um so let me just
  • 10:34: look at starting salary
  • 10:37: let me look at you know as low as 40
  • 10:41: 000 or as high as
  • 10:45: a hundred and twenty thousand and then
  • 10:48: let's look at the interest rate
  • 10:53: um and let's look at
  • 10:56: a three percent rate and a ten percent
  • 10:59: rate
  • 11:04: so then we have everything that we need
  • 11:06: to go ahead and run the sensitivity
  • 11:08: analyzer
  • 11:09: so then i'm going to create an instance
  • 11:12: of the sensitivity analyzer
  • 11:15: i'm going to pass it the sensitivity
  • 11:18: values
  • 11:20: and i'm going to pass it the model
  • 11:22: function
  • 11:23: the one that takes the separate
  • 11:25: arguments
  • 11:27: so then we see that it ran four
  • 11:29: different input cases here
  • 11:32: two times two and
  • 11:35: now we can look at the results so we can
  • 11:37: look at the full result
  • 11:38: data frame there each of the pairwise
  • 11:42: combinations
  • 11:42: and the user retirement
  • 11:46: um and we can
  • 11:49: create the resulting
  • 11:52: hexman plot
  • 11:56: and then we can um
  • 12:01: create the style data frames
  • 12:08: here just a single data frame for now
  • 12:12: um so that's pretty much what you would
  • 12:13: want to be seeing from sensitivity
  • 12:15: analysis as well as
  • 12:16: you know some description of the results
  • 12:19: that you found
  • 12:20: at the end um but there's a fair amount
  • 12:25: we can do here
  • 12:26: to clean things up and to make them more
  • 12:29: comprehensive
  • 12:31: so first thing is we can pass some
  • 12:34: additional options to sensitivity
  • 12:36: analyzer to clean up the output
  • 12:41: so some of those additional options
  • 12:44: would be
  • 12:46: that we want to
  • 12:49: label the results so we can do result
  • 12:52: name equals years to retirement because
  • 12:54: we can see right now it's just coming as
  • 12:56: result
  • 12:58: uh result
  • 13:01: result but we put years to retirement
  • 13:04: here as a result name and then we get
  • 13:07: uh years retirement years for retirement
  • 13:10: here's to retirement
  • 13:15: um and then we'll notice that
  • 13:18: right now it's highlighting the high
  • 13:20: years to retirement as bringing in the
  • 13:22: low
  • 13:23: as red that's the opposite of what we
  • 13:25: want
  • 13:26: so we want to reverse uh
  • 13:29: the colors reverse colors equals true
  • 13:34: um and then with that we will see
  • 13:37: um that now it's showing red for the
  • 13:42: high year's retirement that's bad we
  • 13:43: want to retire sooner
  • 13:47: um you'll notice that this grid is very
  • 13:50: sparse
  • 13:51: um so i'm going to pass a
  • 13:55: grid size of three and then you'll see
  • 13:59: now this will get more filled out as we
  • 14:01: add more inputs here in a moment but
  • 14:03: i think this makes more sense um
  • 14:07: for these data um
  • 14:10: and the other thing that we'll want to
  • 14:12: do is add some labels
  • 14:15: as well and it has to match up the keys
  • 14:19: match up again with the input names
  • 14:23: and then the values would be how you
  • 14:25: want it to look in the output so
  • 14:27: interest rate interest rate
  • 14:31: and then we can pass labels equals
  • 14:34: labels
  • 14:36: and we run these again now we can see in
  • 14:39: all the output
  • 14:39: that we're now getting the labels
  • 14:43: as well so it's starting to look clean
  • 14:47: um and the last thing we can do
  • 14:51: is add a number format um
  • 14:54: so here's your retirement not a currency
  • 14:57: we don't want a dollar sign
  • 15:01: and we can just have zero decimal places
  • 15:07: so then um we'll see now
  • 15:10: in the style data frames that we have no
  • 15:12: decimal places
  • 15:14: on the output
  • 15:19: so that looks good as far as the
  • 15:21: formatting
  • 15:22: options for the output now
  • 15:26: let's look at some more values of the
  • 15:28: inputs and look at more inputs
  • 15:32: so it can get tedious to type out all
  • 15:35: the different values that you might want
  • 15:36: to
  • 15:37: look at so that's why i like to use
  • 15:40: list comprehensions to uh write out the
  • 15:44: outputs
  • 15:45: so um if we want to look at
  • 15:49: um salaries and the range of
  • 15:52: say forty thousand to uh seventy
  • 15:56: thousand
  • 15:57: what we can do is uh
  • 16:03: we can just do a simple for i and range
  • 16:05: loop
  • 16:06: and multiply the result
  • 16:09: by ten thousand you know without the ten
  • 16:11: thousand it would be
  • 16:12: four five six seven then we just
  • 16:14: multiply it by ten thousand
  • 16:16: and then we have that range of salaries
  • 16:19: so i'm gonna put that
  • 16:20: in here as the starting salary
  • 16:24: then for interest rate um
  • 16:28: here we want to look at percentages so
  • 16:30: let's divide by 100
  • 16:32: and let's look from three to six
  • 16:36: percent so i'm going to take that and
  • 16:39: put that into the interest rate
  • 16:41: um and let's look at the other inputs as
  • 16:45: well
  • 16:45: uh so promos every and years and all
  • 16:50: these things
  • 16:51: should be matching up with the
  • 16:53: attributes
  • 16:54: on the model data
  • 16:58: so promos every n years
  • 17:02: let's look at um in the range
  • 17:06: of um
  • 17:09: how about from four to seven years
  • 17:13: uh so i'll put that there for promos
  • 17:15: everyone years
  • 17:18: um let's add cost of living raise
  • 17:23: um and cost of living raise that is
  • 17:26: another percentage we can divide by 100
  • 17:30: and let's go from a one percent to a
  • 17:32: three percent
  • 17:34: so i'm going to put that there um
  • 17:37: and we can add the promotion raise promo
  • 17:40: raise
  • 17:43: um and for that one um
  • 17:47: here we can look in increments of five
  • 17:50: percent
  • 17:50: let's look from ten percent to twenty
  • 17:52: percent in five percent increments
  • 17:54: um so let's keep that divided by a
  • 17:56: hundred since it's
  • 17:57: um a percentage and we're going to go
  • 18:01: from 10
  • 18:02: up to 25 but let's go in five
  • 18:05: steps so this is 10 15 20
  • 18:09: um of course you can write these out
  • 18:12: manually
  • 18:13: if you want just writing those numbers
  • 18:14: in
  • 18:16: but i like using the list comprehensions
  • 18:18: because it's also easy to go and adjust
  • 18:20: these ranges
  • 18:20: as well um
  • 18:24: let's see so let's also add the
  • 18:28: savings rate savings rate
  • 18:33: um and for savings rate let's go up to
  • 18:36: from 10 to 40
  • 18:38: and 10 increments um
  • 18:42: so that would be this 20 30
  • 18:48: um and let's look at the desire and cash
  • 18:54: so for desired cash um
  • 18:56: [Music]
  • 18:58: let's look at from
  • 19:01: a million dollars to 2.5 million dollars
  • 19:05: um in 500 000 increments so that's going
  • 19:09: to be uh
  • 19:10: 10 to 26 minutes of five
  • 19:13: and multiplying by a hundred thousand
  • 19:18: so that looks correct now we can take
  • 19:21: that and put that in there as well
  • 19:24: so then we have all these different
  • 19:26: values of the inputs that we want to
  • 19:28: look at
  • 19:30: um let's add their labels as well
  • 19:35: so promos every years
  • 19:41: promos every and years
  • 19:46: let's do the cost of living raise
  • 19:54: cost of living raise
  • 19:58: let's do the primaries
  • 20:02: motion rays
  • 20:06: i got interest rate already add savings
  • 20:09: rate
  • 20:12: savings rate and add desired cash
  • 20:21: okay um now we've got a bunch of
  • 20:24: different values of all these different
  • 20:25: inputs
  • 20:26: we've got all the labels we had all our
  • 20:28: options from before to make it look good
  • 20:30: let's go ahead and run this and now
  • 20:33: you'll see we have a lot more inputs
  • 20:34: that we're looking at we have 6 900
  • 20:36: different cases
  • 20:38: and now it actually takes some
  • 20:39: substantial time to run the model
  • 20:41: and we see that progress bar go by as
  • 20:44: it's running all these different input
  • 20:46: cases now it's
  • 20:48: done we look at this data frame
  • 20:51: um
  • 20:52: [Music]
  • 20:55: it's going to be
  • 20:58: [Music]
  • 21:00: you know having a lot more rows in it
  • 21:01: this time
  • 21:03: um and we should similarly see
  • 21:06: additional plots and style
  • 21:08: data frames all of this coming together
  • 21:12: um so there's a big advantage
  • 21:16: uh over excel in here in that you can
  • 21:19: pass as many possible inputs as you want
  • 21:23: you're not limited to just looking at
  • 21:24: two at once
  • 21:26: and it's going to be able to generate a
  • 21:29: lot of different results for you
  • 21:32: so now we've got
  • 21:35: we have the 6900 different runs of the
  • 21:38: model and data frame
  • 21:41: and we've got all these different
  • 21:43: combinations of the inputs
  • 21:44: and these flops so we can take any pair
  • 21:48: that we want to look at
  • 21:50: here it's all about the promotions
  • 21:51: promotional race promotions everyone
  • 21:53: years
  • 21:53: as you get quicker promotions we start
  • 21:56: to hit
  • 21:57: or sorry slower promotions than we get
  • 21:59: to longer years to retirement up to 40
  • 22:02: over here
  • 22:04: and as we get higher promotion raises
  • 22:06: then we get shorter years to retirement
  • 22:09: but we can see in the range of inputs
  • 22:11: that we're looking at
  • 22:12: it's not a very huge impact on the years
  • 22:15: to retirement
  • 22:20: so then you have the same information
  • 22:24: over here in the style
  • 22:26: data frames so you can really pick
  • 22:28: whichever one of the two
  • 22:30: you like better for showing the results
  • 22:33: you don't have to
  • 22:34: show both like i'm doing here
  • 22:38: and it would be good to at the end just
  • 22:40: put a description
  • 22:41: of your findings some of the notable
  • 22:43: things from the sensitivity analysis
  • 22:46: to kind of wrap everything together
  • 22:50: so that's adding sensitivity analysis to
  • 22:54: an existing model in python using the
  • 22:56: sensitivity
  • 22:57: package so that concludes
  • 23:01: our segment on exploring the parameter
  • 23:04: space
  • 23:05: we will examine a couple other
  • 23:07: techniques
  • 23:09: which explore the parameter space in the
  • 23:11: future lectures as well
  • 23:14: so thanks for listening and i'll see you
  • 23:16: next time
| Lab Exercise - Adding Sensitivity Analysis to Project 1 - Python =================================================================== .. youtube:: YtE5oRv2Ot4 :height: 315 :width: 80% :align: center | Notes -------- - The lab exercise here is the same as that we did for Excel but now just doing it in Python - You are free to use the manual approach or the sensitivity package but I would recommend the sensitivity package - Be sure to upgrade your sensitivity package before working on the exercise - The lecture on adding sensitivity analysis to the Python Dynamic Salary Retirement model will be very helpful for this - You may need to restructure your model before you can even begin adding sensitivity analysis. You must have a function which accepts the data and produces the final output from that data, and your functions must not access the overall model_data Resources ------------ - :download:`Dynamic Salary Retirement Model - Python ` Transcript ------------- .. raw:: html
  • 00:03: hey everyone
  • 00:04: nick dear burtis here teaching you
  • 00:05: financial modeling today we're going to
  • 00:08: be
  • 00:08: talking about the lab exercise for
  • 00:11: sensitivity analysis
  • 00:12: in python as part of the lecture series
  • 00:15: on exploring the parameter space
  • 00:18: so we left off last time we had covered
  • 00:21: all the material on sensitivity analysis
  • 00:23: in python and now we're coming here to
  • 00:26: the last slide which has the lab
  • 00:28: exercise
  • 00:29: for python sensitivity analysis
  • 00:32: and that is analogous to the exercise we
  • 00:35: completed in excel
  • 00:37: you're going to be adding sensitivity
  • 00:38: analysis to your project
  • 00:40: 1 model um
  • 00:44: and so what we just went through with
  • 00:46: adding
  • 00:47: the uh sensitivity analysis to the
  • 00:50: dynamic salary retirement model in
  • 00:52: python
  • 00:53: is going to be really useful for
  • 00:55: completing this exercise so
  • 00:56: watch that carefully and carry out some
  • 00:59: of the same steps over there
  • 01:02: now since this is working with your own
  • 01:05: model
  • 01:07: there's a good chance that your model
  • 01:09: will not have the structure
  • 01:10: required to be able to extend it in any
  • 01:13: way
  • 01:14: if you're accessing the model data
  • 01:17: directly
  • 01:18: inside your logic rather than having a
  • 01:21: function which accepts an arbitrary data
  • 01:23: and working with that arbitrary data
  • 01:26: then this is not going to work you're
  • 01:28: going to have to go back
  • 01:29: and restructure it you should never be
  • 01:32: accessing that
  • 01:35: original model data from within your
  • 01:37: functions
  • 01:39: and you should have one function where
  • 01:41: you can pass it
  • 01:42: the data class and
  • 01:46: get the result of the entire model
  • 01:50: uh the mpv and cash flows um
  • 01:55: by just running a single function so
  • 01:58: you'll need to have both of those things
  • 01:59: in place before you can even go and
  • 02:01: start
  • 02:02: on this exercise so you should
  • 02:04: definitely go back and restructure
  • 02:06: things
  • 02:07: to be able to complete this and
  • 02:10: don't just think well my model is too
  • 02:13: far gone i'll just skip this lab
  • 02:14: exercise because
  • 02:16: as we go forward in the course we're
  • 02:18: gonna have more of these similar
  • 02:19: exercises of extending project one
  • 02:22: and so you really need to to rebuild it
  • 02:25: in a way
  • 02:26: that is going to be flexible to any
  • 02:28: extensions that you can add to it
  • 02:31: and i set it up this way because you
  • 02:33: want to always structure your models
  • 02:34: this way and this will really teach you
  • 02:36: why
  • 02:37: you want to structure them this way that
  • 02:39: way you can actually
  • 02:41: extend them rather than the model is
  • 02:43: what it is
  • 02:46: so that's the main idea here and then
  • 02:49: unlike the excel exercise where you're
  • 02:52: looking at doing just conditional
  • 02:53: formatting in a table
  • 02:55: here we're going to have the hexman plot
  • 02:57: as well as the styled
  • 02:59: data frame as the outputs
  • 03:03: so that's the lab exercise for the
  • 03:06: python sensitivity analysis and that
  • 03:08: wraps up this
  • 03:09: segment on exploring the parameter space
  • 03:12: so
  • 03:12: thanks for listening next time we'll be
  • 03:14: talking about
  • 03:16: probability modeling so i'll see you
  • 03:19: next time
|