Created
December 4, 2013 05:09
-
-
Save pfhayes/7782653 to your computer and use it in GitHub Desktop.
This file contains 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
import scala.util.Random | |
val random = new Random() | |
def dollarCostValue(initialCapital: Double, prices: List[Double]): Double = { | |
val closingPrice = prices.last | |
val dailySpend = initialCapital / prices.length | |
val sharesOwned = prices.map(dailySpend / _).sum | |
sharesOwned * closingPrice | |
} | |
def lumpSumValue(initialCapital: Double, prices: List[Double]): Double = { | |
val startingPrice = prices.head | |
val closingPrice = prices.last | |
val sharesOwned = initialCapital / startingPrice | |
sharesOwned * closingPrice | |
} | |
// Price either goes up or down a fixed amount each day | |
def simpleWalkPrices(initialPrice: Double, deviance: Double): Iterator[Double] = { | |
Iterator.iterate(initialPrice)(price => | |
if (random.nextBoolean()) { | |
price + (deviance * initialPrice) | |
} else { | |
price - (deviance * initialPrice) | |
}) | |
} | |
// Price goes up or down a random amount each day | |
def randomWalkPrices(initialPrice: Double, deviance: Double): Iterator[Double] = { | |
val range = (initialPrice * deviance) | |
Iterator.iterate(initialPrice)(price => { | |
val change = random.nextDouble() * 2 * range - range | |
price + change | |
}) | |
} | |
// Price goes up or down a random percent each day | |
def percentChangePrices(startingPrice: Double, deviance: Double): Iterator[Double] = { | |
val range = deviance | |
Iterator.iterate(initialPrice)(price => { | |
val change = random.nextDouble() * 2 * range - range | |
price * (1 + change) | |
}) | |
} | |
def logNormalPrices(startingPrice: Double, deviance: Double): Iterator[Double] = { | |
Iterator.iterate(initialPrice)(price => { | |
price * (math.exp(random.nextGaussian() * deviance)) | |
}) | |
} | |
val initialPrice = 100.0 | |
val initialCapital = 1000.0 | |
val deviance = 0.05 | |
val days = 100 | |
val numTrials = 10000 | |
def simulate( | |
strategy: (Double, List[Double]) => Double, | |
generator: (Double, Double) => Iterator[Double] | |
): Double = { | |
val trials = for { | |
t <- (1 to numTrials) | |
} yield { | |
val prices = generator(initialPrice, deviance).take(days).toList | |
strategy(initialCapital, prices) | |
} | |
trials.sum / numTrials | |
} | |
def compare(generator: (Double, Double) => Iterator[Double]): Double = { | |
simulate(lumpSumValue, generator) / simulate(dollarCostValue, generator) | |
} | |
println("Simulated ratio for simpleWalk: " + compare(simpleWalkPrices)) | |
println("Simulated ratio for randomWalk: " + compare(randomWalkPrices)) | |
println("Simulated ratio for percentChange: " + compare(percentChangePrices)) | |
println("Simulated ratio for logNormal: " + compare(logNormalPrices)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment