ib-api 10.33.4 → 972.0

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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/Gemfile +2 -3
  4. data/Gemfile.lock +52 -67
  5. data/README.md +8 -60
  6. data/VERSION +1 -1
  7. data/api.gemspec +3 -10
  8. data/bin/console +38 -39
  9. data/bin/console.yml +2 -2
  10. data/changelog.md +0 -25
  11. data/example/README.md +76 -0
  12. data/example/account_info +54 -0
  13. data/example/account_positions +30 -0
  14. data/example/account_summary +88 -0
  15. data/example/cancel_orders +74 -0
  16. data/example/fa_accounts +25 -0
  17. data/example/fundamental_data +40 -0
  18. data/example/historic_data_cli +186 -0
  19. data/example/list_orders +45 -0
  20. data/example/portfolio_csv +81 -0
  21. data/example/scanner_data +62 -0
  22. data/example/template +19 -0
  23. data/example/tick_data +28 -0
  24. data/lib/extensions/class-extensions.rb +87 -0
  25. data/lib/ib/base.rb +1 -7
  26. data/lib/ib/base_properties.rb +12 -30
  27. data/lib/ib/connection.rb +269 -418
  28. data/lib/ib/constants.rb +22 -31
  29. data/lib/ib/errors.rb +1 -9
  30. data/lib/ib/logger.rb +26 -0
  31. data/lib/ib/messages/abstract_message.rb +43 -10
  32. data/lib/ib/messages/incoming/abstract_message.rb +98 -98
  33. data/lib/ib/messages/incoming/account_value.rb +78 -0
  34. data/lib/ib/messages/incoming/alert.rb +4 -4
  35. data/lib/ib/messages/incoming/contract_data.rb +29 -32
  36. data/lib/ib/messages/incoming/execution_data.rb +3 -3
  37. data/lib/ib/messages/incoming/historical_data.rb +33 -14
  38. data/lib/ib/messages/incoming/{market_depth.rb → market_depths.rb} +10 -0
  39. data/lib/ib/messages/incoming/next_valid_id.rb +0 -1
  40. data/lib/ib/messages/incoming/open_order.rb +201 -214
  41. data/lib/ib/messages/incoming/order_status.rb +1 -1
  42. data/lib/ib/messages/incoming/portfolio_value.rb +58 -27
  43. data/lib/ib/messages/incoming/scanner_data.rb +1 -1
  44. data/lib/ib/messages/incoming/ticks.rb +268 -0
  45. data/lib/ib/messages/incoming.rb +95 -136
  46. data/lib/ib/messages/outgoing/abstract_message.rb +22 -18
  47. data/lib/ib/messages/outgoing/{request_account_summary.rb → account_requests.rb} +40 -7
  48. data/lib/ib/messages/outgoing/{bar_request_message.rb → bar_requests.rb} +16 -13
  49. data/lib/ib/messages/outgoing/place_order.rb +198 -138
  50. data/lib/ib/messages/outgoing/{request_market_data.rb → request_marketdata.rb} +29 -32
  51. data/lib/ib/messages/outgoing/request_tick_data.rb +21 -0
  52. data/lib/ib/messages/outgoing.rb +160 -133
  53. data/lib/ib/messages.rb +7 -47
  54. data/lib/ib/model.rb +4 -0
  55. data/lib/ib/models.rb +14 -0
  56. data/lib/{server_versions.rb → ib/server_versions.rb} +9 -40
  57. data/lib/ib/socket.rb +147 -45
  58. data/lib/ib/support.rb +158 -240
  59. data/lib/ib/version.rb +1 -1
  60. data/lib/ib-api.rb +5 -42
  61. data/lib/models/ib/account.rb +85 -0
  62. data/{models → lib/models}/ib/account_value.rb +5 -5
  63. data/{models → lib/models}/ib/bag.rb +7 -7
  64. data/{models → lib/models}/ib/bar.rb +2 -2
  65. data/{models → lib/models}/ib/combo_leg.rb +4 -26
  66. data/lib/models/ib/condition.rb +245 -0
  67. data/{models → lib/models}/ib/contract.rb +170 -166
  68. data/{models → lib/models}/ib/contract_detail.rb +15 -25
  69. data/{models → lib/models}/ib/execution.rb +1 -1
  70. data/{models → lib/models}/ib/forex.rb +2 -1
  71. data/lib/models/ib/future.rb +15 -0
  72. data/{models → lib/models}/ib/index.rb +3 -2
  73. data/lib/models/ib/option.rb +78 -0
  74. data/lib/models/ib/option_detail.rb +55 -0
  75. data/{models → lib/models}/ib/order.rb +165 -366
  76. data/{models → lib/models}/ib/order_state.rb +22 -25
  77. data/lib/models/ib/portfolio_value.rb +64 -0
  78. data/lib/models/ib/stock.rb +16 -0
  79. data/{models → lib/models}/ib/underlying.rb +5 -3
  80. data/lib/models/ib/vertical.rb +96 -0
  81. data/lib/requires.rb +12 -0
  82. metadata +64 -188
  83. data/CLAUDE.md +0 -131
  84. data/LLM_GUIDE.md +0 -388
  85. data/bin/simple +0 -91
  86. data/conditions/ib/execution_condition.rb +0 -31
  87. data/conditions/ib/margin_condition.rb +0 -28
  88. data/conditions/ib/order_condition.rb +0 -29
  89. data/conditions/ib/percent_change_condition.rb +0 -34
  90. data/conditions/ib/price_condition.rb +0 -44
  91. data/conditions/ib/time_condition.rb +0 -42
  92. data/conditions/ib/volume_condition.rb +0 -36
  93. data/lib/class_extensions.rb +0 -167
  94. data/lib/ib/contract.rb +0 -30
  95. data/lib/ib/messages/incoming/abstract_tick.rb +0 -25
  96. data/lib/ib/messages/incoming/account_message.rb +0 -26
  97. data/lib/ib/messages/incoming/contract_message.rb +0 -13
  98. data/lib/ib/messages/incoming/histogram_data.rb +0 -30
  99. data/lib/ib/messages/incoming/historical_data_update.rb +0 -50
  100. data/lib/ib/messages/incoming/managed_accounts.rb +0 -21
  101. data/lib/ib/messages/incoming/market_depth_l2.rb +0 -15
  102. data/lib/ib/messages/incoming/position_data.rb +0 -21
  103. data/lib/ib/messages/incoming/positions_multi.rb +0 -15
  104. data/lib/ib/messages/incoming/receive_fa.rb +0 -30
  105. data/lib/ib/messages/incoming/tick_by_tick.rb +0 -77
  106. data/lib/ib/messages/incoming/tick_efp.rb +0 -18
  107. data/lib/ib/messages/incoming/tick_generic.rb +0 -12
  108. data/lib/ib/messages/incoming/tick_option.rb +0 -60
  109. data/lib/ib/messages/incoming/tick_price.rb +0 -60
  110. data/lib/ib/messages/incoming/tick_size.rb +0 -55
  111. data/lib/ib/messages/incoming/tick_string.rb +0 -13
  112. data/lib/ib/messages/outgoing/new-place-order.rb +0 -193
  113. data/lib/ib/messages/outgoing/old-place-order.rb +0 -147
  114. data/lib/ib/messages/outgoing/request_historical_data.rb +0 -182
  115. data/lib/ib/messages/outgoing/request_market_depth.rb +0 -57
  116. data/lib/ib/messages/outgoing/request_real_time_bars.rb +0 -48
  117. data/lib/ib/messages/outgoing/request_scanner_subscription.rb +0 -73
  118. data/lib/ib/messages/outgoing/request_tick_by_tick_data.rb +0 -21
  119. data/lib/ib/order_condition.rb +0 -26
  120. data/lib/ib/plugins.rb +0 -27
  121. data/lib/ib/prepare_data.rb +0 -61
  122. data/lib/ib/raw_message_parser.rb +0 -99
  123. data/lib/support/array_function.rb +0 -28
  124. data/lib/support/logging.rb +0 -45
  125. data/models/ib/account.rb +0 -72
  126. data/models/ib/future.rb +0 -64
  127. data/models/ib/option.rb +0 -149
  128. data/models/ib/option_detail.rb +0 -84
  129. data/models/ib/portfolio_value.rb +0 -86
  130. data/models/ib/spread.rb +0 -176
  131. data/models/ib/stock.rb +0 -25
  132. data/plugins/ib/advanced-account.rb +0 -442
  133. data/plugins/ib/alerts/base-alert.rb +0 -125
  134. data/plugins/ib/alerts/gateway-alerts.rb +0 -15
  135. data/plugins/ib/alerts/order-alerts.rb +0 -73
  136. data/plugins/ib/auto-adjust.rb +0 -0
  137. data/plugins/ib/connection-tools.rb +0 -122
  138. data/plugins/ib/eod.rb +0 -326
  139. data/plugins/ib/greeks.rb +0 -102
  140. data/plugins/ib/managed-accounts.rb +0 -274
  141. data/plugins/ib/market-price.rb +0 -150
  142. data/plugins/ib/option-chain.rb +0 -167
  143. data/plugins/ib/order-flow.rb +0 -157
  144. data/plugins/ib/order-prototypes/abstract.rb +0 -67
  145. data/plugins/ib/order-prototypes/adaptive.rb +0 -40
  146. data/plugins/ib/order-prototypes/all-in-one.rb +0 -46
  147. data/plugins/ib/order-prototypes/combo.rb +0 -46
  148. data/plugins/ib/order-prototypes/forex.rb +0 -40
  149. data/plugins/ib/order-prototypes/limit.rb +0 -193
  150. data/plugins/ib/order-prototypes/market.rb +0 -116
  151. data/plugins/ib/order-prototypes/pegged.rb +0 -169
  152. data/plugins/ib/order-prototypes/premarket.rb +0 -31
  153. data/plugins/ib/order-prototypes/stop.rb +0 -202
  154. data/plugins/ib/order-prototypes/volatility.rb +0 -39
  155. data/plugins/ib/order-prototypes.rb +0 -118
  156. data/plugins/ib/probability-of-expiring.rb +0 -109
  157. data/plugins/ib/process-orders.rb +0 -155
  158. data/plugins/ib/roll.rb +0 -86
  159. data/plugins/ib/spread-prototypes/butterfly.rb +0 -77
  160. data/plugins/ib/spread-prototypes/calendar.rb +0 -97
  161. data/plugins/ib/spread-prototypes/stock-spread.rb +0 -56
  162. data/plugins/ib/spread-prototypes/straddle.rb +0 -70
  163. data/plugins/ib/spread-prototypes/strangle.rb +0 -93
  164. data/plugins/ib/spread-prototypes/vertical.rb +0 -83
  165. data/plugins/ib/spread-prototypes.rb +0 -70
  166. data/plugins/ib/symbols/abstract.rb +0 -136
  167. data/plugins/ib/symbols/bonds.rb +0 -28
  168. data/plugins/ib/symbols/cfd.rb +0 -19
  169. data/plugins/ib/symbols/combo.rb +0 -46
  170. data/plugins/ib/symbols/commodity.rb +0 -17
  171. data/plugins/ib/symbols/forex.rb +0 -41
  172. data/plugins/ib/symbols/futures.rb +0 -127
  173. data/plugins/ib/symbols/index.rb +0 -43
  174. data/plugins/ib/symbols/options.rb +0 -99
  175. data/plugins/ib/symbols/stocks.rb +0 -44
  176. data/plugins/ib/symbols/version.rb +0 -5
  177. data/plugins/ib/symbols.rb +0 -118
  178. data/plugins/ib/verify.rb +0 -226
  179. data/symbols/w20.yml +0 -210
  180. data/t.txt +0 -20
  181. data/update.md +0 -71
