def get_content():

    return [
        pl.Section([
            pl.SubSection([
                'You are an analyst trying to decide whether it is worth it to launch a new product line selling '
                't-shirts. The success of the t-shirt business will depend on the state of the economy. '
                'You can purchase a machine which costs \\$10,000,000 at $t=0$, then each year you will earn '
                'the profit per unit (revenue minus variable cost), multiplied by the output. The machine will '
                'last for 10 years. Should this project be undertaken? Will it be successful in all scenarios?',
            ],
                          title='Problem Statement'),
            pl.SubSection([
                pl.Center(
                    lt.Tabular([
                        lt.TopRule(),
                        lt.ValuesTable.from_list_of_lists([[
                            'State of Economy', 'Probability', 'Price',
                            'Output', 'Interest Rate'
                        ]]),
                        lt.MidRule(),
                        lt.ValuesTable.from_list_of_lists([
                            ['Expansion', '20%', '15', '1000000', '7%'],
                            ['Normal', '70%', '12', '500000', '5%'],
                            ['Recession', '10%', '10', '200000', '3%'],
                        ], ),
                        lt.BottomRule(),
                    ],
                               align='l|cccc'))
            ],
                          title='Scenarios'),
        ],
                   title='Capital Budgeting')
    ]
def get_content():
    return [
        pl.Section([
            pl.SubSection([
                'Create a model with two stocks, A and B. Both start at price 100. Generate stock prices for '
                '100 periods. Do this by drawing returns from normal distributions defined with the inputs '
                'below. Then apply the returns to the prior prices to get the price in each period. Create a '
                "portfolio of the two stocks, by taking the weighted-average of the stock's returns, then applying "
                "that return to a third Portfolio series starting at 100. Graph "
                "the two stocks and porfolio performance over time. Calculate the mean and standard deviation "
                "of the generated returns for the two stocks and the portfolio."
            ],
                          title='Problem Statement'),
            pl.SubSection([
                pl.Center(
                    lt.Tabular([
                        lt.TopRule(),
                        lt.ValuesTable.from_list_of_lists(
                            [['Input', 'Default Value']]),
                        lt.MidRule(),
                        lt.ValuesTable.from_list_of_lists([
                            ['Stock A Weight', '60%'],
                            ['Stock A Mean Return', '10%'],
                            ['Stock A Return Standard Deviation', '30%'],
                            ['Stock B Mean Return', '5%'],
                            ['Stock B Return Standard Deviation', '10%'],
                        ], ),
                        lt.BottomRule(),
                    ],
                               align='l|c'))
            ],
                          title='Inputs'),
        ],
                   title='Stock Portfolio')
    ]
Esempio n. 3
0
def get_content():
    return [
        pl.Section([
            pl.SubSection([
                'Create a model of stock returns and correlations. The asset returns should be based on the '
                'capital asset pricing model (CAPM), which states:',
                pl.Equation(str_eq=r'r_s = r_f + \beta (r_m - r_f) + \epsilon',
                            inline=False),
                pl.UnorderedList([
                    '$r_e$: Return on stock',
                    '$r_f$: Return on risk free asset',
                    '$r_m$: Return on the market portfolio',
                    r'$\beta$: Covariance between the market portfolio and the stock',
                    r'$\epsilon$: Idiosyncratic return, (random, normally distributed with mean 0)'
                ]), 'Your model should accept the number of assets, '
                'the average idiosyncratic standard deviation across the assets, the standard deviation of the '
                'idiosyncratic standard deviation across the assets, the market average return, the '
                'market standard deviation, the risk-free rate, and the number of periods as the inputs. You should randomly draw '
                "each asset's standard deviation of idiosyncratic returns from a normal distribution based on the "
                "inputs. You should also randomly draw the stock's beta from a uniform distribution between 0 and 2. "
                "Then draw the market returns from a normal distribution with its mean and standard deviation. Then "
                "the return for each asset in each time period will be determined by drawing its idiosyncratic return "
                "for that period from its normal distribution, then calculating the CAPM formula. After all the assets "
                "returns are generated, calculate the correlation between all the assets. Your model should be updating "
                "the number of assets and number of periods merely by changing the inputs."
            ],
                          title='Problem Definition'),
            pl.SubSection([
                pl.Center(
                    lt.Tabular([
                        lt.TopRule(),
                        lt.ValuesTable.from_list_of_lists(
                            [['Input', 'Default Value']]),
                        lt.MidRule(),
                        lt.ValuesTable.from_list_of_lists([
                            ['Number of Assets', '3'],
                            ['Number of Periods', '20'],
                            [
                                'Average Idiosyncratic Standard Deviation',
                                '20%'
                            ],
                            [
                                'Standard Deviation of Idiosyncratic Return Standard Deviation',
                                '10%'
                            ],
                            ['Market Average Return', '7%'],
                            ['Market Standard Deviation', '15%'],
                            ['Risk-Free Rate', '2%'],
                        ], ),
                        lt.BottomRule(),
                    ],
                               align='l|c'))
            ],
                          title='Model Inputs'),
        ],
                   title='Generating Asset Returns using CAPM')
    ]
