internal static double[,] RandomSetMulti(int TrailNum, int StepNum) { //this is the road which use the multithreading double[,] RandomSetMulti = new double[TrailNum, StepNum]; Random rand2 = new Random(); // int Thread1 = 1; Action <object> MyAct = x => { Parallel.ForEach(Ienum.Step(0, TrailNum, 1), new ParallelOptions { MaxDegreeOfParallelism = cores }, a => { for (long b = 0; b < StepNum; b++) { RandomSetMulti[a, b] = mt_rand();//Call box muller to generate ONE NORMAL random } }); }; Thread th = new Thread(new ParameterizedThreadStart(MyAct)); th.Start(); th.Join(); th.Abort(); return(RandomSetMulti); double mt_rand() //Box Muller Norm Random have to lock when nulti threading { //var obj = new Object(); double randn1 = 0, randn2 = 0; //for parallel computing in the future, lock to ensure serial access // The item you locked is your Random Class lock (rand2) randn1 = rand2.NextDouble(); lock (rand2) randn2 = rand2.NextDouble(); double z1 = 0; z1 = Math.Sqrt((-2) * Math.Log(randn1)) * Math.Cos(2 * Math.PI * randn2); return(z1); } }
internal static double[] Simulate(double SO, double K, double sigma, double r, double t, Int32 StepNum, Int32 TrailNum, double[,] Randoms, int Anti, double div, int Deltabase, int MultiThread) { double[] Result = new double[4]; double[,] set = new double[1, 4]; double SumCall = 0.0; double SumPut = 0.0; double StdCallEr = 0.0; double StdCallSum = 0.0; double StdPutSum = 0.0; double StdPutEr = 0.0; double CallSd, PutSd; if (Anti == 1) { double x, y; if (Deltabase == 1) { double dt, St, St1, Stn, Stn1, cv, cv1, CT, PT, Sum_CT, Sum_PT, Sum_PT2, Sum_CT2, t1, CallDelta = 0, CallDelta1 = 0, PutDelta = 0, PutDelta1 = 0, beta1, nudt, sigsdt, erddt;//I don't know what the beta1 is. dt = t / (StepNum); nudt = (r - div - 0.5 * Math.Pow(sigma, 2)) * dt; sigsdt = sigma * Math.Sqrt(dt); erddt = Math.Exp((r - div) * dt); Sum_CT = 0; Sum_CT2 = 0; Sum_PT = 0; Sum_PT2 = 0; beta1 = -1; double[] DeltaSet = new double[2]; double[] DeltaSet1 = new double[2]; //this loop is used for restoring the simulation result if (MultiThread == 1) { int Thread1 = 1; Parallel.ForEach(Ienum.Step(0, TrailNum, 1), new ParallelOptions { MaxDegreeOfParallelism = Thread1 }, a => { St = SO; St1 = SO; cv = 0; cv1 = 0; for (int j = 1; j <= StepNum; j++) { t1 = t - dt * (j - 1); DeltaSet = Black_Scholes_Delta.Black_Scholes_DeltaSet(St, t1, K, sigma, r); DeltaSet1 = Black_Scholes_Delta.Black_Scholes_DeltaSet(St1, t1, K, sigma, r); CallDelta = DeltaSet[0]; PutDelta = DeltaSet[1]; CallDelta1 = DeltaSet1[0]; PutDelta1 = DeltaSet1[1]; Stn = St * Math.Exp(nudt + sigsdt * Randoms[a, j - 1]); Stn1 = St1 * Math.Exp(nudt + sigsdt * (-Randoms[a, j - 1])); cv = cv + CallDelta * (Stn - St * erddt) + CallDelta1 * (Stn1 - St1 * erddt); cv1 = cv1 + PutDelta * (Stn - St * erddt) + PutDelta1 * (Stn1 - St1 * erddt); St = Stn; St1 = Stn1; } CT = Math.Max(St - K, 0) + Math.Max(St1 - K, 0) + beta1 * cv; Sum_CT = Sum_CT + CT; Sum_CT2 = Sum_CT2 + CT * CT; PT = Math.Max(K - St, 0) + Math.Max(K - St1, 0) + beta1 * cv1; Sum_PT = Sum_PT + PT; Sum_PT2 = Sum_PT2 + PT * PT; }); x = Sum_CT * Math.Exp(-r * t) / (2 * TrailNum);; CallSd = Math.Sqrt((Sum_CT2 - Sum_CT * Sum_CT / (2 * TrailNum)) * Math.Exp(-2 * r * t) / (2 * TrailNum - 1)); StdCallEr = CallSd / Math.Sqrt(2 * TrailNum); y = Sum_PT * Math.Exp(-r * t) / (2 * TrailNum); PutSd = Math.Sqrt((Sum_PT2 - Sum_PT * Sum_PT / (2 * TrailNum)) * Math.Exp(-2 * r * t) / (2 * TrailNum - 1)); StdPutEr = PutSd / Math.Sqrt(2 * TrailNum); } else { for (int i = 0; i < TrailNum; i++) { St = SO; St1 = SO; cv = 0; cv1 = 0; for (int j = 1; j <= StepNum; j++) { t1 = t - dt * (j - 1); DeltaSet = Black_Scholes_Delta.Black_Scholes_DeltaSet(St, t1, K, sigma, r); DeltaSet1 = Black_Scholes_Delta.Black_Scholes_DeltaSet(St1, t1, K, sigma, r); CallDelta = DeltaSet[0]; PutDelta = DeltaSet[1]; CallDelta1 = DeltaSet1[0]; PutDelta1 = DeltaSet1[1]; Stn = St * Math.Exp(nudt + sigsdt * Randoms[i, j - 1]); Stn1 = St1 * Math.Exp(nudt + sigsdt * (-Randoms[i, j - 1])); cv = cv + CallDelta * (Stn - St * erddt) + CallDelta1 * (Stn1 - St1 * erddt); cv1 = cv1 + PutDelta * (Stn - St * erddt) + PutDelta1 * (Stn1 - St1 * erddt); St = Stn; St1 = Stn1; } CT = Math.Max(St - K, 0) + Math.Max(St1 - K, 0) + beta1 * cv; Sum_CT = Sum_CT + CT; Sum_CT2 = Sum_CT2 + CT * CT; PT = Math.Max(K - St, 0) + Math.Max(K - St1, 0) + beta1 * cv1; Sum_PT = Sum_PT + PT; Sum_PT2 = Sum_PT2 + PT * PT; } } x = Sum_CT * Math.Exp(-r * t) / (2 * TrailNum);; CallSd = Math.Sqrt((Sum_CT2 - Sum_CT * Sum_CT / (2 * TrailNum)) * Math.Exp(-2 * r * t) / (2 * TrailNum - 1)); StdCallEr = CallSd / Math.Sqrt(2 * TrailNum); y = Sum_PT * Math.Exp(-r * t) / (2 * TrailNum); PutSd = Math.Sqrt((Sum_PT2 - Sum_PT * Sum_PT / (2 * TrailNum)) * Math.Exp(-2 * r * t) / (2 * TrailNum - 1)); StdPutEr = PutSd / Math.Sqrt(2 * TrailNum); } else { double[,] sims = new double[TrailNum, StepNum]; double[,] sims1 = new double[TrailNum, StepNum]; //int Thread1 = 1; if (MultiThread == 1) { Action <object> MyAct1 = x2 => { Parallel.ForEach(Ienum.Step(0, TrailNum, 1), new ParallelOptions { MaxDegreeOfParallelism = cores }, a => { lock (sims) sims[a, 0] = SO; lock (sims1) sims1[a, 0] = SO; for (int j = 1; j < StepNum; j++) { lock (sims) sims[a, j] = sims[a, j - 1] * Math.Exp((r - 0.5 * Math.Pow(sigma, 2)) * (t / (StepNum - 1)) + sigma * Math.Pow((t / (StepNum - 1)), 0.5) * Randoms[a, j]); lock (sims1) sims1[a, j] = sims1[a, j - 1] * Math.Exp((r - 0.5 * Math.Pow(sigma, 2)) * (t / (StepNum - 1)) + sigma * Math.Pow((t / (StepNum - 1)), 0.5) * (-Randoms[a, j])); } lock (sims) lock (sims1) SumCall += Math.Max(sims[a, StepNum - 1] - K, 0) + Math.Max(sims1[a, StepNum - 1] - K, 0); lock (sims) lock (sims1) SumPut += Math.Max(K - sims[a, StepNum - 1], 0) + Math.Max(K - sims1[a, StepNum - 1], 0); }); }; Thread th = new Thread(new ParameterizedThreadStart(MyAct1)); th.Start(); th.Join(); th.Abort(); x = (SumCall / (2 * TrailNum)) * Math.Exp(-r * t); y = (SumPut / (2 * TrailNum)) * Math.Exp(-r * t); //calculate the sum of call and put Action <object> MyAct2 = x2 => { Parallel.ForEach(Ienum.Step(0, TrailNum, 1), new ParallelOptions { MaxDegreeOfParallelism = cores }, a => { lock (sims) lock (sims1) StdCallSum = StdCallSum + Math.Pow(((Math.Max(sims[a, StepNum - 1] - K, 0) + Math.Max(sims1[a, StepNum - 1] - K, 0)) / 2 - SumCall / (2 * TrailNum)), 2); lock (sims) lock (sims1) StdPutSum = StdPutSum + Math.Pow(((Math.Max(K - sims[a, StepNum - 1], 0) + Math.Max(K - sims1[a, StepNum - 1], 0)) / 2 - (SumPut / (2 * TrailNum))), 2); }); }; Thread th1 = new Thread(new ParameterizedThreadStart(MyAct2)); th1.Start(); th1.Join(); th1.Abort(); //calculate the StdError StdCallEr = Math.Sqrt(StdCallSum) * Math.Exp(-r * t) / TrailNum; StdPutEr = Math.Sqrt(StdPutSum) * Math.Exp(-r * t) / TrailNum; } else { for (int p = 0; p < TrailNum; p++) { sims[p, 0] = SO; sims1[p, 0] = SO; } //this loop is used for restoring the simulation result for (int i = 0; i < TrailNum; i++) { for (int j = 1; j < StepNum; j++) { sims[i, j] = sims[i, j - 1] * Math.Exp((r - 0.5 * Math.Pow(sigma, 2)) * (t / (StepNum - 1)) + sigma * Math.Pow((t / (StepNum - 1)), 0.5) * Randoms[i, j]); sims1[i, j] = sims1[i, j - 1] * Math.Exp((r - 0.5 * Math.Pow(sigma, 2)) * (t / (StepNum - 1)) + sigma * Math.Pow((t / (StepNum - 1)), 0.5) * (-Randoms[i, j])); } } for (int a = 0; a < TrailNum; a++) { SumCall += Math.Max(sims[a, StepNum - 1] - K, 0) + Math.Max(sims1[a, StepNum - 1] - K, 0); SumPut += Math.Max(K - sims[a, StepNum - 1], 0) + Math.Max(K - sims1[a, StepNum - 1], 0); } x = (SumCall / (2 * TrailNum)) * Math.Exp(-r * t); y = (SumPut / (2 * TrailNum)) * Math.Exp(-r * t); //calculate the sum of call and put for (int q = 0; q < TrailNum; q++) { StdCallSum = StdCallSum + Math.Pow(((Math.Max(sims[q, StepNum - 1] - K, 0) + Math.Max(sims1[q, StepNum - 1] - K, 0)) / 2 - SumCall / (2 * TrailNum)), 2); StdPutSum = StdPutSum + Math.Pow(((Math.Max(K - sims[q, StepNum - 1], 0) + Math.Max(K - sims1[q, StepNum - 1], 0)) / 2 - (SumPut / (2 * TrailNum))), 2); } //calculate the StdError StdCallEr = Math.Sqrt(StdCallSum) * Math.Exp(-r * t) / TrailNum; StdPutEr = Math.Sqrt(StdPutSum) * Math.Exp(-r * t) / TrailNum; } } Result[0] = x; Result[1] = y; Result[2] = StdCallEr; Result[3] = StdPutEr; } else { double[,] sims = new double[TrailNum, StepNum]; double x, y; if (Deltabase == 1) { double dt, St, Stn, cv, cv1, CT, PT, Sum_CT, Sum_PT, Sum_PT2, Sum_CT2, t1, CallDelta = 0, PutDelta = 0, beta1, nudt, sigsdt, erddt;//I don't know what the beta1 is. dt = t / (StepNum); nudt = (r - div - 0.5 * Math.Pow(sigma, 2)) * dt; sigsdt = sigma * Math.Sqrt(dt); erddt = Math.Exp((r - div) * dt); Sum_CT = 0; Sum_CT2 = 0; Sum_PT = 0; Sum_PT2 = 0; beta1 = -1; double[] DeltaSet = new double[2]; int Thread1 = 1; //this loop is used for restoring the simulation result if (MultiThread == 1) { Parallel.ForEach(Ienum.Step(0, TrailNum, 1), new ParallelOptions { MaxDegreeOfParallelism = Thread1 }, a => { St = SO; cv = 0; cv1 = 0; for (int j = 1; j <= StepNum; j++) { t1 = t - dt * (j - 1); DeltaSet = Black_Scholes_Delta.Black_Scholes_DeltaSet(St, t1, K, sigma, r); CallDelta = DeltaSet[0]; PutDelta = DeltaSet[1]; Stn = St * Math.Exp(nudt + sigsdt * Randoms[a, j - 1]); cv = cv + CallDelta * (Stn - St * erddt); cv1 = cv1 + PutDelta * (Stn - St * erddt); St = Stn; } CT = Math.Max(St - K, 0) + beta1 * cv; Sum_CT = Sum_CT + CT; Sum_CT2 = Sum_CT2 + CT * CT; PT = Math.Max(K - St, 0) + beta1 * cv1; Sum_PT = Sum_PT + PT; Sum_PT2 = Sum_PT2 + PT * PT; }); } else { for (int i = 0; i < TrailNum; i++) { St = SO; cv = 0; cv1 = 0; for (int j = 1; j <= StepNum; j++) { t1 = t - dt * (j - 1); DeltaSet = Black_Scholes_Delta.Black_Scholes_DeltaSet(St, t1, K, sigma, r); CallDelta = DeltaSet[0]; PutDelta = DeltaSet[1]; Stn = St * Math.Exp(nudt + sigsdt * Randoms[i, j - 1]); cv = cv + CallDelta * (Stn - St * erddt); cv1 = cv1 + PutDelta * (Stn - St * erddt); St = Stn; } CT = Math.Max(St - K, 0) + beta1 * cv; Sum_CT = Sum_CT + CT; Sum_CT2 = Sum_CT2 + CT * CT; PT = Math.Max(K - St, 0) + beta1 * cv1; Sum_PT = Sum_PT + PT; Sum_PT2 = Sum_PT2 + PT * PT; } } x = Sum_CT * Math.Exp(-r * t) / (TrailNum);; CallSd = Math.Sqrt((Sum_CT2 - Sum_CT * Sum_CT / (TrailNum)) * Math.Exp(-2 * r * t) / (TrailNum - 1)); StdCallEr = CallSd / Math.Sqrt(TrailNum); y = Sum_PT * Math.Exp(-r * t) / (TrailNum); PutSd = Math.Sqrt((Sum_PT2 - Sum_PT * Sum_PT / (TrailNum)) * Math.Exp(-2 * r * t) / (TrailNum - 1)); StdPutEr = PutSd / Math.Sqrt(TrailNum); } else { int Thread1 = 1; if (MultiThread == 1) { Action <object> MyAct1 = x2 => { Parallel.ForEach(Ienum.Step(0, TrailNum, 1), new ParallelOptions { MaxDegreeOfParallelism = cores }, a => { lock (sims) sims[a, 0] = SO; for (int j = 1; j < StepNum; j++) { lock (sims) sims[a, j] = sims[a, j - 1] * Math.Exp((r - 0.5 * Math.Pow(sigma, 2)) * (t / (StepNum - 1)) + sigma * Math.Pow((t / (StepNum - 1)), 0.5) * Randoms[a, j]); } lock (sims) SumCall += Math.Max(sims[a, StepNum - 1] - K, 0); lock (sims) SumPut += Math.Max(K - sims[a, StepNum - 1], 0); }); }; Thread th = new Thread(new ParameterizedThreadStart(MyAct1)); th.Start(); th.Join(); th.Abort(); x = (SumCall / TrailNum) * Math.Exp(-r * t); y = (SumPut / TrailNum) * Math.Exp(-r * t); //calculate the sum of call and put Parallel.ForEach(Ienum.Step(0, TrailNum, 1), new ParallelOptions { MaxDegreeOfParallelism = Thread1 }, a => { StdCallSum = StdCallSum + Math.Pow((Math.Max(sims[a, StepNum - 1] - K, 0) - x), 2); StdPutSum = StdPutSum + Math.Pow((Math.Max(K - sims[a, StepNum - 1], 0) - y), 2); }); } else { for (int p = 0; p < TrailNum; p++) { sims[p, 0] = SO; } //this loop is used for restoring the simulation result for (int i = 0; i < TrailNum; i++) { for (int j = 1; j < StepNum; j++) { sims[i, j] = sims[i, j - 1] * Math.Exp((r - 0.5 * Math.Pow(sigma, 2)) * (t / (StepNum - 1)) + sigma * Math.Pow((t / (StepNum - 1)), 0.5) * Randoms[i, j]); } } for (int a = 0; a < TrailNum; a++) { SumCall += Math.Max(sims[a, StepNum - 1] - K, 0); SumPut += Math.Max(K - sims[a, StepNum - 1], 0); } x = (SumCall / TrailNum) * Math.Exp(-r * t); y = (SumPut / TrailNum) * Math.Exp(-r * t); //calculate the sum of call and put for (int q = 0; q < TrailNum; q++) { StdCallSum = StdCallSum + Math.Pow((Math.Max(sims[q, StepNum - 1] - K, 0) - x), 2); StdPutSum = StdPutSum + Math.Pow((Math.Max(K - sims[q, StepNum - 1], 0) - y), 2); } } //calculate the StdError StdCallEr = Math.Sqrt((1.0 / (TrailNum - 1)) * StdCallSum) / Math.Sqrt(TrailNum); StdPutEr = Math.Sqrt((1.0 / (TrailNum - 1)) * StdPutSum) / Math.Sqrt(TrailNum); } Result[0] = x; Result[1] = y; Result[2] = StdCallEr; Result[3] = StdPutEr; } return(Result); }