Case Study

Green Sole
Crop Optimization

An integrated study guide bridging algorithmic problem-solving and CFA financial modelling — where every calculation connects.

LeetCode · DP CFA Level I–II NPV · IRR · DCF
Algorithm
705 Profit
Cash Flows
NPV / IRR
Decision
STEP 01

Algorithmic Layer — Max Profit with K Transactions

Scenario Setup

Green Sole tracks maize prices over 6 seasons. We must find the optimal buy/sell pairs to maximise profit using at most k = 2 transactions.

prices = [100, 180, 260, 310, 40, 535]  |  k = 2
Maize Price — 6 Seasons
Normal Sell Point Buy Point
TRANSACTION 01
Buy at Season 1100
Sell at Season 4310
Profit +210
TRANSACTION 02
Buy at Season 540
Sell at Season 6535
Profit +495
TOTAL OPTIMISED PROFIT 705
How Does the DP Algorithm Work?

We build a 2D DP table where dp[i][j] = max profit using i transactions up to day j.

dp[i][j] = max(dp[i][j-1], prices[j] + maxDiff)
maxDiff = max(maxDiff, dp[i-1][j] - prices[j])

Key insight: maxDiff tracks the best "buy opportunity" seen so far, accounting for profits from previous transactions. This collapses a 3-loop O(kn²) solution into O(kn).

Time: O(k × n)  ·  Space: O(k × n) — optimisable to O(n)

{ } JavaScript Implementation
JAVASCRIPT
function maxProfit(k, prices) {
  // dp[i][j] = max profit with i transactions through day j
  let dp = Array.from({ length: k + 1 }, () =>
    Array(prices.length).fill(0)
  );

  for (let i = 1; i <= k; i++) {
    let maxDiff = -prices[0]; // best "buy" seen so far
    for (let j = 1; j < prices.length; j++) {
      // Option A: skip today | Option B: sell today
      dp[i][j] = Math.max(
        dp[i][j - 1],
        prices[j] + maxDiff
      );
      // Update best buy: buy today vs buy before (with prev tx profit)
      maxDiff = Math.max(
        maxDiff,
        dp[i - 1][j] - prices[j]
      );
    }
  }
  return dp[k][prices.length - 1];
}

console.log(maxProfit(2, [100,180,260,310,40,535]));
// → 705 ✅
STEP 02

Financial Model — Cash Flow Construction

The Bridge

The 705 algorithmic profit per cycle flows directly into the farm's financial model — added to final-year cash flows, feeding the NPV and IRR calculations below.

🧠 Algorithm → 705 Profit
feeds into
💰 Cash Flows (Year 5 + 705)
discounted at 15%
✅ NPV + IRR → Investment Decision
Year Base Farm Return Algo Profit Added Final Cash Flow
0 −500,000 −500,000
1 120,000 120,000
2 150,000 150,000
3 180,000 180,000
4 220,000 220,000
5 260,000 + 705 260,705
STEP 03

NPV Calculation — Manual Breakdown

Discount Rate Construction
BASE RATE
10%
+
RISK PREMIUM
5%
=
ADJUSTED RATE (r)
15%
NPV = Σ [CF_t / (1 + r)^t]    for t = 0 to 5
Year (t) Cash Flow Discount Factor Present Value
0 −500,000 (1.15)⁰ = 1.0000 −500,000.00
1 120,000 (1.15)¹ = 1.1500 104,347.83
2 150,000 (1.15)² = 1.3225 113,422.82
3 180,000 (1.15)³ = 1.5209 118,324.00
4 220,000 (1.15)⁴ = 1.7490 125,786.57
5 260,705 (1.15)⁵ = 2.0114 129,617.34
TOTAL NPV ≈ +91,498
? Why is NPV > 0 a Green Light?

A positive NPV means the project generates more value than its cost of capital. In CFA terms:

  • NPV > 0 → project adds value → ACCEPT
  • NPV < 0 → project destroys value → REJECT
  • NPV = 0 → project earns exactly the required return → indifferent

The risk premium of 5% already accounts for the agricultural uncertainty — so an NPV of ~91k above that hurdle is meaningful.

STEP 04

IRR — Internal Rate of Return

Definition

IRR is the discount rate at which NPV = 0. Compare it against the required return (hurdle rate). If IRR > hurdle rate, the project is viable.

0 = Σ [CF_t / (1 + IRR)^t]  → solve for IRR using Newton-Raphson
Return Comparison Estimated IRR ≈ 18–20%
Hurdle 15%
0%5%10%15%20%
ESTIMATED IRR
~19%
HURDLE RATE
15%
SPREAD
+4%
{ } Newton-Raphson IRR Solver (JS)
JAVASCRIPT
function calculateIRR(cashFlows, guess = 0.1) {
  let rate = guess;
  for (let i = 0; i < 1000; i++) {
    let npv = 0;
    let derivative = 0;
    for (let t = 0; t < cashFlows.length; t++) {
      npv += cashFlows[t] / Math.pow((1 + rate), t);
      derivative -= t * cashFlows[t]
        / Math.pow((1 + rate), t + 1);
    }
    let newRate = rate - npv / derivative;
    if (Math.abs(newRate - rate) < 1e-6) break;
    rate = newRate;
  }
  return rate;
}

const flows = [-500000,120000,150000,180000,220000,260705];
console.log((calculateIRR(flows) * 100).toFixed(2) + "%");
// → ~18.91%
⚡ TOOL

Interactive NPV Calculator

Adjust the Variables

Modify any parameter to see how NPV changes in real time. Try changing the discount rate or the initial investment.

Year 0 (Investment)
Sum of PV (Years 1–5)
NPV
Estimated IRR
Decision
FINAL RECOMMENDATION
Green Sole Recommends: INVEST ✅
NPV > 0 (≈ +91,498)
IRR (~19%) > Hurdle (15%)
Algorithm maximises seasonal returns
TEST

Quick Revision Quiz

1. What is the maximum profit achievable with k=2 transactions on prices [100,180,260,310,40,535]?
A
210
B
495
C
705
D
435
2. The adjusted discount rate of 15% is composed of which two elements?
A
10% base rate + 5% risk premium
B
12% base rate + 3% inflation adjustment
C
IRR minus 4% spread
D
A flat market-determined 15%
3. What does a positive NPV tell a CFA analyst about a project?
A
The project is guaranteed to be profitable
B
The project generates returns above the cost of capital
C
The IRR exactly equals the discount rate
D
Cash flows are positive every year
4. Which algorithmic complexity does the DP solution achieve?
A
O(n²)
B
O(k²·n)
C
O(k × n)
D
O(n log n)