# インプライド・ボラティリティ Implied Volatility # 引数 原資産価格 権利行使価格 残存期間(日) 安全資産利子率(%) 原資産利回り(%) オプションの現在価格 ($Price, $Strike, $CurrentMaturity, $RiskFreeRate, $DividendYield, %OpPrice) # 戻り値 hash {'iv'}->({'call'} {'put'}) (%iv) sub IV{ my ($Price, $Strike, $CurrentMaturity, $RiskFreeRate, $DividendYield, %OpPrice) = @_; my %iv = (); my $Year = 365; my $pi = atan2(1, 1) * 4; my $SqrtCurrentMaturity = 0; $CurrentMaturity = $CurrentMaturity / $Year; $SqrtCurrentMaturity = sqrt($CurrentMaturity); $Volatility = $Volatility / 100; $RiskFreeRate = $RiskFreeRate / 100; $DividendYield = $DividendYield / 100; # 計算 my @op_price = ($OpPrice{'call'}, $OpPrice{'put'}); my @tmp = (); for(my $i = 0; $i <= 1; $i++){ my $Accuracy = 1.0e-6; my $diff = 1; my $vega = 0; my $t_op_price = 0; my $vo = (abs(log($Price / $Strike) + ($RiskFreeRate * $CurrentMaturity)) * 2 / $CurrentMaturity) ** 0.5; while(abs($diff) > $Accuracy){ my $num1 = log($Price / $Strike); my $num2 = ($RiskFreeRate - $DividendYield + (($vo * $vo) / 2)) * $CurrentMaturity; my $den = $vo * $SqrtCurrentMaturity; my $d1 = ($num1 + $num2) / $den; my $d2 = $d1 - ($vo * $SqrtCurrentMaturity); my $nd1 = exp(-($d1 * $d1) / 2) / sqrt(2 * $pi); if($i == 0){ # Call my $call_d1 = &NORMDIST($d1); my $call_d2 = &NORMDIST($d2); $t_op_price = (exp(-($CurrentMaturity * $DividendYield)) * ($Price * $call_d1)) - ($Strike * exp(-($CurrentMaturity * $RiskFreeRate)) * $call_d2); }else { # Put my $put_d1 = &NORMDIST(-$d1); my $put_d2 = &NORMDIST(-$d2); $t_op_price = ($Strike * exp(-($CurrentMaturity * $RiskFreeRate)) * $put_d2) -(exp(-($CurrentMaturity * $DividendYield)) * ($Price * $put_d1)); } $diff = $op_price[$i] - $t_op_price; $vega = $Price * exp(-($CurrentMaturity * $DividendYield)) * $nd1 * $SqrtCurrentMaturity; if($vega == 0){ $vo = "Illegal division by zero"; last; } $vo = $vo + ($diff / $vega); } $tmp[$i] = $vo; } # IV $iv{'iv'}->{'call'} = $tmp[0]; $iv{'iv'}->{'put'} = $tmp[1]; return %iv; }