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,720 @@
1
+ module IB
2
+ class Order < IB::Base
3
+ include BaseProperties
4
+
5
+ # General Notes:
6
+ # 1. Placing Orders by con_id - When you place an order by con_id, you must
7
+ # provide the con_id AND the exchange. If you provide extra fields when placing
8
+ # an order by conid, the order may not work.
9
+
10
+ # 2. Order IDs - Each order you place must have a unique Order ID. Increment
11
+ # your own Order IDs to avoid conflicts between orders placed from your API application.
12
+
13
+ # Main order fields
14
+ prop :local_id, # int: Order id associated with client (volatile).
15
+ :client_id, # int: The id of the client that placed this order.
16
+ :perm_id, # int: TWS permanent id, remains the same over TWS sessions.
17
+ :quantity, :total_quantity, # int: The order quantity.
18
+
19
+ :order_type, # String: Order type.
20
+ # Limit Risk: MTL / MKT PRT / QUOTE / STP / STP LMT / TRAIL / TRAIL LIMIT / TRAIL LIT / TRAIL MIT
21
+ # Speed of Execution: MKT / MIT / MOC / MOO / PEG MKT / REL
22
+ # Price Improvement: BOX TOP / LOC / LOO / LIT / PEG MID / VWAP
23
+ # Advanced Trading: OCA / VOL / SCALE
24
+ # Other (no abbreviation): Bracket, Auction, Discretionary, Sweep-to-Fill,
25
+ # Price Improvement Auction, Block, Hidden, Iceberg/Reserve, All-or-None, Fill-or-Kill
26
+ # See 'ib/constants.rb' ORDER_TYPES for a complete list of valid values.
27
+
28
+ :limit_price, # double: LIMIT price, used for limit, stop-limit and relative
29
+ # orders. In all other cases specify zero. For relative
30
+ # orders with no limit price, also specify zero.
31
+ :aux_price, # double: default is set to "" (as implemented in python code)
32
+ # STOP price for stop-limit orders,
33
+ # OFFSET amount for relative orders.
34
+ # In all other cases, specify zero.
35
+
36
+ :oca_group, # String: Identifies a member of a one-cancels-all group.
37
+ :oca_type, # int: Tells how to handle remaining orders in an OCA group
38
+ # when one order or part of an order executes. Valid values:
39
+ # - 1 = Cancel all remaining orders with block
40
+ # - 2 = Remaining orders are reduced in size with block
41
+ # - 3 = Remaining orders are reduced in size with no block
42
+ # If you use a value "with block" your order has
43
+ # overfill protection. This means that only one order in
44
+ # the group will be routed at a time to remove the
45
+ # possibility of an overfill.
46
+ :parent_id, # int: The order ID of the parent (original) order, used
47
+ # for bracket (STP) and auto trailing stop (TRAIL) orders.
48
+ :display_size, # int: publicly disclosed order size for Iceberg orders.
49
+
50
+ :trigger_method, # Specifies how Simulated Stop, Stop-Limit and Trailing
51
+ # Stop orders are triggered. Valid values are:
52
+ # 0 - Default, "double bid/ask" for OTC/US options, "last" otherswise.
53
+ # 1 - "double bid/ask" method, stop orders are triggered based on
54
+ # two consecutive bid or ask prices.
55
+ # 2 - "last" method, stops are triggered based on the last price.
56
+ # 3 - double last method.
57
+ # 4 - bid/ask method. For a buy order, a single occurrence of the
58
+ # bid price must be at or above the trigger price. For a sell
59
+ # order, a single occurrence of the ask price must be at or
60
+ # below the trigger price.
61
+ # 7 - last or bid/ask method. For a buy order, a single bid price
62
+ # or the last price must be at or above the trigger price.
63
+ # For a sell order, a single ask price or the last price
64
+ # must be at or below the trigger price.
65
+ # 8 - mid-point method, where the midpoint must be at or above
66
+ # (for a buy) or at or below (for a sell) the trigger price,
67
+ # and the spread between the bid and ask must be less than
68
+ # 0.1% of the midpoint
69
+
70
+ :good_after_time, # Indicates that the trade should be submitted after the
71
+ # time and date set, format YYYYMMDD HH:MM:SS (seconds are optional).
72
+ :good_till_date, # Indicates that the trade should remain working until the
73
+ # time and date set, format YYYYMMDD HH:MM:SS (seconds are optional).
74
+ # You must set the :tif to GTD when using this string.
75
+ # Use an empty String if not applicable.
76
+
77
+ :rule_80a, # Individual = 'I', Agency = 'A', AgentOtherMember = 'W',
78
+ # IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M',
79
+ # IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N'
80
+ :min_quantity, # int: Identifies a minimum quantity order type.
81
+ :percent_offset, # double: REL-Ordes – percent offset amount
82
+ :trail_stop_price, # double: TRAILLIMIT orders only
83
+ # As of client v.56, we receive trailing_percent in openOrder
84
+ :trailing_percent,
85
+
86
+ # Financial advisors only - use an empty String if not applicable.
87
+ :fa_group, :fa_profile, :fa_method, :fa_percentage,
88
+ :model_code , # string, no further reference in docs.
89
+ # Institutional orders only!
90
+ :origin, # 0=Customer, 1=Firm
91
+ :order_ref, # String: Order reference. Customer defined order ID tag.
92
+ :short_sale_slot, # 1 - you hold the shares,
93
+ # 2 - they will be delivered from elsewhere.
94
+ # Only for Action="SSHORT
95
+ :designated_location, # String: set when slot==2 only
96
+ :exempt_code, # int
97
+
98
+ # Clearing info
99
+ :account, # String: The account number (Uxxx). For institutional customers only.
100
+ :settling_firm, # String: Institutional only
101
+ :clearing_account, # String: For IBExecution customers: Specifies the
102
+ # true beneficiary of the order. This value is required
103
+ # for FUT/FOP orders for reporting to the exchange.
104
+ :clearing_intent, # IBExecution customers: "", IB, Away, PTA (post trade allocation).
105
+
106
+ # SMART routing only
107
+ :discretionary_amount, # double: The amount off the limit price
108
+ # allowed for discretionary orders.
109
+
110
+ # BOX or VOL ORDERS ONLY
111
+ :auction_strategy, # For BOX exchange only. Valid values:
112
+ # 1=AUCTION_MATCH, 2=AUCTION_IMPROVEMENT, 3=AUCTION_TRANSPARENT
113
+ :starting_price, # double: Starting price. Valid on BOX orders only.
114
+ :stock_ref_price, # double: The stock reference price, used for VOL
115
+ # orders to compute the limit price sent to an exchange (whether or not
116
+ # Continuous Update is selected), and for price range monitoring.
117
+ :delta, # double: Stock delta. Valid on BOX orders only.
118
+
119
+ # Pegged to stock or VOL orders. For price improvement option orders
120
+ # on BOX and VOL orders with dynamic management:
121
+ :stock_range_lower, # double: The lower value for the acceptable
122
+ # underlying stock price range.
123
+ :stock_range_upper, # double The upper value for the acceptable
124
+ # underlying stock price range.
125
+
126
+ # VOLATILITY ORDERS ONLY:
127
+ # http://www.interactivebrokers.com/en/general/education/pdfnotes/PDF-VolTrader.php
128
+ :volatility, # double: What the price is, computed via TWSs Options
129
+ # Analytics. For VOL orders, the limit price sent to an
130
+ # exchange is not editable, as it is the output of a
131
+ # function. Volatility is expressed as a percentage.
132
+ :volatility_type, # int: How the volatility is calculated: 1=daily, 2=annual
133
+ :reference_price_type, # int: For dynamic management of volatility orders:
134
+ # - 1 = Average of National Best Bid or Ask,
135
+ # - 2 = National Best Bid when buying a call or selling a put;
136
+ # and National Best Ask when selling a call or buying a put.
137
+ :continuous_update, # int: Used for dynamic management of volatility orders.
138
+ # Determines whether TWS is supposed to update the order price as the underlying
139
+ # moves. If selected, the limit price sent to an exchange is modified by TWS
140
+ # if the computed price of the option changes enough to warrant doing so. This
141
+ # is helpful in keeping the limit price up to date as the underlying price changes.
142
+ :delta_neutral_order_type, # String: Enter an order type to instruct TWS
143
+ # to submit a delta neutral trade on full or partial execution of the
144
+ # VOL order. For no hedge delta order to be sent, specify NONE.
145
+ # Valid values - LMT, MKT, MTL, REL, MOC
146
+ :delta_neutral_aux_price, # double: Use this field to enter a value if
147
+ # the value in the deltaNeutralOrderType field is an order
148
+ # type that requires an Aux price, such as a REL order.
149
+
150
+ # As of client v.52, we also receive delta... params in openOrder
151
+ :delta_neutral_designated_location,
152
+ :delta_neutral_con_id,
153
+ :delta_neutral_settling_firm,
154
+ :delta_neutral_clearing_account,
155
+ :delta_neutral_clearing_intent,
156
+ # Used when the hedge involves a stock and indicates whether or not it is sold short.
157
+ :delta_neutral_short_sale,
158
+ # Has a value of 1 (the clearing broker holds shares) or 2 (delivered from a third party).
159
+ # If you use 2, then you must specify a deltaNeutralDesignatedLocation.
160
+ :delta_neutral_short_sale_slot,
161
+ # Specifies whether the order is an Open or a Close order and is used
162
+ # when the hedge involves a CFD and and the order is clearing away.
163
+ :delta_neutral_open_close,
164
+
165
+ # HEDGE ORDERS ONLY:
166
+ # As of client v.49/50, we can now add hedge orders using the API.
167
+ # Hedge orders are child orders that take additional fields. There are four
168
+ # types of hedging orders supported by the API: Delta, Beta, FX, Pair.
169
+ # All hedge orders must have a parent order submitted first. The hedge order
170
+ # should set its :parent_id. If the hedgeType is Beta, the beta sent in the
171
+ # hedgeParm can be zero, which means it is not used. Delta is only valid
172
+ # if the parent order is an option and the child order is a stock.
173
+
174
+ :hedge_type, # String: D = Delta, B = Beta, F = FX or P = Pair
175
+ :hedge_param, # String; value depends on the hedgeType; sent from the API
176
+ # only if hedge_type is NOT null. It is required for Pair hedge order,
177
+ # optional for Beta hedge orders, and ignored for Delta and FX hedge orders.
178
+
179
+ # COMBO ORDERS ONLY:
180
+ :basis_points, # double: EFP orders only
181
+ :basis_points_type, # double: EFP orders only
182
+
183
+ # ALGO ORDERS ONLY:
184
+ :algo_strategy, # String
185
+ :algo_params, # public Vector<TagValue> m_algoParams; ?!
186
+ :algo_id, # since Vers. 71
187
+ # SCALE ORDERS ONLY:
188
+ :scale_init_level_size, # int: Size of the first (initial) order component.
189
+ :scale_subs_level_size, # int: Order size of the subsequent scale order
190
+ # components. Used in conjunction with scaleInitLevelSize().
191
+ :scale_price_increment, # double: Price increment between scale components.
192
+ # This field is required for Scale orders.
193
+
194
+ # As of client v.54, we can receive additional scale order fields:
195
+ :scale_price_adjust_value,
196
+ :scale_price_adjust_interval,
197
+ :scale_profit_offset,
198
+ :scale_init_position,
199
+ :scale_init_fill_qty,
200
+ :scale_table, # Vers 69
201
+ :active_start_time, # Vers 69
202
+ :active_stop_time, # Vers 69
203
+ # pegged to benchmark
204
+ :reference_contract_id,
205
+ :pegged_change_amount,
206
+ :reference_change_amount,
207
+ :reference_exchange_id ,
208
+
209
+ :conditions, # Conditions determining when the order will be activated or canceled.
210
+ ### http://xavierib.github.io/twsapidocs/order_conditions.html
211
+ :conditions_ignore_rth, # bool: Indicates whether or not conditions will also be valid outside Regular Trading Hours
212
+ :conditions_cancel_order,# bool: Conditions can determine if an order should become active or canceled.
213
+ #AdjustedOrderParams
214
+ :adjusted_order_type,
215
+ :trigger_price,
216
+ :trail_stop_price,
217
+ :limit_price_offset, # used in trailing stop limit + trailing limit orders
218
+ :adjusted_stop_price,
219
+ :adjusted_stop_limit_price,
220
+ :adjusted_trailing_amount,
221
+ :adjustable_trailing_unit,
222
+ :ext_operator , # 105: MIN_SERVER_VER_EXT_OPERATOR
223
+ # This is a regulartory attribute that applies
224
+ # to all US Commodity (Futures) Exchanges, provided
225
+ # to allow client to comply with CFTC Tag 50 Rules.
226
+ :soft_dollar_tier_name, # 106: MIN_SERVER_VER_SOFT_DOLLAR_TIER
227
+ :soft_dollar_tier_value,
228
+ :soft_dollar_tier_display_name,
229
+ # Define the Soft Dollar Tier used for the order.
230
+ # Only provided for registered professional advisors and hedge and mutual funds.
231
+ # format: "#{name}=#{value},#{display_name}", name and value are used in the
232
+ # order-specification. Its included as ["#{name}","#{value}"] pair
233
+
234
+ :cash_qty, # decimal : The native cash quantity
235
+ :mifid_2_decision_maker,
236
+ :mifid_2_decision_algo,
237
+ :mifid_2_execution_maker,
238
+ :mifid_2_execution_algo,
239
+ :dont_use_auto_price_for_hedge,# => :bool,
240
+ :discretionary_up_to_limit_price,# => :bool,
241
+ :use_price_management_algo,# => :bool,
242
+ :duration ,# => :int,
243
+ :post_to_ats ,# => :int,
244
+ :auto_cancel_parent, # => :bool
245
+ :is_O_ms_container,
246
+ :advanced_order_reject,
247
+ :manual_order_time,
248
+ :min_trade_qty,
249
+ :min_compete_size,
250
+ :compete_against_best_offset,
251
+ :mid_offset_at_whole,
252
+ :mid_offset_at_half,
253
+ :customer_account,
254
+ :professional_account
255
+
256
+
257
+
258
+ # Properties with complex processing logics
259
+ prop :tif, # String: Time in Force (time to market): DAY/GAT/GTD/GTC/IOC
260
+ :random_size => :bool,
261
+ :random_price => :bool,
262
+ :scale_auto_reset => :bool,
263
+ :scale_random_percent => :bool,
264
+ :solicided => :bool,
265
+ :what_if => :bool, # Only return pre-trade commissions and margin info, do not place
266
+ :not_held => :bool, # Not Held
267
+ :outside_rth => :bool, # Order may trigger or fill outside of regular hours. (WAS: ignore_rth)
268
+ :hidden => :bool, # Order will not be visible in market depth. ISLAND only.
269
+ :transmit => :bool, # If false, order will be created but not transmitted.
270
+ :block_order => :bool, # This is an ISE Block order.
271
+ :sweep_to_fill => :bool, # This is a Sweep-to-Fill order.
272
+ :override_percentage_constraints => :bool,
273
+ # TWS Presets page constraints ensure that your price and size order values
274
+ # are reasonable. Orders sent from the API are also validated against these
275
+ # safety constraints, unless this parameter is set to True.
276
+ :all_or_none => :bool, # AON
277
+ :opt_out_smart_routing => :bool, # Australian exchange only, default false
278
+ :is_pegged_change_amount_decrease => :bool, # pegged_to_benchmark-oders, default false (increase)
279
+ :open_close => PROPS[:open_close], # Originally String: O=Open, C=Close ()
280
+ # for ComboLeg compatibility: SAME = 0; OPEN = 1; CLOSE = 2; UNKNOWN = 3;
281
+ [:side, :action] => PROPS[:side] # String: Action/side: BUY/SELL/SSHORT/SSHORTX
282
+
283
+ prop :placed_at,
284
+ :modified_at,
285
+ :leg_prices,
286
+ :algo_params,
287
+ :combo_params # Valid tags are LeginPrio, MaxSegSize, DontLeginNext, ChangeToMktTime1,
288
+ # ChangeToMktTime2, ChangeToMktOffset, DiscretionaryPct, NonGuaranteed,
289
+ # CondPriceMin, CondPriceMax, and PriceCondConid.
290
+ # to set an execuction-range of a security:
291
+ # PriceCondConid, 10375; -- conid of the combo-leg
292
+ # CondPriceMax, 62.0; -- max and min-price
293
+ # CondPriceMin.;60.0
294
+
295
+ prop :etrade_only, :firm_quote_only, :nbbo_price_cap # depreciated, needed for open-order message
296
+ # prop :misc1, :misc2, :misc3, :misc4, :misc5, :misc6, :misc7, :misc8 # just 4 debugging
297
+
298
+ alias order_combo_legs leg_prices
299
+ alias smart_combo_routing_params combo_params
300
+
301
+ # serialize is included for active_record compatibility
302
+ # serialize :leg_prices
303
+ # serialize :conditions
304
+ # serialize :algo_params, Hash
305
+ # serialize :combo_params
306
+ # serialize :soft_dollar_tier_params, HashWithIndifferentAccess
307
+ serialize :mics_options, Hash
308
+
309
+ # Order is always placed for a contract. We explicitly set this link.
310
+ belongs_to :contract
311
+
312
+ # Order has a collection of Executions if it was filled
313
+ has_many :executions
314
+
315
+ # Order has a collection of OrderStates. The last one is always current
316
+ has_many :order_states
317
+ # Order can have multible conditions
318
+ has_many :conditions
319
+
320
+ def order_state
321
+ order_states.last
322
+ end
323
+
324
+ def order_state= state
325
+ self.order_states.push case state
326
+ when IB::OrderState
327
+ state
328
+ when Symbol, String
329
+ IB::OrderState.new :status => state
330
+ end
331
+ end
332
+
333
+ # Some properties received from IB are separated into OrderState object,
334
+ # but they are still readable as Order properties through delegation:
335
+ # Properties arriving via OpenOrder message:
336
+ [:commission, # double: Shows the commission amount on the order.
337
+ :commission_currency, # String: Shows the currency of the commission.
338
+ :min_commission, # The possible min range of the actual order commission.
339
+ :max_commission, # The possible max range of the actual order commission.
340
+ :warning_text, # String: Displays a warning message if warranted.
341
+ :status, # String: Displays the order status. See OrderState for values
342
+ # Properties arriving via OrderStatus message:
343
+ :filled, # int
344
+ :remaining, # int
345
+ :price, # double
346
+ :last_fill_price, # double
347
+ :average_price, # double
348
+ :average_fill_price, # double
349
+ :why_held, # String: comma-separated list of reasons for order to be held.
350
+ # Testing Order state:
351
+ :new?,
352
+ :submitted?,
353
+ :pending?,
354
+ :active?,
355
+ :inactive?,
356
+ :complete_fill?
357
+ ].each { |property| define_method(property) { order_state.send(property) } }
358
+
359
+ [:init_margin, # Float: The impact the order would have on your initial margin.
360
+ :equity_with_loan, # Float: The impact the order would have on your equity
361
+ :maint_margin # Float: The impact the order would have on your maintenance margin.
362
+ ].each { |property| define_method(property) { order_state.send(property.to_s+"_change") } }
363
+
364
+ # Order is not valid without correct :local_id
365
+ validates_numericality_of :local_id, :perm_id, :client_id, :parent_id,
366
+ :total_quantity, :min_quantity, :display_size,
367
+ :only_integer => true, :allow_nil => true
368
+
369
+ validates_numericality_of :limit_price, :aux_price, :allow_nil => true
370
+
371
+
372
+ def default_attributes # default valus are taken from order.java
373
+ # public Order() { }
374
+ super.merge(
375
+ :active_start_time => "", # order.java # 470 # Vers 69
376
+ :active_stop_time => "", # order.java # 471 # Vers 69
377
+ :adjusted_order_type => "",
378
+ :algo_params => Hash.new, #{},
379
+ :algo_strategy => '',
380
+ :algo_id => '' , # order.java # 495
381
+ :all_or_none => false,
382
+ :auction_strategy => :none,
383
+ :aux_price => server_version < KNOWN_SERVERS[ :min_server_ver_trailing_percent ] ? 0 : '',
384
+ :block_order => false,
385
+ :combo_params => Hash.new,
386
+ :conditions => [],
387
+ :continuous_update => 0,
388
+ :delta => "",
389
+ :designated_location => '', # order.java # 487
390
+ :display_size => nil,
391
+ :discretionary_amount => 0,
392
+ :exempt_code => -1,
393
+ :ext_operator => '' , # order.java # 499
394
+ :hedge_param => [],
395
+ :hidden => false,
396
+ :is_pegged_change_amount_decrease => false,
397
+ :leg_prices => [],
398
+ :limit_price => server_version < KNOWN_SERVERS[ :min_server_ver_order_combo_legs_price ] ? 0 : '',
399
+ :min_quantity => "",
400
+ :model_code => "",
401
+ :not_held => false, # order.java # 494
402
+ :oca_type => :none,
403
+ :order_type => :limit,
404
+ :open_close => :open, # order.java #
405
+ :opt_out_smart_routing => false,
406
+ :order_state => IB::OrderState.new( :status => 'New',
407
+ :filled => 0,
408
+ :remaining => 0,
409
+ :price => 0,
410
+ :average_price => 0 ),
411
+ :origin => :customer,
412
+ :outside_rth => false, # order.java # 472
413
+ :override_percentage_constraints => false,
414
+ :percent_offset =>"",
415
+ :parent_id => 0,
416
+ :pegged_change_amount => 0.0,
417
+ :random_size => false, #oder.java 497 # Vers 76
418
+ :random_price => false, # order.java # 498 # Vers 76
419
+ :reference_price_type => "",
420
+ :reference_contract_id => 0,
421
+ :reference_change_amount => 0.0,
422
+ :reference_exchange_id => "",
423
+ :scale_auto_reset => false, # order.java # 490
424
+ :scale_random_percent => false, # order.java # 491
425
+ :scale_table => "", # order.java # 492
426
+ :stock_range_lower => "",
427
+ :stock_range_upper => "",
428
+ :stock_ref_price =>"",
429
+ :short_sale_slot => :default,
430
+ :solicided => false, # order.java # 496
431
+ :sweep_to_fill => false,
432
+ :tif => :day,
433
+ :trail_stop_price => "",
434
+ :trailing_percent => "",
435
+ :transmit => true,
436
+ :trigger_method => :default,
437
+ :use_price_management_algo => "",
438
+ :volatility_type => :annual,
439
+ :what_if => false, # order.java # 493
440
+
441
+ ) # closing of merge
442
+ end
443
+
444
+ def serialize_combo_legs(contract)
445
+ if contract.bag?
446
+ [ contract.serialize_legs,
447
+ # todo implement usecase
448
+ leg_prices.empty? ? 0 : [ leg_prices.size, leg_prices ],
449
+ # combo_params is an array of hashes
450
+ contract.combo_params.nil? || contract.combo_params.empty? ? 0 : [ contract.combo_params.size, contract.combo_params.to_a ]
451
+ ]
452
+ else
453
+ []
454
+ end
455
+ end
456
+ def serialize_main_order_fields
457
+ include_short = -> (s) { if s == :short then 'SSHORT' else s == :short_exempt ? 'SSHORTX' : s.to_sup end }
458
+ include_total_quantity = -> (q) { server_version >= KNOWN_SERVERS[ :min_server_ver_fractional_positions ] ? q.to_d : q.to_i }
459
+
460
+ [ include_short[ side ],
461
+ include_total_quantity[ total_quantity ],
462
+ self[ :order_type ], # Internal code, 'LMT' instead of :limit
463
+ limit_price ,
464
+ aux_price ]
465
+ end
466
+
467
+ def serialize_extended_order_fields
468
+
469
+ [ self[ :tif ],
470
+ oca_group,
471
+ account,
472
+ open_close.to_sup[0], # "O" or "C"
473
+ self[ :origin ], # translates :customer, :firm to 0,1
474
+ order_ref,
475
+ transmit,
476
+ parent_id,
477
+ block_order,
478
+ sweep_to_fill,
479
+ display_size,
480
+ self[ :trigger_method ],
481
+ outside_rth,
482
+ hidden ]
483
+ end
484
+
485
+ def serialize_auxilery_order_fields
486
+ [ "", # deprecated shares_allocation field
487
+ discretionary_amount,
488
+ good_after_time,
489
+ good_till_date,
490
+ serialize_advisory_order_fields
491
+ ]
492
+ end
493
+
494
+ =begin rdoc
495
+ Format of serialisation
496
+
497
+ count of records
498
+ for each condition: conditiontype, condition-fields
499
+ =end
500
+ def serialize_conditions
501
+ if conditions.empty?
502
+ [ 0 ]
503
+ else
504
+ [ conditions.size ] + conditions.map( &:serialize ) + [ conditions_ignore_rth, conditions_cancel_order ]
505
+ end
506
+ end
507
+
508
+ def serialize_algo
509
+ return [''] if algo_strategy.blank?
510
+ [algo_strategy, algo_params.size] + algo_params.to_a
511
+ end
512
+
513
+ def serialize_advisory_order_fields
514
+ aof = [ fa_group, fa_method, fa_percentage, fa_profile ]
515
+ if server_version < KNOWN_SERVERS[:min_server_ver_fa_profile_desupport]
516
+ aof
517
+ else
518
+ aof[ 0..-2 ]
519
+ end
520
+ end
521
+
522
+ def serialize_volatility_order_fields
523
+ if volatility.present?
524
+ [ volatility , # Volatility orders
525
+ self[:volatility_type] ] # default: annual volatility
526
+ else
527
+ ["",""]
528
+ end
529
+ end
530
+
531
+ def serialize_delta_neutral_order_fields
532
+
533
+ if delta_neutral_order_type && delta_neutral_order_type != :none
534
+ [
535
+ delta_neutral_con_id,
536
+ delta_neutral_settling_firm,
537
+ delta_neutral_clearing_account,
538
+ self[ :delta_neutral_clearing_intent ],
539
+ delta_neutral_open_close,
540
+ delta_neutral_short_sale,
541
+ delta_neutral_short_sale_slot,
542
+ delta_neutral_designated_location
543
+ ]
544
+ else
545
+ ['', '']
546
+ end
547
+ end
548
+
549
+ def serialize_scale_order_fields
550
+
551
+ a= [ scale_init_level_size || "",
552
+ scale_subs_level_size || "",
553
+ scale_price_increment || "" ]
554
+
555
+ # Support for extended scale orders parameters
556
+ if scale_price_increment.to_i > 0
557
+ a << [ scale_price_adjust_value || "",
558
+ scale_price_adjust_interval || "",
559
+ scale_profit_offset || "",
560
+ scale_auto_reset, # default: false,
561
+ scale_init_position || "",
562
+ scale_init_fill_qty || "",
563
+ scale_random_percent # default: false,
564
+ ]
565
+ end
566
+
567
+ a << scale_table
568
+ a << active_start_time || ""
569
+ a << active_stop_time || ""
570
+ a
571
+ end
572
+ def serialize_pegged_order_fields
573
+ if order_type == :pegged_to_benchmark && server_version >= KNOWN_SERVERS[ :min_server_ver_pegged_to_benchmark ]
574
+ [ reference_contract_id,
575
+ is_pegged_change_amount_decrease,
576
+ pegged_change_amount,
577
+ reference_change_amount,
578
+ reference_exchange_id ]
579
+ else
580
+ []
581
+ end
582
+ end
583
+
584
+ def serialize_advanced_option_order_fields
585
+
586
+ [ starting_price , # pegged to stock
587
+ stock_ref_price , # pegged to stock
588
+ delta , # pegged to stock
589
+ stock_range_lower , # pegged
590
+ stock_range_upper # pegged
591
+ ]
592
+ end
593
+
594
+ def serialize_soft_dollar_tier
595
+ [ soft_dollar_tier_name,
596
+ soft_dollar_tier_value
597
+ ]
598
+ end
599
+
600
+
601
+ def serialize_mifid_order_fields
602
+ a = []
603
+ if server_version >= KNOWN_SERVERS[:min_server_ver_decision_maker] # 138
604
+ a << [ mifid_2_decision_maker, mifid_2_decision_algo ]
605
+ end
606
+ if server_version >= KNOWN_SERVERS[:min_server_ver_mifid_execution] # 139
607
+ a << [ mifid_2_execution_maker, mifid_2_execution_algo ]
608
+ end
609
+ a
610
+ end
611
+
612
+ def serialize_peg_best_and_mid
613
+ return [] unless server_version >= KNOWN_SERVERS[:min_server_ver_pegbest_pegmid_offsets]
614
+ a = []
615
+ send_mid_offsets = false
616
+ a << min_trade_qty if contract.exchange == 'IBKRATS'
617
+ if order.type == :pegged_to_best
618
+ a << min_compete_size
619
+ a << compete_against_best_offset
620
+ send_mid_offsets = true if compete_against_best_offset.nil? # TODO: float max?
621
+ end
622
+ if order.type == :pegged_to_midpoint
623
+ send_mid_offsets = true
624
+ end
625
+ if send_mid_offsets
626
+ a << mid_offset_at_whole
627
+ a << mid_offset_at_half
628
+ end
629
+ a
630
+ end
631
+
632
+ def serialize_misc_options
633
+ "" # Vers. 70
634
+ end
635
+ # Order comparison
636
+ def == other
637
+ super(other) ||
638
+ other.is_a?(self.class) &&
639
+ (perm_id && other.perm_id && perm_id == other.perm_id ||
640
+ local_id == other.local_id && # ((p __LINE__)||true) &&
641
+ (client_id == other.client_id || client_id == 0 || other.client_id == 0) &&
642
+ parent_id == other.parent_id &&
643
+ tif == other.tif &&
644
+ action == other.action &&
645
+ order_type == other.order_type &&
646
+ total_quantity == other.total_quantity &&
647
+ limit_price == other.limit_price &&
648
+ aux_price == other.aux_price &&
649
+ origin == other.origin &&
650
+ designated_location == other.designated_location &&
651
+ exempt_code == other.exempt_code &&
652
+ what_if == other.what_if &&
653
+ algo_strategy == other.algo_strategy &&
654
+ algo_params == other.algo_params)
655
+
656
+ # TODO: compare more attributes!
657
+ end
658
+
659
+ def to_s #human
660
+ "<Order:" + instance_variables.map do |key|
661
+ value = instance_variable_get(key)
662
+ " #{key}=#{value}" unless value.nil? || value == '' || value == 0
663
+ end.compact.join(',') + " >"
664
+ end
665
+
666
+ def to_human
667
+ misc = []
668
+ misc << algo_strategy if algo_strategy.present?
669
+ misc << "benchmark con-id: #{reference_contract_id}" if reference_contract_id.to_i >0
670
+ misc << "vola: #{volatility}" if volatility.present?
671
+ misc << "fee: #{commission}" if commission.present?
672
+ misc << "dc: #{discretionary_amount}," if discretionary_amount.to_i != 0
673
+ "<Order: " + (order_ref.present? ? order_ref.to_s : '') +
674
+ "#{self[:order_type]} #{self[:tif]} #{action} #{total_quantity} " + " @ " +
675
+ (limit_price ? "#{limit_price} " : '') + "#{status} " +
676
+ ((aux_price && aux_price != 0) ? "/#{aux_price}" : '') +
677
+ "##{local_id}/#{perm_id} from #{client_id}" +
678
+ (account ? "/#{account}" : '') +
679
+ (misc.empty? ? "" : " ") + misc.join( " " ) + ">"
680
+ end
681
+
682
+ alias inspect to_human
683
+
684
+
685
+ def table_header
686
+ [ 'account','status', 'contract', 'type', 'tif', 'action', 'amount','price' , '','misc' ]
687
+ end
688
+
689
+ def table_row
690
+ misc = []
691
+ misc << algo_strategy if algo_strategy.present?
692
+ misc << " benchmark con-id: #{reference_contract_id}" if reference_contract_id.to_i > 0
693
+ misc << " vola: #{volatility}" if volatility.present?
694
+ misc << " fee: #{commission}" if commission.present?
695
+ misc << " id: #{local_id}" if local_id.to_i > 0
696
+ misc << " dc: #{discretionary_amount}," if discretionary_amount.to_i != 0
697
+ [ account, order_ref.present? ? order_ref.to_s : status,
698
+ contract.to_human.then{ |y| y.size > 20 ? y[ 1 .. 20 ] + "…" : y[1..-2] },
699
+ self[:order_type] ,
700
+ self[:tif],
701
+ action,
702
+ total_quantity,
703
+ ((limit_price && !limit_price.to_i.zero?) ? "#{limit_price} " : '') + ((aux_price && !aux_price.to_i.zero?) ? "/#{aux_price}" : '') , !what_if.blank? ? "Preview" : "",
704
+ misc.join( " " ) ]
705
+ end
706
+
707
+ def serialize_rabbit
708
+ { 'Contract' => contract.present? ? contract.serialize( :option, :trading_class ): '' ,
709
+ 'Order' => self,
710
+ 'OrderState' => order_state}
711
+ end
712
+
713
+ # expell uncommon attributes
714
+ def invariant_attributes
715
+ attributes.reject{ |x| [ :designated_location, :display_size, :etrade_only, :exempt_code, :ext_operator, :random_size, :random_price, :firm_quote_only, :scale_auto_reset, :scale_random_percent, :scale_table, :short_sale_slot, :solicided, :created_at, :modified_at ].include? x }
716
+
717
+ end
718
+
719
+ end # class Order
720
+ end # module IB