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')
    ]
Example #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')
    ]
    def to_pyexlatex(
            self,
            lectures: Dict[str, List[Lecture]],
            lab_exercises: List[LabExerciseLecture],
            week_num: int,
            start_date: datetime.date,
            end_date: datetime.date,
            project_date: Optional[datetime.date] = None) -> pl.Section:
        if project_date is None:
            project_date = start_date

        start_fmt = start_date.strftime(self.date_fmt)
        end_fmt = end_date.strftime(self.date_fmt)
        project_fmt = project_date.strftime(self.date_fmt)

        section_contents = []

        if lectures:
            content = []
            for lecture_group_title, lecture_list in lectures.items():
                lecture_contents = pl.UnorderedList(
                    [lect.title for lect in lecture_list])
                content.append(
                    pl.UnorderedList([lecture_group_title, lecture_contents]))

            section_contents.append(
                pl.SubSection(content, title='Lectures Covered'))

        if self.assigned_projects:
            section_contents.append(
                pl.SubSection([
                    pl.UnorderedList(
                        [proj.display_name for proj in self.assigned_projects])
                ],
                              title='Projects Assigned'))

        if self.projects_due:
            section_contents.append(
                pl.SubSection([
                    pl.UnorderedList(
                        [proj.display_name for proj in self.projects_due])
                ],
                              title=f'Projects Due by {project_fmt}'))

        if lab_exercises:
            section_contents.append(
                pl.SubSection(
                    [pl.UnorderedList([lab.title for lab in lab_exercises])],
                    title=f'Lab Exercises Due by {end_fmt}'))

        date_str = f'{start_fmt} - {end_fmt}'
        section = pl.Section(section_contents,
                             title=f'Week {week_num} ({date_str})')
        return section
Example #5
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')
    ]