Esempio n. 4
0
def get_content():
    jinja_templates_path = os.path.sep.join(['pltemplates', 'projects', 'p4'])
    jinja_env = pl.JinjaEnvironment(
        loader=FileSystemLoader(jinja_templates_path))

    return [
        pl.Section([
            pl.SubSection([
                Project4ProblemModel(template_path='prob_definition.j2',
                                     environment=jinja_env),
            ],
                          title='Problem Definition'),
            pl.SubSection([
                Project4ProblemModel(template_path='notes.j2',
                                     environment=jinja_env),
            ],
                          title='Notes'),
            pl.SubSection([
                Project4ProblemModel(template_path='bonus.j2',
                                     environment=jinja_env),
            ],
                          title='Bonus')
        ],
                   title='Overview'),
        pl.Section([
            pl.SubSection([
                Project4ProblemModel(template_path='submission.j2',
                                     environment=jinja_env),
            ],
                          title='Submission'),
            pl.SubSection([
                pl.Center(
                    lt.Tabular([
                        pl.MultiColumnLabel('Grading Breakdown', span=2),
                        lt.TopRule(),
                        lt.ValuesTable.from_list_of_lists(
                            [['Category', 'Percentage']]),
                        lt.TableLineSegment(0, 1),
                        lt.ValuesTable.from_list_of_lists(
                            [['Model Accuracy', '60%'],
                             ['Model Readability', '30%'],
                             ['Model Formatting', '10%'], ['Bonus', '5%']]),
                        lt.MidRule(),
                        lt.ValuesTable.from_list_of_lists(
                            [['Total Possible', '105%']]),
                        lt.BottomRule()
                    ],
                               align='l|c'))
            ],
                          title='Grading'),
        ],
                   title='Submission & Grading')
    ]
Esempio n. 5
0
def get_content():
    jinja_templates_path = os.path.sep.join(
        ['pltemplates', 'practice', 'python_retirement'])
    jinja_env = pl.JinjaEnvironment(
        loader=FileSystemLoader(jinja_templates_path))
    return [
        pl.Section([
            pl.SubSection([
                PythonRetirementPracticeProblemModel(
                    template_path='prob_definition.j2', environment=jinja_env),
            ],
                          title='Problem Definition'),
            pl.SubSection([
                pl.Center(
                    lt.Tabular([
                        lt.TopRule(),
                        lt.ValuesTable.from_list_of_lists([[
                            'Input',
                            'Default Value',
                        ]]),
                        lt.MidRule(),
                        lt.ValuesTable.from_list_of_lists([
                            ['Starting Salary', '\$50,000'],
                            ['Salary Growth', '3%'],
                            ['Mid-Salary Cutoff', r'\$80,000'],
                            ['High-Salary Cutoff', r'\$120,000'],
                            ['Low Savings Rate', '10%'],
                            ['Mid Savings Rate', '25%'],
                            ['High Savings Rate', '40%'],
                            ['Interest Rate', '5%'],
                            ['Desired Cash', r'\$1,500,000'],
                        ], ),
                        lt.BottomRule(),
                    ],
                               align='l|cc'))
            ],
                          title='Inputs'),
            pl.SubSection([
                """
                        The final answer with the default inputs should be 37 years to retirement. Try hard to get
                        there working from scratch. If you are very stuck, then try taking the Dynamic Salary
                        Retirement model and modifying it. If you are still stuck, then check the provided Jupyter 
                        notebook solution. If you have a lot of trouble with this, please see me in office hours or
                        after class, as your first project will be similar but a bit more difficult.
                        """
            ],
                          title='Solution')
        ],
                   title=
                   'Capital Budgeting Probabilities with Monte Carlo Simulation'
                   )
    ]
