Permalink
Browse files

Got basic bond functionality working

  • Loading branch information...
brymck committed Sep 28, 2011
1 parent 9df0211 commit 83a33defd89b08f73c4eb4ac1a469dd4fbd0d6c2
View
@@ -1,27 +1,17 @@
#include "rupee.h"
double
-bond_price(rcf_times, rcfs, r)
- VALUE rcf_times, rcfs;
- double r;
+bond_price(cf_times, cfs, r, len)
+ double *cf_times, *cfs, r;
+ int len;
{
double p, *cft;
- int i, cfs_len;
+ int i;
- VALUE *cf_times, *cfs;
- cf_times = RARRAY_PTR(rcf_times);
- cfs = RARRAY_PTR(rcfs);
- cfs_len = RARRAY_LEN(rcfs);
p = 0;
- for (i = 0; i < cfs_len; i++) {
- double cfti, cfi;
-
- cfti = NUM2DBL(cf_times[i]);
- cfi = NUM2DBL(cfs[i]);
-
- p += exp(-r * cfti) * cfi;
- };
+ for (i = 0; i < len; i++)
+ p += exp(-r * cf_times[i]) * cfs[i];
return p;
};
@@ -30,37 +20,33 @@ static VALUE
price(self, rcf_times, rcfs, rr)
VALUE self, rcf_times, rcfs, rr;
{
- double r;
+ int len = RARRAY_LEN(rcfs);
+ double r, cf_times[len], cfs[len];
r = NUM2DBL(rr);
+ rtofa(cf_times, rcf_times, len);
+ rtofa(cfs, rcfs, len);
- return rb_float_new(bond_price(rcf_times, rcfs, r));
+ return rb_float_new(bond_price(cf_times, cfs, r, len));
}
static VALUE
convexity(self, rcf_times, rcfs, rr)
VALUE self, rcf_times, rcfs, rr;
{
- double r, C, B;
- int i, cfs_len;
- VALUE *cf_times, *cfs;
+ int len = RARRAY_LEN(rcfs);
+ double r, C, B, cf_times[len], cfs[len];
+ int i;
- cf_times = RARRAY_PTR(rcf_times);
- cfs = RARRAY_PTR(rcfs);
- cfs_len = RARRAY_LEN(rcfs);
+ rtofa(cf_times, rcf_times, len);
+ rtofa(cfs, rcfs, len);
r = NUM2DBL(rr);
C = 0;
- for (i = 0; i < cfs_len; i++) {
- double cfti, cfi;
-
- cfti = NUM2DBL(cf_times[i]);
- cfi = NUM2DBL(cfs[i]);
-
- C += cfi * pow(cfti, 2) * exp(-r * cfti);
- };
+ for (i = 0; i < len; i++)
+ C += cfs[i] * pow(cf_times[i], 2) * exp(-r * cf_times[i]);
- B = bond_price(rcf_times, rcfs, r);
+ B = bond_price(cf_times, cfs, r, len);
return rb_float_new(C / B);
};
View
@@ -1,20 +1,18 @@
#include "rupee.h"
double *
-rtofary(rary)
- VALUE rary;
+rtofa(dest, src, len)
+ double *dest;
+ VALUE src;
+ int len;
{
- int len, i;
- double *result;
+ int i;
VALUE *ary;
- ary = RARRAY_PTR(rary);
- len = RARRAY_LEN(rary);
- result = realloc(result, len);
+ ary = RARRAY_PTR(src);
for (i = 0; i < len; i++)
- result[i] = NUM2DBL(ary[i]);
+ dest[i] = NUM2DBL(ary[i]);
- return result;
+ return dest;
}
-
View
@@ -9,7 +9,7 @@
extern VALUE module;
/* Conversion */
-double *rtofary(VALUE rary);
+double *rtofa(double *dest, VALUE src, int len);
/* Statistics */
double cnd(double);
@@ -21,7 +21,7 @@ double gbs(const char *call_put_flag, double S, double X, double T, double r,
void init_option();
/* Bonds */
-double bond_price(VALUE rcf_times, VALUE rcfs, double r);
+double bond_price(double *cf_times, double *cfs, double r, int len);
void init_bond();
#endif
View
@@ -0,0 +1,39 @@
+require File.dirname(__FILE__) + "/../spec_helper"
+
+# Discrete discounting
+# bonds price = 102.531
+# bond yield to maturity = 0.09
+# bond duration = 2.73895
+# bond duration modified = 2.5128
+# bond convexity =8.93248
+# new bond price = 100
+#Continous discounting
+# bonds price = 101.464
+# bond yield to maturity = 0.09
+# bond duration = 2.73753
+# bond convexity =7.86779
+# new bond price = 104.282
+
+TOLERANCE = 0.001
+
+describe Rupee::Bond do
+ before :each do
+ @times = [1, 2, 3]
+ @cflows = [10, 10, 110]
+ @r = 0.09
+ end
+
+ describe "with continuous discounting" do
+ it "should produce an accurate price" do
+ Rupee::Bond.price(@times, @cflows, @r).should be_within(TOLERANCE).of 101.464
+ end
+
+ it "should produce an accurate duration" do
+ Rupee::Bond.duration(@times, @cflows, @r).should be_within(TOLERANCE).of 2.73753
+ end
+
+ it "should produce an accurate convexity" do
+ Rupee::Bond.convexity(@times, @cflows, @r).should be_within(TOLERANCE).of 7.86779
+ end
+ end
+end
File renamed without changes.
View
@@ -0,0 +1,45 @@
+require File.dirname(__FILE__) + "/../spec_helper"
+
+describe Rupee::Option do
+ describe "European option valuation" do
+ describe "using the Black-76 model" do
+ describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
+ it "should return $1.7202 for a call" do
+ Rupee::Option.black76("c", 60, 65, 0.25, 0.08, 0.3).round(4).should == 1.7202
+ end
+
+ it "should return $6.6212 for a put" do
+ Rupee::Option.black76("p", 60, 65, 0.25, 0.08, 0.3).round(4).should == 6.6212
+ end
+ end
+ end
+
+ describe "using the generalized Black-Scholes model" do
+ describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
+ it "should return $1.7202 for a call" do
+ Rupee::Option.generalized_black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 1.7202
+ Rupee::Option.gbs("c", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 1.7202
+ end
+
+ it "should return $6.6212 for a put" do
+ Rupee::Option.generalized_black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 6.6212
+ Rupee::Option.gbs("p", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 6.6212
+ end
+ end
+ end
+
+ describe "using the Black-Scholes model" do
+ describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
+ it "should return $1.7202 for a call" do
+ Rupee::Option.black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 2.1334
+ Rupee::Option.bs("c", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 2.1334
+ end
+
+ it "should return $6.6212 for a put" do
+ Rupee::Option.black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 5.8463
+ Rupee::Option.bs("p", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 5.8463
+ end
+ end
+ end
+ end
+end
View
@@ -1,43 +0,0 @@
-require File.dirname(__FILE__) + "/../spec_helper"
-
-describe "European option valuation" do
- describe "using the Black-76 model" do
- describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
- it "should return $1.7202 for a call" do
- Rupee::Option.black76("c", 60, 65, 0.25, 0.08, 0.3).round(4).should == 1.7202
- end
-
- it "should return $6.6212 for a put" do
- Rupee::Option.black76("p", 60, 65, 0.25, 0.08, 0.3).round(4).should == 6.6212
- end
- end
- end
-
- describe "using the generalized Black-Scholes model" do
- describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
- it "should return $1.7202 for a call" do
- Rupee::Option.generalized_black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 1.7202
- Rupee::Option.gbs("c", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 1.7202
- end
-
- it "should return $6.6212 for a put" do
- Rupee::Option.generalized_black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 6.6212
- Rupee::Option.gbs("p", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 6.6212
- end
- end
- end
-
- describe "using the Black-Scholes model" do
- describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
- it "should return $1.7202 for a call" do
- Rupee::Option.black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 2.1334
- Rupee::Option.bs("c", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 2.1334
- end
-
- it "should return $6.6212 for a put" do
- Rupee::Option.black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 5.8463
- Rupee::Option.bs("p", 60, 65, 0.25, 0.08, 0, 0.3).round(4).should == 5.8463
- end
- end
- end
-end

0 comments on commit 83a33de

Please sign in to comment.