//Fonction Psi(theta_n,Ztilde_n+1) = Y_n+1. public double FonctionPSI_(double K, double theta) { this.K_ = K; double ratio1 = 0.0; double Z = LoiNormal.random_normal_parBoxMuller(rnd); List <double> ST = new List <double>(); for (int i = 0; i < S0_.Count; i++) { ST.Add(S0_[i] * Math.Exp((r_ - Math.Pow(Sigma_[i], 2) / 2) * t_ + Sigma_[i] * Math.Pow(t_, 0.50) * Z)); } if (this.op_ == type_.Call) { ratio1 = Math.Exp(-r_ * t_) * Math.Pow(Math.Max(ST.Average() - K_, 0.0), 2); //attention Math.Exp(-2*r_ * t_) } else if (this.op_ == type_.Put) { ratio1 = Math.Exp(-r_ * t_) * Math.Pow(Math.Max(K_ - ST.Average(), 0.0), 2); //attention Math.Exp(-2*r_ * t_) } else { throw new InvalidOperationException("Impossible de traiter le type d'option entrer!!!!: " + this.op_); } double ratio2 = (theta - Z) * Math.Exp(-0.5 * theta * (2 * Z - theta)); double Psi = ratio1 * ratio2; return(Psi); }
/****************************************************************************** * ************ Valeur d'une option basket avec la méthode de réduction ******* **************** de la variance Robbins Monro (Arouna) ******************* * ****************************************************************************/ public double[] MC_RM_ArounaBasketOptionVal(type_ op) { //RobbinsMonroAlgorithme RM; List <double> Payoff_; double[,] ST_; double[] res = new double[2]; //Tableau résultat Payoff_ = new List <double>(); ST_ = new double[NSim_, S0_.Count]; double NormBoxMuller; switch (op) { case type_.Call: for (int j = 0; j < NSim_; j++) { double som = 0; for (int i = 0; i < S0_.Count; i++) { NormBoxMuller = LoiNormal.random_normal_parBoxMuller(rnd); ST_[j, i] = S0_[i] * Math.Exp((r_ - 0.5 * Math.Pow(Sigma_[i], 2)) * t_ + Sigma_[i] * Math.Sqrt(t_) * NormBoxMuller); if (j < NSim_ - 1) { ST_[j + 1, i] = S0_[i] * Math.Exp((r_ - 0.5 * Math.Pow(Sigma_[i], 2)) * t_ + Sigma_[i] * Math.Sqrt(t_) * NormBoxMuller); } som += ST_[j, i]; } j++; Payoff_.Add(Math.Exp(-r_ * t_) * Math.Max((som / S0_.Count - K_), 0.0)); } break; case type_.Put: for (int j = 0; j < NSim_; j++) { double som = 0; for (int i = 0; i < S0_.Count; i++) { NormBoxMuller = LoiNormal.random_normal_parBoxMuller(rnd); ST_[j, i] = S0_[i] * Math.Exp((r_ - 0.5 * Math.Pow(Sigma_[i], 2)) * t_ + Sigma_[i] * Math.Sqrt(t_) * NormBoxMuller); if (j < NSim_ - 1) { ST_[j + 1, i] = S0_[i] * Math.Exp((r_ - 0.5 * Math.Pow(Sigma_[i], 2)) * t_ + Sigma_[i] * Math.Sqrt(t_) * NormBoxMuller); } som += ST_[j, i]; } j++; Payoff_.Add(Math.Exp(-r_ * t_) * Math.Max((K_ - som / S0_.Count), 0.0)); } break; default: throw new InvalidOperationException("Impossible de traiter le type d'option entrer!!!!: " + op); } res[0] = Payoff_.Average(); //La valeur de l'option, Esperance des payoff actualisés res[1] = Math.Sqrt(Variance(Payoff_, res[0], 0, Payoff_.Count)); //L'ecarte type de simulation, return(res); }
//Algorithme de robbinsMonro public double ThetaOptimalRMArouna(double K, double Theta0, int Niter) { double x1 = -2; double x2 = 2; List <int> rho_ = new List <int>(); List <double> u_ = new List <double>(); List <double> Theta_ = new List <double>(); List <double> y_ = new List <double>(); List <double> gamma_ = new List <double>(); Theta_.Add(Theta0); double x = LoiNormal.random_normal_parBoxMuller(rnd); y_.Add(FonctionPSI_(K_, Theta_[0])); rho_.Add(0); gamma_.Add(1); u_.Add(50); for (int i = 1; i <= Niter + 1; i++) { gamma_.Add(1 / (double)(i + 1)); //gamma_n = a/(b+n) u_.Add(Math.Sqrt((1 / 6) * Math.Log((double)i + 1)) + u_[0]); //U_n = sqrt(1/6*ln(n))+U_0 } for (int i = 0; i <= Niter; i++) { rho_.Add(0); y_.Add(FonctionPSI_(K, Theta_[i])); double xn = 0; if (i >= 1) { rho_[i] = rho_[i - 1]; if (Math.Abs(Theta_[i - 1] - gamma_[i] * y_[i]) > u_[rho_[i - 1]]) { rho_[i] = rho_[i] + 1; } } if (rho_[i] % 2 == 0) { xn = x1; } else { xn = x2; } if (Math.Abs(Theta_[i] - gamma_[i + 1] * y_[i + 1]) <= u_[rho_[i]]) { Theta_.Add(Theta_[i] - gamma_[i + 1] * y_[i + 1]); } else { Theta_.Add(xn); } } return(Theta_[Niter - 1]); }
//Calcul de la valeur d'une option basket en utilisant l'algorithme de RM pour la réduction de la variance public double[] MC_RM_BasketOptionVal(double Theta, double K) { List <double> Payoff_; double[,] ST_; List <double> Z; double Ztilde = LoiNormal.random_normal_parBoxMuller(rnd) + Theta; Payoff_ = new List <double>(); //Payoff de l'option à chaque trajectoire ST_ = new double[NSim_, S0_.Count]; //ST simulées Z = new List <double>(); // double[] res = new double[2]; //Tableau résultat if (this.op_ == type_.Call) { for (int j = 0; j < NSim_; j++) { double som = 0; for (int i = 0; i < S0_.Count; i++) { Ztilde = LoiNormal.random_normal_parBoxMuller(rnd) + Theta; ST_[j, i] = S0_[i] * Math.Exp((r_ - 0.5 * Math.Pow(Sigma_[i], 2)) * t_ + Sigma_[i] * Math.Sqrt(t_) * Ztilde); som += ST_[j, i]; } Payoff_.Add(Math.Max((som / S0_.Count - K_), 0.0)); Z.Add(Math.Exp(-r_ * t_) * (Math.Exp(0.5 * Math.Pow(Theta, 2) - Theta * Ztilde)) * Payoff_[j]); } } else if (this.op_ == type_.Put) { for (int j = 0; j < NSim_; j++) { double som = 0; for (int i = 0; i < S0_.Count; i++) { Ztilde = LoiNormal.random_normal_parBoxMuller(rnd) + Theta; ST_[j, i] = S0_[i] * Math.Exp((r_ - 0.5 * Math.Pow(Sigma_[i], 2)) * t_ + Sigma_[i] * Math.Sqrt(t_) * Ztilde); som += ST_[j, i]; } Payoff_.Add(Math.Max((K_ - som / S0_.Count), 0.0)); Z.Add(Math.Exp(-r_ * t_) * (Math.Exp(0.5 * Math.Pow(Theta, 2) - Theta * Ztilde)) * Payoff_[j]); } } else { throw new InvalidOperationException("Impossible de traiter le type d'option entrer!!!!: "); } res[0] = Z.Average(); //La valeur de l'option, Esperance des payoff actualisés res[1] = Math.Sqrt(Variance(Z, Z.Average(), 0, Z.Count)); //L'ecarte type de simulation, return(res); }
/********************************************************************************************************* * Fonction return à la valeur d'une option européenne type=Call ou Put * return à une vecteur de taille 2: première composante de la table contenant la valeur de l'option * Deuxième composante: l'erreur de la simulation MC **********************************************************************************************************/ public double[] MCEuropOptionVal(type_ op) { List <double> ST_, Payoff_, SquareEsperance; double mu = (r_ - 0.5 * Math.Pow(Sigma_, 2)) * t_; double sig = Sigma_ * Math.Sqrt(t_); double NormBoxMuller; //Variable Normale centrée reduite ST_ = new List <double>(); //Tableau pour stocker les valeurs de ST simuler Payoff_ = new List <double>(); //Tableau des PayOff SquareEsperance = new List <double>(); //Esperance des crées double[] res = new double[2]; //Tableau résultat for (int i = 0; i < NSim_; i++) { NormBoxMuller = LoiNormal.random_normal_parBoxMuller(rnd); ST_.Add(S0_ * Math.Exp(mu + sig * NormBoxMuller)); if (i < NSim_ - 1) { ST_.Add(S0_ * Math.Exp(mu - (sig * NormBoxMuller))); } i++; } switch (op) { case type_.Call: for (int i = 0; i < NSim_; i++) { Payoff_.Add(Math.Exp(-r_ * t_) * Math.Max((ST_[i] - K_), 0.0)); SquareEsperance.Add(Math.Pow(Payoff_[i], 2)); } break; case type_.Put: for (int i = 0; i < NSim_; i++) { Payoff_.Add(Math.Exp(-r_ * t_) * Math.Max((K_ - ST_[i]), 0.0)); SquareEsperance.Add(Math.Pow(Payoff_[i], 2)); } break; default: throw new InvalidOperationException("Impossible de traiter le type d'option entrer!!!!: " + op); } res[0] = Payoff_.Average(); //La valeur de l'option, Esperance des payoff actualisés res[1] = Math.Sqrt(Variance(Payoff_, res[0], 0, Payoff_.Count)); //L'ecarte type de simulation, return(res); }
//Calcul de la valeur d'une option européenne en utilisant l'algorithme de RM pour la réduction de la variance public double[] MCEurValeurISLemairePages(double Theta, double K) { double[] PrixSimul = new double[NSim_]; double Ztilde = LoiNormal.random_normal_parBoxMuller(rnd) + Theta; //Variable Normale: moyenne =tetha* , variance = 1; double mu = (r_ - 0.5 * Math.Pow(Sigma_, 2)) * T_; double sig = Sigma_ * Math.Sqrt(T_); List <double> Payoff_ = new List <double>(); List <double> Z = new List <double>();; List <double> NormalVar = new List <double>(); List <double> Zcarre = new List <double>(); double[] res = new double[2]; this.K_ = K; for (int i = 0; i < NSim_; i++) { Ztilde = LoiNormal.random_normal_parBoxMuller(rnd) + Theta; PrixSimul[i] = S0_ * Math.Exp(mu + sig * Ztilde); NormalVar.Add(Math.Pow(Ztilde, 2)); if (this.op_ == type_.Call) { Payoff_.Add(Math.Max(PrixSimul[i] - K_, 0.0)); } else if (this.op_ == type_.Put) { Payoff_.Add(Math.Max(K_ - PrixSimul[i], 0.0)); } else { throw new InvalidOperationException("Impossible de traiter le type d'option entrer!!!!: " + this.op_); } Z.Add(Math.Exp(-r_ * T_) * (Math.Exp(0.5 * Math.Pow(Theta, 2) - Theta * Ztilde)) * Payoff_[i]); Zcarre.Add((Math.Pow(Z[i], 2))); } res[0] = Z.Average(); //La moyenne des PayOff actulisés res[1] = Math.Sqrt(Variance(Z, Z.Average(), 0, Z.Count)); //L'ecarte type de simulation, return(res); }
public double ThetaOptimalPL(double K, double Theta0, double lamda, int Niter) { List <double> Theta_ = new List <double>(); List <double> gamma_ = new List <double>(); List <double> y_ = new List <double>(); double Z = LoiNormal.random_normal_parBoxMuller(rnd); this.K_ = K; Theta_.Add(Theta0); gamma_.Add(1); y_.Add(Math.Exp(-2 * lamda * Theta_[0]) * FonctionFCaree(K_, Theta_[0]) * (2 * Theta_[0] - Z)); for (int i = 1; i <= Niter + 1; i++) { gamma_.Add(1 / (double)(i + 1)); //gamma_n = a/(b+n) } for (int i = 0; i < Niter; i++) { Z = LoiNormal.random_normal_parBoxMuller(rnd); Theta_.Add(Theta_[i] - gamma_[i + 1] * y_[i]); y_.Add(Math.Exp(-2 * lamda * Theta_[i + 1]) * FonctionFCaree(K_, Theta_[i + 1]) * (2 * Theta_[i + 1] - Z)); } return(Theta_[Niter - 1]); }
//Fonction F^2(Xn+1 - theta) public double FonctionFCaree(double K, double theta) { this.K_ = K; double ratio1 = 0.0; double Z = LoiNormal.random_normal_parBoxMuller(rnd) - theta; double ST = S0_ * Math.Exp((r_ - Math.Pow(Sigma_, 2) / 2) * T_ + Sigma_ * Math.Pow(T_, 0.50) * Z); if (this.op_ == type_.Call) { ratio1 = Math.Pow(Math.Max(ST - K_, 0.0), 2); } else if (this.op_ == type_.Put) { ratio1 = Math.Pow(Math.Max(K_ - ST, 0.0), 2); } else { throw new InvalidOperationException("Impossible de traiter le type d'option entrer!!!!: " + this.op_); } double ratio2 = 1; double Psi = ratio1 * ratio2; return(Psi); }
static void Main(string[] args) { Random rnd = new Random(); BSEurOption Eur; RobbinsMonroAlgorithme RM_Put; RobbinsMonroAlgorithme RM_Call; MCEuropOption MCEur; RMAlgoPagesLemaire PL_Call; RMAlgoPagesLemaire PL_Put; double S0 = 100; double K = 95; double r = 0.05; int T = 1; double sigma = 0.15; double theta0 = 1.5; double lamda = 30; long Nsim = 2000; int Ntier = 500000; Eur = new BSEurOption(S0, K, r, T, sigma); RM_Put = new RobbinsMonroAlgorithme(S0, K, T, sigma, r, Nsim, type_.Put); RM_Call = new RobbinsMonroAlgorithme(S0, K, T, sigma, r, Nsim, type_.Call); PL_Call = new RMAlgoPagesLemaire(S0, K, T, sigma, r, Nsim, type_.Call); PL_Put = new RMAlgoPagesLemaire(S0, K, T, sigma, r, Nsim, type_.Put); MCEur = new MCEuropOption(S0, K, T, sigma, r, Nsim); double z = LoiNormal.random_normal_parBoxMuller(rnd); double thetaOptArouna; double thetaPL; /*********************************************** * ********** Valeur d'un call Européen ******** * **********************************************/ Console.WriteLine("============================================================"); Console.WriteLine("====================Call Européen==========================="); Console.WriteLine("============================================================"); Console.WriteLine("Valeur exacte d'un Call (avec formules de BS)= " + Eur.callBlackScholes()); Console.WriteLine("\nValeur d'un Call avec réduction de la variance par var ANti= " + MCEur.MCEuropOptionVal(type_.Call)[0]); Console.WriteLine("\nVariance IS(Variables Antithetique)= " + MCEur.MCEuropOptionVal(type_.Call)[1]); thetaOptArouna = RM_Call.ThetaOptimalRMArouna(K, theta0, Ntier); Console.WriteLine("\nTheta optimal avec Robbins Monro [Arouna]= " + thetaOptArouna); Console.WriteLine("\nValeur d'un Call avec réduction de la variance IS= " + +RM_Call.MCEurValeurImportanceSampling(thetaOptArouna, K)[0]); Console.WriteLine("\nVariance IS(Anouna RM algo)= " + +RM_Call.MCEurValeurImportanceSampling(thetaOptArouna, K)[1]); thetaPL = PL_Call.ThetaOptimalPL(105, 0.3, 30, 10); Console.WriteLine("\nTheta RMPagesLemaire = " + thetaPL); Console.WriteLine("\nValeur d'un Call avec (Algo RM PagesLemaire) = " + PL_Call.MCEurValeurISLemairePages(thetaPL, K)[0]); Console.WriteLine("\nVariance IS(PagesLemaire RM algo) = " + PL_Call.MCEurValeurISLemairePages(thetaPL, K)[1]); /*************************************** ********* Test options basket ********* ***************************************/ Console.WriteLine("\n\n============================================================"); Console.WriteLine("====================Options Basket==========================="); Console.WriteLine("============================================================"); List <double> S0_ = new List <double>(); List <double> Sigma_ = new List <double>(); for (int i = 0; i < 3; i++) { S0_.Add(94 + i * 4); Sigma_.Add(0.25 + i * 0.02); } MCBasketOption bsket = new MCBasketOption(S0_, K, T, Sigma_, r, Nsim); MCRMBasketOption rmbask = new MCRMBasketOption(S0_, K, T, Sigma_, r, Nsim, type_.Call); Console.WriteLine("\n\n prix Basket Call MC_ Var Anti= " + bsket.MC_AntitBasketOptionVal(type_.Call)[0]); Console.WriteLine("\n\n prix Basket Put MC_ Var Anti= " + bsket.MC_AntitBasketOptionVal(type_.Put)[0]); double thetarmBasket = rmbask.ThetaOptimalRMArouna(105, 1.5, 100000); Console.WriteLine("\n\n Theta optimal avec RM de l'option Basket = " + thetarmBasket); Console.ReadLine(); }