Mini Project 1: A small tool

Due Sunday, 10/11, 11:59 PM

On this page
  1. How to start
  2. A · A Loan Repayment Schedule
  3. B · A Reorder Simulation
  4. C · Rebalancing a Portfolio
  5. D · Your Own Option
  6. Whichever You Choose
  7. Submit
  8. Grading

Build a small tool in Python that answers a real question. Its inputs sit together at the top, so changing one changes every result after it. Choose one option below: A, B, C or D. D is a tool of your own, about as much work as the others, and needs no approval.

How to start#

  1. Open the starter notebook, click Download the file, and save it in your course repository as projects/mp1/<your-tool>.py, named for what it does, such as loan-schedule.py.
  2. Fill in section 1, the question, and section 2, your plan in words, before you ask your agent anything. Commit with the message mp1: plan before AI.
  3. Try each step yourself first, then work with your agent. When it writes a line you could not have written yourself, ask it to explain that line before you keep it. Commit as you go.
Role Where it applies
By hand Your plan, and your first attempt at each step
AI writes, you check Any code your agent writes, read and tested before you keep it
You direct, you verify The Going further part
You choose the question Your own option, if you choose D

A · A Loan Repayment Schedule#

A friend is buying a $500,000 condo with 20% down and has to choose a mortgage for the other $400,000. The lender offers the national averages from Freddie Mac's weekly survey for September 24, 2026: 7.03% for 30 years, 6.42% for 15. The 30-year payment is lower every month and the 15-year costs less in total. Your friend wants the numbers side by side before signing, and wants to be able to change them when the lender's quote comes in.

loan_amount = 400000
annual_rates = {30: 0.0703, 15: 0.0642}

The main task

  • The monthly payment for each term, loan_amount * r / (1 - (1 + r) ** -n), where r is that term's annual rate divided by 12 and n is the number of months. Round it to the cent.
  • A schedule with one row per month: month, payment, interest, principal paid, and the balance left. Each month's interest is the balance times r, rounded to the cent. The last payment is whatever brings the balance to exactly zero.
  • The total interest over each loan, and one sentence comparing the two.

You may need range(1, n + 1) to count the months, and round(x, 2) to round to the cent.

Going further

  • Pay an extra $200 every month. How many months, and how much interest, does that save on each loan?
  • Refinance the 30-year loan: after five years the rate falls to 6%, and refinancing costs $6,000. In which month do the savings overtake the cost?
  • Add sliders with mo.ui.slider for the rate and the extra payment, so somebody who does not write code can try their own numbers.
  • Chart the balance over time for both loans.

B · A Reorder Simulation#

A coffee shop near campus goes through eight to 20 cartons of oat milk a day. Its distributor delivers in lots of 100 cartons, three days after the order is placed. When the shop runs out, customers who wanted oat milk walk out, and when it orders too early, cartons sit in a small refrigerator it needs for other things. The owner wants to know how low stock should fall before the next order goes in.

starting_stock = 60
order_quantity = 100
lead_time_days = 3
reorder_points = [20, 30, 40, 50]
daily_demand = [12, 15, 9, 14, 18, 11, 10, 16, 13, 17, 8, 12, 20, 14, 11,
                9, 15, 13, 16, 12, 10, 14, 19, 11, 13, 15, 9, 12, 17, 14]

The rules for one day

  1. Any delivery due today arrives first.
  2. Sell up to today's demand. Demand you cannot meet is lost.
  3. At the end of the day, add the stock on hand to everything already ordered and not yet delivered. If that total is at or below the reorder point, place an order. An order placed at the end of day 2 arrives at the start of day 5.

The main task

  • A table with one row per day for a reorder point of 40: day, starting stock, arrived, demand, sold, lost, ending stock, and units ordered.
  • The same simulation for every reorder point in the list, compared in one table: units lost, days with a lost sale, orders placed, and average ending stock over the 30 days.
  • One sentence recommending a reorder point, with the numbers that justify it.

You may need a loop inside a loop, or a function written with def, to run the same simulation for each reorder point.

Going further

  • Put a cost on each part: $0.50 a carton for each night in the refrigerator, $40 delivery fee for each order, $8 of lost margin for each carton the shop could not sell. Which reorder point from 10 to 80 costs least?
  • Generate a year of random demand with a fixed seed, and find out whether your recommendation still holds.
  • Make the order quantity a second input and search both together.
  • Add a slider for the reorder point, so the owner can try one, and a chart of stock over the 30 days.

C · Rebalancing a Portfolio#