data/lib/ib-api.rb CHANGED
@@ -1,44 +1,7 @@
1
+ module IB
1
2
 
2
- require "zeitwerk"
3
- require "active_model"
4
- require 'active_support/concern'
5
- require 'active_support/core_ext/module/attribute_accessors.rb'
6
- require 'bigdecimal/util' # provides .to_d for numeric and string classes
7
- require 'class_extensions'
8
- require 'logger'
9
- require 'terminal-table'
10
- require 'workflow'
3
+ end
4
+ IbRuby = IB
5
+ Ib = IB
11
6
 
12
- #require 'ib/version'
13
- #require 'ib/connection'
14
-
15
- require "server_versions"
16
-
17
- require 'ib/constants'
18
- require 'ib/errors'
19
- #loader = Zeitwerk::Loader.new
20
- loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
21
- loader.ignore("#{__dir__}/server_versions.rb")
22
- loader.ignore("#{__dir__}/ib-api.rb")
23
- loader.ignore("#{__dir__}/ib/contract.rb")
24
- loader.ignore("#{__dir__}/ib/constants.rb")
25
- loader.ignore("#{__dir__}/ib/errors.rb")
26
- loader.ignore("#{__dir__}/ib/order_condition.rb")
27
- loader.ignore("#{__dir__}/ib/messages/outgoing/old-place-order.rb")
28
- loader.ignore("#{__dir__}/ib/messages/outgoing/new-place-order.rb")
29
- #loader.ignore("#{__dir__}/models")
30
- loader.inflector.inflect(
31
- "ib" => "IB",
32
- "receive_fa" => "ReceiveFA",
33
- "tick_efp" => "TickEFP",
34
- )
35
- #loader.push_dir("#{__dir__}")
36
- loader.push_dir("#{__dir__}/../models/")
37
- loader.push_dir("#{__dir__}/../conditions/")
38
- loader.setup
39
- loader.eager_load
40
- #require 'requires'
41
- require 'ib/contract.rb'
42
- require 'ib/order_condition.rb'
43
- #IbRuby = Ib
44
- #IB = Ib
7
+ require 'requires'
@@ -0,0 +1,85 @@
1
+ module IB
2
+ class Account < IB::Model
3
+ include BaseProperties
4
+ # include Redis::Objects
5
+ # attr_accessible :alias, :account, :connected
6
+
7
+ prop :account, # String
8
+ :alias, #
9
+ :type,
10
+ :last_updated,
11
+ :connected => :bool
12
+
13
+ # redis_id_field :account
14
+ # value :my_alias
15
+ # value :the_account
16
+ # value :active
17
+
18
+
19
+ validates_format_of :account, :with => /\A[D]?[UF]{1}\d{5,8}\z/ , :message => 'should be (X)X00000'
20
+
21
+ # in tableless mode the scope is ignored
22
+
23
+ has_many :account_values
24
+ has_many :portfolio_values
25
+ has_many :contracts
26
+ has_many :orders
27
+ has_many :focuses
28
+
29
+ def default_attributes
30
+ super.merge account: 'X000000'
31
+ super.merge alias: ''
32
+ super.merge type: 'Account'
33
+ super.merge connected: false
34
+ end
35
+
36
+ def logger #nodoc#
37
+ Connection.logger
38
+ end
39
+
40
+ # Setze Account connect/disconnect und undate!
41
+ def connect!
42
+ update_attribute :connected , true
43
+ end
44
+ def disconnect!
45
+ update_attribute :connected , false
46
+ end
47
+
48
+ def print_type #nodoc#
49
+ (test_environment? ? "demo_" : "") + ( user? ? "user" : "advisor" )
50
+ end
51
+
52
+ def advisor?
53
+ !!(type =~ /Advisor/ || account =~ /\A[D]?[F]{1}/)
54
+ end
55
+
56
+ def user?
57
+ !!(type =~ /User/ || account =~ /\A[D]?[U]{1}/)
58
+ end
59
+
60
+ def test_environment?
61
+ !!(account =~ /^[D]{1}/)
62
+ end
63
+
64
+ def == other
65
+ super(other) ||
66
+ other.is_a?(self.class) && account == other.account
67
+ end
68
+
69
+ def to_human
70
+ a = if self.alias.present? && self.alias != account
71
+ " alias: "+ self.alias
72
+ else
73
+ ""
74
+ end
75
+ "<#{print_type} #{account}#{a}>"
76
+ end
77
+
78
+ def name #nodoc#
79
+ self.alias.present? ? self.alias : account
80
+ end
81
+
82
+ # alias :id :account
83
+ end # class
84
+
85
+ end # module
@@ -1,13 +1,13 @@
1
1
  module IB
