ib-ruby 0.7.3 → 0.7.4
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +4 -0
- data/README.md +60 -30
- data/TODO +1 -0
- data/VERSION +1 -1
- data/bin/account_info +1 -4
- data/bin/cancel_orders +0 -3
- data/bin/contract_details +2 -5
- data/bin/depth_of_market +1 -4
- data/bin/fa_accounts +22 -0
- data/bin/historic_data +1 -4
- data/bin/historic_data_cli +0 -4
- data/bin/list_orders +2 -6
- data/bin/market_data +1 -4
- data/bin/option_data +2 -5
- data/bin/place_combo_order +17 -22
- data/bin/place_order +6 -10
- data/bin/tick_data +6 -9
- data/bin/time_and_sales +2 -5
- data/lib/ib-ruby/connection.rb +10 -5
- data/lib/ib-ruby/messages/incoming/open_order.rb +15 -13
- data/lib/ib-ruby/messages/incoming/ticks.rb +1 -1
- data/lib/ib-ruby/messages/incoming.rb +18 -18
- data/lib/ib-ruby/messages/outgoing.rb +2 -2
- data/lib/ib-ruby/messages.rb +3 -7
- data/lib/ib-ruby/models/{contract → contracts}/bag.rb +5 -8
- data/lib/ib-ruby/models/contracts/contract.rb +296 -0
- data/lib/ib-ruby/models/{contract → contracts}/option.rb +2 -4
- data/lib/ib-ruby/models/contracts.rb +27 -0
- data/lib/ib-ruby/models/execution.rb +1 -1
- data/lib/ib-ruby/models/order.rb +6 -17
- data/lib/ib-ruby/models.rb +9 -7
- data/lib/ib-ruby/symbols/forex.rb +50 -50
- data/lib/ib-ruby/symbols/futures.rb +47 -47
- data/lib/ib-ruby/symbols/options.rb +23 -23
- data/lib/ib-ruby/symbols/stocks.rb +14 -14
- data/lib/ib-ruby.rb +17 -9
- data/spec/README.md +6 -0
- data/spec/account_helper.rb +1 -1
- data/spec/combo_helper.rb +31 -0
- data/spec/ib-ruby/models/combo_leg_spec.rb +4 -4
- data/spec/ib-ruby/models/contract_spec.rb +37 -26
- data/spec/ib-ruby/models/execution_spec.rb +5 -5
- data/spec/ib-ruby/models/order_spec.rb +16 -16
- data/spec/integration/contract_info_spec.rb +8 -10
- data/spec/integration/historic_data_spec.rb +1 -1
- data/spec/integration/market_data_spec.rb +5 -5
- data/spec/integration/orders/attached_spec.rb +87 -0
- data/spec/integration/orders/combo_spec.rb +52 -65
- data/spec/integration/orders/placement_spec.rb +8 -8
- data/spec/order_helper.rb +97 -28
- data/spec/spec_helper.rb +2 -2
- metadata +12 -5
- data/lib/ib-ruby/models/contract.rb +0 -308
@@ -343,8 +343,8 @@ module IB
|
|
343
343
|
error ":bar_size must be one of #{BAR_SIZES.inspect}", :args
|
344
344
|
end
|
345
345
|
|
346
|
-
contract = data[:contract].is_a?(
|
347
|
-
data[:contract] :
|
346
|
+
contract = data[:contract].is_a?(IB::Contract) ?
|
347
|
+
data[:contract] : IB::Contract.from_ib_ruby(data[:contract])
|
348
348
|
|
349
349
|
[data_type, bar_size, contract]
|
350
350
|
end
|
data/lib/ib-ruby/messages.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
module IB
|
2
|
-
|
3
2
|
module Messages
|
4
3
|
end
|
4
|
+
end
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
IncomingMessages = Messages::Incoming # Legacy alias
|
10
|
-
OutgoingMessages = Messages::Outgoing # Legacy alias
|
6
|
+
require 'ib-ruby/messages/outgoing'
|
7
|
+
require 'ib-ruby/messages/incoming'
|
11
8
|
|
12
|
-
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'ib-ruby/models/contract'
|
1
|
+
require 'ib-ruby/models/contracts/contract'
|
2
2
|
|
3
3
|
module IB
|
4
4
|
module Models
|
5
|
-
|
5
|
+
module Contracts
|
6
6
|
|
7
7
|
# "BAG" is not really a contract, but a combination (combo) of securities.
|
8
8
|
# AKA basket or bag of securities. Individual securities in combo are represented
|
@@ -53,9 +53,6 @@ module IB
|
|
53
53
|
end
|
54
54
|
|
55
55
|
end # class Bag
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end # class Contract
|
60
|
-
end # module Models
|
61
|
-
end # module IB
|
56
|
+
end # Contracts
|
57
|
+
end # Models
|
58
|
+
end # IB
|
@@ -0,0 +1,296 @@
|
|
1
|
+
require 'ib-ruby/models/model'
|
2
|
+
|
3
|
+
module IB
|
4
|
+
module Models
|
5
|
+
module Contracts
|
6
|
+
class Contract < Model
|
7
|
+
|
8
|
+
# This returns a Contract initialized from the serialize_ib_ruby format string.
|
9
|
+
def self.build opts = {}
|
10
|
+
Contracts::TYPES[opts[:sec_type]].new opts
|
11
|
+
end
|
12
|
+
|
13
|
+
# This returns a Contract initialized from the serialize_ib_ruby format string.
|
14
|
+
def self.from_ib_ruby string
|
15
|
+
keys = [:symbol, :sec_type, :expiry, :strike, :right, :multiplier,
|
16
|
+
:exchange, :primary_exchange, :currency, :local_symbol]
|
17
|
+
props = Hash[keys.zip(string.split(":"))]
|
18
|
+
props.delete_if { |k, v| v.nil? || v.empty? }
|
19
|
+
Contract.new props
|
20
|
+
end
|
21
|
+
|
22
|
+
# Fields are Strings unless noted otherwise
|
23
|
+
prop :con_id, # int: The unique contract identifier.
|
24
|
+
:symbol, # This is the symbol of the underlying asset.
|
25
|
+
:sec_type, # Security type. Valid values are: SECURITY_TYPES
|
26
|
+
:strike, # double: The strike price.
|
27
|
+
:exchange, # The order destination, such as Smart.
|
28
|
+
:currency, # Only needed if there is an ambiguity, e.g. when SMART exchange
|
29
|
+
# and IBM is being requested (IBM can trade in GBP or USD).
|
30
|
+
|
31
|
+
:local_symbol, # Local exchange symbol of the underlying asset
|
32
|
+
:include_expired, # When true, contract details requests and historical
|
33
|
+
# data queries can be performed pertaining to expired contracts.
|
34
|
+
# Note: Historical data queries on expired contracts are
|
35
|
+
# limited to the last year of the contracts life, and are
|
36
|
+
# only supported for expired futures contracts.
|
37
|
+
# This field can NOT be set to true for orders.
|
38
|
+
|
39
|
+
:sec_id_type, # Security identifier, when querying contract details or
|
40
|
+
# when placing orders. Supported identifiers are:
|
41
|
+
# - ISIN (Example: Apple: US0378331005)
|
42
|
+
# - CUSIP (Example: Apple: 037833100)
|
43
|
+
# - SEDOL (6-AN + check digit. Example: BAE: 0263494)
|
44
|
+
# - RIC (exchange-independent RIC Root and exchange-
|
45
|
+
# identifying suffix. Ex: AAPL.O for Apple on NASDAQ.)
|
46
|
+
:sec_id, # Unique identifier of the given secIdType.
|
47
|
+
|
48
|
+
# COMBOS
|
49
|
+
:legs_description, # received in OpenOrder for all combos
|
50
|
+
|
51
|
+
:multiplier => :i,
|
52
|
+
# Future/option contract multiplier (only needed when multiple possibilities exist)
|
53
|
+
|
54
|
+
:primary_exchange =>
|
55
|
+
# non-aggregate (ie not the SMART) exchange that the contract trades on.
|
56
|
+
proc { |val|
|
57
|
+
val.upcase! if val.is_a?(String)
|
58
|
+
error "Don't set primary_exchange to smart", :args if val == 'SMART'
|
59
|
+
self[:primary_exchange] = val
|
60
|
+
},
|
61
|
+
|
62
|
+
:right => # Specifies a Put or Call. Valid input values are: P, PUT, C, CALL
|
63
|
+
proc { |val|
|
64
|
+
self[:right] =
|
65
|
+
case val.to_s.upcase
|
66
|
+
when '', '0', '?'
|
67
|
+
nil
|
68
|
+
when 'PUT', 'P'
|
69
|
+
'PUT'
|
70
|
+
when 'CALL', 'C'
|
71
|
+
'CALL'
|
72
|
+
else
|
73
|
+
error "Right must be one of PUT, CALL, P, C - not '#{val}'", :args
|
74
|
+
end
|
75
|
+
},
|
76
|
+
|
77
|
+
:expiry => # The expiration date. Use the format YYYYMM.
|
78
|
+
proc { |val|
|
79
|
+
self[:expiry] =
|
80
|
+
case val.to_s
|
81
|
+
when /\d{6,8}/
|
82
|
+
val.to_s
|
83
|
+
when nil, ''
|
84
|
+
nil
|
85
|
+
else
|
86
|
+
error "Invalid expiry '#{val}' (must be in format YYYYMM or YYYYMMDD)", :args
|
87
|
+
end
|
88
|
+
},
|
89
|
+
|
90
|
+
:sec_type => # Security type. Valid values are: SECURITY_TYPES
|
91
|
+
proc { |val|
|
92
|
+
val = nil if !val.nil? && val.empty?
|
93
|
+
unless val.nil? || SECURITY_TYPES.values.include?(val)
|
94
|
+
error "Invalid security type '#{val}' (must be one of #{SECURITY_TYPES.values}", :args
|
95
|
+
end
|
96
|
+
self[:sec_type] = val
|
97
|
+
}
|
98
|
+
|
99
|
+
# ContractDetails fields are bundled into Contract proper, as it should be
|
100
|
+
# All fields Strings, unless specified otherwise:
|
101
|
+
prop :market_name, # The market name for this contract.
|
102
|
+
:trading_class, # The trading class name for this contract.
|
103
|
+
:min_tick, # double: The minimum price tick.
|
104
|
+
:price_magnifier, # int: Allows execution and strike prices to be
|
105
|
+
# reported consistently with market data, historical data and the
|
106
|
+
# order price: Z on LIFFE is reported in index points, not GBP.
|
107
|
+
|
108
|
+
:order_types, # The list of valid order types for this contract.
|
109
|
+
:valid_exchanges, # The list of exchanges this contract is traded on.
|
110
|
+
:under_con_id, # int: The underlying contract ID.
|
111
|
+
:long_name, # Descriptive name of the asset.
|
112
|
+
:contract_month, # The contract month of the underlying for a futures contract.
|
113
|
+
|
114
|
+
# The industry classification of the underlying/product:
|
115
|
+
:industry, # Wide industry. For example, Financial.
|
116
|
+
:category, # Industry category. For example, InvestmentSvc.
|
117
|
+
:subcategory, # Subcategory. For example, Brokerage.
|
118
|
+
:time_zone, # Time zone for the trading hours of the product. For example, EST.
|
119
|
+
:trading_hours, # The trading hours of the product. For example:
|
120
|
+
# 20090507:0700-1830,1830-2330;20090508:CLOSED.
|
121
|
+
:liquid_hours, # The liquid trading hours of the product. For example,
|
122
|
+
# 20090507:0930-1600;20090508:CLOSED.
|
123
|
+
|
124
|
+
# Bond values:
|
125
|
+
:cusip, # The nine-character bond CUSIP or the 12-character SEDOL.
|
126
|
+
:ratings, # Credit rating of the issuer. Higher rating is less risky investment.
|
127
|
+
# Bond ratings are from Moody's and S&P respectively.
|
128
|
+
:desc_append, # Additional descriptive information about the bond.
|
129
|
+
:bond_type, # The type of bond, such as "CORP."
|
130
|
+
:coupon_type, # The type of bond coupon.
|
131
|
+
:callable, # bool: Can be called by the issuer under certain conditions.
|
132
|
+
:puttable, # bool: Can be sold back to the issuer under certain conditions
|
133
|
+
:coupon, # double: The interest rate used to calculate the amount you
|
134
|
+
# will receive in interest payments over the year. default 0
|
135
|
+
:convertible, # bool: Can be converted to stock under certain conditions.
|
136
|
+
:maturity, # The date on which the issuer must repay bond face value
|
137
|
+
:issue_date, # The date the bond was issued.
|
138
|
+
:next_option_date, # only if bond has embedded options.
|
139
|
+
:next_option_type, # only if bond has embedded options.
|
140
|
+
:next_option_partial, # bool: # only if bond has embedded options.
|
141
|
+
:notes # Additional notes, if populated for the bond in IB's database
|
142
|
+
|
143
|
+
# Used for Delta-Neutral Combo contracts only!
|
144
|
+
# UnderComp fields are bundled into Contract proper, as it should be.
|
145
|
+
prop :under_comp, # if not nil, attributes below are sent to server
|
146
|
+
#:under_con_id is is already defined in ContractDetails section
|
147
|
+
:under_delta, # double: The underlying stock or future delta.
|
148
|
+
:under_price # double: The price of the underlying.
|
149
|
+
|
150
|
+
# Legs arriving via OpenOrder message, need to define them here
|
151
|
+
attr_accessor :legs # leg definitions for this contract.
|
152
|
+
alias combo_legs legs
|
153
|
+
alias combo_legs= legs=
|
154
|
+
alias combo_legs_description legs_description
|
155
|
+
alias combo_legs_description= legs_description=
|
156
|
+
|
157
|
+
attr_accessor :description # NB: local to ib-ruby, not part of TWS.
|
158
|
+
|
159
|
+
DEFAULT_PROPS = {:con_id => 0,
|
160
|
+
:strike => 0,
|
161
|
+
:exchange => 'SMART',
|
162
|
+
:include_expired => false,
|
163
|
+
|
164
|
+
# These properties are from ContractDetails
|
165
|
+
:under_con_id => 0,
|
166
|
+
:min_tick => 0,
|
167
|
+
:callable => false,
|
168
|
+
:puttable => false,
|
169
|
+
:coupon => 0,
|
170
|
+
:convertible => false,
|
171
|
+
:next_option_partial => false, }
|
172
|
+
|
173
|
+
# NB: ContractDetails reference - to self!
|
174
|
+
def summary
|
175
|
+
self
|
176
|
+
end
|
177
|
+
|
178
|
+
# This returns an Array of data from the given contract.
|
179
|
+
# Different messages serialize contracts differently. Go figure.
|
180
|
+
# Note that it does NOT include the combo legs.
|
181
|
+
def serialize *fields
|
182
|
+
[(fields.include?(:con_id) ? [con_id] : []),
|
183
|
+
symbol,
|
184
|
+
sec_type,
|
185
|
+
(fields.include?(:option) ? [expiry, strike, right, multiplier] : []),
|
186
|
+
exchange,
|
187
|
+
(fields.include?(:primary_exchange) ? [primary_exchange] : []),
|
188
|
+
currency,
|
189
|
+
local_symbol,
|
190
|
+
(fields.include?(:sec_id) ? [sec_id_type, sec_id] : []),
|
191
|
+
(fields.include?(:include_expired) ? [include_expired] : []),
|
192
|
+
].flatten
|
193
|
+
end
|
194
|
+
|
195
|
+
def serialize_long *fields
|
196
|
+
serialize :option, :primary_exchange, *fields
|
197
|
+
end
|
198
|
+
|
199
|
+
def serialize_short *fields
|
200
|
+
serialize :option, *fields
|
201
|
+
end
|
202
|
+
|
203
|
+
# Serialize under_comp parameters
|
204
|
+
def serialize_under_comp *args
|
205
|
+
# EClientSocket.java, line 471:
|
206
|
+
if under_comp
|
207
|
+
[true,
|
208
|
+
under_con_id,
|
209
|
+
under_delta,
|
210
|
+
under_price]
|
211
|
+
else
|
212
|
+
[false]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Redefined in BAG subclass
|
217
|
+
def serialize_legs *fields
|
218
|
+
[]
|
219
|
+
end
|
220
|
+
|
221
|
+
# This produces a string uniquely identifying this contract, in the format used
|
222
|
+
# for command line arguments in the IB-Ruby examples. The format is:
|
223
|
+
#
|
224
|
+
# symbol:security_type:expiry:strike:right:multiplier:exchange:primary_exchange:currency:local_symbol
|
225
|
+
#
|
226
|
+
# Fields not needed for a particular security should be left blank
|
227
|
+
# (e.g. strike and right are only relevant for options.)
|
228
|
+
#
|
229
|
+
# For example, to query the British pound futures contract trading on Globex
|
230
|
+
# expiring in September, 2008, the string is:
|
231
|
+
#
|
232
|
+
# GBP:FUT:200809:::62500:GLOBEX::USD:
|
233
|
+
def serialize_ib_ruby
|
234
|
+
serialize_long.join(":")
|
235
|
+
end
|
236
|
+
|
237
|
+
# Contract comparison
|
238
|
+
def == other
|
239
|
+
return false unless other.is_a?(self.class)
|
240
|
+
|
241
|
+
# Different sec_id_type
|
242
|
+
return false if sec_id_type && other.sec_id_type && sec_id_type != other.sec_id_type
|
243
|
+
|
244
|
+
# Different sec_id
|
245
|
+
return false if sec_id && other.sec_id && sec_id != other.sec_id
|
246
|
+
|
247
|
+
# Different under_comp
|
248
|
+
return false if under_comp && other.under_comp && under_comp != other.under_comp
|
249
|
+
|
250
|
+
# Different symbols
|
251
|
+
return false if symbol && other.symbol && symbol != other.symbol
|
252
|
+
|
253
|
+
# Different currency
|
254
|
+
return false if currency && other.currency && currency != other.currency
|
255
|
+
|
256
|
+
# Same con_id for all Bags, but unknown for new Contracts...
|
257
|
+
# 0 or nil con_id matches any
|
258
|
+
return false if con_id != 0 && other.con_id != 0 &&
|
259
|
+
con_id && other.con_id && con_id != other.con_id
|
260
|
+
|
261
|
+
# SMART or nil exchange matches any
|
262
|
+
return false if exchange != 'SMART' && other.exchange != 'SMART' &&
|
263
|
+
exchange && other.exchange && exchange != other.exchange
|
264
|
+
|
265
|
+
# Comparison for Bonds and Options
|
266
|
+
if sec_type == SECURITY_TYPES[:bond] || sec_type == SECURITY_TYPES[:option]
|
267
|
+
return false if right != other.right || strike != other.strike
|
268
|
+
return false if multiplier && other.multiplier && multiplier != other.multiplier
|
269
|
+
return false if expiry[0..5] != other.expiry[0..5]
|
270
|
+
return false unless expiry[6..7] == other.expiry[6..7] ||
|
271
|
+
expiry[6..7].empty? || other.expiry[6..7].empty?
|
272
|
+
end
|
273
|
+
|
274
|
+
# All else being equal...
|
275
|
+
sec_type == other.sec_type
|
276
|
+
end
|
277
|
+
|
278
|
+
def to_s
|
279
|
+
"<Contract: " + instance_variables.map do |key|
|
280
|
+
value = send(key[1..-1])
|
281
|
+
" #{key}=#{value}" unless value.nil? || value == '' || value == 0
|
282
|
+
end.compact.join(',') + " >"
|
283
|
+
end
|
284
|
+
|
285
|
+
def to_human
|
286
|
+
"<Contract: " + [symbol, sec_type, expiry, strike, right, exchange, currency].join("-") + ">"
|
287
|
+
end
|
288
|
+
|
289
|
+
def to_short
|
290
|
+
"#{symbol}#{expiry}#{strike}#{right}#{exchange}#{currency}"
|
291
|
+
end
|
292
|
+
|
293
|
+
end # class Contract
|
294
|
+
end # module Contracts
|
295
|
+
end # module Models
|
296
|
+
end # module IB
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'ib-ruby/models/contract'
|
1
|
+
require 'ib-ruby/models/contracts/contract'
|
2
2
|
|
3
3
|
module IB
|
4
4
|
module Models
|
5
|
-
|
5
|
+
module Contracts
|
6
6
|
class Option < Contract
|
7
7
|
|
8
8
|
# For Options, this is contract's OSI (Option Symbology Initiative) name/code
|
@@ -52,8 +52,6 @@ module IB
|
|
52
52
|
"<Option: " + [symbol, expiry, right, strike, exchange, currency].join("-") + ">"
|
53
53
|
end
|
54
54
|
end # class Option
|
55
|
-
|
56
|
-
TYPES[IB::SECURITY_TYPES[:option]] = Option
|
57
55
|
end # class Contract
|
58
56
|
end # module Models
|
59
57
|
end # module IB
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module IB
|
2
|
+
module Models
|
3
|
+
module Contracts
|
4
|
+
end
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'ib-ruby/models/contracts/contract'
|
9
|
+
require 'ib-ruby/models/contracts/option'
|
10
|
+
require 'ib-ruby/models/contracts/bag'
|
11
|
+
|
12
|
+
module IB
|
13
|
+
module Models
|
14
|
+
# This module contains Contract subclasses
|
15
|
+
module Contracts
|
16
|
+
# Specialized Contract subclasses representing different security types
|
17
|
+
TYPES = Hash.new(Contract)
|
18
|
+
TYPES[IB::SECURITY_TYPES[:bag]] = Bag
|
19
|
+
TYPES[IB::SECURITY_TYPES[:option]] = Option
|
20
|
+
|
21
|
+
# Returns concrete subclass for this sec_type, or default Contract
|
22
|
+
def [] sec_type
|
23
|
+
TYPES[sec_type]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -35,7 +35,7 @@ module IB
|
|
35
35
|
def to_s
|
36
36
|
"<Execution #{time}: #{side} #{shares} @ #{price} on #{exchange}, " +
|
37
37
|
"cumulative: #{cumulative_quantity} @ #{average_price}, " +
|
38
|
-
"
|
38
|
+
"order: #{order_id}/#{perm_id}#{order_ref}, exec: #{exec_id}>"
|
39
39
|
end
|
40
40
|
end # Execution
|
41
41
|
end # module Models
|
data/lib/ib-ruby/models/order.rb
CHANGED
@@ -316,16 +316,9 @@ module IB
|
|
316
316
|
:min_commission,
|
317
317
|
:max_commission,
|
318
318
|
:warning_text, # String: Displays a warning message if warranted.
|
319
|
-
|
320
|
-
#
|
321
|
-
:
|
322
|
-
|
323
|
-
# String: Shows the impact the order would have on your maintenance margin.
|
324
|
-
:maint_margin => proc { |val| self[:maint_margin] = filter_max val },
|
325
|
-
|
326
|
-
# String: Shows the impact the order would have on your equity with loan value.
|
327
|
-
:equity_with_loan => proc { |val| self[:equity_with_loan] = filter_max val }
|
328
|
-
|
319
|
+
:init_margin, # Float: The impact the order would have on your initial margin.
|
320
|
+
:maint_margin, # Float: The impact the order would have on your maintenance margin.
|
321
|
+
:equity_with_loan # Float: The impact the order would have on your equity
|
329
322
|
|
330
323
|
# Returned in OpenOrder for Bag Contracts
|
331
324
|
# public Vector<OrderComboLeg> m_orderComboLegs
|
@@ -333,11 +326,6 @@ module IB
|
|
333
326
|
alias order_combo_legs leg_prices
|
334
327
|
alias smart_combo_routing_params combo_params
|
335
328
|
|
336
|
-
# IB uses weird String with Java Double.MAX_VALUE to indicate no value here
|
337
|
-
def filter_max val
|
338
|
-
val == "1.7976931348623157E308" ? nil : val.to_f
|
339
|
-
end
|
340
|
-
|
341
329
|
DEFAULT_PROPS = {:aux_price => 0.0,
|
342
330
|
:parent_id => 0,
|
343
331
|
:tif => 'DAY',
|
@@ -465,14 +453,15 @@ module IB
|
|
465
453
|
# Order comparison
|
466
454
|
def == other
|
467
455
|
perm_id && other.perm_id && perm_id == other.perm_id ||
|
468
|
-
order_id == other.order_id && #
|
456
|
+
order_id == other.order_id && # ((p __LINE__)||true) &&
|
469
457
|
(client_id == other.client_id || client_id == 0 || other.client_id == 0) &&
|
470
458
|
parent_id == other.parent_id &&
|
471
459
|
tif == other.tif &&
|
472
460
|
action == other.action &&
|
473
461
|
order_type == other.order_type &&
|
474
462
|
total_quantity == other.total_quantity &&
|
475
|
-
limit_price == other.limit_price
|
463
|
+
(limit_price == other.limit_price || # TODO Floats should be Decimals!
|
464
|
+
(limit_price - other.limit_price).abs < 0.00001) &&
|
476
465
|
aux_price == other.aux_price &&
|
477
466
|
outside_rth == other.outside_rth &&
|
478
467
|
origin == other.origin &&
|
data/lib/ib-ruby/models.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
module IB
|
2
2
|
module Models
|
3
|
+
require 'ib-ruby/models/contracts'
|
4
|
+
# Flatten namespace (IB::Models::Option instead of IB::Models::Contracts::Option)
|
5
|
+
include Contracts
|
6
|
+
|
7
|
+
require 'ib-ruby/models/order'
|
8
|
+
require 'ib-ruby/models/combo_leg'
|
9
|
+
require 'ib-ruby/models/execution'
|
10
|
+
require 'ib-ruby/models/bar'
|
11
|
+
|
3
12
|
end
|
4
|
-
Datatypes = Models # Legacy alias
|
5
13
|
end
|
6
14
|
|
7
|
-
require 'ib-ruby/models/order'
|
8
|
-
require 'ib-ruby/models/contract'
|
9
|
-
require 'ib-ruby/models/combo_leg'
|
10
|
-
require 'ib-ruby/models/execution'
|
11
|
-
require 'ib-ruby/models/bar'
|
12
|
-
|
@@ -7,65 +7,65 @@ module IB
|
|
7
7
|
# IDEAL is for smaller orders, and has wider spreads/slower execution... generally
|
8
8
|
# used for smaller currency conversions.
|
9
9
|
Forex = {
|
10
|
-
:audusd =>
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
:audusd => IB::Contract.new(:symbol => "AUD",
|
11
|
+
:exchange => "IDEALPRO",
|
12
|
+
:currency => "USD",
|
13
|
+
:sec_type => SECURITY_TYPES[:forex],
|
14
|
+
:description => "AUDUSD"),
|
15
15
|
|
16
|
-
:gbpusd =>
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
:gbpusd => IB::Contract.new(:symbol => "GBP",
|
17
|
+
:exchange => "IDEALPRO",
|
18
|
+
:currency => "USD",
|
19
|
+
:sec_type => SECURITY_TYPES[:forex],
|
20
|
+
:description => "GBPUSD"),
|
21
21
|
|
22
|
-
:euraud =>
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
:euraud => IB::Contract.new(:symbol => "EUR",
|
23
|
+
:exchange => "IDEALPRO",
|
24
|
+
:currency => "AUD",
|
25
|
+
:sec_type => SECURITY_TYPES[:forex],
|
26
|
+
:description => "EURAUD"),
|
27
27
|
|
28
|
-
:eurgbp =>
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
:eurgbp => IB::Contract.new(:symbol => "EUR",
|
29
|
+
:exchange => "IDEALPRO",
|
30
|
+
:currency => "GBP",
|
31
|
+
:sec_type => SECURITY_TYPES[:forex],
|
32
|
+
:description => "EURGBP"),
|
33
33
|
|
34
|
-
:eurjpy =>
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
:eurjpy => IB::Contract.new(:symbol => "EUR",
|
35
|
+
:exchange => "IDEALPRO",
|
36
|
+
:currency => "JPY",
|
37
|
+
:sec_type => SECURITY_TYPES[:forex],
|
38
|
+
:description => "EURJPY"),
|
39
39
|
|
40
|
-
:eurusd =>
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
:eurusd => IB::Contract.new(:symbol => "EUR",
|
41
|
+
:exchange => "IDEALPRO",
|
42
|
+
:currency => "USD",
|
43
|
+
:sec_type => SECURITY_TYPES[:forex],
|
44
|
+
:description => "EURUSD"),
|
45
45
|
|
46
|
-
:eurcad =>
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
:eurcad => IB::Contract.new(:symbol => "EUR",
|
47
|
+
:exchange => "IDEALPRO",
|
48
|
+
:currency => "CAD",
|
49
|
+
:sec_type => SECURITY_TYPES[:forex],
|
50
|
+
:description => "EURCAD"),
|
51
51
|
|
52
|
-
:usdchf =>
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
:usdchf => IB::Contract.new(:symbol => "USD",
|
53
|
+
:exchange => "IDEALPRO",
|
54
|
+
:currency => "CHF",
|
55
|
+
:sec_type => SECURITY_TYPES[:forex],
|
56
|
+
:description => "USDCHF"),
|
57
57
|
|
58
|
-
:usdcad =>
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
:usdcad => IB::Contract.new(:symbol => "USD",
|
59
|
+
:exchange => "IDEALPRO",
|
60
|
+
:currency => "CAD",
|
61
|
+
:sec_type => SECURITY_TYPES[:forex],
|
62
|
+
:description => "USDCAD"),
|
63
63
|
|
64
|
-
:usdjpy =>
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
:usdjpy => IB::Contract.new(:symbol => "USD",
|
65
|
+
:exchange => "IDEALPRO",
|
66
|
+
:currency => "JPY",
|
67
|
+
:sec_type => SECURITY_TYPES[:forex],
|
68
|
+
:description => "USDJPY")
|
69
69
|
}
|
70
70
|
end
|
71
71
|
end
|