def test_wiener_process(self): shift = .5 grid = list(range(0, 10)) r = .8 producer = MultiGaussEvolutionProducer( [WienerProcess(), WienerProcess(shift)], [[1., r], [r, 1.]]) consumer = MultiConsumer(TransposedConsumer(), TransposedConsumer()) first, second = Engine(producer, consumer).run(grid, 500, num_of_workers=None) if plt is not None: t = '2d-Scatter-MultiWiener' fig, ax = plt.subplots() ax.scatter(first[1], second[1]) plt.title(t) plt.savefig('.' + sep + 'pdf' + sep + t.replace(' ', '_') + '.pdf') plt.close() t = '3d-Scatter-MultiWiener' fig = plt.figure() ax = fig.add_subplot(111, projection='3d') for i in grid: ax.scatter([i] * len(first[i]), first[i], second[i]) for x, y in zip(first[i], second[i]): self.assertAlmostEqual(x, y - shift * i, -100) plt.title(t) plt.savefig('.' + sep + 'pdf' + sep + t.replace(' ', '_') + '.pdf') plt.close()
def test_multi_gauss_process(self): grid = list(range(0, 10)) r = .9 producer = GaussEvolutionProducer( MultiGauss([0., 0.], [[1., r], [r, 1.]], [0., 0.])) consumer = ConsumerConsumer(TransposedConsumer(lambda s: s.value[0]), TransposedConsumer(lambda s: s.value[1])) first, second = Engine(producer, consumer).run(grid, 500, num_of_workers=None) if plt is not None: t = '2d-Scatter-MultiGauss' fig, ax = plt.subplots() ax.scatter(first[1], second[1]) plt.title(t) plt.savefig('.' + sep + 'pdf' + sep + t.replace(' ', '_') + '.pdf') plt.close() t = '3d-Scatter-MultiGauss' fig = plt.figure() ax = fig.add_subplot(111, projection='3d') for i in grid: ax.scatter([i] * len(first[i]), first[i], second[i]) for x, y in zip(first[i], second[i]): self.assertAlmostEqual(x, y, -100) plt.title(t) plt.savefig('.' + sep + 'pdf' + sep + t.replace(' ', '_') + '.pdf') plt.close()
def test_string_producer(self): grid = list(range(100)) num_of_paths = 5000 sample = [[float(i) / float(j + 1) for j in grid] for i in range(num_of_paths)] p = DeterministicProducer(sample) result_str = Engine(p, StringWriterConsumer()).run( p.grid, p.num_of_paths) self.assertTrue(isinstance(result_str, str)) pp = StringReaderProducer(result_str) result = Engine(pp, Consumer()).run(pp.grid, pp.num_of_paths) for i, j in zip(sample, result): for x, y in zip(i, j): self.assertEqual(x, y)
def test_mean(self): start, drift, vol, time = 1., 0.1, 0.02, 1. expected = start * exp((drift + 0.5 * vol**2) * time) process = GeometricBrownianMotion(drift, vol, start) e = Engine(GaussEvolutionProducer(process), StatisticsConsumer()) mean = list() median = list() variance = list() for seed in range(100): d, r = e.run(grid=[0., time], seed=seed, num_of_paths=5000)[-1] mean.append(r.mean) median.append(r.median) variance.append(r.variance) self.assertTrue(min(mean) <= expected <= max(mean)) self.assertTrue(min(median) <= expected <= max(median)) self.assertTrue(min(mean) <= process.mean(time) <= max(mean)) self.assertTrue( min(variance) <= process.variance(time) <= max(variance))
def test_geometric_brownian_motion_timwave_plot(self): """ Monte Carlo simulation of geometric Brownian motion with constant volatility, hence initial state should be reached on average """ producer = GeometricBrownianMotionProducer(.01, .01) consumer = TimeWaveConsumer() Engine(producer, consumer).run(list(range(0, 50)), 5000) plot_timewave_result(consumer.result, '3d-GBM', '.' + sep + 'pdf')
def test_geometric_brownian_motion_plot(self): """ Monte Carlo simulation of geometric Brownian motion with constant volatility, hence initial state should be reached on average """ producer = GeometricBrownianMotionProducer(.05, .05) consumer = Consumer() Engine(producer, consumer).run(list(range(0, 20)), 100) plot_consumer_result(consumer.result, consumer.grid, '2d-GBM', '.' + sep + 'pdf')
def test_statistics(self): producer = GaussEvolutionProducer(self.process) consumer = StatisticsConsumer(func=self.eval) stats = Engine(producer, consumer).run(self.grid, self.path) for p, s in stats: self.assertAlmostEqual(self.process.mean(p), s.mean, self.places) # self.assertAlmostEqual(self.process.mean(p), s.median, self.places) self.assertAlmostEqual(self.process.variance(p), s.variance, self.places)
def test_deterministic_producer(self): grid = list(range(100)) num_of_paths = 5000 sample = [[float(i) / float(j + 1) for j in grid] for i in range(num_of_paths)] p = DeterministicProducer(sample) result = Engine(p, Consumer()).run(p.grid, p.num_of_paths) for i, j in zip(sample, result): for x, y in zip(i, j): self.assertEqual(x, y)
def test_statistics(self): producer = GaussEvolutionProducer(self.process) consumer = StatisticsConsumer(statistics=_MultiStatistics) stats = Engine(producer, consumer).run(self.grid, self.path) for p, s in stats: for pm, sm in zip(self.process.mean(p), s.mean): self.assertAlmostEqual(pm, sm, self.places) for pv, sv in zip(self.process.variance(p), s.variance): self.assertAlmostEqual(pv, sv, self.places)
def test_statistics(self): producer = GaussEvolutionProducer(self.process) consumer = StatisticsConsumer(lambda s: s.value[0]) stats = Engine(producer, consumer).run(self.grid, 50000) for p, s in stats: # print p, self.process.mean(p), self.process.variance(p), '\n', s self.assertAlmostEqual(self.process.mean(p), s.mean, self.places) self.assertAlmostEqual(self.process.mean(p), s.median, self.places) self.assertAlmostEqual(self.process.variance(p), s.variance, self.places)
def test_multi_producer(self): shift = 1. producer = MultiProducer(WienerProcessProducer(), WienerProcessProducer(shift)) consumer = MultiConsumer(TransposedConsumer(), TransposedConsumer()) first, second = Engine(producer, consumer).run(list(range(0, 20)), 500, num_of_workers=None) for i in range(len(first)): for x, y in zip(first[i], second[i]): self.assertAlmostEqual(x, y - shift * i)
def test_brownian_motion(self): """ Monte Carlo simulation of Brownian motion with constant volatility, hence initial state should be reached on average """ producer = WienerProcessProducer() consumer = TransposedConsumer() waves = Engine(producer, consumer).run(list(range(0, 25)), 25000, profiling=PROFILING) # check that on average there is no movement for g, w in enumerate(waves): mean = sum(w) / len(w) vol = sum([x * x for x in w]) / (len(w) - 1) self.assertAlmostEqual(0.0, mean, 0) self.assertAlmostEqual(float(g), vol, 0)
def test_random_statistics(self): for d in range(2, 4, 2): process = self.process.__class__.random(d) producer = GaussEvolutionProducer(process) consumer = StatisticsConsumer(statistics=_MultiStatistics) stats = Engine(producer, consumer).run(self.grid, self.path) msg = '\ntransition matrix:\n' + str(process._transition_matrix) msg += '\nstart distribution:\n' + str(process.start) for p, s in stats: for pm, sm in zip(process.mean(p), s.mean): self.assertAlmostEqual( pm, sm, self.places, 'mean at %d: %f vs. %f' % (p, pm, sm) + msg) for pv, sv in zip(process.variance(p), s.variance): self.assertAlmostEqual( pv, sv, self.places, 'variance t %d: %f vs. %f' % (p, pv, sv) + msg)
def test_brownian_motion_statistics(self): """ Monte Carlo simulation of Brownian motion with constant volatility, hence initial state should be reached on average """ producer = WienerProcessProducer() consumer = ConsumerConsumer(StatisticsConsumer(), StochasticProcessStatisticsConsumer()) stats, (_, t) = Engine(producer, consumer).run(list(range(0, 20)), 5000, profiling=PROFILING) for p, s in stats: self.assertAlmostEqual(0.0, s.mean, 0) self.assertAlmostEqual(0.0, s.median, 0) self.assertAlmostEqual(float(p), s.variance, -1) self.assertAlmostEqual(0.0, max(t.mean), 0) self.assertAlmostEqual(0.0, min(t.mean), 0)
def test_geometric_brownian_motion(self): """ Monte Carlo simulation of geometric Brownian motion with constant volatility, hence initial state should be reached on average """ mu = 0.01 sigma = 0.01 mean = (lambda t: exp(mu * t)) variance = (lambda t: exp(2 * mu * t) * (exp(sigma**2 * t) - 1)) producer = GeometricBrownianMotionProducer(mu, sigma) consumer = TransposedConsumer() waves = Engine(producer, consumer).run(list(range(0, 100)), 5000) # check that on average there is no movement for g, w in enumerate(waves): s_mean = sum(w) / len(w) s_variance = sqrt(sum([x * x for x in w]) / len(w) - s_mean**2) self.assertAlmostEqual(mean(g), s_mean, 0) self.assertAlmostEqual(variance(g), s_variance, 0)
def test_geometric_brownian_motion_statistics(self): """ Monte Carlo simulation of geometric Brownian motion with constant volatility, hence initial state should be reached on average """ mu = 0.0 sigma = 0.01 mean = (lambda t: exp(mu * t)) variance = (lambda t: exp(2 * mu * t) * (exp(sigma**2 * t) - 1)) producer = GeometricBrownianMotionProducer(mu, sigma) consumer = ConsumerConsumer(StatisticsConsumer(), StochasticProcessStatisticsConsumer(), Consumer()) stats, _, paths = Engine(producer, consumer).run(list(range(0, 100)), 500) # check that on average there is alright for p, s in stats: self.assertAlmostEqual(mean(p), s.mean, 0) self.assertAlmostEqual(mean(p), s.median, 0) self.assertAlmostEqual(variance(p), s.variance, 0)
def test_3d_plot(self): producer = GaussEvolutionProducer(self.process) consumer = TimeWaveConsumer(lambda s: s.value[0]) Engine(producer, consumer).run(self.grid, 5000) plot_timewave_result(consumer.result, '3d-' + str(self.process), '.' + sep + 'pdf')
def test_2d_plot(self): producer = GaussEvolutionProducer(self.process) consumer = Consumer(lambda s: s.value[0]) Engine(producer, consumer).run(self.grid, 500) plot_consumer_result(consumer.result, consumer.grid, '2d-' + str(self.process), '.' + sep + 'pdf')