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,67 @@
|
|
1
|
+
# These modules are used to facilitate referencing of most common Ordertypes
|
2
|
+
|
3
|
+
module IB
|
4
|
+
module OrderPrototype
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
def order **fields
|
10
|
+
|
11
|
+
# special treatment of size: positive numbers --> buy order, negative: sell
|
12
|
+
if fields[:size].present? && fields[:action].blank?
|
13
|
+
error "Size = 0 is not possible" if fields[:size].zero?
|
14
|
+
fields[:action] = fields[:size] >0 ? :buy : :sell
|
15
|
+
fields[:size] = fields[:size].abs
|
16
|
+
end
|
17
|
+
# change aliases to the original. We are modifying the fields-hash.
|
18
|
+
fields.keys.each{|x| fields[aliases.key(x)] = fields.delete(x) if aliases.has_value?(x)}
|
19
|
+
# inlcude defaults (arguments override defaults)
|
20
|
+
the_arguments = defaults.merge fields
|
21
|
+
# check if requirements are fullfilled
|
22
|
+
necessary = requirements.keys.detect{|y| the_arguments[y].nil?}
|
23
|
+
if necessary.present?
|
24
|
+
msg =self.name + ".order -> A necessary field is missing: #{necessary}: --> #{requirements[necessary]}"
|
25
|
+
error msg, :args, nil
|
26
|
+
end
|
27
|
+
if alternative_parameters.present?
|
28
|
+
unless ( alternative_parameters.keys & the_arguments.keys ).size == 1
|
29
|
+
msg =self.name + ".order -> One of the alternative fields needs to be specified: \n\t:" +
|
30
|
+
"#{alternative_parameters.map{|x| x.join ' => '}.join(" or \n\t:")}"
|
31
|
+
error msg, :args, nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# initialise order with given attributes
|
36
|
+
IB::Order.new the_arguments
|
37
|
+
end
|
38
|
+
|
39
|
+
def alternative_parameters
|
40
|
+
{}
|
41
|
+
end
|
42
|
+
def requirements
|
43
|
+
{ action: IB::VALUES[:side], total_quantity: 'also aliased as :size' }
|
44
|
+
end
|
45
|
+
|
46
|
+
def defaults
|
47
|
+
{ tif: :good_till_cancelled }
|
48
|
+
end
|
49
|
+
|
50
|
+
def optional
|
51
|
+
{ account: 'Account(number) to trade on' }
|
52
|
+
end
|
53
|
+
|
54
|
+
def aliases
|
55
|
+
{ total_quantity: :size }
|
56
|
+
end
|
57
|
+
|
58
|
+
def parameters
|
59
|
+
the_output = ->(var){ var.map{|x| x.join(" --> ") }.join("\n\t: ")}
|
60
|
+
|
61
|
+
"Required : " + the_output[requirements] + "\n --------------- \n" +
|
62
|
+
"Optional : " + the_output[optional] + "\n --------------- \n"
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module IB
|
2
|
+
|
3
|
+
#Combo-Orders are used for NonGuaranteed Orders only.
|
4
|
+
#»Normal« Option-Spreads are transmited by ordinary Limit-Orders
|
5
|
+
module Combo
|
6
|
+
### Basic Order Prototype: Combo with two limits
|
7
|
+
extend OrderPrototype
|
8
|
+
class << self
|
9
|
+
def defaults
|
10
|
+
## todo implement serialisation of key/tag Hash to camelCased-keyValue-List
|
11
|
+
# super.merge order_type: :limit , combo_params: { non_guaranteed: true}
|
12
|
+
# for the time being, we use the array representation
|
13
|
+
super.merge order_type: :limit , combo_params: [ ['NonGuaranteed', true] ]
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def requirements
|
18
|
+
Limit.requirements
|
19
|
+
end
|
20
|
+
|
21
|
+
def aliases
|
22
|
+
Limit.aliases
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def summary
|
27
|
+
<<-HERE
|
28
|
+
Create combination orders. It is constructed through options, stock and futures legs
|
29
|
+
(stock legs can be included if the order is routed through SmartRouting).
|
30
|
+
|
31
|
+
Although a combination/spread order is constructed of separate legs, it is executed
|
32
|
+
as a single transaction if it is routed directly to an exchange. For combination orders
|
33
|
+
that are SmartRouted, each leg may be executed separately to ensure best execution.
|
34
|
+
|
35
|
+
The »NonGuaranteed«-Flag is set to "false". A Pair of two securites should always be
|
36
|
+
routed »Guaranteed«, otherwise separate orders are prefered.
|
37
|
+
|
38
|
+
If a Bag-Order with »NonGuarateed :true« should be submitted, the Order-Type would be
|
39
|
+
REL+MKT, LMT+MKT, or REL+LMT
|
40
|
+
--------
|
41
|
+
Products: Options, Stocks, Futures
|
42
|
+
HERE
|
43
|
+
end # def
|
44
|
+
end # class
|
45
|
+
end # module combo
|
46
|
+
end # module ib
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module IB
|
2
|
+
# module UseOrder
|
3
|
+
module ForexLimit
|
4
|
+
extend OrderPrototype
|
5
|
+
class << self
|
6
|
+
|
7
|
+
|
8
|
+
def defaults
|
9
|
+
super.merge order_type: :limit , tif: :day
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def requirements
|
14
|
+
super.merge cash_qty: '(true/false) to indicate to let IB calculate the cash-quantity of the alternate currency'
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def summary
|
19
|
+
<<-HERE
|
20
|
+
Forex orders can be placed in denomination of second currency in pair using cashQty field.
|
21
|
+
Don't specify a limit-price to force immidiate execution.
|
22
|
+
HERE
|
23
|
+
end
|
24
|
+
end
|
25
|
+
=begin
|
26
|
+
2.5.0 :001 > f = Symbols::Forex[:eurusd]
|
27
|
+
=> #<IB::Contract:0x0000000003299458 @attributes={"symbol"=>"EUR", "exchange"=>"IDEALPRO", "currency"=>"USD", "sec_type"=>"CASH", "created_at"=>2018-01-20 05:21:01 +0100, "updated_at"=>2018-01-20 05:21:01 +0100, "con_id"=>0, "right"=>"", "include_expired"=>false}, @description="EURUSD">
|
28
|
+
|
29
|
+
2.5.0 :002 > uf = ForexLimit.order action: :buy, size: 15000, cash_qty: true
|
30
|
+
{:action=>:buy, :cash_qty=>true, :total_quantity=>15000}
|
31
|
+
=> #<IB::Order:0x0000000002f45a40 @attributes={"tif"=>"DAY", "order_type"=>"LMT", "side"=>"B", "cash_qty"=>true, "total_quantity"=>15000, "created_at"=>2018-01-20 05:21:06 +0100, "updated_at"=>2018-01-20 05:21:06 +0100, "active_start_time"=>"", "active_stop_time"=>"", "algo_strategy"=>"", "algo_id"=>"", "auction_strategy"=>0, "conditions"=>[], "continuous_update"=>0, "delta_neutral_designated_location"=>"", "delta_neutral_con_id"=>0, "delta_neutral_settling_firm"=>"", "delta_neutral_clearing_account"=>"", "delta_neutral_clearing_intent"=>"", "designated_location"=>"", "display_size"=>0, "discretionary_amount"=>0, "etrade_only"=>true, "exempt_code"=>-1, "ext_operator"=>"", "firm_quote_only"=>true, "not_held"=>false, "oca_type"=>0, "open_close"=>1, "opt_out_smart_routing"=>false, "origin"=>0, "outside_rth"=>false, "parent_id"=>0, "random_size"=>false, "random_price"=>false, "scale_auto_reset"=>false, "scale_random_percent"=>false, "scale_table"=>"", "short_sale_slot"=>0, "solicided"=>false, "transmit"=>true, "trigger_method"=>0, "what_if"=>false, "leg_prices"=>[], "algo_params"=>{}, "combo_params"=>[], "soft_dollar_tier_params"=>{"name"=>"", "val"=>"", "display_name"=>""}}, @order_states=[#<IB::OrderState:0x0000000002f44258 @attributes={"status"=>"New", "filled"=>0, "remaining"=>0, "price"=>0, "average_price"=>0, "created_at"=>2018-01-20 05:21:06 +0100, "updated_at"=>2018-01-20 05:21:06 +0100}>]>
|
32
|
+
2.5.0 :004 > C.place_order uf, f
|
33
|
+
=> 4
|
34
|
+
2.5.0 :005 > 05:21:23.606 Got message 4 (IB::Messages::Incoming::Alert)
|
35
|
+
I, [2018-01-20T05:21:23.606819 #31020] INFO -- : TWS Warning 10164: Traders are responsible for understanding cash quantity details, which are provided on a best efforts basis only.
|
36
|
+
Restriction is specified in Precautionary Settings of Global Configuration/Presets.
|
37
|
+
|
38
|
+
=end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
|
2
|
+
module IB
|
3
|
+
module Limit
|
4
|
+
extend OrderPrototype
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def defaults
|
8
|
+
super.merge order_type: :limit
|
9
|
+
end
|
10
|
+
|
11
|
+
def aliases
|
12
|
+
super.merge limit_price: :price
|
13
|
+
end
|
14
|
+
|
15
|
+
def requirements
|
16
|
+
super.merge limit_price: "also aliased as :price"
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def summary
|
21
|
+
<<-HERE
|
22
|
+
A Limit order is an order to buy or sell at a specified price or better.
|
23
|
+
The Limit order ensures that if the order fills, it will not fill at a price less favorable than
|
24
|
+
your limit price, but it does not guarantee a fill.
|
25
|
+
It appears in the orderbook.
|
26
|
+
HERE
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
module Discretionary
|
31
|
+
extend OrderPrototype
|
32
|
+
class << self
|
33
|
+
|
34
|
+
def defaults
|
35
|
+
Limit.defaults
|
36
|
+
end
|
37
|
+
|
38
|
+
def aliases
|
39
|
+
Limit.aliases.merge discretionary_amount: :dc
|
40
|
+
end
|
41
|
+
|
42
|
+
def requirements
|
43
|
+
Limit.requirements
|
44
|
+
end
|
45
|
+
|
46
|
+
def optional
|
47
|
+
super.merge discretionary_amount: :decimal
|
48
|
+
end
|
49
|
+
|
50
|
+
def summary
|
51
|
+
<<-HERE
|
52
|
+
A Discretionary order is a Limitorder submitted with a hidden,
|
53
|
+
specified 'discretionary' amount off the limit price which may be used
|
54
|
+
to increase the price range over which the limit order is eligible to execute.
|
55
|
+
The market sees only the limit price.
|
56
|
+
The discretionary amount adds to the given limit price. The main effort is
|
57
|
+
to hide your real intentions from the public.
|
58
|
+
HERE
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
# module OrderPrototype
|
63
|
+
module Sweep2Fill
|
64
|
+
extend OrderPrototype
|
65
|
+
class << self
|
66
|
+
|
67
|
+
def defaults
|
68
|
+
super.merge order_type: ':limit' , tif: :day, sweep_to_fill: true
|
69
|
+
end
|
70
|
+
|
71
|
+
def aliases
|
72
|
+
Limit.aliases
|
73
|
+
end
|
74
|
+
|
75
|
+
def requirements
|
76
|
+
Limit.requirements
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def summary
|
81
|
+
<<-HERE
|
82
|
+
Sweep-to-fill orders are useful when a trader values speed of execution over price. A sweep-to-fill
|
83
|
+
order identifies the best price and the exact quantity offered/available at that price, and
|
84
|
+
transmits the corresponding portion of your order for immediate execution. Simultaneously it
|
85
|
+
identifies the next best price and quantity offered/available, and submits the matching quantity
|
86
|
+
of your order for immediate execution.
|
87
|
+
|
88
|
+
------------------------
|
89
|
+
Products: CFD, STK, WAR (SMART only)
|
90
|
+
|
91
|
+
HERE
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
module LimitIfTouched
|
96
|
+
extend OrderPrototype
|
97
|
+
class << self
|
98
|
+
|
99
|
+
def defaults
|
100
|
+
Limit.defaults.merge order_type: :limit_if_touched
|
101
|
+
end
|
102
|
+
|
103
|
+
def aliases
|
104
|
+
Limit.aliases.merge aux_price: :trigger_price
|
105
|
+
end
|
106
|
+
|
107
|
+
def requirements
|
108
|
+
Limit.requirements.merge aux_price: 'also aliased as :trigger_price '
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def summary
|
113
|
+
<<-HERE
|
114
|
+
A Limit if Touched is an order to buy (or sell) a contract at a specified price or better,
|
115
|
+
below (or above) the market. This order is held in the system until the trigger price is touched.
|
116
|
+
An LIT order is similar to a stop limit order, except that an LIT sell order is placed above
|
117
|
+
the current market price, and a stop limit sell order is placed below.
|
118
|
+
HERE
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
module LimitOnClose
|
125
|
+
extend OrderPrototype
|
126
|
+
class << self
|
127
|
+
|
128
|
+
def defaults
|
129
|
+
Limit.defaults.merge order_type: :limit_on_close
|
130
|
+
end
|
131
|
+
|
132
|
+
def aliases
|
133
|
+
Limit.aliases
|
134
|
+
end
|
135
|
+
|
136
|
+
def requirements
|
137
|
+
Limit.requirements
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
def summary
|
142
|
+
<<-HERE
|
143
|
+
A Limit-on-close (LOC) order will be submitted at the close and will execute if the
|
144
|
+
closing price is at or better than the submitted limit price.
|
145
|
+
HERE
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
module LimitOnOpen
|
151
|
+
extend OrderPrototype
|
152
|
+
class << self
|
153
|
+
|
154
|
+
def defaults
|
155
|
+
super.merge order_type: :limit_on_open , tif: :opening_price
|
156
|
+
end
|
157
|
+
|
158
|
+
def aliases
|
159
|
+
Limit.aliases
|
160
|
+
end
|
161
|
+
|
162
|
+
def requirements
|
163
|
+
Limit.requirements
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
def summary
|
168
|
+
<<-HERE
|
169
|
+
A Limit-on-Open (LOO) order combines a limit order with the OPG time in force to create an
|
170
|
+
order that is submitted at the market's open, and that will only execute at the specified
|
171
|
+
limit price or better. Orders are filled in accordance with specific exchange rules.
|
172
|
+
HERE
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
# end
|
177
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
|
2
|
+
module IB
|
3
|
+
# module OrderPrototype
|
4
|
+
module Market
|
5
|
+
extend OrderPrototype
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def defaults
|
9
|
+
super.merge order_type: 'MKT' , tif: :day
|
10
|
+
end
|
11
|
+
|
12
|
+
def aliases
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def requirements
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def summary
|
22
|
+
<<-HERE
|
23
|
+
A Market order is an order to buy or sell at the market bid or offer price.
|
24
|
+
A market order may increase the likelihood of a fill and the speed of execution,
|
25
|
+
but unlike the Limit order a Market order provides no price protection and
|
26
|
+
may fill at a price far lower/higher than the current displayed bid/ask.
|
27
|
+
HERE
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
module MarketIfTouched
|
32
|
+
extend OrderPrototype
|
33
|
+
class << self
|
34
|
+
|
35
|
+
def defaults
|
36
|
+
super.merge order_type: 'MIT' , tif: :day
|
37
|
+
end
|
38
|
+
|
39
|
+
def aliases
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def requirements
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def summary
|
49
|
+
<<-HERE
|
50
|
+
A Market if Touched (MIT) is an order to buy (or sell) a contract below (or above) the market.
|
51
|
+
Its purpose is to take advantage of sudden or unexpected changes in share or other prices and
|
52
|
+
rovides investors with a trigger price to set an order in motion.
|
53
|
+
Investors may be waiting for excessive strength (or weakness) to cease, which might be represented
|
54
|
+
by a specific price point.
|
55
|
+
MIT orders can be used to determine whether or not to enter the market once a specific price level
|
56
|
+
has been achieved. This order is held in the system until the trigger price is touched, and
|
57
|
+
is then submitted as a market order. An MIT order is similar to a stop order, except that an MIT
|
58
|
+
sell order is placed above the current market price, and a stop sell order is placed below.
|
59
|
+
HERE
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
module MarketOnClose
|
66
|
+
extend OrderPrototype
|
67
|
+
class << self
|
68
|
+
|
69
|
+
def defaults
|
70
|
+
super.merge order_type: 'MOC' , tif: :day
|
71
|
+
end
|
72
|
+
|
73
|
+
def aliases
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
def requirements
|
78
|
+
super
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def summary
|
83
|
+
<<-HERE
|
84
|
+
A Market-on-Close (MOC) order is a market order that is submitted to execute as close
|
85
|
+
to the closing price as possible.
|
86
|
+
HERE
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module MarketOnOpen
|
92
|
+
extend OrderPrototype
|
93
|
+
class << self
|
94
|
+
|
95
|
+
def defaults
|
96
|
+
super.merge order_type: 'MOC' , tif: :opening_price
|
97
|
+
end
|
98
|
+
|
99
|
+
def aliases
|
100
|
+
super
|
101
|
+
end
|
102
|
+
|
103
|
+
def requirements
|
104
|
+
super
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def summary
|
109
|
+
<<-HERE
|
110
|
+
A Market-on-Close (MOC) order is a market order that is submitted to execute as close
|
111
|
+
to the closing price as possible.
|
112
|
+
HERE
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|