File Coverage

blib/lib/Finance/Options/Calc.pm
Criterion Covered Total %
statement 56 56 100.0
branch 1 2 50.0
condition 2 3 66.6
subroutine 16 16 100.0
pod 0 10 0.0
total 75 87 86.2


line stmt bran cond sub pod time code
1             package Finance::Options::Calc;
2              
3 1     1   4492 use strict;
  1         3  
  1         45  
4 1     1   6 use Carp;
  1         2  
  1         154  
5 1     1   7 use constant PI => 4 * atan2(1,1);
  1         5  
  1         109  
6 1     1   6 use vars qw(@EXPORT @ISA $VERSION $s $k $r $vol $t $d1 $d2 $nd1);
  1         2  
  1         1210  
7             require Exporter;
8             $VERSION = 0.90;
9             @ISA = qw( Exporter );
10              
11             =head1 NAME
12              
13             C - Option analysis based on different option pricing models.
14              
15             =head1 SYNOPSIS
16              
17             use Finance::Options::Calc;
18            
19             print b_s_call(90, 80, 20, 30, 4.5);
20             print b_s_put (90, 80, 20, 30, 4.5);
21             print call_delta(90, 80, 20, 30, 4.5);
22             print put_delta(90, 80, 20, 30, 4.5);
23             print call_theta(90, 80, 20, 30, 4.5);
24             print put_theta(90, 80, 20, 30, 4.5);
25             print gamma(90, 80, 20, 30, 4.5);
26             print vega(90, 80, 20, 30, 4.5);
27             print call_rho(90, 80, 20, 30, 4.5);
28             print put_rho(90, 80, 20, 30, 4.5);
29              
30              
31             =head1 DESCRIPTION
32              
33             b_s_call() subroutines returns theorical value of the call option based on
34             Black_Scholes model. The arguments are current stock price,
35             strike price, time to expiration (calender days, note this module
36             does NOT use business days), volatility(%), annual interest rate(%) in order.
37              
38             b_s_put() subroutines returns theorical value of the put option based on
39             Black_Scholes model. The arguments are current stock price,
40             strike price, time to expiration (calender days, note this module
41             does NOT use business days), volatility(%), annual interest rate(%) in order.
42              
43             call_delta() returns call delta.
44              
45             put_delta() returns put delta.
46              
47             Other methods are similar.
48              
49             =head1 TODO
50              
51             more calculation models will be included.
52              
53             =head1 AUTHOR
54              
55             Chicheng Zhang
56              
57             chichengzhang@hotmail.com
58              
59             =cut
60              
61             @EXPORT = qw(b_s_call b_s_put call_delta put_delta vega
62             call_rho put_rho call_theta put_theta gamma);
63              
64             sub _variables {
65            
66 10 50   10   30 croak "Not enough arguments.\n" unless $#_ == 4;
67              
68             ## s -- current price
69             ## k -- strike price
70             ## t -- time remains
71             ## vol -- volatility
72             ## r -- interest rate
73              
74 10         28 ($s, $k, $t, $vol, $r) = @_;
75 10         18 $r /= 100;
76 10         13 $vol /= 100;
77 10         10 $t /= 365;
78 10         39 $d1 = (log($s / $k) + ( $r + $vol * $vol / 2 ) * $t) / ($vol * (sqrt $t));
79 10         17 $d2 = $d1 - $vol * (sqrt $t);
80 10         35 $nd1 = exp( - $d1 * $d1 / 2 ) / sqrt( 2 * PI );
81             }
82              
83             sub call_delta {
84 1     1 0 22 _variables(@_);
85 1         3 return sprintf "%5.5f", _norm($d1);
86             }
87              
88             sub put_delta {
89 1     1 0 35 _variables(@_);
90 1         4 return sprintf "%5.5f", _norm($d1) - 1;
91             }
92              
93             sub call_theta {
94 1     1 0 32 _variables(@_);
95 1         7 my $theta_c = - $s * $nd1 * $vol / (2 * sqrt($t)) - $r * $k * exp( - $r * $t ) * _norm($d2);
96 1         12 return sprintf "%5.5f", $theta_c / 365;
97             }
98              
99             sub put_theta {
100 1     1 0 31 _variables(@_);
101 1         6 my $theta_p = - $s * $nd1 * $vol / (2 * sqrt($t)) + $r * $k * exp( - $r * $t ) * _norm(-$d2);
102 1         9 return sprintf "%5.5f", $theta_p / 365;
103             }
104              
105             sub call_rho {
106 1     1 0 29 _variables(@_);
107 1         5 my $rho = $k * $t * exp( - $r * $t ) * _norm($d2);
108 1         8 return sprintf "%5.5f", $rho / 100;
109             }
110              
111             sub put_rho {
112 1     1 0 21 _variables(@_);
113 1         5 my $rho = - $k * $t * exp( - $r * $t ) * _norm(-$d2);
114 1         7 return sprintf "%5.5f", $rho / 100;
115             }
116              
117             sub vega {
118 1     1 0 10 _variables(@_);
119 1         2 my $vega = $s * sqrt($t) * $nd1;
120 1         5 return sprintf "%5.5f", $vega / 100;
121             }
122              
123             sub gamma {
124 1     1 0 13 _variables(@_);
125 1         3 my $gamma= $nd1 / ( $s * $vol * sqrt($t) );
126 1         5 return sprintf "%5.5f", $gamma;
127             }
128              
129             sub b_s_call {
130 1     1 0 48 _variables(@_);
131 1         4 my $c = $s * _norm($d1) - $k * (exp (-$r*$t)) * _norm($d2);
132 1         25 return sprintf "%5.5f", $c;
133             }
134              
135             sub b_s_put {
136 1     1 0 45 _variables(@_);
137 1         6 my $p = $k * (exp (-$r*$t)) * _norm(-$d2) - $s * _norm(-$d1);
138 1         19 return sprintf "%5.5f", $p;
139             }
140              
141             sub _norm {
142              
143 10     10   16 my $d = shift;
144 10         9 my $step = 0.01;
145 10         12 my $sum = 0;
146 10         16 my $x = -5 + $step / 2;
147              
148 10   66     46 while ( ($x < $d) && ($x < 4) )
149             {
150 5350         6816 $sum += exp(- $x * $x / 2) * $step;
151 5350         17509 $x += $step;
152             }
153 10         52 return $sum / sqrt(2 * PI);
154             }
155              
156             1;
157