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.
Files changed (128) hide show
  1. data/.gitignore +0 -1
  2. data/HISTORY +5 -0
  3. data/README.md +47 -53
  4. data/Rakefile +2 -1
  5. data/VERSION +1 -1
  6. data/app/assets/javascripts/ib/application.js +15 -0
  7. data/app/assets/javascripts/ib/underlyings.js +2 -0
  8. data/app/assets/stylesheets/ib/application.css +13 -0
  9. data/app/assets/stylesheets/ib/underlyings.css +4 -0
  10. data/app/assets/stylesheets/scaffold.css +56 -0
  11. data/app/controllers/ib/application_controller.rb +5 -0
  12. data/app/controllers/ib/underlyings_controller.rb +87 -0
  13. data/app/helpers/ib/application_helper.rb +4 -0
  14. data/app/helpers/ib/underlyings_helper.rb +4 -0
  15. data/app/models/ib/underlying.rb +5 -0
  16. data/app/views/ib/underlyings/_form.html.erb +33 -0
  17. data/app/views/ib/underlyings/edit.html.erb +6 -0
  18. data/app/views/ib/underlyings/index.html.erb +29 -0
  19. data/app/views/ib/underlyings/new.html.erb +5 -0
  20. data/app/views/ib/underlyings/show.html.erb +25 -0
  21. data/app/views/layouts/ib/application.html.erb +14 -0
  22. data/config/routes.rb +6 -0
  23. data/db/config.yml +19 -0
  24. data/db/migrate/{101_add_executions.rb → 101_add_ib_executions.rb} +2 -2
  25. data/db/migrate/{111_add_bars.rb → 111_add_ib_bars.rb} +2 -2
  26. data/db/migrate/{121_add_order_states.rb → 121_add_ib_order_states.rb} +2 -2
  27. data/db/migrate/{131_add_orders.rb → 131_add_ib_orders.rb} +2 -2
  28. data/db/migrate/{141_add_combo_legs.rb → 141_add_ib_combo_legs.rb} +2 -2
  29. data/db/migrate/{151_add_underlyings.rb → 151_add_ib_underlyings.rb} +2 -2
  30. data/db/migrate/{161_add_contract_details.rb → 161_add_ib_contract_details.rb} +2 -2
  31. data/db/migrate/{171_add_contracts.rb → 171_add_ib_contracts.rb} +2 -2
  32. data/db/schema.rb +245 -0
  33. data/lib/ib/base.rb +97 -0
  34. data/lib/ib/base_properties.rb +140 -0
  35. data/lib/{ib-ruby → ib}/connection.rb +2 -2
  36. data/lib/{ib-ruby → ib}/constants.rb +0 -0
  37. data/lib/{ib-ruby → ib}/db.rb +9 -5
  38. data/lib/ib/engine.rb +35 -0
  39. data/lib/{ib-ruby → ib}/errors.rb +0 -0
  40. data/lib/{ib-ruby → ib}/extensions.rb +2 -2
  41. data/lib/{ib-ruby → ib}/logger.rb +0 -0
  42. data/lib/{ib-ruby → ib}/messages/abstract_message.rb +0 -0
  43. data/lib/{ib-ruby → ib}/messages/incoming/abstract_message.rb +1 -1
  44. data/lib/{ib-ruby → ib}/messages/incoming/alert.rb +0 -0
  45. data/lib/{ib-ruby → ib}/messages/incoming/contract_data.rb +0 -0
  46. data/lib/{ib-ruby → ib}/messages/incoming/delta_neutral_validation.rb +0 -0
  47. data/lib/{ib-ruby → ib}/messages/incoming/execution_data.rb +0 -0
  48. data/lib/{ib-ruby → ib}/messages/incoming/historical_data.rb +0 -0
  49. data/lib/{ib-ruby → ib}/messages/incoming/market_depths.rb +0 -0
  50. data/lib/{ib-ruby → ib}/messages/incoming/next_valid_id.rb +0 -0
  51. data/lib/{ib-ruby → ib}/messages/incoming/open_order.rb +0 -0
  52. data/lib/{ib-ruby → ib}/messages/incoming/order_status.rb +0 -0
  53. data/lib/{ib-ruby → ib}/messages/incoming/portfolio_value.rb +0 -0
  54. data/lib/{ib-ruby → ib}/messages/incoming/real_time_bar.rb +0 -0
  55. data/lib/{ib-ruby → ib}/messages/incoming/scanner_data.rb +0 -0
  56. data/lib/{ib-ruby → ib}/messages/incoming/ticks.rb +0 -0
  57. data/lib/{ib-ruby → ib}/messages/incoming.rb +14 -14
  58. data/lib/{ib-ruby → ib}/messages/outgoing/abstract_message.rb +1 -1
  59. data/lib/{ib-ruby → ib}/messages/outgoing/bar_requests.rb +0 -0
  60. data/lib/{ib-ruby → ib}/messages/outgoing/place_order.rb +0 -0
  61. data/lib/{ib-ruby → ib}/messages/outgoing.rb +5 -5
  62. data/lib/ib/messages.rb +8 -0
  63. data/lib/ib/model.rb +8 -0
  64. data/lib/ib/models.rb +10 -0
  65. data/lib/ib/requires.rb +9 -0
  66. data/lib/{ib-ruby → ib}/socket.rb +0 -0
  67. data/lib/{ib-ruby → ib}/symbols/forex.rb +1 -1
  68. data/lib/{ib-ruby → ib}/symbols/futures.rb +2 -2
  69. data/lib/{ib-ruby → ib}/symbols/options.rb +1 -1
  70. data/lib/{ib-ruby → ib}/symbols/stocks.rb +1 -1
  71. data/lib/ib/symbols.rb +9 -0
  72. data/lib/{ib-ruby → ib}/version.rb +0 -0
  73. data/lib/ib-ruby.rb +2 -24
  74. data/lib/ib.rb +23 -0
  75. data/lib/models/ib/bag.rb +51 -0
  76. data/lib/models/ib/bar.rb +41 -0
  77. data/lib/models/ib/combo_leg.rb +102 -0
  78. data/lib/models/ib/contract.rb +287 -0
  79. data/lib/models/ib/contract_detail.rb +68 -0
  80. data/lib/models/ib/execution.rb +62 -0
  81. data/lib/models/ib/option.rb +60 -0
  82. data/lib/models/ib/order.rb +389 -0
  83. data/lib/models/ib/order_state.rb +126 -0
  84. data/lib/models/ib/underlying.rb +35 -0
  85. data/spec/README.md +34 -2
  86. data/spec/TODO +5 -1
  87. data/spec/comb.rb +13 -0
  88. data/spec/db.rb +1 -1
  89. data/spec/db_helper.rb +3 -3
  90. data/spec/dummy.rb +13 -0
  91. data/spec/gw.rb +4 -0
  92. data/spec/{ib-ruby → ib}/connection_spec.rb +0 -0
  93. data/spec/{ib-ruby → ib}/messages/incoming/alert_spec.rb +0 -0
  94. data/spec/{ib-ruby → ib}/messages/incoming/open_order_spec.rb +0 -0
  95. data/spec/{ib-ruby → ib}/messages/incoming/order_status_spec.rb +16 -17
  96. data/spec/{ib-ruby → ib}/messages/outgoing/account_data_spec.rb +0 -0
  97. data/spec/{ib-ruby → ib}/messages/outgoing/market_data_type_spec.rb +0 -0
  98. data/spec/integration/historic_data_spec.rb +3 -3
  99. data/spec/integration/orders/trades_spec.rb +1 -1
  100. data/spec/{ib-ruby/models → models/ib}/bag_spec.rb +2 -7
  101. data/spec/{ib-ruby/models → models/ib}/bar_spec.rb +1 -6
  102. data/spec/{ib-ruby/models → models/ib}/combo_leg_spec.rb +2 -12
  103. data/spec/{ib-ruby/models → models/ib}/contract_detail_spec.rb +3 -8
  104. data/spec/{ib-ruby/models → models/ib}/contract_spec.rb +4 -12
  105. data/spec/{ib-ruby/models → models/ib}/execution_spec.rb +2 -7
  106. data/spec/{ib-ruby/models → models/ib}/option_spec.rb +1 -6
  107. data/spec/{ib-ruby/models → models/ib}/order_spec.rb +5 -10
  108. data/spec/{ib-ruby/models → models/ib}/order_state_spec.rb +2 -7
  109. data/spec/{ib-ruby/models → models/ib}/underlying_spec.rb +3 -7
  110. data/spec/my.rb +5 -0
  111. data/spec/spec_helper.rb +62 -36
  112. metadata +417 -544
  113. data/lib/ib-ruby/messages.rb +0 -8
  114. data/lib/ib-ruby/models/bag.rb +0 -54
  115. data/lib/ib-ruby/models/bar.rb +0 -43
  116. data/lib/ib-ruby/models/combo_leg.rb +0 -104
  117. data/lib/ib-ruby/models/contract.rb +0 -287
  118. data/lib/ib-ruby/models/contract_detail.rb +0 -70
  119. data/lib/ib-ruby/models/execution.rb +0 -64
  120. data/lib/ib-ruby/models/model.rb +0 -105
  121. data/lib/ib-ruby/models/model_properties.rb +0 -146
  122. data/lib/ib-ruby/models/option.rb +0 -62
  123. data/lib/ib-ruby/models/order.rb +0 -389
  124. data/lib/ib-ruby/models/order_state.rb +0 -128
  125. data/lib/ib-ruby/models/underlying.rb +0 -36
  126. data/lib/ib-ruby/models.rb +0 -15
  127. data/lib/ib-ruby/symbols.rb +0 -9
  128. data/spec/test.rb +0 -61
@@ -1,8 +0,0 @@
1
- module IB
2
- module Messages
3
- end
4
- end
5
-
6
- require 'ib-ruby/messages/outgoing'
7
- require 'ib-ruby/messages/incoming'
8
-
@@ -1,54 +0,0 @@
1
- require 'ib-ruby/models/contract'
2
-
3
- module IB
4
- module Models
5
-
6
- # "BAG" is not really a contract, but a combination (combo) of securities.
7
- # AKA basket or bag of securities. Individual securities in combo are represented
8
- # by ComboLeg objects.
9
- class Bag < Contract
10
- # General Notes:
11
- # 1. :exchange for the leg definition must match that of the combination order.
12
- # The exception is for a STK legs, which must specify the SMART exchange.
13
- # 2. :symbol => "USD" For combo Contract, this is an arbitrary value (like "USD")
14
-
15
- validates_format_of :sec_type, :with => /^bag$/, :message => "should be a bag"
16
- validates_format_of :right, :with => /^none$/, :message => "should be none"
17
- validates_format_of :expiry, :with => /^$/, :message => "should be blank"
18
-
19
- def default_attributes
20
- super.merge :sec_type => :bag #,:legs => Array.new,
21
-
22
- end
23
-
24
- def description
25
- self[:description] || to_human
26
- end
27
-
28
- def to_human
29
- "<Bag: #{[symbol, exchange, currency].join(' ')} legs: #{legs_description} >"
30
- end
31
-
32
- ### Leg-related methods
33
-
34
- # TODO: Rewrite with legs and legs_description being strictly in sync...
35
- # TODO: Find a way to serialize legs without references...
36
- # IB-equivalent leg description.
37
- def legs_description
38
- self[:legs_description] || legs.map { |leg| "#{leg.con_id}|#{leg.weight}" }.join(',')
39
- end
40
-
41
- # Check if two Contracts have same legs (maybe in different order)
42
- def same_legs? other
43
- legs == other.legs ||
44
- legs_description.split(',').sort == other.legs_description.split(',').sort
45
- end
46
-
47
- # Contract comparison
48
- def == other
49
- super && same_legs?(other)
50
- end
51
-
52
- end # class Bag
53
- end # Models
54
- end # IB
@@ -1,43 +0,0 @@
1
- module IB
2
- module Models
3
- # This is a single data point delivered by HistoricData or RealTimeBar messages.
4
- # Instantiate with a Hash of attributes, to be auto-set via initialize in Model.
5
- class Bar < Model.for(:bar)
6
- include ModelProperties
7
-
8
- prop :open, # The bar opening price.
9
- :high, # The high price during the time covered by the bar.
10
- :low, # The low price during the time covered by the bar.
11
- :close, # The bar closing price.
12
- :volume, # Volume
13
- :wap, # Weighted average price during the time covered by the bar.
14
- :trades, # int: When TRADES data history is returned, represents number
15
- # of trades that occurred during the time period the bar covers
16
- :time, # TODO: convert into Time object?
17
- # The date-time stamp of the start of the bar. The format is
18
- # determined by the reqHistoricalData() formatDate parameter.
19
- :has_gaps => :bool # Whether or not there are gaps in the data.
20
-
21
- validates_numericality_of :open, :high, :low, :close, :volume
22
-
23
- # Order comparison
24
- def == other
25
- time == other.time &&
26
- open == other.open &&
27
- high == other.high &&
28
- low == other.low &&
29
- close == other.close &&
30
- wap == other.wap &&
31
- trades == other.trades &&
32
- volume == other.volume
33
- end
34
-
35
- def to_human
36
- "<Bar: #{time} wap #{wap} OHLC #{open} #{high} #{low} #{close} " +
37
- (trades ? "trades #{trades}" : "") + " vol #{volume} gaps #{has_gaps}>"
38
- end
39
-
40
- alias to_s to_human
41
- end # class Bar
42
- end # module Models
43
- end # module IB
@@ -1,104 +0,0 @@
1
- module IB
2
- module Models
3
-
4
- # ComboLeg is essentially a join Model between Combo (BAG) Contract and
5
- # individual Contracts (securities) that this BAG contains.
6
- class ComboLeg < Model.for(:combo_leg)
7
- include ModelProperties
8
-
9
- # BAG Combo Contract that contains this Leg
10
- belongs_to :combo, :class_name => 'Contract'
11
- # Contract that constitutes this Leg
12
- belongs_to :leg_contract, :class_name => 'Contract', :foreign_key => :leg_contract_id
13
-
14
- # General Notes:
15
- # 1. The exchange for the leg definition must match that of the combination order.
16
- # The exception is for a STK leg definition, which must specify the SMART exchange.
17
-
18
- prop :con_id, # int: The unique contract identifier specifying the security.
19
- :ratio, # int: Select the relative number of contracts for the leg you
20
- # are constructing. To help determine the ratio for a
21
- # specific combination order, refer to the Interactive
22
- # Analytics section of the User's Guide.
23
-
24
- :exchange, # String: exchange to which the complete combo order will be routed.
25
- # For institutional customers only! For stock legs when doing short sale
26
- :short_sale_slot, # int: 0 - retail(default), 1 = clearing broker, 2 = third party
27
- :designated_location, # String: Only for shortSaleSlot == 2.
28
- # Otherwise leave blank or orders will be rejected.
29
- :exempt_code, # int: ?
30
- [:side, :action] => PROPS[:side], # String: Action/side: BUY/SELL/SSHORT/SSHORTX
31
- :open_close => PROPS[:open_close]
32
- # int: Whether the order is an open or close order. Values:
33
- # SAME = 0 Same as the parent security. The only option for retail customers.
34
- # OPEN = 1 Open. This value is only valid for institutional customers.
35
- # CLOSE = 2 Close. This value is only valid for institutional customers.
36
- # UNKNOWN = 3
37
-
38
- # Extra validations
39
- validates_numericality_of :ratio, :con_id
40
- validates_format_of :designated_location, :with => /^$/,
41
- :message => "should be blank or orders will be rejected"
42
-
43
- def default_attributes
44
- super.merge :con_id => 0,
45
- :ratio => 1,
46
- :side => :buy,
47
- :open_close => :same, # The only option for retail customers.
48
- :short_sale_slot => :default,
49
- :designated_location => '',
50
- :exchange => 'SMART', # Unless SMART, Order modification fails
51
- :exempt_code => -1
52
- end
53
-
54
- # Leg's weight is a combination of action and ratio
55
- def weight
56
- side == :buy ? ratio : -ratio
57
- end
58
-
59
- def weight= value
60
- value = value.to_i
61
- if value > 0
62
- self.side = :buy
63
- self.ratio = value
64
- else
65
- self.side = :sell
66
- self.ratio = -value
67
- end
68
- end
69
-
70
- # Some messages include open_close, some don't. wtf.
71
- def serialize *fields
72
- [con_id,
73
- ratio,
74
- side.to_sup,
75
- exchange,
76
- (fields.include?(:extended) ?
77
- [self[:open_close],
78
- self[:short_sale_slot],
79
- designated_location,
80
- exempt_code] :
81
- [])
82
- ].flatten
83
- end
84
-
85
- def to_human
86
- "<ComboLeg: #{side} #{ratio} con_id #{con_id} at #{exchange}>"
87
- end
88
-
89
- # Order comparison
90
- def == other
91
- other && other.is_a?(ComboLeg) &&
92
- con_id == other.con_id &&
93
- ratio == other.ratio &&
94
- open_close == other.open_close &&
95
- short_sale_slot == other.short_sale_slot&&
96
- exempt_code == other.exempt_code &&
97
- side == other.side &&
98
- exchange == other.exchange &&
99
- designated_location == other.designated_location
100
- end
101
-
102
- end # ComboLeg
103
- end # module Models
104
- end # module IB
@@ -1,287 +0,0 @@
1
- require 'ib-ruby/models/contract_detail'
2
- require 'ib-ruby/models/underlying'
3
-
4
- module IB
5
- module Models
6
- class Contract < Model.for(:contract)
7
- include ModelProperties
8
-
9
- # Fields are Strings unless noted otherwise
10
- prop :con_id, # int: The unique contract identifier.
11
- :currency, # Only needed if there is an ambiguity, e.g. when SMART exchange
12
- # and IBM is being requested (IBM can trade in GBP or USD).
13
-
14
- :legs_description, # received in OpenOrder for all combos
15
-
16
- :sec_type, # Security type. Valid values are: SECURITY_TYPES
17
-
18
- :sec_id, # Unique identifier of the given secIdType.
19
-
20
- :sec_id_type => :sup, # Security identifier, when querying contract details or
21
- # when placing orders. Supported identifiers are:
22
- # - ISIN (Example: Apple: US0378331005)
23
- # - CUSIP (Example: Apple: 037833100)
24
- # - SEDOL (6-AN + check digit. Example: BAE: 0263494)
25
- # - RIC (exchange-independent RIC Root and exchange-
26
- # identifying suffix. Ex: AAPL.O for Apple on NASDAQ.)
27
-
28
- :symbol => :s, # This is the symbol of the underlying asset.
29
-
30
- :local_symbol => :s, # Local exchange symbol of the underlying asset
31
-
32
- # Future/option contract multiplier (only needed when multiple possibilities exist)
33
- :multiplier => {:set => :i},
34
-
35
- :strike => :f, # double: The strike price.
36
- :expiry => :s, # The expiration date. Use the format YYYYMM or YYYYMMDD
37
- :exchange => :sup, # The order destination, such as Smart.
38
- :primary_exchange => :sup, # Non-SMART exchange where the contract trades.
39
- :include_expired => :bool, # When true, contract details requests and historical
40
- # data queries can be performed pertaining to expired contracts.
41
- # Note: Historical data queries on expired contracts are
42
- # limited to the last year of the contracts life, and are
43
- # only supported for expired futures contracts.
44
- # This field can NOT be set to true for orders.
45
-
46
-
47
- # Specifies a Put or Call. Valid input values are: P, PUT, C, CALL
48
- :right =>
49
- {:set => proc { |val|
50
- self[:right] =
51
- case val.to_s.upcase
52
- when 'NONE', '', '0', '?'
53
- ''
54
- when 'PUT', 'P'
55
- 'P'
56
- when 'CALL', 'C'
57
- 'C'
58
- else
59
- val
60
- end },
61
- :validate => {:format => {:with => /^put$|^call$|^none$/,
62
- :message => "should be put, call or none"}}
63
- }
64
-
65
- attr_accessor :description # NB: local to ib-ruby, not part of TWS.
66
-
67
- ### Associations
68
-
69
- has_many :orders # Placed for this Contract
70
-
71
- has_one :contract_detail # Volatile info about this Contract
72
-
73
- # For Contracts that are part of BAG
74
- has_one :leg, :class_name => 'ComboLeg', :foreign_key => :leg_contract_id
75
- has_one :combo, :class_name => 'Contract', :through => :leg
76
-
77
- # for Combo/BAG Contracts that contain ComboLegs
78
- has_many :combo_legs, :foreign_key => :combo_id
79
- has_many :leg_contracts, :class_name => 'Contract', :through => :combo_legs
80
- alias legs combo_legs
81
- alias legs= combo_legs=
82
- alias combo_legs_description legs_description
83
- alias combo_legs_description= legs_description=
84
-
85
- # for Delta-Neutral Combo Contracts
86
- has_one :underlying
87
- alias under_comp underlying
88
- alias under_comp= underlying=
89
-
90
-
91
- ### Extra validations
92
- validates_inclusion_of :sec_type, :in => CODES[:sec_type].keys,
93
- :message => "should be valid security type"
94
-
95
- validates_format_of :expiry, :with => /^\d{6}$|^\d{8}$|^$/,
96
- :message => "should be YYYYMM or YYYYMMDD"
97
-
98
- validates_format_of :primary_exchange, :without => /SMART/,
99
- :message => "should not be SMART"
100
-
101
- validates_format_of :sec_id_type, :with => /ISIN|SEDOL|CUSIP|RIC|^$/,
102
- :message => "should be valid security identifier"
103
-
104
- validates_numericality_of :multiplier, :strike, :allow_nil => true
105
-
106
- def default_attributes
107
- super.merge :con_id => 0,
108
- :strike => 0.0,
109
- :right => :none, # Not an option
110
- :exchange => 'SMART',
111
- :include_expired => false
112
- end
113
-
114
- # This returns an Array of data from the given contract.
115
- # Different messages serialize contracts differently. Go figure.
116
- # Note that it does NOT include the combo legs.
117
- # serialize [:option, :con_id, :include_expired, :sec_id]
118
- def serialize *fields
119
- [(fields.include?(:con_id) ? [con_id] : []),
120
- symbol,
121
- self[:sec_type],
122
- (fields.include?(:option) ?
123
- [expiry,
124
- strike,
125
- self[:right],
126
- multiplier] : []),
127
- exchange,
128
- (fields.include?(:primary_exchange) ? [primary_exchange] : []),
129
- currency,
130
- local_symbol,
131
- (fields.include?(:sec_id) ? [sec_id_type, sec_id] : []),
132
- (fields.include?(:include_expired) ? [include_expired] : []),
133
- ].flatten
134
- end
135
-
136
- def serialize_long *fields
137
- serialize :option, :primary_exchange, *fields
138
- end
139
-
140
- def serialize_short *fields
141
- serialize :option, *fields
142
- end
143
-
144
- # Serialize under_comp parameters: EClientSocket.java, line 471
145
- def serialize_under_comp *args
146
- under_comp ? under_comp.serialize : [false]
147
- end
148
-
149
- # Defined in Contract, not BAG subclass to keep code DRY
150
- def serialize_legs *fields
151
- case
152
- when !bag?
153
- []
154
- when legs.empty?
155
- [0]
156
- else
157
- [legs.size, legs.map { |leg| leg.serialize *fields }].flatten
158
- end
159
- end
160
-
161
- # This produces a string uniquely identifying this contract, in the format used
162
- # for command line arguments in the IB-Ruby examples. The format is:
163
- #
164
- # symbol:sec_type:expiry:strike:right:multiplier:exchange:primary_exchange:currency:local_symbol
165
- #
166
- # Fields not needed for a particular security should be left blank
167
- # (e.g. strike and right are only relevant for options.)
168
- #
169
- # For example, to query the British pound futures contract trading on Globex
170
- # expiring in September, 2008, the string is:
171
- #
172
- # GBP:FUT:200809:::62500:GLOBEX::USD:
173
- def serialize_ib_ruby
174
- serialize_long.join(":")
175
- end
176
-
177
- # Contract comparison
178
- def == other
179
- return false unless other.is_a?(self.class)
180
-
181
- # Different sec_id_type
182
- return false if sec_id_type && other.sec_id_type && sec_id_type != other.sec_id_type
183
-
184
- # Different sec_id
185
- return false if sec_id && other.sec_id && sec_id != other.sec_id
186
-
187
- # Different symbols
188
- return false if symbol && other.symbol && symbol != other.symbol
189
-
190
- # Different currency
191
- return false if currency && other.currency && currency != other.currency
192
-
193
- # Same con_id for all Bags, but unknown for new Contracts...
194
- # 0 or nil con_id matches any
195
- return false if con_id != 0 && other.con_id != 0 &&
196
- con_id && other.con_id && con_id != other.con_id
197
-
198
- # SMART or nil exchange matches any
199
- return false if exchange != 'SMART' && other.exchange != 'SMART' &&
200
- exchange && other.exchange && exchange != other.exchange
201
-
202
- # Comparison for Bonds and Options
203
- if bond? || option?
204
- return false if right != other.right || strike != other.strike
205
- return false if multiplier && other.multiplier &&
206
- multiplier != other.multiplier
207
- return false if expiry && expiry[0..5] != other.expiry[0..5]
208
- return false unless expiry && (expiry[6..7] == other.expiry[6..7] ||
209
- expiry[6..7].empty? || other.expiry[6..7].empty?)
210
- end
211
-
212
- # All else being equal...
213
- sec_type == other.sec_type
214
- end
215
-
216
- def to_s
217
- "<Contract: " + instance_variables.map do |key|
218
- value = send(key[1..-1])
219
- " #{key}=#{value}" unless value.nil? || value == '' || value == 0
220
- end.compact.join(',') + " >"
221
- end
222
-
223
- def to_human
224
- "<Contract: " +
225
- [symbol,
226
- sec_type,
227
- (expiry == '' ? nil : expiry),
228
- (right == :none ? nil : right),
229
- (strike == 0 ? nil : strike),
230
- exchange,
231
- currency
232
- ].compact.join(" ") + ">"
233
- end
234
-
235
- def to_short
236
- "#{symbol}#{expiry}#{strike}#{right}#{exchange}#{currency}"
237
- end
238
-
239
- # Testing for type of contract:
240
-
241
- def bag?
242
- self[:sec_type] == 'BAG'
243
- end
244
-
245
- def bond?
246
- self[:sec_type] == 'BOND'
247
- end
248
-
249
- def stock?
250
- self[:sec_type] == 'STK'
251
- end
252
-
253
- def option?
254
- self[:sec_type] == 'OPT'
255
- end
256
-
257
- end # class Contract
258
-
259
-
260
- ### Now let's deal with Contract subclasses
261
-
262
- require 'ib-ruby/models/option'
263
- require 'ib-ruby/models/bag'
264
-
265
- class Contract
266
- # Specialized Contract subclasses representing different security types
267
- Subclasses = Hash.new(Contract)
268
- Subclasses[:bag] = IB::Models::Bag
269
- Subclasses[:option] = IB::Models::Option
270
-
271
- # This returns a Contract initialized from the serialize_ib_ruby format string.
272
- def self.build opts = {}
273
- subclass = VALUES[:sec_type][opts[:sec_type]] || opts[:sec_type].to_sym
274
- Contract::Subclasses[subclass].new opts
275
- end
276
-
277
- # This returns a Contract initialized from the serialize_ib_ruby format string.
278
- def self.from_ib_ruby string
279
- keys = [:symbol, :sec_type, :expiry, :strike, :right, :multiplier,
280
- :exchange, :primary_exchange, :currency, :local_symbol]
281
- props = Hash[keys.zip(string.split(":"))]
282
- props.delete_if { |k, v| v.nil? || v.empty? }
283
- Contract.build props
284
- end
285
- end # class Contract
286
- end # module Models
287
- end # module IB
@@ -1,70 +0,0 @@
1
- module IB
2
- module Models
3
-
4
- # Additional Contract properties (volatile, therefore extracted)
5
- class ContractDetail < Model.for(:contract_detail)
6
- include ModelProperties
7
-
8
- belongs_to :contract
9
- alias summary contract
10
- alias summary= contract=
11
-
12
- # All fields Strings, unless specified otherwise:
13
- prop :market_name, # The market name for this contract.
14
- :trading_class, # The trading class name for this contract.
15
- :min_tick, # double: The minimum price tick.
16
- :price_magnifier, # int: Allows execution and strike prices to be
17
- # reported consistently with market data, historical data and the
18
- # order price: Z on LIFFE is reported in index points, not GBP.
19
-
20
- :order_types, # The list of valid order types for this contract.
21
- :valid_exchanges, # The list of exchanges this contract is traded on.
22
- :under_con_id, # int: The underlying contract ID.
23
- :long_name, # Descriptive name of the asset.
24
- :contract_month, # The contract month of the underlying futures contract.
25
-
26
- # The industry classification of the underlying/product:
27
- :industry, # Wide industry. For example, Financial.
28
- :category, # Industry category. For example, InvestmentSvc.
29
- :subcategory, # Subcategory. For example, Brokerage.
30
- [:time_zone, :time_zone_id], # Time zone for the trading hours (e.g. EST)
31
- :trading_hours, # The trading hours of the product. For example:
32
- # 20090507:0700-1830,1830-2330;20090508:CLOSED.
33
- :liquid_hours, # The liquid trading hours of the product. For example,
34
- # 20090507:0930-1600;20090508:CLOSED.
35
-
36
- # BOND values:
37
- :cusip, # The nine-character bond CUSIP or the 12-character SEDOL.
38
- :ratings, # Credit rating of the issuer. Higher rating is less risky investment.
39
- # Bond ratings are from Moody's and S&P respectively.
40
- :desc_append, # Additional descriptive information about the bond.
41
- :bond_type, # The type of bond, such as "CORP."
42
- :coupon_type, # The type of bond coupon.
43
- :coupon, # double: The interest rate used to calculate the amount you
44
- # will receive in interest payments over the year. default 0
45
- :maturity, # The date on which the issuer must repay bond face value
46
- :issue_date, # The date the bond was issued.
47
- :next_option_date, # only if bond has embedded options.
48
- :next_option_type, # only if bond has embedded options.
49
- :notes, # Additional notes, if populated for the bond in IB's database
50
- :callable => :bool, # Can be called by the issuer under certain conditions.
51
- :puttable => :bool, # Can be sold back to the issuer under certain conditions
52
- :convertible => :bool, # Can be converted to stock under certain conditions.
53
- :next_option_partial => :bool # # only if bond has embedded options.
54
-
55
- # Extra validations
56
- validates_format_of :time_zone, :with => /^\w{3}$/, :message => 'should be XXX'
57
-
58
- def default_attributes
59
- super.merge :coupon => 0.0,
60
- :under_con_id => 0,
61
- :min_tick => 0,
62
- :callable => false,
63
- :puttable => false,
64
- :convertible => false,
65
- :next_option_partial => false
66
- end
67
-
68
- end # class ContractDetail
69
- end # module Models
70
- end # module IB
@@ -1,64 +0,0 @@
1
- module IB
2
- module Models
3
- # This is IB Order execution report.
4
- # Instantiate with a Hash of attributes, to be auto-set via initialize in Model.
5
- class Execution < Model.for(:execution)
6
- include ModelProperties
7
-
8
- belongs_to :order
9
-
10
- prop :local_id, # int: order id. TWS orders have a fixed order id of 0.
11
- :client_id, # int: client id. TWS orders have a fixed client id of 0.
12
- :perm_id, # int: TWS id used to identify orders over TWS sessions
13
- :exec_id, # String: Unique order execution id over TWS sessions.
14
- :time, # # TODO: convert into Time object?
15
- # String: The order execution time.
16
- :exchange, # String: Exchange that executed the order.
17
- :order_ref, # int: Same order_ref as in corresponding Order
18
- :price, # double: The order execution price.
19
- :average_price, # double: Average price. Used in regular trades, combo
20
- # trades and legs of the combo.
21
- [:quantity, :shares], # int: The number of shares filled.
22
- :cumulative_quantity, # int: Cumulative quantity. Used in regular
23
- # trades, combo trades and legs of the combo
24
- :liquidation => :bool, # This position is liquidated last should the need arise.
25
- [:account_name, :account_number] => :s, # The customer account number.
26
- [:side, :action] => PROPS[:side] # Was the transaction a buy or a sale: BOT|SLD
27
-
28
- # Extra validations
29
- validates_numericality_of :quantity, :cumulative_quantity, :price, :average_price
30
- validates_numericality_of :local_id, :client_id, :perm_id, :only_integer => true
31
-
32
- def default_attributes
33
- super.merge :local_id => 0,
34
- :client_id => 0,
35
- :quantity => 0,
36
- :price => 0,
37
- :perm_id => 0,
38
- :liquidation => false
39
- end
40
-
41
- # Comparison
42
- def == other
43
- perm_id == other.perm_id &&
44
- local_id == other.local_id && # ((p __LINE__)||true) &&
45
- client_id == other.client_id &&
46
- exec_id == other.exec_id &&
47
- time == other.time &&
48
- exchange == other.exchange &&
49
- order_ref == other.order_ref &&
50
- side == other.side
51
- # TODO: || compare all attributes!
52
- end
53
-
54
- def to_human
55
- "<Execution: #{time} #{side} #{quantity} at #{price} on #{exchange}, " +
56
- "cumulative #{cumulative_quantity} at #{average_price}, " +
57
- "ids #{local_id}/#{perm_id}/#{exec_id}>"
58
- end
59
-
60
- alias to_s to_human
61
-
62
- end # Execution
63
- end # module Models
64
- end # module IB