2
2
  # Instantiate with a Hash of attributes, to be auto-set via initialize in Model.
3
- class AccountValue < IB::Base
3
+ class AccountValue < IB::Model
4
4
  include BaseProperties
5
5
 
6
6
  belongs_to :account
7
7
 
8
8
  prop :key,
9
- :value,
10
- :currency
9
+ :value,
10
+ :currency
11
11
 
12
12
 
13
13
  # comparison
@@ -20,8 +20,8 @@ module IB
20
20
  end
21
21
  def default_attributes
22
22
  super.merge key: 'AccountValue',
23
- value: 0,
24
- currency: 'USD'
23
+ value: 0,
24
+ currency: 'USD'
25
25
  end
26
26
 
27
27
  def to_human
@@ -1,3 +1,5 @@
1
+ require 'models/ib/contract'
2
+
1
3
  module IB
2
4
 
3
5
  # "BAG" is not really a contract, but a combination (combo) of securities.
@@ -9,9 +11,6 @@ module IB
9
11
  # The exception is for a STK legs, which must specify the SMART exchange.
10
12
  # 2. :symbol => "USD" For combo Contract, this is an arbitrary value (like "USD")
11
13
 
12
- prop :combo_params # bags carry "non_guarantieed: true/false" in combo_params
13
-
14
-
15
14
  validates_format_of :sec_type, :with => /\Abag\z/, :message => "should be a bag"
