ib-ruby 0.8.4 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/.gitignore +3 -0
  2. data/HISTORY +3 -0
  3. data/README.md +29 -9
  4. data/VERSION +1 -1
  5. data/app/assets/javascripts/ib/bars.js +2 -0
  6. data/app/assets/javascripts/ib/executions.js +2 -0
  7. data/app/assets/javascripts/ib/order_states.js +2 -0
  8. data/app/assets/stylesheets/ib/bars.css +4 -0
  9. data/app/assets/stylesheets/ib/executions.css +4 -0
  10. data/app/assets/stylesheets/ib/order_states.css +4 -0
  11. data/app/controllers/ib/bars_controller.rb +87 -0
  12. data/app/controllers/ib/combo_legs_controller.rb +87 -0
  13. data/app/controllers/ib/contract_details_controller.rb +87 -0
  14. data/app/controllers/ib/contracts_controller.rb +87 -0
  15. data/app/controllers/ib/executions_controller.rb +87 -0
  16. data/app/controllers/ib/order_states_controller.rb +87 -0
  17. data/app/controllers/ib/orders_controller.rb +87 -0
  18. data/app/helpers/ib/bars_helper.rb +4 -0
  19. data/app/helpers/ib/combo_legs_helper.rb +4 -0
  20. data/app/helpers/ib/contract_details_helper.rb +4 -0
  21. data/app/helpers/ib/contracts_helper.rb +4 -0
  22. data/app/helpers/ib/executions_helper.rb +4 -0
  23. data/app/helpers/ib/order_states_helper.rb +4 -0
  24. data/app/helpers/ib/orders_helper.rb +4 -0
  25. data/app/views/ib/bars/_form.html.erb +57 -0
  26. data/app/views/ib/bars/edit.html.erb +6 -0
  27. data/app/views/ib/bars/index.html.erb +41 -0
  28. data/app/views/ib/bars/new.html.erb +5 -0
  29. data/app/views/ib/bars/show.html.erb +55 -0
  30. data/app/views/ib/combo_legs/_form.html.erb +53 -0
  31. data/app/views/ib/combo_legs/edit.html.erb +6 -0
  32. data/app/views/ib/combo_legs/index.html.erb +39 -0
  33. data/app/views/ib/combo_legs/new.html.erb +5 -0
  34. data/app/views/ib/combo_legs/show.html.erb +55 -0
  35. data/app/views/ib/contract_details/_form.html.erb +141 -0
  36. data/app/views/ib/contract_details/edit.html.erb +6 -0
  37. data/app/views/ib/contract_details/index.html.erb +83 -0
  38. data/app/views/ib/contract_details/new.html.erb +5 -0
  39. data/app/views/ib/contract_details/show.html.erb +160 -0
  40. data/app/views/ib/contracts/_form.html.erb +77 -0
  41. data/app/views/ib/contracts/edit.html.erb +6 -0
  42. data/app/views/ib/contracts/index.html.erb +53 -0
  43. data/app/views/ib/contracts/new.html.erb +5 -0
  44. data/app/views/ib/contracts/show.html.erb +85 -0
  45. data/app/views/ib/executions/_form.html.erb +77 -0
  46. data/app/views/ib/executions/edit.html.erb +6 -0
  47. data/app/views/ib/executions/index.html.erb +51 -0
  48. data/app/views/ib/executions/new.html.erb +5 -0
  49. data/app/views/ib/executions/show.html.erb +80 -0
  50. data/app/views/ib/order_states/_form.html.erb +93 -0
  51. data/app/views/ib/order_states/edit.html.erb +6 -0
  52. data/app/views/ib/order_states/index.html.erb +59 -0
  53. data/app/views/ib/order_states/new.html.erb +5 -0
  54. data/app/views/ib/order_states/show.html.erb +100 -0
  55. data/app/views/ib/orders/_form.html.erb +353 -0
  56. data/app/views/ib/orders/edit.html.erb +6 -0
  57. data/app/views/ib/orders/index.html.erb +193 -0
  58. data/app/views/ib/orders/new.html.erb +5 -0
  59. data/app/views/ib/orders/show.html.erb +435 -0
  60. data/bin/scaffold.rb +29 -0
  61. data/config/routes.rb +8 -1
  62. data/db/config.yml +5 -0
  63. data/db/migrate/101_add_ib_executions.rb +3 -0
  64. data/db/migrate/111_add_ib_bars.rb +6 -0
  65. data/db/migrate/121_add_ib_order_states.rb +8 -0
  66. data/db/migrate/131_add_ib_orders.rb +24 -0
  67. data/db/migrate/141_add_ib_combo_legs.rb +6 -0
  68. data/db/migrate/151_add_ib_underlyings.rb +3 -0
  69. data/db/migrate/161_add_ib_contract_details.rb +11 -0
  70. data/db/migrate/171_add_ib_contracts.rb +8 -1
  71. data/db/schema.rb +6 -5
  72. data/lib/ib/base.rb +3 -1
  73. data/lib/ib/base_properties.rb +26 -15
  74. data/lib/ib/connection.rb +3 -2
  75. data/lib/ib/errors.rb +16 -9
  76. data/lib/ib/extensions.rb +6 -4
  77. data/lib/ib/symbols.rb +10 -3
  78. data/lib/ib/symbols/forex.rb +49 -64
  79. data/lib/ib/symbols/futures.rb +2 -3
  80. data/lib/ib/symbols/options.rb +2 -1
  81. data/lib/ib/symbols/stocks.rb +2 -1
  82. data/lib/models/ib/bar.rb +6 -2
  83. data/lib/models/ib/combo_leg.rb +4 -3
  84. data/lib/models/ib/contract.rb +9 -5
  85. data/lib/models/ib/contract_detail.rb +1 -1
  86. data/lib/models/ib/execution.rb +3 -1
  87. data/lib/models/ib/order.rb +22 -20
  88. data/lib/models/ib/order_state.rb +4 -2
  89. data/lib/models/ib/underlying.rb +3 -4
  90. data/spec/README.md +12 -10
  91. data/spec/ib/symbols/symbols_spec.rb +10 -0
  92. data/spec/integration_helper.rb +1 -1
  93. data/spec/model_helper.rb +9 -8
  94. data/spec/models/ib/combo_leg_spec.rb +29 -28
  95. data/spec/models/ib/contract_detail_spec.rb +4 -1
  96. data/spec/models/ib/contract_spec.rb +66 -58
  97. data/spec/models/ib/execution_spec.rb +50 -44
  98. data/spec/models/ib/order_spec.rb +2 -2
  99. data/spec/order_helper.rb +5 -4
  100. data/spec/spec_helper.rb +3 -3
  101. metadata +59 -35
  102. data/app/models/ib/underlying.rb +0 -5
  103. data/bin/account_info +0 -29
  104. data/bin/cancel_orders +0 -27
  105. data/bin/contract_details +0 -35
  106. data/bin/depth_of_market +0 -43
  107. data/bin/fa_accounts +0 -22
  108. data/bin/fundamental_data +0 -39
  109. data/bin/historic_data +0 -51
  110. data/bin/historic_data_cli +0 -182
  111. data/bin/list_orders +0 -28
  112. data/bin/market_data +0 -41
  113. data/bin/option_data +0 -44
  114. data/bin/place_combo_order +0 -58
  115. data/bin/place_order +0 -27
  116. data/bin/template +0 -18
  117. data/bin/tick_data +0 -26
  118. data/bin/time_and_sales +0 -53
