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