#ifndef investment_H #define investment_H 1 #include "assetAllocation.h" #include "Rate.h" #include "time.h" #include "types.h" // INVESTMENT // Stores the current investment's value, updating each month. class investment { public: // Constructor // input <- asset allocation object (already initialized) // historical rates object (already initialized) // time object (already initialized) // initial investment value // increment amount // boolean true if increment is inflated every month // final investment target // boolean true if investment target should be inflated every month // boolean true if taxes should be computed // (optional) long-term capital gains tax rate // (optional) short-term capital gains and ordinary income tax rate // The tax rates need not be specified if taxes are not being computed. investment(const assetAllocation &aa, const Rates &r, const Time &t, const Dollars &initialInvestmentValue, const Dollars &incrementAmount, const bool inflateIncrement, const Dollars & financialTarget, const bool inflateTarget, const bool taxedP, const Fraction capGainsTaxRate, const Fraction incomeTaxRate) : m_AssetAlloc(aa), m_Time(t), m_Target(financialTarget*100), m_bTInflate(inflateTarget), m_Rates(r) { // assign all parameter data to their member equivalent m_Inc = incrementAmount*100; m_bInflate = inflateIncrement; m_bTax = taxedP; m_CGTax = capGainsTaxRate; m_ITax = incomeTaxRate; // set the initial asset values m_LCStockApr = m_LTGovApr = m_ITGovApr = 0; m_LCStock = 0; m_LTGov = 0; m_ITGov = 0; m_Treas = initialInvestmentValue*100; // ReallocateAssets() moves $ to the proper assets. ReallocateAssets(); } // Modify the investment's value per this month's data. // output-> true if this was the last month of the time frame bool updateInvestmentValue(void) { #ifdef DEBUG cout << *this; #endif // DEBUG CalculateAllIncome(); // calculate all income earned CalculateAllAppreciation(); // calculate all appreciation for assets InflateIncrement(); // inflate the increment if necessary InflateTarget(); // inflate the financial target if necessary if (IsTimeToIncrementAssets()) // if it's time to increment IncrementAssets(); // then increment if (IsTimeToReallocateAssets()) // if it's time to reallocate ReallocateAssets(); // then reallocate if (!EndOfTimeFrame()) { AdvanceMonth(); // advance the time object a month return false; } else { ReallocateAssets(); // pay all taxes at timeframe's end return true; } } // Return the investment's value. Dollars totalValue(void) const { return (m_LCStock + m_LTGov + m_ITGov + m_Treas+50)/100; } // Return the ending financial target. Dollars financialTarget(void) const { return (m_Target+50)/100; } private: // helper operations // DESCRIPTION: Increments the assets by the periodic increment/decrement // amount. // PRECONDITION: None. // POSTCONDITION: The assets are incremented according to the appropriate // asset allocation scheme. void IncrementAssets() { if (!m_bTax) { m_LCStock += static_cast(m_Inc * m_AssetAlloc.findAllocation(m_Time, largeCoStocks)+0.5); m_LTGov += static_cast(m_Inc * m_AssetAlloc.findAllocation(m_Time, LTGovtBonds)+0.5); m_ITGov += static_cast(m_Inc * m_AssetAlloc.findAllocation(m_Time, ITGovtBonds)+0.5); m_Treas += static_cast(m_Inc * m_AssetAlloc.findAllocation(m_Time, Treas)+0.5); } else m_Treas += m_Inc; return; } // DESCRIPTION: Predicate determining whether it's time to increment // (deposit/withdrawal) the assets. bool IsTimeToIncrementAssets() const { return m_Time.incrementP(); } // DESCRIPTION: Predicate determining whether it's the last month of the // time frame. bool EndOfTimeFrame() const { return m_Time.endOfTimeFrameP(); } // DESCRIPTION: Inflates the increment amount. // PRECONDITION: None. // POSTCONDITION: The increment amount is inflated. void InflateIncrement() { if (m_bInflate) // if to inflate // okay, i'm a little unclear if this will return inflation data, // but i'm assuming so for now m_Inc = static_cast(m_Inc * (1 + m_Rates.IncomeReturn(m_Time, inflation))+0.5); #ifdef DEBUG cout << "Amount to increment: " << m_Inc << endl; #endif // DEBUG } // DESCRIPTION: Inflates the financial target. // PRECONDITION: m_Target and m_bTInflate have values. // POSTCONDITION: The target amount is inflated if required. void InflateTarget() { if (m_bTInflate) // if to inflate // okay, i'm a little unclear if this will return inflation data, // but i'm assuming so for now m_Target = static_cast(m_Target * (1 + m_Rates.IncomeReturn(m_Time, inflation))+0.5); #ifdef DEBUG cout << "Financial target: " << m_Target << endl; #endif // DEBUG } // DESCRIPTION: Predicate determining whether it's time to reallocate the assets // and pay capital gains tax. bool IsTimeToReallocateAssets() const { return !m_bTax || m_Time.sellAssetsP(); } // DESCRIPTION: Calculates and applies all income earned from assets. // PRECONDITION: None. // POSTCONDITION: The income is added to the treasury asset. void CalculateAllIncome() { const Rate TaxFree = 1 - m_ITax; // rate for tax-free income // calculate all income and add to the treasury asset total m_Treas += static_cast(m_Treas * m_Rates.IncomeReturn(m_Time, Treas) * TaxFree+0.5); m_Treas += static_cast(m_ITGov * m_Rates.IncomeReturn(m_Time, ITGovtBonds) * TaxFree+0.5); m_Treas += static_cast(m_LTGov * m_Rates.IncomeReturn(m_Time, LTGovtBonds) * TaxFree+0.5); m_Treas += static_cast(m_LCStock * m_Rates.IncomeReturn(m_Time, largeCoStocks) * TaxFree+0.5); } // DESCRIPTION: Calculates each asset's appreciation. // PRECONDITION: If appropriate, m_LCStockApr, m_LTGovApr, m_ITGovApr // have values. // POSTCONDITION: The appreciation is added to each asset's Cents value, and // the appreciation total (since last reallocation) is saved in each asset's // appreciation value (this is for calculating capital gains taxes later). void CalculateAllAppreciation() { Cents TmpApr = 0; TmpApr = static_cast(m_LCStock * m_Rates.CapApprecReturn(m_Time, largeCoStocks)+0.5); m_LCStock += TmpApr; m_LCStockApr += TmpApr; TmpApr = static_cast(m_LTGov * m_Rates.CapApprecReturn(m_Time, LTGovtBonds)+0.5); m_LTGov += TmpApr; m_LTGovApr += TmpApr; TmpApr = static_cast(m_ITGov * m_Rates.CapApprecReturn(m_Time, ITGovtBonds)+0.5); m_ITGov += TmpApr; m_ITGovApr += TmpApr; } // DESCRIPTION: Reallocates the assets. // PRECONDITIONS: If appropriate, m_LCStockApr, m_LTGovApr, m_ITGovApr // have values. // Income taxes have already been paid. // POSTCONDITION: The assets are reallocated. Reallocation is based upon // the current total worth (the sum of all current assets) and the // the asset allocation scheme. void ReallocateAssets() { Cents Total = 0; // calculate total worth Total = m_LCStock + m_LTGov + m_ITGov + m_Treas; if (m_bTax) { Cents Taxes = 0; Rate TaxRate = 0; // if the holding period is <= one year *or* this is the end of the time frame // so we might have held our assets for an amount of time inequal to the // holding period (e.g., holding period of 18 months, time frame of 24) if (m_Time.GetHoldingPeriod() <= 12 || (EndOfTimeFrame() && m_Time.GetLastHoldingPeriod() <= 12) ) TaxRate = m_ITax; // else apply income tax rate else TaxRate = m_CGTax; // apply capital gains tax rate // calculate taxes by taking total appreciation amount and multiplying by // the tax rate being used Taxes = max(static_cast(0), static_cast((m_LCStockApr + m_LTGovApr + m_ITGovApr) * TaxRate+0.5)); // reset appreciation data m_LCStockApr = m_LTGovApr = m_ITGovApr = 0; // subtract taxes from total Total -= Taxes; } // reallocate by multiplying total by the allocation amount m_LCStock = static_cast(Total * m_AssetAlloc.findAllocation(m_Time, largeCoStocks)+0.5); m_LTGov = static_cast(Total * m_AssetAlloc.findAllocation(m_Time, LTGovtBonds)+0.5); m_ITGov = static_cast(Total * m_AssetAlloc.findAllocation(m_Time, ITGovtBonds)+0.5); m_Treas = static_cast(Total * m_AssetAlloc.findAllocation(m_Time, Treas)+0.5); } // DESCRIPTION: Advances the time object one month. // PRECONDITION: None. // POSTCONDITION: The time object is advanced. void AdvanceMonth() { m_Time.nextMonth(); } private: // data assetAllocation m_AssetAlloc; Time m_Time; Cents m_LCStockApr; Cents m_LTGovApr; Cents m_ITGovApr; Cents m_LCStock; Cents m_LTGov; Cents m_ITGov; Cents m_Treas; Cents m_Inc; // increment amount bool m_bInflate; // inflate increment Cents m_Target; // financial target bool m_bTInflate; // inflate financial target bool m_bTax; Rate m_CGTax; Rate m_ITax; const Rates &m_Rates; #ifdef DEBUG friend ostream& operator<<(ostream& out, const investment & i) { out << "stock=" << i.m_LCStock << "\t" << i.m_LCStockApr << endl; out << "LTGov=" << i.m_LTGov << "\t" << i.m_LTGovApr << endl; out << "ITGov=" << i.m_ITGov << "\t" << i.m_ITGovApr << endl; out << "Treas=" << i.m_Treas << endl; return out; } #endif // DEBUG }; #endif