@@ -1,5 +1,5 @@
1
- # The Futures module tries to guess the front month currency future using a crude algorithm
2
- # that does not take into account expiry/rollover day. This will be valid most of the time,
1
+ # The Futures module tries to guess the front month future using a crude algorithm that
2
+ # does not take into account expiry/rollover day. This will be valid most of the time,
3
3
  # but near/after expiry day the next quarter's contract takes over as the volume leader.
4
4
 
5
5
  module IB
@@ -8,7 +8,6 @@ module IB
8
8
  extend Symbols
9
9
 
10
10
  # Find the next front month of quarterly futures.
11
- #
12
11
  # N.B. This will not work as expected during the front month before expiration, as
13
12
  # it will point to the next quarter even though the current month is still valid!
14
13
  def self.next_quarter_month time=Time.now
@@ -1,4 +1,5 @@
1
- # Option contracts definitions
1
+ # Option contracts definitions.
2
+ # TODO: add next_expiry and other convenience from Futures module.
2
3
  module IB
3
4
  module Symbols
4
5
  module Options
@@ -1,4 +1,5 @@
1
- # Stock contracts definitions
1
+ # Frequently used stock contracts definitions
2
+ # TODO: auto-request :ContractDetails from IB if unknown symbol is requested?
2
3
  module IB