Esempio n. 6
0
 def _get_contents(self):
     contents = [
         *self.content,
         pl.VFill(),
     ]
     if self.bottom_content:
         bottom_contents = list(
             more_itertools.chunked(self.bottom_content, 3))
         if len(bottom_contents) > 1:
             # Multiple rows
             new_bottom_contents = []
             for content_row in bottom_contents:
                 # Deal with incomplete rows
                 if len(content_row) == 1:
                     # Single item, center it
                     value = content_row[0]
                     new_bottom_contents.append(['', value, ''])
                 elif len(content_row) == 2:
                     # Two items, put on edges
                     value1, value2 = content_row
                     new_bottom_contents.append([value1, '', value2])
                 else:
                     new_bottom_contents.append(content_row)
             bottom_contents = new_bottom_contents
         # Add padding
         new_bottom_contents = []
         for row in bottom_contents:
             new_bottom_contents.append([pl.HFill(), *row, pl.HFill()])
         bottom_contents = new_bottom_contents
         align = 'c' * len(bottom_contents[0])
         tab = lt.TabularStar([
             lt.TopRule(),
             lt.ValuesTable.from_list_of_lists(bottom_contents)
         ],
                              align=align)
         tab = self.format_contents(tab)
         contents.append(tab)
     lb = _LabBlock(contents, **self.kwargs)
     return lb
 pl.Section([
     pl.SubSection([submission_str], title='Submission'),
     pl.SubSection([
         solutions_str,
         pl.Center(
             pl.Graphic(images_path('project-2-solutions.png'),
                        width=0.5), ),
         case_solutions_str,
         pl.UnorderedList(case_solutions_list),
     ],
                   title='Selected Solutions'),
     pl.SubSection([
         pl.Center(
             lt.Tabular([
                 lt.MultiColumnLabel('Grading Breakdown', span=2),
                 lt.TopRule(),
                 lt.ValuesTable.from_list_of_lists(
                     [['Category', 'Percentage']]),
                 lt.TableLineSegment(0, 1),
                 lt.ValuesTable.from_list_of_lists([
                     ['Model Accuracy', '60%'],
                     ['Model Readability', '20%'],
                     ['Model Formatting', '10%'],
                     ['Following the Template', '10%'], ['Bonus', '5%']
                 ]),
                 lt.MidRule(),
                 lt.ValuesTable.from_list_of_lists(
                     [['Total Possible', '105%']]),
                 lt.BottomRule()
             ],
                        align=align))
Esempio n. 8
0
def get_content():
    align_c = lt.ColumnAlignment('c')
    align_l = lt.ColumnAlignment('l')
    align = lt.ColumnsAlignment([align_l, align_c])

    n_phones = 100000
    price_scrap = 50000
    price_phone = 500
    cogs_phone = 250
    price_machine_adv = 1000000
    n_life = 10
    n_machines = 5
    d_1 = 100000
    g_d = 0.2
    max_year = 20
    interest = 0.05

    pmm = PhoneManufacturingModel(n_phones, price_scrap, price_phone, n_life,
                                  n_machines, d_1, g_d, max_year, interest)

    scipy_mono = pl.Monospace('scipy')
    scipy_minimize_link = 'https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize_scalar.html#' \
                          'scipy-optimize-minimize-scalar'
    scipy_minimize_mono = pl.Monospace('scipy.optimize.minimize_scalar')

    possible_elasicity_str = ', '.join([
        f'($E = {ec[0]}$, $d_c = {ec[1]}$)' for ec in ELASTICITY_CONSTANT_CASES
    ])
    possible_elasicity_str = ', '.join([
        f'($E = {ec[0]}$, $d_c = {ec[1]}$)' for ec in ELASTICITY_CONSTANT_CASES
    ])
    possible_elasicity_str = '[' + possible_elasicity_str + ']'

    return [
        pl.Section([
            pl.SubSection([
                'You work for a new startup that is trying to manufacture phones. You are tasked with building '
                'a model which will help determine how many machines to invest in and how much to spend on '
                'marketing. Each machine produces $n_{output}$ phones per year. Each phone sells '
                r'for \$$p_{phone}$ and costs \$$c_{phone}$ in variable costs to produce. '
                'After $n_{life}$ years, the machine can no longer produce output, but may be scrapped for '
                r'\$$p_{scrap}$. The machine will not be replaced, so you may end up with zero total output '
                r'before your model time period ends. '
                'Equity investment is limited, so in each year you can spend $c_{machine}$ to either buy a machine or buy '
                'advertisements. In the first year you must buy a machine. Any other machine purchases must '
                'be made one after another (advertising can only begin after machine buying is done). '
                'Demand for your phones starts at '
                '$d_1$. Each time you advertise, demand increases by $g_d$%. The prevailing market interest '
                'rate is $r$.'
            ],
                          title='The Problem'),
            pl.SubSection([
                pl.UnorderedList([
                    'You may limit your model to 20 years and a maximum of 5 machines if it is helpful.',
                    'For simplicity, assume that $c_{machine}$ is paid in every year, '
                    'even after all machines have shut down.',
                    'Ensure that you can change the inputs and the outputs change as expected.',
                    'For simplicity, assume that fractional phones can be sold, you do not '
                    'need to round the quantity transacted.'
                ])
            ],
                          title='Notes'),
            pl.SubSection([
                pl.SubSubSection([
                    pl.UnorderedList([
                        '$n_{output}$: Number of phones per machine per year',
                        '$n_{machines}$: Number of machines purchased',
                        '$n_{life}$: Number of years for which the machine produces phones',
                        '$p_{phone}$: Price per phone',
                        '$p_{scrap}$: Scrap value of machine',
                        '$c_{machine}$: Price per machine or advertising year',
                        '$c_{phone}$: Variable cost per phone',
                        '$d_1$: Quantity of phones demanded in the first year',
                        '$g_d$: Percentage growth in demand for each advertisement',
                        '$r$: Interest rate earned on investments'
                    ])
                ],
                                 title='Inputs'),
                pl.SubSubSection([
                    pl.UnorderedList([
                        'Cash flows in each year, up to 20 years',
                        'PV of cash flows, years 1 - 20',
                    ])
                ],
                                 title='Outputs')
            ],
                          title='The Model'),
            pl.SubSection([
                "It is unrealistic to assume that price and demand are unrelated. To extend the model, "
                "we can introduce a relationship between price and demand, given by the following equation: ",
                pl.Equation(str_eq=r'd_1 = d_c - Ep_{phone}', inline=False),
                pl.UnorderedList([
                    f'{pl.Equation(str_eq="E")}: Price elasticity of demand',
                    f'{pl.Equation(str_eq="d_c")}: Demand constant'
                ]),
                [
                    f"For elasticities and constants {possible_elasicity_str} "
                    f"({len(ELASTICITY_CONSTANT_CASES)} total cases), and taking the other "
                    "model inputs in the ",
                    pl.NameRef('check-work'),
                    ' section, determine the optimal price for each '
                    'elasticity, that is the price which maximizes the NPV.'
                ],
                pl.SubSubSection([
                    pl.UnorderedList([
                        '$d_1$ is no longer an input, but an output.',
                        'This bonus requires optimization, which we have not yet covered in class.',
                        'In Excel, you can use Solver.',
                        [
                            f'In Python, the {scipy_mono} package provides optimization tools. You will '
                            f'probably want to use:',
                        ],
                        pl.UnorderedList([
                            Hyperlink(scipy_minimize_link,
                                      scipy_minimize_mono),
                            "You will need to write a function which accepts price and returns NPV, "
                            "with other model inputs fixed.",
                            pl.UnorderedList([[
                                'Depending on how you set this up,',
                                Hyperlink(
                                    'https://www.learnpython.org/en/Partial_functions',
                                    'functools.partial'),
                                'may be helpful for this.'
                            ]]),
                            "It will actually need to return negative NPV, as the optimizer only minimizes, "
                            "but we want maximum NPV.",
                            [
                                'No answers to check your work are given for this bonus. The',
                                pl.NameRef('check-work'),
                                'section only applies to without the bonus.'
                            ]
                        ])
                    ])
                ],
                                 title='Notes')
            ],
                          title='Bonus Problem'),
        ],
                   title='Overview'),
        pl.Section([
            'You must start from "Project 1 Template.xlsx". Ensure that you reference all inputs from '
            'the Inputs/Outputs tab. Also ensure that all outputs are referenced back to the Inputs/Outputs tab. '
            'Do not change any locations of the inputs or outputs. '
            'The final submission is your Excel workbook.'
        ],
                   title='Excel Exercise'),
        pl.Section([[
            'You must start from "Project 1 Template.ipynb". '
            'I should be able to run all the '
            'cells and get the output of your model at the bottom. ',
            [
                'You should not change the name of the',
                pl.Monospace('ModelInputs'), 'class or the',
                pl.Monospace('model_data'), 'variable.'
            ], 'You need to define',
            pl.Monospace('cash_flows'), 'as your output cash flows (numbers, '
            'not formatted), and ',
            pl.Monospace('npv'),
            'as your NPV (number, not formatted). When you '
            'show your final outputs in the notebook, then they should be formatted.'
        ]],
                   title='Python Exercise'),
        pl.Section([
            Center(
                lt.Tabular([
                    lt.MultiColumnLabel('Grading Breakdown', span=2),
                    lt.TopRule(),
                    lt.ValuesTable.from_list_of_lists(
                        [['Category', 'Percentage']]),
                    lt.TableLineSegment(0, 1),
                    lt.ValuesTable.from_list_of_lists([[
                        'Model Accuracy', '60%'
                    ], ['Model Readability', '20%'], [
                        'Model Formatting', '10%'
                    ], ['Following the Template', '10%'], ['Bonus', '5%']]),
                    lt.MidRule(),
                    lt.ValuesTable.from_list_of_lists(
                        [['Total Possible', '105%']]),
                    lt.BottomRule()
                ],
                           align=align))
        ],
                   title='Grading'),
        pl.Section(
            [
                'If you pass the following inputs (to the basic model, not bonus model): ',
                pl.UnorderedList([
                    f'{pl.Equation(str_eq="n_{output}")}: {n_phones:,.0f}',
                    f'{pl.Equation(str_eq="p_{scrap}")}: \${price_scrap:,.0f}',
                    f'{pl.Equation(str_eq="p_{phone}")}: \${price_phone:,.0f}',
                    f'{pl.Equation(str_eq="c_{machine}")}: \${price_machine_adv:,.0f}',
                    f'{pl.Equation(str_eq="c_{phone}")}: \${cogs_phone:,.0f}',
                    f'{pl.Equation(str_eq="n_{life}")}: {n_life}',
                    f'{pl.Equation(str_eq="n_{machines}")}: {n_machines}',
                    f'{pl.Equation(str_eq="d_1")}: {d_1:,.0f}',
                    f'{pl.Equation(str_eq="g_d")}: {g_d:.0%}',
                    f'{pl.Equation(str_eq="r")}: {interest:.0%}',
                ]),
                'You should get the following result:',
                # TODO [#10]: replace project 1 result using notebook executor
                """
                Cash Flows:

Year 1: \$24,000,000

Year 2: \$24,000,000

Year 3: \$24,000,000

Year 4: \$24,000,000

Year 5: \$24,000,000

Year 6: \$29,000,000

Year 7: \$35,000,000

Year 8: \$42,200,000

Year 9: \$50,840,000

Year 10: \$61,208,000

Year 11: \$73,699,600

Year 12: \$74,050,000

Year 13: \$49,050,000

Year 14: \$24,050,000

Year 15: \$-950,000

Year 16: \$-1,000,000

Year 17: \$-1,000,000

Year 18: \$-1,000,000

Year 19: \$-1,000,000

Year 20: \$-1,000,000



NPV: \$369,276,542
                """
            ],
            title='Check your Work',
            label='check-work')
    ]
def get_content():
    jinja_templates_path = os.path.sep.join(['pltemplates', 'projects', 'p3'])
    jinja_env = pl.JinjaEnvironment(
        loader=FileSystemLoader(jinja_templates_path))

    with open(ANSWERS_OUTPUT_PATH, 'r') as f:
        answers_json = json.load(f)
    answers_dict = answers_json[0]

    beta_std = answers_dict['beta_std']
    mkt_ret_std = answers_dict['mkt_ret_std']
    bond_price_std = answers_dict['bond_price_std']
    tax_rate_std = answers_dict['tax_rate_std']
    bond_years = answers_dict['bond_years']
    bond_coupon = answers_dict['bond_coupon']
    bond_price = answers_dict['bond_price']
    bond_par = answers_dict['bond_par']
    risk_free = answers_dict['risk_free']
    price = answers_dict['price']
    shares_outstanding = answers_dict['shares_outstanding']
    libor_rate = answers_dict['libor_rate']

    inputs_table = pl.Center(
        lt.Tabular([
            pl.MultiColumnLabel('Baseline Inputs', span=2),
            lt.TopRule(),
            lt.ValuesTable.from_list_of_lists([['Variable', 'Baseline Value']
                                               ]),
            lt.TableLineSegment(0, 1),
            lt.ValuesTable.from_list_of_lists([
                ['Market Bond Maturity (Years)', f'{bond_years:.0f}'],
                ['Market Bond Coupon', f'{bond_coupon:.2%}'],
                ['Market Bond Price', rf'\${bond_price:.2f}'],
                ['Market Bond Par Value', rf'\${bond_par:.2f}'],
                ['Risk Free Rate', f'{risk_free:.2%}'],
                ['Stock Price', rf'\${price:.2f}'],
                ['Shares Outstanding', f'{shares_outstanding:,.0f}'],
                ['LIBOR Rate', f'{libor_rate:.2%}'],
            ]),
            lt.BottomRule()
        ],
                   align='l|c'))

    stdev_table = pl.Center(
        lt.Tabular([
            pl.MultiColumnLabel('Standard Deviations', span=2),
            lt.TopRule(),
            lt.ValuesTable.from_list_of_lists(
                [['Variable', 'Standard Deviation']]),
            lt.TableLineSegment(0, 1),
            lt.ValuesTable.from_list_of_lists([
                [r'$\beta$', beta_std],
                ['Market Return', f'{mkt_ret_std:.0%}'],
                ['Walmart Bond Market Price', rf'\${bond_price_std}'],
                ['Tax Rate', f'{tax_rate_std:.0%}'],
            ]),
            lt.BottomRule()
        ],
                   align='l|c'))

    return [
        pl.Section([
            Project3ProblemModel(template_path='prob_definition.j2',
                                 environment=jinja_env),
            Project3ProblemModel(template_path='notes.j2',
                                 environment=jinja_env),
            Project3ProblemModel(template_path='bonus.j2',
                                 environment=jinja_env),
            pl.SubSection([inputs_table],
                          title='Baseline Model Inputs',
                          label='baseline-inputs'),
            pl.SubSection(
                [stdev_table], title='Monte Carlo Inputs', label='mc-inputs'),
        ],
                   title='Overview'),
        pl.Section([
            Project3ProblemModel(template_path='submission.j2',
                                 environment=jinja_env),
            pl.SubSection([
                'Selected solutions with the baseline inputs:',
                pl.UnorderedList([
                    f'WACC: {answers_dict["wacc"]:.2%}',
                    rf'MV Debt: \${answers_dict["mv_debt"] / 1000000000:.1f} billion',
                    f'Cost of Equity: {answers_dict["coe"]:.2%}',
                    f'Pre-Tax Cost of Debt: {answers_dict["pretax_cost_of_debt"]:.2%}'
                ])
            ],
                          title='Solutions'),
            pl.SubSection([
                pl.Center(
                    lt.Tabular([
                        pl.MultiColumnLabel('Grading Breakdown', span=2),
                        lt.TopRule(),
                        lt.ValuesTable.from_list_of_lists(
                            [['Category', 'Percentage']]),
                        lt.TableLineSegment(0, 1),
                        lt.ValuesTable.from_list_of_lists([
                            ['Model Accuracy', '60%'],
                            ['Model Readability', '20%'],
                            ['Model Formatting', '10%'],
                            ['Following the Template', '10%'], ['Bonus', '5%']
                        ]),
                        lt.MidRule(),
                        lt.ValuesTable.from_list_of_lists(
                            [['Total Possible', '105%']]),
                        lt.BottomRule()
                    ],
                               align='l|c'))
            ],
                          title='Grading'),
        ],
                   title='Submission & Grading')
    ]
Esempio n. 10
0
def get_content():
    return [
        pl.Section(
            [
                pl.SubSection(
                    [
                        'You are a financial analyst for an aircraft manufacturer. Your company is trying to decide '
                        'how large its next line of planes should be. Developing a line of planes takes a one-time '
                        'research cost, then each plane has a cost to manufacture afterwards. The larger the plane, '
                        'the higher the research and manufacture costs, but also the more revenue per plane. The '
                        'larger planes are more risky because if the economy goes poorly, not many airlines will want '
                        'to invest in such a large plane, but if the economy goes well, airlines will be rushing to the '
                        'larger planes to fit rising demand.',
                        '',
                        """
                        The research cost will be paid at $t=0$. For simplicity, assume that all planes are manufactured 
                        at $t=1$ and sold at $t=2$. The interest rate is given in the below table.
                        
                        Find the expected NPV and standard deviation of NPV for each plane. Which plane has the lowest
                        chance of a negative NPV? Which has the highest chance of a positive NPV? Visualize the range
                        of possible NPVs for each plane, as well as the probability of acheiving different NPV levels 
                        (probability table). For the mid-size plane, which has a larger impact on the NPV, an 
                        additional plane sold or a decrease in the interest rate by 1%? In your opinion, which
                        plane should the manufacturer create?
                        """
                    ],
                    title='Problem Definition'
                ),
                pl.SubSection(
                    [
                        pl.Center(
                            lt.Tabular(
                                [
                                    lt.TopRule(),
                                    lt.ValuesTable.from_list_of_lists([[
                                        'Plane', 'Research Cost', 'Manufacture Cost', 'Sale Price', 'Expected Unit Sales', 'Stdev Unit Sales'
                                    ]]),
                                    lt.MidRule(),
                                    lt.ValuesTable.from_list_of_lists(
                                        [
                                            ['Super Size', r'\$100,000,000', r'\$10,000,000', r'\$11,500,000', '200', '120'],
                                            ['Large', r'\$50,000,000', r'\$5,000,000', r'\$5,600,000', '400', '50'],
                                            ['Mid-size', r'\$25,000,000', r'\$3,000,000', r'\$3,350,000', '500', '20'],
                                        ],
                                    ),
                                    lt.BottomRule(),
                                ],
                                align='l|ccccc'
                            )
                        )
                    ],
                    title='Possible Planes'
                ),
                pl.SubSection(
                    [
                        pl.Center(
                            lt.Tabular(
                                [
                                    lt.TopRule(),
                                    lt.ValuesTable.from_list_of_lists([[
                                        'Input', 'Default Value', 'Default Stdev'
                                    ]]),
                                    lt.MidRule(),
                                    lt.ValuesTable.from_list_of_lists(
                                        [
                                            ['Interest Rate', '7%', '4%'],
                                        ],
                                    ),
                                    lt.BottomRule(),
                                ],
                                align='l|cc'
                            )
                        )
                    ],
                    title='Other Inputs'
                )
            ],
            title='Capital Budgeting Probabilities with Monte Carlo Simulation'
        )
    ]
Esempio n. 11
0
def get_content():
    random.seed(1000)
    ev_bet = (999999 / 1000000) * 1 + (1 / 1000000) * (-750001)
    xlwings_mono = pl.Monospace('xlwings')
    pd_mono = pl.Monospace('pandas')
    quickstart_mono = pl.Monospace('quickstart')

    read_from_excel_example = pl.Python("""
my_value = xw.Range("G11").value  # single value
# all values in cell range
my_value = xw.Range("G11:F13").value  
# expands cell range down and left getting all values
my_values = xw.Range("G11").expand().value  
    """)

    write_to_excel_example = pl.Python("""
xw.Range("G11").value = 10
xw.Range("G11").value = [10, 11]  # horizontal
xw.Range("G11").value = [[10], [11]]  # vertical
xw.Range("G11").value = [[10, 11], [12, 13]]  # table
    """)

    ball_options = ['fill', 'circle', 'inner sep=8pt']

    blue_ball_options = ball_options + ['blue']

    red_ball_options = ball_options + ['red']

    def rand_pos():
        return random.randrange(-150, 150) / 100

    blue_nodes = [
        lg.Node(None, (rand_pos(), rand_pos()), options=blue_ball_options)
        for _ in range(10)
    ]
    red_nodes = [
        lg.Node(None, (rand_pos(), rand_pos()), options=red_ball_options)
        for _ in range(10)
    ]

    red_blue_ball_graphic = lg.TikZPicture([
        lg.Rectangle(5, 5, shape_options=['blue', 'thick']), *blue_nodes,
        *red_nodes
    ])

    lecture = get_monte_carlo_lecture()
    intro_mc_python_lab = get_intro_monte_carlo_lab_lecture().to_pyexlatex()
    mc_python_lab = get_python_retirement_monte_carlo_lab_lecture(
    ).to_pyexlatex()
    mc_excel_lab = get_excel_retirement_monte_carlo_lab_lecture().to_pyexlatex(
    )

    return [
        pl.Section([
            lp.
            TwoColumnGraphicDimRevealFrame([
                [
                    pl.Bold('Monte Carlo Simulation'),
                    'is a technique which allows understanding the probability '
                    'of acheiving certain outputs from a model.'
                ],
                'This gives the modeler a greater understanding of the likelihood of different outputs, rather '
                'than relying on a single number',
            ],
                                           graphics=[
                                               images_path(
                                                   'random-numbers.jpg')
                                           ],
                                           title=
                                           'What is Monte Carlo Simulation?'),
            lp.DimRevealListFrame([
                r'Imagine you have a one-time opportunity to place a bet for \$1. ',
                r'If you win the bet, you will receive \$2. If you lose the bet, you will lose \$750,000. '
                r'You cannot avoid the payment by declaring bankruptcy.',
                r'The odds of winning the bet are 999,999/1,000,000. In 1/1,000,000 you lose the \$750,000.',
                fr'The expected profit from the bet is \${ev_bet:.2f}. Should you take it? Depends on your '
                fr'risk tolerance.',
                'Therefore not only the expected outcome matters, but also what other outcomes may occur and '
                'their probabilities.'
            ],
                                  title='Why Use Monte Carlo Simulation?'),
            lp.GraphicFrame(explore_parameters_graphic(),
                            title='Monte Carlo Simulation in One Picture'),
            lp.DimRevealListFrame([
                'Monte Carlo simulation is carried out similarly to external scenario analysis.',
                'The main difference is that we manually picked specific cases for the inputs with scenario '
                'analysis.',
                'In Monte Carlo simulation, we assign distributions to the inputs, and input values are drawn '
                'from the distributions for each run of the model',
                'Finally, we can fit a probability distribution to the outputs to be able to talk about the '
                'chance of a certain outcome occurring'
            ],
                                  title=
                                  'Basic Process for Monte Carlo Simulation')
        ],
                   title='Introduction'),
        pl.Section(
            [
                lp.DimRevealListFrame([
                    'Monte Carlo simulation can be applied to any model',
                    'It is generally easier to run them in Python than in Excel.',
                    "With pure Excel, you're either going to VBA or hacking something with data tables",
                    'In Python, just loop for N iterations, each time drawing inputs, running the model, and collecting '
                    'outputs.',
                    [
                        'We will start with a pure Python model, then move to using',
                        xlwings_mono, 'to add Monte Carlo '
                        'simulations to our Excel models.'
                    ],
                ],
                                      title=
                                      'Running Monte Carlo Simulations - Python or Excel?'
                                      ),
                lp.Frame([
                    lp.Block([
                        r'You have \$1,000 now and need to pay \$1,050 in one year. You have available to you '
                        r'two assets: a risk free asset that returns 3%, and a stock that returns 10% with a '
                        r'20% standard deviation. How much should you invest in the two assets to maximize '
                        r'your probability of having at least \$1,050 in one year?'
                    ],
                             title='An Investment Problem'),
                    pl.VFill(),
                    pl.UnorderedList([
                        lp.DimAndRevealListItems([
                            'We must first construct the basic model which gets the portfolio value for given '
                            'returns',
                            'Then draw values of the stock return from a normal distribution, and run the model '
                            'many times and visualize the outputs. ',
                            'Then repeat this process with each weight to determine the best weight.'
                        ])
                    ])
                ],
                         title='An Example Application'),
                InClassExampleFrame([
                    'Go to the course site and download the Jupyter notebook "MC Investment Returns.ipynb" from '
                    'Monte Carlo Examples',
                    'I will go through this example notebook to solve the problem from the prior slide.'
                ],
                                    title='Simluating Portfolio Values',
                                    block_title=
                                    'Example for Simulating Portfolio Values'),
                pl.TextSize(-2),
                intro_mc_python_lab.presentation_frames(),
                pl.TextSize(0),
            ],
            title='Running a First Monte Carlo Simulation',
            short_title='Run MC',
        ),
        pl.Section(
            [
                lp.Frame([
                    pl.TextSize(-2), 'For the model given by:',
                    pl.Equation(str_eq='y = f(X)', inline=False),
                    pl.Equation(str_eq='X = [x_1, x_2, ..., x_n]',
                                inline=False),
                    pl.UnorderedList([[
                        pl.Equation(str_eq='y:'), 'Model output'
                    ], [pl.Equation(str_eq='X:'), 'Model input matrix'],
                                      [
                                          pl.Equation(str_eq='x_i:'),
                                          'Value of $i$th $x$ variable'
                                      ]]),
                    'To run $N$ Monte Carlo simulations, follow the following steps:',
                    pl.OrderedList(
                        [[
                            'Assign a probability distribution for each',
                            pl.Equation(str_eq='x_i')
                        ],
                         [
                             'For each',
                             pl.Equation(str_eq='x_i'),
                             'randomly pick a value from its probability distribution. Store them as',
                             pl.Equation(str_eq='X_j')
                         ],
                         [
                             'Repeat the previous step $N$ times, yielding',
                             pl.Equation(str_eq='[X_1, X_2, ..., X_N]')
                         ],
                         [
                             'For each',
                             pl.Equation(str_eq='X_j'), 'calculate',
                             pl.Equation(str_eq='y_j = f(X_j)')
                         ],
                         [
                             'Store the values of',
                             pl.Equation(str_eq='X_j'), 'mapped to',
                             pl.Equation(str_eq='y_j')
                         ],
                         [
                             'Visualize and analyze',
                             pl.Equation(str_eq='y_j'), 'versus',
                             pl.Equation(str_eq='X_j')
                         ]])
                ],
                         title='Monte Carlo Simulation Process'),
                lp.DimRevealListFrame([
                    'There are a multitude of outputs we can get from a Monte Carlo simulation. We saw a few '
                    'already in the example.',
                    [
                        pl.Bold('Outcome probability distributions'),
                        'are the main output. We saw this with two '
                        'approaches in the example, a',
                        pl.Underline('histogram'), 'and a',
                        pl.Underline('probability table.')
                    ],
                    [
                        'We also examined the',
                        pl.Bold('probability of a certain outcome'),
                        'in whether we reached '
                        'the desired cash.'
                    ],
                    [
                        'The last main output is examining the',
                        pl.Bold('relationship between inputs and outputs.'),
                        'for which common approaches include',
                        pl.Underline('scatter plots'), 'and',
                        pl.Underline('regressions.')
                    ]
                ],
                                      title=
                                      'Outputs from Monte Carlo Simulation'),
                lp.TwoColumnGraphicDimRevealFrame(
                    [
                        pl.TextSize(-3),
                        'The outcome probability distribution represents the chance of receiving different '
                        'outcomes from your model.',
                        'There are two main ways to visualize a probability distribution: a plot and a table.',
                        [
                            'The plot, usually a',
                            pl.Underline('histogram'), 'or',
                            pl.Underline('KDE'),
                            'gives a high-level overview of the probabilities and can uncover any non-normal '
                            'features of the distribution.'
                        ],
                        [
                            'The probability table represents the chance of receiving the given value or '
                            'lower.'
                        ],
                        'The Value at Risk (VaR) is a common measure calculated in the industry, and it represents '
                        'the probability of losing at least a certain amount. This would be a subset of this analysis '
                        'and so this analysis can be used to calculate VaR',
                    ],
                    graphics=[
                        images_path('outcome-probability-distribution.png'),
                        lt.Tabular([
                            pl.MultiColumnLabel('Probability Table', span=2),
                            lt.TopRule(),
                            lt.ValuesTable.from_list_of_lists(
                                [['Probability', 'Value']]),
                            lt.TableLineSegment(0, 1),
                            lt.ValuesTable.from_list_of_lists(
                                [['25%', '1020'], ['50%', '1039'],
                                 ['75%', '1053']]),
                            lt.BottomRule()
                        ],
                                   align='c|c')
                    ],
                    title='Outcome Probability Distributions',
                    graphics_on_right=False,
                ),
                lp.TwoColumnGraphicDimRevealFrame(
                    [
                        'Imagine a box which contains red and blue balls. You do not know in advance how many there '
                        'are of each color.',
                        'You want to estimate the probability of getting a blue ball when pulling a ball from the box.',
                        'To evaluate this, you grab a ball, write down its color, and put it back, 1,000 times.',
                        'You pull a blue ball in 350 out of the 1,000 trials. What is the probability of getting blue?'
                    ],
                    graphics=[red_blue_ball_graphic
                              ],
                    title='Probability of a Certain Outcome - A Simple Example'
                ),
                lp.DimRevealListFrame([
                    'We followed the same logic when estimating the probability of receiving our desired cash '
                    'in the investment example.',
                    pl.Equation(
                        str_eq=
                        fr'p = \frac{{{pl.Text("Count of positive outcomes")}}}{{{pl.Text("Count of trials")}}}'
                    ),
                    [
                        'For the balls example, this is simply',
                        pl.Equation(str_eq=r'p = \frac{350}{1000} = 0.35'),
                    ],
                    [
                        'In the investment example, we used', pd_mono,
                        'to check for each trial, whether it was a '
                        'positive outcome (made it a 1) or not (made it a 0). Then the sum is the count of '
                        'positive outcomes and so the mean is the probability.'
                    ],
                ],
                                      title=
                                      'Probability of a Certain Outcome, Formally'
                                      ),
                lp.DimRevealListFrame([
                    'Monte Carlo simulation can also provide a more comprehensive look at the relationship between '
                    'inputs and outputs.',
                    'While sensitivity analysis can be used to estimate the relationship between an input and '
                    'output, it is usually done with other inputs at their base case',
                    'The values of inputs may affect how other inputs affect the output. E.g. for the retirement '
                    'model, an increase in interest rate increases wealth more if the initial salary was higher.',
                    'As all the inputs change each time, you can get a more realistic view of the relationship, e.g. '
                    'some trials with a higher interest rate will have high salary and some will have low salary.'
                ],
                                      title=
                                      'Why Monte Carlo Simulations Help Understand Inputs vs. Outputs'
                                      ),
                lp.TwoColumnGraphicDimRevealFrame(
                    [
                        pl.TextSize(-1),
                        'A scatter plot is a simple way to visualize the relationship between two variables',
                        'If there is a relationship, you will see some defined pattern in the points. This may be '
                        'somewhat of an upward or downward line (linear relationship) or some other shape such '
                        'as a U (non-linear relationship).',
                        'If there is no relationship, then there will just be a random cloud of points (lower '
                        'plot) or a horizontal line.'
                    ],
                    graphics=[
                        images_path('scatter-plot-line.png'),
                        images_path('scatter-plot-no-relationship.png')
                    ],
                    graphics_on_right=False,
                    title=
                    'Visualizing the Relationship between Inputs and Outputs'),
                lp.TwoColumnGraphicDimRevealFrame([
                    pl.TextSize(-2),
                    'The scatter plots help give a broad understanding of the relationship but do not answer the '
                    'question, how much will my output change if my input changes? E.g. if I earn 10,000 more '
                    'for a starting salary, how much sooner can I retire?',
                    'Simply increasing the input in your model and checking the output is not enough, because it '
                    'does not take into account how all the other variables may be changing.',
                    'Multivariate regression is a general tool which is good at answering these kinds of questions, '
                    'while taking into account all the changing inputs.'
                ],
                                                  graphics=[
                                                      images_path(
                                                          'excel-multivariate-reg.png'
                                                      )
                                                  ],
                                                  title=
                                                  'Numerically Analyzing the Relationships'
                                                  ),
                lp.DimRevealListFrame([
                    pl.TextSize(-1),
                    'The coefficient in a multivariate regression represents how much the outcome variable '
                    'changes with a one unit change in the input variable.',
                    'E.g. a coefficient of -.0002 on starting salary in explaining years to retirement would mean '
                    r'that a \$1 increase in starting salary is associated with a decrease in years to retirement by .0002 years, or '
                    r'a \$10,000 increase in starting salary is associated with a decrease in years to retirement by 2 years.',
                    'All interpretations are "all else constant", meaning that it does not consider relationships '
                    'between the inputs. E.g. if starting salary is higher because of a good economy, and interest '
                    'rates are also higher due to the good economy, the starting salary coefficient is not taking '
                    'into account the increase in interest rates.',
                    'Be careful about units. If you use decimals for percentages, you will need to multiply or '
                    'divide by 100 to get the effect in percentages.'
                ],
                                      title='How to use Multivariate Regression'
                                      ),
                InClassExampleFrame(
                    [
                        'I will now go through adding a Monte Carlo simulation to the Dynamic Salary Retirement '
                        'Model in Python',
                        'The completed example is on the course site in '
                        'Monte Carlo Examples',
                    ],
                    title='Adding Monte Carlo Simulation to a Formal Model',
                    block_title='Dynamic Salary Retirement with Monte Carlo'),
                mc_python_lab.presentation_frames(),
            ],
            title='A More Formal Treatment of Monte Carlo Simulation',
            short_title='Formal MC',
        ),
        pl.Section([
            lp.DimRevealListFrame([
                'In pure Excel, it is much more difficult to run a Monte Carlo Simulation',
                'Without going to VBA, typically the only way is to use a data table',
                'A data table can be used in situations where you only want to have one or two inputs '
                'varying at once. Just generate the random inputs and use them as the axes of the data table',
                'If you want to vary more than two inputs, VBA or Python would be required',
                'There are also add-ons that accomplish this but they are usually not free'
            ],
                                  title=
                                  "How is it Different Running MC in Excel?"),
            lp.DimRevealListFrame([
                'The process for Monte Carlo Simulation which works for any number of variables is '
                'very similar to what we were doing in Python.',
                'We are still just changing the inputs, running the model, and storing the outputs from each run',
                [
                    'Using', xlwings_mono,
                    'from Python code we can change and retrieve the values of cells'
                ],
                'This allows us to change inputs, run the model, and store outputs, just as in Python, but running our Excel model.',
                'We can either analyze the outputs in Python or output them back to Excel for analysis'
            ],
                                  title=
                                  'Monte Carlo in Excel with More than Two Variables'
                                  ),
            InClassExampleFrame([
                'Go to the course site and download the "Dynamic Salary Retirement Model.xlsx" and '
                '"Excel Monte Carlo.ipynb" from the Monte Carlo Examples',
                'Open up the Jupyter notebook and follow along with me',
                'The completed Excel model is also there in case you lose track. Visualizations '
                'were added after running the Jupyter notebook on the original Excel model.',
            ],
                                title='Monte Carlo Excel Retirement Model',
                                block_title=
                                f'Using {xlwings_mono} to Run Monte Carlo Simulations'
                                ),
            mc_excel_lab.presentation_frames(),
        ],
                   title='Monte Carlo Simulation in Excel',
                   short_title='Excel MC'),
        pl.PresentationAppendix([
            lecture.pyexlatex_resources_frame,
            intro_mc_python_lab.appendix_frames(),
            mc_python_lab.appendix_frames(),
            mc_excel_lab.appendix_frames(),
        ])
    ]