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,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
|
+
#
|