3
4
  module Symbols
4
5
  module Stocks
@@ -4,6 +4,8 @@ module IB
4
4
  class Bar < IB::Model
5
5
  include BaseProperties
6
6
 
7
+ has_one :contract # The bar represents timeseries info for this Contract
8
+
7
9
  prop :open, # The bar opening price.
8
10
  :high, # The high price during the time covered by the bar.
9
11
  :low, # The low price during the time covered by the bar.
@@ -17,11 +19,13 @@ module IB
17
19
  # determined by the reqHistoricalData() formatDate parameter.
18
20
  :has_gaps => :bool # Whether or not there are gaps in the data.
19
21
 
20
- validates_numericality_of :open, :high, :low, :close, :volume
22
+ validates_numericality_of :open, :high, :low, :close, :volume
21
23
 
22
24
  # Order comparison
23
25
  def == other
24
- time == other.time &&
26
+ super(other) ||
27
+ other.is_a?(self.class) &&
28
+ time == other.time &&
25
29
  open == other.open &&
26
30
  high == other.high &&
27
31
  low == other.low &&
@@ -87,11 +87,12 @@ module IB
87
87
 
88
88
  # Order comparison
89
89
  def == other
90
- other && other.is_a?(ComboLeg) &&
90
+ super(other) ||
91
+ other.is_a?(self.class) &&
91
92
  con_id == other.con_id &&
92
93
  ratio == other.ratio &&
93
- open_close == other.open_close &&
94
- short_sale_slot == other.short_sale_slot&&
94
+ open_close == other.open_close &&
95
+ short_sale_slot == other.short_sale_slot &&
95
96
  exempt_code == other.exempt_code &&
96
97
  side == other.side &&
97
98
  exchange == other.exchange &&
@@ -14,7 +14,7 @@ module IB
14
14
 
15
15
  :sec_type, # Security type. Valid values are: SECURITY_TYPES
16
16
 
17
- :sec_id, # Unique identifier of the given secIdType.
17
+ :sec_id => :sup, # Unique identifier of the given secIdType.
18
18
 
19
19
  :sec_id_type => :sup, # Security identifier, when querying contract details or
20
20
  # when placing orders. Supported identifiers are:
@@ -68,6 +68,8 @@ module IB
68
68
 
69
69
  has_many :orders # Placed for this Contract
70
70
 
71
+ has_many :bars # Possibly representing trading history for this Contract
72
+
71
73
  has_one :contract_detail # Volatile info about this Contract
72
74
 
73
75
  # For Contracts that are part of BAG
@@ -80,17 +82,17 @@ module IB
80
82
  alias legs combo_legs
81
83
  alias legs= combo_legs=
82
84
 
83
- alias combo_legs_description legs_description
85
+ alias combo_legs_description legs_description
84
86
  alias combo_legs_description= legs_description=
85
87
 
86
- # for Delta-Neutral Combo Contracts
87
- has_one :underlying
88
+ # for Delta-Neutral Combo Contracts
89
+ has_one :underlying
88
90
  alias under_comp underlying
89
91
  alias under_comp= underlying=
90
92
 
91
93
 
92
94
  ### Extra validations
93
- validates_inclusion_of :sec_type, :in => CODES[:sec_type].keys,
95
+ validates_inclusion_of :sec_type, :in => CODES[:sec_type].keys,
94
96
  :message => "should be valid security type"
95
97
 
96
98
  validates_format_of :expiry, :with => /^\d{6}$|^\d{8}$|^$/,
@@ -177,6 +179,8 @@ module IB
177
179
 
178
180
  # Contract comparison
179
181
  def == other
182
+ return true if super(other)
183
+
180
184
  return false unless other.is_a?(self.class)
181
185
 
182
186
  # Different sec_id_type
@@ -48,7 +48,7 @@ module IB
48
48
  :next_option_partial => :bool # # only if bond has embedded options.
49
49
 
50
50
  # Extra validations
51
- validates_format_of :time_zone, :with => /^\w{3}$/, :message => 'should be XXX'
51
+ validates_format_of :time_zone, :with => /^\w{3}$/, :message => 'should be XXX'
52
52
 
53
53
  belongs_to :contract
54
54
  alias summary contract
@@ -39,7 +39,9 @@ module IB
39
39
 
40
40
  # Comparison
41
41
  def == other
42
- perm_id == other.perm_id &&
42
+ super(other) ||
43
+ other.is_a?(self.class) &&
44
+ perm_id == other.perm_id &&
43
45
  local_id == other.local_id && # ((p __LINE__)||true) &&
44
46
  client_id == other.client_id &&
45
47
  exec_id == other.exec_id &&
@@ -348,26 +348,28 @@ module IB
348
348
 
349
349
  # Order comparison
350
350
  def == other
351
- perm_id && other.perm_id && perm_id == other.perm_id ||
352
- local_id == other.local_id && # ((p __LINE__)||true) &&
353
- (client_id == other.client_id || client_id == 0 || other.client_id == 0) &&
354
- parent_id == other.parent_id &&
355
- tif == other.tif &&
356
- action == other.action &&
357
- order_type == other.order_type &&
358
- quantity == other.quantity &&
359
- (limit_price == other.limit_price || # TODO Floats should be Decimals!
360
- (limit_price - other.limit_price).abs < 0.00001) &&
361
- aux_price == other.aux_price &&
362
- origin == other.origin &&
363
- designated_location == other.designated_location &&
364
- exempt_code == other.exempt_code &&
365
- what_if == other.what_if &&
366
- algo_strategy == other.algo_strategy &&
367
- algo_params == other.algo_params
368
-
369
- # TODO: || compare all attributes!
370
- end
351
+ super(other) ||
352
+ other.is_a?(self.class) &&
353
+ (perm_id && other.perm_id && perm_id == other.perm_id ||
354
+ local_id == other.local_id && # ((p __LINE__)||true) &&
355
+ (client_id == other.client_id || client_id == 0 || other.client_id == 0) &&
356
+ parent_id == other.parent_id &&
357
+ tif == other.tif &&
358
+ action == other.action &&
359
+ order_type == other.order_type &&
360
+ quantity == other.quantity &&
361
+ (limit_price == other.limit_price || # TODO Floats should be Decimals!
362
+ (limit_price - other.limit_price).abs < 0.00001) &&
363
+ aux_price == other.aux_price &&
364
+ origin == other.origin &&
365
+ designated_location == other.designated_location &&
366
+ exempt_code == other.exempt_code &&
367
+ what_if == other.what_if &&
368
+ algo_strategy == other.algo_strategy &&
369
+ algo_params == other.algo_params)
370
+
371
+ # TODO: compare more attributes!
372
+ end
371
373
 
372
374
  def to_s #human
373
375
  "<Order:" + instance_variables.map do |key|
@@ -57,7 +57,7 @@ module IB
57
57
  # (simulated orders) or an exchange (native orders) but that currently
58
58
  # the order is inactive due to system, exchange or other issues.
59
59
 
60
- validates_format_of :status, :without => /^$/, :message => 'must not be empty'
60
+ validates_format_of :status, :without => /^$/, :message => 'must not be empty'
61
61
  validates_numericality_of :price, :average_price, :allow_nil => true
62
62
  validates_numericality_of :local_id, :perm_id, :client_id, :parent_id, :filled,
63
63
  :remaining, :only_integer => true, :allow_nil => true
@@ -94,7 +94,9 @@ module IB
94
94
 
95
95
  # Comparison
96
96
  def == other
97
- other && other.is_a?(OrderState) &&
97
+
98
+ super(other) ||
99
+ other.is_a?(self.class) &&
98
100
  status == other.status &&
99
101
  local_id == other.local_id &&
100
102
  perm_id == other.perm_id &&
@@ -4,9 +4,6 @@ module IB
4
4
  class Underlying < IB::Model
5
5
  include BaseProperties
6
6
 
7
- attr_accessible :created_at, :updated_at
8
- attr_protected :id
9
-
10
7
  has_one :contract
11
8
 
12
9
  prop :con_id, # Id of the Underlying Contract
@@ -26,7 +23,9 @@ module IB
26
23
 
27
24
  # Comparison
28
25
  def == other
29
- con_id == other.con_id && delta == other.delta && price == other.price
26
+ super(other) ||
27
+ other.is_a?(self.class) &&
28
+ con_id == other.con_id && delta == other.delta && price == other.price
30
29
  end
31
30
 
32
31
  end # class Underlying
@@ -1,7 +1,7 @@
1
1
  ## RUNNING TEST SUITE:
2
2
 
3
- The gem comes with a spec suit that may be used to test ib-ruby compatibility
4
- with your specific TWS/Gateway installation. The test suit should be run ONLY
3
+ The gem comes with a spec suite that may be used to test ib-ruby compatibility
4
+ with your specific TWS/Gateway installation. The test suite should be run ONLY
5
5
  against your IB paper trading account. Running it against live account may result
6
6
  in financial losses.
7
7
 
@@ -15,7 +15,7 @@ to running tests, otherwise some tests will fail. Use 'bin/cancel_orders' script
15
15
  bulk cancelling of open orders before running tests as needed.
16
16
 
17
17
  By default, specs suppress logging output that is normally produced by IB::Connection.
18
- This may make it difficult to debug a failing spec. Following option will switch on verbose
18
+ This may make it difficult to debug a failing spec. The following option will switch on verbose
19
19
  output (both logger output and content of all received IB messages is dumped). Do not use
20
20
  this mode to run a whole spec - you will be swamped! Use it to debug specific failing specs
21
21
  only:
@@ -53,22 +53,24 @@ To run specs with Dummy Rails application, use:
53
53
  $ rspec -rdummy rails_spec
54
54
  $ rspec -rdummy [spec/specific_spec.rb]
55
55
 
56
- Other suit switches described in previous section should work with Rails as well.
56
+ Other suite switches described in previous section should work with Rails as well.
57
57
 
58
58
  ## PROBLEMS WHILE RUNNING THE SPECS:
59
59
 
60
- Some of the specs may randomly fail from time to time when you are running the spec suit
60
+ Some of the specs may randomly fail from time to time when you are running the spec suite
61
61
  against your IB paper account. This happens because these specs depend on live connection
62
62
  to IB, which is inherently non-deterministic. Anything happening along the way - network
63
63
  delay, problems with IB data farms, even high CPU load on your machine - may delay the
64
- expected responce, so that the spec times out or does not find expected data. For example,
64
+ expected response, so that the spec times out or does not find expected data. For example,
65
65
  IB historical data farm is known to disappear from time to time, so any specs related to
66
66
  historical data will fail while this outage lasts.
67
67
 
68
68
  If you experience such intermittent spec failures, it is recommended that you run the
69
- failing specs several times, possibly with a delay of 10-20 minutes. Start debugging
70
- the specs only if they are failing regularly. Otherwise, you may just waste time chasing
71
- an artifact of unreliable IB connection, rather than some real problem with the specs.
69
+ failing specs several times, possibly with a delay of 10-20 minutes. Sometimes it helps
70
+ to restart your TWS or Gateway, as it may be stuck in inconsistent state, preventing
71
+ test suite from running properly. Start debugging the specs only if they are failing
72
+ regularly. Otherwise, you may just waste time chasing an artifact of unreliable IB
73
+ connection, rather than some real problem with the specs.
72
74
 
