| 1 | /* |
|---|
| 2 | * Copyright (c) Numerical Method Inc. |
|---|
| 3 | * http://www.numericalmethod.com/ |
|---|
| 4 | * |
|---|
| 5 | * THIS SOFTWARE IS LICENSED, NOT SOLD. |
|---|
| 6 | * |
|---|
| 7 | * YOU MAY USE THIS SOFTWARE ONLY AS DESCRIBED IN THE LICENSE. |
|---|
| 8 | * IF YOU ARE NOT AWARE OF AND/OR DO NOT AGREE TO THE TERMS OF THE LICENSE, |
|---|
| 9 | * DO NOT USE THIS SOFTWARE. |
|---|
| 10 | * |
|---|
| 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITH NO WARRANTY WHATSOEVER, |
|---|
| 12 | * EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, |
|---|
| 13 | * ANY WARRANTIES OF ACCURACY, ACCESSIBILITY, COMPLETENESS, |
|---|
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, NON-INFRINGEMENT, |
|---|
| 15 | * TITLE AND USEFULNESS. |
|---|
| 16 | * |
|---|
| 17 | * IN NO EVENT AND UNDER NO LEGAL THEORY, |
|---|
| 18 | * WHETHER IN ACTION, CONTRACT, NEGLIGENCE, TORT, OR OTHERWISE, |
|---|
| 19 | * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR |
|---|
| 20 | * ANY CLAIMS, DAMAGES OR OTHER LIABILITIES, |
|---|
| 21 | * ARISING AS A RESULT OF USING OR OTHER DEALINGS IN THE SOFTWARE. |
|---|
| 22 | */ |
|---|
| 23 | package com.numericalmethod.suanshu.examples; |
|---|
| 24 | |
|---|
| 25 | import com.numericalmethod.suanshu.stats.descriptive.moment.Mean; |
|---|
| 26 | import com.numericalmethod.suanshu.stats.descriptive.moment.Variance; |
|---|
| 27 | import com.numericalmethod.suanshu.stats.distribution.univariate.EmpiricalDistribution; |
|---|
| 28 | import com.numericalmethod.suanshu.stats.stochasticprocess.timegrid.EvenlySpacedGrid; |
|---|
| 29 | import com.numericalmethod.suanshu.stats.stochasticprocess.timegrid.TimeGrid; |
|---|
| 30 | import com.numericalmethod.suanshu.stats.stochasticprocess.univariate.filtration.Filtration; |
|---|
| 31 | import com.numericalmethod.suanshu.stats.stochasticprocess.univariate.filtration.FiltrationFunction; |
|---|
| 32 | import com.numericalmethod.suanshu.stats.stochasticprocess.univariate.integration.*; |
|---|
| 33 | import com.numericalmethod.suanshu.stats.stochasticprocess.univariate.random.RandomRealizationGenerator; |
|---|
| 34 | import com.numericalmethod.suanshu.stats.stochasticprocess.univariate.random.RandomRealizationOfRandomProcess; |
|---|
| 35 | import com.numericalmethod.suanshu.stats.stochasticprocess.univariate.sde.discrete.BrownianSDE; |
|---|
| 36 | import com.numericalmethod.suanshu.stats.stochasticprocess.univariate.sde.discrete.DiscreteSDE; |
|---|
| 37 | |
|---|
| 38 | /** |
|---|
| 39 | * Demonstrates how to numerically compute stochastic integrals in Java using SuanShu. |
|---|
| 40 | * |
|---|
| 41 | * @author Haksun Li |
|---|
| 42 | */ |
|---|
| 43 | public final class StochasticIntegral { |
|---|
| 44 | |
|---|
| 45 | /** |
|---|
| 46 | * The number of discretizations. |
|---|
| 47 | */ |
|---|
| 48 | public static final int N_T = 1000; |
|---|
| 49 | /** |
|---|
| 50 | * The number of simulations. |
|---|
| 51 | */ |
|---|
| 52 | public static final int N_SIMS = 1000; |
|---|
| 53 | /** |
|---|
| 54 | * The time of the first point. |
|---|
| 55 | */ |
|---|
| 56 | public static final double T_0 = 0; |
|---|
| 57 | /** |
|---|
| 58 | * The time of the last point. |
|---|
| 59 | */ |
|---|
| 60 | public static final double T_1 = N_T; |
|---|
| 61 | |
|---|
| 62 | private StochasticIntegral() { |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | /** |
|---|
| 66 | * Computes various stochastic integrals numerically. |
|---|
| 67 | * |
|---|
| 68 | * @param args not used |
|---|
| 69 | */ |
|---|
| 70 | public static void main(String[] args) { |
|---|
| 71 | System.out.println("This class demonstrates how to numerically compute stochastic " |
|---|
| 72 | + "integrals in Java using SuanShu."); |
|---|
| 73 | B2dB1_0010(); |
|---|
| 74 | B2dB1_0020(); |
|---|
| 75 | B1B1dt_0010(); |
|---|
| 76 | B1B1dt_0020(); |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | /** |
|---|
| 80 | * Demonstrates how to calculate the mean and variance of the integral: |
|---|
| 81 | * |
|---|
| 82 | * /1 E( | B2(t) dB1(t) ) /0, where B1, B2 are two different Brownian motions. |
|---|
| 83 | * |
|---|
| 84 | * We calculate the statistics by manually generate filtrations from B1 and evaluate the |
|---|
| 85 | * integral w.r.t. each filtration, obtaining a data point. |
|---|
| 86 | */ |
|---|
| 87 | public static void B2dB1_0010() { |
|---|
| 88 | final TimeGrid T = new EvenlySpacedGrid(T_0, T_1, N_T); // discretization |
|---|
| 89 | DiscreteSDE sde = new BrownianSDE(); |
|---|
| 90 | double x0 = 0.0; |
|---|
| 91 | |
|---|
| 92 | final RandomRealizationGenerator B = new RandomRealizationOfRandomProcess(sde, T, x0); |
|---|
| 93 | |
|---|
| 94 | Mean mu = new Mean(); |
|---|
| 95 | Variance var = new Variance(); |
|---|
| 96 | |
|---|
| 97 | for (int i = 0; i < N_SIMS; ++i) { |
|---|
| 98 | // generate a Brownian filtration |
|---|
| 99 | Filtration Ft = new Filtration(B.nextRealization()); |
|---|
| 100 | |
|---|
| 101 | // a new B2 is created for each iteration, hence a different FT2 |
|---|
| 102 | FiltrationFunction B2 = new FiltrationFunction() { |
|---|
| 103 | // generate a different Brownian filtration |
|---|
| 104 | private Filtration Ft2 = new Filtration(B.nextRealization()); |
|---|
| 105 | |
|---|
| 106 | @Override |
|---|
| 107 | public double evaluate(int t) { |
|---|
| 108 | double B2 = Ft2.B(t); |
|---|
| 109 | return B2; |
|---|
| 110 | } |
|---|
| 111 | }; |
|---|
| 112 | |
|---|
| 113 | double I = new IntegralDB(B2).value(Ft); |
|---|
| 114 | |
|---|
| 115 | mu.addData(I); |
|---|
| 116 | var.addData(I); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | /** |
|---|
| 120 | * E = -0.010207 with n = 100000; nSims = 10000, 3:52am, 23/2/2011 |
|---|
| 121 | */ |
|---|
| 122 | System.out.printf("the mean is %f%n", mu.value()); |
|---|
| 123 | System.out.printf("the variance is %f%n", var.value()); |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | /** |
|---|
| 127 | * Demonstrates a simpler way to compute: |
|---|
| 128 | * |
|---|
| 129 | * /1 E( | B2(t) dB1(t) ) /0, where B1, B2 are two different Brownian motions. |
|---|
| 130 | * |
|---|
| 131 | * Instead of the process above, we use {@link Exception}. |
|---|
| 132 | */ |
|---|
| 133 | public static void B2dB1_0020() { |
|---|
| 134 | TimeGrid T = new EvenlySpacedGrid(T_0, T_1, N_T); // discretization |
|---|
| 135 | DiscreteSDE sde = new BrownianSDE(); |
|---|
| 136 | double x0 = 0.0; |
|---|
| 137 | final RandomRealizationGenerator B = new RandomRealizationOfRandomProcess(sde, T, x0); |
|---|
| 138 | |
|---|
| 139 | FiltrationFunction B2 = new FiltrationFunction() { |
|---|
| 140 | private Filtration Ft2; |
|---|
| 141 | |
|---|
| 142 | @Override |
|---|
| 143 | public void setFt(Filtration Ft) { |
|---|
| 144 | // FT is not used in this function |
|---|
| 145 | super.setFt(Ft); |
|---|
| 146 | Ft2 = new Filtration(B.nextRealization()); |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | @Override |
|---|
| 150 | public double evaluate(int t) { |
|---|
| 151 | double B2 = Ft2.B(t); |
|---|
| 152 | return B2; |
|---|
| 153 | } |
|---|
| 154 | }; |
|---|
| 155 | Integral I = new IntegralDB(B2); |
|---|
| 156 | |
|---|
| 157 | Expectation E = new Expectation(I, |
|---|
| 158 | T_0, T_1, // [0, 1] |
|---|
| 159 | N_T, // discretization |
|---|
| 160 | N_SIMS); // number of simulations |
|---|
| 161 | |
|---|
| 162 | /** |
|---|
| 163 | * mean = -0.003524; var = 0.501905; with n = 100000; nSims = 10000, 4:01am, 23/2/2011 |
|---|
| 164 | */ |
|---|
| 165 | System.out.printf("the mean is %f%n", E.mean()); |
|---|
| 166 | System.out.printf("the variance is %f%n", E.variance()); |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | /** |
|---|
| 170 | * Computes |
|---|
| 171 | * |
|---|
| 172 | * /1 E( | [B1(t) * B2(t)] dt ) /0, where B1, B2 are two different Brownian motions. |
|---|
| 173 | * |
|---|
| 174 | * |
|---|
| 175 | */ |
|---|
| 176 | public static void B1B1dt_0010() { |
|---|
| 177 | TimeGrid T = new EvenlySpacedGrid(T_0, T_1, N_T); // discretization |
|---|
| 178 | DiscreteSDE sde = new BrownianSDE(); |
|---|
| 179 | double x0 = 0.0; |
|---|
| 180 | final RandomRealizationGenerator B = new RandomRealizationOfRandomProcess(sde, T, x0); |
|---|
| 181 | |
|---|
| 182 | FiltrationFunction B1B2 = new FiltrationFunction() { |
|---|
| 183 | private Filtration Ft1; |
|---|
| 184 | private Filtration Ft2; |
|---|
| 185 | |
|---|
| 186 | @Override |
|---|
| 187 | public void setFt(Filtration Ft) { |
|---|
| 188 | // FT is not used in this function |
|---|
| 189 | super.setFt(Ft); |
|---|
| 190 | // generate a filtration for each new simulation |
|---|
| 191 | Ft1 = new Filtration(B.nextRealization()); |
|---|
| 192 | Ft2 = new Filtration(B.nextRealization()); |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | @Override |
|---|
| 196 | public double evaluate(int t) { |
|---|
| 197 | double B1 = Ft1.B(t); |
|---|
| 198 | double B2 = Ft2.B(t); |
|---|
| 199 | return B1 * B2; |
|---|
| 200 | } |
|---|
| 201 | }; |
|---|
| 202 | Integral I = new IntegralDt(B1B2); |
|---|
| 203 | |
|---|
| 204 | Expectation E = new Expectation(I, |
|---|
| 205 | T_0, T_1, // [0, 1] |
|---|
| 206 | N_T, // discretization |
|---|
| 207 | N_SIMS); // number of simulations |
|---|
| 208 | |
|---|
| 209 | System.out.printf("the mean is %f%n", E.mean()); |
|---|
| 210 | System.out.printf("the variance is %f%n", E.variance()); |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | /** |
|---|
| 214 | * Compute the (empirical) distribution for |
|---|
| 215 | * |
|---|
| 216 | * /1 | [B1(t) * B2(t)] dt /0 |
|---|
| 217 | * |
|---|
| 218 | * B1, B2 are two different Brownian motions. |
|---|
| 219 | */ |
|---|
| 220 | public static void B1B1dt_0020() { |
|---|
| 221 | |
|---|
| 222 | TimeGrid T = new EvenlySpacedGrid(T_0, T_1, N_T); // discretization |
|---|
| 223 | DiscreteSDE sde = new BrownianSDE(); |
|---|
| 224 | double x0 = 0.0; |
|---|
| 225 | final RandomRealizationGenerator B = new RandomRealizationOfRandomProcess(sde, T, x0); |
|---|
| 226 | |
|---|
| 227 | FiltrationFunction B1B2 = new FiltrationFunction() { |
|---|
| 228 | private Filtration Ft1; |
|---|
| 229 | private Filtration Ft2; |
|---|
| 230 | |
|---|
| 231 | @Override |
|---|
| 232 | public void setFt(Filtration Ft) { |
|---|
| 233 | // FT is not used in this function |
|---|
| 234 | super.setFt(Ft); |
|---|
| 235 | // generate a filtration for each new simulation |
|---|
| 236 | Ft1 = new Filtration(B.nextRealization()); |
|---|
| 237 | Ft2 = new Filtration(B.nextRealization()); |
|---|
| 238 | } |
|---|
| 239 | |
|---|
| 240 | @Override |
|---|
| 241 | public double evaluate(int t) { |
|---|
| 242 | double B1 = Ft1.B(t); |
|---|
| 243 | double B2 = Ft2.B(t); |
|---|
| 244 | return B1 * B2; |
|---|
| 245 | } |
|---|
| 246 | }; |
|---|
| 247 | |
|---|
| 248 | double[] stats = new double[N_SIMS]; |
|---|
| 249 | for (int i = 0; i < N_SIMS; ++i) { |
|---|
| 250 | double I = new IntegralDt(B1B2).value(new Filtration(B.nextRealization())); |
|---|
| 251 | stats[i] = I; |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | // construct an empirical distribution |
|---|
| 255 | EmpiricalDistribution dist = new EmpiricalDistribution(stats); |
|---|
| 256 | double x = 0.1; |
|---|
| 257 | double cdf = dist.cdf(x); |
|---|
| 258 | System.out.printf("F(%.1f) = %f%n", x, cdf); |
|---|
| 259 | } |
|---|
| 260 | } |
|---|