Example #6
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'
                   )
    ]
    """

    case_solutions_str = """
    I am also providing the IRRs for each possible default situation in the model with base case inputs 
    and a 20% interest rate. This way you
    can check your model without having to run lots of iterations. Make sure that your model can reproduce each of the
    IRRs corresponding to each default case, and then you will only need the full solutions to check that the probabilities
    are set correctly. Note that unlike the full solutions, you should be able to match these default case solutions 
    exactly.
    """

    return [
        pl.Section([
            pl.SubSection([
                problem_definition_pre_prob,
                pl.Equation(str_eq=default_prob_eq_str, inline=False),
                problem_definition_post_prob
            ],
                          title='Problem Definition'),
            pl.SubSection([main_q_str], title='Main Question'),
            pl.SubSection([pl.UnorderedList(notes)], title='Notes'),
            pl.SubSection([inputs_content], title='Inputs'),
            pl.SubSection([bonus_q_str], title='Bonus Question'),
        ],
                   title='Overview'),
        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), ),
Example #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')
    ]
def get_content():
    return [
        pl.Section([
            'You will be graded across several dimensions in completing projects. These dimensions include, but '
            'are not limited to: ',
            pl.UnorderedList([
                'Model Accuracy',
                'Model Readability',
                'Model Formatting',
                'Following the Template',
            ]),
            'Some projects may have their own specific categories. If so, the criteria for that category will '
            "be defined in that project's description."
        ],
                   title='The Grading Categories'),
        pl.Section([
            'I will first look at all the models before grading any of them. This is how I will establish what '
            'to expect. The grading is somewhat absolute and somewhat relative. For example, if your model is '
            'completely accurate, you will receive a 100% for model accuracy. But, you could also receive a high '
            'grade for model accuracy even if there are errors, if the rest of the class made similar errors. '
            'Partial credit will be given in every category. The amount of points given will be proportional '
            'to how well you completed the category, on an absolute basis if applicable and also relative to '
            'other students.'
        ],
                   title='The Score in a Category'),
        pl.Section([
            'The weights of each category will be specific to the project. Generally, Model Accuracy will '
            'carry the highest weight, and Model Formatting will carry the lowest weight. Look '
            'to the project description for a breakdown of the weights.'
        ],
                   title='The Grading Weights of the Categories'),
        pl.Section([
            pl.UnorderedList([
                'Does the model obtain the correct results?',
                'When inputs are changed, does the output change appropriately?',
                'Can the model handle the full range of possible values?'
            ])
        ],
                   title='Model Accuracy'),
        pl.Section([
            "Model readability is all about how easily can I understand what you're doing in the model, "
            "and how easily I can navigate through it.",
            pl.SubSection([
                pl.UnorderedList([
                    'Is the model organized into sections using tabs?',
                    'Are there clear names for inputs, outputs, and table headers?',
                    'Is each tab organized to separate inputs, outputs, and calculation?',
                    'Are there any comments explaining complex parts of the model?'
                ])
            ],
                          title='Excel'),
            pl.SubSection([
                pl.UnorderedList([
                    'Is the model organized into functions and sections?',
                    'Are all inputs at the top and main outputs at the bottom?',
                    'Are there docstrings, comments, or Jupyter markdown explaining things?',
                    'Does the submitted notebook or Python script have clear sections?',
                    'Are the length of code lines limited to the size of Jupyter cells (no long lines)?',
                    'Are the results of intermediate calculations shown? Should not be just one answer at end.',
                    [
                        'Do variable, function, and class names follow conventions? See',
                        Hyperlink(
                            'https://realpython.com/python-pep8/#naming-conventions',
                            'Naming Conventions')
                    ],
                ])
            ],
                          title='Python')
        ],
                   title='Model Readability'),
        pl.Section([
            "Model formatting is about the visual representation of the model.",
            pl.SubSection([
                pl.UnorderedList([
                    'Are tables formatted nicely?',
                    'Are inputs and outputs sections formatted to separate them from calculations?'
                ])
            ],
                          title='Excel'),
            pl.SubSection([
                pl.UnorderedList([
                    'Are model outputs displayed with nice formatting?',
                    pl.UnorderedList([
                        'Number formatting (percentages are percentages, '
                        'currency has dollar sign, commas, and two decimals, etc.)',
                        'Sentence explaining results is printed',
                        'Tables are used where appropriate and are well formatted',
                        'Plots have axis names and are appropriately sized'
                    ])
                ])
            ],
                          title='Python')
        ],
                   title='Model Formatting'),
        pl.Section([
            "Following the template is about conforming to the requested structure of the project "
            "such that it can be graded in a uniform way.",
            pl.SubSection([
                pl.UnorderedList([
                    'Use any provided template to start from',
                    'Do not move any of the inputs or outputs from the template',
                    'It is fine to change formatting of the inputs and outputs so long as the cell '
                    'reference location stay the same'
                ])
            ],
                          title='Excel'),
            pl.SubSection([
                pl.UnorderedList([
                    'Use any provided template to start from',
                    'Do not change the name of the ModelInputs class and be sure to use model_data as '
                    'the name of the variable containing the inputs',
                    'Do not rename variables in the ModelInputs dataclass. You may add additional variables '
                    'if you wish.',
                    'Keep the inputs at the top and outputs at the bottom',
                    'The instructions for a project may ask you to define certain variables and that they '
                    'should conform to certain data structures. Ensure that you do this and do not use '
                    'a different name or data structure.',
                    'For example, it may ask for cash_flows as a list of numbers. Ensure that you actually '
                    'have numbers in it and not formatted strings. However when you show the output '
                    'you should format it.'
                ])
            ],
                          title='Python')
        ],
                   title='Following the Template'),
    ]
Example #11
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'
        )
    ]
Example #12
0
EXAMPLE_BODY = [
    pl.Chapter([
        'Some content',
        pl.UnorderedList(['a', 'b', 'c']),
    ],
               title='First'),
    pl.Chapter([
        'Chapter content',
        pl.Section([
            'Section content',
            pl.SubSection([
                'Subsection content',
                pl.SubSubSection([
                    'Subsubsubsection content',
                    pl.CiteP('person'),
                ],
                                 title='First sub sub')
            ],
                          title='First sub')
        ],
                   title='First section')
    ],
               title='Second')
]
EXAMPLE_BODY_NEXT_LEVEL_DOWN = [
    pl.Section([
        'Some content',
        pl.UnorderedList(['a', 'b', 'c']),
    ],
               title='First'),
import pyexlatex as pl
import pytest
from pyexlatex.logic.builder import build

from plufthesis.transformers import elevate_sections_by_one_level

SUB_SUB_SECTION = pl.SubSubSection("Sub sub content", title="Sub Sub section")
SUB_SECTION = pl.SubSection(["Sub content", SUB_SUB_SECTION],
                            title="Sub section")
SECTION = pl.Section(["Section content", SUB_SECTION], title="Section")
CHAPTER = pl.Chapter(["Chapter content", SECTION], title='Chapter')

SECTIONS_BY_TEXT = r"""
\section{Section}
Section content
\subsection{Sub section}
Sub content
\subsubsection{Sub Sub section}
Sub sub content
"""

CHAPTERS_BY_TEXT = r"""
\chapter{Chapter}
Chapter content
""" + SECTIONS_BY_TEXT


def test_elevate_sections_objects_success():
    content = build([SECTION])
    revised = elevate_sections_by_one_level(content)
    assert (