trading_formulas 0.0.1
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +34 -0
- data/Rakefile +10 -0
- data/lib/trading_formulas/bermudan_options.rb +124 -0
- data/lib/trading_formulas/binomial_options.rb +753 -0
- data/lib/trading_formulas/black_scholes.rb +369 -0
- data/lib/trading_formulas/version.rb +3 -0
- data/lib/trading_formulas.rb +8 -0
- data/test/test_bermudan_options.rb +65 -0
- data/test/test_binomial_options.rb +393 -0
- data/test/test_black_scholes.rb +329 -0
- data/trading_formulas.gemspec +18 -0
- metadata +62 -0
@@ -0,0 +1,393 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'trading_formulas'
|
3
|
+
|
4
|
+
class BinomialOptionsTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_call
|
7
|
+
s = 100
|
8
|
+
k = 100
|
9
|
+
r = 0.10
|
10
|
+
sigma = 0.25
|
11
|
+
time = 1.0
|
12
|
+
steps = 100
|
13
|
+
test_val = TradingFormulas::BinomialOptions.call(s, k, r, sigma, time, steps)
|
14
|
+
assert_equal(14.9505, test_val.round(4))
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Negative test case
|
19
|
+
def test_invalid_call
|
20
|
+
s = 100
|
21
|
+
k = 100
|
22
|
+
r = 0.10
|
23
|
+
sigma = 0.25
|
24
|
+
time = 1.0
|
25
|
+
steps = 100
|
26
|
+
test_val = TradingFormulas::BinomialOptions.call(s, k, r, sigma, time, steps)
|
27
|
+
assert_not_equal(14.9509, test_val.round(4))
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_put
|
31
|
+
s = 100
|
32
|
+
k = 100
|
33
|
+
r = 0.10
|
34
|
+
sigma = 0.25
|
35
|
+
time = 1.0
|
36
|
+
steps = 100
|
37
|
+
test_val = TradingFormulas::BinomialOptions.put(s, k, r, sigma, time, steps)
|
38
|
+
assert_equal(6.54691, test_val.round(5))
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Negative test case
|
43
|
+
def test_invalid_put
|
44
|
+
s = 100
|
45
|
+
k = 100
|
46
|
+
r = 0.10
|
47
|
+
sigma = 0.25
|
48
|
+
time = 1.0
|
49
|
+
steps = 100
|
50
|
+
test_val = TradingFormulas::BinomialOptions.put(s, k, r, sigma, time, steps)
|
51
|
+
assert_not_equal(6.54699, test_val.round(5))
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_delta_call
|
55
|
+
s = 100
|
56
|
+
k = 100
|
57
|
+
r = 0.10
|
58
|
+
sigma = 0.25
|
59
|
+
time = 1.0
|
60
|
+
steps = 100
|
61
|
+
test_val = TradingFormulas::BinomialOptions.delta_call(s, k, r, sigma,
|
62
|
+
time, steps)
|
63
|
+
assert_equal(0.699792, test_val.round(6))
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Negative test case
|
68
|
+
def test_invalid_delta_call
|
69
|
+
s = 100
|
70
|
+
k = 100
|
71
|
+
r = 0.10
|
72
|
+
sigma = 0.25
|
73
|
+
time = 1.0
|
74
|
+
steps = 100
|
75
|
+
test_val = TradingFormulas::BinomialOptions.delta_call(s, k, r, sigma,
|
76
|
+
time, steps)
|
77
|
+
assert_not_equal(0.699799, test_val.round(6))
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_delta_put
|
81
|
+
s = 100
|
82
|
+
k = 100
|
83
|
+
r = 0.10
|
84
|
+
sigma = 0.25
|
85
|
+
time = 1.0
|
86
|
+
steps = 100
|
87
|
+
test_val = TradingFormulas::BinomialOptions.delta_put(s, k, r, sigma,
|
88
|
+
time, steps)
|
89
|
+
assert_equal(-0.387636, test_val.round(6))
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Negative test case
|
94
|
+
def test_invalid_delta_put
|
95
|
+
s = 100
|
96
|
+
k = 100
|
97
|
+
r = 0.10
|
98
|
+
sigma = 0.25
|
99
|
+
time = 1.0
|
100
|
+
steps = 100
|
101
|
+
test_val = TradingFormulas::BinomialOptions.delta_put(s, k, r, sigma,
|
102
|
+
time, steps)
|
103
|
+
assert_not_equal(-0.387639, test_val.round(6))
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_partials_call
|
107
|
+
s = 100
|
108
|
+
k = 100
|
109
|
+
r = 0.10
|
110
|
+
sigma = 0.25
|
111
|
+
time = 1.0
|
112
|
+
steps = 100
|
113
|
+
delta, gamma, theta, vega, rho = TradingFormulas::BinomialOptions.partials_call(s, k, r, sigma, time, steps)
|
114
|
+
assert_equal(0.699792, delta.round(6))
|
115
|
+
assert_equal(0.0140407, gamma.round(7))
|
116
|
+
assert_equal(-9.89067, theta.round(5))
|
117
|
+
assert_equal(34.8536, vega.round(4))
|
118
|
+
assert_equal(56.9652, rho.round(4))
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# Negative test case
|
123
|
+
def test_invalid_partials_call
|
124
|
+
s = 100
|
125
|
+
k = 100
|
126
|
+
r = 0.10
|
127
|
+
sigma = 0.25
|
128
|
+
time = 1.0
|
129
|
+
steps = 100
|
130
|
+
delta, gamma, theta, vega, rho = TradingFormulas::BinomialOptions.partials_call(s, k, r, sigma, time, steps)
|
131
|
+
assert_not_equal(0.699799, delta.round(6))
|
132
|
+
assert_not_equal(0.0140409, gamma.round(7))
|
133
|
+
assert_not_equal(-9.89069, theta.round(5))
|
134
|
+
assert_not_equal(34.8539, vega.round(4))
|
135
|
+
assert_not_equal(56.9659, rho.round(4))
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_partials_put
|
139
|
+
s = 100
|
140
|
+
k = 100
|
141
|
+
r = 0.10
|
142
|
+
sigma = 0.25
|
143
|
+
time = 1.0
|
144
|
+
steps = 100
|
145
|
+
delta, gamma, theta, vega, rho = TradingFormulas::BinomialOptions.partials_put(s, k, r, sigma, time, steps)
|
146
|
+
assert_equal(-0.387636, delta.round(6))
|
147
|
+
assert_equal(0.0209086, gamma.round(7))
|
148
|
+
assert_equal(-1.99027, theta.round(5))
|
149
|
+
assert_equal(35.3943, vega.round(4))
|
150
|
+
assert_equal(-21.5433, rho.round(4))
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Negative test case
|
155
|
+
def test_invalid_partials_put
|
156
|
+
s = 100
|
157
|
+
k = 100
|
158
|
+
r = 0.10
|
159
|
+
sigma = 0.25
|
160
|
+
time = 1.0
|
161
|
+
steps = 100
|
162
|
+
delta, gamma, theta, vega, rho = TradingFormulas::BinomialOptions.partials_put(s, k, r, sigma, time, steps)
|
163
|
+
assert_not_equal(-0.387639, delta.round(6))
|
164
|
+
assert_not_equal(0.0209089, gamma.round(7))
|
165
|
+
assert_not_equal(-1.99029, theta.round(5))
|
166
|
+
assert_not_equal(35.3949, vega.round(4))
|
167
|
+
assert_not_equal(-21.5439, rho.round(4))
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_discrete_dividends_call
|
171
|
+
s = 100
|
172
|
+
k = 100
|
173
|
+
r = 0.10
|
174
|
+
sigma = 0.25
|
175
|
+
time = 1.0
|
176
|
+
steps = 100
|
177
|
+
dividend_times = [0.25, 0.75]
|
178
|
+
dividend_amounts = [2.5, 2.5]
|
179
|
+
test_val = TradingFormulas::BinomialOptions.discrete_dividends_call(s, k,
|
180
|
+
r, sigma, time, steps, dividend_times, dividend_amounts)
|
181
|
+
assert_equal(12.0233, test_val.round(4))
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# Negative test case
|
186
|
+
def test_invalid_discrete_dividends_call
|
187
|
+
s = 100
|
188
|
+
k = 100
|
189
|
+
r = 0.10
|
190
|
+
sigma = 0.25
|
191
|
+
time = 1.0
|
192
|
+
steps = 100
|
193
|
+
dividend_times = [0.25, 0.75]
|
194
|
+
dividend_amounts = [2.5, 2.5]
|
195
|
+
test_val = TradingFormulas::BinomialOptions.discrete_dividends_call(s, k,
|
196
|
+
r, sigma, time, steps, dividend_times, dividend_amounts)
|
197
|
+
assert_not_equal(12.0239, test_val.round(4))
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_discrete_dividends_put
|
201
|
+
s = 100
|
202
|
+
k = 100
|
203
|
+
r = 0.10
|
204
|
+
sigma = 0.25
|
205
|
+
time = 1.0
|
206
|
+
steps = 100
|
207
|
+
dividend_times = [0.25, 0.75]
|
208
|
+
dividend_amounts = [2.5, 2.5]
|
209
|
+
test_val = TradingFormulas::BinomialOptions.discrete_dividends_put(s, k,
|
210
|
+
r, sigma, time, steps, dividend_times, dividend_amounts)
|
211
|
+
assert_equal(8.11801, test_val.round(5))
|
212
|
+
end
|
213
|
+
|
214
|
+
##
|
215
|
+
# Negative test case
|
216
|
+
def test_invalid_discrete_dividends_put
|
217
|
+
s = 100
|
218
|
+
k = 100
|
219
|
+
r = 0.10
|
220
|
+
sigma = 0.25
|
221
|
+
time = 1.0
|
222
|
+
steps = 100
|
223
|
+
dividend_times = [0.25, 0.75]
|
224
|
+
dividend_amounts = [2.5, 2.5]
|
225
|
+
test_val = TradingFormulas::BinomialOptions.discrete_dividends_put(s, k,
|
226
|
+
r, sigma, time, steps, dividend_times, dividend_amounts)
|
227
|
+
assert_not_equal(8.11809, test_val.round(5))
|
228
|
+
end
|
229
|
+
|
230
|
+
def test_proportional_dividends_call
|
231
|
+
s = 100
|
232
|
+
k = 100
|
233
|
+
r = 0.10
|
234
|
+
sigma = 0.25
|
235
|
+
time = 1.0
|
236
|
+
steps = 100
|
237
|
+
dividend_times = [0.25, 0.75]
|
238
|
+
dividend_yields = [0.025, 0.025]
|
239
|
+
test_val = TradingFormulas::BinomialOptions.proportional_dividends_call(s,
|
240
|
+
k, r, sigma, time, steps, dividend_times, dividend_yields)
|
241
|
+
assert_equal(11.8604, test_val.round(4))
|
242
|
+
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# Negative test case
|
246
|
+
def test_invalid_proportional_dividends_call
|
247
|
+
s = 100
|
248
|
+
k = 100
|
249
|
+
r = 0.10
|
250
|
+
sigma = 0.25
|
251
|
+
time = 1.0
|
252
|
+
steps = 100
|
253
|
+
dividend_times = [0.25, 0.75]
|
254
|
+
dividend_yields = [0.025, 0.025]
|
255
|
+
test_val = TradingFormulas::BinomialOptions.proportional_dividends_call(s,
|
256
|
+
k, r, sigma, time, steps, dividend_times, dividend_yields)
|
257
|
+
assert_not_equal(11.8609, test_val.round(4))
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_proportional_dividends_put
|
261
|
+
s = 100
|
262
|
+
k = 100
|
263
|
+
r = 0.10
|
264
|
+
sigma = 0.25
|
265
|
+
time = 1.0
|
266
|
+
steps = 100
|
267
|
+
dividend_times = [0.25, 0.75]
|
268
|
+
dividend_yields = [0.025, 0.025]
|
269
|
+
test_val = TradingFormulas::BinomialOptions.proportional_dividends_put(s,
|
270
|
+
k, r, sigma, time, steps, dividend_times, dividend_yields)
|
271
|
+
assert_equal(7.99971, test_val.round(5))
|
272
|
+
end
|
273
|
+
|
274
|
+
##
|
275
|
+
# Negative test case
|
276
|
+
def test_invalid_proportional_dividends_put
|
277
|
+
s = 100
|
278
|
+
k = 100
|
279
|
+
r = 0.10
|
280
|
+
sigma = 0.25
|
281
|
+
time = 1.0
|
282
|
+
steps = 100
|
283
|
+
dividend_times = [0.25, 0.75]
|
284
|
+
dividend_yields = [0.025, 0.025]
|
285
|
+
test_val = TradingFormulas::BinomialOptions.proportional_dividends_put(s,
|
286
|
+
k, r, sigma, time, steps, dividend_times, dividend_yields)
|
287
|
+
assert_not_equal(7.99979, test_val.round(5))
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_continuous_payout_call
|
291
|
+
s = 100
|
292
|
+
k = 100
|
293
|
+
r = 0.10
|
294
|
+
sigma = 0.25
|
295
|
+
y = 0.02
|
296
|
+
time = 1.0
|
297
|
+
steps = 100
|
298
|
+
test_val = TradingFormulas::BinomialOptions.continuous_payout_call(s, k, r, y,
|
299
|
+
sigma, time, steps)
|
300
|
+
assert_equal(13.5926, test_val.round(4))
|
301
|
+
end
|
302
|
+
|
303
|
+
##
|
304
|
+
# Negative test case
|
305
|
+
def test_invalid_continuous_payout_call
|
306
|
+
s = 100
|
307
|
+
k = 100
|
308
|
+
r = 0.10
|
309
|
+
sigma = 0.25
|
310
|
+
y = 0.02
|
311
|
+
time = 1.0
|
312
|
+
steps = 100
|
313
|
+
test_val = TradingFormulas::BinomialOptions.continuous_payout_call(s, k, r, y,
|
314
|
+
sigma, time, steps)
|
315
|
+
assert_not_equal(13.5929, test_val.round(4))
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_continuous_payout_put
|
319
|
+
s = 100
|
320
|
+
k = 100
|
321
|
+
r = 0.10
|
322
|
+
sigma = 0.25
|
323
|
+
y = 0.02
|
324
|
+
time = 1.0
|
325
|
+
steps = 100
|
326
|
+
test_val = TradingFormulas::BinomialOptions.continuous_payout_put(s, k, r, y,
|
327
|
+
sigma, time, steps)
|
328
|
+
assert_equal(6.99407, test_val.round(5))
|
329
|
+
end
|
330
|
+
|
331
|
+
##
|
332
|
+
# Negative test case
|
333
|
+
def test_invalid_continuous_payout_put
|
334
|
+
s = 100
|
335
|
+
k = 100
|
336
|
+
r = 0.10
|
337
|
+
sigma = 0.25
|
338
|
+
y = 0.02
|
339
|
+
time = 1.0
|
340
|
+
steps = 100
|
341
|
+
test_val = TradingFormulas::BinomialOptions.continuous_payout_put(s, k, r, y,
|
342
|
+
sigma, time, steps)
|
343
|
+
assert_not_equal(6.99409, test_val.round(5))
|
344
|
+
end
|
345
|
+
|
346
|
+
def test_european_call
|
347
|
+
s = 100
|
348
|
+
k = 100
|
349
|
+
r = 0.10
|
350
|
+
sigma = 0.25
|
351
|
+
time = 1.0
|
352
|
+
steps = 100
|
353
|
+
test_val = TradingFormulas::BinomialOptions.european_call(s, k, r, sigma, time, steps)
|
354
|
+
assert_equal(14.9505, test_val.round(4))
|
355
|
+
end
|
356
|
+
|
357
|
+
##
|
358
|
+
# Negative test case
|
359
|
+
def test_invalid_european_call
|
360
|
+
s = 100
|
361
|
+
k = 100
|
362
|
+
r = 0.10
|
363
|
+
sigma = 0.25
|
364
|
+
time = 1.0
|
365
|
+
steps = 100
|
366
|
+
test_val = TradingFormulas::BinomialOptions.european_call(s, k, r, sigma, time, steps)
|
367
|
+
assert_not_equal(14.9509, test_val.round(4))
|
368
|
+
end
|
369
|
+
|
370
|
+
def test_european_put
|
371
|
+
s = 100
|
372
|
+
k = 100
|
373
|
+
r = 0.10
|
374
|
+
sigma = 0.25
|
375
|
+
time = 1.0
|
376
|
+
steps = 100
|
377
|
+
test_val = TradingFormulas::BinomialOptions.european_put(s, k, r, sigma, time, steps)
|
378
|
+
assert_equal(5.43425, test_val.round(5))
|
379
|
+
end
|
380
|
+
|
381
|
+
##
|
382
|
+
# Negative test case
|
383
|
+
def test_invalid_european_put
|
384
|
+
s = 100
|
385
|
+
k = 100
|
386
|
+
r = 0.10
|
387
|
+
sigma = 0.25
|
388
|
+
time = 1.0
|
389
|
+
steps = 100
|
390
|
+
test_val = TradingFormulas::BinomialOptions.european_put(s, k, r, sigma, time, steps)
|
391
|
+
assert_not_equal(5.43429, test_val.round(5))
|
392
|
+
end
|
393
|
+
end
|
@@ -0,0 +1,329 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'trading_formulas'
|
3
|
+
|
4
|
+
class BlackScholesTest < Test::Unit::TestCase
|
5
|
+
def test_n
|
6
|
+
test_val = TradingFormulas::BlackScholes.n(1.23)
|
7
|
+
assert_equal(0.187235, test_val.round(6))
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Negative test case
|
12
|
+
def test_invalid_n
|
13
|
+
test_val = TradingFormulas::BlackScholes.n(1.23)
|
14
|
+
assert_not_equal(0.187239, test_val.round(6))
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_N
|
18
|
+
test_val = TradingFormulas::BlackScholes.N(1.23)
|
19
|
+
assert_equal(0.890651, test_val.round(6))
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Negative test case
|
24
|
+
def test_invalid_N
|
25
|
+
test_val = TradingFormulas::BlackScholes.N(1.23)
|
26
|
+
assert_not_equal(0.890659, test_val.round(6))
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_call
|
30
|
+
s = 50
|
31
|
+
k = 50
|
32
|
+
r = 0.10
|
33
|
+
sigma = 0.30
|
34
|
+
time = 0.50
|
35
|
+
test_val = TradingFormulas::BlackScholes.call(s, k, r, sigma, time)
|
36
|
+
assert_equal(5.45325, test_val.round(5))
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Negative test case
|
41
|
+
def test_invalid_call
|
42
|
+
s = 50
|
43
|
+
k = 50
|
44
|
+
r = 0.10
|
45
|
+
sigma = 0.30
|
46
|
+
time = 0.50
|
47
|
+
test_val = TradingFormulas::BlackScholes.call(s, k, r, sigma, time)
|
48
|
+
assert_not_equal(5.45329, test_val.round(5))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_put
|
52
|
+
s = 50
|
53
|
+
k = 50
|
54
|
+
r = 0.10
|
55
|
+
sigma = 0.30
|
56
|
+
time = 0.50
|
57
|
+
test_val = TradingFormulas::BlackScholes.put(s, k, r, sigma, time)
|
58
|
+
assert_equal(3.01472, test_val.round(5))
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Negative test case
|
63
|
+
def test_invalid_put
|
64
|
+
s = 50
|
65
|
+
k = 50
|
66
|
+
r = 0.10
|
67
|
+
sigma = 0.30
|
68
|
+
time = 0.50
|
69
|
+
test_val = TradingFormulas::BlackScholes.put(s, k, r, sigma, time)
|
70
|
+
assert_not_equal(3.01479, test_val.round(5))
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_delta_call
|
74
|
+
s = 50
|
75
|
+
k = 50
|
76
|
+
r = 0.10
|
77
|
+
sigma = 0.30
|
78
|
+
time = 0.50
|
79
|
+
test_val = TradingFormulas::BlackScholes.delta_call(s, k, r, sigma, time)
|
80
|
+
assert_equal(0.633737, test_val.round(6))
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Negative test case
|
85
|
+
def test_invalid_delta_call
|
86
|
+
s = 50
|
87
|
+
k = 50
|
88
|
+
r = 0.10
|
89
|
+
sigma = 0.30
|
90
|
+
time = 0.50
|
91
|
+
test_val = TradingFormulas::BlackScholes.delta_call(s, k, r, sigma, time)
|
92
|
+
assert_not_equal(0.633739, test_val.round(6))
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_delta_put
|
96
|
+
s = 50
|
97
|
+
k = 50
|
98
|
+
r = 0.10
|
99
|
+
sigma = 0.30
|
100
|
+
time = 0.50
|
101
|
+
test_val = TradingFormulas::BlackScholes.delta_put(s, k, r, sigma, time)
|
102
|
+
assert_equal(-0.366263, test_val.round(6))
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Negative test case
|
107
|
+
def test_invalid_delta_put
|
108
|
+
s = 50
|
109
|
+
k = 50
|
110
|
+
r = 0.10
|
111
|
+
sigma = 0.30
|
112
|
+
time = 0.50
|
113
|
+
test_val = TradingFormulas::BlackScholes.delta_put(s, k, r, sigma, time)
|
114
|
+
assert_not_equal(-0.366269, test_val.round(6))
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_implied_volatility_call_bisections
|
118
|
+
s = 50
|
119
|
+
k = 50
|
120
|
+
r = 0.10
|
121
|
+
time = 0.50
|
122
|
+
option_price = 2.5
|
123
|
+
test_val = TradingFormulas::BlackScholes.implied_volatility_call_bisections(
|
124
|
+
s, k, r, time, option_price)
|
125
|
+
assert_equal(0.0500419, test_val.round(7))
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Negative test case
|
130
|
+
def test_invalid_implied_volatility_call_bisections
|
131
|
+
s = 50
|
132
|
+
k = 50
|
133
|
+
r = 0.10
|
134
|
+
time = 0.50
|
135
|
+
option_price = 2.5
|
136
|
+
test_val = TradingFormulas::BlackScholes.implied_volatility_call_bisections(
|
137
|
+
s, k, r, time, option_price)
|
138
|
+
assert_not_equal(0.0500411, test_val.round(7))
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_implied_volatility_call_newton
|
142
|
+
s = 50
|
143
|
+
k = 50
|
144
|
+
r = 0.10
|
145
|
+
time = 0.50
|
146
|
+
option_price = 2.5
|
147
|
+
test_val = TradingFormulas::BlackScholes.implied_volatility_call_newton(s,
|
148
|
+
k, r, time, option_price)
|
149
|
+
assert_equal(0.0500427, test_val.round(7))
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
# Negative test case
|
154
|
+
def test_invalid_implied_volatility_call_newton
|
155
|
+
s = 50
|
156
|
+
k = 50
|
157
|
+
r = 0.10
|
158
|
+
time = 0.50
|
159
|
+
option_price = 2.5
|
160
|
+
test_val = TradingFormulas::BlackScholes.implied_volatility_call_newton(s,
|
161
|
+
k, r, time, option_price)
|
162
|
+
assert_not_equal(0.0500429, test_val.round(7))
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_partials_call
|
166
|
+
s = 50
|
167
|
+
k = 50
|
168
|
+
r = 0.10
|
169
|
+
sigma = 0.30
|
170
|
+
time = 0.50
|
171
|
+
delta, gamma, theta, vega, rho = TradingFormulas::BlackScholes.partials_call(s, k, r, sigma, time)
|
172
|
+
assert_equal(0.633737, delta.round(6))
|
173
|
+
assert_equal(0.0354789, gamma.round(7))
|
174
|
+
assert_equal(-6.61473, theta.round(5))
|
175
|
+
assert_equal(13.3046, vega.round(4))
|
176
|
+
assert_equal(13.1168, rho.round(4))
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# Negative test case
|
181
|
+
def test_invalid_partials_call
|
182
|
+
s = 50
|
183
|
+
k = 50
|
184
|
+
r = 0.10
|
185
|
+
sigma = 0.30
|
186
|
+
time = 0.50
|
187
|
+
delta, gamma, theta, vega, rho = TradingFormulas::BlackScholes.partials_call(s, k, r, sigma, time)
|
188
|
+
assert_not_equal(0.633739, delta.round(6))
|
189
|
+
assert_not_equal(0.0354781, gamma.round(7))
|
190
|
+
assert_not_equal(-6.61479, theta.round(5))
|
191
|
+
assert_not_equal(13.3049, vega.round(4))
|
192
|
+
assert_not_equal(13.1169, rho.round(4))
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_partials_put
|
196
|
+
s = 50
|
197
|
+
k = 50
|
198
|
+
r = 0.10
|
199
|
+
sigma = 0.30
|
200
|
+
time = 0.50
|
201
|
+
delta, gamma, theta, vega, rho = TradingFormulas::BlackScholes.partials_put(s, k, r, sigma, time)
|
202
|
+
assert_equal(-0.366263, delta.round(6))
|
203
|
+
assert_equal(0.0354789, gamma.round(7))
|
204
|
+
assert_equal(-1.85859, theta.round(5))
|
205
|
+
assert_equal(13.3046, vega.round(4))
|
206
|
+
assert_equal(-10.6639, rho.round(4))
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Negative test case
|
211
|
+
def test_invalid_partials_put
|
212
|
+
s = 50
|
213
|
+
k = 50
|
214
|
+
r = 0.10
|
215
|
+
sigma = 0.30
|
216
|
+
time = 0.50
|
217
|
+
delta, gamma, theta, vega, rho = TradingFormulas::BlackScholes.partials_put(s, k, r, sigma, time)
|
218
|
+
assert_not_equal(-0.366269, delta.round(6))
|
219
|
+
assert_not_equal(0.0354781, gamma.round(7))
|
220
|
+
assert_not_equal(-1.85851, theta.round(5))
|
221
|
+
assert_not_equal(13.3049, vega.round(4))
|
222
|
+
assert_not_equal(-10.6631, rho.round(4))
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_european_call_payout
|
226
|
+
s = 100
|
227
|
+
k = 100
|
228
|
+
r = 0.1
|
229
|
+
q = 0.05
|
230
|
+
sigma = 0.25
|
231
|
+
time = 1.0
|
232
|
+
test_val = TradingFormulas::BlackScholes.european_call_payout(s, k, r, q, sigma, time)
|
233
|
+
assert_equal(11.7344, test_val.round(4))
|
234
|
+
end
|
235
|
+
|
236
|
+
##
|
237
|
+
# Negative test case
|
238
|
+
def test_invalid_european_call_payout
|
239
|
+
s = 100
|
240
|
+
k = 100
|
241
|
+
r = 0.1
|
242
|
+
q = 0.05
|
243
|
+
sigma = 0.25
|
244
|
+
time = 1.0
|
245
|
+
test_val = TradingFormulas::BlackScholes.european_call_payout(s, k, r, q, sigma, time)
|
246
|
+
assert_not_equal(11.7349, test_val.round(4))
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_european_put_payout
|
250
|
+
s = 100
|
251
|
+
k = 100
|
252
|
+
r = 0.1
|
253
|
+
q = 0.05
|
254
|
+
sigma = 0.25
|
255
|
+
time = 1.0
|
256
|
+
test_val = TradingFormulas::BlackScholes.european_put_payout(s, k, r, q, sigma, time)
|
257
|
+
assert_equal(7.09515, test_val.round(5))
|
258
|
+
end
|
259
|
+
|
260
|
+
##
|
261
|
+
# Negative test case
|
262
|
+
def test_invalid_european_put_payout
|
263
|
+
s = 100
|
264
|
+
k = 100
|
265
|
+
r = 0.1
|
266
|
+
q = 0.05
|
267
|
+
sigma = 0.25
|
268
|
+
time = 1.0
|
269
|
+
test_val = TradingFormulas::BlackScholes.european_put_payout(s, k, r, q, sigma, time)
|
270
|
+
assert_not_equal(7.09519, test_val.round(5))
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_european_call_dividends
|
274
|
+
s = 100
|
275
|
+
k = 100
|
276
|
+
r = 0.1
|
277
|
+
sigma = 0.25
|
278
|
+
time = 1.0
|
279
|
+
dividend_times = [0.25, 0.75]
|
280
|
+
dividend_amounts = [2.5, 2.5]
|
281
|
+
test_val = TradingFormulas::BlackScholes.european_call_dividends(s, k, r, sigma,
|
282
|
+
time, dividend_times, dividend_amounts )
|
283
|
+
assert_equal(11.8094, test_val.round(4))
|
284
|
+
end
|
285
|
+
|
286
|
+
##
|
287
|
+
# Negative test case
|
288
|
+
def test_inactive_european_call_dividends
|
289
|
+
s = 100
|
290
|
+
k = 100
|
291
|
+
r = 0.1
|
292
|
+
sigma = 0.25
|
293
|
+
time = 1.0
|
294
|
+
dividend_times = [0.25, 0.75]
|
295
|
+
dividend_amounts = [2.5, 2.5]
|
296
|
+
test_val = TradingFormulas::BlackScholes.european_call_dividends(s, k, r, sigma,
|
297
|
+
time, dividend_times, dividend_amounts )
|
298
|
+
assert_not_equal(11.8099, test_val.round(4))
|
299
|
+
end
|
300
|
+
|
301
|
+
def test_european_put_dividends
|
302
|
+
s = 100
|
303
|
+
k = 100
|
304
|
+
r = 0.1
|
305
|
+
sigma = 0.25
|
306
|
+
time = 1.0
|
307
|
+
dividend_times = [0.25, 0.75]
|
308
|
+
dividend_amounts = [2.5, 2.5]
|
309
|
+
test_val = TradingFormulas::BlackScholes.european_put_dividends(s, k, r, sigma,
|
310
|
+
time, dividend_times, dividend_amounts )
|
311
|
+
assert_equal(7.05077, test_val.round(5))
|
312
|
+
end
|
313
|
+
|
314
|
+
##
|
315
|
+
# Negative test case
|
316
|
+
def test_invalid_european_put_dividends
|
317
|
+
s = 100
|
318
|
+
k = 100
|
319
|
+
r = 0.1
|
320
|
+
sigma = 0.25
|
321
|
+
time = 1.0
|
322
|
+
dividend_times = [0.25, 0.75]
|
323
|
+
dividend_amounts = [2.5, 2.5]
|
324
|
+
test_val = TradingFormulas::BlackScholes.european_put_dividends(s, k, r, sigma,
|
325
|
+
time, dividend_times, dividend_amounts )
|
326
|
+
assert_not_equal(7.05079, test_val.round(5))
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|