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