In this post, I give out a ready to use figure or plot that one could keep handy to relate VIX level to the Expected S&P 500 returns Range over the next 30 days. I also show how the plot is derived. DOUBLE CLICK THE PLOT FOR A BIGGER IMAGE
As you can see from the Above figure, one can easily figure out the expected range of S&P 500 Returns with a given VIX Level for a given Probability. For example, Currently the VIX level is 30%. So looking at the above plot, for 90% Probability,30% VIX,on the X-Axis and following it vertically and across, we can see that over the next 30 days, the expected range for S&P 500 Returns is +/- 14.24% .
In general, The linear relationship is as follows:
Expected Range with 50% Probability = 0.1947 * VIX
Expected Range with 68% Probability = 0.2871 * VIX
Expected Range with 75% Probability = 0.3321* VIX
Expected Range with 90% Probability = 0.4748* VIX
Expected Range with 95% Probability = 0.5658 * VIX
Expected Range with 99% Probability = 0.7436 * VIX
Now I show how I derived the Above Plot
% probabilities
p = [0.50 0.68 0.75 0.90 0.95 0.99]
% Properly adjust those probabilities to be passed into norminv program
p2 = 0.50 + p./2;
% Before we proceed we should make an important assumption that
% The rate of return on the S&P 500 over the next 30 days is normally
% distributed
% USe the norminv command to get the number of standard deviations
% that a number drawn from unit normal distribution will be
nstd = norminv(p2,0,1);
% since VIX is is an annualized standard deviation, We divide the values
% Obtainded above by sqrt(12)
nstd = nstd ./ sqrt(12);
% Now the Linear Relationship between Level of VIX and S&P 500 return range
% would be: ExpRangeSP500 = nstd .* VIX
% Now let us plot using various values of VIX
VIX = 0:10:100;
ExpRangeSP500 = nstd' * VIX;
%%PLOT
plot(VIX,ExpRangeSP500,'-*')
set(gca,'YTick',[0:5:max(ExpRangeSP500(:))])
set(gca,'YtickLabel',cellstr(strcat(num2str([0:5:max(ExpRangeSP500(:))]'),'%')))
set(gca,'XTickLabel',cellstr(strcat(num2str(VIX'),'%')))
title('VIX vs S&P 500 returns Expected Range over next 30 days')
xlabel('VIX')
ylabel('S&P 500 returns Expected Range over next 30 days')
plottitles = strcat(cellstr(num2str(p' .*100)),'%');
legend(plottitles,'Location','best')
text(VIX(9)*ones(6,1),ExpRangeSP500(:,9),plottitles,'FontSize',14,'FontWeight','bold')
grid on
axis tight
Quantitative Futures, stocks and Options Trading
Saturday, June 27, 2009
Wednesday, June 24, 2009
Applying VIX methodology to Stocks (American )
GOOGLEDOCS file:
http://docs.google.com/View?id=ddb2j6dw_13dg24q4mk
In this post I show how one could utilize the VIX methodology for American
Options.VIX was designed with European Type Options. It was designed
for S&P500 Options ( which are European ). But when applied to American
Options,These have a bias due to early exercise and Dividend and disbursement
events. If the forecasted period avoids dividends, then the bias should
be minimal. Neverthelss, It can be used as a valuable forecast or a
technical indicator.
function VIX = ReplicateVixStock(Data,TM,Rf,CT)
%REPLICATEVIXSTOCK applies VIX methodology for stocks (American Options)
% VIX was designed with European Type Options. It was designed for S&P500
% Options ( which are European ). But when applied to American Options,
% These have a bias due to early exercise and Dividend and disbursement
% events. If the forecasted period avoids dividends, then the bias should
% be minimal. Neverthelss, It can be used as a valuable forecast or a
% technical indicator.
% Inputs: If NO Inputs are provided, Example will run
% Data: Should be cell array with separate data for two Maturities
% centered around 30 days. I.e One option expiry must be less than 30
% days and the other should be greater than 30 days.
% Data is a three column data with Strike, Call and Put Prices.
% Data{1} should be Near Term Option Data
% Data{2} should be far Term Option Data
% TM : Time to maturity for two options
% Rf : Risk free Rate
% CT : Current Time ( Time Stamp when The data was collected )
% Output : VIX-- A single number that Applies the VIX methodology to the
% American Options
% Example : Try running with NO inputs
if(nargin==0)
% Near-Term
% Strike Call Put
Data{1} = [75 11.75 0.05;...
80 6.90 0.08;...
85 2.40 0.60;...
90 0.18 3.40;...
95 0.05 8.30;...
];
% Next Term
% Strike Call Put
Data{2} = [75 NaN NaN;...
80 7.70 0.73;...
85 3.80 1.80;...
90 1.05 4.05;...
95 NaN NaN;...
];
%Time_To_Maturity
TM = [9;37];
%Risk_Free_Rate
Rf = 1.1625/100; %Per Annum
% Current Time
CT = '12:09:00';
end
% remove NaN Rows
Data{1}((any(isnan(Data{1}),2)),:)=[];
Data{2}((any(isnan(Data{2}),2)),:)=[];
% Difference between Calls and Puts (Absolute Value)
DF{1} = abs(Data{1}(:,2) - Data{1}(:,3));
DF{2} = abs(Data{2}(:,2) - Data{2}(:,3));
% FInd Hour, Minute, Second from the time using datevec function
[Year, Month, Day, Hour, Minute, Second] = datevec(CT);
%In Years
%1440 is the number of minutes in a day and 510 is the number
% of minutes to 8:30 AM which is the time the option expires
% on its expiration date
NumYears(1) =[1440 - (Hour * 60 + Minute + Second/60) + 510]/ ...
(1440 * 365) + [(TM(1) - 2)/365];
NumYears(2) =[1440 - (Hour * 60 + Minute + Second/60) + 510]/ ...
(1440 * 365) + [(TM(2) - 2)/365];
% In days
NumDays = NumYears .* 365;
% Find the minimum of the difference in Call and Put
% Prices and Get the corresponding Strike Price.
ATM(1,:) = Data{1}((DF{1}==min(DF{1})),:);
ATM(2,:) = Data{2}((DF{2}==min(DF{2})),:);
% Calculate Forward Price Level and Referential Strike
% Application of PUT CALL Parity
Level = ATM(:,1) + exp(Rf*NumYears(:)) .* (ATM(:,2) - ATM(:,3));
%Reference Strike
for i = 1:2
Strike = ATM(i,1);
if(ATM(i,2)>=ATM(i,3))
Ref_Strike(i)=ATM(i,1);
else
Ref_Strike(i) = Data{i}(find(Data{i}(:,1) < ATM(i,1),1,'last'),1);
end
% Differences of Strikes
Temp = diff(Data{i}(:,1));
Delta_Strike{i} = [Temp(1);Temp];
% If the strike is above the “reference strike” , use the call price
% If the strike is below the “reference strike” , use the put price
%If the strike equals the “reference strike” , use the average of the call
% and put prices
cpval= zeros(size(Data{i},1),1);
cid = find(Data{i}(:,1) > Ref_Strike(i));
cpval(cid) = Data{i}(cid,2);
pid = find(Data{i}(:,1) < Ref_Strike(i));
cpval(pid) = Data{i}(pid,3);
Aid = find(Data{i}(:,1) == Ref_Strike(i));
cpval(Aid) = (Data{i}(Aid,2) + Data{i}(Aid,3))/2;
% Now do the math as given in the paper vixwhite.pdf
vix{i} = Delta_Strike{i} * exp(Rf*NumYears(i)) .* cpval ./(Data{i}(:,1).^2);
Var(i) = (2/NumYears(i)) * sum(vix{i}) - ((Level(i)/Ref_Strike(i) ...
- 1).^2)/NumYears(i);
% Center the data to 30 days
if(i==1)
Term(i) = NumYears(i) * Var(i) * ((NumDays(i+1)-30)/(NumDays(i+1)-NumDays(i)));
elseif(i==2)
Term(i) = NumYears(i) * Var(i) * ((-NumDays(i-1)+30)/(NumDays(i)-NumDays(i-1)));
end
end %i
% Final Vix Calculation
VIX = sqrt(sum(Term) * 365/30) * 100;
http://docs.google.com/View?id=ddb2j6dw_13dg24q4mk
In this post I show how one could utilize the VIX methodology for American
Options.VIX was designed with European Type Options. It was designed
for S&P500 Options ( which are European ). But when applied to American
Options,These have a bias due to early exercise and Dividend and disbursement
events. If the forecasted period avoids dividends, then the bias should
be minimal. Neverthelss, It can be used as a valuable forecast or a
technical indicator.
function VIX = ReplicateVixStock(Data,TM,Rf,CT)
%REPLICATEVIXSTOCK applies VIX methodology for stocks (American Options)
% VIX was designed with European Type Options. It was designed for S&P500
% Options ( which are European ). But when applied to American Options,
% These have a bias due to early exercise and Dividend and disbursement
% events. If the forecasted period avoids dividends, then the bias should
% be minimal. Neverthelss, It can be used as a valuable forecast or a
% technical indicator.
% Inputs: If NO Inputs are provided, Example will run
% Data: Should be cell array with separate data for two Maturities
% centered around 30 days. I.e One option expiry must be less than 30
% days and the other should be greater than 30 days.
% Data is a three column data with Strike, Call and Put Prices.
% Data{1} should be Near Term Option Data
% Data{2} should be far Term Option Data
% TM : Time to maturity for two options
% Rf : Risk free Rate
% CT : Current Time ( Time Stamp when The data was collected )
% Output : VIX-- A single number that Applies the VIX methodology to the
% American Options
% Example : Try running with NO inputs
if(nargin==0)
% Near-Term
% Strike Call Put
Data{1} = [75 11.75 0.05;...
80 6.90 0.08;...
85 2.40 0.60;...
90 0.18 3.40;...
95 0.05 8.30;...
];
% Next Term
% Strike Call Put
Data{2} = [75 NaN NaN;...
80 7.70 0.73;...
85 3.80 1.80;...
90 1.05 4.05;...
95 NaN NaN;...
];
%Time_To_Maturity
TM = [9;37];
%Risk_Free_Rate
Rf = 1.1625/100; %Per Annum
% Current Time
CT = '12:09:00';
end
% remove NaN Rows
Data{1}((any(isnan(Data{1}),2)),:)=[];
Data{2}((any(isnan(Data{2}),2)),:)=[];
% Difference between Calls and Puts (Absolute Value)
DF{1} = abs(Data{1}(:,2) - Data{1}(:,3));
DF{2} = abs(Data{2}(:,2) - Data{2}(:,3));
% FInd Hour, Minute, Second from the time using datevec function
[Year, Month, Day, Hour, Minute, Second] = datevec(CT);
%In Years
%1440 is the number of minutes in a day and 510 is the number
% of minutes to 8:30 AM which is the time the option expires
% on its expiration date
NumYears(1) =[1440 - (Hour * 60 + Minute + Second/60) + 510]/ ...
(1440 * 365) + [(TM(1) - 2)/365];
NumYears(2) =[1440 - (Hour * 60 + Minute + Second/60) + 510]/ ...
(1440 * 365) + [(TM(2) - 2)/365];
% In days
NumDays = NumYears .* 365;
% Find the minimum of the difference in Call and Put
% Prices and Get the corresponding Strike Price.
ATM(1,:) = Data{1}((DF{1}==min(DF{1})),:);
ATM(2,:) = Data{2}((DF{2}==min(DF{2})),:);
% Calculate Forward Price Level and Referential Strike
% Application of PUT CALL Parity
Level = ATM(:,1) + exp(Rf*NumYears(:)) .* (ATM(:,2) - ATM(:,3));
%Reference Strike
for i = 1:2
Strike = ATM(i,1);
if(ATM(i,2)>=ATM(i,3))
Ref_Strike(i)=ATM(i,1);
else
Ref_Strike(i) = Data{i}(find(Data{i}(:,1) < ATM(i,1),1,'last'),1);
end
% Differences of Strikes
Temp = diff(Data{i}(:,1));
Delta_Strike{i} = [Temp(1);Temp];
% If the strike is above the “reference strike” , use the call price
% If the strike is below the “reference strike” , use the put price
%If the strike equals the “reference strike” , use the average of the call
% and put prices
cpval= zeros(size(Data{i},1),1);
cid = find(Data{i}(:,1) > Ref_Strike(i));
cpval(cid) = Data{i}(cid,2);
pid = find(Data{i}(:,1) < Ref_Strike(i));
cpval(pid) = Data{i}(pid,3);
Aid = find(Data{i}(:,1) == Ref_Strike(i));
cpval(Aid) = (Data{i}(Aid,2) + Data{i}(Aid,3))/2;
% Now do the math as given in the paper vixwhite.pdf
vix{i} = Delta_Strike{i} * exp(Rf*NumYears(i)) .* cpval ./(Data{i}(:,1).^2);
Var(i) = (2/NumYears(i)) * sum(vix{i}) - ((Level(i)/Ref_Strike(i) ...
- 1).^2)/NumYears(i);
% Center the data to 30 days
if(i==1)
Term(i) = NumYears(i) * Var(i) * ((NumDays(i+1)-30)/(NumDays(i+1)-NumDays(i)));
elseif(i==2)
Term(i) = NumYears(i) * Var(i) * ((-NumDays(i-1)+30)/(NumDays(i)-NumDays(i-1)));
end
end %i
% Final Vix Calculation
VIX = sqrt(sum(Term) * 365/30) * 100;
Subscribe to:
Posts (Atom)