/***************************************************************************************************************************************************************************
Options Pricing , Option Greeks Indicator and Exploration Module
Inspired and Adapted from Yogesh Dalvi on Amibroker forum.
Reference Url : https://forum.amibroker.com/t/black-scholes/4890/8
Coded by Rajandran R (Founder - Marketcalls / Creator - OpenAlgo
Coded Date : 17-02-2021
*****************************************************************************************************************************************************************************/
EnableTextOutput(False);
Symbol = Paramlist("Symbol","NIFTY|BANKNIFTY");
Underlying = Paramlist("Underlying","SPOT|FUTURES",1);
DataVendor = Paramlist("Data Vendor","Globaldatafeeds");
//Data Vendor Block
if(DataVendor == "Globaldatafeeds")
{
_N(Optiontype = StrRight(Name(),6));
Optiontype = StrReplace(Optiontype,".NFO","");
printf("\nOption Type :"+Optiontype);
strikeprice = StrReplace(Name(),".NFO","");
strikeprice1 = Strtrim(strikeprice,Optiontype,2); //remove ce or pe from the extreme right
strikeprice2 = StrReplace(strikeprice1,symbol,"");
expdate = StrLeft(strikeprice2,7);
printf("\nExpiry Date :"+expdate);
iDate = StrLeft(expdate,2);
iYear = StrRight(expdate,2);
iMonth = StrReplace(expdate,iDate,"");
iMonth = StrReplace(iMonth,iYear,"");
jMonth = Null;
if(iMonth=="JAN") jMonth = 1;
if(iMonth=="FEB") jMonth = 2;
if(iMonth=="MAR") jMonth = 3;
if(iMonth=="APR") jMonth = 4;
if(iMonth=="MAY") jMonth = 5;
if(iMonth=="JUN") jMonth = 6;
if(iMonth=="JUL") jMonth = 7;
if(iMonth=="AUG") jMonth = 8;
if(iMonth=="SEP") jMonth = 9;
if(iMonth=="OCT") jMonth = 10;
if(iMonth=="NOV") jMonth = 11;
if(iMonth=="DEC") jMonth = 12;
strikeprice = StrReplace(strikeprice2,idate+imonth+iyear,"");
printf("\nStrike Price :"+strikeprice);
iYear = 2000+StrToNum(iYear);
printf("\nDate :"+iDate + " Month :"+jMonth + " Year :"+iYear );
ExpiryDate = ((iYear-1900)*10000)+(jMonth*100)+StrToNum(iDate);
printf("\nExpiry Date :"+ExpiryDate);
ExpiryTime = ParamTime( "Expiry Time", "15:30:00" );
Expirydatetime = DateTimeConvert(2, ExpiryDate,ExpiryTime);
//Realtime decay
ExpiryDateTime = Expirydatetime;
//candle time difference
timeleftindays = DateTimeDiff(ExpiryDateTime,DateTime())/( 60*60*24 );
//difference from current time to expiry
timeleftnowindays = DateTimeDiff(ExpiryDateTime,StrToDateTime(now()))/( 60*60*24 );
printf( "\nDays left for Expiry: " + timeleftindays );
printf( "\nTime left for Expiry: " + timeleftnowindays );
//Underlying Symbol Mapping Block
if(Underlying == "SPOT")
{
if(symbol=="NIFTY")
{
sym = "NIFTY 50.NSE_IDX";
}
if(symbol=="BANKNIFTY")
{
sym = "NIFTY BANK.NSE_IDX";
}
}
if(Underlying == "FUTURES")
{
if(symbol=="NIFTY")
{
sym = "NIFTY-I.NFO";
}
if(symbol=="BANKNIFTY")
{
sym = "BANKNIFTY-I.NFO";
}
}
printf("\nSymbol :"+sym);
SetForeign(sym);
spotprice = Close;
RestorePriceArrays();
}
/***************************************************************************************************************************************************************************
// Adapted from source code in many programming languages here:
// http://www.espenhaug.com/black_scholes.html
// Greeks forumlas used form Options Pricing Model excel sheet from http://www.optiontradingtips.com
Original Author : Yogesh Dalvi
Date : 10-Sep-2020
Email : [email protected]
twitter : @dyogesh21
Telegram : https:/t.me/Dyogesh
***************************************************************************************************************************************************************************/
//Options Functions
// BlackScholes function parameters:
// isCallFlag = True for Call / False for Put
// S = Stock price
// X = Strike price
// T = Years to maturity (DTE / 365) - DTE = Days to expiration
// r = Risk-free rate
// v = Volatility
// d = Divident
// mp = Market Price
S = spotprice;
X = StrToNum(strikeprice);
T = timeleftindays/365;
r = 0;
mp = Close; //option premium
d = 0;
isCallFlag = False;
if(Optiontype=="CE")
isCallFlag =True;
else if(Optiontype=="PE")
isCallFlag =False;
function OptionPrice(isCallFlag, S, X , T, r, iv,d)
{
local d1, d2, result;
d1 = (log(S / X) + (r - d + (iv * iv * 0.5)) * T) / (iv * sqrt(T));
d2 = d1 - iv * sqrt(T);
if (isCallFlag)
result = ((S * exp(-d * T)* NormDist(d1)) - (X * exp(-r * T) * NormDist(d2)) );
else
result = ( (X * exp(-r * T) * NormDist(-d2)) - (S * NormDist(-d1) * exp(-d * T) ));
return result;
}
function OptionDelta(isCallFlag, S, X, T, r, iv,d)
{
local d1, d2, result;
d1 = (log(S / X) + (r - d + (iv * iv * 0.5)) * T) / (iv * sqrt(T));
d2 = d1 - iv * sqrt(T);
if (isCallFlag)
result = NormDist(d1);
else
result = NormDist(d1) - 1;
return result;
}
function OptionGamma(S, X, T, r, iv,d)
{
local d1, d2, nd1,Pi,result;
Pi = 3.14159265358979;
d1 = (log(S / X) + (r - d + (iv * iv * 0.5)) * T) / (iv * sqrt(T));
d2 = d1 - iv * sqrt(T);
nd1 = exp(-(d1*d1) / 2) / sqrt(2 * Pi);
result = nd1 / (S * (iv * sqrt(T)));
return result;
}
function OptionTheta(isCallFlag, S, X, T, r, iv,d)
{
local d1, d2,nd1,nd2,Pi,theta,result;
Pi = 3.14159265358979;
d1 = (log(S / X) + (r - d + (iv * iv * 0.5)) * T) / (iv * sqrt(T));
d2 = d1 - iv * sqrt(T);
nd1 = exp(-(d1*d1) / 2) / sqrt(2 * Pi);
nd2 = d1 - iv * sqrt(T);
if (isCallFlag)
{
theta = - (((S * iv * nd1) / (2 * sqrt(T))) - (r * X * exp(-r * T) * nd2)) ;
}
else
{
theta = - (((S * iv * nd1) / (2 * sqrt(T))) + (r * X * exp(-r * T) * (1- nd2))) ;
}
if (T < 1 / 365)
result = theta * T ;
else
result = theta / 365;
return result;
}
function OptionVega(S, X, T, r, iv,d)
{
local d1, d2, nd1,Pi,result;
Pi = 3.14159265358979;
d1 = (log(S / X) + (r - d + (iv * iv * 0.5)) * T) / (iv * sqrt(T));
d2 = d1 - iv * sqrt(T);
nd1 = exp(-(d1*d1) / 2) / sqrt(2 * Pi);
result = 0.01 * S * sqrt(T) * nd1;
return result;
}
function OptionRho(isCallFlag,S, X, T, r, iv,d)
{
local d1, d2, nd1,Pi,result;
Pi = 3.14159265358979;
d1 = (log(S / X) + (r - d + (iv * iv * 0.5)) * T) / (iv * sqrt(T));
d2 = d1 - iv * sqrt(T);
nd1 = exp(-(d1*d1) / 2) / sqrt(2 * Pi);
if(iscallFlag)
result = 0.01 * X * T * exp(-r * T) * NormDist(d2);
else
result = - 0.01 * X * T * exp(-r * T) * (1 -NormDist(d2));
}
function OptionIV(isCallFlag, S, X, T, r,mp,d)
{
local hval,lval,result;
hval = 3;
lval = 0;
if(isCallFlag)
{
do
{
if(OptionPrice(isCallFlag,S,X,T,r,(hval+lval) / 2 ,d) > mp)
hval = (hval + lval) / 2;
else
lval = (hval + lval) / 2;
} while ((hval - lval) > 0.0001);
}
else
{
do
{
if(OptionPrice(isCallFlag,S,X,T,r,(hval+lval) / 2 ,d) > mp)
hval = (hval + lval) / 2;
else
lval = (hval + lval) / 2;
} while ((hval - lval) > 0.0001) ;
}
result = (hval + lval) / 2;
return result;
}
for(i=0;i<=BarCount-1;i++)
{
IV[i] = OptionIV(isCallFlag, S[i], X, T[i], r[i],mp[i],d[i]);
}
function OptionGreeks(Greeks)
{
result = Null;
if(Greeks=="IV")
{
result = IV*100;
}
if(Greeks=="delta")
{
for(i=0;i<=BarCount-1;i++)
{
Delta[i] = OptionDelta(isCallFlag, S[i], X , T[i], r[i], IV[i],d[i]) ;
}
Delta = round(prec(Delta, 5) *10000)/10000; //rounding of to the nearest 4 digits
result = Delta;
}
if(Greeks=="gamma")
{
for(i=0;i<=BarCount-1;i++)
{
Gamma[i] = OptionGamma(S[i], X , T[i], r[i], IV[i],d[i]) ;
}
gamma = round(prec(Gamma, 5) *10000)/10000; //rounding of to the nearest 4 digits
result = gamma;
}
if(Greeks=="theta")
{
for(i=0;i<=BarCount-1;i++)
{
Theta[i] = OptionTheta(isCallFlag, S[i], X , T[i], r[i], IV[i],d[i]) ;
}
Theta = round(prec(Theta, 5) *10000)/10000; //rounding of to the nearest 4 digits
result = Theta;
}
if(Greeks=="vega")
{
for(i=0;i<=BarCount-1;i++)
{
Vega[i] = OptionVega( S[i], X , T[i], r[i], IV[i],d[i]) ;
}
Vega = round(prec(Vega, 5) *10000)/10000; //rounding of to the nearest 4 digits
result = Vega;
}
return result;
}
_SECTION_BEGIN("Option Greeks");
list = ParamList("Option Greeks","delta|gamma|theta|gamma|vega|IV",0);
Plot( OptionGreeks(list),"Option Greeks - "+list,colorYellow,styleThick);
//Option Greeks Exploration Module
Filter = 1;
AddColumn(Close,"Premium LTP",1.2);
AddColumn(OptionGreeks("delta"),"Delta",1.2);
AddColumn(OptionGreeks("gamma"),"Gamma",1.2);
AddColumn(OptionGreeks("theta"),"Theta",1.2);
AddColumn(OptionGreeks("vega"),"Vega",1.2);
AddColumn(OptionGreeks("IV"),"Implied Volatility",1.2);
_SECTION_END();