割引キャッシュフロー計算

コーポレートファイナンスを勉強中です。…ていっても1月以上かけて300ページちょっとしか読めてないんですけど…
で、割引キャッシュフローを計算する問題がいっぱい出てきます。

0年 1年 2年
設備 -100
販促 -50 -30 -20
費用 -50 -100 -120
売上 150 300 360

みたいな表があって、NPVを計算しなさい、て問題がいっぱい書いてあるんですけど、ちょっと計算が面倒なのではしょってました。
ちょっと電計機に計算させれば済む事をしないなんてソフトウェア技術者の名折れです。このままではいけません。そこで、この表を

[
    [-100],
    [-50, -30, -30],
    [-50,-100,-120],
    [100, 200, 240],
]

みたいに[C0, C1, C2, …,Cn]のようなキャッシュフローのリストのリストで投入してNPVを計算できるようなスクリプトを書いてみることにしました。

/** 現在価値 = 将来のキャッシュフロー / (1 + 割引率)^期間 */
class PresentValue {
    Number futureValue
    Number earningRate = 0.1G
    int years = 0
    
    def getPv(){ futureValue / ((1+earningRate) ** years) }
}

/** NPV(純現在価値) = Σ(各時期でのキャッシュフローの現在価値) */
class NetPresentValue {
    def presentValues = []
    
    public NetPresentValue(Map properties = [:], List<Number> futureValues) {
        int years = 0
        presentValues = futureValues.collect{
            new PresentValue(properties + [futureValue:it, years:years++])
        }
    }
    
    Number getNpv(){ presentValues*.pv.sum() }
}

/* 動作確認 */
// 0年目のみならNPV = CF
assert (new NetPresentValue([40]).npv == 40)
// デフォルト割引率の1割を相殺して将来価値を計算 
assert ((int)new NetPresentValue([-4000, (2100 * 1.1), (2100 * 1.1**2)]).npv == 200) 
// 割引率2割を指定して、同様に年率2割の将来価値と相殺 
assert ((int)new NetPresentValue([-4000, (2100 * 1.2), (2100 * 1.2**2)], earningRate:0.2).npv == 200)

PresentValue#getPvとかNetPresentValue#getNpvとか、かっこわるい事この上ありません。
計算前の情報は将来のキャッシュフローやその集合なので、そう言った名前をつけるべきだったと思います。そもそもOOよりも関数型の方が素直な気もしますが、ちょっとデータ弄るとかがめんどくさくなりそうだったので、小細工しやすいようになれたOOで書きました。
まぁ用は足りるので、よしとします。

これで、

[
    [-100],
    [-50, -30, -30],
    [-50,-100,-120],
    [100, 200, 240],
].collect{new NetPresentValue(it)}*.npv.sum()

とやればデフォルトの割引率1割でNPV計算、

[
    [-100],
    [-50, -30, -30],
    [-50,-100,-120],
    [100, 200, 240],
].collect{new NetPresentValue(it, earningRate:0.2)}*.npv.sum()

とやれば割引率2割でのNPV計算、が出来るようになりました。

うーん、もうちょっと…手を入れたいですねー。