ib-symbols 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 +4 -0
- data/Guardfile +24 -0
- data/README.md +98 -0
- data/Rakefile +6 -0
- data/bin/console +108 -0
- data/bin/console.yml +3 -0
- data/bin/setup +8 -0
- data/build.md +28 -0
- data/examples/contract_details +71 -0
- data/examples/contract_sample_details +50 -0
- data/examples/contract_samples.rb +716 -0
- data/examples/depth_of_market +45 -0
- data/examples/head_time_stamp +35 -0
- data/examples/historic_data +102 -0
- data/examples/market_data +57 -0
- data/examples/option_data +63 -0
- data/examples/real_time_data +35 -0
- data/examples/snapshot_market_data +105 -0
- data/examples/time_and_sales +51 -0
- data/ib-symbols.gemspec +38 -0
- data/lib/ib/symbols.rb +112 -0
- data/lib/ib/symbols/abstract.rb +137 -0
- data/lib/ib/symbols/bonds.rb +28 -0
- data/lib/ib/symbols/cfd.rb +19 -0
- data/lib/ib/symbols/combo.rb +52 -0
- data/lib/ib/symbols/commodity.rb +17 -0
- data/lib/ib/symbols/forex.rb +41 -0
- data/lib/ib/symbols/futures.rb +137 -0
- data/lib/ib/symbols/index.rb +43 -0
- data/lib/ib/symbols/options.rb +82 -0
- data/lib/ib/symbols/stocks.rb +38 -0
- data/lib/ib/symbols/version.rb +5 -0
- data/lib/ib/symbols_base.rb +58 -0
- data/symbols/README.md +20 -0
- data/symbols/test.yml +12 -0
- metadata +196 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script connects to IB API and subscribes to market data for Forex symbols.
|
4
|
+
# It then prints out all trades that exceed certain size.
|
5
|
+
|
6
|
+
require 'bundler/setup'
|
7
|
+
require 'ib/symbols'
|
8
|
+
|
9
|
+
# Define the symbols we're interested in.
|
10
|
+
@market = {
|
11
|
+
123 => IB::Symbols::Futures[:gbp],
|
12
|
+
234 => IB::Symbols::Futures[:jpy],
|
13
|
+
444 => IB::Symbols::Forex[:usdjpy]
|
14
|
+
}
|
15
|
+
|
16
|
+
# First, connect to IB TWS. Arbitrary :client_id is used to identify your script
|
17
|
+
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
18
|
+
|
19
|
+
# Subscribe to TWS alerts/errors
|
20
|
+
ib.subscribe(:Alert, :ManagedAccounts) { |msg| puts msg.to_human }
|
21
|
+
|
22
|
+
# This method filters out non-:last type events, and filters out any sale < MIN_SIZE.
|
23
|
+
# Note that we have to look the ticker id of each incoming message
|
24
|
+
# up in local memory to figure out what it's for.
|
25
|
+
# (N.B. The description field is not from IB TWS. It is defined
|
26
|
+
# locally in symbols/futures.rb symbols/forex.rb, and is just arbitrary text.)
|
27
|
+
def show_sales_and_size(msg)
|
28
|
+
#return if msg.type != :last_price || msg.data[:size] < MIN_SIZE
|
29
|
+
puts @market[msg.ticker_id].description + ": " +
|
30
|
+
(msg.is_a?(IB::Messages::Incoming::TickPrice) ?
|
31
|
+
"#{msg.data[:size]} at #{msg.data[:price]}" : msg.to_human)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Now, subscribe to TickerPrice and TickerSize events. The code passed in the block
|
35
|
+
# will be executed when a message of that type is received, with the received message
|
36
|
+
# as its argument. In this case, we just print out the tick.
|
37
|
+
ib.subscribe(:TickPrice, :TickSize, :TickString) { |msg| show_sales_and_size(msg) }
|
38
|
+
|
39
|
+
# Now we actually request market data for the symbols we're interested in.
|
40
|
+
@market.each_pair do |id, contract|
|
41
|
+
ib.send_message :RequestMarketData, :ticker_id => id, :contract => contract
|
42
|
+
end
|
43
|
+
|
44
|
+
puts "\nSubscribed to TWS market data"
|
45
|
+
puts "\n******** Press <Enter> to cancel... *********\n\n"
|
46
|
+
STDIN.gets
|
47
|
+
puts "Unsubscribing from TWS market data.."
|
48
|
+
|
49
|
+
@market.each_pair { |id, contract| ib.send_message :CancelMarketData, :ticker_id => id }
|
50
|
+
|
51
|
+
sleep 2
|
data/ib-symbols.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'lib/ib/symbols/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "ib-symbols"
|
5
|
+
spec.version = IB::Symbols::VERSION
|
6
|
+
spec.authors = ["Hartmut Bischoff"]
|
7
|
+
spec.email = ["topofocus@gmail.com"]
|
8
|
+
|
9
|
+
spec.summary = %q{Predefined symbols and watchlist, part of ib-ruby}
|
10
|
+
spec.description = %q{Easy access to most common contracts through templates, define watchlists to perfrom bulk operations}
|
11
|
+
spec.homepage = "https://ib-ruby.github.io/ib-doc/"
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
13
|
+
|
14
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = "https://github.com/ib-ruby/ib-symbols"
|
18
|
+
# spec.metadata["changelog_uri"] = "https://github.com/ib-ruby/ib-symbols/changelog.md"
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_dependency "ib-api"
|
30
|
+
spec.add_dependency "ox"
|
31
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
32
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
33
|
+
spec.add_development_dependency 'rspec-collection_matchers'
|
34
|
+
spec.add_development_dependency 'rspec-its'
|
35
|
+
|
36
|
+
spec.add_development_dependency "guard"
|
37
|
+
spec.add_development_dependency "guard-rspec"
|
38
|
+
end
|
data/lib/ib/symbols.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require "ib/symbols/version"
|
2
|
+
require "ib-api"
|
3
|
+
|
4
|
+
# These modules are used to facilitate referencing of most popular IB Contracts.
|
5
|
+
# Like pages in the TWS-GUI, they can be utilised to organise trading and research.
|
6
|
+
#
|
7
|
+
# Symbol Allocations are organized as modules. They represent the contents of yaml files in
|
8
|
+
#
|
9
|
+
# /lib/symbols/
|
10
|
+
#
|
11
|
+
# Any collection is represented as simple Hash, with __key__ as qualifier and an __IB::Contract__ as value.
|
12
|
+
# The Value is either a fully prequalified Contract (Stock, Option, Future, Forex, CFD, BAG) or
|
13
|
+
# a lazy qualified Contract acting as base für further calucaltions and requests.
|
14
|
+
#
|
15
|
+
# IB::Symbols.allocate_collection :Name
|
16
|
+
#
|
17
|
+
# creates the Module and file. If a previously created file is found, its contents are read and
|
18
|
+
# the vcollection ist reestablished.
|
19
|
+
#
|
20
|
+
# IB::Symbols::Name.add_contract :wfc, IB::Stock.new( symbol: 'WFC' )
|
21
|
+
#
|
22
|
+
# adds the contract and stores it in the yaml file
|
23
|
+
#
|
24
|
+
# IB::Symbols::Name.wfc # or IB::Symbols::Name[:wfc]
|
25
|
+
#
|
26
|
+
# retrieves the contract
|
27
|
+
#
|
28
|
+
# IB::Symbols::Name.all
|
29
|
+
#
|
30
|
+
# returns an Array of stored contracts
|
31
|
+
#
|
32
|
+
# IB::Symbols::Name.remove_contract :wfc
|
33
|
+
#
|
34
|
+
# deletes the contract from the list (and the file)
|
35
|
+
#
|
36
|
+
# To finish the cycle
|
37
|
+
#
|
38
|
+
# IB::Symbols::Name.purge_collection
|
39
|
+
#
|
40
|
+
# deletes the file and erases the collection in memory.
|
41
|
+
#
|
42
|
+
# Additional methods can be introduced
|
43
|
+
# * for individual contracts on the module-level or
|
44
|
+
# * to organize the list as methods of Array in Module IB::SymbolExtention
|
45
|
+
#
|
46
|
+
#
|
47
|
+
# Contracts can be hardcoded in the required standard-collections as well.
|
48
|
+
# Note that the :description field is local to ib-ruby, and is NOT part of the standard TWS API.
|
49
|
+
# It is never transmitted to IB. It's purely used clientside, and you can store any arbitrary
|
50
|
+
# string that you may find useful there.
|
51
|
+
|
52
|
+
module IB
|
53
|
+
module Symbols
|
54
|
+
class Error < StandardError; end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
def hardcoded?
|
59
|
+
!self.methods.include? :yml_file
|
60
|
+
end
|
61
|
+
def method_missing(method, *key)
|
62
|
+
if key.empty?
|
63
|
+
if contracts.has_key?(method)
|
64
|
+
contracts[method]
|
65
|
+
elsif methods.include?(:each) && each.methods.include?(method)
|
66
|
+
self.each.send method
|
67
|
+
else
|
68
|
+
error "contract #{method} not defined. Try »all« for a list of defined Contracts.", :symbol
|
69
|
+
end
|
70
|
+
else
|
71
|
+
error "method missing"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def all
|
76
|
+
contracts.keys.sort rescue contracts.keys
|
77
|
+
end
|
78
|
+
def print_all
|
79
|
+
puts contracts.sort.map{|x,y| [x,y.description].join(" -> ")}.join "\n"
|
80
|
+
end
|
81
|
+
def contracts
|
82
|
+
if @contracts.present?
|
83
|
+
@contracts
|
84
|
+
else
|
85
|
+
@contracts = Hash.new
|
86
|
+
end
|
87
|
+
end
|
88
|
+
def [] symbol
|
89
|
+
if c=contracts[symbol]
|
90
|
+
return c
|
91
|
+
else
|
92
|
+
# symbol probably has not been predefined, tell user about it
|
93
|
+
file = self.to_s.split(/::/).last.downcase
|
94
|
+
msg = "Unknown symbol :#{symbol}, please pre-define it in lib/ib/symbols/#{file}.rb"
|
95
|
+
error msg, :symbol
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
require 'ib/symbols/forex'
|
103
|
+
require 'ib/symbols/futures'
|
104
|
+
require 'ib/symbols/stocks'
|
105
|
+
require 'ib/symbols/index'
|
106
|
+
require 'ib/symbols/cfd'
|
107
|
+
require 'ib/symbols/commodity'
|
108
|
+
require 'ib/symbols/options'
|
109
|
+
require 'ib/symbols/combo'
|
110
|
+
require 'ib/symbols/bonds'
|
111
|
+
require 'ib/symbols/abstract'
|
112
|
+
|
@@ -0,0 +1,137 @@
|
|
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
|
+
|
20
|
+
module Symbols
|
21
|
+
|
22
|
+
=begin
|
23
|
+
Creates a Class and associates it with a filename
|
24
|
+
|
25
|
+
raises an IB::Error in case of a conflict with existing class-names
|
26
|
+
=end
|
27
|
+
|
28
|
+
# set the Pathname to "ib-api/symbols" by default
|
29
|
+
@@dir= Pathname.new File.expand_path("../../../../symbols/", __FILE__ )
|
30
|
+
def self.set_origin directory
|
31
|
+
p = Pathname.new directory
|
32
|
+
@@dir = p if p.directory?
|
33
|
+
rescue Errno::ENOENT
|
34
|
+
error "Setting up origin for symbol-files --> Directory (#{directory}) does not exist"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.allocate_collection name # name might be a string or a symbol
|
38
|
+
symbol_table = Module.new do
|
39
|
+
extend Symbols
|
40
|
+
extend Enumerable
|
41
|
+
def self.yml_file
|
42
|
+
@@dir + name.to_s.downcase.split("::").last.concat( ".yml" )
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.each &b
|
46
|
+
contracts.values.each &b
|
47
|
+
end
|
48
|
+
end # module new
|
49
|
+
name = name.to_s.camelize.to_sym
|
50
|
+
the_collection = if Symbols.send :const_defined?, name
|
51
|
+
Symbols.send :const_get, name
|
52
|
+
else
|
53
|
+
Symbols.const_set name, symbol_table
|
54
|
+
end
|
55
|
+
if the_collection.is_a? Symbols
|
56
|
+
the_collection.send :read_collection if the_collection.all.empty?
|
57
|
+
the_collection # return_value
|
58
|
+
else
|
59
|
+
error "#{the_collection} is already a Class"
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def purge_collection
|
65
|
+
yml_file.delete
|
66
|
+
@contracts = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
=begin
|
70
|
+
cuts the Collection in `bunch_count` pieces. Each bunch is delivered to the block.
|
71
|
+
|
72
|
+
Sleeps for `sleeping time` between processing bunches
|
73
|
+
|
74
|
+
Returns count of created bunches
|
75
|
+
=end
|
76
|
+
def bunch( bunch_count = 50 , sleeping_time = 1)
|
77
|
+
en = self.each
|
78
|
+
the_size = en.size
|
79
|
+
i = 0
|
80
|
+
loop do
|
81
|
+
the_start = i * bunch_count
|
82
|
+
the_end = the_start + bunch_count
|
83
|
+
the_end = the_size -1 if the_end >= the_size
|
84
|
+
it = the_start .. the_end
|
85
|
+
yield it.map{|x| en.next rescue nil}.compact
|
86
|
+
break if the_end == the_size -1
|
87
|
+
i+=1
|
88
|
+
sleep sleeping_time
|
89
|
+
end
|
90
|
+
i -1 # return counts of bunches
|
91
|
+
end
|
92
|
+
|
93
|
+
def read_collection
|
94
|
+
if yml_file.exist?
|
95
|
+
contracts.merge! YAML.load_file yml_file rescue contracts
|
96
|
+
else
|
97
|
+
yml_file.open( "w"){}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def store_collection
|
102
|
+
yml_file.open( 'w' ){|f| f.write @contracts.to_yaml}
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_contract symbol, contract
|
106
|
+
if symbol.is_a? String
|
107
|
+
symbol.to_sym
|
108
|
+
elsif symbol.is_a? Symbol
|
109
|
+
symbol
|
110
|
+
else
|
111
|
+
symbol.to_i
|
112
|
+
end
|
113
|
+
# ensure that evey Sybmol::xxx.yyy entry has a description
|
114
|
+
contract.description = contract.to_human[1..-2] if contract.description.nil?
|
115
|
+
# overwrite contract if existing
|
116
|
+
contracts[ symbol ] = contract.essential
|
117
|
+
store_collection
|
118
|
+
end
|
119
|
+
|
120
|
+
def remove_contract symbol
|
121
|
+
@contracts.delete symbol
|
122
|
+
store_collection
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
def to_human
|
127
|
+
self.to_s.split("::").last
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
module Unspecified
|
133
|
+
extend Symbols
|
134
|
+
end
|
135
|
+
|
136
|
+
end # module Symbols
|
137
|
+
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,52 @@
|
|
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
|
+
|
10
|
+
@contracts ||= { #super.merge(
|
11
|
+
stoxx_straddle: IB::Straddle.build( from: IB::Symbols::Index.stoxx, strike: 3000,
|
12
|
+
expiry: IB::Symbols::Futures.next_expiry, trading_class: 'OESX') ,
|
13
|
+
stoxx_calendar: IB::Calendar.build( from: IB::Symbols::Index.stoxx, strike: 3000, back: '2m' ,
|
14
|
+
front: IB::Symbols::Futures.next_expiry, trading_class: 'OESX'),
|
15
|
+
stoxx_butterfly: IB::Butterfly.fabricate( Symbols::Options.stoxx.merge( strike: 3300), front: 3250, back: 3350 ),
|
16
|
+
stoxx_vertical: IB::Vertical.build( from: IB::Symbols::Index.stoxx, sell: 3000, buy: 3500, right: :put,
|
17
|
+
expiry: IB::Symbols::Futures.next_expiry, trading_class: 'OESX'),
|
18
|
+
zn_calendar: IB::Calendar.fabricate( IB::Symbols::Futures.zn, '3m') ,
|
19
|
+
|
20
|
+
dbk_straddle: Bag.new( symbol: 'DBK', currency: 'EUR', exchange: 'DTB', combo_legs:
|
21
|
+
[ ComboLeg.new( con_id: 270581032 , action: :buy, exchange: 'DTB', ratio: 1), #DBK Dez20 2018 C
|
22
|
+
ComboLeg.new( con_id: 270580382, action: :buy, exchange: 'DTB', ratio: 1 ) ], #DBK Dez 20 2018 P
|
23
|
+
description: 'Option Straddle: Deutsche Bank(20)[Dez 2018]'
|
24
|
+
),
|
25
|
+
ib_mcd: Bag.new( symbol: 'IBKR,MCD', currency: 'USD', combo_legs:
|
26
|
+
[ ComboLeg.new( con_id: 43645865, action: :buy, ratio: 1), # IKBR STK
|
27
|
+
ComboLeg.new( con_id: 9408, action: :sell,ratio: 1 ) ], # MCD STK
|
28
|
+
description: 'Stock Spread: Buy Interactive Brokers, sell Mc Donalds'
|
29
|
+
),
|
30
|
+
|
31
|
+
vix_calendar: Bag.new( symbol: 'VIX', currency: 'USD', exchange: 'CFE', combo_legs:
|
32
|
+
[ ComboLeg.new( con_id: 256038899, action: :buy, exchange: 'CFE', ratio: 1), # VIX FUT 201708
|
33
|
+
ComboLeg.new( con_id: 260564703, action: :sell, exchange: 'CFE', ratio: 1 ) ], # VIX FUT 201709
|
34
|
+
description: 'VixFuture Calendar-Spread August - September 2017'
|
35
|
+
),
|
36
|
+
wti_coil: Bag.new( symbol: 'WTI', currency: 'USD', exchange: 'SMART', combo_legs:
|
37
|
+
[ ComboLeg.new( con_id: 55928698, action: :buy, exchange: 'IPE', ratio: 1), # WTI future June 2017
|
38
|
+
ComboLeg.new( con_id: 55850663, action: :sell, exchange: 'IPE', ratio: 1 ) ], # COIL future June 2017
|
39
|
+
description: 'Smart Future Spread WTI - COIL (June 2017) '
|
40
|
+
),
|
41
|
+
wti_brent: Bag.new( symbol: 'CL.BZ', currency: 'USD', exchange: 'NYMEX', combo_legs:
|
42
|
+
[ ComboLeg.new( con_id: 47207310, action: :buy, exchange: 'NYMEX', ratio: 1), # CL Dec'16 @NYMEX
|
43
|
+
ComboLeg.new( con_id: 47195961, action: :sell, exchange: 'NYMEX', ratio: 1 ) ], #BZ Dec'16 @NYMEX
|
44
|
+
description: ' WTI - Brent Spread (Dez. 2016)'
|
45
|
+
)
|
46
|
+
}
|
47
|
+
# )
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
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
|