A client's account holds six stocks and $5,000 in cash. Last January the client and an advisor agreed on target weights, and a year of price moves has pulled the account away from them. Tesla, for one, has grown to almost a third of the account, against a target of 15%. Once a year the advisor puts it back, and the brokerage trades whole shares only. The prices below are from the latest statement, the same six holdings as in notebook 2.

holdings = [
    ("AAPL", 100, 173.93),
    ("MSFT", 50, 319.53),
    ("GOOG", 80, 131.36),
    ("AMZN", 200, 129.33),
    ("NVDA", 20, 410.17),
    ("TSLA", 150, 255.70),
]
cash = 5000.00
target_weights = {"AAPL": 0.20, "MSFT": 0.20, "GOOG": 0.15,
                  "AMZN": 0.15, "NVDA": 0.15, "TSLA": 0.15}

The rules

  • The portfolio's value is every holding at its price, plus the cash.
  • The targets add up to 100%, so the cash is invested as well. Whatever is left after rounding down stays as cash.
  • Each holding's target in dollars is that value times its weight. Its target in shares is the dollar target divided by the price, rounded down to a whole share. A target of $10,000 at a price of $300, for instance, is 33 shares, since 33.3 rounds down to 33.
  • Trades happen at the listed prices, with no fees, so the order of the trades does not change the result.

The main task

  • A table: ticker, shares now, shares at target, shares to buy or sell (positive to buy, negative to sell), value after, and weight after, as a share of the whole portfolio including the cash left.
  • The cash left once all the trades are done. It must not be negative.
  • How far each weight ends from its target, in percentage points (a weight of 19.5% against a target of 20% is 0.5 of a point below), and one sentence on whether that is close enough.

You may need // to round down to whole shares, and abs() to measure a gap whatever its sign.

Going further

  • Use today's prices from yfinance in place of the listed ones.
  • Charge $5 a trade and skip any trade under $500. How far from target does that leave the portfolio?
  • Rebalance only the holdings that have drifted more than five percentage points from their target.
  • Let a user set the targets with sliders, and refuse any set that does not add up to 100%.

D · Your Own Option#

Build a tool of your own, in a field you know, about as much work as A, B or C. Its main task needs:

  • Its inputs together in one cell at the top
  • A loop that carries something from one step to the next, or that works through more than one collection
  • A table of results and a sentence that answers the question

Choose your own Going further, and describe it in section 8.

Whichever You Choose#

The main task

  • Plain Python only: lists, dictionaries, tuples, loops, conditions and f-strings. It imports nothing beyond what the starter already has, so no pandas, no polars, and none of the other libraries an agent tends to suggest. If your agent imports a library or writes a line you have not met, such as a lambda, ask it to do the same thing in plain Python.
  • Its data lives in the notebook and it reads no file. Type the inputs in; for your own option you may instead generate them with faker, in the inputs cell only (uv add faker first). Everything after the inputs is plain Python.
  • Print your result tables with print and f-strings, with the columns lined up, as in f"{month:>5} {payment:>10,.2f}".
  • Section 6, How I know these numbers are right, reaches at least one result a second, independent way. For instance: the principal paid adds up to the loan; stock at the start, plus deliveries, minus sales, equals stock at the end; the portfolio is worth the same before and after the trades. Another way is an input whose answer you know without the code: zero demand every day leaves the stock at 60 with no orders; one holding with a target of 100% and no cash needs no trade.
  • Section 7 answers: Pick one piece of AI output you did not accept as-is. What did it give you, what did you change, and how did you know? Point to the commit or the cell. If the agent got it right the first time: What did you do to verify that?

Going further

  • It is required, and any direction counts. Take at least one step past the main task, either one of the ideas listed under your option or one of your own. It does not have to work. Be ambitious here, and use your agent as much as you like. Describe what you tried in section 8.
  • Any library is allowed, except one that needs an API key: add it with uv add so it is recorded in pyproject.toml, and import it only in a Going further cell.
  • A file is allowed: a CSV in projects/mp1/public/, read with mo.notebook_location() / "public" / "<file>.csv", as in Publishing a Notebook. A path written any other way breaks when marimo starts from another folder. Your repository is public, so use only data you would publish.
  • Publishing is optional this time. To publish, follow Publishing a Notebook.

Submit#

The link to your notebook on GitHub, in this form:

https://github.com/<your-github-username>/<course-code>/blob/main/projects/mp1/<your-tool>.py

Grading#

What I look at Points
The main task runs, and its results are right 4
Section 6 reaches one result a second way, and the two agree 2
Your plan was committed before any code from your agent, and section 7 points to a commit or a cell 2
Section 8 describes a Going further you tried 1
The question and your answer are clear to somebody outside this course 1

The table above is a guide. I read each notebook as a whole.

Last updated: Thursday, 10/8/2026