ib-extensions 1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ #