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