16
15
  validates_format_of :right, :with => /\Anone\z/, :message => "should be none"
17
16
  validates_format_of :expiry, :with => /\A\z/, :message => "should be blank"
@@ -28,12 +27,14 @@ module IB
28
27
  "<Bag: #{[symbol, exchange, currency].join(' ')} legs: #{legs_description} >"
29
28
  end
30
29
 
31
- def con_id= arg
32
- # dont' update con_id
33
- end
30
+ def con_id= arg
31
+ # dont' update con_id
32
+ end
34
33
 
35
34
  ### Leg-related methods
36
35
 
36
+ # TODO: Rewrite with legs and legs_description being strictly in sync...
37
+ # TODO: Find a way to serialize legs without references...
37
38
  # IB-equivalent leg description.
38
39
  def legs_description
39
40
  self[:legs_description] || combo_legs.map { |the_leg| "#{the_leg.con_id}|#{the_leg.weight}" }.join(',')
@@ -45,7 +46,6 @@ module IB
45
46
  legs_description.split(',').sort == other.legs_description.split(',').sort
46
47
  end
47
48
 
48
-
49
49
  # Contract comparison
50
50
  def == other
51
51
  super && same_legs?(other)
@@ -1,7 +1,7 @@
1
1
  module IB
2
2
  # This is a single data point delivered by HistoricData or RealTimeBar messages.
