rupee 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/rupee/option.c CHANGED
@@ -9,7 +9,7 @@ is_call(call_put_flag)
9
9
  return (call_put_flag[0] != 'p');
10
10
  }
11
11
 
12
- static double
12
+ double
13
13
  bs(call_put_flag, S, X, T, r, q, v)
14
14
  const char *call_put_flag;
15
15
  double S, X, T, r, q, v;
@@ -25,9 +25,477 @@ bs(call_put_flag, S, X, T, r, q, v)
25
25
  return X * exp(-r * T) * cnd(-d2) - S * exp(-q * T) * cnd(-d1);
26
26
  }
27
27
 
28
- /* call-seq:
29
- * black_scholes(call_put_flag, forward, strike_price, time_to_expiry,
30
- * risk_free_rate, volatility)
28
+ // GREEKS
29
+
30
+ double
31
+ delta(call_put_flag, S, K, T, r, q, v)
32
+ const char *call_put_flag;
33
+ double S, K, T, r, q, v;
34
+ {
35
+ double d1;
36
+
37
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
38
+
39
+ if (is_call(call_put_flag))
40
+ return exp(-q * T) * cnd(d1);
41
+ else
42
+ return -exp(-q * T) * cnd(-d1);
43
+ }
44
+
45
+ double
46
+ vega(call_put_flag, S, K, T, r, q, v)
47
+ const char *call_put_flag;
48
+ double S, K, T, r, q, v;
49
+ {
50
+ double d1;
51
+
52
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
53
+
54
+ return S * exp(-q * T) * pdf(d1) * sqrt(T);
55
+ }
56
+
57
+ double
58
+ theta(call_put_flag, S, K, T, r, q, v)
59
+ const char *call_put_flag;
60
+ double S, K, T, r, q, v;
61
+ {
62
+ double d1, d2;
63
+
64
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
65
+ d2 = d1 - v * sqrt(T);
66
+
67
+ if (is_call(call_put_flag))
68
+ return -exp(-q * T) * (S * pdf(d1) * v) / (2 * sqrt(T)) -
69
+ r * K * exp(-r * T) * cnd(d2) + q * S * exp(-q * T) * cnd(d1);
70
+ else
71
+ return -exp(-q * T) * (S * pdf(d1) * v) / (2 * sqrt(T)) +
72
+ r * K * exp(-r * T) * cnd(-d2) - q * S * exp(-q * T) * cnd(-d1);
73
+ }
74
+
75
+ double
76
+ rho(call_put_flag, S, K, T, r, q, v)
77
+ const char *call_put_flag;
78
+ double S, K, T, r, q, v;
79
+ {
80
+ double d1, d2;
81
+
82
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
83
+ d2 = d1 - v * sqrt(T);
84
+
85
+ if (is_call(call_put_flag))
86
+ return K * T * exp(-r * T) * cnd(d2);
87
+ else
88
+ return -K * T * exp(-r * T) * cnd(-d2);
89
+ }
90
+
91
+ double
92
+ bs_gamma(call_put_flag, S, K, T, r, q, v)
93
+ const char *call_put_flag;
94
+ double S, K, T, r, q, v;
95
+ {
96
+ double d1;
97
+
98
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
99
+
100
+ return exp(-q * T) * pdf(d1) / (S * v * sqrt(T));
101
+ }
102
+
103
+ /* call-seq: delta(call_put_flag, underlying, strike, time, rate, div_yield,
104
+ * volatility)
105
+ *
106
+ * Returns the delta options Greek (sensitivity to changes in the underlying's
107
+ * price
108
+ */
109
+ static VALUE
110
+ rupee_delta(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
111
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
112
+ {
113
+ const char *call_put_flag;
114
+ double S, K, T, r, q, v;
115
+
116
+ call_put_flag = StringValuePtr(_call_put_flag);
117
+ S = NUM2DBL(_S);
118
+ K = NUM2DBL(_K);
119
+ T = NUM2DBL(_T);
120
+ r = NUM2DBL(_r);
121
+ q = NUM2DBL(_q);
122
+ v = NUM2DBL(_v);
123
+
124
+ return rb_float_new(delta(call_put_flag, S, K, T, r, q, v));
125
+ }
126
+
127
+ /* call-seq: vega(call_put_flag, underlying, strike, time, rate, div_yield,
128
+ * volatility)
129
+ *
130
+ * Returns the vega options Greek (sensitivity to changes in volatility)
131
+ */
132
+ static VALUE
133
+ rupee_vega(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
134
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
135
+ {
136
+ const char *call_put_flag;
137
+ double S, K, T, r, q, v;
138
+
139
+ call_put_flag = StringValuePtr(_call_put_flag);
140
+ S = NUM2DBL(_S);
141
+ K = NUM2DBL(_K);
142
+ T = NUM2DBL(_T);
143
+ r = NUM2DBL(_r);
144
+ q = NUM2DBL(_q);
145
+ v = NUM2DBL(_v);
146
+
147
+ return rb_float_new(vega(call_put_flag, S, K, T, r, q, v));
148
+ }
149
+
150
+ /* call-seq: theta(call_put_flag, underlying, strike, time, rate, div_yield,
151
+ * volatility)
152
+ *
153
+ * returns the theta options greek (sensitivity to the passage of time; time
154
+ * decay)
155
+ */
156
+ static VALUE
157
+ rupee_theta(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
158
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
159
+ {
160
+ const char *call_put_flag;
161
+ double S, K, T, r, q, v;
162
+
163
+ call_put_flag = StringValuePtr(_call_put_flag);
164
+ S = NUM2DBL(_S);
165
+ K = NUM2DBL(_K);
166
+ T = NUM2DBL(_T);
167
+ r = NUM2DBL(_r);
168
+ q = NUM2DBL(_q);
169
+ v = NUM2DBL(_v);
170
+
171
+ return rb_float_new(theta(call_put_flag, S, K, T, r, q, v));
172
+ }
173
+
174
+ /* call-seq: rho(call_put_flag, underlying, strike, time, rate, div_yield,
175
+ * volatility)
176
+ *
177
+ * Returns the rho options Greek (sensitivity to the risk-free rate)
178
+ */
179
+ static VALUE
180
+ rupee_rho(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
181
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
182
+ {
183
+ const char *call_put_flag;
184
+ double S, K, T, r, q, v;
185
+
186
+ call_put_flag = StringValuePtr(_call_put_flag);
187
+ S = NUM2DBL(_S);
188
+ K = NUM2DBL(_K);
189
+ T = NUM2DBL(_T);
190
+ r = NUM2DBL(_r);
191
+ q = NUM2DBL(_q);
192
+ v = NUM2DBL(_v);
193
+
194
+ return rb_float_new(rho(call_put_flag, S, K, T, r, q, v));
195
+ }
196
+
197
+ /* call-seq: gamma(call_put_flag, underlying, strike, time, rate, div_yield,
198
+ * volatility)
199
+ *
200
+ * Returns the gamma options Greek (sensitivity to changes in delta; convexity)
201
+ */
202
+ static VALUE
203
+ rupee_gamma(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
204
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
205
+ {
206
+ const char *call_put_flag;
207
+ double S, K, T, r, q, v;
208
+
209
+ call_put_flag = StringValuePtr(_call_put_flag);
210
+ S = NUM2DBL(_S);
211
+ K = NUM2DBL(_K);
212
+ T = NUM2DBL(_T);
213
+ r = NUM2DBL(_r);
214
+ q = NUM2DBL(_q);
215
+ v = NUM2DBL(_v);
216
+
217
+ return rb_float_new(bs_gamma(call_put_flag, S, K, T, r, q, v));
218
+ }
219
+
220
+ /* call-seq: vanna(call_put_flag, S, K, T, r, q, v)
221
+ *
222
+ * Returns the vanna options Greek (sensitivity of delta to changes in
223
+ * volatility)
224
+ */
225
+ static VALUE
226
+ rupee_vanna(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
227
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
228
+ {
229
+ const char *call_put_flag;
230
+ double d1, d2, S, K, T, r, q, v;
231
+
232
+ call_put_flag = StringValuePtr(_call_put_flag);
233
+ S = NUM2DBL(_S);
234
+ K = NUM2DBL(_K);
235
+ T = NUM2DBL(_T);
236
+ r = NUM2DBL(_r);
237
+ q = NUM2DBL(_q);
238
+ v = NUM2DBL(_v);
239
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
240
+ d2 = d1 - v * sqrt(T);
241
+
242
+ return rb_float_new(-exp(-q * T) * pdf(d1) * d2 / v);
243
+ }
244
+
245
+ /* call-seq: charm(call_put_flag, S, K, T, r, q, v)
246
+ *
247
+ * Returns the charm options Greek (sensitivity of delta to the passage of
248
+ * time)
249
+ */
250
+ static VALUE
251
+ rupee_charm(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
252
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
253
+ {
254
+ const char *call_put_flag;
255
+ double d1, d2, S, K, T, r, q, v;
256
+
257
+ call_put_flag = StringValuePtr(_call_put_flag);
258
+ S = NUM2DBL(_S);
259
+ K = NUM2DBL(_K);
260
+ T = NUM2DBL(_T);
261
+ r = NUM2DBL(_r);
262
+ q = NUM2DBL(_q);
263
+ v = NUM2DBL(_v);
264
+
265
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
266
+ d2 = d1 - v * sqrt(T);
267
+
268
+ if (is_call(call_put_flag))
269
+ return rb_float_new(-q * exp(-q * T) * cnd(d1) + exp(-q * T) * pdf(d1) *
270
+ (2 * (r - q) * T - d2 * v * sqrt(T)) / (2 * T * v * sqrt(T)));
271
+ else
272
+ return rb_float_new(q * exp(-q * T) * cnd(-d1) + exp(-q * T) * pdf(d1) *
273
+ (2 * (r - q) * T - d2 * v * sqrt(T)) / (2 * T * v * sqrt(T)));
274
+ }
275
+
276
+ /* call-seq: rupee_speed(call_put_flag, S, K, T, r, q, v)
277
+ *
278
+ * Returns the speed options Greek (sensitivity of gamma to changes in the
279
+ * underlying's price).
280
+ */
281
+ static VALUE
282
+ rupee_speed(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
283
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
284
+ {
285
+ const char *call_put_flag;
286
+ double d1, S, K, T, r, q, v;
287
+
288
+ call_put_flag = StringValuePtr(_call_put_flag);
289
+ S = NUM2DBL(_S);
290
+ K = NUM2DBL(_K);
291
+ T = NUM2DBL(_T);
292
+ r = NUM2DBL(_r);
293
+ q = NUM2DBL(_q);
294
+ v = NUM2DBL(_v);
295
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
296
+
297
+ return rb_float_new(-exp(-q * T) * pdf(d1) / (S * S * v * sqrt(T)) *
298
+ (d1 / (v * sqrt(T)) + 1));
299
+ }
300
+
301
+ /* call-seq: zomma(call_put_flag, S, K, T, r, q, v)
302
+ *
303
+ * Returns the zomma options Greek (sensitivity of gamma to changes in
304
+ * volatility)
305
+ */
306
+ static VALUE
307
+ rupee_zomma(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
308
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
309
+ {
310
+ const char *call_put_flag;
311
+ double d1, d2, S, K, T, r, q, v;
312
+
313
+ call_put_flag = StringValuePtr(_call_put_flag);
314
+ S = NUM2DBL(_S);
315
+ K = NUM2DBL(_K);
316
+ T = NUM2DBL(_T);
317
+ r = NUM2DBL(_r);
318
+ q = NUM2DBL(_q);
319
+ v = NUM2DBL(_v);
320
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
321
+ d2 = d1 - v * sqrt(T);
322
+
323
+ return rb_float_new(-exp(-q * T) * pdf(d1) * (d1 * d2 - 1) /
324
+ (S * v * v * sqrt(T)));
325
+ }
326
+
327
+ /* call-seq: color(call_put_flag, S, K, T, r, q, v)
328
+ *
329
+ * Returns the color options Greek (sensitivity of gamma to the passage of
330
+ * time)
331
+ */
332
+ static VALUE
333
+ rupee_color(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
334
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
335
+ {
336
+ const char *call_put_flag;
337
+ double d1, d2, S, K, T, r, q, v;
338
+
339
+ call_put_flag = StringValuePtr(_call_put_flag);
340
+ S = NUM2DBL(_S);
341
+ K = NUM2DBL(_K);
342
+ T = NUM2DBL(_T);
343
+ r = NUM2DBL(_r);
344
+ q = NUM2DBL(_q);
345
+ v = NUM2DBL(_v);
346
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
347
+ d2 = d1 - v * sqrt(T);
348
+
349
+ return rb_float_new(-exp(-q * T) * pdf(d1) / (2.0 * S * T * v * sqrt(T)) *
350
+ (2.0 * q * T + 1.0 + (2.0 * (r - q) * T - d2 * v * sqrt(T)) /
351
+ (2.0 * T * v * sqrt(T)) * d1));
352
+ }
353
+
354
+ /* call-seq: dvega_dtime(call_put_flag, S, K, T, r, q, v)
355
+ *
356
+ * Returns the dvega dtime options Greek (sensitivity of vega to the passage of
357
+ * time)
358
+ */
359
+ static VALUE
360
+ rupee_dvega_dtime(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
361
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
362
+ {
363
+ const char *call_put_flag;
364
+ double d1, d2, S, K, T, r, q, v;
365
+
366
+ call_put_flag = StringValuePtr(_call_put_flag);
367
+ S = NUM2DBL(_S);
368
+ K = NUM2DBL(_K);
369
+ T = NUM2DBL(_T);
370
+ r = NUM2DBL(_r);
371
+ q = NUM2DBL(_q);
372
+ v = NUM2DBL(_v);
373
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
374
+ d2 = d1 - v * sqrt(T);
375
+
376
+ return rb_float_new(S * exp(-q * T) * pdf(d1) * sqrt(T) *
377
+ (q + ((r - q) * d1) / (v * sqrt(T)) - (1 + d1 * d2) / (2 * T)));
378
+ }
379
+
380
+ /* call-seq: vomma(call_put_flag, S, K, T, r, q, v)
381
+ *
382
+ * Returns the vomma options Greek (sensitivity of vega to changes in
383
+ * volatility)
384
+ */
385
+ static VALUE
386
+ rupee_vomma(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
387
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
388
+ {
389
+ const char *call_put_flag;
390
+ double d1, d2, S, K, T, r, q, v;
391
+
392
+ call_put_flag = StringValuePtr(_call_put_flag);
393
+ S = NUM2DBL(_S);
394
+ K = NUM2DBL(_K);
395
+ T = NUM2DBL(_T);
396
+ r = NUM2DBL(_r);
397
+ q = NUM2DBL(_q);
398
+ v = NUM2DBL(_v);
399
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
400
+ d2 = d1 - v * sqrt(T);
401
+
402
+ return rb_float_new(S * exp(-q * T) * pdf(d1) * sqrt(T) * d1 * d2 / v);
403
+ }
404
+
405
+ /* call-seq: dual_delta(call_put_flag, S, K, T, r, q, v)
406
+ *
407
+ * Returns the dual delta options Greek (probability of finishing in-the-money)
408
+ */
409
+ static VALUE
410
+ rupee_dual_delta(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
411
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
412
+ {
413
+ const char *call_put_flag;
414
+ double d1, d2, S, K, T, r, q, v;
415
+
416
+ call_put_flag = StringValuePtr(_call_put_flag);
417
+ S = NUM2DBL(_S);
418
+ K = NUM2DBL(_K);
419
+ T = NUM2DBL(_T);
420
+ r = NUM2DBL(_r);
421
+ q = NUM2DBL(_q);
422
+ v = NUM2DBL(_v);
423
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
424
+ d2 = d1 - v * sqrt(T);
425
+
426
+ if (is_call(call_put_flag))
427
+ return rb_float_new(-exp(-q * T) * cnd(d2));
428
+ else
429
+ return rb_float_new(exp(-q * T) * cnd(-d2));
430
+ }
431
+
432
+ /* call-seq: dual_gamma(call_put_flag, S, K, T, r, q, v)
433
+ *
434
+ * Returns the dual gamma options Greek.
435
+ */
436
+ static VALUE
437
+ rupee_dual_gamma(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
438
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
439
+ {
440
+ const char *call_put_flag;
441
+ double d1, d2, S, K, T, r, q, v;
442
+
443
+ call_put_flag = StringValuePtr(_call_put_flag);
444
+ S = NUM2DBL(_S);
445
+ K = NUM2DBL(_K);
446
+ T = NUM2DBL(_T);
447
+ r = NUM2DBL(_r);
448
+ q = NUM2DBL(_q);
449
+ v = NUM2DBL(_v);
450
+ d1 = (log(S / K) + (r - q + v * v / 2) * T) / (v * sqrt(T));
451
+ d2 = d1 - v * sqrt(T);
452
+
453
+ return rb_float_new(exp(-r * T) * pdf(d2) / (K * v * sqrt(T)));
454
+ }
455
+
456
+
457
+ /* call-seq: implied_volatility(call_put_flag, underlying, strike, time, rate,
458
+ * div_yield, price)
459
+ *
460
+ * Returns the Black-Scholes implied volatility using the Newton-Raphson method
461
+ */
462
+ static VALUE
463
+ rupee_impl_vol(self, _call_put_flag, _S, _K, _T, _r, _q, _cm)
464
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _cm;
465
+ {
466
+ static const double epsilon = 0.00000001;
467
+ double vi, ci, vegai, min_diff, S, K, T, r, q, cm;
468
+ const char *call_put_flag;
469
+
470
+ call_put_flag = StringValuePtr(_call_put_flag);
471
+ S = NUM2DBL(_S);
472
+ K = NUM2DBL(_K);
473
+ T = NUM2DBL(_T);
474
+ r = NUM2DBL(_r);
475
+ q = NUM2DBL(_q);
476
+ cm = NUM2DBL(_cm);
477
+
478
+ // Manaster and Koehler seed value
479
+ vi = sqrt(abs(log(S / K) + r * T) * 2 / T);
480
+ ci = bs(call_put_flag, S, K, T, r, q, vi);
481
+ vegai = vega(call_put_flag, S, K, T, r, q, vi);
482
+ min_diff = abs(cm - ci);
483
+
484
+ while (min_diff >= epsilon) {
485
+ vi -= (ci - cm) / vegai;
486
+ ci = bs(call_put_flag, S, K, T, r, q, vi);
487
+ vegai = vega(call_put_flag, S, K, T, r, q, vi);
488
+ min_diff = abs(cm - ci);
489
+ }
490
+
491
+ if (min_diff < epsilon)
492
+ return vi;
493
+ else
494
+ return 0;
495
+ }
496
+
497
+ /* call-seq: black_scholes(call_put_flag, underlying, strike, time, rate,
498
+ * volatility)
31
499
  *
32
500
  * The Black-Scholes European call/put valuation
33
501
  *
@@ -42,37 +510,37 @@ bs(call_put_flag, S, X, T, r, q, v)
42
510
  * * +volatility+ - The implied volatility at expiry
43
511
  */
44
512
  static VALUE
45
- rupee_black_scholes(self, rcall_put_flag, rF, rX, rT, rr, rq, rv)
46
- VALUE self, rcall_put_flag, rF, rX, rT, rr, rq, rv;
513
+ rupee_black_scholes(self, _call_put_flag, _S, _K, _T, _r, _q, _v)
514
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _q, _v;
47
515
  {
48
516
  const char *call_put_flag;
49
- double F, X, T, r, q, v;
517
+ double S, K, T, r, q, v;
50
518
 
51
- call_put_flag = StringValuePtr(rcall_put_flag);
52
- F = NUM2DBL(rF);
53
- X = NUM2DBL(rX);
54
- T = NUM2DBL(rT);
55
- r = NUM2DBL(rr);
56
- q = NUM2DBL(rq);
57
- v = NUM2DBL(rv);
519
+ call_put_flag = StringValuePtr(_call_put_flag);
520
+ S = NUM2DBL(_S);
521
+ K = NUM2DBL(_K);
522
+ T = NUM2DBL(_T);
523
+ r = NUM2DBL(_r);
524
+ q = NUM2DBL(_q);
525
+ v = NUM2DBL(_v);
58
526
 
59
- return rb_float_new(bs(call_put_flag, F, X, T, r, q, v));
527
+ return rb_float_new(bs(call_put_flag, S, K, T, r, q, v));
60
528
  }
61
529
 
62
530
  double
63
- gbs(call_put_flag, S, X, T, r, b, v)
531
+ gbs(call_put_flag, S, K, T, r, b, v)
64
532
  const char *call_put_flag;
65
- double S, X, T, r, b, v;
533
+ double S, K, T, r, b, v;
66
534
  {
67
535
  double d1, d2;
68
536
 
69
- d1 = (log(S / X) + (b + v * v / 2) * T) / (v * sqrt(T));
537
+ d1 = (log(S / K) + (b + v * v / 2) * T) / (v * sqrt(T));
70
538
  d2 = d1 - v * sqrt(T);
71
539
 
72
540
  if (is_call(call_put_flag))
73
- return S * exp((b - r) * T) * cnd(d1) - X * exp(-r * T) * cnd(d2);
541
+ return S * exp((b - r) * T) * cnd(d1) - K * exp(-r * T) * cnd(d2);
74
542
  else
75
- return X * exp(-r * T) * cnd(-d2) - S * exp((b - r) * T) * cnd(-d1);
543
+ return K * exp(-r * T) * cnd(-d2) - S * exp((b - r) * T) * cnd(-d1);
76
544
  }
77
545
 
78
546
  /* call-seq:
@@ -92,37 +560,37 @@ gbs(call_put_flag, S, X, T, r, b, v)
92
560
  * * +volatility+ - The implied volatility at expiry
93
561
  */
94
562
  static VALUE
95
- rupee_generalized_black_scholes(self, rcall_put_flag, rF, rX, rT, rr, rb, rv)
96
- VALUE self, rcall_put_flag, rF, rX, rT, rr, rb, rv;
563
+ rupee_generalized_black_scholes(self, _call_put_flag, _S, _K, _T, _r, _b, _v)
564
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _b, _v;
97
565
  {
98
566
  const char *call_put_flag;
99
- double F, X, T, r, b, v;
567
+ double S, K, T, r, b, v;
100
568
 
101
- call_put_flag = StringValuePtr(rcall_put_flag);
102
- F = NUM2DBL(rF);
103
- X = NUM2DBL(rX);
104
- T = NUM2DBL(rT);
105
- r = NUM2DBL(rr);
106
- b = NUM2DBL(rb);
107
- v = NUM2DBL(rv);
569
+ call_put_flag = StringValuePtr(_call_put_flag);
570
+ S = NUM2DBL(_S);
571
+ K = NUM2DBL(_K);
572
+ T = NUM2DBL(_T);
573
+ r = NUM2DBL(_r);
574
+ b = NUM2DBL(_b);
575
+ v = NUM2DBL(_v);
108
576
 
109
- return rb_float_new(gbs(call_put_flag, F, X, T, r, b, v));
577
+ return rb_float_new(gbs(call_put_flag, S, K, T, r, b, v));
110
578
  }
111
579
 
112
580
  static double
113
- black76(call_put_flag, F, X, T, r, v)
581
+ black76(call_put_flag, S, K, T, r, v)
114
582
  const char *call_put_flag;
115
- double F, X, T, r, v;
583
+ double S, K, T, r, v;
116
584
  {
117
585
  double d1, d2;
118
586
 
119
- d1 = (log(F / X) + (v * v / 2.0) * T) / (v * sqrt(T));
587
+ d1 = (log(S / K) + (v * v / 2.0) * T) / (v * sqrt(T));
120
588
  d2 = d1 - v * sqrt(T);
121
589
 
122
590
  if (is_call(call_put_flag))
123
- return exp(-r * T) * (F * cnd(d1) - X * cnd(d2));
591
+ return exp(-r * T) * (S * cnd(d1) - K * cnd(d2));
124
592
  else
125
- return exp(-r * T) * (X * cnd(-d2) - F * cnd(-d1));
593
+ return exp(-r * T) * (K * cnd(-d2) - S * cnd(-d1));
126
594
  }
127
595
 
128
596
  /* call-seq:
@@ -141,20 +609,20 @@ black76(call_put_flag, F, X, T, r, v)
141
609
  * * +volatility+ - The implied volatility at expiry
142
610
  */
143
611
  static VALUE
144
- rupee_black76(self, rcall_put_flag, rF, rX, rT, rr, rv)
145
- VALUE self, rcall_put_flag, rF, rX, rT, rr, rv;
612
+ rupee_black76(self, _call_put_flag, _S, _K, _T, _r, _v)
613
+ VALUE self, _call_put_flag, _S, _K, _T, _r, _v;
146
614
  {
147
615
  const char *call_put_flag;
148
- double F, X, T, r, v;
616
+ double S, K, T, r, v;
149
617
 
150
- call_put_flag = StringValuePtr(rcall_put_flag);
151
- F = NUM2DBL(rF);
152
- X = NUM2DBL(rX);
153
- T = NUM2DBL(rT);
154
- r = NUM2DBL(rr);
155
- v = NUM2DBL(rv);
618
+ call_put_flag = StringValuePtr(_call_put_flag);
619
+ S = NUM2DBL(_S);
620
+ K = NUM2DBL(_K);
621
+ T = NUM2DBL(_T);
622
+ r = NUM2DBL(_r);
623
+ v = NUM2DBL(_v);
156
624
 
157
- return rb_float_new(black76(call_put_flag, F, X, T, r, v));
625
+ return rb_float_new(black76(call_put_flag, S, K, T, r, v));
158
626
  }
159
627
 
160
628
  void
@@ -173,7 +641,35 @@ init_option()
173
641
  rb_define_singleton_method(klass, "black76", rupee_black76, 6);
174
642
  rb_define_singleton_method(klass, "black_scholes", rupee_black_scholes, 7);
175
643
  rb_define_alias(singleton, "bs", "black_scholes");
644
+ rb_define_singleton_method(klass, "charm", rupee_charm, 7);
645
+ rb_define_singleton_method(klass, "color", rupee_color, 7);
646
+ rb_define_singleton_method(klass, "delta", rupee_delta, 7);
647
+ rb_define_singleton_method(klass, "dual_delta", rupee_dual_delta, 7);
648
+ rb_define_singleton_method(klass, "dual_gamma", rupee_dual_gamma, 7);
649
+ rb_define_singleton_method(klass, "dvega_dtime", rupee_dvega_dtime, 7);
650
+ rb_define_singleton_method(klass, "gamma", rupee_gamma, 7);
176
651
  rb_define_singleton_method(klass, "generalized_black_scholes",
177
652
  rupee_generalized_black_scholes, 7);
178
653
  rb_define_alias(singleton, "gbs", "generalized_black_scholes");
654
+ rb_define_singleton_method(klass, "implied_volatility", rupee_impl_vol, 7);
655
+ rb_define_singleton_method(klass, "rho", rupee_rho, 7);
656
+ rb_define_singleton_method(klass, "speed", rupee_speed, 7);
657
+ rb_define_singleton_method(klass, "theta", rupee_theta, 7);
658
+ rb_define_singleton_method(klass, "vanna", rupee_vanna, 7);
659
+ rb_define_singleton_method(klass, "vega", rupee_vega, 7);
660
+ rb_define_singleton_method(klass, "vomma", rupee_vomma, 7);
661
+ rb_define_singleton_method(klass, "zomma", rupee_zomma, 7);
179
662
  }
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+
674
+
675
+