penfold 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/portfolio.yml ADDED
@@ -0,0 +1,277 @@
1
+ ---
2
+ #C: !ruby/object:CoveredCallPosition
3
+ # commission: OptionsHouseAlt
4
+ # num_shares: 2500
5
+ # date_established: 2010-07-19
6
+ # option: !ruby/object:Call
7
+ # expires: 2011-01-22
8
+ # price: 50
9
+ # stock: !ruby/object:Stock
10
+ # price: 395
11
+ # symbol: C
12
+ # strike: 400
13
+
14
+ #S: !ruby/object:CoveredCallPosition
15
+ # commission: OptionsHouseAlt
16
+ # num_shares: 2000
17
+ # date_established: 2010-07-19
18
+ # option: !ruby/object:Call
19
+ # expires: 2011-01-22
20
+ # price: 118
21
+ # stock: !ruby/object:Stock
22
+ # price: 471
23
+ # symbol: S
24
+ # strike: 400
25
+
26
+ #LYG: !ruby/object:CoveredCallPosition
27
+ # commission: OptionsHouseAlt
28
+ # num_shares: 400
29
+ # date_established: 2010-07-22
30
+ # option: !ruby/object:Call
31
+ # expires: 2010-08-21
32
+ # price: 11
33
+ # stock: !ruby/object:Stock
34
+ # price: 371
35
+ # symbol: LYG
36
+ # strike: 400
37
+
38
+ #CBS: !ruby/object:CoveredCallPosition
39
+ # commission: OptionsHouseAlt
40
+ # num_shares: 100
41
+ # date_established: 2010-07-29
42
+ # option: !ruby/object:Call
43
+ # expires: 2010-08-21
44
+ # price: 96
45
+ # stock: !ruby/object:Stock
46
+ # price: 1449
47
+ # symbol: CBS
48
+ # strike: 1400
49
+
50
+ #RIG: !ruby/object:CoveredCallPosition
51
+ # commission: OptionsHouseAlt
52
+ # num_shares: 200
53
+ # date_established: 2010-08-05
54
+ # option: !ruby/object:Call
55
+ # expires: 2010-08-06
56
+ # price: 225
57
+ # stock: !ruby/object:Stock
58
+ # price: 5681
59
+ # symbol: RIG
60
+ # strike: 5500
61
+
62
+ #VXX: !ruby/object:CoveredCallPosition
63
+ # commission: OptionsHouseAlt
64
+ # num_shares: 200
65
+ # date_established: 2010-08-05
66
+ # option: !ruby/object:Call
67
+ # expires: 2010-08-21
68
+ # price: 187
69
+ # stock: !ruby/object:Stock
70
+ # price: 2143
71
+ # symbol: VXX
72
+ # strike: 2000
73
+
74
+ #WY: !ruby/object:CoveredCallPosition
75
+ # commission: OptionsHouseAlt
76
+ # num_shares: 600
77
+ # date_established: 2010-08-13
78
+ # option: !ruby/object:Call
79
+ # expires: 2010-08-21
80
+ # price: 80
81
+ # stock: !ruby/object:Stock
82
+ # price: 1651
83
+ # symbol: WY
84
+ # strike: 1600
85
+
86
+ #ING: !ruby/object:CoveredCallPosition
87
+ # commission: OptionsHouseAlt
88
+ # num_shares: 1000
89
+ # date_established: 2010-08-11
90
+ # option: !ruby/object:Call
91
+ # expires: 2010-09-18
92
+ # price: 50
93
+ # stock: !ruby/object:Stock
94
+ # price: 886
95
+ # symbol: ING
96
+ # strike: 900
97
+
98
+ BCS: !ruby/object:CoveredCallPosition
99
+ commission: OptionsHouseAlt
100
+ num_shares: 500
101
+ date_established: 2010-08-02
102
+ option: !ruby/object:Call
103
+ expires: 2010-12-18
104
+ price: 30
105
+ stock: !ruby/object:Stock
106
+ price: 1966
107
+ symbol: BCS
108
+ strike: 2100
109
+
110
+ # DOW: !ruby/object:CoveredCallPosition
111
+ # commission: OptionsHouseAlt
112
+ # num_shares: 400
113
+ # date_established: 2010-08-02
114
+ # option: !ruby/object:Call
115
+ # expires: 2010-10-16
116
+ # price: 22
117
+ # stock: !ruby/object:Stock
118
+ # price: 2714
119
+ # symbol: DOW
120
+ # strike: 2800
121
+
122
+ #F: !ruby/object:CoveredCallPosition
123
+ # commission: OptionsHouseAlt
124
+ # num_shares: 900
125
+ # date_established: 2010-08-04
126
+ # option: !ruby/object:Call
127
+ # expires: 2010-09-18
128
+ # price: 33
129
+ # stock: !ruby/object:Stock
130
+ # price: 1189
131
+ # symbol: F
132
+ # strike: 1200
133
+
134
+ #GRMN: !ruby/object:CoveredCallPosition
135
+ # commission: OptionsHouseAlt
136
+ # num_shares: 400
137
+ # date_established: 2010-08-04
138
+ # option: !ruby/object:Call
139
+ # expires: 2010-09-18
140
+ # price: 64
141
+ # stock: !ruby/object:Stock
142
+ # price: 2760
143
+ # symbol: GRMN
144
+ # strike: 2800
145
+
146
+ #BP: !ruby/object:CoveredCallPosition
147
+ # commission: OptionsHouseAlt
148
+ # num_shares: 300
149
+ # date_established: 2010-08-30
150
+ # option: !ruby/object:Call
151
+ # expires: 2010-09-03
152
+ # price: 122
153
+ # stock: !ruby/object:Stock
154
+ # price: 3589
155
+ # symbol: BP
156
+ # strike: 3500
157
+
158
+ #BP2: !ruby/object:CoveredCallPosition
159
+ # commission: OptionsHouseAlt
160
+ # num_shares: 300
161
+ # date_established: 2010-09-02
162
+ # option: !ruby/object:Call
163
+ # expires: 2010-09-10
164
+ # price: 48
165
+ # stock: !ruby/object:Stock
166
+ # price: 3640
167
+ # symbol: BP
168
+ # strike: 3700
169
+
170
+ #RIG: !ruby/object:CoveredCallPosition
171
+ # commission: OptionsHouseAlt
172
+ # num_shares: 200
173
+ # date_established: 2010-09-08
174
+ # option: !ruby/object:Call
175
+ # expires: 2010-09-18
176
+ # price: 242
177
+ # stock: !ruby/object:Stock
178
+ # price: 5404
179
+ # symbol: RIG
180
+ # strike: 5250
181
+
182
+ #WFC: !ruby/object:CoveredCallPosition
183
+ # commission: OptionsHouseAlt
184
+ # num_shares: 400
185
+ # date_established: 2010-09-13
186
+ # option: !ruby/object:Call
187
+ # expires: 2010-09-18
188
+ # price: 55
189
+ # stock: !ruby/object:Stock
190
+ # price: 2629
191
+ # symbol: WFC
192
+ # strike: 2600
193
+
194
+ # ING: !ruby/object:CoveredCallPosition
195
+ # commission: OptionsHouseAlt
196
+ # num_shares: 1000
197
+ # date_established: 2010-09-21
198
+ # option: !ruby/object:Call
199
+ # expires: 2010-10-16
200
+ # price: 55
201
+ # stock: !ruby/object:Stock
202
+ # price: 1026
203
+ # symbol: ING
204
+ # strike: 1000
205
+
206
+ #BP: !ruby/object:CoveredCallPosition
207
+ # commission: OptionsHouseAlt
208
+ # num_shares: 300
209
+ # date_established: 2010-09-27
210
+ # option: !ruby/object:Call
211
+ # expires: 2010-10-01
212
+ # price: 74
213
+ # stock: !ruby/object:Stock
214
+ # price: 3856
215
+ # symbol: BP
216
+ # strike: 3800
217
+
218
+ JPM: !ruby/object:CoveredCallPosition
219
+ commission: OptionsHouseAlt
220
+ num_shares: 300
221
+ date_established: 2010-09-27
222
+ option: !ruby/object:Call
223
+ expires: 2010-11-20
224
+ price: 133
225
+ stock: !ruby/object:Stock
226
+ price: 3734
227
+ symbol: JPM
228
+ strike: 3800
229
+
230
+ # HPQ: !ruby/object:CoveredCallPosition
231
+ # commission: OptionsHouseAlt
232
+ # num_shares: 300
233
+ # date_established: 2010-09-29
234
+ # option: !ruby/object:Call
235
+ # expires: 2010-10-16
236
+ # price: 179
237
+ # stock: !ruby/object:Stock
238
+ # price: 4221
239
+ # symbol: HPQ
240
+ # strike: 4100
241
+ #
242
+ # AET: !ruby/object:CoveredCallPosition
243
+ # commission: OptionsHouseAlt
244
+ # num_shares: 400
245
+ # date_established: 2010-09-29
246
+ # option: !ruby/object:Call
247
+ # expires: 2010-10-16
248
+ # price: 120
249
+ # stock: !ruby/object:Stock
250
+ # price: 3079
251
+ # symbol: AET
252
+ # strike: 3000
253
+ #
254
+ # MON: !ruby/object:CoveredCallPosition
255
+ # commission: OptionsHouseAlt
256
+ # num_shares: 200
257
+ # date_established: 2010-10-06
258
+ # option: !ruby/object:Call
259
+ # expires: 2010-10-16
260
+ # price: 212
261
+ # stock: !ruby/object:Stock
262
+ # price: 4891
263
+ # symbol: MON
264
+ # strike: 4750
265
+
266
+ PKX: !ruby/object:CoveredCallPosition
267
+ commission: OptionsHouseAlt
268
+ num_shares: 100
269
+ date_established: 2010-10-19
270
+ option: !ruby/object:Call
271
+ expires: 2010-11-20
272
+ price: 490
273
+ stock: !ruby/object:Stock
274
+ price: 10720
275
+ symbol: PKX
276
+ strike: 10500
277
+
@@ -0,0 +1,74 @@
1
+ require 'option_calendar'
2
+ require 'test/unit'
3
+
4
+ class OptionCalendarTest < Test::Unit::TestCase
5
+
6
+ # Saturday expiries
7
+ EXPIRY_MONTHS = [
8
+ [Date.parse("Jan 1 2010"), Date.parse("Jan 16 2010")],
9
+ [Date.parse("Feb 1 2010"), Date.parse("Feb 20 2010")],
10
+ [Date.parse("Mar 1 2010"), Date.parse("Mar 20 2010")],
11
+ [Date.parse("Apr 1 2010"), Date.parse("Apr 17 2010")],
12
+ [Date.parse("May 1 2010"), Date.parse("May 22 2010")],
13
+ [Date.parse("Jun 1 2010"), Date.parse("Jun 19 2010")],
14
+ [Date.parse("Jul 1 2010"), Date.parse("Jul 17 2010")],
15
+ [Date.parse("Aug 1 2010"), Date.parse("Aug 21 2010")],
16
+ [Date.parse("Sep 1 2010"), Date.parse("Sep 18 2010")],
17
+ [Date.parse("Oct 1 2010"), Date.parse("Oct 16 2010")],
18
+ [Date.parse("Nov 1 2010"), Date.parse("Nov 20 2010")],
19
+ [Date.parse("Dec 1 2010"), Date.parse("Dec 18 2010")],
20
+
21
+ [Date.parse("Jan 1 2011"), Date.parse("Jan 22 2011")],
22
+ [Date.parse("Feb 1 2011"), Date.parse("Feb 19 2011")],
23
+ [Date.parse("Mar 1 2011"), Date.parse("Mar 19 2011")],
24
+ [Date.parse("Apr 1 2011"), Date.parse("Apr 16 2011")],
25
+ [Date.parse("May 1 2011"), Date.parse("May 21 2011")],
26
+ [Date.parse("Jun 1 2011"), Date.parse("Jun 18 2011")],
27
+ [Date.parse("Jul 1 2011"), Date.parse("Jul 16 2011")],
28
+ [Date.parse("Aug 1 2011"), Date.parse("Aug 20 2011")],
29
+ [Date.parse("Sep 1 2011"), Date.parse("Sep 17 2011")],
30
+ [Date.parse("Oct 1 2011"), Date.parse("Oct 22 2011")],
31
+ [Date.parse("Nov 1 2011"), Date.parse("Nov 19 2011")],
32
+ [Date.parse("Dec 1 2011"), Date.parse("Dec 17 2011")]
33
+ ]
34
+
35
+ def test_monthly_expirations
36
+ EXPIRY_MONTHS.each do |month, exp|
37
+ message = "Month #{month.strftime("%b")} should have expiry of #{exp}"
38
+
39
+ assert_equal exp, OptionCalendar.expiration_for(month), message
40
+ assert_equal exp, OptionCalendar.expiration_for(month.end_of_month), message
41
+ end
42
+ end
43
+
44
+ NEXT_MONTHS = [
45
+ [Date.parse("Sep 15 2010"), Date.parse("Sep 18 2010"), Date.parse("Oct 16 2010")],
46
+ [Date.parse("Sep 16 2010"), Date.parse("Sep 18 2010"), Date.parse("Oct 16 2010")],
47
+ [Date.parse("Sep 17 2010"), Date.parse("Oct 16 2010"), Date.parse("Nov 20 2010")],
48
+ [Date.parse("Sep 18 2010"), Date.parse("Oct 16 2010"), Date.parse("Nov 20 2010")],
49
+ [Date.parse("Sep 19 2010"), Date.parse("Oct 16 2010"), Date.parse("Nov 20 2010")]
50
+ ]
51
+
52
+ def test_next_expiring_months
53
+ NEXT_MONTHS.each do |date, *expected|
54
+ message = "#{date} should have expirations #{expected.inspect}"
55
+
56
+ assert_equal expected, OptionCalendar.next_expiring_months(date), message
57
+ end
58
+ end
59
+
60
+ def test_nearest_expiration
61
+ jan_expiry = OptionCalendar.expiration_for(Date.parse("Jan 2011"))
62
+ feb_expiry = OptionCalendar.expiration_for(Date.parse("Feb 2011"))
63
+
64
+ assert_equal jan_expiry, OptionCalendar.nearest_expiration(jan_expiry - 4.days, 3.days)
65
+ assert_equal feb_expiry, OptionCalendar.nearest_expiration(jan_expiry - 3.days, 3.days)
66
+ assert_equal feb_expiry, OptionCalendar.nearest_expiration(jan_expiry - 2.days, 3.days)
67
+
68
+ assert_equal jan_expiry, OptionCalendar.nearest_expiration(Date.parse("Dec 31 2010"), 3.days)
69
+ assert_equal feb_expiry, OptionCalendar.nearest_expiration(Date.parse("Dec 31 2010"), 30.days)
70
+ assert_equal feb_expiry, OptionCalendar.nearest_expiration(Date.parse("Nov 30 2010"), 60.days)
71
+ end
72
+
73
+ end
74
+
@@ -0,0 +1,315 @@
1
+ require "test/unit"
2
+ require "flexmock/test_unit"
3
+ require "penfold"
4
+
5
+ class TestPenfold < Test::Unit::TestCase
6
+
7
+ # options
8
+ def test_call_type
9
+ call = Call.new
10
+
11
+ assert call.call?
12
+ assert !call.put?
13
+ end
14
+
15
+ def test_put_type
16
+ put = Put.new
17
+
18
+ assert !put.call?
19
+ assert put.put?
20
+ end
21
+
22
+ def test_option_cannot_be_instantiated
23
+ assert_raise ArgumentError do
24
+ Option.new
25
+ end
26
+ end
27
+
28
+ def test_option_expiry
29
+ unexpired = Call.new(:expires => Date.today + 10)
30
+ expired = Call.new(:expires => Date.today - 10)
31
+ expires_today = Call.new(:expires => Date.today)
32
+
33
+ assert !unexpired.expired?
34
+ assert_equal 10, unexpired.days_to_expiry
35
+
36
+ assert expired.expired?
37
+ assert_equal 0, expired.days_to_expiry
38
+
39
+ assert !expires_today.expired?
40
+ assert_equal 0, expires_today.days_to_expiry
41
+ end
42
+
43
+ def test_to_s
44
+ expires = Date.today + 93
45
+
46
+ stock = Stock.new(:symbol => "XYZ", :price => 50_00)
47
+
48
+ option = Call.new(
49
+ :stock => stock,
50
+ :strike => 35_00,
51
+ :expires => expires,
52
+ :price => 4_50
53
+ )
54
+
55
+ assert_equal "XYZ 35 #{expires.strftime("%b %y").upcase} CALL", option.to_s,
56
+ "A whole dollar amount does not require a floating point strike price"
57
+
58
+ option = Call.new(
59
+ :stock => stock,
60
+ :strike => 5_50,
61
+ :expires => expires,
62
+ :price => 4_50
63
+ )
64
+
65
+ assert_equal "XYZ 5.5 #{expires.strftime("%b %y").upcase} CALL", option.to_s,
66
+ "A partial dollar amount requires a floating point strike price"
67
+ end
68
+
69
+ def test_out_the_money?
70
+ assert flexmock(Call.new, :in_the_money? => false).out_the_money?
71
+ assert !flexmock(Call.new, :in_the_money? => true).out_the_money?
72
+ end
73
+
74
+ def test_call_moneyness
75
+ call = Call.new(:strike => 5_00, :stock => Stock.new(:price => 4_90))
76
+
77
+ assert !call.in_the_money?
78
+ assert !call.at_the_money?
79
+
80
+ call.stock.price += 10
81
+ assert !call.in_the_money?
82
+ assert call.at_the_money?
83
+
84
+ call.stock.price += 10
85
+ assert call.in_the_money?
86
+ assert !call.at_the_money?
87
+ end
88
+
89
+ def test_put_moneyness
90
+ put = Put.new(:strike => 5_00, :stock => Stock.new(:price => 4_90))
91
+
92
+ assert put.in_the_money?
93
+ assert !put.at_the_money?
94
+
95
+ put.stock.price += 10
96
+ assert !put.in_the_money?
97
+ assert put.at_the_money?
98
+
99
+ put.stock.price += 10
100
+ assert !put.in_the_money?
101
+ assert !put.at_the_money?
102
+ end
103
+
104
+ # position
105
+
106
+ def test_stock_total
107
+ position = CoveredCallPosition.new(
108
+ :num_shares => 500,
109
+ :option => Call.new(:stock => Stock.new(:price => 50_00)),
110
+ :commission => "OptionsHouse"
111
+ )
112
+
113
+ assert_equal 500 * 50_00 + position.commission.stock_entry, position.stock_total
114
+ end
115
+
116
+ def test_call_sale
117
+ position = CoveredCallPosition.new(
118
+ :num_shares => 500,
119
+ :option => Call.new(:price => 6_00),
120
+ :commission => "OptionsHouse"
121
+ )
122
+
123
+ assert_equal 3_000_00 - (position.commission.option_entry), position.call_sale
124
+ end
125
+
126
+ def test_net_outlay
127
+ position = flexmock(
128
+ CoveredCallPosition.new,
129
+ :stock_total => 25_000_00,
130
+ :call_sale => 3_000_00
131
+ )
132
+
133
+ assert_equal 22_000_00, position.net_outlay
134
+ end
135
+
136
+ def test_net_per_share
137
+ position = CoveredCallPosition.new(:num_shares => 500)
138
+ flexmock(position, :net_outlay => 22_012_20)
139
+
140
+ assert_equal 44_02.44, position.net_per_share
141
+ end
142
+
143
+ def test_downside_protection
144
+ position = flexmock(
145
+ CoveredCallPosition.new,
146
+ :net_per_share => 44_00,
147
+ :stock => Stock.new(:price => 50_00)
148
+ )
149
+
150
+ assert_equal(-0.12, position.downside_protection, "should be -12%")
151
+ end
152
+
153
+ def test_odd_lots
154
+ assert_raise ArgumentError do
155
+ CoveredCallPosition.new(:num_shares => 23)
156
+ end
157
+
158
+ assert_nothing_raised do
159
+ CoveredCallPosition.new(:num_shares => 100)
160
+ end
161
+ end
162
+
163
+ def test_num_options
164
+ assert 3, CoveredCallPosition.new(:num_shares => 300)
165
+ end
166
+
167
+ def test_stock
168
+ stock = Stock.new
169
+ position = CoveredCallPosition.new(:option => Put.new(:stock => stock))
170
+
171
+ assert_equal stock, position.stock
172
+ end
173
+
174
+ # exit
175
+
176
+ def test_creation
177
+ date = Date.today
178
+
179
+ position = CoveredCallPosition.new(
180
+ :num_shares => 500,
181
+ :commission => "OptionsHouse",
182
+ :date_established => date,
183
+
184
+ :option => Call.new(
185
+ :expires => date + 30,
186
+ :strike => 50_00,
187
+ :price => 6_00,
188
+ :stock => Stock.new(
189
+ :symbol => "XYZ",
190
+ :price => 50_00
191
+ )
192
+ )
193
+ )
194
+
195
+ closing_position = CoveredCallExit.new(
196
+ :opening_position => position,
197
+ :exit_date => date + 34,
198
+ :stock_price => 55_00
199
+ )
200
+
201
+ assert_not_same position.stock, closing_position.stock
202
+ assert_equal position.stock, closing_position.stock
203
+
204
+ assert_not_same position.option, closing_position.option
205
+ assert_equal position.option, closing_position.option
206
+
207
+ assert_same position.commission, closing_position.commission
208
+
209
+ assert_equal date + 30, closing_position.exit_date
210
+ assert closing_position.option.expired?
211
+
212
+ assert_equal 55_00, closing_position.stock.price
213
+ end
214
+
215
+ def test_creates_expired_position_when_expired_in_the_money
216
+ position = CoveredCallPosition.new(
217
+ :option => Call.new(
218
+ :stock => Stock.new(:price => 48_00),
219
+ :strike => 50_00,
220
+ :expires => Date.today + 10
221
+ )
222
+ )
223
+
224
+ expired_itm = CoveredCallExit.new(
225
+ :opening_position => position,
226
+ :stock_price => 52_00,
227
+ :exit_date => Date.today + 11
228
+ )
229
+
230
+ expired_otm = CoveredCallExit.new(
231
+ :opening_position => position,
232
+ :stock_price => 48_00,
233
+ :exit_date => Date.today + 11
234
+ )
235
+
236
+ unexpired_itm = CoveredCallExit.new(
237
+ :opening_position => position,
238
+ :stock_price => 52_00,
239
+ :exit_date => Date.today + 1
240
+ )
241
+
242
+ unexpired_otm = CoveredCallExit.new(
243
+ :opening_position => position,
244
+ :stock_price => 48_00,
245
+ :exit_date => Date.today + 1
246
+ )
247
+
248
+ assert_kind_of CoveredCallExpiryItmExit, expired_itm
249
+ assert !expired_otm.kind_of?(CoveredCallExpiryItmExit)
250
+ assert !unexpired_itm.kind_of?(CoveredCallExpiryItmExit)
251
+ assert !unexpired_otm.kind_of?(CoveredCallExpiryItmExit)
252
+ end
253
+
254
+ def test_no_profit_method_body_for_default_class
255
+ assert_raise NotImplementedError do
256
+ CoveredCallExit.allocate.profit
257
+ end
258
+ end
259
+
260
+ # Option pricing
261
+
262
+ def test_black_scholes
263
+ assert_in_delta 0.35725, BlackScholes.call_iv(19.18, 17.50, 0.27, 32, 1.89), 0.0001
264
+ assert_in_delta 0.25866, BlackScholes.call_iv(19.18, 19, 0.27, 32, 0.68), 0.0001
265
+ end
266
+
267
+ def test_probability
268
+ vol = BlackScholes.call_iv(19.18, 19, 0.27, 32, 0.68)
269
+
270
+ below, above = BlackScholes.probability(19.18, 19, 32, vol)
271
+
272
+ assert_in_delta 0.548, above, 0.001
273
+ assert_in_delta 0.451, below, 0.001
274
+
275
+ assert_equal above, BlackScholes.probability_above(19.18, 19, 32, vol)
276
+ assert_equal below, BlackScholes.probability_below(19.18, 19, 32, vol)
277
+ end
278
+
279
+ # comms
280
+
281
+ def test_optionshouse
282
+ (0..10).each do |i|
283
+ cost = 8_50 + (i * 15)
284
+
285
+ oh = Commission::OptionsHouse.new(:contracts => i)
286
+ assert_equal i.zero? ? 0 : cost, oh.option_entry
287
+ end
288
+
289
+ oh = Commission::OptionsHouse.new(:shares => 0)
290
+ assert_equal 0, oh.stock_entry
291
+
292
+ oh = Commission::OptionsHouse.new(:shares => 123)
293
+ assert_equal 2_95, oh.stock_entry
294
+
295
+ oh = Commission::OptionsHouse.new
296
+ assert_equal 0, oh.stock_entry
297
+ assert_equal 0, oh.option_entry
298
+ assert_equal 0, oh.option_assignment
299
+ end
300
+
301
+ def test_optionshouse_alt
302
+ opt_comms = [
303
+ [0, 0],
304
+ [4, 5_00],
305
+ [5, 5_00],
306
+ [6, 6_00]
307
+ ]
308
+
309
+ opt_comms.each do |num_contracts, cost|
310
+ oha = Commission::OptionsHouseAlt.new(:shares => 0, :contracts => num_contracts)
311
+ assert_equal cost, oha.option_entry
312
+ assert_equal num_contracts.zero? ? 0 : 5_00, oha.option_assignment
313
+ end
314
+ end
315
+ end