// John Healy // revised by Jeffrey D. Oldham, 2000Apr28 #include #include #include #include "investment.h" #include "statistics.h" #include "date.h" #include "types.h" // Parse the command-line parameters. // Returns true only if the parsing succeeds. bool GetInput(const int ItemCount, char *Input[], Dollars & InitialAmount, Dollars & IncrementAmount, bool & InflatedIncrement, Dollars & TargetAmount, bool & InflatedTarget, unsigned long & TimeFrame, unsigned long & TimeIncrement, bool &Age_Varying_Allocation, assetFormulaChoice & Age_Formula, unsigned long & Age, Fraction & LCStock_Alloc, Fraction & LTBond_Alloc, Fraction & ITBond_Alloc, Fraction & Treasury_Alloc, bool &Taxes, Fraction & Cap_Gains_TaxRate, Fraction & Income_TaxRate, unsigned long & AssetHoldTime, double & Monthly_RateMod, string & CA_StockFile, string & IR_StockFile, string & CA_LTBondFile, string & IR_LTBondFile, string & CA_ITBondFile, string & IR_ITBondFile, string & TreasuryFile, string & InflationFile) { unsigned int nextArg = 0; if (!(ItemCount == 21 || ItemCount == 23 || ItemCount == 24 || ItemCount == 26)) { cerr<(0), 0); #ifdef DEBUG_INPUT cout << "Initial Amount: " << InitialAmount << endl;; #endif // DEBUG_INPUT IncrementAmount=strtol(Input[++nextArg], static_cast(0), 0); #ifdef DEBUG_INPUT cout << "Increment Amount: " << IncrementAmount << endl; #endif // DEBUG_INPUT if (strcmp(Input[++nextArg], "0") == 0) InflatedIncrement=false; else if (strcmp(Input[nextArg], "1") == 0) InflatedIncrement=true; else { cerr << "increment inflation must be true or false"; return false; } #ifdef DEBUG_INPUT cout << "Inflated Increment?: " << InflatedIncrement << endl; #endif // DEBUG_INPUT TargetAmount=strtoul(Input[++nextArg], static_cast(0), 0); #ifdef DEBUG_INPUT cout << "TargetAmount: " << TargetAmount << endl; #endif // DEBUG_INPUT if (strcmp(Input[++nextArg], "0") == 0) InflatedTarget=false; else if (strcmp(Input[nextArg], "1") == 0) InflatedTarget=true; else { cerr << "financial target inflation must be true or false"; return false; } #ifdef DEBUG_INPUT cout << "Inflated Financial Target?: " << InflatedTarget << endl; #endif // DEBUG_INPUT // Obtain the time amounts. TimeFrame=strtoul(Input[++nextArg], static_cast(0), 0); if (TimeFrame==0) { cerr << "time frame must be a positive number of months"; return false; } #ifdef DEBUG_INPUT cout << "TimeFrame: " << TimeFrame << endl; #endif // DEBUG_INPUT TimeIncrement=strtoul(Input[++nextArg], static_cast(0), 0); if (TimeIncrement==0) { cerr << "increment time must be a positive number of months"; return false; } #ifdef DEBUG_INPUT cout << "TimeIncrement: " << TimeIncrement << endl; #endif // DEBUG_INPUT // Obtain the asset allocation. if (strcmp(Input[++nextArg], "0") == 0) Age_Varying_Allocation=false; else if (strcmp(Input[nextArg], "1") == 0) Age_Varying_Allocation=true; else { cerr << "age-varying asset allocation choice must be either true or false"; return false; } #ifdef DEBUG_INPUT cout << "Age Allocation?: " << Age_Varying_Allocation << endl; #endif // DEBUG_INPUT if (Age_Varying_Allocation) { Age_Formula=static_cast(strtoul(Input[++nextArg], static_cast(0), 0)); if (Age_Formula!=conservative && Age_Formula!=moderate && Age_Formula!=aggressive) { cerr << "incorrect asset age formula choice\n"; return false; } #ifdef DEBUG_INPUT cout << "Age Formula (1, 2, or 3): " << static_cast(Age_Formula) << endl; #endif // DEBUG_INPUT Age = strtoul(Input[++nextArg], static_cast(0), 0); } else { #ifdef DEBUG_INPUT cout << "Fixed asset allocation.\n"; #endif // DEBUG_INPUT LCStock_Alloc=strtoul(Input[++nextArg], static_cast(0), 0) / 100.0; if (LCStock_Alloc>1.0) { cerr << "large-company stock allocation too large\n"; return false; } #ifdef DEBUG_INPUT cout << "Stock_Alloc: " << LCStock_Alloc << endl; #endif // DEBUG_INPUT LTBond_Alloc=strtoul(Input[++nextArg], static_cast(0), 0) / 100.0; if (LTBond_Alloc>1.0) { cerr << "long-term government bond allocation too large\n"; return false; } #ifdef DEBUG_INPUT cout << "LTBond_Alloc: " << LTBond_Alloc << endl; #endif // DEBUG_INPUT ITBond_Alloc=strtoul(Input[++nextArg], static_cast(0), 0) / 100.0; if (ITBond_Alloc>1.0) { cerr << "intermediate-term government bond allocation too large\n"; return false; } #ifdef DEBUG_INPUT cout << "ITBond_Alloc: " << ITBond_Alloc << endl; #endif // DEBUG_INPUT Treasury_Alloc=strtoul(Input[++nextArg], static_cast(0), 0) / 100.0; if (Treasury_Alloc>1.0) { cerr << "intermediate-term government bond allocation too large\n"; return false; } #ifdef DEBUG_INPUT cout << "Treasury_Alloc: " << Treasury_Alloc << endl; #endif // DEBUG_INPUT if (LCStock_Alloc + LTBond_Alloc + ITBond_Alloc + Treasury_Alloc > 1.00001) { cerr << "assets overallocated\n"; return false; } } // Obtain the tax-related input. if (strcmp(Input[++nextArg], "0")==0) Taxes=false; else if (strcmp(Input[nextArg], "1")==0) Taxes=true; else { cerr << "boolean whether to charge taxes must be true or false\n"; return false; } #ifdef DEBUG_INPUT cout << "Taxes?: " << Taxes << endl; #endif // DEBUG_INPUT if (Taxes) { Cap_Gains_TaxRate=strtoul(Input[++nextArg], static_cast(0), 0) / 100.0; if (Cap_Gains_TaxRate>1.0) { cerr << "long-term capital appreciation tax rate is too large\n"; return false; } #ifdef DEBUG_INPUT cout << "Capital Gains Tax Rate: " << Cap_Gains_TaxRate << endl; #endif // DEBUG_INPUT Income_TaxRate=strtoul(Input[++nextArg], static_cast(0), 0) / 100.0; if (Income_TaxRate > 1.0) { cerr << "ordinary income tax rate is too large\n"; return false; } #ifdef DEBUG_INPUT cout << "Income Tax Rate: " << Income_TaxRate << endl; #endif // DEBUG_INPUT AssetHoldTime=strtoul(Input[++nextArg], static_cast(0), 0); if (AssetHoldTime==0) { cerr << "asset-holding time must be a positive number of months\n"; return false; } #ifdef DEBUG_INPUT cout << "Asset Holding Time: " << AssetHoldTime << endl; #endif // DEBUG_INPUT } // Obtain the monthly modification amount. Monthly_RateMod=strtod(Input[++nextArg], static_cast(0)) / 100.0; #ifdef DEBUG_INPUT cout << "Monthly Rate Modification: " << Monthly_RateMod << endl; #endif // DEBUG_INPUT // Read the data filenames. CA_StockFile= Input[++nextArg]; #ifdef DEBUG_INPUT cout << "CA_StockFile: " << CA_StockFile << endl; #endif // DEBUG_INPUT IR_StockFile=Input[++nextArg]; #ifdef DEBUG_INPUT cout << "IR_StockFile: " << IR_StockFile << endl; #endif // DEBUG_INPUT CA_LTBondFile=Input[++nextArg]; #ifdef DEBUG_INPUT cout << "CA_LTBondFile: " << CA_LTBondFile << endl; #endif // DEBUG_INPUT IR_LTBondFile=Input[++nextArg]; #ifdef DEBUG_INPUT cout << "IR_LTBondFile: " << IR_LTBondFile << endl; #endif // DEBUG_INPUT CA_ITBondFile=Input[++nextArg]; #ifdef DEBUG_INPUT cout << "CA_ITBondFile: " << CA_ITBondFile << endl; #endif // DEBUG_INPUT IR_ITBondFile=Input[++nextArg]; #ifdef DEBUG_INPUT cout << "IR_ITBondFile: " << IR_ITBondFile << endl; #endif // DEBUG_INPUT TreasuryFile=Input[++nextArg]; #ifdef DEBUG_INPUT cout << "TreasuryFile: " << TreasuryFile << endl; #endif // DEBUG_INPUT InflationFile=Input[++nextArg]; #ifdef DEBUG_INPUT cout << "InflationFile: " << InflationFile << endl; #endif // DEBUG_INPUT return true; } int main(int argc, char *argv[]) { //Program Inputs// /*1*/ Dollars InitialAmount= 0; /*2*/ Dollars IncrementAmount= 0; /*3*/ bool InflatedIncrement=false; /*4*/ Dollars TargetAmount= 0; /*5*/ bool InflatedTarget=false; /*6*/ unsigned long TimeFrame=0; /*7*/ unsigned long TimeIncrement=0; /*8*/ bool Age_Varying_Allocation=false; /*9*/ assetFormulaChoice Age_Formula= none; unsigned long Age = 0; /*10*/ Fraction LCStock_Alloc= 0.0; /*11*/ Fraction LTBond_alloc= 0.0; /*12*/ Fraction ITBonds_Alloc= 0.0; /*13*/ Fraction Treasury_Alloc= 0.0; /*14*/ bool Taxes=false; /*15*/ Fraction Cap_Gains_TaxRate = 0.0; /*16*/ Fraction Income_TaxRate = 0.0; /*17*/ unsigned long AssetHoldTime=0; /*18*/ double Monthly_RateMod=0.0; /*19*/ string CA_StockFile; /*20*/ string IR_StockFile; /*21*/ string CA_LTBondFile; /*22*/ string IR_LTBondFile; /*23*/ string CA_ITBondFile; /*24*/ string IR_ITBondFile; /*25*/ string TreasuryFile; /*26*/ string InflationFile; //End of Inputs// if (!GetInput(argc, argv, InitialAmount, IncrementAmount, InflatedIncrement, TargetAmount, InflatedTarget, TimeFrame, TimeIncrement, Age_Varying_Allocation, Age_Formula, Age, LCStock_Alloc, LTBond_alloc, ITBonds_Alloc, Treasury_Alloc, Taxes, Cap_Gains_TaxRate, Income_TaxRate, AssetHoldTime, Monthly_RateMod, CA_StockFile, IR_StockFile, CA_LTBondFile, IR_LTBondFile, CA_ITBondFile, IR_ITBondFile, TreasuryFile, InflationFile)) { cerr << argv[0] << ": unable to parse the command-line arguments\n"; cout << "5\n"; throw "unable to parse the command-line arguments"; } // Perform the simulation. // create all the necessary objects statistics Stats; Rates HistRates(Monthly_RateMod, CA_StockFile, IR_StockFile, CA_LTBondFile, IR_LTBondFile, CA_ITBondFile, IR_ITBondFile, TreasuryFile, InflationFile); assetAllocation aa(Age_Varying_Allocation ? Age_Formula : none, LCStock_Alloc, LTBond_alloc, ITBonds_Alloc, Treasury_Alloc); for (Date d(HistRates.firstDate()); d + (TimeFrame-1) <= HistRates.lastDate(); ++d) { Time tm(d.year(), d.month(), TimeIncrement, AssetHoldTime, TimeFrame, Age); investment Investments(aa, HistRates, tm, InitialAmount, IncrementAmount, InflatedIncrement, TargetAmount, InflatedTarget, Taxes, Cap_Gains_TaxRate, Income_TaxRate); while (!Investments.updateInvestmentValue()) ; Stats.nextValue(Investments.totalValue(), Investments.financialTarget()); } // Print the answer. cout << Stats << endl; return EXIT_SUCCESS; }