ib-extensions 1.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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +9 -0
  7. data/Gemfile.lock +112 -0
  8. data/Guardfile +24 -0
  9. data/README.md +99 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +96 -0
  12. data/bin/console.yml +3 -0
  13. data/bin/gateway.rb +97 -0
  14. data/bin/setup +8 -0
  15. data/changelog.md +31 -0
  16. data/examples/cancel_orders +74 -0
  17. data/examples/eod +35 -0
  18. data/examples/input.rb +475 -0
  19. data/examples/market_price +57 -0
  20. data/examples/option_chain +67 -0
  21. data/examples/place_and_modify_order +162 -0
  22. data/examples/place_bracket_order +62 -0
  23. data/examples/place_butterfly_order +104 -0
  24. data/examples/place_combo_order +70 -0
  25. data/examples/place_limit_order +82 -0
  26. data/examples/place_the_limit_order +145 -0
  27. data/examples/volatility_research +139 -0
  28. data/examples/what_if_order +90 -0
  29. data/ib-extensions.gemspec +37 -0
  30. data/lib/ib-gateway.rb +5 -0
  31. data/lib/ib/alerts/base-alert.rb +128 -0
  32. data/lib/ib/alerts/gateway-alerts.rb +15 -0
  33. data/lib/ib/alerts/order-alerts.rb +68 -0
  34. data/lib/ib/eod.rb +152 -0
  35. data/lib/ib/extensions.rb +9 -0
  36. data/lib/ib/extensions/contract.rb +37 -0
  37. data/lib/ib/extensions/version.rb +5 -0
  38. data/lib/ib/flex.rb +150 -0
  39. data/lib/ib/gateway.rb +425 -0
  40. data/lib/ib/gateway/account-infos.rb +115 -0
  41. data/lib/ib/gateway/order-handling.rb +150 -0
  42. data/lib/ib/market-price.rb +134 -0
  43. data/lib/ib/models/account.rb +329 -0
  44. data/lib/ib/models/spread.rb +159 -0
  45. data/lib/ib/option-chain.rb +198 -0
  46. data/lib/ib/option-greeks.rb +88 -0
  47. data/lib/ib/order-prototypes.rb +110 -0
  48. data/lib/ib/order_prototypes/abstract.rb +67 -0
  49. data/lib/ib/order_prototypes/combo.rb +46 -0
  50. data/lib/ib/order_prototypes/forex.rb +40 -0
  51. data/lib/ib/order_prototypes/limit.rb +177 -0
  52. data/lib/ib/order_prototypes/market.rb +116 -0
  53. data/lib/ib/order_prototypes/pegged.rb +173 -0
  54. data/lib/ib/order_prototypes/premarket.rb +31 -0
  55. data/lib/ib/order_prototypes/stop.rb +202 -0
  56. data/lib/ib/order_prototypes/volatility.rb +39 -0
  57. data/lib/ib/spread-prototypes.rb +62 -0
  58. data/lib/ib/spread_prototypes/butterfly.rb +79 -0
  59. data/lib/ib/spread_prototypes/calendar.rb +85 -0
  60. data/lib/ib/spread_prototypes/stock-spread.rb +48 -0
  61. data/lib/ib/spread_prototypes/straddle.rb +75 -0
  62. data/lib/ib/spread_prototypes/strangle.rb +96 -0
  63. data/lib/ib/spread_prototypes/vertical.rb +84 -0
  64. data/lib/ib/verify.rb +226 -0
  65. metadata +206 -0
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Fetching market-prices for 500 Contracts
4
+ #
5
+ # Ensure to run `ruby input.rb` prior to the first run.
6
+ # That initializes the watchlist `W500`.
7
+ #
8
+ # First a (fast) asynchron request is fired.
9
+ # Second a (much slower) synchron attempt is drawn
10
+
11
+ require 'bundler/setup'
12
+ require 'ib/symbols'
13
+ require 'ib/market-price'
14
+ require 'yaml'
15
+
16
+ # First, connect to IB TWS and subscribe for events.
17
+ ib = IB::Connection.new :client_id => 1112 do | gw | #, :port => 7497 # TWS
18
+
19
+ # Subscribe to TWS alerts/errors
20
+ gw.subscribe(:Alert) { |msg| puts msg.to_human }
21
+ # Set log level
22
+ gw.logger.level = Logger::FATAL # DEBUG -- INFO -- WARN -- ERROR -- FATAL
23
+
24
+ end
25
+ # Put your code here
26
+ # ...
27
+ IB::Symbols.allocate_collection :w500
28
+
29
+ puts
30
+ puts '*'*40
31
+ puts "(1) asynchon fetching of snapshot data "
32
+ start = Time.now;
33
+ IB::Symbols::W500.bunch(45,1){|x| x.map{|y| y.market_price(thread: true)}};
34
+
35
+ print "Finished Time:"
36
+ puts second_duration = Time.now - start
37
+ puts "Prices: "; sleep(7)
38
+ puts IB::Symbols::W500.map{|x| x.misc}.join( ' - ' )
39
+
40
+ IB::Connection.current.disconnect
41
+ IB::Connection.current.connect
42
+ puts '*'*40
43
+ puts "(2) sequencial fetching of snapshot data "
44
+ start = Time.now;
45
+ prices = IB::Symbols::W500.map &:market_price
46
+
47
+ print "Finished Time:"
48
+ puts first_duration = Time.now - start
49
+
50
+ puts "Prices: #{prices.map( &:to_s ).join(" - ")}"
51
+
52
+
53
+ puts
54
+ puts "first_duration: #{first_duration} s "
55
+ puts "second_duration: #{second_duration} s "
56
+
57
+ puts "finished"
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Gets the OptionChain of GE
4
+
5
+ require 'bundler/setup'
6
+ require 'ib-api'
7
+ require 'ib/verify'
8
+
9
+ # First, connect to IB TWS and subscribe for events.
10
+ ib = IB::Connection.new :client_id => 1112 do | gw | #, :port => 7497 # TWS
11
+
12
+ # Subscribe to TWS alerts/errors
13
+ gw.subscribe(:Alert) { |msg| puts msg.to_human }
14
+ # Set log level
15
+ gw.logger.level = Logger::ERROR # DEBUG # -- INFO -- WARN -- ERROR -- FATAL
16
+
17
+ end
18
+
19
+ TheYear = 2021
20
+ TheStrike = 6
21
+ TheRight = :put
22
+
23
+ # get expiries (last-trading-days)
24
+ the_contract = IB::Option.new symbol: 'GE',
25
+ currency: 'USD',
26
+ exchange: 'SMART',
27
+ expiry: TheYear,
28
+ strike: TheStrike,
29
+ right: TheRight
30
+
31
+ provided_expiries = Array.new
32
+
33
+ puts "Using #{the_contract.to_human}"
34
+
35
+ # get all available expiries
36
+ the_contract.verify do | detected_contract |
37
+ # last trading day: format yyyy-mm-dd
38
+ # expiry: format yyyymmdd
39
+ provided_expiries << detected_contract.last_trading_day
40
+ end
41
+ puts "detected Expiries #{provided_expiries.sort{|a,b| a.to_f <=> b.to_f }.join(" -- ")}"
42
+ puts
43
+
44
+
45
+
46
+ # get provided strikes
47
+ option_matrix = provided_expiries.map do | last_trading_day |
48
+ provided_strikes = Array.new
49
+
50
+ # because we used last_trading day as input to the expiry's array, it has to be assigned that way, too
51
+ the_contract = IB::Option.new symbol: 'GE', currency: 'USD', exchange: 'SMART', last_trading_day: last_trading_day, right: TheRight
52
+
53
+ the_contract.verify do | detected_contract |
54
+ provided_strikes << detected_contract.strike
55
+ end
56
+ puts "Expiry: #{the_contract.expiry}"
57
+ puts "Strikes: "+ provided_strikes.join(" -- ")
58
+ provided_strikes # return array
59
+
60
+ end
61
+
62
+ puts "NOTICE: Strikes are not sorted when :RequestContractData is used"
63
+ # print summary
64
+ #option_matrix.zip( provided_expiries) do | strikes, expiry|
65
+ # puts "expiry #{strikes}"
66
+ # puts "provided strikes: #{strikes.join(' ')}"
67
+ #end
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ ## This script places WFC buy order for 100 lots
4
+ #
5
+ ## RUN ONLY ON A DEMO ACCOUNT
6
+
7
+ module OrderPlacement
8
+
9
+ # Utility Method
10
+ #
11
+ # gets the most recent price of the asset
12
+ # User has to specify order in the block provided
13
+ # returns the order_id
14
+ #
15
+ def place_the_order( contract: IB::Symbols::Stocks.wfc, modus: :place ) # modus: place or modify
16
+ # First, get the current connection
17
+ ib = IB::Connection.current
18
+ raise 'Unable to place order, no connection' unless ib && ib.connected?
19
+ # Ask the TWS for the last available price for the asset,
20
+ # Optional: switch to delayed data, if no market-data subscription is booked;
21
+ # Unsubscribe from the Marketdata-Feed after successfully received the data
22
+ ib.send_message :RequestMarketDataType, :market_data_type => :delayed
23
+ the_id = ib.send_message :RequestMarketData, contract: contract
24
+ ib.wait_for :TickPrice
25
+ ib.send_message :CancelMarketData, id: the_id
26
+ # We received High, Low, (perhaps open and close, too), choose the maximum value for reference
27
+ # and clear the received-array for proper bookkeeping
28
+ last_price = ib.received[:TickPrice].price.map(&:to_f).max
29
+ ib.clear_received :TickPrice
30
+ # let the calling method decide how to use the price
31
+ # the calling method should return a valid order
32
+ order = yield(last_price.presence || 47)
33
+ # to finish, we place the order using the given contract and return the order_id
34
+ the_order_id = if modus == :place
35
+ ib.place_order order, contract
36
+ else
37
+ ib.modify_order order, contract
38
+ end
39
+ ib.wait_for :OpenOrder, 3
40
+ the_order_id # return value
41
+ end
42
+ end
43
+
44
+
45
+
46
+
47
+
48
+
49
+ require 'bundler/setup'
50
+ require 'ib-api'
51
+ require 'ib/symbols'
52
+ require 'ib/order-prototypes'
53
+
54
+ include OrderPlacement
55
+
56
+ # Only for Advisor accounts: you need to provide account_code such as DU666777
57
+ account_code = ARGV[0] || ''
58
+ puts "\n" * 3
59
+ puts "*" * 50
60
+ puts " We are going to place a BUY-order on Wells Fargo on the account #{account_code} "
61
+ puts ""
62
+ puts " The Order is placed by the Order-Prototye »Limit.order»"
63
+ puts " "
64
+ puts " The Order is left open after finishing this script. You have to cancel it manualy"
65
+ puts "*" * 50
66
+ puts "\n" * 3
67
+ #
68
+ # First, connect to IB TWS. Arbitrary :client_id is used to identify your script
69
+ ib = IB::Connection.new client_id: 1112 do | gw | #, :port => 7496 # TWS
70
+
71
+ # Subscribe to TWS alerts/errors and order-related messages prior to the connection of the client
72
+ gw.subscribe(:Alert, :ManagedAccounts, :OpenOrder, :OrderStatus, :ContractDataEnd ) { |msg| puts msg.to_human }
73
+ gw.subscribe(:ContractData ) do |msg|
74
+ puts msg.contract.to_human + "\n"
75
+ end
76
+ gw.logger.level = Logger::FATAL # DEBUG -- INFO -- WARN -- ERROR -- FATAL
77
+
78
+ end
79
+
80
+ buy_order = nil # placeholder for buy_order defined in the block
81
+ contract = IB::Symbols::Stocks.wfc
82
+ puts '*'*10 + ' Introduction '+ '*'*10
83
+ puts IB::Limit.summary
84
+ puts "\nSupported Parameter \n -------------------------- "
85
+ puts IB::Limit.parameters
86
+
87
+ buy_order = IB::Limit.order size: 100,
88
+ price: 0, # dummy, specified later
89
+ action: :buy,
90
+ account: account_code
91
+
92
+ the_initial_order_id = place_the_order( contract: contract ) do | asset_price |
93
+ buy_order.limit_price = ( asset_price -( asset_price * 0.1)).round
94
+ puts buy_order.to_human
95
+ buy_order # return_value
96
+ end
97
+
98
+
99
+ puts "going to modify the order "
100
+
101
+ puts "\n******** Press <Enter> to proceed... *********\n\n"
102
+ STDIN.gets
103
+
104
+ puts "changing price by 1$"
105
+
106
+ the_modified_order_id = place_the_order( contract: contract, modus: :modify ) do | asset_price |
107
+ buy_order.limit_price = ( asset_price - 1 - ( asset_price * 0.1)).round
108
+ puts buy_order.to_human
109
+ buy_order # return_value
110
+ end
111
+
112
+
113
+ ib.send_message :RequestAllOpenOrders
114
+
115
+
116
+ puts "\n******** Press <Enter> to cancel... *********\n\n"
117
+ STDIN.gets
118
+
119
+
120
+ ## RUN ONLY ON A DEMO ACCOUNT
121
+ #
122
+ #
123
+ # expected output
124
+ #
125
+ #12:13:05.096 Got message 15 (IB::Messages::Incoming::ManagedAccounts)
126
+ #12:13:05.097 No subscribers for message IB::Messages::Incoming::ManagedAccounts!
127
+ #12:13:05.137 Got message 9 (IB::Messages::Incoming::NextValidId)
128
+ #12:13:05.137 Got next valid order id: 1.
129
+ #------sendto ---------(debugging output in outgoing/abstract_message)
130
+ #["'9", "8", "56", "", "WFC", "STK", "", "0.0", "", "", "NYSE", "", "USD", "", "", "0", "", "", "\""]
131
+ #------sendto ---------
132
+ # A Limit order is an order to buy or sell at a specified price or better.
133
+ # The Limit order ensures that if the order fills, it will not fill at a price less favorable than
134
+ # your limit price, but it does not guarantee a fill.
135
+ # It appears in the orderbook.
136
+ #Supported Parameter
137
+ # --------------------------
138
+ #Required : action --> {"B"=>:buy, "S"=>:sell, "T"=>:short, "X"=>:short_exempt}
139
+ # : total_quantity --> also aliased as :size
140
+ # : limit_price --> decimal
141
+ # ---------------
142
+ #Optional : account --> Account(number) to trade on
143
+ # ---------------
144
+ #<Order: LMT GTC buy 100 1.13 New #/ from /DU167348>
145
+ #------sendto ---------(debugging output in outgoing/abstract_message)
146
+ #["\\xB03", "45", "1", "", "WFC", "STK", "", "0.0", "", "", "NYSE", "", "USD", "", "", "", "", "BUY", "100", "LMT", "1.13", "", "GTC", "", "DU167348", "O", "0", "", "1", "0", "0", "0", "0", "0", "0", "0", "", "0", "", "", "", "", "", "", "", "0", "", "-1", "0", "", "", "0", "", "", "1", "1", "", "0", "", "", "", "", "", "0", "", "", "", "", "0", "", "", "", "", "", "", "", "", "", "", "0", "", "", "0", "0", "", "", "0", "", "0", "0", "0", "0", "", "", "", "", "", "", "", "", "", "", "", "\""]
147
+ #------sendto ---------
148
+ #12:13:05.290 Got message 10 (IB::Messages::Incoming::ContractData)
149
+ #<Stock: WFC USD>
150
+ #12:13:05.291 Got message 52 (IB::Messages::Incoming::ContractDataEnd)
151
+ #<ContractDataEnd: request_id 56 >
152
+ #
153
+ #******** Press <Enter> to cancel... *********
154
+ #
155
+ #12:13:05.303 Got message 3 (IB::Messages::Incoming::OrderStatus)
156
+ #<OrderStatus: <OrderState: ApiPending #1/0 from 1112 filled 0.0/100.0 at 0.0/0.0>>
157
+ #12:13:05.304 Got message 53 (IB::Messages::Incoming::OpenOrderEnd)
158
+ #12:13:05.304 No subscribers for message IB::Messages::Incoming::OpenOrderEnd!
159
+ #12:13:05.712 Got message 5 (IB::Messages::Incoming::OpenOrder)
160
+ #<OpenOrder: <Stock: WFC USD> <Order: LMT GTC buy 100.0 1.13 Submitted #1/1562725191 from 1112/DU167348 fee 0.0>>
161
+ #12:13:05.714 Got message 3 (IB::Messages::Incoming::OrderStatus)
162
+ #<OrderStatus: <OrderState: Submitted #1/1562725191 from 1112 filled 0.0/100.0 at 0.0/0.0 why_held >>
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This script places WFC bracketed buy order.
4
+ # Two child orders are attached:
5
+ # STOP order
6
+ # LIMIT order (profit target)
7
+
8
+ require 'rubygems'
9
+ require 'bundler/setup'
10
+ require 'ib-api'
11
+ require 'ib/symbols'
12
+ require 'ib/order-prototypes'
13
+ # Only for Advisor accounts: you need to provide account_code such as U666777
14
+ account_code = ARGV[0] || ''
15
+ # First, connect to IB TWS. Arbitrary :client_id is used to identify your script
16
+ ib = IB::Connection.new :client_id => 1112 do | gw | #, :port => 7497 # TWS
17
+
18
+ # Subscribe to TWS alerts/errors and order-related messages
19
+ gw.subscribe(:Alert, :OpenOrder, :OrderStatus, :ManagedAccounts) { |msg| puts msg.to_human }
20
+ end
21
+
22
+ symbol = IB::Symbols::Stocks[:wfc]
23
+
24
+ order_price = 24
25
+ stop_price = order_price - 0.25
26
+ profit_price = order_price + 0.25
27
+
28
+ #-- Parent Order --
29
+ buy_order = IB::Limit.order :total_quantity => 100,
30
+ :price => order_price,
31
+ :action => :buy,
32
+ :algo_strategy => '',
33
+ :transmit => false,
34
+ account: account_code
35
+ ib.wait_for :NextValidId
36
+
37
+ #-- Child STOP --
38
+ stop_order = IB::SimpleStop.order :total_quantity => 100,
39
+ :price => stop_price,
40
+ :action => :sell,
41
+ :parent_id => buy_order.local_id,
42
+ account: account_code
43
+ #-- Profit LMT
44
+ profit_order = IB::Limit.order :total_quantity => 100,
45
+ :price => profit_price,
46
+ :action => :sell,
47
+ :parent_id => buy_order.local_id,
48
+ account: account_code
49
+
50
+ # place parent order
51
+ ib.place_order buy_order, symbol
52
+ stop_order.parent_id = buy_order.local_id
53
+ profit_order.parent_id = buy_order.local_id
54
+
55
+ # place child orders
56
+ ib.place_order stop_order, symbol
57
+ ib.place_order profit_order, symbol
58
+
59
+ ib.send_message :RequestAllOpenOrders
60
+
61
+ puts "\n******** Press <Enter> to cancel... *********\n\n"
62
+ STDIN.gets
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This script places GOOG option butterfly combo order
4
+
5
+ require 'rubygems'
6
+ require 'bundler/setup'
7
+ require 'ib-api'
8
+ require 'ib/verify'
9
+ require 'ib/market-price'
10
+ require 'ib/order-prototypes'
11
+
12
+ # Utility method that helps us build multi-legged (BAG) Orders
13
+ def butterfly symbol, expiry, right, *strikes
14
+
15
+ legs = strikes.zip([1, -2, 1]).map do |strike, weight|
16
+ # Create contract
17
+ the_leg = nil
18
+ IB::Option.new( :symbol => symbol,
19
+ :expiry => expiry,
20
+ :right => right,
21
+ :strike => strike).verify do | c |
22
+
23
+ # Create Comboleg from con_id and weight
24
+ the_leg = IB::ComboLeg.new :con_id => c.con_id, :weight => weight
25
+ end
26
+ the_leg # return_value
27
+ end
28
+ if legs.size < 3
29
+ puts "Could'nd initialize all legs"
30
+ nil # return nil
31
+ else
32
+ # Create and return new Combo contract
33
+ IB::Bag.new :symbol => symbol,
34
+ :currency => "USD", # Only US options in combo Contracts
35
+ :exchange => "SMART",
36
+ :combo_legs => legs
37
+ end
38
+ end
39
+
40
+ # Only for Advisor accounts: you need to provide account_code such as U666777
41
+ account_code = ARGV[0] || ''
42
+
43
+ #
44
+ # First, connect to IB TWS. Arbitrary :client_id is used to identify your script
45
+ ib = IB::Connection.new :client_id => 1112 do | gw | #, :port => 7497 # TWS
46
+
47
+ # Subscribe to TWS alerts/errors and order-related messages
48
+ gw.subscribe(:Alert, :OpenOrder, :OrderStatus, :ManagedAccounts) { |msg| puts msg.to_human }
49
+ end
50
+ ib.wait_for :NextValidId
51
+
52
+ # Create multi-legged option Combo using utility method above
53
+ combo = butterfly 'WMT', '20201218', 'CALL', 145, 150 , 155
54
+ unless combo.nil?
55
+ puts "MARKETPRICE: #{combo.market_price}"
56
+ # Create Order stub
57
+ order = IB::Limit.order total_quantity: 10, # 10 butterflies
58
+ limit_price: 0.06, # at 0.06 x 100 USD per contract
59
+ action: :buy,
60
+ account: account_code
61
+
62
+
63
+ ib.place_order order, combo
64
+
65
+ ib.wait_for [:OpenOrder, 3], [:OrderStatus, 2]
66
+
67
+ puts "\n******** Press <Enter> to cancel... *********\n\n"
68
+ STDIN.gets
69
+ end
70
+
71
+ ### Expected output
72
+
73
+ #./place_butterfly_order DU167349
74
+ #Connected to server, version: 137,
75
+ # connection time: 2020-09-03 05:13:24 +0000 local, 2020-09-03T05:13:24+00:00 remote.
76
+ #< ManagedAccounts: DF167347 - DU167348 - DU167349>
77
+ #Got next valid order id: 65.
78
+ #TWS Warning 2104: Market data farm connection is OK:eufarm
79
+ #TWS Warning 2104: Market data farm connection is OK:usopt
80
+ #TWS Warning 2104: Market data farm connection is OK:usfarm
81
+ #TWS Warning 2107: HMDS data farm connection is inactive but should be available upon demand.euhmds
82
+ #TWS Error 354: Requested market data is not subscribed.
83
+ #MARKETPRICE: []
84
+ #<OpenOrder: <Bag: WMT SMART USD legs: 418440165|1,418440170|-2,418440175|1 > <Order: LMT GTC buy 10.0 @ 0.06 PreSubmitted #65/1750019075 from 1112/DU167349>>
85
+ #<OrderState: PreSubmitted #65/1750019075 from 1112 filled 0.0/10.0 at 0.0/0.0 why_held locate>
86
+ #
87
+ #******** Press <Enter> to cancel... *********
88
+ #
89
+ #<OpenOrder: <Bag: WMT SMART USD legs: 418440165|1,418440170|-2,418440175|1 > <Order: LMT GTC buy 10.0 @ 0.06 Submitted #65/1750019075 from 1112/DU167349>>
90
+ #<OrderState: Submitted #65/1750019075 from 1112 filled 0.0/10.0 at 0.0/0.0 why_held >
91
+ #
92
+ #./cancel_orders
93
+ #< ManagedAccounts: DF167347 - DU167348 - DU167349>
94
+ #TWS Warning 2104: Market data farm connection is OK:eufarm
95
+ #TWS Warning 2104: Market data farm connection is OK:usopt
96
+ #TWS Warning 2104: Market data farm connection is OK:usfarm
97
+ #TWS Warning 2107: HMDS data farm connection is inactive but should be available upon demand.euhmds
98
+ #-------------------------------------------------------
99
+ #Remaining Orders
100
+ #-------------------------------------------------------
101
+ #<OpenOrder: <Bag: WMT SMART USD legs: 418440165|1,418440170|-2,418440175|1 > <Order: LMT GTC buy 10.0 @ 0.06 PendingCancel #65/1750019075 from 1112/DU167349>>
102
+ #<OrderState: PendingCancel #65/1750019075 from 1112 filled 0.0/10.0 at 0.0/0.0 why_held >
103
+ #<OpenOrderEnd: >
104
+ ##