Created
April 6, 2012 00:54
-
-
Save gregturn/2315585 to your computer and use it in GitHub Desktop.
Finance app with scala part 3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def absChange(relChange:Double) = 1 + relChange/100.0 | |
| def relChange(absChange:Double) = 100.0 * (absChange - 1.0) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def aMean(xs: Seq[(Int, Double)]): Double = xs.foldLeft(0.0)((subtotal, relChange) => subtotal + relChange._2) / xs.size |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def eiul(xs: Seq[(Int, Double)], limits: EiulLimits): Seq[(Int, Double)] = { | |
| xs.map { case(year, relChange) => (year, limits(relChange)) } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** apply allows it to sort the right value into the middle, and then pick it | |
| * For example, EiulLimits(0.0, 15.0)(4.0) would become List(0.0, 4.0, 15.0), with 4.0 being in the middle | |
| * EiulLimits(0.0, 15.0)(-2.4 would become List(-2.4, 0.0, 15.0), with 0.0 being in the middle | |
| * EiulLimits(0.0, 15.0)(22.5) would become List(0.0, 15.0, 22.5), with 15.0 being in the middle | |
| */ | |
| case class EiulLimits(lower:Double, upper:Double) { | |
| def apply(x: Double) = List(x, lower, upper).sorted.apply(1) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def actualAbsGrowth(xs: Seq[(Int, Double)]): Double = xs.foldLeft(1.0)((subtotal, relChange) => subtotal * absChange(relChange._2)) | |
| def gMean(xs: Seq[(Int, Double)]): Double = { | |
| relChange(math.pow(actualAbsGrowth(xs), 1.0/xs.size)) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| object Main extends App { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def stats(xs: Seq[(Int, Int, Double, Double)]) = { | |
| val aMeans = xs.map(_._3) | |
| val gMeans = xs.map(_._4) | |
| Map("average geom mean" -> round(gMeans.sum/xs.size, 2), "min geom mean" -> round(gMeans.min, 2), "max geom mean" -> round(gMeans.max, 2), | |
| "stddev" -> stddev(gMeans)) | |
| } | |
| println("S&P 500 performance = " + snp) | |
| println("Arithmetic mean = " + aMean(snp) + "%") | |
| println("Geometric mean = " + gMean(snp) + "%" ) | |
| println("Actual total growth factor = " + actualAbsGrowth(snp)) | |
| println | |
| val eiulData = eiul(snp, EiulLimits(0.0, 15.0)) | |
| println("EIUL performance = " + eiulData) | |
| println("EIUL arithmetic performance = " + aMean(eiulData) + "%") | |
| println("EIUL geometric performance = " + gMean(eiulData) + "%") | |
| println("Actual EIUL total growth factor = " + actualAbsGrowth(eiulData)) | |
| println | |
| println(""" | |
| This is where every 10, 15, 20, etc. year interval in all the data is evaluated and then averaged together. | |
| The min and max performance of each interval is displayed, and the 1st stddev is shown. There is a 68% | |
| that actual performance is within 1 stddev of the average. | |
| """) | |
| List(10, 15, 20, 25, 30).foreach {interval => | |
| val snpStats = stats(series(snp, interval)) | |
| val eiulStats = stats(series(eiulData, interval)) | |
| println(interval + "-year stats") | |
| println("==========================") | |
| List(("S&P 500", snpStats), ("EIUL", eiulStats)).foreach {stats => | |
| stats match { | |
| case (desc, stats) => println("%s stats:\t Avg geom mean = %.2f (%.2f..%.2f)\t68%% chance between %.2f and %.2f".format( | |
| desc, stats("average geom mean"), stats("min geom mean"), stats("max geom mean"), | |
| stats("average geom mean")-stats("stddev"), stats("average geom mean")+stats("stddev"))) | |
| } | |
| } | |
| println | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def series(xs: Seq[(Int, Double)], years: Int) = { | |
| xs.sliding(years).map(sublist => | |
| (sublist(0)._1, sublist.takeRight(1)(0)._1, aMean(sublist), gMean(sublist)) | |
| ).toList | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| val snp = List( | |
| (1951, 16.3), (1952, 11.8), (1953, -6.6), (1954, 26.4), (1955, 26.4), | |
| (1956, 2.6), (1957, -14.3), (1958, 38.1), (1959, 8.5), (1960, -3.0), | |
| (1961, 23.1), (1962, -11.8), (1963, 18.9), (1964, 13.0), (1965, 9.1), | |
| (1966, -13.1), (1967, 20.1), (1968, 7.7), (1969, -11.4), (1970, 0.1), | |
| (1971, 10.8), (1972, 15.6), (1973, -17.4), (1974, -29.7), (1975, 31.5), | |
| (1976, 19.1), (1977, -11.5), (1978, 1.1), (1979, 12.3), (1980, 25.8), | |
| (1981, -9.7), (1982, 14.8), (1983, 17.3), (1984, 1.4), (1985, 26.3), | |
| (1986, 14.6), (1987, 2.0), (1988, 12.4), (1989, 27.3), (1990, -6.6), | |
| (1991, 26.3), (1992, 4.5), (1993, 7.1), (1994, -1.5), (1995, 34.1), | |
| (1996, 20.3), (1997, 31.0), (1998, 26.7), (1999, 19.5), (2000, -10.1), | |
| (2001, -13.0), (2002, -23.4), (2003, 26.4), (2004, 9.0), (2005, 3.0), | |
| (2006, 13.6), (2007, 3.5), (2008, -38.5), (2009, 23.5), (2010, 12.8)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def stddev(xs: Seq[Double]): Double = { | |
| val mean = xs.sum/xs.size | |
| val squareSum = xs.foldLeft(0.0)((subtotal, item) => subtotal + math.pow(item - mean, 2)) | |
| math.sqrt(squareSum/xs.size) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment