ib-ruby 0.8.1 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -1
- data/HISTORY +5 -0
- data/README.md +47 -53
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/app/assets/javascripts/ib/application.js +15 -0
- data/app/assets/javascripts/ib/underlyings.js +2 -0
- data/app/assets/stylesheets/ib/application.css +13 -0
- data/app/assets/stylesheets/ib/underlyings.css +4 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/ib/application_controller.rb +5 -0
- data/app/controllers/ib/underlyings_controller.rb +87 -0
- data/app/helpers/ib/application_helper.rb +4 -0
- data/app/helpers/ib/underlyings_helper.rb +4 -0
- data/app/models/ib/underlying.rb +5 -0
- data/app/views/ib/underlyings/_form.html.erb +33 -0
- data/app/views/ib/underlyings/edit.html.erb +6 -0
- data/app/views/ib/underlyings/index.html.erb +29 -0
- data/app/views/ib/underlyings/new.html.erb +5 -0
- data/app/views/ib/underlyings/show.html.erb +25 -0
- data/app/views/layouts/ib/application.html.erb +14 -0
- data/config/routes.rb +6 -0
- data/db/config.yml +19 -0
- data/db/migrate/{101_add_executions.rb → 101_add_ib_executions.rb} +2 -2
- data/db/migrate/{111_add_bars.rb → 111_add_ib_bars.rb} +2 -2
- data/db/migrate/{121_add_order_states.rb → 121_add_ib_order_states.rb} +2 -2
- data/db/migrate/{131_add_orders.rb → 131_add_ib_orders.rb} +2 -2
- data/db/migrate/{141_add_combo_legs.rb → 141_add_ib_combo_legs.rb} +2 -2
- data/db/migrate/{151_add_underlyings.rb → 151_add_ib_underlyings.rb} +2 -2
- data/db/migrate/{161_add_contract_details.rb → 161_add_ib_contract_details.rb} +2 -2
- data/db/migrate/{171_add_contracts.rb → 171_add_ib_contracts.rb} +2 -2
- data/db/schema.rb +245 -0
- data/lib/ib/base.rb +97 -0
- data/lib/ib/base_properties.rb +140 -0
- data/lib/{ib-ruby → ib}/connection.rb +2 -2
- data/lib/{ib-ruby → ib}/constants.rb +0 -0
- data/lib/{ib-ruby → ib}/db.rb +9 -5
- data/lib/ib/engine.rb +35 -0
- data/lib/{ib-ruby → ib}/errors.rb +0 -0
- data/lib/{ib-ruby → ib}/extensions.rb +2 -2
- data/lib/{ib-ruby → ib}/logger.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/abstract_message.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/abstract_message.rb +1 -1
- data/lib/{ib-ruby → ib}/messages/incoming/alert.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/contract_data.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/delta_neutral_validation.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/execution_data.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/historical_data.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/market_depths.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/next_valid_id.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/open_order.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/order_status.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/portfolio_value.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/real_time_bar.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/scanner_data.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/ticks.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming.rb +14 -14
- data/lib/{ib-ruby → ib}/messages/outgoing/abstract_message.rb +1 -1
- data/lib/{ib-ruby → ib}/messages/outgoing/bar_requests.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/outgoing/place_order.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/outgoing.rb +5 -5
- data/lib/ib/messages.rb +8 -0
- data/lib/ib/model.rb +8 -0
- data/lib/ib/models.rb +10 -0
- data/lib/ib/requires.rb +9 -0
- data/lib/{ib-ruby → ib}/socket.rb +0 -0
- data/lib/{ib-ruby → ib}/symbols/forex.rb +1 -1
- data/lib/{ib-ruby → ib}/symbols/futures.rb +2 -2
- data/lib/{ib-ruby → ib}/symbols/options.rb +1 -1
- data/lib/{ib-ruby → ib}/symbols/stocks.rb +1 -1
- data/lib/ib/symbols.rb +9 -0
- data/lib/{ib-ruby → ib}/version.rb +0 -0
- data/lib/ib-ruby.rb +2 -24
- data/lib/ib.rb +23 -0
- data/lib/models/ib/bag.rb +51 -0
- data/lib/models/ib/bar.rb +41 -0
- data/lib/models/ib/combo_leg.rb +102 -0
- data/lib/models/ib/contract.rb +287 -0
- data/lib/models/ib/contract_detail.rb +68 -0
- data/lib/models/ib/execution.rb +62 -0
- data/lib/models/ib/option.rb +60 -0
- data/lib/models/ib/order.rb +389 -0
- data/lib/models/ib/order_state.rb +126 -0
- data/lib/models/ib/underlying.rb +35 -0
- data/spec/README.md +34 -2
- data/spec/TODO +5 -1
- data/spec/comb.rb +13 -0
- data/spec/db.rb +1 -1
- data/spec/db_helper.rb +3 -3
- data/spec/dummy.rb +13 -0
- data/spec/gw.rb +4 -0
- data/spec/{ib-ruby → ib}/connection_spec.rb +0 -0
- data/spec/{ib-ruby → ib}/messages/incoming/alert_spec.rb +0 -0
- data/spec/{ib-ruby → ib}/messages/incoming/open_order_spec.rb +0 -0
- data/spec/{ib-ruby → ib}/messages/incoming/order_status_spec.rb +16 -17
- data/spec/{ib-ruby → ib}/messages/outgoing/account_data_spec.rb +0 -0
- data/spec/{ib-ruby → ib}/messages/outgoing/market_data_type_spec.rb +0 -0
- data/spec/integration/historic_data_spec.rb +3 -3
- data/spec/integration/orders/trades_spec.rb +1 -1
- data/spec/{ib-ruby/models → models/ib}/bag_spec.rb +2 -7
- data/spec/{ib-ruby/models → models/ib}/bar_spec.rb +1 -6
- data/spec/{ib-ruby/models → models/ib}/combo_leg_spec.rb +2 -12
- data/spec/{ib-ruby/models → models/ib}/contract_detail_spec.rb +3 -8
- data/spec/{ib-ruby/models → models/ib}/contract_spec.rb +4 -12
- data/spec/{ib-ruby/models → models/ib}/execution_spec.rb +2 -7
- data/spec/{ib-ruby/models → models/ib}/option_spec.rb +1 -6
- data/spec/{ib-ruby/models → models/ib}/order_spec.rb +5 -10
- data/spec/{ib-ruby/models → models/ib}/order_state_spec.rb +2 -7
- data/spec/{ib-ruby/models → models/ib}/underlying_spec.rb +3 -7
- data/spec/my.rb +5 -0
- data/spec/spec_helper.rb +62 -36
- metadata +417 -544
- data/lib/ib-ruby/messages.rb +0 -8
- data/lib/ib-ruby/models/bag.rb +0 -54
- data/lib/ib-ruby/models/bar.rb +0 -43
- data/lib/ib-ruby/models/combo_leg.rb +0 -104
- data/lib/ib-ruby/models/contract.rb +0 -287
- data/lib/ib-ruby/models/contract_detail.rb +0 -70
- data/lib/ib-ruby/models/execution.rb +0 -64
- data/lib/ib-ruby/models/model.rb +0 -105
- data/lib/ib-ruby/models/model_properties.rb +0 -146
- data/lib/ib-ruby/models/option.rb +0 -62
- data/lib/ib-ruby/models/order.rb +0 -389
- data/lib/ib-ruby/models/order_state.rb +0 -128
- data/lib/ib-ruby/models/underlying.rb +0 -36
- data/lib/ib-ruby/models.rb +0 -15
- data/lib/ib-ruby/symbols.rb +0 -9
- data/spec/test.rb +0 -61
@@ -0,0 +1,126 @@
|
|
1
|
+
module IB
|
2
|
+
|
3
|
+
# OrderState represents dynamic (changeable) info about a single Order,
|
4
|
+
# isolating these changes and making Order essentially immutable
|
5
|
+
class OrderState < IB::Model
|
6
|
+
include BaseProperties
|
7
|
+
|
8
|
+
#p column_names
|
9
|
+
belongs_to :order
|
10
|
+
|
11
|
+
# Properties arriving via OpenOrder message
|
12
|
+
prop :init_margin, # Float: The impact the order would have on your initial margin.
|
13
|
+
:maint_margin, # Float: The impact the order would have on your maintenance margin.
|
14
|
+
:equity_with_loan, # Float: The impact the order would have on your equity
|
15
|
+
:commission, # double: Shows the commission amount on the order.
|
16
|
+
:min_commission, # The possible min range of the actual order commission.
|
17
|
+
:max_commission, # The possible max range of the actual order commission.
|
18
|
+
:commission_currency, # String: Shows the currency of the commission.
|
19
|
+
:warning_text # String: Displays a warning message if warranted.
|
20
|
+
|
21
|
+
# Properties arriving via OrderStatus message:
|
22
|
+
prop :filled, # int
|
23
|
+
:remaining, # int
|
24
|
+
[:price, :last_fill_price,], # double
|
25
|
+
[:average_price, :average_fill_price], # double
|
26
|
+
:why_held # String: comma-separated list of reasons for order to be held.
|
27
|
+
|
28
|
+
# Properties arriving in both messages:
|
29
|
+
prop :local_id, # int: Order id associated with client (volatile).
|
30
|
+
:perm_id, # int: TWS permanent id, remains the same over TWS sessions.
|
31
|
+
:client_id, # int: The id of the client that placed this order.
|
32
|
+
:parent_id, # int: The order ID of the parent (original) order, used
|
33
|
+
:status => :s # String: Displays the order status. Possible values include:
|
34
|
+
# - PendingSubmit - indicates that you have transmitted the order, but
|
35
|
+
# have not yet received confirmation that it has been accepted by the
|
36
|
+
# order destination. NOTE: This order status is NOT sent back by TWS
|
37
|
+
# and should be explicitly set by YOU when an order is submitted.
|
38
|
+
# - PendingCancel - indicates that you have sent a request to cancel
|
39
|
+
# the order but have not yet received cancel confirmation from the
|
40
|
+
# order destination. At this point, your order cancel is not confirmed.
|
41
|
+
# You may still receive an execution while your cancellation request
|
42
|
+
# is pending. NOTE: This order status is not sent back by TWS and
|
43
|
+
# should be explicitly set by YOU when an order is canceled.
|
44
|
+
# - PreSubmitted - indicates that a simulated order type has been
|
45
|
+
# accepted by the IB system and that this order has yet to be elected.
|
46
|
+
# The order is held in the IB system until the election criteria are
|
47
|
+
# met. At that time the order is transmitted to the order destination
|
48
|
+
# as specified.
|
49
|
+
# - Submitted - indicates that your order has been accepted at the order
|
50
|
+
# destination and is working.
|
51
|
+
# - Cancelled - indicates that the balance of your order has been
|
52
|
+
# confirmed canceled by the IB system. This could occur unexpectedly
|
53
|
+
# when IB or the destination has rejected your order.
|
54
|
+
# - ApiCancelled - canceled via API
|
55
|
+
# - Filled - indicates that the order has been completely filled.
|
56
|
+
# - Inactive - indicates that the order has been accepted by the system
|
57
|
+
# (simulated orders) or an exchange (native orders) but that currently
|
58
|
+
# the order is inactive due to system, exchange or other issues.
|
59
|
+
|
60
|
+
validates_format_of :status, :without => /^$/, :message => 'must not be empty'
|
61
|
+
validates_numericality_of :price, :average_price, :allow_nil => true
|
62
|
+
validates_numericality_of :local_id, :perm_id, :client_id, :parent_id, :filled,
|
63
|
+
:remaining, :only_integer => true, :allow_nil => true
|
64
|
+
|
65
|
+
## Testing Order state:
|
66
|
+
|
67
|
+
def new?
|
68
|
+
status.empty? || status == 'New'
|
69
|
+
end
|
70
|
+
|
71
|
+
# Order is in a valid, working state on TWS side
|
72
|
+
def submitted?
|
73
|
+
status == 'PreSubmitted' || status == 'Submitted'
|
74
|
+
end
|
75
|
+
|
76
|
+
# Order is in a valid, working state on TWS side
|
77
|
+
def pending?
|
78
|
+
submitted? || status == 'PendingSubmit'
|
79
|
+
end
|
80
|
+
|
81
|
+
# Order is in invalid state
|
82
|
+
def active?
|
83
|
+
new? || pending?
|
84
|
+
end
|
85
|
+
|
86
|
+
# Order is in invalid state
|
87
|
+
def inactive?
|
88
|
+
!active? # status == 'Inactive'
|
89
|
+
end
|
90
|
+
|
91
|
+
def complete_fill?
|
92
|
+
status == 'Filled' && remaining == 0 # filled >= total_quantity # Manually corrected
|
93
|
+
end
|
94
|
+
|
95
|
+
# Comparison
|
96
|
+
def == other
|
97
|
+
other && other.is_a?(OrderState) &&
|
98
|
+
status == other.status &&
|
99
|
+
local_id == other.local_id &&
|
100
|
+
perm_id == other.perm_id &&
|
101
|
+
client_id == other.client_id &&
|
102
|
+
filled == other.filled &&
|
103
|
+
remaining == other.remaining &&
|
104
|
+
last_fill_price == other.last_fill_price &&
|
105
|
+
init_margin == other.init_margin &&
|
106
|
+
maint_margin == other.maint_margin &&
|
107
|
+
equity_with_loan == other.equity_with_loan &&
|
108
|
+
why_held == other.why_held &&
|
109
|
+
warning_text == other.warning_text &&
|
110
|
+
commission == other.commission
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_human
|
114
|
+
"<OrderState: #{status} ##{local_id}/#{perm_id} from #{client_id}" +
|
115
|
+
(filled ? " filled #{filled}/#{remaining}" : '') +
|
116
|
+
(last_fill_price ? " at #{last_fill_price}/#{average_fill_price}" : '') +
|
117
|
+
(init_margin ? " margin #{init_margin}/#{maint_margin}" : '') +
|
118
|
+
(equity_with_loan ? " equity #{equity_with_loan}" : '') +
|
119
|
+
(commission && commission > 0 ? " fee #{commission}" : "") +
|
120
|
+
(why_held ? " why_held #{why_held}" : '') +
|
121
|
+
((warning_text && warning_text != '') ? " warning #{warning_text}" : '') + ">"
|
122
|
+
end
|
123
|
+
|
124
|
+
alias to_s to_human
|
125
|
+
end # class Order
|
126
|
+
end # module IB
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module IB
|
2
|
+
|
3
|
+
# Calculated characteristics of underlying Contract (volatile)
|
4
|
+
class Underlying < IB::Model
|
5
|
+
include BaseProperties
|
6
|
+
|
7
|
+
attr_accessible :created_at, :updated_at
|
8
|
+
attr_protected :id
|
9
|
+
|
10
|
+
has_one :contract
|
11
|
+
|
12
|
+
prop :con_id, # Id of the Underlying Contract
|
13
|
+
:delta, # double: The underlying stock or future delta.
|
14
|
+
:price # double: The price of the underlying.
|
15
|
+
|
16
|
+
validates_numericality_of :con_id, :delta, :price #, :allow_nil => true
|
17
|
+
|
18
|
+
def default_attributes
|
19
|
+
super.merge :con_id => 0
|
20
|
+
end
|
21
|
+
|
22
|
+
# Serialize under_comp parameters
|
23
|
+
def serialize
|
24
|
+
[true, con_id, delta, price]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Comparison
|
28
|
+
def == other
|
29
|
+
con_id == other.con_id && delta == other.delta && price == other.price
|
30
|
+
end
|
31
|
+
|
32
|
+
end # class Underlying
|
33
|
+
UnderComp = Underlying
|
34
|
+
|
35
|
+
end # module IB
|
data/spec/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
## RUNNING
|
1
|
+
## RUNNING TEST SUITE:
|
2
2
|
|
3
3
|
The gem comes with a spec suit that may be used to test ib-ruby compatibility
|
4
4
|
with your specific TWS/Gateway installation. The test suit should be run ONLY
|
@@ -28,10 +28,42 @@ with database backend, use:
|
|
28
28
|
$ rspec -rdb [spec/specific_spec.rb]
|
29
29
|
|
30
30
|
If you run your specs against both Gateway and TWS, you may want to use the following
|
31
|
-
|
31
|
+
switches (by default, TWS port is used):
|
32
32
|
|
33
|
+
$ rspec -rgw [spec/specific_spec.rb]
|
33
34
|
$ rspec -rtws [spec/specific_spec.rb]
|
34
35
|
|
36
|
+
Some of the specs may randomly fail from time to time when you are running the spec suit
|
37
|
+
against your IB paper account. This happens because these specs depend on live connection
|
38
|
+
to IB, which is inherently non-deterministic. Anything happening along the way - network
|
39
|
+
delay, problems with IB data farms, even high CPU load on your machine - may delay the
|
40
|
+
expected responce, so that the spec times out or does not find expected data. It is
|
41
|
+
suggested that you run the failing specs several times, and start debugging them only
|
42
|
+
if they are failing regularly. Otherwise, you may just waste time chasing an artifact of
|
43
|
+
unreliable IB connection, rather than some real problem with the specs.
|
44
|
+
|
45
|
+
## RUNNING RAILS-SPECIFIC SPECS:
|
46
|
+
|
47
|
+
This gem has two operating modes: standalone and Rails-engine. If you require it in a
|
48
|
+
Rails environment, it loads Rails engine automatically. Otherwise, it does not load any
|
49
|
+
Rails integration. So, Rails-specific specs are separated from generic spec suite and
|
50
|
+
located in 'rails_spec'.
|
51
|
+
|
52
|
+
There are two included Rails apps that can be used to test engine integration. One is
|
53
|
+
an auto-generated Dummy app, and another is [Combustion](https://github.com/freelancing-god/combustion) based.
|
54
|
+
|
55
|
+
To test Rails engine integration with Combustion-based Rails application, use:
|
56
|
+
|
57
|
+
$ rspec -rcomb rails_spec
|
58
|
+
$ rspec -rcomb [spec/specific_spec.rb]
|
59
|
+
|
60
|
+
To run specs with Dummy Rails application, use:
|
61
|
+
|
62
|
+
$ rspec -rdummy rails_spec
|
63
|
+
$ rspec -rdummy [spec/specific_spec.rb]
|
64
|
+
|
65
|
+
Other suit switches described in previous section should work with Rails as well.
|
66
|
+
|
35
67
|
# WRITING YOUR OWN INTEGRATION SPECS
|
36
68
|
|
37
69
|
You can easily create your own integration specs. Pattern for writing specs is like this:
|
data/spec/TODO
CHANGED
data/spec/comb.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
puts 'To run specs with Combustion-based Rails app, use:'
|
2
|
+
puts '$ rspec -rcomb rails_spec'
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'combustion'
|
6
|
+
require 'backports/1.9.2' if RUBY_VERSION =~ /1.8/
|
7
|
+
require 'ib'
|
8
|
+
|
9
|
+
Combustion.path = 'rails_spec/combustion'
|
10
|
+
Combustion.initialize!
|
11
|
+
|
12
|
+
require 'rspec/rails'
|
13
|
+
|
data/spec/db.rb
CHANGED
data/spec/db_helper.rb
CHANGED
@@ -81,7 +81,7 @@ shared_examples_for 'Model with associations' do
|
|
81
81
|
subject_name_plural = described_class.to_s.demodulize.tableize
|
82
82
|
|
83
83
|
associations.each do |name, item_props|
|
84
|
-
item = "IB
|
84
|
+
item = "IB::#{name.to_s.classify}".constantize.new item_props
|
85
85
|
#item = const_get("IB::#{name.to_s.classify}").new item_props
|
86
86
|
puts "Testing single association #{name}"
|
87
87
|
subject.association(name).reflection.should_not be_collection
|
@@ -119,7 +119,7 @@ shared_examples_for 'Model with associations' do
|
|
119
119
|
subject.association(name).reflection.should be_collection
|
120
120
|
|
121
121
|
[items].flatten.each do |item_props|
|
122
|
-
item = "IB
|
122
|
+
item = "IB::#{name.to_s.classify}".constantize.new item_props
|
123
123
|
#item = item_class.new item_props
|
124
124
|
association = subject.send name #, :reload
|
125
125
|
|
@@ -139,7 +139,7 @@ shared_examples_for 'Model with associations' do
|
|
139
139
|
subject.save
|
140
140
|
|
141
141
|
[items].flatten.each do |item_props|
|
142
|
-
item = "IB
|
142
|
+
item = "IB::#{name.to_s.classify}".constantize.new item_props
|
143
143
|
association = subject.send name #, :reload
|
144
144
|
|
145
145
|
association.should include item
|
data/spec/dummy.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
puts 'To run specs with dummy Rails app, use:'
|
2
|
+
puts '$ rspec -rdummy rails_spec'
|
3
|
+
|
4
|
+
# Configure Rails Environment
|
5
|
+
ENV["RAILS_ENV"] = "test"
|
6
|
+
|
7
|
+
require File.expand_path("../../rails_spec/dummy/config/environment.rb", __FILE__)
|
8
|
+
|
9
|
+
require 'rspec/rails'
|
10
|
+
require 'capybara/rails'
|
11
|
+
require 'capybara/dsl'
|
12
|
+
|
13
|
+
Rails.backtrace_cleaner.remove_silencers!
|
data/spec/gw.rb
ADDED
File without changes
|
File without changes
|
File without changes
|
@@ -9,7 +9,7 @@ shared_examples_for 'OrderStatus message' do
|
|
9
9
|
its(:local_id) { should be_an Integer }
|
10
10
|
its(:status) { should =~ /Submit/ }
|
11
11
|
its(:to_human) { should =~
|
12
|
-
|
12
|
+
/<OrderStatus: <OrderState: .*Submit.* #\d+\/\d+ from 1111 filled 0\/100/ }
|
13
13
|
|
14
14
|
it 'has proper order_state accessor' do
|
15
15
|
os = subject.order_state
|
@@ -38,18 +38,17 @@ describe IB::Messages::Incoming::OrderStatus do
|
|
38
38
|
context 'Instantiated with data Hash' do
|
39
39
|
subject do
|
40
40
|
IB::Messages::Incoming::OrderStatus.new :version => 6,
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
41
|
+
:order_state => { :local_id => 1313,
|
42
|
+
:perm_id => 172323928,
|
43
|
+
:client_id => 1111,
|
44
|
+
:parent_id => 0,
|
45
|
+
:status => 'PreSubmitted',
|
46
|
+
:filled => 0,
|
47
|
+
:remaining => 100,
|
48
|
+
:average_fill_price => 0.0,
|
49
|
+
:last_fill_price => 0.0,
|
50
|
+
:why_held => 'child' }
|
51
|
+
end
|
53
52
|
|
54
53
|
it_behaves_like 'OrderStatus message'
|
55
54
|
end
|
@@ -58,15 +57,15 @@ describe IB::Messages::Incoming::OrderStatus do
|
|
58
57
|
before(:all) do
|
59
58
|
verify_account
|
60
59
|
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
61
|
-
@ib.wait_for :NextValidId
|
62
|
-
|
60
|
+
@ib.wait_for :NextValidId, 3
|
61
|
+
@local_id = @ib.next_local_id
|
63
62
|
place_order IB::Symbols::Stocks[:wfc]
|
64
|
-
@ib.wait_for
|
63
|
+
@ib.wait_for 2 # OrderStatus for cancelled orders from previous specs arrives first :(
|
65
64
|
end
|
66
65
|
|
67
66
|
after(:all) { close_connection } # implicitly cancels order
|
68
67
|
|
69
|
-
subject { @ib.received[:OrderStatus].
|
68
|
+
subject { @ib.received[:OrderStatus].find { |msg| msg.local_id == @local_id } }
|
70
69
|
|
71
70
|
it_behaves_like 'OrderStatus message'
|
72
71
|
end
|
File without changes
|
File without changes
|
@@ -2,7 +2,7 @@ require 'integration_helper'
|
|
2
2
|
|
3
3
|
describe 'Request Historic Data', :connected => true, :integration => true do
|
4
4
|
|
5
|
-
CORRECT_OPTS = {:id =>
|
5
|
+
CORRECT_OPTS = {:id => 567,
|
6
6
|
:contract => IB::Symbols::Stocks[:wfc],
|
7
7
|
:end_date_time => Time.now.to_ib,
|
8
8
|
:duration => '1 D',
|
@@ -37,7 +37,7 @@ describe 'Request Historic Data', :connected => true, :integration => true do
|
|
37
37
|
before(:all) do
|
38
38
|
# No historical data for GBP/CASH@IDEALPRO
|
39
39
|
@ib.send_message :RequestHistoricalData, CORRECT_OPTS
|
40
|
-
@ib.wait_for :HistoricalData,
|
40
|
+
@ib.wait_for :HistoricalData, 6 # sec
|
41
41
|
end
|
42
42
|
|
43
43
|
subject { @ib.received[:HistoricalData].last }
|
@@ -45,7 +45,7 @@ describe 'Request Historic Data', :connected => true, :integration => true do
|
|
45
45
|
it { @ib.received[:HistoricalData].should have_at_least(1).historic_data }
|
46
46
|
|
47
47
|
it { should be_an IB::Messages::Incoming::HistoricalData }
|
48
|
-
its(:request_id) { should ==
|
48
|
+
its(:request_id) { should == 567 }
|
49
49
|
its(:count) { should be_an Integer }
|
50
50
|
its(:start_date) { should =~ /\d{8} *\d\d:\d\d:\d\d/ } # "20120302 22:46:42"
|
51
51
|
its(:end_date) { should =~ /\d{8} *\d\d:\d\d:\d\d/ }
|
@@ -32,7 +32,7 @@ def execution_should_be side, opts={}
|
|
32
32
|
exec.local_id.should == @order.local_id if @order
|
33
33
|
exec.exec_id.should be_a String
|
34
34
|
exec.time.should =~ /\d\d:\d\d:\d\d/
|
35
|
-
exec.account_name.should == OPTS[:connection][:
|
35
|
+
exec.account_name.should == OPTS[:connection][:account]
|
36
36
|
exec.exchange.should == 'IDEALPRO'
|
37
37
|
exec.side.should == side
|
38
38
|
exec.shares.should == 20000
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'model_helper'
|
2
2
|
|
3
|
-
describe IB::
|
3
|
+
describe IB::Bag,
|
4
4
|
|
5
5
|
:props =>
|
6
6
|
{:symbol => 'GOOG',
|
@@ -41,16 +41,11 @@ describe IB::Models::Bag,
|
|
41
41
|
[:symbol, :local_symbol] => string_assigns,
|
42
42
|
|
43
43
|
:multiplier => to_i_assigns,
|
44
|
-
} do
|
44
|
+
} do
|
45
45
|
|
46
46
|
it_behaves_like 'Model with valid defaults'
|
47
47
|
it_behaves_like 'Self-equal Model'
|
48
48
|
|
49
|
-
it 'has class name shortcut' do
|
50
|
-
IB::Bag.should == IB::Models::Bag
|
51
|
-
IB::Bag.new.should == IB::Models::Bag.new
|
52
|
-
end
|
53
|
-
|
54
49
|
context 'properly initiated' do
|
55
50
|
subject { IB::Bag.new props }
|
56
51
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'model_helper'
|
2
2
|
|
3
|
-
describe IB::
|
3
|
+
describe IB::Bar,
|
4
4
|
:props =>
|
5
5
|
{:open => 1.31,
|
6
6
|
:high => 1.35,
|
@@ -33,9 +33,4 @@ describe IB::Models::Bar,
|
|
33
33
|
it_behaves_like 'Model with invalid defaults'
|
34
34
|
it_behaves_like 'Self-equal Model'
|
35
35
|
|
36
|
-
it 'has class name shortcut' do
|
37
|
-
IB::Bar.should == IB::Models::Bar
|
38
|
-
IB::Bar.new.should == IB::Models::Bar.new
|
39
|
-
end
|
40
|
-
|
41
36
|
end # describe IB::Bar
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'model_helper'
|
2
2
|
|
3
|
-
describe IB::
|
3
|
+
describe IB::ComboLeg,
|
4
4
|
:props =>
|
5
5
|
{:con_id => 81032967,
|
6
6
|
:ratio => 2,
|
@@ -40,12 +40,6 @@ describe IB::Models::ComboLeg,
|
|
40
40
|
it_behaves_like 'Model with valid defaults'
|
41
41
|
it_behaves_like 'Self-equal Model'
|
42
42
|
|
43
|
-
it 'has class name shortcut' do
|
44
|
-
IB::ComboLeg.should == IB::Models::ComboLeg
|
45
|
-
IB::ComboLeg.new.should == IB::Models::ComboLeg.new
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
43
|
context "serialization" do
|
50
44
|
subject { IB::ComboLeg.new props }
|
51
45
|
|
@@ -105,10 +99,6 @@ describe IB::Models::ComboLeg,
|
|
105
99
|
combo_leg = IB::ComboLeg.where(:con_id => 454).first
|
106
100
|
combo_leg.should be_valid
|
107
101
|
|
108
|
-
#p combo_leg.combo.attributes
|
109
|
-
#p combo_leg.combo.strike
|
110
|
-
#p combo_leg.combo.include_expired
|
111
|
-
|
112
102
|
combo = combo_leg.combo
|
113
103
|
google = combo_leg.leg_contract
|
114
104
|
#combo.should == @combo # NOT equal, different legs
|
@@ -138,4 +128,4 @@ describe IB::Models::ComboLeg,
|
|
138
128
|
end
|
139
129
|
end
|
140
130
|
|
141
|
-
end # describe IB::
|
131
|
+
end # describe IB::ComboLeg
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'model_helper'
|
2
2
|
|
3
|
-
describe IB::
|
3
|
+
describe IB::ContractDetail,
|
4
4
|
|
5
5
|
:props =>
|
6
6
|
{:market_name => 'AAPL',
|
@@ -33,14 +33,9 @@ describe IB::Models::ContractDetail,
|
|
33
33
|
|
34
34
|
:aliases =>
|
35
35
|
{[:contract, :summary] => {IB::Contract.new => IB::Contract.new}
|
36
|
-
} do
|
36
|
+
} do
|
37
37
|
|
38
38
|
it_behaves_like 'Model with invalid defaults'
|
39
39
|
it_behaves_like 'Self-equal Model'
|
40
40
|
|
41
|
-
|
42
|
-
IB::ContractDetail.should == IB::Models::ContractDetail
|
43
|
-
IB::ContractDetail.new.should == IB::Models::ContractDetail.new
|
44
|
-
end
|
45
|
-
|
46
|
-
end # describe IB::Contract
|
41
|
+
end # describe IB::ContractDetail
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'model_helper'
|
2
2
|
require 'combo_helper'
|
3
3
|
|
4
|
-
describe IB::
|
4
|
+
describe IB::Contract,
|
5
5
|
:props =>
|
6
6
|
{:symbol => 'AAPL',
|
7
7
|
:sec_type => :option,
|
@@ -51,16 +51,11 @@ describe IB::Models::Contract,
|
|
51
51
|
:strike => to_f_assigns,
|
52
52
|
|
53
53
|
:include_expired => boolean_assigns,
|
54
|
-
} do
|
54
|
+
} do
|
55
55
|
|
56
56
|
it_behaves_like 'Model with invalid defaults'
|
57
57
|
it_behaves_like 'Self-equal Model'
|
58
58
|
|
59
|
-
it 'has class name shortcut' do
|
60
|
-
IB::Contract.should == IB::Models::Contract
|
61
|
-
IB::Contract.new.should == IB::Models::Contract.new
|
62
|
-
end
|
63
|
-
|
64
59
|
context 'testing for Contract type (sec_type)' do
|
65
60
|
|
66
61
|
it 'correctly defines Contract type (sec_type) for Option contract' do
|
@@ -111,8 +106,9 @@ describe IB::Models::Contract,
|
|
111
106
|
|
112
107
|
end
|
113
108
|
|
114
|
-
context "serialization" do
|
109
|
+
context "serialization", :connected => true do
|
115
110
|
before(:all) do
|
111
|
+
# TODO: Change butterfly into a stub, reduce dependency on IB connection
|
116
112
|
@ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
|
117
113
|
@ib.wait_for :ManagedAccounts
|
118
114
|
@combo = butterfly 'GOOG', '201301', 'CALL', 500, 510, 520
|
@@ -152,7 +148,3 @@ describe IB::Models::Contract,
|
|
152
148
|
|
153
149
|
|
154
150
|
end # describe IB::Contract
|
155
|
-
|
156
|
-
__END__
|
157
|
-
IB::Models::ContractDetail id: nil, contract_id: nil, market_name: "AAPL", trading_class: "AAPL", min_tick: 0.01, price_magnifier: 1, order_types: "ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKE...", valid_exchanges: "SMART,AMEX,BATS,BOX,CBOE,CBOE2,IBSX,ISE,MIBSX,NASDA...", under_con_id: 265598, long_name: "APPLE INC", contract_month: "201301", industry: "Technology", category: "Computers", subcategory: "Computers", time_zone: "EST", trading_hours: "20120422:0930-1600;20120423:0930-1600", liquid_hours: "20120422:0930-1600;20120423:0930-1600", cusip: nil, ratings: nil, desc_append: nil, bond_type: nil, coupon_type: nil, coupon: 0.0, maturity: nil, issue_date: nil, next_option_date: nil, next_option_type: nil, notes: nil, callable: false, puttable: false, convertible: false, next_option_partial: false, created_at: "2012-04-23 13:58:05", updated_at: "2012-04-23 13:58:05"
|
158
|
-
IB::Models::ContractDetail id: nil, contract_id: nil, market_name: "AAPL", trading_class: "AAPL", min_tick: 0.01, price_magnifier: 1, order_types: "ACTIVETIM,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKE...", valid_exchanges: "SMART,AMEX,BATS,BOX,CBOE,CBOE2,IBSX,ISE,MIBSX,NASDA...", under_con_id: 265598, long_name: "APPLE INC", contract_month: "201301", industry: "Technology", category: "Computers", subcategory: "Computers", time_zone: "EST", trading_hours: "20120422:0930-1600;20120423:0930-1600", liquid_hours: "20120422:0930-1600;20120423:0930-1600", cusip: nil, ratings: nil, desc_append: nil, bond_type: nil, coupon_type: nil, coupon: 0.0, maturity: nil, issue_date: nil, next_option_date: nil, next_option_type: nil, notes: nil, callable: false, puttable: false, convertible: false, next_option_partial: false, created_at: "2012-04-23 13:58:04", updated_at: "2012-04-23 13:58:04">
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'model_helper'
|
2
2
|
|
3
|
-
describe IB::
|
3
|
+
describe IB::Execution,
|
4
4
|
:props =>
|
5
5
|
{:account_name => "DU111110",
|
6
6
|
:client_id => 1111,
|
@@ -49,11 +49,6 @@ describe IB::Models::Execution,
|
|
49
49
|
it_behaves_like 'Model with invalid defaults'
|
50
50
|
it_behaves_like 'Self-equal Model'
|
51
51
|
|
52
|
-
it 'has class name shortcut' do
|
53
|
-
IB::Execution.should == IB::Models::Execution
|
54
|
-
IB::Execution.new.should == IB::Models::Execution.new
|
55
|
-
end
|
56
|
-
|
57
52
|
context 'DB backed associations', :db => true do
|
58
53
|
subject { IB::Execution.new props }
|
59
54
|
|
@@ -113,4 +108,4 @@ describe IB::Models::Execution,
|
|
113
108
|
end
|
114
109
|
end
|
115
110
|
|
116
|
-
end # describe IB::
|
111
|
+
end # describe IB::Execution
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'model_helper'
|
2
2
|
|
3
|
-
describe IB::
|
3
|
+
describe IB::Option,
|
4
4
|
:human => "<Option: AAPL 201301 put 600.5 SMART >",
|
5
5
|
|
6
6
|
:errors => {:right => ["should be put or call"],
|
@@ -50,11 +50,6 @@ describe IB::Models::Option,
|
|
50
50
|
it_behaves_like 'Self-equal Model'
|
51
51
|
it_behaves_like 'Model with invalid defaults'
|
52
52
|
|
53
|
-
it 'has class name shortcut' do
|
54
|
-
IB::Option.should == IB::Models::Option
|
55
|
-
IB::Option.new.should == IB::Models::Option.new
|
56
|
-
end
|
57
|
-
|
58
53
|
context 'properly initiated' do
|
59
54
|
subject { IB::Option.new props }
|
60
55
|
it_behaves_like 'Contract'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'model_helper'
|
2
2
|
|
3
|
-
describe IB::
|
3
|
+
describe IB::Order,
|
4
4
|
:props =>
|
5
5
|
{:local_id => 23,
|
6
6
|
:order_ref => 'Test',
|
@@ -86,13 +86,8 @@ describe IB::Models::Order,
|
|
86
86
|
it_behaves_like 'Self-equal Model'
|
87
87
|
it_behaves_like 'Model with invalid defaults'
|
88
88
|
|
89
|
-
it 'has class name shortcut' do
|
90
|
-
IB::Order.should == IB::Models::Order
|
91
|
-
IB::Order.new.should == IB::Models::Order.new
|
92
|
-
end
|
93
|
-
|
94
89
|
context 'Order associations' do
|
95
|
-
after(:all) { DatabaseCleaner.clean }
|
90
|
+
after(:all) { DatabaseCleaner.clean if IB::DB }
|
96
91
|
|
97
92
|
subject { IB::Order.new props }
|
98
93
|
|
@@ -107,7 +102,7 @@ describe IB::Models::Order,
|
|
107
102
|
last_state.should be_an IB::OrderState
|
108
103
|
last_state.status.should == 'New'
|
109
104
|
subject.save
|
110
|
-
last_state.order.should == subject if IB
|
105
|
+
last_state.order.should == subject if IB.db_backed?
|
111
106
|
end
|
112
107
|
|
113
108
|
it 'has abbreviated accessor to last (current) OrderState' do
|
@@ -152,7 +147,7 @@ describe IB::Models::Order,
|
|
152
147
|
subject.status.should == 'Bar'
|
153
148
|
subject.save
|
154
149
|
subject.order_states.should have_exactly(3).states
|
155
|
-
subject.order_states.first.order.should == subject if IB
|
150
|
+
subject.order_states.first.order.should == subject if IB.db_backed?
|
156
151
|
end
|
157
152
|
|
158
153
|
it 'or simply assigning to order_state accessor' do
|
@@ -240,7 +235,7 @@ describe IB::Models::Order,
|
|
240
235
|
|
241
236
|
subject { IB::Order.new(props.merge(serializable_props)) }
|
242
237
|
|
243
|
-
after(:all) { DatabaseCleaner.clean }
|
238
|
+
after(:all) { DatabaseCleaner.clean if IB::DB }
|
244
239
|
|
245
240
|
it 'is saved to DB with serializable_props' do
|
246
241
|
subject.save.should be_true
|