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,70 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # =============================
4
+ # DO ONLY RUN ON A DEMO ACCOUNT
5
+ #
6
+ # This script places a combo order: Buy Microsoft, sell WellsFarge
7
+ #
8
+ # The first Account (IB::Gateway.clients.first) is used.
9
+ #
10
+ #
11
+ # DO ONLY RUN ON A DEMO ACCOUNT
12
+ # =============================
13
+ #
14
+ require 'bundler/setup'
15
+ require 'ib-gateway'
16
+ require 'ib/order-prototypes'
17
+ require 'ib/spread-prototypes'
18
+ require 'ib/market-price'
19
+
20
+
21
+ #
22
+ # First, connect to IB TWS. Arbitrary :client_id is used to identify your script
23
+ g = IB::Gateway.new :client_id => 1112 do | gw | #, :port => 7497 # TWS
24
+
25
+ # Subscribe to TWS alerts/errors and order-related messages
26
+ gw.tws.subscribe(:Alert, :OpenOrder, :OrderStatus) { |msg| puts msg.to_human }
27
+ end
28
+
29
+ # if tws/gateway is ready
30
+ g.tws.wait_for :NextValidId
31
+
32
+ # create the bag
33
+ # only US-Stocks are allowed by IB
34
+ the_bag = IB::StockSpread.fabricate 'MSFT', 'WFC', ratio: [1, -8]
35
+
36
+ puts "Market price for Microsoft/WellsFargo Combo: #{the_market_price = the_bag.market_price}"
37
+
38
+ if the_market_price.nil?
39
+ puts "No marketdata received, using default (10 $) "
40
+ the_market_price = 14
41
+ end
42
+ # use the order-prototype to create the order
43
+ order = IB::Combo.order total_quantity: 10,
44
+ limit_price: the_market_price,
45
+ action: :buy
46
+
47
+ # calculate margin impact
48
+ impact= g.clients.first.preview order: order, contract: the_bag
49
+
50
+ puts "Preview:: Margin Impact"
51
+ puts impact #map{ |x,y| "#{ x }: #{ y.blank? ? '---' ? y.to_f }" unless x == :created_at }.join("; ")
52
+
53
+
54
+
55
+ # and place
56
+ if g.clients.first.test_environment?
57
+ local_id = g.clients.first.place_order order: order
58
+
59
+ g.tws.wait_for [:OpenOrder, 3], [:OrderStatus, 2]
60
+
61
+ else
62
+ puts "Order not placed. #{G.clients.first.to_human} is not a demo account"
63
+ end
64
+ #puts "\n******** Press <Enter> to cancel... *********\n\n"
65
+ #STDIN.gets
66
+
67
+ =begin
68
+ Expected output
69
+
70
+ =end
@@ -0,0 +1,82 @@
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
+ require 'bundler/setup'
7
+ require 'ib-api'
8
+ require 'ib/order-prototypes'
9
+
10
+ # you need to provide account_code such as DU666777
11
+ account_code = ARGV[0] || ''
12
+ #
13
+ # First, connect to IB TWS. Arbitrary :client_id is used to identify your script
14
+ ib = IB::Connection.new client_id: 1112 do | gw | #, :port => 7496 # TWS
15
+
16
+ # Subscribe to TWS alerts/errors and order-related messages prior to the connection of the client
17
+ gw.subscribe(:Alert, :OpenOrder, :OrderStatus, :ManagedAccounts, :OpenOrderEnd ) { |msg| puts "recieved: #{msg.to_human }"}
18
+
19
+ end
20
+
21
+ puts "-" * 80
22
+ wfc = IB::Stock.new symbol: 'WFC'
23
+
24
+ puts IB::Limit.summary
25
+ puts "Supported Parameter "
26
+ puts "-" * 80
27
+ puts IB::Limit.parameters
28
+ buy_order = IB::Limit.order size: 100,
29
+ price: 1 + rand().round(2),
30
+ action: :buy,
31
+ account: account_code
32
+ puts "placing #{buy_order.to_human} "
33
+ ib.wait_for :NextValidId
34
+ ib.place_order buy_order, wfc
35
+
36
+ puts "requesting all open orders "
37
+ ib.send_message :RequestAllOpenOrders
38
+ ib.wait_for :OpenOrderEnd, 5 #sec
39
+
40
+ puts "\n******** Press <Enter> to cancel... *********\n\n"
41
+ STDIN.gets
42
+
43
+ ## RUN ONLY ON A DEMO ACCOUNT
44
+ #
45
+ #
46
+ # expected output
47
+ =begin
48
+ ./place_limit_order DU167349
49
+ Connected to server, version: 137,
50
+ connection time: 2020-09-03 05:21:47 +0000 local, 2020-09-03T05:21:47+00:00 remote.
51
+ < ManagedAccounts: DF167347 - DU167348 - DU167349>
52
+ Got next valid order id: 68.
53
+ TWS Warning 2104: Market data farm connection is OK:eufarm
54
+ TWS Warning 2104: Market data farm connection is OK:usopt
55
+ TWS Warning 2104: Market data farm connection is OK:usfarm
56
+ TWS Warning 2107: HMDS data farm connection is inactive but should be available upon demand.euhmds
57
+ A Limit order is an order to buy or sell at a specified price or better.
58
+ The Limit order ensures that if the order fills, it will not fill at a price less favorable than
59
+ your limit price, but it does not guarantee a fill.
60
+ It appears in the orderbook.
61
+ Supported Parameter
62
+ --------------------------
63
+ Required : action --> {"B"=>:buy, "S"=>:sell, "T"=>:short, "X"=>:short_exempt}
64
+ : total_quantity --> also aliased as :size
65
+ : limit_price --> also aliased as :price
66
+ ---------------
67
+ Optional : account --> Account(number) to trade on
68
+ ---------------
69
+ <Order: LMT GTC buy 100 @ 1.43 New #/ from /DU167349>
70
+ <Stock: WFC USD NYSE>
71
+ <ContractDataEnd: request_id 56 >
72
+
73
+ ******** Press <Enter> to cancel... *********
74
+
75
+ <OpenOrder: <Stock: WFC USD> <Order: LMT GTC buy 100.0 @ 1.45 PreSubmitted #67/1750019077 from 1112/DU167349>>
76
+ <OrderState: PreSubmitted #67/1750019077 from 1112 filled 0.0/100.0 at 0.0/0.0 why_held locate>
77
+ <OrderState: ApiPending #68/0 from 1112 filled 0.0/100.0>
78
+ No subscribers for message IB::Messages::Incoming::OpenOrderEnd!
79
+ <OpenOrder: <Stock: WFC USD> <Order: LMT GTC buy 100.0 @ 1.43 PreSubmitted #68/1750019078 from 1112/DU167349>>
80
+ <OrderState: PreSubmitted #68/1750019078 from 1112 filled 0.0/100.0 at 0.0/0.0 why_held locate>
81
+
82
+ =end
@@ -0,0 +1,145 @@
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
+ # always place the order, if there is no reference to an existing one: local_id nust not be nil, 0 or ""
35
+ the_order_id = if modus == :place || order.local_id.to_i.zero?
36
+ ib.place_order order, contract
37
+ else
38
+ ib.modify_order order, contract
39
+ end
40
+ ib.wait_for :OpenOrder, 3
41
+ the_order_id # return value
42
+ end
43
+ end
44
+
45
+
46
+
47
+
48
+
49
+
50
+ require 'bundler/setup'
51
+ require 'ib-ruby'
52
+ include OrderPlacement
53
+
54
+ # Only for Advisor accounts: you need to provide account_code such as U666777
55
+ account_code = ARGV[0] || ''
56
+ #
57
+ # First, connect to IB TWS. Arbitrary :client_id is used to identify your script
58
+ ib = IB::Connection.new client_id: 1112 do | gw | #, :port => 7496 # TWS
59
+
60
+ # Subscribe to TWS alerts/errors and order-related messages prior to the connection of the client
61
+ gw.subscribe(:Alert, :OpenOrder, :OrderStatus, :ContractDataEnd ) { |msg| puts msg.to_human }
62
+ gw.subscribe(:ContractData ) do |msg|
63
+ puts msg.contract.to_human + "\n"
64
+ end
65
+
66
+ end
67
+
68
+ buy_order = nil # placeholder for buy_order defined in the block
69
+ contract = IB::Symbols::Stocks.wfc
70
+ puts '*'*10 + ' Introduction '+ '*'*10
71
+ puts IB::Limit.summary
72
+ puts "\nSupported Parameter \n -------------------------- "
73
+ puts IB::Limit.parameters
74
+
75
+ buy_order = IB::Limit.order size: 100,
76
+ price: 0, # dummy, specified later
77
+ action: :buy,
78
+ account: account_code
79
+
80
+ the_initial_order_id = place_the_order( contract: contract ) do | asset_price |
81
+ buy_order.limit_price = ( asset_price -( asset_price * 0.1)).round
82
+ puts buy_order.to_human
83
+ buy_order # return_value
84
+ end
85
+
86
+
87
+ puts "going to modify the order "
88
+ puts "changing price by 1$"
89
+
90
+ the_modified_order_id = place_the_order( contract: contract, modus: :modify ) do | asset_price |
91
+ buy_order.limit_price = ( asset_price - 1 - ( asset_price * 0.1)).round
92
+ puts buy_order.to_human
93
+ buy_order # return_value
94
+ end
95
+
96
+
97
+ ib.send_message :RequestAllOpenOrders
98
+
99
+
100
+ puts "\n******** Press <Enter> to cancel... *********\n\n"
101
+ STDIN.gets
102
+
103
+
104
+ ## RUN ONLY ON A DEMO ACCOUNT
105
+ #
106
+ # expected output
107
+ #
108
+ #12:13:05.096 Got message 15 (IB::Messages::Incoming::ManagedAccounts)
109
+ #12:13:05.097 No subscribers for message IB::Messages::Incoming::ManagedAccounts!
110
+ #12:13:05.137 Got message 9 (IB::Messages::Incoming::NextValidId)
111
+ #12:13:05.137 Got next valid order id: 1.
112
+ #------sendto ---------(debugging output in outgoing/abstract_message)
113
+ #["'9", "8", "56", "", "WFC", "STK", "", "0.0", "", "", "NYSE", "", "USD", "", "", "0", "", "", "\""]
114
+ #------sendto ---------
115
+ # A Limit order is an order to buy or sell at a specified price or better.
116
+ # The Limit order ensures that if the order fills, it will not fill at a price less favorable than
117
+ # your limit price, but it does not guarantee a fill.
118
+ # It appears in the orderbook.
119
+ #Supported Parameter
120
+ # --------------------------
121
+ #Required : action --> {"B"=>:buy, "S"=>:sell, "T"=>:short, "X"=>:short_exempt}
122
+ # : total_quantity --> also aliased as :size
123
+ # : limit_price --> decimal
124
+ # ---------------
125
+ #Optional : account --> Account(number) to trade on
126
+ # ---------------
127
+ #<Order: LMT GTC buy 100 1.13 New #/ from /DU167348>
128
+ #------sendto ---------(debugging output in outgoing/abstract_message)
129
+ #["\\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", "", "", "", "", "", "", "", "", "", "", "", "\""]
130
+ #------sendto ---------
131
+ #12:13:05.290 Got message 10 (IB::Messages::Incoming::ContractData)
132
+ #<Stock: WFC USD>
133
+ #12:13:05.291 Got message 52 (IB::Messages::Incoming::ContractDataEnd)
134
+ #<ContractDataEnd: request_id 56 >
135
+ #
136
+ #******** Press <Enter> to cancel... *********
137
+ #
138
+ #12:13:05.303 Got message 3 (IB::Messages::Incoming::OrderStatus)
139
+ #<OrderStatus: <OrderState: ApiPending #1/0 from 1112 filled 0.0/100.0 at 0.0/0.0>>
140
+ #12:13:05.304 Got message 53 (IB::Messages::Incoming::OpenOrderEnd)
141
+ #12:13:05.304 No subscribers for message IB::Messages::Incoming::OpenOrderEnd!
142
+ #12:13:05.712 Got message 5 (IB::Messages::Incoming::OpenOrder)
143
+ #<OpenOrder: <Stock: WFC USD> <Order: LMT GTC buy 100.0 1.13 Submitted #1/1562725191 from 1112/DU167348 fee 0.0>>
144
+ #12:13:05.714 Got message 3 (IB::Messages::Incoming::OrderStatus)
145
+ #<OrderStatus: <OrderState: Submitted #1/1562725191 from 1112 filled 0.0/100.0 at 0.0/0.0 why_held >>
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'ib-api'
5
+ require 'ib/symbols'
6
+ require 'ib/verify'
7
+
8
+ =begin
9
+ Discover properties of Options
10
+
11
+ IB provides two calculations: :RequestOptionPrice and :RequestImpliedVolatility
12
+
13
+ ib.send_message :RequestOptionPrice
14
+ -----------------------------------
15
+ Given a valid option-contract, a fair option-price is calculated using appropiate
16
+ Underlying-price (:under_price) and :volatility-input-values
17
+
18
+ In addition, the »greeks« and the incorporated dividend are provided by the tws
19
+
20
+ ib.send_message :RequestImpliedVolatility
21
+ -----------------------------------------
22
+ Instead of :volatility, the :option_price is used as input.
23
+
24
+ Both requests are answered by a :TickOption-Message and are thus easily displayed by
25
+ (in console)
26
+ C.send_message :RequestImpliedVolatility, contract: IB::Symbols::Options.aapl200, under_price: 180, option_price: 11.3
27
+ => 8673 # returns the ticker_id
28
+ C.received[:TickOption].to_human
29
+ => ["<TickOption cust_option_computation for ticker_id: underlying @ 180.0, option @ 11.3, IV 0.16260792724594816%, delta -2.0, gamma -2.0, vega -2.0, theta -2.0, pv_dividend -1.0>"]
30
+ ...(greeks: -2.0 indicates, that IB has not jet calculated anything, but the IV is there )
31
+
32
+ =end
33
+
34
+
35
+ # First, connect to IB TWS and subscribe for events.
36
+ # The output is produced »on the fly« if the tws-response is detected
37
+ # The output is unsorted!
38
+ #
39
+ #ib = IB::Connection.new( :client_id => 1102, port: 7496, host: '10.222.148.177' ) do | gw |
40
+ ib = IB::Connection.new( :client_id => 1112 )do | gw | #, :port => 7497 # TWS
41
+
42
+ # Subscribe to TWS alerts/errors
43
+ gw.subscribe(:Alert, :ManagedAccounts ) { |msg| puts msg.to_human }
44
+
45
+ # the Output
46
+ gw.subscribe( :TickOption ) do |msg|
47
+ print " %3d %% ---> %6.3f " % [msg.ticker_id.to_i, msg.option_price]
48
+ puts " || " + "%7.6f %6.3f %6.3f %6.3f" % [ msg.gamma, msg.delta, msg.theta || -1, msg.vega ]
49
+ end
50
+ # Set log level
51
+ gw.logger.level = Logger::ERROR # DEBUG -- INFO -- WARN -- ERROR -- FATAL
52
+ end
53
+
54
+ # We use OptionPriceCalculations provided by IB
55
+ # specify the Option
56
+ the_option = IB::Symbols::Options.aapl.merge( strike: 120 ).verify.first
57
+
58
+ # specify the desired Volatility-Range
59
+ vola_range = ( 10 .. 50 ) # in % p.a.
60
+
61
+ # Specify the hypothetical price of the underlying
62
+
63
+ underlying_price = 100
64
+
65
+ puts "BASE: #{the_option.to_human}"
66
+ puts "Hypothetical price of the underlying: #{underlying_price}"
67
+ puts
68
+ puts " We simulate the rise of volatility"
69
+ puts '-'*66
70
+ puts "Vola ---> Option-Price || Gamma Delta Theta Vega "
71
+ puts '-'*66
72
+ # get the prices and store in recieved-array
73
+ vola_range.each do | the_vola |
74
+ req_id = ib.send_message :RequestOptionPrice,
75
+ id: the_vola,
76
+ contract: the_option,
77
+ volatility: the_vola.to_f/100,
78
+ under_price: underlying_price
79
+ ib.wait_for :TickOption, 1
80
+
81
+ ib.send_message :CancelOptionPrice, id: req_id
82
+ end
83
+ sleep 2
84
+ puts "Thats it, folks"
85
+
86
+
87
+ =begin
88
+ Expected Output
89
+
90
+ BASE: <Option: AAPL 20201218 call 120.0 SMART USD>
91
+ Hypothetical price of the underlying: 100
92
+ (the date: Oct. 26th)
93
+ We simulate the rise of volatility
94
+ ------------------------------------------------------------------
95
+ Vola ---> Option-Price || Gamma Delta Theta Vega
96
+ ------------------------------------------------------------------
97
+ 10 % ---> 0.000 || 0.000001 0.000 -1.000 0.000
98
+ 16 % ---> 0.002 || 0.000664 0.001 -1.000 0.002
99
+ 17 % ---> 0.004 || 0.001086 0.002 -1.000 0.004
100
+ 18 % ---> 0.008 || 0.001625 0.004 -1.000 0.005
101
+ 19 % ---> 0.013 || 0.002237 0.006 -1.000 0.007
102
+ 20 % ---> 0.020 || 0.002921 0.008 -1.000 0.011
103
+ 21 % ---> 0.031 || 0.003728 0.011 -1.000 0.012
104
+ 22 % ---> 0.042 || 0.004450 0.015 -1.000 0.018
105
+ 23 % ---> 0.060 || 0.005344 0.019 -1.000 0.018
106
+ 24 % ---> 0.078 || 0.006098 0.023 -1.000 0.025
107
+ 25 % ---> 0.102 || 0.006935 0.029 -1.000 0.027
108
+ 26 % ---> 0.129 || 0.007706 0.034 -1.000 0.027
109
+ 27 % ---> 0.157 || 0.008352 0.039 -1.000 0.039
110
+ 28 % ---> 0.196 || 0.009119 0.046 -1.000 0.039
111
+ 29 % ---> 0.235 || 0.009763 0.053 -1.000 0.039
112
+ 30 % ---> 0.274 || 0.010301 0.058 -1.000 0.049
113
+ 31 % ---> 0.322 || 0.010860 0.065 -1.000 0.054
114
+ 32 % ---> 0.376 || 0.011385 0.073 -1.000 0.054
115
+ 33 % ---> 0.430 || 0.011827 0.079 -1.000 0.054
116
+ 34 % ---> 0.483 || 0.012198 0.086 -1.000 0.059
117
+ 35 % ---> 0.543 || 0.012538 0.092 -1.000 0.071
118
+ 36 % ---> 0.614 || 0.012883 0.100 -1.000 0.071
119
+ 37 % ---> 0.685 || 0.013173 0.107 -1.000 0.071
120
+ 38 % ---> 0.756 || 0.013415 0.114 -1.000 0.071
121
+ 39 % ---> 0.827 || 0.013614 0.121 -1.000 0.071
122
+ 40 % ---> 0.898 || 0.013777 0.127 -1.000 0.082
123
+ 41 % ---> 0.980 || 0.013927 0.133 -1.000 0.090
124
+ 42 % ---> 1.070 || 0.014062 0.141 -1.000 0.090
125
+ 43 % ---> 1.161 || 0.014169 0.148 -1.000 0.090
126
+ 44 % ---> 1.251 || 0.014252 0.154 -1.000 0.090
127
+ 45 % ---> 1.342 || 0.014314 0.160 -1.000 0.090
128
+ 46 % ---> 1.432 || 0.014356 0.166 -1.000 0.090
129
+ 47 % ---> 1.522 || 0.014382 0.172 -1.000 0.090
130
+ 48 % ---> 1.613 || 0.014393 0.178 -1.000 0.099
131
+ 49 % ---> 1.712 || 0.014390 0.184 -1.000 0.110
132
+ 50 % ---> 1.822 || 0.014376 0.190 -1.000 0.110
133
+ 11 % ---> 0.000 || 0.000004 0.000 -1.000 0.000
134
+ 12 % ---> 0.000 || 0.000021 0.000 -1.000 0.000
135
+ 13 % ---> 0.000 || 0.000071 0.000 -1.000 0.000
136
+ 14 % ---> 0.000 || 0.000178 0.000 -1.000 0.001
137
+ 15 % ---> 0.001 || 0.000367 0.001 -1.000 0.001
138
+ Thats it, folks
139
+ =end
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ ## This script places WFC buy what-if order for 100 lots
4
+ ## and estimates commision, margin requirements and verifies that its executable.
5
+ ## It does not place the order for execution.
6
+ #
7
+ require 'bundler/setup'
8
+ require 'ib-api'
9
+ require 'ib/order-prototypes'
10
+
11
+ # you need to provide account_code such as U666777
12
+ account_code = ARGV[0] || ''
13
+ #
14
+ # First, connect to IB TWS. Arbitrary :client_id is used to identify your script
15
+ ib = IB::Connection.new client_id: 1112 do | gw | #, :port => 7496 # TWS
16
+
17
+ # Subscribe to TWS alerts/errors and order-related messages prior to the connection of the client
18
+ gw.subscribe(:Alert, :OpenOrder, :OrderStatus, :ManagedAccounts, :OpenOrderEnd ) { |msg| puts "recieved: #{msg.to_human }" }
19
+
20
+ end
21
+ wfc = IB::Stock.new symbol: 'WFC'
22
+
23
+ puts "-" * 80
24
+ puts IB::Limit.summary
25
+ puts "Supported Parameter"
26
+ puts "-" * 80
27
+ puts IB::Limit.parameters
28
+ buy_order = IB::Limit.order size: 100,
29
+ price: 1 + rand().round(2),
30
+ action: :buy,
31
+ what_if: true,
32
+ account: account_code
33
+ puts "placing #{buy_order.to_human}"
34
+ ib.wait_for :NextValidId
35
+ ib.place_order buy_order, wfc
36
+ ib.wait_for :OpenOrder, 5 #sec
37
+
38
+ puts "Got OpenOrder message"
39
+ #ib.send_message :RequestAllOpenOrders
40
+
41
+
42
+ #puts ib.received[:OpenOrder].last.order.inspect
43
+
44
+ recieved_order = ib.received[:OpenOrder].last.order
45
+ recieved_status = recieved_order.order_states.last
46
+ #puts recieved_status.to_human
47
+ puts ""
48
+ puts '*' * 80
49
+ puts "Summary for a placement of #{buy_order.total_quantity} shares of #{wfc.to_human} on #{account_code}"
50
+ puts '_' * 80
51
+ puts ""
52
+ puts "Available Cash (equity with loan) \t #{recieved_status[:equity_with_loan].to_f}"
53
+ puts "Margin usage after placement \t (init) #{recieved_status[:init_margin].to_f} \t (maint.) #{recieved_status[:maint_margin].to_f} "
54
+ puts "Commissions \t \t \t (min) #{recieved_status[:min_commission].to_f} \t\t (max) #{recieved_status[:max_commission].to_f} "
55
+
56
+ puts ""
57
+ puts '*' * 80
58
+ #### Expected Output
59
+ #
60
+ #Connected to server, version: 137,
61
+ # connection time: 2020-10-16 05:07:08 +0000 local, 2020-10-16T05:07:07+00:00 remote.
62
+ #recieved: < ManagedAccounts: DF167347 - DU167348 - DU167349>
63
+ #Got next valid order id: 104.
64
+ #--------------------------------------------------------------------------------
65
+ # A Limit order is an order to buy or sell at a specified price or better.
66
+ # The Limit order ensures that if the order fills, it will not fill at a price less favorable than
67
+ # your limit price, but it does not guarantee a fill.
68
+ # It appears in the orderbook.
69
+ #Supported Parameter
70
+ #--------------------------------------------------------------------------------
71
+ #Required : action --> {"B"=>:buy, "S"=>:sell, "T"=>:short, "X"=>:short_exempt}
72
+ # : total_quantity --> also aliased as :size
73
+ # : limit_price --> also aliased as :price
74
+ # ---------------
75
+ #Optional : account --> Account(number) to trade on
76
+ # ---------------
77
+ #placing <Order: LMT GTC buy 100 @ 1.0 New #/ from /DU167349>
78
+ #recieved: <OpenOrder: <Stock: WFC USD> <Order: LMT GTC buy 100.0 @ 1.0 PreSubmitted #104/988357646 from 0/DU167349>>
79
+ #Got OpenOrderEnd message
80
+ #
81
+ #********************************************************************************
82
+ #Summary for a placement of 100 shares of <Stock: WFC USD> on DU167349
83
+ #________________________________________________________________________________
84
+ #
85
+ #Available Cash (equity with loan) 891888.27
86
+ #Margin requirements (init) 53170.9 (maint.) 50222.84
87
+ #Commissions (min) 0.9 (max) 1.0
88
+ #
89
+ #********************************************************************************
90
+ #