ib-api 10.33.1

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 (161) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +52 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CLAUDE.md +131 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +17 -0
  8. data/Gemfile.lock +120 -0
  9. data/Guardfile +24 -0
  10. data/LICENSE +674 -0
  11. data/LLM_GUIDE.md +388 -0
  12. data/README.md +114 -0
  13. data/Rakefile +11 -0
  14. data/VERSION +1 -0
  15. data/api.gemspec +50 -0
  16. data/bin/console +96 -0
  17. data/bin/console.yml +3 -0
  18. data/bin/setup +8 -0
  19. data/bin/simple +91 -0
  20. data/changelog.md +32 -0
  21. data/conditions/ib/execution_condition.rb +31 -0
  22. data/conditions/ib/margin_condition.rb +28 -0
  23. data/conditions/ib/order_condition.rb +29 -0
  24. data/conditions/ib/percent_change_condition.rb +34 -0
  25. data/conditions/ib/price_condition.rb +44 -0
  26. data/conditions/ib/time_condition.rb +42 -0
  27. data/conditions/ib/volume_condition.rb +36 -0
  28. data/lib/class_extensions.rb +167 -0
  29. data/lib/ib/base.rb +109 -0
  30. data/lib/ib/base_properties.rb +178 -0
  31. data/lib/ib/connection.rb +573 -0
  32. data/lib/ib/constants.rb +402 -0
  33. data/lib/ib/contract.rb +30 -0
  34. data/lib/ib/errors.rb +52 -0
  35. data/lib/ib/messages/abstract_message.rb +68 -0
  36. data/lib/ib/messages/incoming/abstract_message.rb +116 -0
  37. data/lib/ib/messages/incoming/abstract_tick.rb +25 -0
  38. data/lib/ib/messages/incoming/account_message.rb +26 -0
  39. data/lib/ib/messages/incoming/alert.rb +34 -0
  40. data/lib/ib/messages/incoming/contract_data.rb +105 -0
  41. data/lib/ib/messages/incoming/contract_message.rb +13 -0
  42. data/lib/ib/messages/incoming/delta_neutral_validation.rb +23 -0
  43. data/lib/ib/messages/incoming/execution_data.rb +50 -0
  44. data/lib/ib/messages/incoming/histogram_data.rb +30 -0
  45. data/lib/ib/messages/incoming/historical_data.rb +65 -0
  46. data/lib/ib/messages/incoming/historical_data_update.rb +50 -0
  47. data/lib/ib/messages/incoming/managed_accounts.rb +21 -0
  48. data/lib/ib/messages/incoming/market_depth.rb +34 -0
  49. data/lib/ib/messages/incoming/market_depth_l2.rb +15 -0
  50. data/lib/ib/messages/incoming/next_valid_id.rb +19 -0
  51. data/lib/ib/messages/incoming/open_order.rb +290 -0
  52. data/lib/ib/messages/incoming/order_status.rb +85 -0
  53. data/lib/ib/messages/incoming/portfolio_value.rb +47 -0
  54. data/lib/ib/messages/incoming/position_data.rb +21 -0
  55. data/lib/ib/messages/incoming/positions_multi.rb +15 -0
  56. data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
  57. data/lib/ib/messages/incoming/receive_fa.rb +30 -0
  58. data/lib/ib/messages/incoming/scanner_data.rb +54 -0
  59. data/lib/ib/messages/incoming/tick_by_tick.rb +77 -0
  60. data/lib/ib/messages/incoming/tick_efp.rb +18 -0
  61. data/lib/ib/messages/incoming/tick_generic.rb +12 -0
  62. data/lib/ib/messages/incoming/tick_option.rb +60 -0
  63. data/lib/ib/messages/incoming/tick_price.rb +60 -0
  64. data/lib/ib/messages/incoming/tick_size.rb +55 -0
  65. data/lib/ib/messages/incoming/tick_string.rb +13 -0
  66. data/lib/ib/messages/incoming.rb +292 -0
  67. data/lib/ib/messages/outgoing/abstract_message.rb +84 -0
  68. data/lib/ib/messages/outgoing/bar_request_message.rb +247 -0
  69. data/lib/ib/messages/outgoing/new-place-order.rb +193 -0
  70. data/lib/ib/messages/outgoing/old-place-order.rb +147 -0
  71. data/lib/ib/messages/outgoing/place_order.rb +149 -0
  72. data/lib/ib/messages/outgoing/request_account_summary.rb +79 -0
  73. data/lib/ib/messages/outgoing/request_historical_data.rb +182 -0
  74. data/lib/ib/messages/outgoing/request_market_data.rb +102 -0
  75. data/lib/ib/messages/outgoing/request_market_depth.rb +57 -0
  76. data/lib/ib/messages/outgoing/request_real_time_bars.rb +48 -0
  77. data/lib/ib/messages/outgoing/request_scanner_subscription.rb +73 -0
  78. data/lib/ib/messages/outgoing/request_tick_by_tick_data.rb +21 -0
  79. data/lib/ib/messages/outgoing.rb +410 -0
  80. data/lib/ib/messages.rb +139 -0
  81. data/lib/ib/order_condition.rb +26 -0
  82. data/lib/ib/plugins.rb +27 -0
  83. data/lib/ib/prepare_data.rb +61 -0
  84. data/lib/ib/raw_message_parser.rb +99 -0
  85. data/lib/ib/socket.rb +83 -0
  86. data/lib/ib/support.rb +236 -0
  87. data/lib/ib/version.rb +6 -0
  88. data/lib/ib-api.rb +44 -0
  89. data/lib/server_versions.rb +145 -0
  90. data/lib/support/array_function.rb +28 -0
  91. data/lib/support/logging.rb +45 -0
  92. data/models/ib/account.rb +72 -0
  93. data/models/ib/account_value.rb +33 -0
  94. data/models/ib/bag.rb +55 -0
  95. data/models/ib/bar.rb +31 -0
  96. data/models/ib/combo_leg.rb +127 -0
  97. data/models/ib/contract.rb +411 -0
  98. data/models/ib/contract_detail.rb +118 -0
  99. data/models/ib/execution.rb +67 -0
  100. data/models/ib/forex.rb +12 -0
  101. data/models/ib/future.rb +64 -0
  102. data/models/ib/index.rb +14 -0
  103. data/models/ib/option.rb +149 -0
  104. data/models/ib/option_detail.rb +84 -0
  105. data/models/ib/order.rb +720 -0
  106. data/models/ib/order_state.rb +155 -0
  107. data/models/ib/portfolio_value.rb +86 -0
  108. data/models/ib/spread.rb +176 -0
  109. data/models/ib/stock.rb +25 -0
  110. data/models/ib/underlying.rb +32 -0
  111. data/plugins/ib/advanced-account.rb +442 -0
  112. data/plugins/ib/alerts/base-alert.rb +125 -0
  113. data/plugins/ib/alerts/gateway-alerts.rb +15 -0
  114. data/plugins/ib/alerts/order-alerts.rb +73 -0
  115. data/plugins/ib/auto-adjust.rb +0 -0
  116. data/plugins/ib/connection-tools.rb +122 -0
  117. data/plugins/ib/eod.rb +326 -0
  118. data/plugins/ib/greeks.rb +102 -0
  119. data/plugins/ib/managed-accounts.rb +274 -0
  120. data/plugins/ib/market-price.rb +150 -0
  121. data/plugins/ib/option-chain.rb +167 -0
  122. data/plugins/ib/order-flow.rb +157 -0
  123. data/plugins/ib/order-prototypes/abstract.rb +67 -0
  124. data/plugins/ib/order-prototypes/adaptive.rb +40 -0
  125. data/plugins/ib/order-prototypes/all-in-one.rb +46 -0
  126. data/plugins/ib/order-prototypes/combo.rb +46 -0
  127. data/plugins/ib/order-prototypes/forex.rb +40 -0
  128. data/plugins/ib/order-prototypes/limit.rb +193 -0
  129. data/plugins/ib/order-prototypes/market.rb +116 -0
  130. data/plugins/ib/order-prototypes/pegged.rb +169 -0
  131. data/plugins/ib/order-prototypes/premarket.rb +31 -0
  132. data/plugins/ib/order-prototypes/stop.rb +202 -0
  133. data/plugins/ib/order-prototypes/volatility.rb +39 -0
  134. data/plugins/ib/order-prototypes.rb +118 -0
  135. data/plugins/ib/probability-of-expiring.rb +109 -0
  136. data/plugins/ib/process-orders.rb +155 -0
  137. data/plugins/ib/roll.rb +86 -0
  138. data/plugins/ib/spread-prototypes/butterfly.rb +77 -0
  139. data/plugins/ib/spread-prototypes/calendar.rb +97 -0
  140. data/plugins/ib/spread-prototypes/stock-spread.rb +56 -0
  141. data/plugins/ib/spread-prototypes/straddle.rb +70 -0
  142. data/plugins/ib/spread-prototypes/strangle.rb +93 -0
  143. data/plugins/ib/spread-prototypes/vertical.rb +83 -0
  144. data/plugins/ib/spread-prototypes.rb +70 -0
  145. data/plugins/ib/symbols/abstract.rb +136 -0
  146. data/plugins/ib/symbols/bonds.rb +28 -0
  147. data/plugins/ib/symbols/cfd.rb +19 -0
  148. data/plugins/ib/symbols/combo.rb +46 -0
  149. data/plugins/ib/symbols/commodity.rb +17 -0
  150. data/plugins/ib/symbols/forex.rb +41 -0
  151. data/plugins/ib/symbols/futures.rb +127 -0
  152. data/plugins/ib/symbols/index.rb +43 -0
  153. data/plugins/ib/symbols/options.rb +99 -0
  154. data/plugins/ib/symbols/stocks.rb +44 -0
  155. data/plugins/ib/symbols/version.rb +5 -0
  156. data/plugins/ib/symbols.rb +118 -0
  157. data/plugins/ib/verify.rb +226 -0
  158. data/symbols/w20.yml +210 -0
  159. data/t.txt +20 -0
  160. data/update.md +71 -0
  161. metadata +327 -0
