Nishant
• 111
• 2
public double BlackScholes(boolean callFlag, double S, double K, double T, double r, double v)
{
//S is underlyng spot price
//K is the strike price
//T is time left to expiry
// r is the risk free rate
// v is volatility
//callFlag is true for Call Option, false for put

double d1, d2;

d1=(log(S/K)+(r+v*v/2)*T)/(v* sqrt(T));
d2=d1-v* sqrt(T);

if (callFlag){
return S*CND(d1)-K* exp(-r*T)*CND(d2);
}else{
return K* exp(-r*T)*CND(-d2)-S*CND(-d1);
}
}

// The cumulative normal distribution function
public double CND(double X)
{
double L, K, w ;
double a1 = 0.31938153, a2 = -0.356563782, a3 = 1.781477937, a4 = -1.821255978, a5 = 1.330274429;

L = Math.abs(X);
K = 1.0 / (1.0 + 0.2316419 * L);
w = 1.0 - 1.0 / sqrt(2.0 * Math.PI) * exp(-L *L / 2) * (a1 * K + a2 * K *K + a3
* Math.pow(K,3) + a4 * Math.pow(K,4) + a5 * Math.pow(K,5));

if (X < 0.0)
{
w= 1.0 - w;
}
return w;
}

public double implVolNR(double S, double K, double r, double time, double option_price, boolean callFlag) {
if (option_price < 0.99 * (S - K * exp(-time * r))) { // check for arbitrage violations. Option price is too low if this happens
return 0.0;
}
final int MAX_ITERATIONS = 100;
final double ACCURACY = 1.0e-2;
double t_sqrt = Math.sqrt(time);
double sigma = (option_price / S) / (0.398 * t_sqrt); // find initial value
for (int i = 0; i < MAX_ITERATIONS; i++) {
double price = BlackScholes(callFlag, S, K, time, r, sigma);

//option_price call black scholes(S,K,r,sigma,time);
double diff = option_price - price;
if (Math.abs(diff) < ACCURACY) return sigma;
double d1 = (log(S / K) + r * time) / (sigma * t_sqrt) + 0.5 * sigma * t_sqrt;
double vega = S * t_sqrt * CND(d1);
sigma = sigma + diff / vega;
}
return Double.NaN; // return error values
}

Nishant
• 111
• 2
public double BlackScholes(boolean callFlag, double S, double K, double T, double r, double v)
{
//S is underlyng spot price
//K is the strike price
//T is time left to expiry
// r is the risk free rate
// v is volatility
//callFlag is true for Call Option, false for put

double d1, d2;

d1=(log(S/K)+(r+v*v/2)*T)/(v* sqrt(T));
d2=d1-v* sqrt(T);

if (callFlag){
return S*CND(d1)-K* exp(-r*T)*CND(d2);
}else{
return K* exp(-r*T)*CND(-d2)-S*CND(-d1);
}
}

// The cumulative normal distribution function
public double CND(double X)
{
double L, K, w ;
double a1 = 0.31938153, a2 = -0.356563782, a3 = 1.781477937, a4 = -1.821255978, a5 = 1.330274429;

L = Math.abs(X);
K = 1.0 / (1.0 + 0.2316419 * L);
w = 1.0 - 1.0 / sqrt(2.0 * Math.PI) * exp(-L *L / 2) * (a1 * K + a2 * K *K + a3
* Math.pow(K,3) + a4 * Math.pow(K,4) + a5 * Math.pow(K,5));

if (X < 0.0)
{
w= 1.0 - w;
}
return w;
}

public double implVolNR(double S, double K, double r, double time, double option_price, boolean callFlag) {
if (option_price < 0.99 * (S - K * exp(-time * r))) { // check for arbitrage violations. Option price is too low if this happens
return 0.0;
}
final int MAX_ITERATIONS = 100;
final double ACCURACY = 1.0e5;0e-2;
double t_sqrt = Math.sqrt(time);
double sigma = (option_price / S) / (0.398 * t_sqrt); // find initial value
for (int i = 0; i < MAX_ITERATIONS; i++) {
double price = BlackScholes(callFlag, S, K, time, r, sigma);
//option_price call black scholes(S,K,r,sigma,time);
double diff = option_price - price;
if (Math.abs(diff) < ACCURACY) return sigma;
double d1 = (log(S / K) + r * time) / (sigma * t_sqrt) + 0.5 * sigma * t_sqrt;
double vega = S * t_sqrt * CND(d1);
sigma = sigma + diff / vega;
}
return Double.NaN; // return error values
}

Nishant
• 111
• 2

For Java, combining @vjond answer (as the initial starting estimate for implied Volatility), with a basic Cumulative Density Function for Normal distribution (CDN), and the Black Scholes Model applied to Newton Raphson, below is a basic Implied Volatility calculation for Java :

For the NR code (C), plz refer http://finance.bi.no/~bernt/gcc_prog/recipes/recipes.pdf

For the Black Scholes price calculator (Java and other languages) and Cumulative Density function, please refer http://www.espenhaug.com/black_scholes.html

public double BlackScholes(boolean callFlag, double S, double K, double T, double r, double v)
{
//S is underlyng spot price
//K is the strike price
//T is time left to expiry
// r is the risk free rate
// v is volatility
//callFlag is true for Call Option, false for put

double d1, d2;

d1=(log(S/K)+(r+v*v/2)*T)/(v* sqrt(T));
d2=d1-v* sqrt(T);

if (callFlag){
return S*CND(d1)-K* exp(-r*T)*CND(d2);
}else{
return K* exp(-r*T)*CND(-d2)-S*CND(-d1);
}
}

// The cumulative normal distribution function
public double CND(double X)
{
double L, K, w ;
double a1 = 0.31938153, a2 = -0.356563782, a3 = 1.781477937, a4 = -1.821255978, a5 = 1.330274429;

L = Math.abs(X);
K = 1.0 / (1.0 + 0.2316419 * L);
w = 1.0 - 1.0 / sqrt(2.0 * Math.PI) * exp(-L *L / 2) * (a1 * K + a2 * K *K + a3
* Math.pow(K,3) + a4 * Math.pow(K,4) + a5 * Math.pow(K,5));

if (X < 0.0)
{
w= 1.0 - w;
}
return w;
}

public double implVolNR(double S, double K, double r, double time, double option_price, boolean callFlag) {
if (option_price < 0.99 * (S - K * exp(-time * r))) { // check for arbitrage violations. Option price is too low if this happens
return 0.0;
}
final int MAX_ITERATIONS = 100;
final double ACCURACY = 1.0e5;
double t_sqrt = Math.sqrt(time);
double sigma = (option_price / S) / (0.398 * t_sqrt); // find initial value
for (int i = 0; i < MAX_ITERATIONS; i++) {
double price = BlackScholes(callFlag, S, K, time, r, sigma);
//option_price call black scholes(S,K,r,sigma,time);
double diff = option_price - price;
if (Math.abs(diff) < ACCURACY) return sigma;
double d1 = (log(S / K) + r * time) / (sigma * t_sqrt) + 0.5 * sigma * t_sqrt;
double vega = S * t_sqrt * CND(d1);
sigma = sigma + diff / vega;
}
return Double.NaN; // return error values
}