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,157 @@
1
+ module IB
2
+
3
+ =begin
4
+
5
+ Plugin to support a simple Order-Flow
6
+
7
+ Public API
8
+ ==========
9
+
10
+ Extends IB::Order
11
+
12
+ * check_margin
13
+ * depends on a previously submitted `what-if' order
14
+ * on success it returns the order-object for further processing, otherwise nil.
15
+ * place
16
+ * submit the order
17
+ * return a order-object for further processing
18
+ * modify
19
+ * modify price or quantity of the submitted order
20
+ * cancel
21
+ * submit a cancel request
22
+
23
+ =end
24
+ module OrderFlow
25
+ # Placement
26
+ #
27
+ # The Order is only placed, if local_id is not set
28
+ #
29
+ # Modifies the Order-Object and returns the assigned local_id
30
+ def place
31
+ connection = IB::Connection.current
32
+ error "Unable to place order, next_local_id not known" unless connection.next_local_id
33
+ error "local_id present. Order is already placed. Do you want to modify?" unless local_id.nil?
34
+ # self.client_id = connection.client_id
35
+ self.local_id = connection.next_local_id
36
+ connection.next_local_id += 1
37
+ self.placed_at = Time.now
38
+ #connection.place_order self.dup.then{|y| y.contract = nil; y}, contract
39
+ modify
40
+ end
41
+
42
+ # Modify Order (convenience wrapper for send_message :PlaceOrder), returns order record received trom tws
43
+ def modify
44
+ error "Unable to modify order; local_id not specified" if local_id.nil?
45
+ error "Unable to place order, contract has to be specified" unless contract.is_a?( IB::Contract )
46
+
47
+ ib = IB::Connection.current
48
+ q = Queue.new
49
+ is = ib.subscribe( :OpenOrder ) do | msg |
50
+ puts msg.to_human
51
+ if msg.order.local_id == local_id
52
+ q << msg.order
53
+ end
54
+ end
55
+ ia = ib.subscribe( :Alert ) do | msg|
56
+ ib.logger.error msg.to_human
57
+ end
58
+
59
+ self.modified_at = Time.now
60
+ ib.send_message :PlaceOrder,
61
+ :local_id => local_id,
62
+ :order => self.dup.then{|y| y.contract = nil; y},
63
+ :contract => if contract.con_id.to_i > 0
64
+ Contract.new con_id: the_contract.con_id,
65
+ exchange: the_contract.exchange
66
+ else
67
+ contract
68
+ end
69
+
70
+ th = Thread.new{ sleep 1 ; q.close }
71
+ received_order = q.pop # synchronize
72
+ ib.unsubscribe ia, is
73
+ if q.closed?
74
+ error "order #{to_human} is not accepted", :reader
75
+ self # return original error after error handling
76
+ else
77
+ Thread.kill th
78
+ q.close
79
+ received_order
80
+ end
81
+ end
82
+
83
+ # returns the order if the margin-requirements are met
84
+ #
85
+ # Details of the test are published in the log (level: LOGGER::INOT)
86
+ #
87
+ # typical setup
88
+ # ```ruby
89
+ # ib = IB::Connection.new
90
+ # ib.activate_plugin ...
91
+ # u = ib.clients.last
92
+ # submitted_order = u.preview( order: some_order, contract: some_contract )
93
+ # .check_margin( 0.25 ) &.place
94
+ # place order only if after its placement Equity-with-loan ist minimal 25 percent higher then the margin requirements
95
+ # i.e. the margin utilization is max. 75 %.
96
+ #
97
+ # ```
98
+ def check_margin treshold = 0.1
99
+ error "Unable to check margin, forcast is not initialized" if order_state.nil? or order_state.init_margin_after.nil?
100
+ utilization = order_state.init_margin_after / order_state.equity_with_loan_after
101
+ if 1 - utilization > treshold
102
+ Connection.current.logger.info "Margin OK: #{action} #{total_quantity} of #{contract.to_human}: requirements: #{order_state.init_margin_change.round} #{contract.currency} equals to #{utilization.round(1) *100} % margin utilization"
103
+ self
104
+ else
105
+ Connection.current.logger.info "Margin requirements NOT met, utilization: #{utilization.round(2) *100} % ( margin requirement: #{order_state.init_margin_change.round} #{contract.currency})"
106
+ nil
107
+ end
108
+ end
109
+ #
110
+ # Auto Adjust implements a simple algorithm to ensure that an order is accepted
111
+
112
+ # It reads `contract_detail.min_tick`.
113
+ #
114
+ # For min-tick smaller then 0.01, the value is rounded to the next higer digit.
115
+ #
116
+ # The method mutates the Order-Object.
117
+ #
118
+ # | min-tick | round |
119
+ # |--------------|------------|
120
+ # | 10 | 110 |
121
+ # | 1 | 111 |
122
+ # | 0.1 | 111.1 |
123
+ # | 0.01 | 111.11 |
124
+ # | 0.001 | 111.111 |
125
+ # | 0.0001 | 111.111 |
126
+ # |--------------|------------|
127
+ #
128
+ def auto_adjust
129
+ # lambda to perform the calculation
130
+ adjust_price = ->(a,b) do
131
+ count = -Math.log10(b).round.to_i
132
+ count = count -1 if count > 2
133
+ a.round count
134
+
135
+ end
136
+
137
+
138
+ error "No Contract provided to Auto adjust" unless contract.is_a? IB::Contract
139
+
140
+ unless contract.is_a? IB::Bag
141
+
142
+ min_tick = contract.then{ |y| y.contract_detail.is_a?( IB::ContractDetail ) ? y.contract_detail.min_tick : y.verify.first.contract_detail.min_tick }
143
+ # there are two attributes to consider: limit_price and aux_price
144
+ # limit_price + aux_price may be nil or an empty string. Then ".to_f.zero?" becomes true
145
+ self.limit_price = adjust_price.call(limit_price.to_d, min_tick) unless limit_price.to_f.zero?
146
+ self.aux_price = adjust_price.call(aux_price.to_d, min_tick) unless aux_price.to_f.zero?
147
+ end
148
+ end
149
+
150
+ end # module OrderFlow
151
+
152
+ class Order
153
+ include OrderFlow
154
+ end # class
155
+ # Connection.current.activate_plugin 'process-orders'
156
+ end # module IB
157
+
@@ -0,0 +1,67 @@
1
+ # These modules are used to facilitate referencing of most common Ordertypes
2
+
3
+ module IB
4
+ module OrderPrototype
5
+
6
+
7
+
8
+
9
+ def order **fields
10
+
11
+ # special treatment of size: positive numbers --> buy order, negative: sell
12
+ if fields[:size].present? && fields[:action].blank?
13
+ error "Size = 0 is not possible" if fields[:size].zero?
14
+ fields[:action] = fields[:size] >0 ? :buy : :sell
15
+ fields[:size] = fields[:size].abs
16
+ end
17
+ # change aliases to the original. We are modifying the fields-hash.
18
+ fields.keys.each{|x| fields[aliases.key(x)] = fields.delete(x) if aliases.has_value?(x)}
19
+ # inlcude defaults (arguments override defaults)
20
+ the_arguments = defaults.merge fields
21
+ # check if requirements are fullfilled
22
+ necessary = requirements.keys.detect{|y| the_arguments[y].nil?}
23
+ if necessary.present?
24
+ msg =self.name + ".order -> A necessary field is missing: #{necessary}: --> #{requirements[necessary]}"
25
+ error msg, :args, nil
26
+ end
27
+ if alternative_parameters.present?
28
+ unless ( alternative_parameters.keys & the_arguments.keys ).size == 1
29
+ msg =self.name + ".order -> One of the alternative fields needs to be specified: \n\t:" +
30
+ "#{alternative_parameters.map{|x| x.join ' => '}.join(" or \n\t:")}"
31
+ error msg, :args, nil
32
+ end
33
+ end
34
+
35
+ # initialise order with given attributes
36
+ IB::Order.new the_arguments
37
+ end
38
+
39
+ def alternative_parameters
40
+ {}
41
+ end
42
+ def requirements
43
+ { action: IB::VALUES[:side], total_quantity: 'also aliased as :size' }
44
+ end
45
+
46
+ def defaults
47
+ { tif: :good_till_cancelled }
48
+ end
49
+
50
+ def optional
51
+ { account: 'Account(number) to trade on' }
52
+ end
53
+
54
+ def aliases
55
+ { total_quantity: :size }
56
+ end
57
+
58
+ def parameters
59
+ the_output = ->(var){ var.map{|x| x.join(" --> ") }.join("\n\t: ")}
60
+
61
+ "Required : " + the_output[requirements] + "\n --------------- \n" +
62
+ "Optional : " + the_output[optional] + "\n --------------- \n"
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,40 @@
1
+
2
+ module IB
3
+ # module OrderPrototype
4
+ module Adaptive
5
+ extend OrderPrototype
6
+ class << self
7
+
8
+ def defaults
9
+ Limit.defaults.merge algo_strategy: "Adaptive",
10
+ algo_params: { "adaptivePriority" => "Normal" }
11
+ end
12
+
13
+ def aliases
14
+ Limit.aliases
15
+ end
16
+
17
+ def requirements
18
+ Limit.requirements
19
+ end
20
+
21
+
22
+ def summary
23
+ <<-HERE
24
+ The Adaptive Algo combines IB’s Smart routing capabilities with user-defined
25
+ priority settings in an effort to achieve further cost efficiency at the
26
+ point of execution. Using the Adaptive algo leads to better execution prices
27
+ on average than for regular limit or market orders.
28
+
29
+ Algo Strategy Value: Adaptive
30
+
31
+ adaptivePriority: String. The ‘Priority’ selector determines the time taken
32
+ to scan for better execution prices. The ‘Urgent’ setting scans only briefly,
33
+ while the ‘Patient’ scan works more slowly and has a higher chance of
34
+ achieving a better overall fill for your order. Valid Value/Format:
35
+ Urgent > Normal > Patient
36
+ HERE
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ module IB
2
+
3
+ #Combo-Orders are used for NonGuaranteed Orders only.
4
+ #»Normal« Option-Spreads are transmited by ordinary Limit-Orders
5
+ module Combo
6
+ ### Basic Order Prototype: Combo with two limits
7
+ extend OrderPrototype
8
+ class << self
9
+ def defaults
10
+ ## todo implement serialisation of key/tag Hash to camelCased-keyValue-List
11
+ # super.merge order_type: :limit , combo_params: { non_guaranteed: true}
12
+ # for the time being, we use the array representation
13
+ super.merge order_type: :limit , combo_params: [ ['NonGuaranteed', true] ]
14
+ end
15
+
16
+
17
+ def requirements
18
+ Limit.requirements
19
+ end
20
+
21
+ def aliases
22
+ Limit.aliases
23
+ end
24
+
25
+
26
+ def summary
27
+ <<-HERE
28
+ Create combination orders. It is constructed through options, stock and futures legs
29
+ (stock legs can be included if the order is routed through SmartRouting).
30
+
31
+ Although a combination/spread order is constructed of separate legs, it is executed
32
+ as a single transaction if it is routed directly to an exchange. For combination orders
33
+ that are SmartRouted, each leg may be executed separately to ensure best execution.
34
+
35
+ The »NonGuaranteed«-Flag is set to "false". A Pair of two securites should always be
36
+ routed »Guaranteed«, otherwise separate orders are prefered.
37
+
38
+ If a Bag-Order with »NonGuarateed :true« should be submitted, the Order-Type would be
39
+ REL+MKT, LMT+MKT, or REL+LMT
40
+ --------
41
+ Products: Options, Stocks, Futures
42
+ HERE
43
+ end # def
44
+ end # class
45
+ end # module combo
46
+ end # module ib
@@ -0,0 +1,46 @@
1
+ module IB
2
+
3
+ #Combo-Orders are used for NonGuaranteed Orders only.
4
+ #»Normal« Option-Spreads are transmited by ordinary Limit-Orders
5
+ module Combo
6
+ ### Basic Order Prototype: Combo with two limits
7
+ extend OrderPrototype
8
+ class << self
9
+ def defaults
10
+ ## todo implement serialisation of key/tag Hash to camelCased-keyValue-List
11
+ # super.merge order_type: :limit , combo_params: { non_guaranteed: true}
12
+ # for the time being, we use the array representation
13
+ super.merge order_type: :limit , combo_params: [ ['NonGuaranteed', true] ]
14
+ end
15
+
16
+
17
+ def requirements
18
+ Limit.requirements
19
+ end
20
+
21
+ def aliases
22
+ Limit.aliases
23
+ end
24
+
25
+
26
+ def summary
27
+ <<-HERE
28
+ Create combination orders. It is constructed through options, stock and futures legs
29
+ (stock legs can be included if the order is routed through SmartRouting).
30
+
31
+ Although a combination/spread order is constructed of separate legs, it is executed
32
+ as a single transaction if it is routed directly to an exchange. For combination orders
33
+ that are SmartRouted, each leg may be executed separately to ensure best execution.
34
+
35
+ The »NonGuaranteed«-Flag is set to "false". A Pair of two securites should always be
36
+ routed »Guaranteed«, otherwise separate orders are prefered.
37
+
38
+ If a Bag-Order with »NonGuarateed :true« should be submitted, the Order-Type would be
39
+ REL+MKT, LMT+MKT, or REL+LMT
40
+ --------
41
+ Products: Options, Stocks, Futures
42
+ HERE
43
+ end # def
44
+ end # class
45
+ end # module combo
46
+ end # module ib
@@ -0,0 +1,40 @@
1
+ module IB
2
+ # module UseOrder
3
+ module ForexLimit
4
+ extend OrderPrototype
5
+ class << self
6
+
7
+
8
+ def defaults
9
+ super.merge order_type: :limit , tif: :day
10
+ end
11
+
12
+
13
+ def requirements
14
+ super.merge cash_qty: '(true/false) to indicate to let IB calculate the cash-quantity of the alternate currency'
15
+ end
16
+
17
+
18
+ def summary
19
+ <<-HERE
20
+ Forex orders can be placed in denomination of second currency in pair using cashQty field.
21
+ Don't specify a limit-price to force immidiate execution.
22
+ HERE
23
+ end
24
+ end
25
+ =begin
26
+ 2.5.0 :001 > f = Symbols::Forex[:eurusd]
27
+ => #<IB::Contract:0x0000000003299458 @attributes={"symbol"=>"EUR", "exchange"=>"IDEALPRO", "currency"=>"USD", "sec_type"=>"CASH", "created_at"=>2018-01-20 05:21:01 +0100, "updated_at"=>2018-01-20 05:21:01 +0100, "con_id"=>0, "right"=>"", "include_expired"=>false}, @description="EURUSD">
28
+
29
+ 2.5.0 :002 > uf = ForexLimit.order action: :buy, size: 15000, cash_qty: true
30
+ {:action=>:buy, :cash_qty=>true, :total_quantity=>15000}
31
+ => #<IB::Order:0x0000000002f45a40 @attributes={"tif"=>"DAY", "order_type"=>"LMT", "side"=>"B", "cash_qty"=>true, "total_quantity"=>15000, "created_at"=>2018-01-20 05:21:06 +0100, "updated_at"=>2018-01-20 05:21:06 +0100, "active_start_time"=>"", "active_stop_time"=>"", "algo_strategy"=>"", "algo_id"=>"", "auction_strategy"=>0, "conditions"=>[], "continuous_update"=>0, "delta_neutral_designated_location"=>"", "delta_neutral_con_id"=>0, "delta_neutral_settling_firm"=>"", "delta_neutral_clearing_account"=>"", "delta_neutral_clearing_intent"=>"", "designated_location"=>"", "display_size"=>0, "discretionary_amount"=>0, "etrade_only"=>true, "exempt_code"=>-1, "ext_operator"=>"", "firm_quote_only"=>true, "not_held"=>false, "oca_type"=>0, "open_close"=>1, "opt_out_smart_routing"=>false, "origin"=>0, "outside_rth"=>false, "parent_id"=>0, "random_size"=>false, "random_price"=>false, "scale_auto_reset"=>false, "scale_random_percent"=>false, "scale_table"=>"", "short_sale_slot"=>0, "solicided"=>false, "transmit"=>true, "trigger_method"=>0, "what_if"=>false, "leg_prices"=>[], "algo_params"=>{}, "combo_params"=>[], "soft_dollar_tier_params"=>{"name"=>"", "val"=>"", "display_name"=>""}}, @order_states=[#<IB::OrderState:0x0000000002f44258 @attributes={"status"=>"New", "filled"=>0, "remaining"=>0, "price"=>0, "average_price"=>0, "created_at"=>2018-01-20 05:21:06 +0100, "updated_at"=>2018-01-20 05:21:06 +0100}>]>
32
+ 2.5.0 :004 > C.place_order uf, f
33
+ => 4
34
+ 2.5.0 :005 > 05:21:23.606 Got message 4 (IB::Messages::Incoming::Alert)
35
+ I, [2018-01-20T05:21:23.606819 #31020] INFO -- : TWS Warning 10164: Traders are responsible for understanding cash quantity details, which are provided on a best efforts basis only.
36
+ Restriction is specified in Precautionary Settings of Global Configuration/Presets.
37
+
38
+ =end
39
+ end
40
+ end
@@ -0,0 +1,193 @@
1
+
2
+ module IB
3
+ module Limit
4
+ extend OrderPrototype
5
+ class << self
6
+
7
+ def defaults
8
+ super.merge order_type: :limit
9
+ end
10
+
11
+ def aliases
12
+ super.merge limit_price: :price
13
+ end
14
+
15
+ def requirements
16
+ super.merge limit_price: "also aliased as :price"
17
+ end
18
+
19
+
20
+ def summary
21
+ <<-HERE
22
+ A Limit order is an order to buy or sell at a specified price or better.
23
+ The Limit order ensures that if the order fills, it will not fill at a price less favorable than
24
+ your limit price, but it does not guarantee a fill.
25
+ It appears in the orderbook.
26
+ HERE
27
+ end
28
+ end
29
+ end
30
+ module Discretionary
31
+ extend OrderPrototype
32
+ class << self
33
+
34
+ def defaults
35
+ Limit.defaults
36
+ end
37
+
38
+ def aliases
39
+ Limit.aliases.merge discretionary_amount: :dc
40
+ end
41
+
42
+ def requirements
43
+ Limit.requirements
44
+ end
45
+
46
+ def optional
47
+ super.merge discretionary_amount: :decimal
48
+ end
49
+
50
+ def summary
51
+ <<-HERE
52
+ A Discretionary order is a Limitorder submitted with a hidden,
53
+ specified 'discretionary' amount off the limit price which may be used
54
+ to increase the price range over which the limit order is eligible to execute.
55
+ The market sees only the limit price.
56
+ The discretionary amount adds to the given limit price. The main effort is
57
+ to hide your real intentions from the public. Discretionary orders can be placed
58
+ for stocks and option on us exchanges, using 'SMART' routing.
59
+ HERE
60
+ end
61
+
62
+ def example
63
+ <<-HERE
64
+ You want to by a stock for 65 $ or less. Its trading is volatile, the spread is large.
65
+ There is a technical resistence at 64.5 $ and you think, that there will be a price
66
+ floor somewhere between 64.5 and 65 $. You place a limit order
67
+ at 64.5 $, which appears in the order book. Secretly, you instruct your broker to
68
+ fill the order, if the price is lower then 65 $. Chances for a filling are inceased.
69
+
70
+ ```
71
+ dc_order = IB::Discretionary.order size: 1000, price: 65, dc: 0.5
72
+ account.place order: dc_order, contract: IB::Stock.new( symbol: 'BN' )
73
+ ```
74
+ HERE
75
+ end
76
+ end
77
+ end
78
+ # module OrderPrototype
79
+ module Sweep2Fill
80
+ extend OrderPrototype
81
+ class << self
82
+
83
+ def defaults
84
+ super.merge order_type: ':limit' , tif: :day, sweep_to_fill: true
85
+ end
86
+
87
+ def aliases
88
+ Limit.aliases
89
+ end
90
+
91
+ def requirements
92
+ Limit.requirements
93
+ end
94
+
95
+
96
+ def summary
97
+ <<-HERE
98
+ Sweep-to-fill orders are useful when a trader values speed of execution over price. A sweep-to-fill
99
+ order identifies the best price and the exact quantity offered/available at that price, and
100
+ transmits the corresponding portion of your order for immediate execution. Simultaneously it
101
+ identifies the next best price and quantity offered/available, and submits the matching quantity
102
+ of your order for immediate execution.
103
+
104
+ ------------------------
105
+ Products: CFD, STK, WAR (SMART only)
106
+
107
+ HERE
108
+ end
109
+ end
110
+ end
111
+ module LimitIfTouched
112
+ extend OrderPrototype
113
+ class << self
114
+
115
+ def defaults
116
+ Limit.defaults.merge order_type: :limit_if_touched
117
+ end
118
+
119
+ def aliases
120
+ Limit.aliases.merge aux_price: :trigger_price
121
+ end
122
+
123
+ def requirements
124
+ Limit.requirements.merge aux_price: 'also aliased as :trigger_price '
125
+ end
126
+
127
+
128
+ def summary
129
+ <<-HERE
130
+ A Limit if Touched is an order to buy (or sell) a contract at a specified price or better,
131
+ below (or above) the market. This order is held in the system until the trigger price is touched.
132
+ An LIT order is similar to a stop limit order, except that an LIT sell order is placed above
133
+ the current market price, and a stop limit sell order is placed below.
134
+ HERE
135
+ end
136
+ end
137
+ end
138
+
139
+
140
+ module LimitOnClose
141
+ extend OrderPrototype
142
+ class << self
143
+
144
+ def defaults
145
+ Limit.defaults.merge order_type: :limit_on_close
146
+ end
147
+
148
+ def aliases
149
+ Limit.aliases
150
+ end
151
+
152
+ def requirements
153
+ Limit.requirements
154
+ end
155
+
156
+
157
+ def summary
158
+ <<-HERE
159
+ A Limit-on-close (LOC) order will be submitted at the close and will execute if the
160
+ closing price is at or better than the submitted limit price.
161
+ HERE
162
+ end
163
+ end
164
+ end
165
+
166
+ module LimitOnOpen
167
+ extend OrderPrototype
168
+ class << self
169
+
170
+ def defaults
171
+ super.merge order_type: :limit_on_open , tif: :opening_price
172
+ end
173
+
174
+ def aliases
175
+ Limit.aliases
176
+ end
177
+
178
+ def requirements
179
+ Limit.requirements
180
+ end
181
+
182
+
183
+ def summary
184
+ <<-HERE
185
+ A Limit-on-Open (LOO) order combines a limit order with the OPG time in force to create an
186
+ order that is submitted at the market's open, and that will only execute at the specified
187
+ limit price or better. Orders are filled in accordance with specific exchange rules.
188
+ HERE
189
+ end
190
+ end
191
+ end
192
+ # end
193
+ end