greeks 1.2 → 1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/greeks-1.1.gem +0 -0
- data/greeks.gemspec +1 -1
- data/lib/greeks/calculations/time_values.rb +12 -14
- data/lib/greeks.rb +24 -6
- data/spec/greeks/22days.calls.csv +1 -0
- data/spec/greeks/22days.puts.csv +1 -0
- data/spec/greeks/50days.calls.csv +1 -0
- data/spec/greeks/50days.puts.csv +1 -0
- data/spec/greeks/calculations/iv_option_price_spec.rb +0 -1
- data/spec/greeks/calculations/iv_spec.rb +0 -1
- data/spec/greeks/calculations/iv_vega_spec.rb +0 -1
- data/spec/greeks/calculations/time_values_spec.rb +0 -1
- data/spec/greeks/greeks_spec.rb +30 -104
- data/spec/helpers/greek_calculation_shorthand_helpers.rb +54 -0
- data/spec/spec_helper.rb +14 -54
- data/spec/support/calculate_greeks_hash.rb +39 -0
- metadata +15 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ed185ec81ab234f6465a7a78a435ddfcd7055d6
|
4
|
+
data.tar.gz: 624f32c01e177d5cb626f081f5ed7068bc1d31bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f0accecffdf8324a71297cc584b1d6fb53100c9a4f1cf9b48a52b0bf1c657e6cdce8d5a4ad12d82ca0ca0cd6af601ce833f33bf2b9c79a1db39a08a2e48e509
|
7
|
+
data.tar.gz: edafcc4521dbb21879e0ed7a575f61fb5616b818f03620d7054d47d5181383f09dbcfcb4d234c1d9347c034defa0dd84298f80350026f53328df534a3e5db32b
|
data/Gemfile.lock
CHANGED
data/greeks-1.1.gem
ADDED
Binary file
|
data/greeks.gemspec
CHANGED
@@ -2,7 +2,7 @@ module Math
|
|
2
2
|
module GreekCalculations
|
3
3
|
|
4
4
|
def nil_or_gte0(value)
|
5
|
-
value.nil? || value.to_f < 0 ? nil : value
|
5
|
+
value.nil? || value.to_f < 0.0 ? nil : value
|
6
6
|
end
|
7
7
|
|
8
8
|
|
@@ -15,14 +15,16 @@ module Math
|
|
15
15
|
def premium_value(opts)
|
16
16
|
opts.requires_fields(:option_type, :option_strike, :stock_price)
|
17
17
|
|
18
|
-
case opts[:option_type]
|
18
|
+
value = case opts[:option_type]
|
19
19
|
when :call
|
20
|
-
|
20
|
+
[opts[:stock_price] - opts[:option_strike], 0].max
|
21
21
|
when :put
|
22
|
-
|
22
|
+
[opts[:option_strike] - opts[:stock_price], 0].max
|
23
23
|
else
|
24
24
|
raise ArgumentError, "Invalid option_type = #{opts[:option_type]}"
|
25
25
|
end
|
26
|
+
|
27
|
+
nil_or_gte0(value)
|
26
28
|
end
|
27
29
|
|
28
30
|
|
@@ -34,10 +36,8 @@ module Math
|
|
34
36
|
# of $35 were trading for $7, the call would have a $5 intrinsic value ($40-$35) and a $2 time value ($7-$5).
|
35
37
|
# Time value will decay by expiration assuming the underlying security stays at the same price.
|
36
38
|
def time_value(opts)
|
37
|
-
opts.
|
38
|
-
|
39
|
-
return nil if opts[:option_price].nil?
|
40
|
-
return nil if opts[:option_price] < 0
|
39
|
+
return nil if opts[:option_price].nil? || opts[:option_price] < 0
|
40
|
+
return nil if opts[:premium_value].nil? || opts[:premium_value] < 0
|
41
41
|
|
42
42
|
nil_or_gte0(opts[:option_price] - opts[:premium_value])
|
43
43
|
end
|
@@ -48,11 +48,10 @@ module Math
|
|
48
48
|
# premium to develop an intuitive understanding of how much the market is "paying" for a dollar of risk.
|
49
49
|
# For example, if a stock is trading at $50 and you sell a $50 strike 6 month call for $4, you are getting
|
50
50
|
# paid 8% in 6 months, or about 16% annualized, in exchange for being willing to buy at $50, the current price.
|
51
|
-
def annualized_premium_value
|
52
|
-
opts.requires_fields(:option_price, :option_strike, :option_expires_pct_year)
|
53
|
-
|
51
|
+
def annualized_premium_value(opts)
|
54
52
|
return nil if opts[:option_price].nil?
|
55
53
|
return nil if opts[:option_price] < 0
|
54
|
+
opts.requires_fields(:option_price, :option_strike, :option_expires_pct_year)
|
56
55
|
|
57
56
|
nil_or_gte0(100 * Math.log(1 + opts[:option_price] / opts[:option_strike]) / opts[:option_expires_pct_year])
|
58
57
|
end
|
@@ -65,10 +64,9 @@ module Math
|
|
65
64
|
# six month call on that stock with a strike price of $35 has an intrinsic value of $5 and a total
|
66
65
|
# value of $7, the time value ($2) divided by the strike is ($2/$40) = 5%. Annualizing that time value
|
67
66
|
# to a one year horizon on a continuously compounded basis yields 9.76% (2 × ln(1 + 0.05)).
|
68
|
-
def annualized_time_value
|
67
|
+
def annualized_time_value(opts)
|
68
|
+
return nil if opts[:time_value].nil? || opts[:time_value] < 0
|
69
69
|
opts.requires_fields(:option_strike, :option_expires_pct_year, :time_value)
|
70
|
-
|
71
|
-
return nil if opts[:time_value].nil?
|
72
70
|
|
73
71
|
nil_or_gte0(100 * Math.log(1.0 + opts[:time_value] / opts[:option_strike]) / opts[:option_expires_pct_year])
|
74
72
|
end
|
data/lib/greeks.rb
CHANGED
@@ -34,6 +34,10 @@ module Math
|
|
34
34
|
attr_reader :price_vs_rate_vs_expires
|
35
35
|
attr_reader :strike_vs_fed_vs_expires
|
36
36
|
attr_reader :price_ratio_log_less_rates
|
37
|
+
|
38
|
+
# Optional fields
|
39
|
+
attr_reader :option_volume
|
40
|
+
attr_reader :option_open_interest
|
37
41
|
|
38
42
|
|
39
43
|
def initialize(opts)
|
@@ -50,6 +54,9 @@ module Math
|
|
50
54
|
@option_expires_pct_year = (option_expires_in_days + 1.0) / 365.0
|
51
55
|
@option_expires_pct_year_sqrt = Math.sqrt(option_expires_pct_year)
|
52
56
|
|
57
|
+
@option_volume = opts[:option_volume]
|
58
|
+
@option_open_interest = opts[:option_open_interest]
|
59
|
+
|
53
60
|
|
54
61
|
@price_vs_rate_vs_expires = GreekCalculations.misc_price_vs_rate_vs_expires(
|
55
62
|
:stock_price => stock_price,
|
@@ -281,7 +288,8 @@ module Math
|
|
281
288
|
|
282
289
|
|
283
290
|
def to_hash
|
284
|
-
hash
|
291
|
+
return @hash if @hash
|
292
|
+
@hash = {
|
285
293
|
:federal_reserve_interest_rate => federal_reserve_interest_rate,
|
286
294
|
:stock_dividend_rate => stock_dividend_rate,
|
287
295
|
:stock_price => stock_price,
|
@@ -289,13 +297,19 @@ module Math
|
|
289
297
|
:option_type => option_type,
|
290
298
|
:option_strike => option_strike,
|
291
299
|
:option_price => option_price,
|
300
|
+
:option_volume => option_volume,
|
301
|
+
:option_open_interest => option_open_interest,
|
302
|
+
:premium_value => premium_value,
|
303
|
+
:time_value => time_value,
|
304
|
+
:annualized_premium_value => annualized_premium_value,
|
305
|
+
:annualized_time_value => annualized_time_value,
|
292
306
|
:iv => (NilMath.new(iv) * 100.0).to_f, # iv * 100
|
293
307
|
:delta => (NilMath.new(delta) * stock_price / option_price).to_f, # delta * stock_price / option_price
|
294
308
|
:gamma => (NilMath.new(gamma) * stock_price / delta).to_f, # gamma * stock_price / delta
|
295
309
|
:vega => (NilMath.new(vega) * 100.0 * iv / option_price).to_f, # vega * iv * 100 / option_price
|
296
310
|
:rho => (NilMath.new(rho) * 100.0 / option_price).to_f, # rho * 100 / option_price
|
297
311
|
:theta => (NilMath.new(theta) * 100.0 / option_price).to_f, # theta * 100 / option_price
|
298
|
-
:
|
312
|
+
:delta_vs_theta => nil,
|
299
313
|
:break_even => (NilMath.new(break_even) * 100.0).to_f, # break_even * 100
|
300
314
|
}
|
301
315
|
|
@@ -305,14 +319,18 @@ module Math
|
|
305
319
|
# decay rate, the trend in the Delta/Theta column indicates which options give the most exposure
|
306
320
|
# to the movement of the underlying stock or index for a given decay rate of the option value.
|
307
321
|
# The highest numbers indicate the most bang for the buck for the least decay rate.
|
308
|
-
hash[:
|
322
|
+
@hash[:delta_vs_theta] = (NilMath.new(@hash[:delta]) / @hash[:theta]).to_f
|
309
323
|
|
310
324
|
# Iterate the generated columns and round the output
|
311
|
-
|
312
|
-
|
325
|
+
# Skip all the fields related to the input data: Federal, Stock, & Option
|
326
|
+
@hash.keys.reject do |key|
|
327
|
+
key = key.to_s
|
328
|
+
key.start_with?('federal_') || key.start_with?('stock_') || key.start_with?('option_')
|
329
|
+
end.each do |key|
|
330
|
+
@hash[key] &&= @hash[key].round(2)
|
313
331
|
end
|
314
332
|
|
315
|
-
hash
|
333
|
+
@hash
|
316
334
|
end
|
317
335
|
|
318
336
|
|
@@ -0,0 +1 @@
|
|
1
|
+
:stock_price,:stock_dividend_rate,:federal_reserve_interest_rate,:option_expires_in_days,:option_strike,:option_price,:option_volume,:option_open_interest,:iv,:delta,:gamma,:vega,:rho,:theta,:delta_vs_theta,:annualized_premium_value,:premium_value,:time_value,:annualized_time_value,:break_even
|
@@ -0,0 +1 @@
|
|
1
|
+
:stock_price,:stock_dividend_rate,:federal_reserve_interest_rate,:option_expires_in_days,:option_strike,:option_price,:option_volume,:option_open_interest,:iv,:delta,:gamma,:vega,:rho,:theta,:delta_vs_theta,:annualized_premium_value,:premium_value,:time_value,:annualized_time_value,:break_even
|
@@ -0,0 +1 @@
|
|
1
|
+
:stock_price,:stock_dividend_rate,:federal_reserve_interest_rate,:option_expires_in_days,:option_strike,:option_price,:option_volume,:option_open_interest,:iv,:delta,:gamma,:vega,:rho,:theta,:delta_vs_theta,:annualized_premium_value,:premium_value,:time_value,:annualized_time_value,:break_even
|
@@ -0,0 +1 @@
|
|
1
|
+
:stock_price,:stock_dividend_rate,:federal_reserve_interest_rate,:option_expires_in_days,:option_strike,:option_price,:option_volume,:option_open_interest,:iv,:delta,:gamma,:vega,:rho,:theta,:delta_vs_theta,:annualized_premium_value,:premium_value,:time_value,:annualized_time_value,:break_even
|
@@ -3,7 +3,6 @@ require File.expand_path("../../spec_helper.rb", File.dirname(__FILE__))
|
|
3
3
|
describe "Math::GreekCalculations::iv_option_price" do
|
4
4
|
include Math
|
5
5
|
include Math::GreekCalculations
|
6
|
-
include Math::GreekCalculationHelpers
|
7
6
|
|
8
7
|
let(:stock_price) { 10.00 }
|
9
8
|
let(:stock_dividend_rate_f) { 0.00 }
|
@@ -3,7 +3,6 @@ require File.expand_path("../../spec_helper.rb", File.dirname(__FILE__))
|
|
3
3
|
describe "Math::GreekCalculations::iv_vega" do
|
4
4
|
include Math
|
5
5
|
include Math::GreekCalculations
|
6
|
-
include Math::GreekCalculationHelpers
|
7
6
|
|
8
7
|
let(:stock_price) { 10.00 }
|
9
8
|
let(:stock_dividend_rate_f) { 0.00 }
|
@@ -3,7 +3,6 @@ require File.expand_path("../../spec_helper.rb", File.dirname(__FILE__))
|
|
3
3
|
describe "Math::GreekCalculations::misc_price_ratio_log_less_rates" do
|
4
4
|
include Math
|
5
5
|
include Math::GreekCalculations
|
6
|
-
include Math::GreekCalculationHelpers
|
7
6
|
|
8
7
|
let(:stock_price) { 10.00 }
|
9
8
|
let(:stock_dividend_rate_f) { 0.00 }
|
data/spec/greeks/greeks_spec.rb
CHANGED
@@ -1,116 +1,42 @@
|
|
1
1
|
require File.expand_path("../spec_helper.rb", File.dirname(__FILE__))
|
2
2
|
|
3
3
|
describe Math::Greeks::Calculator do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
let(:date) { '2013-06-21' }
|
13
|
-
let(:days) { 35.0 }
|
14
|
-
|
15
|
-
let(:call) do
|
16
|
-
{
|
17
|
-
:strike => 4.50,
|
18
|
-
:bid => 0.16,
|
19
|
-
:iv => 61.92,
|
20
|
-
:delta => 8.59,
|
21
|
-
:gamma => 5.57,
|
22
|
-
:vega => 1.81,
|
23
|
-
:rho => 0.75,
|
24
|
-
:theta => -2.51,
|
25
|
-
:break_even => 21.38,
|
26
|
-
}
|
27
|
-
end
|
4
|
+
# Helper method to iterate the sample data
|
5
|
+
def compare_csv(days, option_type)
|
6
|
+
table = CSV.table(File.join(File.dirname(__FILE__), "#{days}days.#{option_type}s.csv"))
|
7
|
+
|
8
|
+
table.each do |row|
|
9
|
+
# Convert to a hash
|
10
|
+
row = row.to_hash
|
28
11
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
:
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
let(:base_opts) do
|
44
|
-
{
|
45
|
-
:stock_price => 4.07,
|
46
|
-
:stock_dividend_rate => 0.00,
|
47
|
-
:option_expires_in_days => 35.0,
|
48
|
-
:federal_reserve_interest_rate => 0.01,
|
49
|
-
:option_type => nil,
|
50
|
-
:option_price => nil,
|
51
|
-
:option_strike => nil,
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
context "call option" do
|
56
|
-
let(:opts) do
|
57
|
-
base_opts.merge(
|
58
|
-
:option_type => :call,
|
59
|
-
:option_price => call[:bid],
|
60
|
-
:option_strike => call[:strike],
|
61
|
-
)
|
12
|
+
# Strip empty/nil values
|
13
|
+
row.each do |k,v|
|
14
|
+
if v.to_s === "nil" || v.to_s.strip.empty?
|
15
|
+
row[k] = nil
|
16
|
+
else
|
17
|
+
row[k] = row[k].to_f
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Calculate the options
|
22
|
+
row.merge!(:option_type => option_type)
|
23
|
+
Math::Greeks::Calculator.new(row).should be_a_greeks_hash row
|
62
24
|
end
|
25
|
+
end
|
63
26
|
|
64
|
-
|
27
|
+
it "compute call options @ 22 days" do
|
28
|
+
compare_csv(22, :call)
|
29
|
+
end
|
65
30
|
|
66
|
-
|
67
|
-
|
68
|
-
it { calc.option_type.should === opts[:option_type] }
|
69
|
-
it { calc.option_price.should === opts[:option_price] }
|
70
|
-
it { calc.option_strike.should === opts[:option_strike] }
|
71
|
-
it { calc.option_expires_in_days.should === opts[:option_expires_in_days] }
|
72
|
-
it { calc.federal_reserve_interest_rate.should === opts[:federal_reserve_interest_rate] }
|
73
|
-
|
74
|
-
it { calc.to_hash[:iv].should === call[:iv] }
|
75
|
-
it { calc.to_hash[:delta].should === call[:delta] }
|
76
|
-
it { calc.to_hash[:gamma].should === call[:gamma] }
|
77
|
-
it { calc.to_hash[:vega].should === call[:vega] }
|
78
|
-
it { calc.to_hash[:theta].should === call[:theta] }
|
79
|
-
it { calc.to_hash[:rho].should === call[:rho] }
|
80
|
-
it { calc.to_hash[:break_even].round(2).should === call[:break_even] }
|
31
|
+
it "compute put options @ 22 days" do
|
32
|
+
compare_csv(22, :put)
|
81
33
|
end
|
82
|
-
|
83
|
-
context "put option" do
|
84
|
-
let(:opts) do
|
85
|
-
base_opts.merge(
|
86
|
-
:option_type => :put,
|
87
|
-
:option_price => put[:bid],
|
88
|
-
:option_strike => put[:strike],
|
89
|
-
)
|
90
|
-
end
|
91
34
|
|
92
|
-
|
35
|
+
it "compute call options @ 50 days" do
|
36
|
+
compare_csv(50, :call)
|
37
|
+
end
|
93
38
|
|
94
|
-
|
95
|
-
|
96
|
-
it { calc.option_type.should === opts[:option_type] }
|
97
|
-
it { calc.option_price.should === opts[:option_price] }
|
98
|
-
it { calc.option_strike.should === opts[:option_strike] }
|
99
|
-
it { calc.option_expires_in_days.should === opts[:option_expires_in_days] }
|
100
|
-
it { calc.federal_reserve_interest_rate.should === opts[:federal_reserve_interest_rate] }
|
101
|
-
|
102
|
-
it { calc.to_hash[:iv].should === put[:iv] }
|
103
|
-
it { calc.to_hash[:delta].should === put[:delta] }
|
104
|
-
it { calc.to_hash[:gamma].should === put[:gamma] }
|
105
|
-
it { calc.to_hash[:vega].should === put[:vega] }
|
106
|
-
it { calc.to_hash[:theta].should === put[:theta] }
|
107
|
-
it { calc.to_hash[:rho].should === put[:rho] }
|
108
|
-
it { calc.to_hash[:break_even].round(2).should === put[:break_even] }
|
39
|
+
it "compute put options @ 50 days" do
|
40
|
+
compare_csv(50, :put)
|
109
41
|
end
|
110
|
-
|
111
|
-
it {
|
112
|
-
calculator = Math::Greeks::Calculator.new(:stock_price=>1558.86, :stock_dividend_rate=>0.0, :federal_reserve_interest_rate=>0.0, :option_type=>:call, :option_price=>751.50, :option_strike=>800.00, :option_expires_in_days=>2)
|
113
|
-
calculator.iv.should be_nil
|
114
|
-
calculator.to_hash[:iv].should be_nil
|
115
|
-
}
|
116
42
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module Math
|
3
|
+
module GreekCalculationShorthandHelpers
|
4
|
+
include Math
|
5
|
+
include Math::GreekCalculations
|
6
|
+
|
7
|
+
def var_price_ratio_log_less_rates
|
8
|
+
misc_price_ratio_log_less_rates(
|
9
|
+
:stock_price => stock_price,
|
10
|
+
:option_strike => option_strike,
|
11
|
+
:option_expires_pct_year => option_expires_pct_year,
|
12
|
+
:federal_reserve_interest_rate_f => federal_reserve_interest_rate_f,
|
13
|
+
:stock_dividend_rate_f => stock_dividend_rate_f
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def var_price_vs_rate_vs_expires
|
18
|
+
misc_price_vs_rate_vs_expires(
|
19
|
+
:stock_price => stock_price,
|
20
|
+
:option_expires_pct_year => option_expires_pct_year,
|
21
|
+
:stock_dividend_rate_f => stock_dividend_rate_f
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def var_vega
|
26
|
+
iv_vega(stock_price, option_strike, option_expires_pct_year, volatility_guess, federal_reserve_interest_rate_f, stock_dividend_rate_f, var_price_ratio_log_less_rates, var_price_vs_rate_vs_expires)
|
27
|
+
end
|
28
|
+
|
29
|
+
def var_vega
|
30
|
+
iv_vega(stock_price, option_strike, option_expires_pct_year, Math::sqrt(option_expires_pct_year), volatility_guess, federal_reserve_interest_rate_f, stock_dividend_rate_f, var_price_ratio_log_less_rates, var_price_vs_rate_vs_expires)
|
31
|
+
end
|
32
|
+
|
33
|
+
def var_option_price
|
34
|
+
iv_option_price(stock_price, option_strike, option_expires_pct_year, Math::sqrt(option_expires_pct_year), volatility_guess, federal_reserve_interest_rate_f, stock_dividend_rate_f, option_type, var_price_ratio_log_less_rates, var_price_vs_rate_vs_expires, misc_strike_vs_fed_vs_expires(:option_strike => option_strike, :option_expires_pct_year => option_expires_pct_year, :federal_reserve_interest_rate_f => federal_reserve_interest_rate_f))
|
35
|
+
end
|
36
|
+
|
37
|
+
def var_iv
|
38
|
+
iv(
|
39
|
+
:stock_price => stock_price,
|
40
|
+
:option_strike => option_strike,
|
41
|
+
:option_expires_pct_year => option_expires_pct_year,
|
42
|
+
:option_expires_pct_year_sqrt => Math::sqrt(option_expires_pct_year),
|
43
|
+
:federal_reserve_interest_rate_f => federal_reserve_interest_rate_f,
|
44
|
+
:stock_dividend_rate_f => stock_dividend_rate_f,
|
45
|
+
:option_type => option_type,
|
46
|
+
:option_price => option_price,
|
47
|
+
:rate_vs_expires => misc_rate_vs_expires(:option_expires_pct_year => option_expires_pct_year, :stock_dividend_rate_f => stock_dividend_rate_f),
|
48
|
+
:price_vs_rate_vs_expires => var_price_vs_rate_vs_expires,
|
49
|
+
:strike_vs_fed_vs_expires => misc_strike_vs_fed_vs_expires(:option_strike => option_strike, :option_expires_pct_year => option_expires_pct_year, :federal_reserve_interest_rate_f => federal_reserve_interest_rate_f),
|
50
|
+
:price_ratio_log_less_rates => var_price_ratio_log_less_rates
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,15 +2,29 @@ require 'rubygems'
|
|
2
2
|
require 'rspec'
|
3
3
|
require 'rspec-expectations'
|
4
4
|
require 'benchmark'
|
5
|
+
require 'require_all'
|
6
|
+
require 'csv'
|
5
7
|
|
6
8
|
$:.push File.expand_path("../lib", File.dirname(__FILE__))
|
7
9
|
require 'greeks'
|
8
10
|
|
9
11
|
$spec_root = File.dirname(__FILE__)
|
10
12
|
|
13
|
+
require_all File.join($spec_root, 'support')
|
14
|
+
require_all File.join($spec_root, 'helpers')
|
15
|
+
|
16
|
+
|
11
17
|
RSpec.configure do |config|
|
18
|
+
config.include Math::GreekCalculationShorthandHelpers
|
19
|
+
|
12
20
|
old_verbose, $VERBOSE = $VERBOSE, nil
|
13
21
|
|
22
|
+
def verbose_puts(s)
|
23
|
+
return unless $VERBOSE
|
24
|
+
file = File.basename(caller(1).first)
|
25
|
+
super("puts() from #{file}: #{s}")
|
26
|
+
end
|
27
|
+
|
14
28
|
def puts(s)
|
15
29
|
file = File.basename(caller(1).first)
|
16
30
|
super("puts() from #{file}: #{s}")
|
@@ -32,57 +46,3 @@ RSpec.configure do |config|
|
|
32
46
|
@result
|
33
47
|
end
|
34
48
|
end
|
35
|
-
|
36
|
-
module Math
|
37
|
-
module GreekCalculationHelpers
|
38
|
-
include Math
|
39
|
-
include Math::GreekCalculations
|
40
|
-
|
41
|
-
def var_price_ratio_log_less_rates
|
42
|
-
misc_price_ratio_log_less_rates(
|
43
|
-
:stock_price => stock_price,
|
44
|
-
:option_strike => option_strike,
|
45
|
-
:option_expires_pct_year => option_expires_pct_year,
|
46
|
-
:federal_reserve_interest_rate_f => federal_reserve_interest_rate_f,
|
47
|
-
:stock_dividend_rate_f => stock_dividend_rate_f
|
48
|
-
)
|
49
|
-
end
|
50
|
-
|
51
|
-
def var_price_vs_rate_vs_expires
|
52
|
-
misc_price_vs_rate_vs_expires(
|
53
|
-
:stock_price => stock_price,
|
54
|
-
:option_expires_pct_year => option_expires_pct_year,
|
55
|
-
:stock_dividend_rate_f => stock_dividend_rate_f
|
56
|
-
)
|
57
|
-
end
|
58
|
-
|
59
|
-
def var_vega
|
60
|
-
iv_vega(stock_price, option_strike, option_expires_pct_year, volatility_guess, federal_reserve_interest_rate_f, stock_dividend_rate_f, var_price_ratio_log_less_rates, var_price_vs_rate_vs_expires)
|
61
|
-
end
|
62
|
-
|
63
|
-
def var_vega
|
64
|
-
iv_vega(stock_price, option_strike, option_expires_pct_year, Math::sqrt(option_expires_pct_year), volatility_guess, federal_reserve_interest_rate_f, stock_dividend_rate_f, var_price_ratio_log_less_rates, var_price_vs_rate_vs_expires)
|
65
|
-
end
|
66
|
-
|
67
|
-
def var_option_price
|
68
|
-
iv_option_price(stock_price, option_strike, option_expires_pct_year, Math::sqrt(option_expires_pct_year), volatility_guess, federal_reserve_interest_rate_f, stock_dividend_rate_f, option_type, var_price_ratio_log_less_rates, var_price_vs_rate_vs_expires, misc_strike_vs_fed_vs_expires(:option_strike => option_strike, :option_expires_pct_year => option_expires_pct_year, :federal_reserve_interest_rate_f => federal_reserve_interest_rate_f))
|
69
|
-
end
|
70
|
-
|
71
|
-
def var_iv
|
72
|
-
iv(
|
73
|
-
:stock_price => stock_price,
|
74
|
-
:option_strike => option_strike,
|
75
|
-
:option_expires_pct_year => option_expires_pct_year,
|
76
|
-
:option_expires_pct_year_sqrt => Math::sqrt(option_expires_pct_year),
|
77
|
-
:federal_reserve_interest_rate_f => federal_reserve_interest_rate_f,
|
78
|
-
:stock_dividend_rate_f => stock_dividend_rate_f,
|
79
|
-
:option_type => option_type,
|
80
|
-
:option_price => option_price,
|
81
|
-
:rate_vs_expires => misc_rate_vs_expires(:option_expires_pct_year => option_expires_pct_year, :stock_dividend_rate_f => stock_dividend_rate_f),
|
82
|
-
:price_vs_rate_vs_expires => var_price_vs_rate_vs_expires,
|
83
|
-
:strike_vs_fed_vs_expires => misc_strike_vs_fed_vs_expires(:option_strike => option_strike, :option_expires_pct_year => option_expires_pct_year, :federal_reserve_interest_rate_f => federal_reserve_interest_rate_f),
|
84
|
-
:price_ratio_log_less_rates => var_price_ratio_log_less_rates
|
85
|
-
)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'rspec-expectations'
|
3
|
+
|
4
|
+
RSpec::Matchers.define :be_a_greeks_hash do |expected|
|
5
|
+
match do |actual|
|
6
|
+
hash = actual.to_hash
|
7
|
+
hash.should_not be_nil
|
8
|
+
hash.should_not be_empty
|
9
|
+
|
10
|
+
keys = [hash.keys, expected.keys].flatten.uniq.sort
|
11
|
+
verbose_puts "Keys: #{keys.inspect}"
|
12
|
+
keys.each do |key|
|
13
|
+
verbose_puts "[#{"%30s" % key}] Hash: #{hash[key].inspect} vs Actual: #{expected[key].inspect}"
|
14
|
+
end
|
15
|
+
|
16
|
+
# Delete all the values that match
|
17
|
+
# This will leave only the values that differ
|
18
|
+
expected.keys.dup.each do |key|
|
19
|
+
if hash[key] == expected[key]
|
20
|
+
expected.delete(key)
|
21
|
+
next
|
22
|
+
end
|
23
|
+
|
24
|
+
if hash[key].class == expected[key].class && !hash[key].nil? && !hash[key].is_a?(Symbol) && hash[key].round(1) == expected[key].round(1)
|
25
|
+
expected.delete(key)
|
26
|
+
next
|
27
|
+
end
|
28
|
+
|
29
|
+
expected[key] = "#{expected.delete(key).inspect}(e) vs #{hash[key].inspect}(a)"
|
30
|
+
end
|
31
|
+
verbose_puts "Hash: #{hash}"
|
32
|
+
verbose_puts "Expected: #{expected}"
|
33
|
+
expected.should be_empty
|
34
|
+
end
|
35
|
+
|
36
|
+
failure_message_for_should do |actual|
|
37
|
+
"expected that #{actual.to_hash} would match values of #{expected}"
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: greeks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '1.
|
4
|
+
version: '1.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Glenn Nagel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: require_all
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- Gemfile
|
78
78
|
- Gemfile.lock
|
79
79
|
- README.md
|
80
|
+
- greeks-1.1.gem
|
80
81
|
- greeks.gemspec
|
81
82
|
- lib/greeks.rb
|
82
83
|
- lib/greeks/calculations/delta.rb
|
@@ -87,6 +88,10 @@ files:
|
|
87
88
|
- lib/greeks/calculations/theta.rb
|
88
89
|
- lib/greeks/calculations/time_values.rb
|
89
90
|
- lib/greeks/calculations/vega.rb
|
91
|
+
- spec/greeks/22days.calls.csv
|
92
|
+
- spec/greeks/22days.puts.csv
|
93
|
+
- spec/greeks/50days.calls.csv
|
94
|
+
- spec/greeks/50days.puts.csv
|
90
95
|
- spec/greeks/calculations/delta_spec.rb
|
91
96
|
- spec/greeks/calculations/gamma_spec.rb
|
92
97
|
- spec/greeks/calculations/iv_option_price_spec.rb
|
@@ -98,7 +103,9 @@ files:
|
|
98
103
|
- spec/greeks/calculations/time_values_spec.rb
|
99
104
|
- spec/greeks/calculations/vega_spec.rb
|
100
105
|
- spec/greeks/greeks_spec.rb
|
106
|
+
- spec/helpers/greek_calculation_shorthand_helpers.rb
|
101
107
|
- spec/spec_helper.rb
|
108
|
+
- spec/support/calculate_greeks_hash.rb
|
102
109
|
homepage: https://github.com/gnagel/greeks
|
103
110
|
licenses:
|
104
111
|
- MIT
|
@@ -126,6 +133,10 @@ specification_version: 4
|
|
126
133
|
summary: Calculate greeks for options trading (Implied Volatility, Delta, Gamma, Vega,
|
127
134
|
Rho, and Theta)
|
128
135
|
test_files:
|
136
|
+
- spec/greeks/22days.calls.csv
|
137
|
+
- spec/greeks/22days.puts.csv
|
138
|
+
- spec/greeks/50days.calls.csv
|
139
|
+
- spec/greeks/50days.puts.csv
|
129
140
|
- spec/greeks/calculations/delta_spec.rb
|
130
141
|
- spec/greeks/calculations/gamma_spec.rb
|
131
142
|
- spec/greeks/calculations/iv_option_price_spec.rb
|
@@ -137,4 +148,6 @@ test_files:
|
|
137
148
|
- spec/greeks/calculations/time_values_spec.rb
|
138
149
|
- spec/greeks/calculations/vega_spec.rb
|
139
150
|
- spec/greeks/greeks_spec.rb
|
151
|
+
- spec/helpers/greek_calculation_shorthand_helpers.rb
|
140
152
|
- spec/spec_helper.rb
|
153
|
+
- spec/support/calculate_greeks_hash.rb
|