#include WORD CashFlow::generateCashFlows(const PurePassThru &purePassThru,Block &cashFlows) { double issBal(purePassThru.issBal()); double tempCPR; short actualMonth; short indexFlows; cashFlows.remove(); indexFlows=cashFlows.size(); cashFlows.insert(&PureCashFlow()); for(short wam=purePassThru.wam();wam>0&&issBal>0.00;wam--) { actualMonth=(purePassThru.origTerm()-wam)+1; if(actualMonth<=30)tempCPR=.002*(double)actualMonth; else tempCPR=.06; cashFlows[indexFlows].beginBal(issBal); cashFlows[indexFlows].smm(1.00-::pow(1.00-(tempCPR*purePassThru.psa()/100.00),1.00/12.00)); if(!indexFlows) { cashFlows[indexFlows].mtgPay((issBal*(purePassThru.wac()/1200.00))/ (1.00-::pow(1.00/(1.00+(purePassThru.wac()/1200.00)),(double)wam))); } else cashFlows[indexFlows].mtgPay(cashFlows[indexFlows-1].mtgPay()); if(issBal<=cashFlows[indexFlows].mtgPay())cashFlows[indexFlows].mtgPay(issBal); cashFlows[indexFlows].netIntPay(issBal*(purePassThru.coupon()/1200.00)); if(!indexFlows)cashFlows[indexFlows].grossIntPay(cashFlows[indexFlows].netIntPay()); else cashFlows[indexFlows].grossIntPay(cashFlows[indexFlows-1].grossIntPay()+cashFlows[indexFlows].netIntPay()); cashFlows[indexFlows].schedPrinPay(cashFlows[indexFlows].mtgPay()-cashFlows[indexFlows].netIntPay()); cashFlows[indexFlows].prepayment(0.00); cashFlows[indexFlows].totPrin(cashFlows[indexFlows].schedPrinPay()+cashFlows[indexFlows].prepayment()); cashFlows[indexFlows].cashFlow(cashFlows[indexFlows].netIntPay()+cashFlows[indexFlows].totPrin()); cashFlows[indexFlows].factor(issBal/purePassThru.issBal()); issBal-=cashFlows[indexFlows].totPrin(); indexFlows=cashFlows.size(); if(1!=wam&&issBal>0.00)cashFlows.insert(&PureCashFlow()); } return cashFlows.size(); } WORD CashFlow::generateCashFlows(const PurePassThru &purePassThru,Block &cashFlows,PrePay prePay) { double issBal(purePassThru.issBal()); double tempCPR; short actualMonth; short indexFlows; cashFlows.remove(); indexFlows=cashFlows.size(); cashFlows.insert(&PureCashFlow()); for(short wam=purePassThru.wam();wam>0&&issBal>0.00;wam--) { actualMonth=(purePassThru.origTerm()-wam)+1; if(actualMonth<=30)tempCPR=.002*(double)actualMonth; else tempCPR=.06; cashFlows[indexFlows].beginBal(issBal); cashFlows[indexFlows].smm(1.00-::pow(1.00-(tempCPR*purePassThru.psa()/100.00),1.00/12.00)); if(!indexFlows)cashFlows[indexFlows].mtgPay((issBal*(purePassThru.wac()/1200.00))/ (1.00-::pow(1.00/(1.00+(purePassThru.wac()/1200.00)),(double)wam))); else cashFlows[indexFlows].mtgPay(cashFlows[indexFlows-1].mtgPay()); if(issBal<=cashFlows[indexFlows].mtgPay())cashFlows[indexFlows].mtgPay(issBal); cashFlows[indexFlows].netIntPay(issBal*(purePassThru.coupon()/1200.00)); if(!indexFlows)cashFlows[indexFlows].grossIntPay(cashFlows[indexFlows].netIntPay()); else cashFlows[indexFlows].grossIntPay(cashFlows[indexFlows-1].grossIntPay()+cashFlows[indexFlows].netIntPay()); cashFlows[indexFlows].schedPrinPay(cashFlows[indexFlows].mtgPay()-cashFlows[indexFlows].netIntPay()); cashFlows[indexFlows].prepayment(prePay.amount()); prePay.period(prePay.period()+1); if(prePay.period()>prePay.frequency()) { prePay.amount(prePay.amount()+prePay.increment()); prePay.period(1); } cashFlows[indexFlows].totPrin(cashFlows[indexFlows].schedPrinPay()+cashFlows[indexFlows].prepayment()); cashFlows[indexFlows].cashFlow(cashFlows[indexFlows].netIntPay()+cashFlows[indexFlows].totPrin()); cashFlows[indexFlows].factor(issBal/purePassThru.issBal()); issBal-=cashFlows[indexFlows].totPrin(); indexFlows=cashFlows.size(); if(1!=wam&&issBal>0.00)cashFlows.insert(&PureCashFlow()); } return cashFlows.size(); } WORD CashFlow::convergePSA(PurePassThru &purePassThru,double convergeFactor,double issueBal,short runMonths) { double cashFlowFactor; double smallestDiff(999); double tempDiff; short closestPSA; for(short psaValue=MinPSA;psaValue=convergeFactor)return psaCurr; if(cashFlowFactor>convergeFactor) { psaFloor=psaCurr; newCurr=(psaCeiling+psaFloor)/2; } else { psaCeiling=psaCurr; newCurr=(psaFloor+psaCeiling)/2; } if(newCurr==psaCurr)return psaCurr; psaCurr=newCurr; } } double CashFlow::factorFlows(const PurePassThru &purePassThru,double issueBalance,short runMonths) { double issBal(purePassThru.issBal()); Block cashFlows; double tempCPR; short actualMonth; short indexFlows; indexFlows=cashFlows.size(); cashFlows.insert(&PureCashFlow()); for(short wam=purePassThru.wam();wam>=purePassThru.wam()-runMonths;wam--) { actualMonth=(purePassThru.origTerm()-wam)+1; if(actualMonth<=30)tempCPR=.002*(double)actualMonth; else tempCPR=.06; cashFlows[indexFlows].beginBal(issBal); cashFlows[indexFlows].smm(1.00-::pow(1.00-(tempCPR*purePassThru.psa()/100.00),1.00/12.00)); cashFlows[indexFlows].mtgPay((issBal*(purePassThru.wac()/1200.00))/ (1.00-::pow(1.00/(1.00+(purePassThru.wac()/1200.00)),(double)wam))); cashFlows[indexFlows].netIntPay(issBal*(purePassThru.coupon()/1200.00)); cashFlows[indexFlows].grossIntPay(issBal*(purePassThru.wac()/1200.00)); cashFlows[indexFlows].schedPrinPay(cashFlows[indexFlows].mtgPay()-cashFlows[indexFlows].grossIntPay()); cashFlows[indexFlows].prepayment(cashFlows[indexFlows].smm()*(issBal-cashFlows[indexFlows].schedPrinPay())); cashFlows[indexFlows].totPrin(cashFlows[indexFlows].schedPrinPay()+cashFlows[indexFlows].prepayment()); cashFlows[indexFlows].cashFlow(cashFlows[indexFlows].netIntPay()+cashFlows[indexFlows].totPrin()); cashFlows[indexFlows].factor(issBal/issueBalance); issBal-=cashFlows[indexFlows].totPrin(); indexFlows=cashFlows.size(); if(1!=wam)cashFlows.insert(&PureCashFlow()); } return cashFlows[runMonths].factor(); }