ib-api 10.33.1
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 +52 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CLAUDE.md +131 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +120 -0
- data/Guardfile +24 -0
- data/LICENSE +674 -0
- data/LLM_GUIDE.md +388 -0
- data/README.md +114 -0
- data/Rakefile +11 -0
- data/VERSION +1 -0
- data/api.gemspec +50 -0
- data/bin/console +96 -0
- data/bin/console.yml +3 -0
- data/bin/setup +8 -0
- data/bin/simple +91 -0
- data/changelog.md +32 -0
- data/conditions/ib/execution_condition.rb +31 -0
- data/conditions/ib/margin_condition.rb +28 -0
- data/conditions/ib/order_condition.rb +29 -0
- data/conditions/ib/percent_change_condition.rb +34 -0
- data/conditions/ib/price_condition.rb +44 -0
- data/conditions/ib/time_condition.rb +42 -0
- data/conditions/ib/volume_condition.rb +36 -0
- data/lib/class_extensions.rb +167 -0
- data/lib/ib/base.rb +109 -0
- data/lib/ib/base_properties.rb +178 -0
- data/lib/ib/connection.rb +573 -0
- data/lib/ib/constants.rb +402 -0
- data/lib/ib/contract.rb +30 -0
- data/lib/ib/errors.rb +52 -0
- data/lib/ib/messages/abstract_message.rb +68 -0
- data/lib/ib/messages/incoming/abstract_message.rb +116 -0
- data/lib/ib/messages/incoming/abstract_tick.rb +25 -0
- data/lib/ib/messages/incoming/account_message.rb +26 -0
- data/lib/ib/messages/incoming/alert.rb +34 -0
- data/lib/ib/messages/incoming/contract_data.rb +105 -0
- data/lib/ib/messages/incoming/contract_message.rb +13 -0
- data/lib/ib/messages/incoming/delta_neutral_validation.rb +23 -0
- data/lib/ib/messages/incoming/execution_data.rb +50 -0
- data/lib/ib/messages/incoming/histogram_data.rb +30 -0
- data/lib/ib/messages/incoming/historical_data.rb +65 -0
- data/lib/ib/messages/incoming/historical_data_update.rb +50 -0
- data/lib/ib/messages/incoming/managed_accounts.rb +21 -0
- data/lib/ib/messages/incoming/market_depth.rb +34 -0
- data/lib/ib/messages/incoming/market_depth_l2.rb +15 -0
- data/lib/ib/messages/incoming/next_valid_id.rb +19 -0
- data/lib/ib/messages/incoming/open_order.rb +290 -0
- data/lib/ib/messages/incoming/order_status.rb +85 -0
- data/lib/ib/messages/incoming/portfolio_value.rb +47 -0
- data/lib/ib/messages/incoming/position_data.rb +21 -0
- data/lib/ib/messages/incoming/positions_multi.rb +15 -0
- data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
- data/lib/ib/messages/incoming/receive_fa.rb +30 -0
- data/lib/ib/messages/incoming/scanner_data.rb +54 -0
- data/lib/ib/messages/incoming/tick_by_tick.rb +77 -0
- data/lib/ib/messages/incoming/tick_efp.rb +18 -0
- data/lib/ib/messages/incoming/tick_generic.rb +12 -0
- data/lib/ib/messages/incoming/tick_option.rb +60 -0
- data/lib/ib/messages/incoming/tick_price.rb +60 -0
- data/lib/ib/messages/incoming/tick_size.rb +55 -0
- data/lib/ib/messages/incoming/tick_string.rb +13 -0
- data/lib/ib/messages/incoming.rb +292 -0
- data/lib/ib/messages/outgoing/abstract_message.rb +84 -0
- data/lib/ib/messages/outgoing/bar_request_message.rb +247 -0
- data/lib/ib/messages/outgoing/new-place-order.rb +193 -0
- data/lib/ib/messages/outgoing/old-place-order.rb +147 -0
- data/lib/ib/messages/outgoing/place_order.rb +149 -0
- data/lib/ib/messages/outgoing/request_account_summary.rb +79 -0
- data/lib/ib/messages/outgoing/request_historical_data.rb +182 -0
- data/lib/ib/messages/outgoing/request_market_data.rb +102 -0
- data/lib/ib/messages/outgoing/request_market_depth.rb +57 -0
- data/lib/ib/messages/outgoing/request_real_time_bars.rb +48 -0
- data/lib/ib/messages/outgoing/request_scanner_subscription.rb +73 -0
- data/lib/ib/messages/outgoing/request_tick_by_tick_data.rb +21 -0
- data/lib/ib/messages/outgoing.rb +410 -0
- data/lib/ib/messages.rb +139 -0
- data/lib/ib/order_condition.rb +26 -0
- data/lib/ib/plugins.rb +27 -0
- data/lib/ib/prepare_data.rb +61 -0
- data/lib/ib/raw_message_parser.rb +99 -0
- data/lib/ib/socket.rb +83 -0
- data/lib/ib/support.rb +236 -0
- data/lib/ib/version.rb +6 -0
- data/lib/ib-api.rb +44 -0
- data/lib/server_versions.rb +145 -0
- data/lib/support/array_function.rb +28 -0
- data/lib/support/logging.rb +45 -0
- data/models/ib/account.rb +72 -0
- data/models/ib/account_value.rb +33 -0
- data/models/ib/bag.rb +55 -0
- data/models/ib/bar.rb +31 -0
- data/models/ib/combo_leg.rb +127 -0
- data/models/ib/contract.rb +411 -0
- data/models/ib/contract_detail.rb +118 -0
- data/models/ib/execution.rb +67 -0
- data/models/ib/forex.rb +12 -0
- data/models/ib/future.rb +64 -0
- data/models/ib/index.rb +14 -0
- data/models/ib/option.rb +149 -0
- data/models/ib/option_detail.rb +84 -0
- data/models/ib/order.rb +720 -0
- data/models/ib/order_state.rb +155 -0
- data/models/ib/portfolio_value.rb +86 -0
- data/models/ib/spread.rb +176 -0
- data/models/ib/stock.rb +25 -0
- data/models/ib/underlying.rb +32 -0
- data/plugins/ib/advanced-account.rb +442 -0
- data/plugins/ib/alerts/base-alert.rb +125 -0
- data/plugins/ib/alerts/gateway-alerts.rb +15 -0
- data/plugins/ib/alerts/order-alerts.rb +73 -0
- data/plugins/ib/auto-adjust.rb +0 -0
- data/plugins/ib/connection-tools.rb +122 -0
- data/plugins/ib/eod.rb +326 -0
- data/plugins/ib/greeks.rb +102 -0
- data/plugins/ib/managed-accounts.rb +274 -0
- data/plugins/ib/market-price.rb +150 -0
- data/plugins/ib/option-chain.rb +167 -0
- data/plugins/ib/order-flow.rb +157 -0
- data/plugins/ib/order-prototypes/abstract.rb +67 -0
- data/plugins/ib/order-prototypes/adaptive.rb +40 -0
- data/plugins/ib/order-prototypes/all-in-one.rb +46 -0
- data/plugins/ib/order-prototypes/combo.rb +46 -0
- data/plugins/ib/order-prototypes/forex.rb +40 -0
- data/plugins/ib/order-prototypes/limit.rb +193 -0
- data/plugins/ib/order-prototypes/market.rb +116 -0
- data/plugins/ib/order-prototypes/pegged.rb +169 -0
- data/plugins/ib/order-prototypes/premarket.rb +31 -0
- data/plugins/ib/order-prototypes/stop.rb +202 -0
- data/plugins/ib/order-prototypes/volatility.rb +39 -0
- data/plugins/ib/order-prototypes.rb +118 -0
- data/plugins/ib/probability-of-expiring.rb +109 -0
- data/plugins/ib/process-orders.rb +155 -0
- data/plugins/ib/roll.rb +86 -0
- data/plugins/ib/spread-prototypes/butterfly.rb +77 -0
- data/plugins/ib/spread-prototypes/calendar.rb +97 -0
- data/plugins/ib/spread-prototypes/stock-spread.rb +56 -0
- data/plugins/ib/spread-prototypes/straddle.rb +70 -0
- data/plugins/ib/spread-prototypes/strangle.rb +93 -0
- data/plugins/ib/spread-prototypes/vertical.rb +83 -0
- data/plugins/ib/spread-prototypes.rb +70 -0
- data/plugins/ib/symbols/abstract.rb +136 -0
- data/plugins/ib/symbols/bonds.rb +28 -0
- data/plugins/ib/symbols/cfd.rb +19 -0
- data/plugins/ib/symbols/combo.rb +46 -0
- data/plugins/ib/symbols/commodity.rb +17 -0
- data/plugins/ib/symbols/forex.rb +41 -0
- data/plugins/ib/symbols/futures.rb +127 -0
- data/plugins/ib/symbols/index.rb +43 -0
- data/plugins/ib/symbols/options.rb +99 -0
- data/plugins/ib/symbols/stocks.rb +44 -0
- data/plugins/ib/symbols/version.rb +5 -0
- data/plugins/ib/symbols.rb +118 -0
- data/plugins/ib/verify.rb +226 -0
- data/symbols/w20.yml +210 -0
- data/t.txt +20 -0
- data/update.md +71 -0
- metadata +327 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module IB
|
|
2
|
+
|
|
3
|
+
module Strangle
|
|
4
|
+
|
|
5
|
+
extend SpreadPrototype
|
|
6
|
+
class << self
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Fabricate a Strangle from a Master-Option
|
|
10
|
+
# -----------------------------------------
|
|
11
|
+
# If one Leg is known, the other is build by flipping the right and adjusting the strike by distance
|
|
12
|
+
#
|
|
13
|
+
# Call with
|
|
14
|
+
# IB::Strangle.fabricate an_option, numeric_value
|
|
15
|
+
def fabricate master, distance
|
|
16
|
+
|
|
17
|
+
flip_right = ->(the_right){ the_right == :put ? :call : :put }
|
|
18
|
+
|
|
19
|
+
error "Argument must be an option" unless [:option, :futures_option].include? master.sec_type
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
initialize_spread( master ) do | the_spread |
|
|
23
|
+
the_spread.add_leg master.verify.first
|
|
24
|
+
the_spread.add_leg master
|
|
25
|
+
.essential
|
|
26
|
+
.merge( right: flip_right[master.right],
|
|
27
|
+
strike: master.strike.to_f + distance.to_f ,
|
|
28
|
+
local_symbol: '',
|
|
29
|
+
con_id: 0 )
|
|
30
|
+
.verify.first
|
|
31
|
+
error "Initialisation of Legs failed" if the_spread.legs.size != 2
|
|
32
|
+
# the_spread.description = the_description( the_spread )
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Build Strangle out of an Underlying
|
|
38
|
+
# -----------------------------------------
|
|
39
|
+
# Needed attributes: :strike, :expiry
|
|
40
|
+
#
|
|
41
|
+
# Optional: :trading_class, :multiplier
|
|
42
|
+
#
|
|
43
|
+
# Call with
|
|
44
|
+
# IB::Strangle.build from: IB::Contract, p: a_value, c: a_value, expiry: yyyymm(dd)
|
|
45
|
+
def build from:, p: nil, c: nil, expiry: nil, **fields
|
|
46
|
+
underlying = if from.is_a? IB::Option
|
|
47
|
+
p ||= from.strike
|
|
48
|
+
c ||= from.strike
|
|
49
|
+
expiry ||= from.expiry
|
|
50
|
+
|
|
51
|
+
details = from.verify.first.contract_detail
|
|
52
|
+
IB::Contract.new( con_id: details.under_con_id,
|
|
53
|
+
currency: from.currency,
|
|
54
|
+
exchange: from.exchange) .verify.first .essential
|
|
55
|
+
else
|
|
56
|
+
from
|
|
57
|
+
end
|
|
58
|
+
kind = { :p => p, :c => c }
|
|
59
|
+
initialize_spread( underlying ) do | the_spread |
|
|
60
|
+
leg_prototype = IB::Option.new from.attributes
|
|
61
|
+
.slice( :currency, :symbol, :exchange)
|
|
62
|
+
.merge(defaults)
|
|
63
|
+
.merge( expiry: expiry )
|
|
64
|
+
.merge( fields )
|
|
65
|
+
|
|
66
|
+
leg_prototype.sec_type = 'FOP' if underlying.is_a?(IB::Future)
|
|
67
|
+
the_spread.add_leg leg_prototype.merge( right: :put, strike: kind[:p] ).verify.first
|
|
68
|
+
the_spread.add_leg leg_prototype.merge( right: :call, strike: kind[:c] ).verify.first
|
|
69
|
+
error "Initialisation of Legs failed" if the_spread.legs.size != 2
|
|
70
|
+
the_spread.description = the_description( the_spread )
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def defaults
|
|
75
|
+
super.merge expiry: IB::Future.next_expiry
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def requirements
|
|
80
|
+
super.merge p: "the strike of the put option",
|
|
81
|
+
c: "the strike of the call option",
|
|
82
|
+
expiry: "Expiry expressed as »yyyymm(dd)« (String or Integer) )"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def the_description spread
|
|
88
|
+
"<Strangle #{spread.symbol}(#{spread.legs.map(&:strike).join(",")})[#{Date.parse(spread.legs.first.last_trading_day).strftime("%b %Y")}]>"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
end # class
|
|
92
|
+
end # module combo
|
|
93
|
+
end # module ib
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module IB
|
|
2
|
+
|
|
3
|
+
module Vertical
|
|
4
|
+
|
|
5
|
+
extend SpreadPrototype
|
|
6
|
+
class << self
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Fabricate a Vertical from a Master-Option
|
|
10
|
+
# -----------------------------------------
|
|
11
|
+
# If one Leg is known, the other is build by flipping the right and adjusting the strike by distance
|
|
12
|
+
#
|
|
13
|
+
# Call with
|
|
14
|
+
# IB::Vertical.fabricate an_option, buy: {another_strike}, (or) , :sell{another_strike}
|
|
15
|
+
def fabricate master, buy: 0, sell: 0
|
|
16
|
+
|
|
17
|
+
error "Argument must be an option" unless [:option, :futures_option].include? master.sec_type
|
|
18
|
+
error "Unable to fabricate Vertical. Either :buy or :sell must be specified " if buy.zero? && sell.zero?
|
|
19
|
+
|
|
20
|
+
buy = master.strike if buy.zero?
|
|
21
|
+
sell = master.strike if sell.zero?
|
|
22
|
+
initialize_spread( master ) do | the_spread |
|
|
23
|
+
the_spread.add_leg master.merge(strike: sell).verify.first, action: :sell
|
|
24
|
+
the_spread.add_leg master.merge(strike: buy).verify.first, action: :buy
|
|
25
|
+
error "Initialisation of Legs failed" if the_spread.legs.size != 2
|
|
26
|
+
the_spread.description = the_description( the_spread )
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Build Vertical out of an Underlying
|
|
32
|
+
# -----------------------------------------
|
|
33
|
+
# Needed attributes: :strikes (buy: strike1, sell: strike2), :expiry, right
|
|
34
|
+
#
|
|
35
|
+
# Optional: :trading_class, :multiplier
|
|
36
|
+
#
|
|
37
|
+
# Call with
|
|
38
|
+
# IB::Straddle.build from: IB::Contract, buy: a_strike, sell: a_stike, right: {put or call}, expiry: yyyymmm(dd)
|
|
39
|
+
def build from:, **fields
|
|
40
|
+
underlying = if from.is_a? IB::Option
|
|
41
|
+
fields[:right] = from.right unless fields.key?(:right)
|
|
42
|
+
fields[:sell] = from.strike unless fields.key(:sell)
|
|
43
|
+
fields[:buy] = from.strike unless fields.key?(:buy)
|
|
44
|
+
fields[:expiry] = from.expiry unless fields.key?(:expiry)
|
|
45
|
+
fields[:trading_class] = from.trading_class unless fields.key?(:trading_class) || from.trading_class.empty?
|
|
46
|
+
fields[:multiplier] = from.multiplier unless fields.key?(:multiplier) || from.multiplier.to_i.zero?
|
|
47
|
+
details = from.verify.first.contract_detail
|
|
48
|
+
IB::Contract.new( con_id: details.under_con_id,
|
|
49
|
+
currency: from.currency,
|
|
50
|
+
exchange: from.exchange)
|
|
51
|
+
.verify.first
|
|
52
|
+
.essential
|
|
53
|
+
else
|
|
54
|
+
from
|
|
55
|
+
end
|
|
56
|
+
kind = { :buy => fields.delete(:buy), :sell => fields.delete(:sell) }
|
|
57
|
+
error "Specification of :buy and :sell necessary, got: #{kind.inspect}" if kind.values.any?(nil)
|
|
58
|
+
initialize_spread( underlying ) do | the_spread |
|
|
59
|
+
leg_prototype = Option.new underlying.attributes
|
|
60
|
+
.slice( :currency, :symbol, :exchange)
|
|
61
|
+
.merge(defaults)
|
|
62
|
+
.merge( fields )
|
|
63
|
+
leg_prototype.sec_type = 'FOP' if underlying.is_a?(IB::Future)
|
|
64
|
+
the_spread.add_leg leg_prototype.merge(strike: kind[:sell]).verify.first, action: :sell
|
|
65
|
+
the_spread.add_leg leg_prototype.merge(strike: kind[:buy] ).verify.first, action: :buy
|
|
66
|
+
error "Initialisation of Legs failed" if the_spread.legs.size != 2
|
|
67
|
+
the_spread.description = the_description( the_spread )
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def defaults
|
|
72
|
+
super.merge expiry: IB::Future.next_expiry,
|
|
73
|
+
right: :put
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def the_description spread
|
|
78
|
+
x= [ spread.combo_legs.map(&:weight) , spread.legs.map( &:strike )].transpose
|
|
79
|
+
"<Vertical #{spread.symbol} #{spread.legs.first.right}(#{x.map{|w,strike| "#{w} :#{strike} "}.join( '|+|' )} )[#{Date.parse(spread.legs.first.last_trading_day).strftime("%b %Y")}]>"
|
|
80
|
+
end
|
|
81
|
+
end # class
|
|
82
|
+
end # module vertical
|
|
83
|
+
end # module ib
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
|
|
3
|
+
Plugin to automate the creation of common spreads
|
|
4
|
+
|
|
5
|
+
Straddle.build from: Contract, expiry:, strike:
|
|
6
|
+
Strangle build from: Contract. expiry:, p: , c:
|
|
7
|
+
Vertical.build from: Contract, expiry:, right: , buy: (a strike), sell: (a strike)
|
|
8
|
+
Calendar.build from: Contract. right:, :strike:, front: (an expiry), back: (an expiry)
|
|
9
|
+
Butterfly.build from: Contract, right:, strike: , expiry: , front: (long-option strike), back: (long option strike)
|
|
10
|
+
|
|
11
|
+
StockSpread.fabricate symbol1, symbol2, ratio:[ n, m ] # only for us-stocks
|
|
12
|
+
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
module IB
|
|
16
|
+
# Spreads are created in two ways:
|
|
17
|
+
#
|
|
18
|
+
# (1) IB::Spread::{prototype}.build from: {underlying},
|
|
19
|
+
# trading_class: (optional)
|
|
20
|
+
# {other specific attributes}
|
|
21
|
+
#
|
|
22
|
+
# (2) IB::Spread::{prototype}.fabcricate master: [one leg},
|
|
23
|
+
# {other specific attributes}
|
|
24
|
+
#
|
|
25
|
+
# They return a freshly instantiated Spread-Object
|
|
26
|
+
#
|
|
27
|
+
module SpreadPrototype
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def build from: , **fields
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def initialize_spread ref_contract = nil, **attributes
|
|
35
|
+
error "Initializing of Spread failed – contract is missing" unless ref_contract.is_a?(IB::Contract)
|
|
36
|
+
# make sure that :exchange, :symbol and :currency are present
|
|
37
|
+
the_contract = ref_contract.merge( **attributes ).verify.first
|
|
38
|
+
error "Underlying for Spread is not valid: #{ref_contract.to_human}" if the_contract.nil?
|
|
39
|
+
the_spread= IB::Spread.new the_contract.attributes.slice( :exchange, :symbol, :currency )
|
|
40
|
+
error "Initializing of Spread failed – Underling is no Contract" if the_spread.nil?
|
|
41
|
+
yield the_spread if block_given? # yield outside mutex controlled verify-environment
|
|
42
|
+
the_spread # return_value
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def requirements
|
|
46
|
+
{}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def defaults
|
|
50
|
+
{}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def optional
|
|
54
|
+
{ }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def parameters
|
|
58
|
+
the_output = ->(var){ var.empty? ? "none" : var.map{|x| x.join(" --> ") }.join("\n\t: ")}
|
|
59
|
+
|
|
60
|
+
"Required : " + the_output[requirements] + "\n --------------- \n" +
|
|
61
|
+
"Optional : " + the_output[optional] + "\n --------------- \n"
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
Connection.current.activate_plugin "verify"
|
|
66
|
+
[:straddle, :strangle, :vertical, :calendar, :"stock-spread", :butterfly].each do | pt |
|
|
67
|
+
Connection.current.activate_plugin "spread_prototypes/#{pt.to_s}"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
module IB
|
|
2
|
+
|
|
3
|
+
# reopen the contract-class and add yml_file
|
|
4
|
+
class Contract
|
|
5
|
+
|
|
6
|
+
# Reading Contract-Defaults
|
|
7
|
+
#
|
|
8
|
+
# by default, the yml-file in the base-directory (ib-ruby) is used.
|
|
9
|
+
# This method can be overloaded to include a file from a different location
|
|
10
|
+
#
|
|
11
|
+
# IB::Symbols::Stocks.wfc.yml_file
|
|
12
|
+
# => "/home/ubuntu/workspace/ib-ruby/contract_config.yml"
|
|
13
|
+
#
|
|
14
|
+
def yml_file
|
|
15
|
+
File.expand_path('../../../../contract_config.yml',__FILE__ )
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module Symbols
|
|
20
|
+
|
|
21
|
+
=begin
|
|
22
|
+
Creates a Class and associates it with a filename
|
|
23
|
+
|
|
24
|
+
raises an IB::Error in case of a conflict with existing class-names
|
|
25
|
+
=end
|
|
26
|
+
|
|
27
|
+
# set the Pathname to "ib-api/symbols" by default
|
|
28
|
+
@@dir= Pathname.new File.expand_path("../../../../symbols/", __FILE__ )
|
|
29
|
+
def self.set_origin directory
|
|
30
|
+
p = Pathname.new directory
|
|
31
|
+
@@dir = p if p.directory?
|
|
32
|
+
rescue Errno::ENOENT
|
|
33
|
+
error "Setting up origin for symbol-files --> Directory (#{directory}) does not exist"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.allocate_collection name # name might be a string or a symbol
|
|
37
|
+
symbol_table = Module.new do
|
|
38
|
+
extend Symbols
|
|
39
|
+
extend Enumerable
|
|
40
|
+
def self.yml_file
|
|
41
|
+
@@dir + name.to_s.downcase.split("::").last.concat( ".yml" )
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.each &b
|
|
45
|
+
contracts.values.each &b
|
|
46
|
+
end
|
|
47
|
+
end # module new
|
|
48
|
+
name = name.to_s.camelize.to_sym
|
|
49
|
+
the_collection = if Symbols.send :const_defined?, name
|
|
50
|
+
Symbols.send :const_get, name
|
|
51
|
+
else
|
|
52
|
+
Symbols.const_set name, symbol_table
|
|
53
|
+
end
|
|
54
|
+
if the_collection.is_a? Symbols
|
|
55
|
+
the_collection.send :read_collection if the_collection.all.empty?
|
|
56
|
+
the_collection # return_value
|
|
57
|
+
else
|
|
58
|
+
error "#{the_collection} is already a Class"
|
|
59
|
+
nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def purge_collection
|
|
64
|
+
yml_file.delete
|
|
65
|
+
@contracts = nil
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
=begin
|
|
69
|
+
cuts the Collection in `bunch_count` pieces. Each bunch is delivered to the block.
|
|
70
|
+
|
|
71
|
+
Sleeps for `sleeping time` between processing bunches
|
|
72
|
+
|
|
73
|
+
Returns count of created bunches
|
|
74
|
+
=end
|
|
75
|
+
def bunch( bunch_count = 50 , sleeping_time = 1)
|
|
76
|
+
en = self.each
|
|
77
|
+
the_size = en.size
|
|
78
|
+
i = 0
|
|
79
|
+
loop do
|
|
80
|
+
the_start = i * bunch_count
|
|
81
|
+
the_end = the_start + bunch_count
|
|
82
|
+
the_end = the_size -1 if the_end >= the_size
|
|
83
|
+
it = the_start .. the_end
|
|
84
|
+
yield it.map{|x| en.next rescue nil}.compact
|
|
85
|
+
break if the_end == the_size -1
|
|
86
|
+
i+=1
|
|
87
|
+
sleep sleeping_time
|
|
88
|
+
end
|
|
89
|
+
i -1 # return counts of bunches
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def read_collection
|
|
93
|
+
if yml_file.exist?
|
|
94
|
+
contracts.merge! YAML.unsafe_load_file yml_file rescue contracts
|
|
95
|
+
else
|
|
96
|
+
yml_file.open( "w"){}
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def store_collection
|
|
101
|
+
yml_file.open( 'w' ){|f| f.write @contracts.to_yaml}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def add_contract symbol, contract
|
|
105
|
+
if symbol.is_a? String
|
|
106
|
+
symbol.to_sym
|
|
107
|
+
elsif symbol.is_a? Symbol
|
|
108
|
+
symbol
|
|
109
|
+
else
|
|
110
|
+
symbol.to_i
|
|
111
|
+
end
|
|
112
|
+
# ensure that evey Sybmol::xxx.yyy entry has a description
|
|
113
|
+
contract.description = contract.to_human[1..-2] if contract.description.nil?
|
|
114
|
+
# overwrite contract if existing
|
|
115
|
+
contracts[ symbol ] = contract.essential
|
|
116
|
+
store_collection
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def remove_contract symbol
|
|
120
|
+
@contracts.delete symbol
|
|
121
|
+
store_collection
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def to_human
|
|
126
|
+
self.to_s.split("::").last
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
module Unspecified
|
|
132
|
+
extend Symbols
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end # module Symbols
|
|
136
|
+
end # module IB
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Sample bond contract definitions
|
|
2
|
+
module IB
|
|
3
|
+
module Symbols
|
|
4
|
+
module Bonds
|
|
5
|
+
extend Symbols
|
|
6
|
+
|
|
7
|
+
def self.contracts
|
|
8
|
+
@contracts ||= {
|
|
9
|
+
:abbey => IB::Contract.new(:symbol => "ABBEY",
|
|
10
|
+
:currency => "USD",
|
|
11
|
+
:sec_type => :bond,
|
|
12
|
+
:description => "Any ABBEY bond"),
|
|
13
|
+
|
|
14
|
+
:ms => IB::Contract.new(:symbol => "MS",
|
|
15
|
+
:currency => "USD",
|
|
16
|
+
:sec_type => :bond,
|
|
17
|
+
:description => "Any Morgan Stanley bond"),
|
|
18
|
+
|
|
19
|
+
:wag => IB::Contract.new(:symbol => "WAG",
|
|
20
|
+
:currency => "USD",
|
|
21
|
+
:sec_type => :bond,
|
|
22
|
+
:description => "Any Wallgreens bond"),
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Frequently used stock contracts definitions
|
|
2
|
+
# TODO: auto-request :ContractDetails from IB if unknown symbol is requested?
|
|
3
|
+
module IB
|
|
4
|
+
module Symbols
|
|
5
|
+
module CFD
|
|
6
|
+
extend Symbols
|
|
7
|
+
|
|
8
|
+
def self.contracts
|
|
9
|
+
@contracts.presence || super.merge(
|
|
10
|
+
:dax => IB::Contract.new(:symbol => "IBDE30", sec_type: :cfd,
|
|
11
|
+
:currency => "EUR",
|
|
12
|
+
:description => "DAX CFD."),
|
|
13
|
+
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Frequently used stock contracts definitions
|
|
2
|
+
# TODO: auto-request :ContractDetails from IB if unknown symbol is requested?
|
|
3
|
+
module IB
|
|
4
|
+
module Symbols
|
|
5
|
+
module Combo
|
|
6
|
+
extend Symbols
|
|
7
|
+
|
|
8
|
+
def self.contracts
|
|
9
|
+
base = 4800
|
|
10
|
+
exp = IB::Option.next_expiry
|
|
11
|
+
@contracts ||= { #super.merge(
|
|
12
|
+
stoxx_straddle: IB::Straddle.build( from: IB::Symbols::Index.stoxx, strike: base,
|
|
13
|
+
expiry: exp, trading_class: 'OESX' ) ,
|
|
14
|
+
stoxx_calendar: IB::Calendar.build( from: IB::Symbols::Index.stoxx, strike: base, back: '2m' ,
|
|
15
|
+
front: exp, trading_class: 'OESX' ),
|
|
16
|
+
stoxx_butterfly: IB::Butterfly.fabricate( IB::Symbols::Options.stoxx.merge( strike: base - 200,
|
|
17
|
+
expiry: exp),
|
|
18
|
+
front: base - 400, back: base),
|
|
19
|
+
stoxx_vertical: IB::Vertical.build( from: IB::Symbols::Index.stoxx,
|
|
20
|
+
sell: base - 200, buy: base + 200,
|
|
21
|
+
right: :put,
|
|
22
|
+
expiry: exp,
|
|
23
|
+
trading_class: 'OESX'),
|
|
24
|
+
zn_calendar: IB::Calendar.fabricate( IB::Symbols::Futures.zn.next_expiry, '3m') ,
|
|
25
|
+
|
|
26
|
+
dbk_straddle: Bag.new( symbol: 'DBK', currency: 'EUR', exchange: 'EUREX', combo_legs:
|
|
27
|
+
[ ComboLeg.new( con_id: 270581032 , action: :buy, exchange: 'DTB', ratio: 1), #DBK Dez20 2018 C
|
|
28
|
+
ComboLeg.new( con_id: 270580382, action: :buy, exchange: 'DTB', ratio: 1 ) ], #DBK Dez 20 2018 P
|
|
29
|
+
description: 'Option Straddle: Deutsche Bank(20)[Dez 2018]'),
|
|
30
|
+
ib_mcd: Bag.new( symbol: 'IBKR,MCD', currency: 'USD', exchange: 'SMART',
|
|
31
|
+
combo_legs: [ ComboLeg.new( con_id: 43645865, action: :buy, ratio: 1), # IKBR STK
|
|
32
|
+
ComboLeg.new( con_id: 9408, action: :sell,ratio: 1 ) ], # MCD STK
|
|
33
|
+
description: 'Stock Spread: Buy Interactive Brokers, sell Mc Donalds'),
|
|
34
|
+
|
|
35
|
+
vix_calendar: Bag.new( symbol: 'VIX', currency: 'USD', exchange: 'CFE',
|
|
36
|
+
combo_legs: [ ComboLeg.new( con_id: 256038899, action: :buy, exchange: 'CFE', ratio: 1), # VIX FUT 201708
|
|
37
|
+
ComboLeg.new( con_id: 260564703, action: :sell, exchange: 'CFE', ratio: 1 ) ], # VIX FUT 201709
|
|
38
|
+
description: 'VixFuture Calendar-Spread August - September 2017'
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
# )
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Frequently used stock contracts definitions
|
|
2
|
+
# TODO: auto-request :ContractDetails from IB if unknown symbol is requested?
|
|
3
|
+
module IB
|
|
4
|
+
module Symbols
|
|
5
|
+
module Commodity
|
|
6
|
+
extend Symbols
|
|
7
|
+
|
|
8
|
+
def self.contracts
|
|
9
|
+
@contracts.presence || super.merge(
|
|
10
|
+
:xau => IB::Contract.new( symbol: 'XAUUSD', sec_type: :commodity, currency: 'USD',
|
|
11
|
+
:description => "London Gold ")
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module IB
|
|
2
|
+
module Symbols
|
|
3
|
+
module Forex
|
|
4
|
+
extend Symbols
|
|
5
|
+
|
|
6
|
+
def self.contracts
|
|
7
|
+
@contracts ||= define_contracts
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
# IDEALPRO is for orders over 20,000 and routes to the interbank quote stream.
|
|
13
|
+
# IDEAL is for smaller orders, and has wider spreads/slower execution... generally
|
|
14
|
+
# used for smaller currency conversions. IB::Symbols::Forex contracts are pre-defined
|
|
15
|
+
# on IDEALPRO, if you need something else please define forex contracts manually.
|
|
16
|
+
def self.define_contracts
|
|
17
|
+
@contracts = {}
|
|
18
|
+
|
|
19
|
+
# use combinations of these currencies for pre-defined forex contracts
|
|
20
|
+
currencies = [ "aud", "cad", "chf", "eur", "gbp", "hkd", "jpy", "nzd", "usd" ]
|
|
21
|
+
|
|
22
|
+
# create pairs list from currency list
|
|
23
|
+
pairs = currencies.product(currencies).
|
|
24
|
+
map { |pair| pair.join.upcase unless pair.first == pair.last }.compact
|
|
25
|
+
|
|
26
|
+
# now define each contract
|
|
27
|
+
pairs.each do |pair|
|
|
28
|
+
@contracts[pair.downcase.to_sym] = IB::Forex.new(
|
|
29
|
+
:symbol => pair[0..2],
|
|
30
|
+
:exchange => "IDEALPRO",
|
|
31
|
+
:currency => pair[3..5],
|
|
32
|
+
:local_symbol => pair[0..2]+'.'+pair[3..5],
|
|
33
|
+
:description => pair
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
@contracts
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# The Futures module tries to guess the front month future using a crude algorithm that
|
|
2
|
+
# does not take into account expiry/rollover day. This will be valid most of the time,
|
|
3
|
+
# but near/after expiry day the next quarter's contract takes over as the volume leader.
|
|
4
|
+
|
|
5
|
+
module IB
|
|
6
|
+
module Symbols
|
|
7
|
+
module Futures
|
|
8
|
+
extend Symbols
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def self.contracts
|
|
12
|
+
@contracts.presence ||( super.merge :ym => IB::Future.new(:symbol => "YM",
|
|
13
|
+
:expiry => IB::Future.next_expiry,
|
|
14
|
+
:exchange => "CBOT",
|
|
15
|
+
:currency => "USD",
|
|
16
|
+
:description => "Mini-DJIA future"),
|
|
17
|
+
:nq => IB::Future.new(:symbol => "NQ",
|
|
18
|
+
:expiry => IB::Future.next_expiry,
|
|
19
|
+
:exchange => "CME",
|
|
20
|
+
:currency => "USD",
|
|
21
|
+
:multiplier => 20,
|
|
22
|
+
:description => "Mini Nasdaq 100 future"),
|
|
23
|
+
:micro_nq => IB::Future.new(:symbol => "MNQ",
|
|
24
|
+
:expiry => IB::Future.next_expiry,
|
|
25
|
+
:exchange => "CME",
|
|
26
|
+
:currency => "USD",
|
|
27
|
+
:multiplier => 2,
|
|
28
|
+
:description => "Micro Nasdaq 100 future"),
|
|
29
|
+
:es => IB::Future.new(:symbol => "ES",
|
|
30
|
+
:expiry => IB::Future.next_expiry,
|
|
31
|
+
:exchange => "CME",
|
|
32
|
+
:currency => "USD",
|
|
33
|
+
:multiplier => 50,
|
|
34
|
+
:description => "Mini S&P 500 future"),
|
|
35
|
+
:micro_es => IB::Future.new(:symbol => "MES",
|
|
36
|
+
:expiry => IB::Future.next_expiry,
|
|
37
|
+
:exchange => "CME",
|
|
38
|
+
:currency => "USD",
|
|
39
|
+
:multiplier => 5,
|
|
40
|
+
:description => "Micro S&P 500 future"),
|
|
41
|
+
:russell => IB::Future.new(:symbol => "RTY",
|
|
42
|
+
:expiry => IB::Future.next_expiry,
|
|
43
|
+
:exchange => "CME",
|
|
44
|
+
:currency => "USD",
|
|
45
|
+
:multiplier => 5,
|
|
46
|
+
:description => "Mini Russell 2000 future"),
|
|
47
|
+
:micro_russell => IB::Future.new(:symbol => "M2K",
|
|
48
|
+
:expiry => IB::Future.next_expiry,
|
|
49
|
+
:exchange => "CME",
|
|
50
|
+
:currency => "USD",
|
|
51
|
+
:multiplier => 5,
|
|
52
|
+
:description => "Micro Russell 2000 future"),
|
|
53
|
+
:zn => IB::Future.new( symbol: 'ZN',
|
|
54
|
+
expiry: IB::Future.next_expiry,
|
|
55
|
+
currency: 'USD',
|
|
56
|
+
multiplier: 1000,
|
|
57
|
+
exchange: 'CBOT',
|
|
58
|
+
description: 'US Treasury Note -- 10 Years'),
|
|
59
|
+
:zb => IB::Future.new( symbol: 'ZB',
|
|
60
|
+
expiry: IB::Future.next_expiry,
|
|
61
|
+
currency: 'USD',
|
|
62
|
+
multiplier: 1000,
|
|
63
|
+
exchange: 'CBOT',
|
|
64
|
+
description: 'US Treasury Note -- 30 Years'),
|
|
65
|
+
:micro_dax => IB::Future.new( symbol: 'DAX', exchange: 'EUREX',
|
|
66
|
+
expiry: IB::Future.next_expiry,
|
|
67
|
+
currency: 'EUR',
|
|
68
|
+
multiplier: 1,
|
|
69
|
+
description: 'Mini DAX-Future'),
|
|
70
|
+
:mini_dax => IB::Future.new( symbol: 'DAX', exchange: 'EUREX',
|
|
71
|
+
expiry: IB::Future.next_expiry,
|
|
72
|
+
currency: 'EUR',
|
|
73
|
+
multiplier: 5,
|
|
74
|
+
description: 'Mini DAX-Future'),
|
|
75
|
+
:dax => IB::Future.new( symbol: 'DAX', exchange: 'EUREX',
|
|
76
|
+
expiry: IB::Future.next_expiry,
|
|
77
|
+
currency: 'EUR',
|
|
78
|
+
multiplier: 25,
|
|
79
|
+
description: 'DAX-Future'),
|
|
80
|
+
:stoxx=> IB::Future.new( symbol: 'ESTX50', exchange: 'EUREX',
|
|
81
|
+
expiry: IB::Future.next_expiry,
|
|
82
|
+
currency: 'EUR',
|
|
83
|
+
multiplier: 10,
|
|
84
|
+
description: 'EuroStoxx 50 -Future'),
|
|
85
|
+
:mini_stoxx=> IB::Future.new( symbol: 'ESTX50', exchange: 'EUREX',
|
|
86
|
+
expiry: IB::Future.next_expiry,
|
|
87
|
+
currency: 'EUR',
|
|
88
|
+
multiplier: 1,
|
|
89
|
+
description: 'Mini/Micro EuroStoxx 50 -Future'),
|
|
90
|
+
:micro_stoxx=> IB::Future.new( symbol: 'ESTX50', exchange: 'EUREX',
|
|
91
|
+
expiry: IB::Future.next_expiry,
|
|
92
|
+
currency: 'EUR',
|
|
93
|
+
multiplier: 1,
|
|
94
|
+
description: 'Miico EuroStoxx 50 -Future'),
|
|
95
|
+
:gbp => IB::Future.new(:symbol => "GBP",
|
|
96
|
+
:expiry => IB::Future.next_expiry,
|
|
97
|
+
:exchange => "CME",
|
|
98
|
+
:currency => "USD",
|
|
99
|
+
:multiplier => 62500,
|
|
100
|
+
:description => "British Pounds future"),
|
|
101
|
+
:eur => IB::Future.new(:symbol => "EUR",
|
|
102
|
+
:expiry => IB::Future.next_expiry,
|
|
103
|
+
:exchange => "CME",
|
|
104
|
+
:currency => "USD",
|
|
105
|
+
:multiplier => 12500,
|
|
106
|
+
:description => "Euro FX future"),
|
|
107
|
+
:jpy => IB::Future.new(:symbol => "JPY",
|
|
108
|
+
:expiry => IB::Future.next_expiry,
|
|
109
|
+
:exchange => "CME",
|
|
110
|
+
:currency => "USD",
|
|
111
|
+
:multiplier => 12500000,
|
|
112
|
+
:description => "Japanese Yen future"),
|
|
113
|
+
:hsi => IB::Future.new(:symbol => "HSI",
|
|
114
|
+
:expiry => IB::Future.next_expiry,
|
|
115
|
+
:exchange => "HKFE",
|
|
116
|
+
:currency => "HKD",
|
|
117
|
+
:multiplier => 50,
|
|
118
|
+
:description => "Hang Seng Index future"),
|
|
119
|
+
:vix => IB::Future.new(:symbol => "VIX",
|
|
120
|
+
:expiry => IB::Future.next_expiry,
|
|
121
|
+
:exchange => "CFE",
|
|
122
|
+
:currency => "USD",
|
|
123
|
+
:description => "CBOE Volatility Index future"))
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|