73
75
  # WRITING YOUR OWN INTEGRATION SPECS
74
76
 
@@ -112,7 +114,7 @@ You can easily create your own integration specs. Pattern for writing specs is l
112
114
  messages from and log entries. If your do not do this, your examples become coupled.
113
115
 
114
116
  11. If you want to see exactly what's going on inside ib-ruby while your examples are
115
- running, run your specs with '-rv' option to switch on verbose outpset mode.
117
+ running, run your specs with '-rv' option to switch on verbose output mode.
116
118
  Now you will see all the messages received and log entries made as as result of
117
119
  your examples running. Be warned, output is very verbose, so don't run big chunk of
118
120
  specs with -rv option or you will be swamped!.
@@ -45,5 +45,15 @@ describe IB::Symbols do
45
45
  fx.description.should == "British Pounds"
46
46
  end
47
47
 
48
+ it 'raises an error if requested contract symbol is not defined' do
49
+ expect {stk = IB::Symbols::Stocks[:xyz]}.
50
+ to raise_error "Unknown symbol :xyz, please pre-define it in lib/ib/symbols/stocks.rb"
51
+ expect {opt = IB::Symbols::Options[:xyz20]}.
52
+ to raise_error "Unknown symbol :xyz20, please pre-define it in lib/ib/symbols/options.rb"
53
+ expect {fx = IB::Symbols::Forex[:abcdef]}.
54
+ to raise_error "Unknown symbol :abcdef, please pre-define it in lib/ib/symbols/forex.rb"
55
+ expect {fut = IB::Symbols::Futures[:abc]}.
56
+ to raise_error "Unknown symbol :abc, please pre-define it in lib/ib/symbols/futures.rb"
57
+ end
48
58
 
49
59
  end # describe IB::Symbols
@@ -9,7 +9,7 @@ shared_examples_for 'Received Market Data' do
9
9
  it { should be_warning }
10
10
  it { should_not be_error }
11
11
  its(:code) { should be_an Integer }
12
- its(:message) { should =~ /Market data farm connection is OK/ }
12
+ its(:message) { should =~ /data farm connection is OK/ }
13
13
  its(:to_human) { should =~ /TWS Warning/ }
14
14
  end
15
15
 
@@ -71,14 +71,14 @@ def buy_sell_assigns
71
71
  {['BOT', 'BUY', 'Buy', 'buy', :BUY, :BOT, :Buy, :buy, 'B', :b] => :buy,
72
72
  ['SELL', 'SLD', 'Sel', 'sell', :SELL, :SLD, :Sell, :sell, 'S', :S] => :sell,
73
73
  [1, nil, 'ASK', :foo] => /should be buy.sell/
74
- }
74
+ }
75
75
  end
76
76
 
77
77
  def buy_sell_short_assigns
78
78
  buy_sell_assigns.merge(
79
- ['SSHORT', 'Short', 'short', :SHORT, :short, 'T', :T] => :short,
80
- ['SSHORTX', 'Shortextemt', 'shortx', :short_exempt, 'X', :X] => :short_exempt,
81
- [1, nil, 'ASK', :foo] => /should be buy.sell.short/)
79
+ ['SSHORT', 'Short', 'short', :SHORT, :short, 'T', :T] => :short,
80
+ ['SSHORTX', 'Shortextemt', 'shortx', :short_exempt, 'X', :X] => :short_exempt,
81
+ [1, nil, 'ASK', :foo] => /should be buy.sell.short/)
82
82
  end
83
83
 
84
84
  def test_assigns cases, prop, name
@@ -96,7 +96,7 @@ def test_assigns cases, prop, name
96
96
 
97
97
  it "#{prop} = #{value.inspect} #=> raises #{result}" do
98
98
  expect { subject.send "#{prop}=", value }.
99
- to raise_error result
99
+ to raise_error result
100
100
  end
101
101
 
102
102
  when Regexp # ... Non-exceptional error, making model invalid
@@ -106,7 +106,7 @@ def test_assigns cases, prop, name
106
106
  expect { subject.send "#{prop}=", value }.to_not raise_error
