├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── LICENSE.txt ├── NOTICE.txt ├── READ ME.txt ├── README.md ├── build.xml ├── docs ├── algorithmicdifferentiation-dependencyinjection │ ├── experiment-05.jpg │ ├── experiment-05.svg │ └── index.html ├── algorithmicdifferentiation-forwardsensitivities │ └── index.html ├── black-scholes-hedge-simulator │ ├── experiment-01.png │ └── index.html ├── factor-reduction │ ├── experiment-01.png │ └── index.html ├── finmathnet-style.css ├── getting-started │ └── index.html ├── index.html ├── mathematical-finance-laboratory.png ├── montecarlo-bermudan │ ├── BermudanExerciseAdmissible.svg │ ├── BermudanExerciseForesight.svg │ └── index.html ├── montecarlo-blackscholes │ ├── experiment-01.jpg │ ├── experiment-01.svg │ ├── experiment-02.jpg │ ├── experiment-02.svg │ ├── experiment-03.jpg │ ├── experiment-03.svg │ └── index.html ├── parallel-computing-animation │ ├── ParallelComputingAnimation5b.png │ └── index.html ├── random-numbers │ ├── experiment-01a.svg │ ├── experiment-01b.svg │ ├── experiment-02a.svg │ ├── experiment-02b.svg │ └── index.html └── risk-neutral-density │ ├── experiment-01.svg │ ├── experiment-02.jpg │ ├── experiment-02.svg │ └── index.html ├── finmath-checkstyle.xml ├── lib ├── LICENSE for commons-lang3-3.4 │ ├── LICENSE.txt │ ├── NOTICE.txt │ └── RELEASE-NOTES.txt ├── LICENSE for commons-math3-3.6 │ ├── LICENSE.txt │ ├── NOTICE.txt │ └── RELEASE-NOTES.txt ├── colt-1.2.0.jar ├── commons-lang3-3.4.jar ├── commons-math3-3.6.1.jar ├── finmath-lib-1.3.0.jar ├── finmath-lib-2.4.2-java6.jar ├── finmath-lib-3.2.10.jar ├── jblas-1.2.4.jar └── joda-time-2.9.jar ├── logging.properties ├── mvnw ├── mvnw.cmd ├── notebooks ├── Black Scholes Model Monte-Carlo Simulation.json └── Regression of Continuation Value.json ├── pom.xml ├── spreadsheets └── Pseudo Random and Low Discrepancy Sequences │ ├── DISCLAIMER.txt │ ├── Halton Sequence 2 (wrong).ods │ ├── Halton Sequence 2 (wrong).xls │ ├── Halton Sequence.ods │ ├── Halton Sequence.xls │ ├── RandomNumbers.ods │ └── RandomNumbers.xls └── src ├── main ├── java │ ├── module-info.java │ └── net │ │ └── finmath │ │ └── experiments │ │ ├── blackscholes │ │ ├── AnalyticOptionValuation.java │ │ ├── BlackScholesOptionCalculator.java │ │ ├── DisplaceLognormalImpliedVolExperiment.java │ │ └── package-info.java │ │ ├── computation │ │ ├── ComputerArithmeticExperiment.java │ │ ├── ComputerArithmeticSolverQuadraticEquationExperiment.java │ │ ├── RoundingExperiment.java │ │ └── package-info.java │ │ ├── concurrency │ │ ├── ForkJoinPoolTest.java │ │ ├── NestedParallelForEachAndSynchronization.java │ │ ├── NestedParallelForEachBenchmark.java │ │ ├── NestedParallelForEachTest.java │ │ └── package-info.java │ │ ├── dice │ │ ├── DICEModelExperiment.java │ │ └── package-info.java │ │ ├── factorreduction │ │ ├── FactorMatrixExperiment.java │ │ ├── FactorReduction.java │ │ ├── FactorReductionApp.java │ │ ├── FactorReductionPanel.java │ │ └── package-info.java │ │ ├── hedgesimulator │ │ ├── HedgeSimulator.java │ │ ├── HedgeSimulatorApp.java │ │ ├── HedgeSimulatorPanel.java │ │ └── package-info.java │ │ ├── liboverview │ │ ├── MonteCarloBlackScholesEuropeanOptionDeltaAAD.java │ │ ├── MonteCarloBlackScholesEuropeanOptionValuation.java │ │ ├── MonteCarloLIBORMarketModelValuation.java │ │ ├── MonteCarloModelEuropeanOptionValuation.java │ │ └── RandomVariableDependencyInjection.java │ │ ├── marketdata │ │ └── curves │ │ │ └── CurveExperiments.java │ │ ├── montecarlo │ │ ├── BrownianMotionTests.java │ │ ├── MonteCarloIntegrationExperiment.java │ │ ├── MonteCarloIntegrationParallelizedExperiment.java │ │ ├── MonteCarloIntegrationWithQuasiRandomNumbersExperiment.java │ │ ├── assetderivativevaluation │ │ │ ├── BachelierModelPathsPlot.java │ │ │ ├── BlackScholesModelNumerairePlot.java │ │ │ ├── BlackScholesModelPathsPlot.java │ │ │ ├── BlackScholesMonteCarloValuationTest.java │ │ │ ├── DeltaHedgeSimulation.java │ │ │ ├── MonteCarloValuationExperiments.java │ │ │ ├── MonteCarloValuationUsingOpenCL.java │ │ │ ├── SimpleBlackScholesMonteCarloValuation.java │ │ │ ├── package-info.java │ │ │ └── products │ │ │ │ ├── BermudanOptionExerciseInMonteCarloBlackScholesPlot.java │ │ │ │ ├── BermudanOptionExerciseInMonteCarloPrimalDualMethodExperiments.java │ │ │ │ ├── BermudanOptionExperiments.java │ │ │ │ ├── EuropeanOption2.java │ │ │ │ ├── EuropeanOptionDeltaLikelihood.java │ │ │ │ ├── EuropeanOptionDeltaPathwise.java │ │ │ │ ├── EuropeanOptionGammaLikelihood.java │ │ │ │ ├── EuropeanOptionGammaPathwise.java │ │ │ │ ├── EuropeanOptionRhoLikelihood.java │ │ │ │ ├── EuropeanOptionRhoPathwise.java │ │ │ │ ├── EuropeanOptionVegaLikelihood.java │ │ │ │ ├── EuropeanOptionVegaPathwise.java │ │ │ │ └── package-info.java │ │ ├── automaticdifferentiation │ │ │ ├── MonteCarloBlackScholesModelDigitalOptionAADRegressionSensitivitiesLMM.java │ │ │ └── package-info.java │ │ ├── eulerscheme │ │ │ ├── BrownianMotionCoarseTimeDiscretization.java │ │ │ └── EulerSchemeIllustrationPlot.java │ │ ├── interestrates │ │ │ ├── ForwardRate.java │ │ │ ├── LIBORMarketModelBermudanValuationTest.java │ │ │ ├── LIBORMarketModelCalibrationATMTest.java │ │ │ ├── ModelFactory.java │ │ │ ├── NonlinearDiscounting.java │ │ │ ├── TermStructureMonteCarloSimulationExperiments.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── process │ │ │ └── MonteCarloProcessObjectsExperiments.java │ │ ├── randomnumbers │ │ │ ├── HaltonSequence.java │ │ │ ├── PseudoRandomNumberSequence.java │ │ │ └── package-info.java │ │ └── schemes │ │ │ ├── LogProcessEulerScheme.java │ │ │ ├── LogProcessLogEulerScheme.java │ │ │ ├── LogProcessMilsteinScheme.java │ │ │ ├── LognormalProcess.java │ │ │ ├── MonteCarloSchemeTests.java │ │ │ └── package-info.java │ │ ├── optimizer │ │ └── LevenbergMarquardtTest.java │ │ ├── optionvalueinterpolation │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── performance │ │ └── package-info.java │ │ ├── randomnumbers │ │ └── NormalViaICDFPlot.java │ │ ├── reproduction │ │ ├── BackProjection.java │ │ ├── BackProjectionAnalysis.java │ │ ├── DiscretizedLognormalDistribution.java │ │ ├── ReproductionSimulationExperiment.java │ │ └── package-info.java │ │ ├── shortrate │ │ ├── CIRSimulation.java │ │ └── package-info.java │ │ └── timeseries │ │ └── backcasting │ │ ├── BackcastExperiment.java │ │ └── CorrelationBasedBackcast.java └── resources │ └── experiment.jsh └── test └── java └── net └── finmath └── experiments └── reproduction └── BackProjectionTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /results/ 3 | /.settings 4 | release.properties 5 | /.project 6 | /.classpath 7 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.6"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/finmath/finmath-experiments/1a652ef083db4b6903b0eb06f43806f06b0e6a64/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | 2 | NOTICE for finmath lib 3 | --------------------------- 4 | 5 | Copyright (c) 2008-2019 Christian Fries, http://www.christianfries.com/finmath 6 | For updates on finmath lib see http://www.finmath.net 7 | Permission to use and/or redistribute this work is granted under the terms of the Apache License Version 2.0, with the exception that any usage related to military applications is expressly forbidden. The software and documentation made available under the terms of this license are provided with no warranty. 8 | 9 | 10 | NOTICE for Colt Library 11 | --------------------------- 12 | 13 | Packages cern.colt* , cern.jet*, cern.clhep: 14 | 15 | Copyright (c) 1999 CERN - European Organization for Nuclear Research. 16 | Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. CERN makes no representations about the suitability of this software for any purpose. It is provided "as is" without expressed or implied warranty. 17 | 18 | Packages hep.aida.*: 19 | 20 | Written by Pavel Binko, Dino Ferrero Merlino, Wolfgang Hoschek, Tony Johnson, Andreas Pfeiffer, and others. Check the FreeHEP home page for more info. Permission to use and/or redistribute this work is granted under the terms of the LGPL License, with the exception that any usage related to military applications is expressly forbidden. The software and documentation made available under the terms of this license are provided with no warranty. 21 | 22 | 23 | NOTICE for Apache Software 24 | --------------------------- 25 | 26 | This product includes software developed by 27 | The Apache Software Foundation (http://www.apache.org/). 28 | 29 | -------------------------------------------------------------------------------- /READ ME.txt: -------------------------------------------------------------------------------- 1 | finmath experiments 2 | =================== 3 | 4 | Experiments and demos based on finmath lib. 5 | 6 | NOTE: 7 | ----- 8 | 9 | For updates check http://www.finmath.net/finmath-lib 10 | 11 | 12 | DOCUMENTATION: 13 | -------------- 14 | 15 | For API documentation see http://www.finmath.net/finmath-lib 16 | 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | finmath experiments 2 | =================== 3 | 4 | Experiments and demos based on finmath lib. 5 | 6 | See also http://finmath.github.io/finmath-experiments/ 7 | 8 | Projects 9 | -------- 10 | 11 | **finmath lib** 12 | Java library providing implementations of methodologies related to 13 | mathematical finance, but applicable to other fields (e.g., the 14 | Monte-Carlo simulation of SDEs and the estimation of conditional 15 | expectations in Monte-Carlo). 16 | See http://finmath.net/finmath-lib 17 | 18 | **finmath spreadsheets** 19 | A collection of spreadsheets building upon *finmath lib* and 20 | providing end user solutions (e.g, interest rate curve calibration 21 | or calibration of a forward rate model, aka LIBOR market model). 22 | See http://finmath.net/spreadsheets/ 23 | 24 | **finmath experiments** 25 | Small experiments, illustrating some aspects of mathematical 26 | finance. Also illustrates how to use the finmath lib. 27 | 28 | **finmath lib plot extensions** 29 | Convenient abstractions of some plotting libraries and example usages of finmath lib. 30 | See http://finmath.net/finmath-lib-plot-extensions/ 31 | 32 | 33 | Documentation 34 | ------------- 35 | 36 | - [finmath lib API documentation][] 37 | provides the documentation of the library api. 38 | - [finmath.net special topics][] 39 | cover some selected topics with demo spreadsheets and uml diagrams. 40 | Some topics come with additional documentations (technical papers). 41 | 42 | 43 | License 44 | ------- 45 | 46 | The code of "finmath lib" and "finmath experiments" (packages 47 | `net.finmath.*`) are distributed under the [Apache License version 48 | 2.0][], unless otherwise explicitly stated. 49 | 50 | [finmath lib API documentation]: http://www.finmath.net/java/finmath-lib/doc/ 51 | [finmath.net special topics]: http://www.finmath.net/topics 52 | [Apache License version 2.0]: http://www.apache.org/licenses/LICENSE-2.0.html 53 | 54 | 55 | Instruction for Contributors for Experiments 56 | ------- 57 | 58 | Here are a few remarks in case you like to create and contribute a web page with experiments, similar to the ones in the `docs` folder of this repo. 59 | 60 | - Used the same HTML header as in the example on Monte-Carlo simulation, see montecarlo-blackscholes (adjusting title and description). 61 | 62 | - Use the correct HTML tags for code blocks, i.e. the tag `
68 |
69 |
57 | Checkout finmath-experiments from git and run maven (mvn
or mvnw
) from
58 | its directory. This will start a JShell.
59 | See Getting Started for details.
60 |
65 | 66 | Note: due to a bug in Java 11.0.7 for macOS, the simulator does not run 67 | when launched with Java 11.0.7. Please use Java 11.0.8 or Java 14.0.1 or better. 68 | 69 |
70 |71 | The Hedge Simulator is a GUI application. To run it just type the following in JShell: 72 |
73 | 74 |
78 | net.finmath.experiments.hedgesimulator.HedgeSimulator.run();
79 |
54 | Some experiments on this site use Java JShell started from a Maven project as a starting point. 55 |
56 | 57 |58 | There are several options on how you can start that JShell. 59 |
60 | 61 |64 | To checkout the project you need git. 65 |
66 | 67 |mkdir git
(to create a folder git
, if you do not have one)cd git
(to enter your git
folder)git
), change to the cloned directory (cd
) and start jshell via Maven (mvn
) by typing the following three commands:
84 | git clone https://github.com/finmath/finmath-experiments
85 | cd finmath-experiments
86 | mvnw
87 |
mvnw
fails, try ./mvnw
on Linux, macOS or .\mvnw
on Windows. Alternatively, if you Maven installed run mvn
.
90 |
91 | 42 | Some experiments on risk neutral valuation. 43 |
44 | 45 |56 | Small experiments related to the generation of normal distributed random numbers. 57 |
58 | 59 |78 | Some experiments on Monte-Carlo simulation, Bermudan option valuation in a Monte-Carlo simulation and algorithmic differentiation. 79 |
80 | 81 |101 | Some experiments related to interest rate modelling. 102 |
103 | 104 |
55 | To run the animation checkout the project JavaGPUExperiments
and launch
56 | com.christianfries.teaching.gpu.ParallelComputingAnimation
via Maven exec.
57 |
63 | git clone https://github.com/cfries/JavaGPUExperiments
64 | cd JavaGPUExperiments
65 | mvn clean install exec:java -Dexec.mainClass=com.christianfries.teaching.gpu.ParallelComputingAnimation
66 |
IntStream.range(0,numberOfTasks).parallel().forEach
(for example:
17 | * the parallel executions of the outer forEach should be limited due to a
18 | * memory constrain).
19 | *
20 | * Inside the execution block of the outer forEach we use another parallel stream
21 | * to create an inner forEach. The number of concurrent
22 | * executions of the inner forEach is not limited by us (it is however limited by a
23 | * system property "java.util.concurrent.ForkJoinPool.common.parallelism").
24 | *
25 | * Problem: If the semaphore is used AND the inner forEach is active, then
26 | * the execution will be DEADLOCKED.
27 | *
28 | * @author Christian Fries
29 | */
30 | public class ForkJoinPoolTest {
31 |
32 | // Any combination of the booleans works, except (true,true,false)
33 | private final boolean isUseSemaphore = true;
34 | private final boolean isUseInnerStream = true;
35 | private final boolean isWrappedInnerLoopThread = false;
36 |
37 | private final int numberOfTasksInOuterLoop = 20; // In real applications this can be a large number (e.g. > 1000).
38 | private final int numberOfTasksInInnerLoop = 100; // In real applications this can be a large number (e.g. > 1000).
39 | private final int concurrentExecusionsLimitInOuterLoop = 5;
40 | private final int concurrentExecutionsLimitForStreams = 10;
41 |
42 | private final Semaphore concurrentExecutions;
43 |
44 | public static void main(String[] args) {
45 | (new ForkJoinPoolTest()).testNestedLoops();
46 | }
47 |
48 | public ForkJoinPoolTest() {
49 | super();
50 | this.concurrentExecutions = new Semaphore(concurrentExecusionsLimitInOuterLoop);
51 | }
52 |
53 | public void testNestedLoops() {
54 |
55 | System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism",Integer.toString(concurrentExecutionsLimitForStreams));
56 | System.out.println("java.util.concurrent.ForkJoinPool.common.parallelism = " + System.getProperty("java.util.concurrent.ForkJoinPool.common.parallelism"));
57 |
58 | // Outer loop
59 | IntStream.range(0,numberOfTasksInOuterLoop).parallel().forEach(i -> {
60 |
61 | if(isUseSemaphore) {
62 | concurrentExecutions.acquireUninterruptibly();
63 | }
64 |
65 | try {
66 | System.out.println(i + "\t" + "-" + "\t" + concurrentExecutions.availablePermits() + "\t" + Thread.currentThread());
67 |
68 | if(isUseInnerStream) {
69 | try {
70 | Thread.sleep(10*numberOfTasksInInnerLoop);
71 | } catch (final Exception e) {
72 | }
73 | runCodeWhichUsesParallelStream(i, Thread.currentThread().toString());
74 | }
75 | else {
76 | try {
77 | Thread.sleep(10*numberOfTasksInInnerLoop);
78 | } catch (final Exception e) {
79 | }
80 | }
81 | }
82 | finally {
83 | if(isUseSemaphore) {
84 | concurrentExecutions.release();
85 | }
86 | }
87 | });
88 |
89 | System.out.println("D O N E");
90 | }
91 |
92 | /**
93 | * Runs code in a parallel forEach using streams.
94 | *
95 | * @param numberOfTasksInInnerLoop Number of tasks to execute.
96 | */
97 | private void runCodeWhichUsesParallelStream(int i, String callingThread) {
98 |
99 | final Runnable innerLoop = new Runnable() {
100 | @Override
101 | public void run() {
102 | // Inner loop
103 | IntStream.range(0,numberOfTasksInInnerLoop).parallel().forEach(j -> {
104 | try {
105 | System.out.println(i + "\t" + j + "\t" + concurrentExecutions.availablePermits() + "\t" + callingThread + "\t" + Thread.currentThread());
106 | Thread.sleep(10);
107 | } catch (final Exception e) {
108 | }
109 | });
110 | }
111 | };
112 |
113 | if(isWrappedInnerLoopThread) {
114 | final Thread t = new Thread(innerLoop, "Wrapper Thread");
115 | try {
116 | t.start();
117 | t.join();
118 | } catch (final InterruptedException e) {
119 | }
120 | }
121 | else {
122 | innerLoop.run();
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/java/net/finmath/experiments/concurrency/NestedParallelForEachTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christian-fries.de.
3 | *
4 | * Created on 06.05.2014
5 | */
6 | package net.finmath.experiments.concurrency;
7 |
8 | import java.util.stream.IntStream;
9 |
10 | /**
11 | * This is a test of Java 8 parallel streams.
12 | *
13 | * We are testing nested parallel forEach loops, which appear to
14 | * have unexpected poor performance in Java 1.8.0u5.
15 | *
16 | * We have a nested stream.parallel().forEach():
17 | *
18 | * The inner loop is independent (stateless, no interference, etc. - except of the use of a common pool)
19 | * and consumes 1 second in total in the worst case, namely if processed sequential.
20 | * Half of the tasks of the outer loop consume 10 seconds prior that loop.
21 | * Half consume 10 seconds after that loop.
22 | * We have a boolean which allows to switch the inner loop from parallel() to sequential().
23 | * Hence every thread consumes 11 seconds (worst case) in total.
24 | * Now: submitting 24 outer-loop-tasks to a pool of 8 we would expect 24/8 * 11 = 33 seconds at best (on an 8 core or better machine).
25 | *
26 | * The result is:
27 | * - With inner sequential loop: 33 seconds.
28 | * - With inner parallel loop: >80 seconds (I had 92 seconds).
29 | *
30 | * Now, there is a funny workaround. The method
31 | * wraps every operation in its own thread. Use this to wrap the inner loop in its
32 | * own thread via
33 | * {@code
34 | * wrapInThread( () ->
35 | * IntStream.range(0,numberOfTasksInInnerLoop).parallel().forEach(j -> {
36 | * burnTime(10);
37 | * }));
38 | * }
39 | * And the performance issue is gone. Note that this does not introduce any new
40 | * parallelism and that the inner loop tasks are still submitted to the same
41 | * common fork-join pool.
42 | *
43 | * The reason, why this fix works, is because the inner loop is started form a Thread
44 | * and not from possible ForkJoinWorkerThread of the outer loop. In the latter case
45 | * the ForkJoinTask by mistake assumes that the starting thread is a worker of itself
46 | * and issues a join, effectively joining inner loop tasks with outer loop tasks.
47 | *
48 | * @author Christian Fries
49 | */
50 | public class NestedParallelForEachTest {
51 |
52 | // The program uses 33 sec with this boolean to false and around 80+ with this boolean true:
53 | private final boolean isInnerStreamParallel = true;
54 |
55 | // Setup: Inner loop task 0.01 sec in worse case. Outer loop task: 10 sec + inner loop. This setup: (100 * 0.01 sec + 10 sec) * 24/8 = 33 sec.
56 | private final int numberOfTasksInOuterLoop = 24; // In real applications this can be a large number (e.g. > 1000).
57 | private final int numberOfTasksInInnerLoop = 100; // In real applications this can be a large number (e.g. > 1000).
58 | private final int concurrentExecutionsLimitForStreams = 8; // java.util.concurrent.ForkJoinPool.common.parallelism
59 |
60 | // For those, who do not trust the use of Thread.sleep().
61 | private final boolean isCPUTimeBurned = false; // Set to true, if you like a true loop, and not Thread.sleep()
62 | private final long cpuTimeBurningCountPerMillis = 800000; // You might need to calibrate this for your machine
63 |
64 | public static void main(String[] args) {
65 | (new NestedParallelForEachTest()).testNestedLoops();
66 | }
67 |
68 | public void testNestedLoops() {
69 |
70 | final long start = System.currentTimeMillis();
71 |
72 | System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism",Integer.toString(concurrentExecutionsLimitForStreams));
73 | System.out.println("java.util.concurrent.ForkJoinPool.common.parallelism = " + System.getProperty("java.util.concurrent.ForkJoinPool.common.parallelism"));
74 |
75 | // Outer loop
76 | IntStream.range(0,numberOfTasksInOuterLoop).parallel().forEach(i -> {
77 |
78 | try {
79 | if(i < 10) {
80 | burnTime(10 * 1000);
81 | }
82 |
83 | System.out.println(i + "\t" + Thread.currentThread());
84 |
85 | if(isInnerStreamParallel) {
86 | // Inner loop as parallel: worst case (sequential) it takes 10 * numberOfTasksInInnerLoop millis
87 | IntStream.range(0,numberOfTasksInInnerLoop).parallel().forEach(j -> {
88 | burnTime(10);
89 | });
90 | }
91 | else {
92 | // Inner loop as sequential
93 | IntStream.range(0,numberOfTasksInInnerLoop).sequential().forEach(j -> {
94 | burnTime(10);
95 | });
96 | }
97 |
98 | if(i >= 10) {
99 | burnTime(10 * 1000);
100 | }
101 | } catch (final Exception e) { e.printStackTrace(); }
102 |
103 | });
104 |
105 | final long end = System.currentTimeMillis();
106 |
107 | System.out.println("Done in " + (end-start)/1000 + " sec.");
108 | }
109 |
110 | private double burnTime(long millis) {
111 | if(isCPUTimeBurned) {
112 | double x = 0;
113 | for(long i=0; inet.finmath.montecarlo.assetderivativevaluation.products.EuropeanOption
.
17 | *
18 | * @author Christian Fries
19 | * @version 1.0
20 | */
21 | public class EuropeanOption2 extends AbstractAssetMonteCarloProduct {
22 |
23 | private final double maturity;
24 | private final double strike;
25 |
26 | /**
27 | * Construct a product representing an European option on an asset S (where S the asset with index 0 from the model - single asset case).
28 | *
29 | * @param strike The strike K in the option payoff max(S(T)-K,0).
30 | * @param maturity The maturity T in the option payoff max(S(T)-K,0)
31 | */
32 | public EuropeanOption2(double maturity, double strike) {
33 | super();
34 | this.maturity = maturity;
35 | this.strike = strike;
36 | }
37 |
38 | /**
39 | * Calculates the value of the option under a given model.
40 | *
41 | * @param model A reference to a model
42 | * @return the value
43 | * @throws CalculationException
44 | */
45 | public double getValue(AssetModelMonteCarloSimulationModel model) throws CalculationException
46 | {
47 | // Get underlying and numeraire
48 | final RandomVariable underlyingAtMaturity = model.getAssetValue(maturity,0);
49 | final RandomVariable numeraireAtMaturity = model.getNumeraire(maturity);
50 | final RandomVariable monteCarloWeights = model.getMonteCarloWeights(maturity);
51 | final RandomVariable numeraireAtToday = model.getNumeraire(0);
52 |
53 | /*
54 | * The following way of calculating the expected value (average) is discouraged since it makes too strong
55 | * assumptions on the internals of the RandomVariableAccumulator
. Instead you should use
56 | * the mutators sub, div, mult and the getter getAverage. This code is provided for illustrative purposes.
57 | */
58 | double average = 0.0;
59 | for(int path=0; pathRandomVariableAccumulator
. Instead you should use
67 | * the mutators sub, div, mult and the getter getAverage. This code is provided for illustrative purposes.
68 | */
69 | double average = 0.0;
70 | for(int path=0; pathcause()
method.
51 | */
52 | @Override
53 | public RandomVariable getValue(double evaluationTime, AssetModelMonteCarloSimulationModel model) throws CalculationException {
54 | if(!MonteCarloBlackScholesModel.class.isInstance(model)) {
55 | Logger.getLogger("net.finmath").warning("This method assumes a Black-Scholes type model (MonteCarloBlackScholesModel).");
56 | }
57 |
58 | // Get S(T), S(0)
59 | final RandomVariable underlyingAtMaturity = model.getAssetValue(maturity,0);
60 | final RandomVariable underlyingAtEvalTime = model.getAssetValue(evaluationTime,0);
61 |
62 | // The "payoff": values = indicator(S(T)-K) * S(T)/S(0)
63 | final RandomVariable trigger = underlyingAtMaturity.sub(strike);
64 | RandomVariable values = trigger.choose(underlyingAtMaturity, new Scalar(0.0)).div(underlyingAtEvalTime);
65 |
66 | // Discounting...
67 | final RandomVariable numeraireAtMaturity = model.getNumeraire(maturity);
68 | final RandomVariable monteCarloWeights = model.getMonteCarloWeights(maturity);
69 | values = values.div(numeraireAtMaturity).mult(monteCarloWeights);
70 |
71 | // ...to evaluation time.
72 | final RandomVariable numeraireAtEvalTime = model.getNumeraire(evaluationTime);
73 | final RandomVariable monteCarloProbabilitiesAtEvalTime = model.getMonteCarloWeights(evaluationTime);
74 | values = values.mult(numeraireAtEvalTime).div(monteCarloProbabilitiesAtEvalTime);
75 |
76 | return values;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/net/finmath/experiments/montecarlo/assetderivativevaluation/products/EuropeanOptionGammaLikelihood.java:
--------------------------------------------------------------------------------
1 | /*
2 | * (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christian-fries.de.
3 | *
4 | * Created on 12.02.2013
5 | */
6 | package net.finmath.experiments.montecarlo.assetderivativevaluation.products;
7 |
8 | import net.finmath.exception.CalculationException;
9 | import net.finmath.montecarlo.assetderivativevaluation.AssetModelMonteCarloSimulationModel;
10 | import net.finmath.montecarlo.assetderivativevaluation.MonteCarloBlackScholesModel;
11 | import net.finmath.montecarlo.assetderivativevaluation.products.AbstractAssetMonteCarloProduct;
12 | import net.finmath.stochastic.RandomVariable;
13 | import net.finmath.stochastic.RandomVariableAccumulator;
14 |
15 | /**
16 | * Implements calculation of the delta of a European option.
17 | *
18 | * @author Christian Fries
19 | * @version 1.0
20 | */
21 | public class EuropeanOptionGammaLikelihood extends AbstractAssetMonteCarloProduct {
22 |
23 | private final double maturity;
24 | private final double strike;
25 |
26 | private final boolean isLikelihoodByFiniteDifference = false;
27 |
28 | /**
29 | * Construct a product representing an European option on an asset S (where S the asset with index 0 from the model - single asset case).
30 | *
31 | * @param strike The strike K in the option payoff max(S(T)-K,0).
32 | * @param maturity The maturity T in the option payoff max(S(T)-K,0)
33 | */
34 | public EuropeanOptionGammaLikelihood(double maturity, double strike) {
35 | super();
36 | this.maturity = maturity;
37 | this.strike = strike;
38 | }
39 |
40 | /**
41 | * Calculates the value of the option under a given model.
42 | *
43 | * @param model A reference to a model
44 | * @return the value
45 | * @throws CalculationException
46 | */
47 | public double getValue(AssetModelMonteCarloSimulationModel model) throws CalculationException
48 | {
49 | MonteCarloBlackScholesModel blackScholesModel = null;
50 | try {
51 | blackScholesModel = (MonteCarloBlackScholesModel)model;
52 | }
53 | catch(final Exception e) {
54 | throw new ClassCastException("This method requires a Black-Scholes type model (MonteCarloBlackScholesModel).");
55 | }
56 |
57 | // Get underlying and numeraire
58 | final RandomVariable underlyingAtMaturity = model.getAssetValue(maturity,0);
59 | final RandomVariable numeraireAtMaturity = model.getNumeraire(maturity);
60 | final RandomVariable underlyingAtToday = model.getAssetValue(0.0,0);
61 | final RandomVariable numeraireAtToday = model.getNumeraire(0);
62 | final RandomVariable monteCarloWeights = model.getMonteCarloWeights(maturity);
63 |
64 | /*
65 | * The following way of calculating the expected value (average) is discouraged since it makes too strong
66 | * assumptions on the internals of the RandomVariable
. Instead you should use
67 | * the mutators sub, div, mult and the getter getAverage. This code is provided for illustrative purposes.
68 | */
69 | double average = 0.0;
70 | for(int path=0; pathRandomVariableAccumulator
. Instead you should use
64 | * the mutators sub, div, mult and the getter getAverage. This code is provided for illustrative purposes.
65 | */
66 | double average = 0.0;
67 | for(int path=0; pathRandomVariableAccumulator
. Instead you should use
65 | * the mutators sub, div, mult and the getter getAverage. This code is provided for illustrative purposes.
66 | */
67 | double average = 0.0;
68 | for(int path=0; pathRandomVariableAccumulator
. Instead you should use
67 | * the mutators sub, div, mult and the getter getAverage. This code is provided for illustrative purposes.
68 | */
69 | double average = 0.0;
70 | for(int path=0; pathRandomVariableAccumulator
. Instead you should use
65 | * the mutators sub, div, mult and the getter getAverage. This code is provided for illustrative purposes.
66 | */
67 | double average = 0.0;
68 | for(int path=0; pathcause()
method.
87 | */
88 | @Override
89 | public RandomVariable getValue(final double evaluationTime, final TermStructureMonteCarloSimulationModel model) throws CalculationException {
90 |
91 | // Get random variables
92 | final RandomVariable forwardRate = model.getForwardRate(fixingTime, periodStartTime, periodEndTime);
93 | final RandomVariable numeraire = model.getNumeraire(paymentTime);
94 | final RandomVariable monteCarloProbabilities = model.getMonteCarloWeights(periodStartTime);
95 |
96 | RandomVariable values = forwardRate.mult(daycountFraction);
97 |
98 | values = values.div(numeraire).mult(monteCarloProbabilities);
99 |
100 | final RandomVariable numeraireAtValuationTime = model.getNumeraire(evaluationTime);
101 | final RandomVariable monteCarloProbabilitiesAtValuationTime = model.getMonteCarloWeights(evaluationTime);
102 | values = values.mult(numeraireAtValuationTime).div(monteCarloProbabilitiesAtValuationTime);
103 |
104 | return values;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/net/finmath/experiments/montecarlo/interestrates/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Monte Carlo methods for interest rate products
3 | *
4 | * @author Christian Fries
5 | */
6 | package net.finmath.experiments.montecarlo.interestrates;
7 |
--------------------------------------------------------------------------------
/src/main/java/net/finmath/experiments/montecarlo/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Experiments related to Monte Carlo methods.
3 | *
4 | * @author Christian Fries
5 | */
6 | package net.finmath.experiments.montecarlo;
7 |
--------------------------------------------------------------------------------
/src/main/java/net/finmath/experiments/montecarlo/randomnumbers/HaltonSequence.java:
--------------------------------------------------------------------------------
1 | /*
2 | * (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christian-fries.de.
3 | *
4 | * Created on 18.10.2012
5 | */
6 | package net.finmath.experiments.montecarlo.randomnumbers;
7 |
8 | /**
9 | * This class represents a Halton sequence (a low discrepancy sequence), or equivalently a vector of
10 | * Van der Corput sequences. For a given base b the van der Corput sequence is given by
11 | *