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
@@ -1,308 +0,0 @@
|
|
1
|
-
require 'ib-ruby/models/model'
|
2
|
-
|
3
|
-
module IB
|
4
|
-
module Models
|
5
|
-
class Contract < Model
|
6
|
-
|
7
|
-
# Specialized Contract subclasses representing different security types
|
8
|
-
TYPES = {}
|
9
|
-
#BAG_SEC_TYPE = "BAG"
|
10
|
-
|
11
|
-
# This returns a Contract initialized from the serialize_ib_ruby format string.
|
12
|
-
def self.build opts = {}
|
13
|
-
type = opts[:sec_type]
|
14
|
-
if TYPES[type]
|
15
|
-
TYPES[type].new opts
|
16
|
-
else
|
17
|
-
Contract.new opts
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# This returns a Contract initialized from the serialize_ib_ruby format string.
|
22
|
-
def self.from_ib_ruby string
|
23
|
-
keys = [:symbol, :sec_type, :expiry, :strike, :right, :multiplier,
|
24
|
-
:exchange, :primary_exchange, :currency, :local_symbol]
|
25
|
-
props = Hash[keys.zip(string.split(":"))]
|
26
|
-
props.delete_if { |k, v| v.nil? || v.empty? }
|
27
|
-
Contract.new props
|
28
|
-
end
|
29
|
-
|
30
|
-
# Fields are Strings unless noted otherwise
|
31
|
-
prop :con_id, # int: The unique contract identifier.
|
32
|
-
:symbol, # This is the symbol of the underlying asset.
|
33
|
-
:sec_type, # Security type. Valid values are: SECURITY_TYPES
|
34
|
-
:strike, # double: The strike price.
|
35
|
-
:exchange, # The order destination, such as Smart.
|
36
|
-
:currency, # Only needed if there is an ambiguity, e.g. when SMART exchange
|
37
|
-
# and IBM is being requested (IBM can trade in GBP or USD).
|
38
|
-
|
39
|
-
:local_symbol, # Local exchange symbol of the underlying asset
|
40
|
-
:include_expired, # When true, contract details requests and historical
|
41
|
-
# data queries can be performed pertaining to expired contracts.
|
42
|
-
# Note: Historical data queries on expired contracts are
|
43
|
-
# limited to the last year of the contracts life, and are
|
44
|
-
# only supported for expired futures contracts.
|
45
|
-
# This field can NOT be set to true for orders.
|
46
|
-
|
47
|
-
:sec_id_type, # Security identifier, when querying contract details or
|
48
|
-
# when placing orders. Supported identifiers are:
|
49
|
-
# - ISIN (Example: Apple: US0378331005)
|
50
|
-
# - CUSIP (Example: Apple: 037833100)
|
51
|
-
# - SEDOL (6-AN + check digit. Example: BAE: 0263494)
|
52
|
-
# - RIC (exchange-independent RIC Root and exchange-
|
53
|
-
# identifying suffix. Ex: AAPL.O for Apple on NASDAQ.)
|
54
|
-
:sec_id, # Unique identifier of the given secIdType.
|
55
|
-
|
56
|
-
# COMBOS
|
57
|
-
:legs_description, # received in OpenOrder for all combos
|
58
|
-
|
59
|
-
:multiplier => :i,
|
60
|
-
# Future/option contract multiplier (only needed when multiple possibilities exist)
|
61
|
-
|
62
|
-
:primary_exchange =>
|
63
|
-
# non-aggregate (ie not the SMART) exchange that the contract trades on.
|
64
|
-
proc { |val|
|
65
|
-
val.upcase! if val.is_a?(String)
|
66
|
-
error "Don't set primary_exchange to smart", :args if val == 'SMART'
|
67
|
-
self[:primary_exchange] = val
|
68
|
-
},
|
69
|
-
|
70
|
-
:right => # Specifies a Put or Call. Valid input values are: P, PUT, C, CALL
|
71
|
-
proc { |val|
|
72
|
-
self[:right] =
|
73
|
-
case val.to_s.upcase
|
74
|
-
when '', '0', '?'
|
75
|
-
nil
|
76
|
-
when 'PUT', 'P'
|
77
|
-
'PUT'
|
78
|
-
when 'CALL', 'C'
|
79
|
-
'CALL'
|
80
|
-
else
|
81
|
-
error "Right must be one of PUT, CALL, P, C - not '#{val}'", :args
|
82
|
-
end
|
83
|
-
},
|
84
|
-
|
85
|
-
:expiry => # The expiration date. Use the format YYYYMM.
|
86
|
-
proc { |val|
|
87
|
-
self[:expiry] =
|
88
|
-
case val.to_s
|
89
|
-
when /\d{6,8}/
|
90
|
-
val.to_s
|
91
|
-
when nil, ''
|
92
|
-
nil
|
93
|
-
else
|
94
|
-
error "Invalid expiry '#{val}' (must be in format YYYYMM or YYYYMMDD)", :args
|
95
|
-
end
|
96
|
-
},
|
97
|
-
|
98
|
-
:sec_type => # Security type. Valid values are: SECURITY_TYPES
|
99
|
-
proc { |val|
|
100
|
-
val = nil if !val.nil? && val.empty?
|
101
|
-
unless val.nil? || SECURITY_TYPES.values.include?(val)
|
102
|
-
error "Invalid security type '#{val}' (must be one of #{SECURITY_TYPES.values}", :args
|
103
|
-
end
|
104
|
-
self[:sec_type] = val
|
105
|
-
}
|
106
|
-
|
107
|
-
# ContractDetails fields are bundled into Contract proper, as it should be
|
108
|
-
# All fields Strings, unless specified otherwise:
|
109
|
-
prop :market_name, # The market name for this contract.
|
110
|
-
:trading_class, # The trading class name for this contract.
|
111
|
-
:min_tick, # double: The minimum price tick.
|
112
|
-
:price_magnifier, # int: Allows execution and strike prices to be
|
113
|
-
# reported consistently with market data, historical data and the
|
114
|
-
# order price: Z on LIFFE is reported in index points, not GBP.
|
115
|
-
|
116
|
-
:order_types, # The list of valid order types for this contract.
|
117
|
-
:valid_exchanges, # The list of exchanges this contract is traded on.
|
118
|
-
:under_con_id, # int: The underlying contract ID.
|
119
|
-
:long_name, # Descriptive name of the asset.
|
120
|
-
:contract_month, # The contract month of the underlying for a futures contract.
|
121
|
-
|
122
|
-
# The industry classification of the underlying/product:
|
123
|
-
:industry, # Wide industry. For example, Financial.
|
124
|
-
:category, # Industry category. For example, InvestmentSvc.
|
125
|
-
:subcategory, # Subcategory. For example, Brokerage.
|
126
|
-
:time_zone, # Time zone for the trading hours of the product. For example, EST.
|
127
|
-
:trading_hours, # The trading hours of the product. For example:
|
128
|
-
# 20090507:0700-1830,1830-2330;20090508:CLOSED.
|
129
|
-
:liquid_hours, # The liquid trading hours of the product. For example,
|
130
|
-
# 20090507:0930-1600;20090508:CLOSED.
|
131
|
-
|
132
|
-
# Bond values:
|
133
|
-
:cusip, # The nine-character bond CUSIP or the 12-character SEDOL.
|
134
|
-
:ratings, # Credit rating of the issuer. Higher rating is less risky investment.
|
135
|
-
# Bond ratings are from Moody's and S&P respectively.
|
136
|
-
:desc_append, # Additional descriptive information about the bond.
|
137
|
-
:bond_type, # The type of bond, such as "CORP."
|
138
|
-
:coupon_type, # The type of bond coupon.
|
139
|
-
:callable, # bool: Can be called by the issuer under certain conditions.
|
140
|
-
:puttable, # bool: Can be sold back to the issuer under certain conditions
|
141
|
-
:coupon, # double: The interest rate used to calculate the amount you
|
142
|
-
# will receive in interest payments over the year. default 0
|
143
|
-
:convertible, # bool: Can be converted to stock under certain conditions.
|
144
|
-
:maturity, # The date on which the issuer must repay bond face value
|
145
|
-
:issue_date, # The date the bond was issued.
|
146
|
-
:next_option_date, # only if bond has embedded options.
|
147
|
-
:next_option_type, # only if bond has embedded options.
|
148
|
-
:next_option_partial, # bool: # only if bond has embedded options.
|
149
|
-
:notes # Additional notes, if populated for the bond in IB's database
|
150
|
-
|
151
|
-
# Used for Delta-Neutral Combo contracts only!
|
152
|
-
# UnderComp fields are bundled into Contract proper, as it should be.
|
153
|
-
prop :under_comp, # if not nil, attributes below are sent to server
|
154
|
-
#:under_con_id is is already defined in ContractDetails section
|
155
|
-
:under_delta, # double: The underlying stock or future delta.
|
156
|
-
:under_price # double: The price of the underlying.
|
157
|
-
|
158
|
-
# Legs arriving via OpenOrder message, need to define them here
|
159
|
-
attr_accessor :legs # leg definitions for this contract.
|
160
|
-
alias combo_legs legs
|
161
|
-
alias combo_legs= legs=
|
162
|
-
alias combo_legs_description legs_description
|
163
|
-
alias combo_legs_description= legs_description=
|
164
|
-
|
165
|
-
attr_accessor :description # NB: local to ib-ruby, not part of TWS.
|
166
|
-
|
167
|
-
DEFAULT_PROPS = {:con_id => 0,
|
168
|
-
:strike => 0,
|
169
|
-
:exchange => 'SMART',
|
170
|
-
:include_expired => false,
|
171
|
-
|
172
|
-
# These properties are from ContractDetails
|
173
|
-
:under_con_id => 0,
|
174
|
-
:min_tick => 0,
|
175
|
-
:callable => false,
|
176
|
-
:puttable => false,
|
177
|
-
:coupon => 0,
|
178
|
-
:convertible => false,
|
179
|
-
:next_option_partial => false, }
|
180
|
-
|
181
|
-
# NB: ContractDetails reference - to self!
|
182
|
-
def summary
|
183
|
-
self
|
184
|
-
end
|
185
|
-
|
186
|
-
# This returns an Array of data from the given contract.
|
187
|
-
# Different messages serialize contracts differently. Go figure.
|
188
|
-
# Note that it does NOT include the combo legs.
|
189
|
-
def serialize *fields
|
190
|
-
[(fields.include?(:con_id) ? [con_id] : []),
|
191
|
-
symbol,
|
192
|
-
sec_type,
|
193
|
-
(fields.include?(:option) ? [expiry, strike, right, multiplier] : []),
|
194
|
-
exchange,
|
195
|
-
(fields.include?(:primary_exchange) ? [primary_exchange] : []),
|
196
|
-
currency,
|
197
|
-
local_symbol,
|
198
|
-
(fields.include?(:sec_id) ? [sec_id_type, sec_id] : []),
|
199
|
-
(fields.include?(:include_expired) ? [include_expired] : []),
|
200
|
-
].flatten
|
201
|
-
end
|
202
|
-
|
203
|
-
def serialize_long *fields
|
204
|
-
serialize :option, :primary_exchange, *fields
|
205
|
-
end
|
206
|
-
|
207
|
-
def serialize_short *fields
|
208
|
-
serialize :option, *fields
|
209
|
-
end
|
210
|
-
|
211
|
-
# Serialize under_comp parameters
|
212
|
-
def serialize_under_comp *args
|
213
|
-
# EClientSocket.java, line 471:
|
214
|
-
if under_comp
|
215
|
-
[true,
|
216
|
-
under_con_id,
|
217
|
-
under_delta,
|
218
|
-
under_price]
|
219
|
-
else
|
220
|
-
[false]
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
# Redefined in BAG subclass
|
225
|
-
def serialize_legs *fields
|
226
|
-
[]
|
227
|
-
end
|
228
|
-
|
229
|
-
# This produces a string uniquely identifying this contract, in the format used
|
230
|
-
# for command line arguments in the IB-Ruby examples. The format is:
|
231
|
-
#
|
232
|
-
# symbol:security_type:expiry:strike:right:multiplier:exchange:primary_exchange:currency:local_symbol
|
233
|
-
#
|
234
|
-
# Fields not needed for a particular security should be left blank
|
235
|
-
# (e.g. strike and right are only relevant for options.)
|
236
|
-
#
|
237
|
-
# For example, to query the British pound futures contract trading on Globex
|
238
|
-
# expiring in September, 2008, the string is:
|
239
|
-
#
|
240
|
-
# GBP:FUT:200809:::62500:GLOBEX::USD:
|
241
|
-
def serialize_ib_ruby
|
242
|
-
serialize_long.join(":")
|
243
|
-
end
|
244
|
-
|
245
|
-
# Contract comparison
|
246
|
-
def == other
|
247
|
-
return false unless other.is_a?(self.class)
|
248
|
-
|
249
|
-
# Different sec_id_type
|
250
|
-
return false if sec_id_type && other.sec_id_type && sec_id_type != other.sec_id_type
|
251
|
-
|
252
|
-
# Different sec_id
|
253
|
-
return false if sec_id && other.sec_id && sec_id != other.sec_id
|
254
|
-
|
255
|
-
# Different under_comp
|
256
|
-
return false if under_comp && other.under_comp && under_comp != other.under_comp
|
257
|
-
|
258
|
-
# Different symbols
|
259
|
-
return false if symbol && other.symbol && symbol != other.symbol
|
260
|
-
|
261
|
-
# Different currency
|
262
|
-
return false if currency && other.currency && currency != other.currency
|
263
|
-
|
264
|
-
# Same con_id for all Bags, but unknown for new Contracts...
|
265
|
-
# 0 or nil con_id matches any
|
266
|
-
return false if con_id != 0 && other.con_id != 0 &&
|
267
|
-
con_id && other.con_id && con_id != other.con_id
|
268
|
-
|
269
|
-
# SMART or nil exchange matches any
|
270
|
-
return false if exchange != 'SMART' && other.exchange != 'SMART' &&
|
271
|
-
exchange && other.exchange && exchange != other.exchange
|
272
|
-
|
273
|
-
# Comparison for Bonds and Options
|
274
|
-
if sec_type == SECURITY_TYPES[:bond] || sec_type == SECURITY_TYPES[:option]
|
275
|
-
return false if right != other.right || strike != other.strike
|
276
|
-
return false if multiplier && other.multiplier && multiplier != other.multiplier
|
277
|
-
return false if expiry[0..5] != other.expiry[0..5]
|
278
|
-
return false unless expiry[6..7] == other.expiry[6..7] ||
|
279
|
-
expiry[6..7].empty? || other.expiry[6..7].empty?
|
280
|
-
end
|
281
|
-
|
282
|
-
# All else being equal...
|
283
|
-
sec_type == other.sec_type
|
284
|
-
end
|
285
|
-
|
286
|
-
def to_s
|
287
|
-
"<Contract: " + instance_variables.map do |key|
|
288
|
-
value = send(key[1..-1])
|
289
|
-
" #{key}=#{value}" unless value.nil? || value == '' || value == 0
|
290
|
-
end.compact.join(',') + " >"
|
291
|
-
end
|
292
|
-
|
293
|
-
def to_human
|
294
|
-
"<Contract: " + [symbol, sec_type, expiry, strike, right, exchange, currency].join("-") + ">"
|
295
|
-
end
|
296
|
-
|
297
|
-
def to_short
|
298
|
-
"#{symbol}#{expiry}#{strike}#{right}#{exchange}#{currency}"
|
299
|
-
end
|
300
|
-
|
301
|
-
end # class Contract
|
302
|
-
end # module Models
|
303
|
-
end # module IB
|
304
|
-
|
305
|
-
# TODO Where should we require this?
|
306
|
-
require 'ib-ruby/models/contract/option'
|
307
|
-
require 'ib-ruby/models/contract/bag'
|
308
|
-
|