107
107
 
108
108
  subject.valid? # just triggers validation
109
- #pp subject.errors.messages
109
+ #pp subject.errors.messages
110
110
 
111
111
  subject.errors.messages.should have_key name
112
112
  subject.should be_invalid
@@ -198,7 +198,7 @@ shared_examples_for 'Model instantiated empty' do
198
198
 
199
199
  it 'sets all properties to defaults' do
200
200
  subject.default_attributes.each do |name, value|
201
- #p name, value
201
+ # p name, subject.send(name), value
202
202
  case value
203
203
  when Time
204
204
  subject.send(name).should be_a Time
@@ -216,8 +216,9 @@ shared_examples_for 'Model instantiated with properties' do
216
216
  let(:init_with_props?) { true }
217
217
 
218
218
  it 'auto-assigns all properties given to initializer' do
219
+ # p subject
219
220
  props.each do |name, value|
220
- #p subject, name, value
221
+ # p name, subject.send(name), value
221
222
  subject.send(name).should == value
222
223
  end
223
224
  end
@@ -1,31 +1,32 @@
1
1
  require 'model_helper'
2
2
 
3
3
  describe IB::ComboLeg,
4
- :props =>
5
- {:con_id => 81032967,
6
- :ratio => 2,
7
- :side => :buy,
8
- :exchange => 'CBOE',
9
- :open_close => :open,
10
- :short_sale_slot => :broker,
11
- :designated_location => nil,
12
- :exempt_code => -1},
13
-
14
- :human => "<ComboLeg: buy 2 con_id 81032967 at CBOE>",
15
-
16
- :errors => {:ratio => ["is not a number"],
17
- :side => ["should be buy/sell/short"]},
18
-
19
- :assigns =>
20
- {:open_close => open_close_assigns,
21
- :side => buy_sell_short_assigns,
22
- :designated_location =>
23
- {[42, 'FOO', :bar] => /should be blank or orders will be rejected/},
24
- },
25
-
26
- :aliases =>
27
- {[:side, :action] => buy_sell_short_assigns,
28
- } do
4
+ :props =>
5
+ {:con_id => 81032967,
6
+ :ratio => 2,
7
+ :side => :buy,
8
+ :exchange => 'CBOE',
9
+ :open_close => :open,
10
+ :short_sale_slot => :broker,
11
+ :designated_location => '',
12
+ :exempt_code => -1},
13
+
14
+ :human => "<ComboLeg: buy 2 con_id 81032967 at CBOE>",
15
+
16
+ :errors => {:ratio => ["is not a number"],
17
+ :side => ["should be buy/sell/short"]},
18
+
19
+ :assigns =>
20
+ {:open_close => open_close_assigns,
21
+ :side => buy_sell_short_assigns,
22
+ :short_sale_slot => codes_and_values_for(:short_sale_slot),
23
+ :designated_location =>
24
+ {[42, 'FOO', :bar] => /should be blank or orders will be rejected/},
25
+ },
26
+
27
+ :aliases =>
28
+ {[:side, :action] => buy_sell_short_assigns,
29
+ } do
29
30
 
30
31
  it 'has combined weight accessor' do
31
32
  leg = IB::ComboLeg.new props
@@ -49,7 +50,7 @@ describe IB::ComboLeg,
49
50
 
50
51
  it "serializes extended" do
51
52
  subject.serialize(:extended).should ==
52
- [81032967, 2, "BUY", "CBOE", 1, 1, nil, -1]
53
+ [81032967, 2, "BUY", "CBOE", 1, 1, '', -1]
53
54
  end
54
55
  end #serialization
55
56
 
@@ -115,8 +116,8 @@ describe IB::ComboLeg,
115
116
 
116
117
  @combo.leg_contracts << @google
117
118
  @combo.leg_contracts.should include @google
118
- p @combo.valid?
119
- p @combo.save
119
+ @combo.valid?.should be_true
120
+ @combo.save.should be_true
120
121
 
121
122
  #combo.legs.should_not be_empty
122
123
  @combo.leg_contracts.should include @google