penfold 1.0.0

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/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