3
3
  # Instantiate with a Hash of attributes, to be auto-set via initialize in Model.
4
- class Bar < IB::Base
4
+ class Bar < IB::Model
5
5
  include BaseProperties
6
6
 
7
7
  has_one :contract # The bar represents timeseries info for this Contract
@@ -22,7 +22,7 @@ module IB
22
22
  validates_numericality_of :open, :high, :low, :close, :volume
23
23
 
24
24
  def to_human
25
- "<Bar: #{time.strftime("(%d.%m.%y)%X")} wap #{wap.round(3)} OHLC #{open} #{high} #{low} #{close} " +
25
+ "<Bar: #{time} wap #{wap} OHLC #{open} #{high} #{low} #{close} " +
26
26
  (trades ? "trades #{trades}" : "") + " vol #{volume}>"
27
27
  end
28
28
 
@@ -2,7 +2,7 @@ module IB
2
2
 
3
3
  # ComboLeg is essentially a join Model between Combo (BAG) Contract and
4
4
  # individual Contracts (securities) that this BAG contains.
5
- class ComboLeg < IB::Base
5
+ class ComboLeg < IB::Model
6
6
  include BaseProperties
7
7
 
8
8
  # BAG Combo Contract that contains this Leg
@@ -20,10 +20,10 @@ module IB
20
20
  # specific combination order, refer to the Interactive
