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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +112 -0
- data/Guardfile +24 -0
- data/README.md +99 -0
- data/Rakefile +6 -0
- data/bin/console +96 -0
- data/bin/console.yml +3 -0
- data/bin/gateway.rb +97 -0
- data/bin/setup +8 -0
- data/changelog.md +31 -0
- data/examples/cancel_orders +74 -0
- data/examples/eod +35 -0
- data/examples/input.rb +475 -0
- data/examples/market_price +57 -0
- data/examples/option_chain +67 -0
- data/examples/place_and_modify_order +162 -0
- data/examples/place_bracket_order +62 -0
- data/examples/place_butterfly_order +104 -0
- data/examples/place_combo_order +70 -0
- data/examples/place_limit_order +82 -0
- data/examples/place_the_limit_order +145 -0
- data/examples/volatility_research +139 -0
- data/examples/what_if_order +90 -0
- data/ib-extensions.gemspec +37 -0
- data/lib/ib-gateway.rb +5 -0
- data/lib/ib/alerts/base-alert.rb +128 -0
- data/lib/ib/alerts/gateway-alerts.rb +15 -0
- data/lib/ib/alerts/order-alerts.rb +68 -0
- data/lib/ib/eod.rb +152 -0
- data/lib/ib/extensions.rb +9 -0
- data/lib/ib/extensions/contract.rb +37 -0
- data/lib/ib/extensions/version.rb +5 -0
- data/lib/ib/flex.rb +150 -0
- data/lib/ib/gateway.rb +425 -0
- data/lib/ib/gateway/account-infos.rb +115 -0
- data/lib/ib/gateway/order-handling.rb +150 -0
- data/lib/ib/market-price.rb +134 -0
- data/lib/ib/models/account.rb +329 -0
- data/lib/ib/models/spread.rb +159 -0
- data/lib/ib/option-chain.rb +198 -0
- data/lib/ib/option-greeks.rb +88 -0
- data/lib/ib/order-prototypes.rb +110 -0
- data/lib/ib/order_prototypes/abstract.rb +67 -0
- data/lib/ib/order_prototypes/combo.rb +46 -0
- data/lib/ib/order_prototypes/forex.rb +40 -0
- data/lib/ib/order_prototypes/limit.rb +177 -0
- data/lib/ib/order_prototypes/market.rb +116 -0
- data/lib/ib/order_prototypes/pegged.rb +173 -0
- data/lib/ib/order_prototypes/premarket.rb +31 -0
- data/lib/ib/order_prototypes/stop.rb +202 -0
- data/lib/ib/order_prototypes/volatility.rb +39 -0
- data/lib/ib/spread-prototypes.rb +62 -0
- data/lib/ib/spread_prototypes/butterfly.rb +79 -0
- data/lib/ib/spread_prototypes/calendar.rb +85 -0
- data/lib/ib/spread_prototypes/stock-spread.rb +48 -0
- data/lib/ib/spread_prototypes/straddle.rb +75 -0
- data/lib/ib/spread_prototypes/strangle.rb +96 -0
- data/lib/ib/spread_prototypes/vertical.rb +84 -0
- data/lib/ib/verify.rb +226 -0
- 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
|
+
##
|