public JsonResult SpotPriceSimulation( int[] timeStepsInLevels, double[] priceLevels, double timeStep, double reversionRate, double volatility, int numberOfSimulations) { if (timeStepsInLevels.Length != priceLevels.Length) { throw new Exception("Lengths not consistent"); } //hourly simulation var horizon = timeStepsInLevels.Sum() * 24; // //TODO: add daily/hourly resolution... if it makes sense... but not really. //estimate an hourly ARMA... var d = AppData.GetHistoricalSeries(PricesController._timeSeries); var data = d .Select(x => x.Value != null ? (double)x.Value : 0) //0 for now, when interpolation is done... etc.. .ToArray(); //just take last 3 years... mhm... var threeYears = 24 * 7 * 4 * 12 * 3; if (data.Length > threeYears) { data = data.Skip(data.Length - threeYears).Take(threeYears).ToArray(); } //detrend to make stationary data = TimeSeries.toStationary(data); //hourly //var seasons = new int[] { 24, 24 * 7, 24 * 7 * 4, 24 * 7 * 4 * 6, 24 * 7 * 4 * 12}; //var arSes = new int[] { 1, 2, 24, 25 }; //daily //var seasons = new int[] { 7, 7*4, 7*4*12 }; //var arSes = new int[] { 1, 7, 7*4 }; //var arma = TimeSeries.ARMASimple2(data, arSes, seasons); //fitted model from matlab var arlags = new int[] { 1, 2, 24, 25 }; //var ar = new TimeSeries.LagOp(new double[] { 1.04216, -0.125323, 0.777886, -0.699448 }, arlags); var malags = new int[] { 24, 168 }; //var ma = new TimeSeries.LagOp(new double[] { -0.44595, 0.175135 }, malags); //var xarma = TimeSeries.ARMASimple3(ar, ma, 0.166685, 2.80023); //our fitting procedure.. difference...? not much... var arma = TimeSeries.ARMASimple2(data, arlags, malags); arma = TimeSeries.ARMASimple3(arma.AR, arma.MA, arma.Const, volatility); var inSampleRes = TimeSeries.Infer(arma, data); var sims = arma.Simulate(numberOfSimulations, horizon, data, inSampleRes); var hoursSteps = timeStepsInLevels.Select(x => x * 24).ToArray(); var desezonalizedData = Desezonalize(data, 168); //add the spikes //Then perform the spike estimation var spikesThreshold = 1.7; var spikeIndices = EstimateSpikesOnMovSDs(desezonalizedData, 24, 2, spikesThreshold); //select hour var peakHour = 16; var peakhourData = TakeShortPeriods(data, 1, peakHour, 24); var peakSpikeIndices = EstimateSpikesOnMovSDs(peakhourData, 7, 2, spikesThreshold); var distrib = EstimateSpikesDistribution(peakhourData, peakSpikeIndices, Forecast.SpikePreprocess.SimilarDay, spikesThreshold); //for testing.. var n = new Normal(distrib.Item1.Mean, distrib.Item1.Variance); var p = new Poisson(distrib.Item2.Lambda * 24); //replace spikes now... //TODO: replace at the right hour... yes... sims = Simulations.spikeSimulationsReplace(sims, p, n); //fit the forward curve sims = Simulations.liftSeriesToPriceCurve(sims, hoursSteps, priceLevels); return(Json(sims)); }