21
21
  # Analytics section of the User's Guide.
22
22
  :exchange, # String: exchange to which the complete combo order will be routed.
23
- #
23
+ #
24
24
  # For institutional customers only! For stock legs when doing short sale
25
- :short_sale_slot, # int: 0 - retail(default),
26
- # 1 = clearing broker, 2 = third party
25
+ :short_sale_slot, # int: 0 - retail(default),
26
+ # 1 = clearing broker, 2 = third party
27
27
  :designated_location, # String: Only for shortSaleSlot == 2.
28
28
  # Otherwise leave blank or orders will be rejected.
29
29
  :exempt_code, # int: (-1)
@@ -83,28 +83,6 @@ module IB
83
83
  ].flatten
84
84
  end
85
85
 
86
-
87
- # fields are generated by serialize(:extended)
88
- # i.e.
89
- # z= Strangle.build from: Symbols::Index.stoxx, p: 3700, c: 4000, expiry: 202106
90
- # zc= z.combo_legs.serialize :extended
91
- # => [[321584786, 1, "BUY", "DTB", 0, 0, "", -1], [321584637, 1, "BUY", "DTB", 0, 0, "", -1]]
92
- # nz = zc.map{|o| ComboLeg.build *o }
93
- # zc.map{|o| ComboLeg.build o } => # is equivalent
94
- # => [#<IB::ComboLeg:0x0000000001c36bc0 @attributes={:con_id=>321584786, :ratio=>1, :side=>"B", :exchange=>"DTB", ...
95
- # nz.first == z.combo_legs.first => true
96
- #
97
- def self.build *fields
98
- self.new Hash[[:con_id,
99
- :ratio,
100
- :side, # reverse to_sup?
101
- :exchange,
102
- :open_close,
103
- :short_sale_slot,
104
- :designated_location,
105
- :exempt_code].zip fields]
106
- end
107
-
108
86
  def to_human
109
87
  "<ComboLeg: #{side} #{ratio} con_id #{con_id} at #{exchange}>"
110
88
  end
