ib-ruby 0.8.1 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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