import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

public class MCInvestSample {

	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Data
		int[] year = {1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009};
		double[] stockReturn = {0.946100, 1.312000, 1.081200, 0.813800, 1.182100, 1.196700, 0.860500, 1.101500, 1.290700, 1.054500, 1.271000, 1.258300, 1.115100, 1.371000, 1.475700, 0.905400, 0.772800, 0.558000, 0.941900, 1.567900, 0.919900, 1.549300, 1.325500, 0.678900, 1.175000, 1.029800, 0.910900, 0.909100, 1.217400, 1.236000, 1.196700, 1.393500, 0.879500, 1.025600, 1.095100, 1.159600, 1.342800, 1.231000, 1.183500, 0.992000, 1.559900, 1.282200, 1.063800, 0.907000, 1.434000, 1.115900, 0.992600, 1.285100, 0.908000, 1.230400, 1.165900, 1.124500, 0.896400, 1.244500, 1.110300, 0.913700, 1.036000, 1.145400, 1.191500, 0.849700, 0.730500, 1.384600, 1.242000, 0.922200, 1.064100, 1.186900, 1.327600, 0.946700, 1.212200, 1.231300, 1.059600, 1.322400, 1.190600, 1.056900, 1.166400, 1.320000, 0.965800, 1.309500, 1.076000, 1.101700, 1.011900, 1.380200, 1.230600, 1.336700, 1.287300, 1.211100, 0.908900, 0.880200, 0.777300, 1.287200, 1.108200, 1.047900, 1.157400, 1.054600, 0.627800, 1.271100};
		double[] inflation = {1.010000, 1.020000, 1.126000, 1.181000, 1.204000, 1.145000, 1.026000, 0.892000, 0.977000, 1.024000, 1.000000, 1.035000, 0.989000, 0.977000, 0.988000, 1.006000, 0.936000, 0.907000, 0.897000, 1.008000, 1.015000, 1.030000, 1.014000, 1.029000, 0.972000, 1.000000, 1.007000, 1.099000, 1.090000, 1.030000, 1.023000, 1.022000, 1.181000, 1.088000, 1.030000, 0.979000, 1.059000, 1.060000, 1.008000, 1.007000, 0.993000, 1.004000, 1.030000, 1.029000, 1.018000, 1.017000, 1.014000, 1.007000, 1.013000, 1.016000, 1.010000, 1.019000, 1.035000, 1.030000, 1.047000, 1.062000, 1.056000, 1.033000, 1.034000, 1.087000, 1.123000, 1.069000, 1.049000, 1.067000, 1.090000, 1.133000, 1.125000, 1.089000, 1.038000, 1.038000, 1.039000, 1.038000, 1.011000, 1.044000, 1.044000, 1.046000, 1.061000, 1.031000, 1.029000, 1.027000, 1.027000, 1.025000, 1.033000, 1.017000, 1.016000, 1.027000, 1.034000, 1.016000, 1.024000, 1.019000, 1.033000, 1.034000, 1.025000, 1.041000, 1.001000, 1.027000};
		int numYears = year.length;
		
		// Assumptions - feel free to change (suggested ranges in parentheses)
		int workYears = 45; // number of years you expect to work (35-45)
		double savingsRate = .20; // fraction of salary invested for retirement (.1-.2)
		double incomeReplGoal = .70; // retirement goal of replacing fraction of last salary at retirement... (.6-.85)
		double withdrawRate = 0.04; // ... given an assumption that one can sustainably withdraw this percentage of savings annually. (.03 - .05)
		double incomeGrowthBeyondCPI = 0.01; // assumed income growth beyond inflation (???)
		double initialSavings = 0.25; // initial savings expressed as a multiple of initial salary (e.g. initial savings $10K / initial salary $50K = .20)
		// Also assumed: Investment is 100% in broad domestic U.S. stocks.
		
		int numTrials = 1000000;
		Random random = new Random();
		int successCount = 0;
		ArrayList<Double> retIncomes = new ArrayList<>();
		ArrayList<Double> goalIncomes = new ArrayList<>();
		// TO DO - implement Monte Carlo retirement savings simulation
		for (int t = 0; t < numTrials; t++) {
			double cpi = 1; // reference initial consumer price index
			double income = 1; // initial unit of annual income
			double savings = initialSavings; 
			for (int y = 0; y < workYears; y++) {
				int i = random.nextInt(numYears);
				savings = savings * stockReturn[i] + income * savingsRate;
				cpi = cpi * inflation[i];
				income = income * (inflation[i] + incomeGrowthBeyondCPI);
			}
			double retIncome = savings * withdrawRate;
			retIncomes.add(retIncome);
			double goalIncome = income * incomeReplGoal;
			goalIncomes.add(goalIncome);
			if (retIncome > goalIncome)
				successCount++;
		}
		System.out.println("Goal success rate: " + (double) successCount / numTrials);
		Collections.sort(retIncomes);
		System.out.println("Median retirement income: " + retIncomes.get(numTrials / 2));
		Collections.sort(goalIncomes);
		System.out.println("Median goal income: " + goalIncomes.get(numTrials / 2));
	}

}