@@ -0,0 +1,245 @@
1
+ require 'ib/support'
2
+ module IB
3
+ class OrderCondition < IB::Model
4
+ include BaseProperties
5
+
6
+
7
+ prop :operator, # 1 -> " >= " , 0 -> " <= " see /lib/ib/constants # 338f
8
+ :conjunction_connection, # "o" -> or "a"
9
+ :contract
10
+ def self.verify_contract_if_necessary c
11
+ c.con_id.to_i.zero? ||( c.primary_exchange.blank? && c.exchange.blank?) ? c.verify! : c
12
+ end
13
+ def condition_type
14
+ error "condition_type method is abstract"
15
+ end
16
+ def default_attributes
17
+ super.merge( operator: ">=" , conjunction_connection: :and )
18
+ end
19
+
20
+ def serialize_contract_by_con_id
21
+ [ contract.con_id , contract.primary_exchange.presence || contract.exchange ]
22
+ end
23
+
24
+ def serialize
25
+ [ condition_type, self[:conjunction_connection] ]
26
+ end
27
+ end
28
+
29
+
30
+
31
+ class PriceCondition < OrderCondition
32
+ using IBSupport # refine Array-method for decoding of IB-Messages
33
+ prop :price,
34
+ :trigger_method # see /models/ib/order.rb# 51 ff and /lib/ib/constants # 210 ff
35
+
36
+ def default_attributes
37
+ super.merge( :trigger_method => :default )
38
+ end
39
+
40
+ def condition_type
41
+ 1
42
+ end
43
+
44
+ def self.make buffer
45
+ m= self.new conjunction_connection: buffer.read_string,
46
+ operator: buffer.read_int,
47
+ price: buffer.read_decimal
48
+
49
+ the_contract = IB::Contract.new con_id: buffer.read_int, exchange: buffer.read_string
50
+ m.contract = the_contract
51
+ m.trigger_method = buffer.read_int
52
+ m
53
+
54
+ end
55
+
56
+ def serialize
57
+ super << self[:operator] << price << serialize_contract_by_con_id << self[:trigger_method]
58
+ end
59
+
60
+ # dsl: PriceCondition.fabricate some_contract, ">=", 500
61
+ def self.fabricate contract, operator, price
62
+ error "Condition Operator has to be \">=\" or \"<=\" " unless ["<=", ">="].include? operator
63
+ self.new operator: operator,
64
+ price: price.to_i,
65
+ contract: verify_contract_if_necessary( contract )
66
+ end
67
+
68
+ end
69
+
70
+ class TimeCondition < OrderCondition
71
+ using IBSupport # refine Array-method for decoding of IB-Messages
72
+ prop :time
73
+
74
+ def condition_type
75
+ 3
76
+ end
77
+
78
+ def self.make buffer
79
+ self.new conjunction_connection: buffer.read_string,
80
+ operator: buffer.read_int,
81
+ time: buffer.read_parse_date
82
+ end
83
+
84
+ def serialize
85
+ t = self[:time]
86
+ if t.is_a?(String) && t =~ /^\d{8}\z/ # expiry-format yyymmmdd
87
+ self.time = DateTime.new t[0..3],t[4..5],t[-2..-1]
88
+ end
89
+ serialized_time = case self[:time] # explicity formatting of time-object
90
+ when String
91
+ self[:time]
92
+ when DateTime
93
+ self[:time].gmtime.strftime("%Y%m%d %H:%M:%S %Z")
94
+ when Date, Time
95
+ self[:time].strftime("%Y%m%d %H:%M:%S")
96
+ end
97
+
98
+ super << self[:operator] << serialized_time
99
+ end
100
+
101
+ def self.fabricate operator, time
102
+ self.new operator: operator,
103
+ time: time
104
+ end
105
+ end
106
+
107
+ class ExecutionCondition < OrderCondition
108
+ using IBSupport # refine Array-method for decoding of IB-Messages
109
+
110
+ def condition_type
111
+ 5
112
+ end
113
+
114
+ def self.make buffer
115
+ m =self.new conjunction_connection: buffer.read_string,
116
+ operator: buffer.read_int
117
+
118
+ the_contract = IB::Contract.new sec_type: buffer.read_string,
119
+ exchange: buffer.read_string,
120
+ symbol: buffer.read_string
121
+ m.contract = the_contract
122
+ m
123
+ end
124
+
125
+ def serialize
126
+ super << contract[:sec_type] <<(contract.primary_exchange.presence || contract.exchange) << contract.symbol
127
+ end
128
+
129
+ def self.fabricate contract
130
+ self.new contract: verify_contract_if_necessary( contract )
131
+ end
132
+
133
+ end
134
+
135
+ class MarginCondition < OrderCondition
136
+ using IBSupport # refine Array-method for decoding of IB-Messages
137
+
138
+ prop :percent
139
+
140
+ def condition_type
141
+ 4
142
+ end
143
+
144
+ def self.make buffer
145
+ self.new conjunction_connection: buffer.read_string,
146
+ operator: buffer.read_int,
147
+ percent: buffer.read_int
148
+
149
+ end
150
+
151
+ def serialize
152
+ super << self[:operator] << percent
153
+ end
154
+ def self.fabricate operator, percent
155
+ error "Condition Operator has to be \">=\" or \"<=\" " unless ["<=", ">="].include? operator
156
+ self.new operator: operator,
157
+ percent: percent
158
+ end
159
+ end
160
+
161
+
162
+ class VolumeCondition < OrderCondition
163
+ using IBSupport # refine Array-method for decoding of IB-Messages
164
+
165
+ prop :volume
166
+
167
+ def condition_type
168
+ 6
169
+ end
170
+
171
+ def self.make buffer
172
+ m = self.new conjunction_connection: buffer.read_string,
173
+ operator: buffer.read_int,
174
+ volumne: buffer.read_int
175
+
176
+ the_contract = IB::Contract.new con_id: buffer.read_int, exchange: buffer.read_string
177
+ m.contract = the_contract
178
+ m
179
+ end
180
+
181
+ def serialize
182
+
183
+ super << self[:operator] << volume << serialize_contract_by.con_id
184
+ end
185
+
186
+ # dsl: VolumeCondition.fabricate some_contract, ">=", 50000
187
+ def self.fabricate contract, operator, volume
188
+ error "Condition Operator has to be \">=\" or \"<=\" " unless ["<=", ">="].include? operator
189
+ self.new operator: operator,
190
+ volume: volume,
191
+ contract: verify_contract_if_necessary( contract )
192
+ end
193
+ end
194
+
195
+ class PercentChangeCondition < OrderCondition
196
+ using IBSupport # refine Array-method for decoding of IB-Messages
197
+ prop :percent_change
198
+
199
+ def condition_type
200
+ 7
201
+ end
202
+
203
+ def self.make buffer
204
+ m = self.new conjunction_connection: buffer.read_string,
205
+ operator: buffer.read_int,
206
+ percent_change: buffer.read_decimal
207
+
208
+ the_contract = IB::Contract.new con_id: buffer.read_int, exchange: buffer.read_string
209
+ m.contract = the_contract
210
+ m
211
+ end
212
+
213
+ def serialize
214
+ super << self[:operator] << percent_change << serialize_contract_by_con_id
215
+
216
+ end
217
+ # dsl: PercentChangeCondition.fabricate some_contract, ">=", "5%"
218
+ def self.fabricate contract, operator, change
219
+ error "Condition Operator has to be \">=\" or \"<=\" " unless ["<=", ">="].include? operator
220
+ self.new operator: operator,
221
+ percent_change: change.to_i,
222
+ contract: verify_contract_if_necessary( contract )
223
+ end
224
+ end
225
+ class OrderCondition
226
+ using IBSupport # refine Array-method for decoding of IB-Messages
227
+ # subclasses representing specialized condition types.
228
+
229
+ Subclasses = Hash.new(OrderCondition)
230
+ Subclasses[1] = IB::PriceCondition
231
+ Subclasses[3] = IB::TimeCondition
232
+ Subclasses[5] = IB::ExecutionCondition
233
+ Subclasses[4] = IB::MarginCondition
234
+ Subclasses[6] = IB::VolumeCondition
235
+ Subclasses[7] = IB::PercentChangeCondition
236
+
237
+
238
+ # This builds an appropriate subclass based on its type
239
+ #
240
+ def self.make_from buffer
241
+ condition_type = buffer.read_int
242
+ OrderCondition::Subclasses[condition_type].make( buffer )
243
+ end
244
+ end # class
245
+ end # module