@@ -0,0 +1,28 @@
1
+ module Support
2
+ module ArrayFunction
3
+ def save_insert item, key, overwrite = true
4
+ member = find { |entry| entry[ key ] == item[ key] }
5
+ if member
6
+ self[ index( member ) ] = item if overwrite
7
+ else
8
+ self << item
9
+ end
10
+ self # always returns the array
11
+ end
12
+
13
+ # performs [ [ array ] & [ array ] & [..] ].first
14
+ def intercept
15
+ a = self.dup
16
+ s = a.pop
17
+ while a.present?
18
+ s = s & a.pop
19
+ end
20
+ s.first unless s.nil? # return_value (or nil)
21
+ end
22
+ end # module
23
+ end # module
24
+
25
+ class Array
26
+ include Support::ArrayFunction
27
+ end
28
+
@@ -0,0 +1,45 @@
1
+ #module Kernel
2
+ # private
3
+ # def this_method_name
4
+ # caller[0] =~ /`([^']*)'/ and $1
5
+ # end
6
+ # see also __method__ and __callee__
7
+ #end
8
+
9
+
10
+
11
+ module Support
12
+ module Logging
13
+ def self.included(base)
14
+ base.extend ClassMethods
15
+ base.send :define_method, :logger do
16
+ base.logger
17
+ end
18
+ end
19
+
20
+ module ClassMethods
21
+ def logger
22
+ @logger
23
+ end
24
+
25
+ def logger=(logger)
26
+ @logger = logger
27
+ end
28
+
29
+ def configure_logger(log=nil)
30
+ if log
31
+ @logger = log
32
+ else
33
+ @logger = ::Logger.new(STDOUT)
34
+ @logger.level = ::Logger::INFO
35
+ @logger.formatter = proc do |severity, datetime, progname, msg|
36
+ # "#{datetime.strftime("%d.%m.(%X)")}#{"%5s" % severity}->#{msg}\n"
37
+ "#{"%1s" % severity[0]}: #{msg}\n"
38
+ end
39
+ @logger.debug "------------------------------ start logging ----------------------------"
40
+ end # branch
41
+ end # def
42
+ end # module ClassMethods
43
+ end # module Logging
44
+ end # module Support
45
+
@@ -0,0 +1,72 @@
1
+ module IB
2
+ class Account < IB::Base
3
+ include BaseProperties
4
+ # attr_accessible :alias, :account, :connected
5
+
6
+ prop :account, # String
7
+ :alias, #
8
+ :type,
9
+ :last_updated,
10
+ :connected => :bool
11
+
12
+
13
+
14
+ validates_format_of :account, :with => /\A[D]?[UF]{1}\d{5,8}\z/ , :message => 'should be (X)X00000'
15
+
16
+ # in tableless mode the scope is ignored
17
+
18
+ has_many :account_values
19
+ has_many :portfolio_values
20
+ has_many :contracts
21
+ has_many :orders
22
+ has_many :focuses
23
+
24
+ def default_attributes
25
+ super.merge account: 'X000000'
26
+ super.merge alias: ''
27
+ super.merge type: 'Account'
28
+ super.merge connected: false
29
+ end
30
+
31
+ def logger #nodoc#
32
+ Connection.logger
33
+ end
34
+
35
+ def print_type #nodoc#
36
+ (test_environment? ? "demo_" : "") + ( user? ? "user" : "advisor" )
37
+ end
38
+
39
+ def advisor?
40
+ !!(type =~ /Advisor/ || account =~ /\A[D]?[F]{1}/)
41
+ end
42
+
43
+ def user?
44
+ !!(type =~ /User/ || account =~ /\A[D]?[U]{1}/)
45
+ end
46
+
47
+ def test_environment?
48
+ !!(account =~ /^[D]{1}/)
49
+ end
50
+
51
+ def == other
52
+ super(other) ||
53
+ other.is_a?(self.class) && account == other.account
54
+ end
55
+
56
+ def to_human
57
+ a = if self.alias.present? && self.alias != account
58
+ " alias: "+ self.alias
59
+ else
60
+ ""
61
+ end
62
+ "<#{print_type} #{account}#{a}>"
63
+ end
64
+
65
+ def name #nodoc#
66
+ self.alias.present? ? self.alias : account
67
+ end
68
+
69
+ # alias :id :account
70
+ end # class
71
+
72
+ end # module
@@ -0,0 +1,33 @@
1
+ module IB
2
+ # Instantiate with a Hash of attributes, to be auto-set via initialize in Model.
3
+ class AccountValue < IB::Base
4
+ include BaseProperties
5
+
6
+ belongs_to :account
7
+
8
+ prop :key,
9
+ :value,
10
+ :currency
11
+
12
+
13
+ # comparison
14
+ def == other
15
+ super(other) ||
16
+ other.is_a?(self.class) &&
17
+ key == other.key &&
18
+ currency == other.currency &&
19
+ value == other.value
20
+ end
21
+ def default_attributes
22
+ super.merge key: 'AccountValue',
23
+ value: 0,
24
+ currency: 'USD'
25
+ end
26
+
27
+ def to_human
28
+ "<#{key}=#{value} #{currency}>"
29
+ end
30
+
31
+ alias to_s to_human
32
+ end # class
33
+ end # module IB
data/models/ib/bag.rb ADDED
@@ -0,0 +1,55 @@
1
+ module IB
2
+
3
+ # "BAG" is not really a contract, but a combination (combo) of securities.
4
+ # AKA basket or bag of securities. Individual securities in combo are represented
5
+ # by ComboLeg objects.
6
+ class Bag < Contract
7
+ # General Notes:
8
+ # 1. :exchange for the leg definition must match that of the combination order.
9
+ # The exception is for a STK legs, which must specify the SMART exchange.
10
+ # 2. :symbol => "USD" For combo Contract, this is an arbitrary value (like "USD")
11
+
12
+ prop :combo_params # bags carry "non_guarantieed: true/false" in combo_params
13
+
14
+
15
+ validates_format_of :sec_type, :with => /\Abag\z/, :message => "should be a bag"
16
+ validates_format_of :right, :with => /\Anone\z/, :message => "should be none"
17
+ validates_format_of :expiry, :with => /\A\z/, :message => "should be blank"
18
+
19
+ def default_attributes
20
+ super.merge :sec_type => :bag #,:legs => Array.new,
21
+ end
22
+
23
+ # def description
24
+ # self[:description] || to_human
25
+ # end
26
+
27
+ def to_human
28
+ "<Bag: #{[symbol, exchange, currency].join(' ')} legs: #{legs_description} >"
29
+ end
30
+
31
+ def con_id= arg
32
+ # dont' update con_id
33
+ end
34
+
35
+ ### Leg-related methods
36
+
37
+ # IB-equivalent leg description.
38
+ def legs_description
39
+ self[:legs_description] || combo_legs.map { |the_leg| "#{the_leg.con_id}|#{the_leg.weight}" }.join(',')
40
+ end
41
+
42
+ # Check if two Contracts have same legs (maybe in different order)
43
+ def same_legs? other
44
+ combo_legs == other.combo_legs ||
45
+ legs_description.split(',').sort == other.legs_description.split(',').sort
46
+ end
47
+
48
+
49
+ # Contract comparison
50
+ def == other
51
+ super && same_legs?(other)
52
+ end
53
+
54
+ end # class Bag
55
+ end # IB
data/models/ib/bar.rb ADDED
@@ -0,0 +1,31 @@
1
+ module IB
2
+ # This is a single data point delivered by HistoricData or RealTimeBar messages.
3
+ # Instantiate with a Hash of attributes, to be auto-set via initialize in Model.
4
+ class Bar < IB::Base
5
+ include BaseProperties
6
+
7
+ has_one :contract # The bar represents timeseries info for this Contract
8
+
9
+ prop :open, # The bar opening price.
10
+ :high, # The high price during the time covered by the bar.
11
+ :low, # The low price during the time covered by the bar.
12
+ :close, # The bar closing price.
13
+ :volume, # Volume
14
+ :wap, # Weighted average price during the time covered by the bar.
15
+ :trades, # int: When TRADES data history is returned, represents number
16
+ # of trades that occurred during the time period the bar covers
17
+ :time #DateTime
18
+ # The date-time stamp of the start of the bar. The format is
19
+ # determined by the reqHistoricalData() formatDate parameter.
20
+ # :has_gaps => :bool # Whether or not there are gaps in the data. ## omitted since ServerVersion 124
21
+
22
+ validates_numericality_of :open, :high, :low, :close, :volume
23
+
24
+ def to_human
25
+ "<Bar: #{time.strftime("(%d.%m.%y)%X")} wap #{wap.round(3)} OHLC #{open} #{high} #{low} #{close} " +
26
+ (trades ? "trades #{trades}" : "") + " vol #{volume}>"
27
+ end
28
+
29
+ alias to_s to_human
30
+ end # class Bar
31
+ end # module IB
@@ -0,0 +1,127 @@
1
+ module IB
2
+
3
+ # ComboLeg is essentially a join Model between Combo (BAG) Contract and
4
+ # individual Contracts (securities) that this BAG contains.
5
+ class ComboLeg < IB::Base
6
+ include BaseProperties
7
+
8
+ # BAG Combo Contract that contains this Leg
9
+ # belongs_to :combo, :class_name => 'Contract'
10
+ # Contract that constitutes this Leg
11
+ # belongs_to :leg_contract, :class_name => 'Contract', :foreign_key => :leg_contract_id
12
+
13
+ # General Notes:
14
+ # 1. The exchange for the leg definition must match that of the combination order.
15
+ # The exception is for a STK leg definition, which must specify the SMART exchange.
16
+
17
+ prop :con_id, # int: The unique contract identifier specifying the security.
18
+ :ratio, # int: Select the relative number of contracts for the leg you
19
+ # are constructing. To help determine the ratio for a
20
+ # specific combination order, refer to the Interactive
21
+ # Analytics section of the User's Guide.
22
+ :exchange, # String: exchange to which the complete combo order will be routed.
23
+ #
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
27
+ :designated_location, # String: Only for shortSaleSlot == 2.
28
+ # Otherwise leave blank or orders will be rejected.
29
+ :exempt_code, # int: (-1)
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
+ :price # support for pet leg prices
38
+
39
+ # Extra validations
40
+ validates_numericality_of :ratio, :con_id
41
+ validates_format_of :designated_location, :with => /\A\z/,
42
+ :message => "should be blank or orders will be rejected"
43
+
44
+ def default_attributes
45
+ super.merge :con_id => 0,
46
+ :ratio => 1,
47
+ :side => :buy,
48
+ :open_close => :same, # The only option for retail customers.
49
+ :short_sale_slot => :default,
50
+ :designated_location => '',
51
+ :exchange => 'SMART', # Unless SMART, Order modification fails
52
+ :exempt_code => -1
53
+ end
54
+
55
+ # Leg's weight is a combination of action and ratio
56
+ def weight
57
+ side == :buy ? ratio : -ratio
58
+ end
59
+
60
+ def weight= value
61
+ value = value.to_i
62
+ if value > 0
63
+ self.side = :buy
64
+ self.ratio = value
65
+ else
66
+ self.side = :sell
67
+ self.ratio = -value
68
+ end
69
+ end
70
+
71
+ # Some messages include open_close, some don't. wtf.
72
+ def serialize *fields
73
+ [con_id,
74
+ ratio,
75
+ side.to_sup,
76
+ exchange,
77
+ (fields.include?(:extended) ?
78
+ [self[:open_close],
79
+ self[:short_sale_slot],
80
+ designated_location,
81
+ exempt_code] :
82
+ [])
83
+ ].flatten
84
+ end
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
+ def to_human
109
+ "<ComboLeg: #{side} #{ratio} con_id #{con_id} at #{exchange}>"
110
+ end
111
+
112
+ # Order comparison
113
+ def == other
114
+ super(other) ||
115
+ other.is_a?(self.class) &&
116
+ con_id == other.con_id &&
117
+ ratio == other.ratio &&
118
+ open_close == other.open_close &&
119
+ short_sale_slot == other.short_sale_slot &&
120
+ exempt_code == other.exempt_code &&
121
+ side == other.side &&
122
+ exchange == other.exchange &&
123
+ designated_location == other.designated_location
124
+ end
125
+
126
+ end # ComboLeg
127
+ end # module IB