ib-symbols 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This script connects to IB API and subscribes to L2 (depth of market) data for
4
+ # specific symbols
5
+
6
+ require 'bundler/setup'
7
+ require 'ib/symbols'
8
+
9
+ # Definition of what we want L2 data for. We have to keep track of what ticker id
10
+ # corresponds to what symbol ourselves, because the ticks don't include any other
11
+ # identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
12
+ market = {123 => IB::Symbols::Stocks[:wfc],
13
+ 456 => IB::Symbols::Futures[:es],
14
+ 789 => IB::Symbols::Forex[:gbpusd]
15
+ }
16
+
17
+ # First, connect to IB TWS.
18
+ ib = IB::Connection.new client_id: 1112, port: 4002 do | gw | #, :port => 7496 # TWS
19
+
20
+ # Subscribe to TWS alerts/errors
21
+ gw.subscribe(:Alert) { |msg| puts msg.to_human }
22
+
23
+ # Subscribe to MarketDepth events.
24
+ gw.subscribe(:MarketDepth) do |msg|
25
+ puts market[msg.request_id].description + ": " + msg.to_human
26
+ end
27
+
28
+ # Set log level
29
+ gw.logger.level = Logger::FATAL # DEBUG #FATAL
30
+
31
+ end
32
+ # Now we actually request L2 market data for the symbols we're interested in.
33
+ market.each_pair do |id, contract|
34
+ ib.send_message :RequestMarketDepth,
35
+ :id => id,
36
+ :contract => contract,
37
+ :num_rows => 5
38
+ end
39
+
40
+ puts "\nSubscribed to market data"
41
+ puts "\n******** Press <Enter> to cancel... *********\n\n"
42
+ STDIN.gets
43
+ puts "Cancelling market data subscription.."
44
+
45
+ market.each_pair { |id, contract| ib.send_message :CancelMarketDepth, :id => id }
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # The Head Time Stamp -Request returns the first available date for historical data requests
4
+
5
+ require 'bundler/setup'
6
+ require 'ib/symbols'
7
+
8
+ # First, connect to IB TWS and subscribe for events.
9
+ ib = IB::Connection.new :client_id => 1112 do | gw | #, :port => 7497 # TWS
10
+
11
+ # Subscribe to TWS alerts/errors
12
+ gw.subscribe(:Alert, :HeadTimeStamp) { |msg| puts msg.to_human }
13
+ # Set log level
14
+ gw.logger.level = Logger::FATAL # DEBUG -- INFO -- WARN -- ERROR -- FATAL
15
+
16
+ end
17
+ #
18
+ # We demonstrate it with Apple
19
+ #
20
+
21
+ ib.send_message :RequestHeadTimeStamp, contract: IB::Symbols::Stocks.aapl
22
+ ib.wait_for :HeadTimeStamp
23
+
24
+
25
+ puts " First datatset for #{IB::Symbols::Stocks.aapl.description} : #{ib.received[:HeadTimeStamp].date.join( " " )} "
26
+ Thread.new do
27
+ sleep 1
28
+ puts "\n******** Press <Enter> to quit *********\n\n"
29
+ end
30
+ STDIN.gets
31
+ puts "\n *** canceling Reqest ..."
32
+ ib.send_message :CancelHeadTimeStamp
33
+ # ..
34
+ puts "Printing all gathered data \n\n"
35
+ pp ib.received[ :HeadTimeStamp ]
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This script downloads historic data for specific symbols from IB
4
+
5
+ require 'bundler/setup'
6
+ require 'ib/symbols'
7
+
8
+ # Definition of what we want data for. We have to keep track of what ticker id
9
+ # corresponds to what symbol ourselves, because the ticks don't include any other
10
+ # identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
11
+ # Predefined Symbol-definitions --> lib/ib/symbols
12
+ contracts = {123 => IB::Symbols::Futures.mini_dax,
13
+ 456 => IB::Stock.new( symbol: 'BAS', currency: 'EUR') , # BASF
14
+ 789 => IB::Symbols::Forex.eurusd
15
+ }
16
+
17
+ # Connect to IB TWS.
18
+ #ib = IB::Connection.new( :client_id => 1102, port: 7496, host: '10.222.148.177' ) do | gw |
19
+ ib = IB::Connection.new :client_id => 1112, :port => 7496 do | gw | #, :port => 7497 # TWS
20
+
21
+ # Subscribe to TWS alerts/errors
22
+ gw.subscribe(:Alert, :ManagedAccounts) { |msg| puts msg.to_human }
23
+
24
+ # Subscribe to HistoricalData incoming events. The code passed in the block
25
+ # will be executed when a message of that type is received, with the received
26
+ # message as its argument. In this case, we just print out the data.
27
+ #
28
+ # Note that we have to look the ticker id of each incoming message
29
+ # up in local memory to figure out what it's for.
30
+ gw.subscribe(IB::Messages::Incoming::HistoricalData) do |msg|
31
+ puts contracts[msg.request_id].description + ": #{msg.count} items:"
32
+ msg.results.each { |entry| puts " #{entry}" }
33
+ end
34
+ end
35
+
36
+ # Now we actually request historical data for the symbols we're interested in. TWS will
37
+ # respond with a HistoricalData message, which will be processed by the code above.
38
+ contracts.each_pair do |request_id, contract|
39
+ ib.send_message IB::Messages::Outgoing::RequestHistoricalData.new(
40
+ :request_id => request_id,
41
+ :contract => contract,
42
+ :end_date_time => Time.now.to_ib,
43
+ :duration => '1 D', # ?
44
+ :bar_size => :hour1, # IB::BAR_SIZES.key(:hour)?
45
+ :what_to_show => :trades,
46
+ :use_rth => 0,
47
+ :keep_up_todate => 0)
48
+ end
49
+
50
+ # IB does not send any indication when all historic data is done being delivered.
51
+ # So we need to interrupt manually when our request is answered.
52
+ puts "\n******** Press <Enter> to exit... *********\n\n"
53
+ STDIN.gets
54
+
55
+ __END__
56
+ ## EXTRACTED FROM THE PYTHON IMPLEMENTATION (Jan 2018)
57
+ contract:Contract - This object contains a description of the contract for which
58
+ market data is being requested.
59
+ endDateTime:str - Defines a query end date and time at any point during the past 6 mos.
60
+ Valid values include any date/time within the past six months in the format:
61
+ yyyymmdd HH:mm:ss ttt
62
+ where "ttt" is the optional time zone.
63
+ durationStr:str - Set the query duration up to one week, using a time unit
64
+ of seconds, days or weeks. Valid values include any integer followed by a space
65
+ and then S (seconds), D (days) or W (week). If no unit is specified, seconds is used.
66
+ barSizeSetting:str - Specifies the size of the bars that will be returned (within IB/TWS listimits).
67
+ Valid values include:
68
+ 1 sec
69
+ 5 secs
70
+ 15 secs
71
+ 30 secs
72
+ 1 min
73
+ 2 mins
74
+ 3 mins
75
+ 5 mins
76
+ 15 mins
77
+ 30 mins
78
+ 1 hour
79
+ 1 day
80
+ whatToShow:str - Determines the nature of data beinging extracted. Valid values include:
81
+ TRADES
82
+ MIDPOINT
83
+ BID
84
+ ASK
85
+ BID_ASK
86
+ HISTORICAL_VOLATILITY
87
+ OPTION_IMPLIED_VOLATILITY
88
+
89
+ useRTH:int - Determines whether to return all data available during the requested time span,
90
+ or only data that falls within regular trading hours. Valid values include:
91
+
92
+ 0 - all data is returned even where the market in question was outside of its
93
+ regular trading hours.
94
+ 1 - only data within the regular trading hours is returned, even if the
95
+ requested time span falls partially or completely outside of the RTH.
96
+ formatDate: int - Determines the date format applied to returned bars. validd values include:
97
+ 1 - dates applying to bars returned in the format: yyyymmdd{space}{space}hh:mm:dd
98
+ 2 - dates are returned as a long integer specifying the number of seconds since
99
+ 1/1/1970 GMT.
100
+ chartOptions:TagValueList - For internal use only. Use default value XYZ. """
101
+
102
+
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This script connects to IB API and subscribes to market data for specific symbols
4
+
5
+ require 'bundler/setup'
6
+ require 'ib-api'
7
+ require 'ib/symbols'
8
+
9
+ COUNT_OF_EVENTS = 20
10
+ # Definition of what we want market data for. We have to keep track of what ticker id
11
+ # corresponds to what symbol ourselves, because the ticks don't include any other
12
+ # identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
13
+ # (note: the forex symbols used here MUST be defined in lib/ib/symbols/forex.rb)
14
+ market = {123 => IB::Symbols::Forex.gbpusd ,
15
+ 456 => IB::Symbols::Forex.eurusd ,
16
+ 789 => IB::Symbols::Forex.usdcad }
17
+
18
+ # connect to IB TWS.
19
+
20
+ counter = 0
21
+
22
+ ib = IB::Connection.new( :client_id => 1112) do | gw | #, :port => 7496 # TWS)
23
+ ## Subcribe to forseable events before the connection is completed
24
+ ## Subscribe to TWS alerts/errors
25
+ gw.subscribe(:Alert) { |msg| puts msg.to_human }
26
+ gw.logger.level = Logger::FATAL
27
+
28
+ # Subscribe to TickerPrice and TickerSize events. The code passed in the block will
29
+ # be executed when a message of that type is received, with the received message as its
30
+ # argument. In this case, we just print out the tick. NB: The description field is not
31
+ # from IB TWS. It is defined locally in forex.rb, and is just arbitrary text.
32
+
33
+ gw.subscribe(:TickRequestParameters, :TickPrice, :TickSize, :TickGeneric) do |msg|
34
+ puts market[msg.ticker_id].description + ": " + msg.to_human
35
+ counter = counter + 1
36
+ if counter == COUNT_OF_EVENTS
37
+ puts "\nCancelling market data subscription.."
38
+ market.each_pair { |id, _| ib.send_message :CancelMarketData, :id => id }
39
+ puts "Generally, the TWS sends additional TickEvents after the subscription is cancelled ... \n\n"
40
+ Thread.new do
41
+ sleep 1
42
+ puts "\n******** Press <Enter> to quit *********\n\n"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ # Now we actually request market data for the symbols we're interested in.
48
+ ib.send_message :RequestMarketDataType, :market_data_type => :delayed
49
+ market.each_pair do |id, contract|
50
+ ib.send_message :RequestMarketData, :id => id, :contract => contract
51
+ end
52
+
53
+ puts "\nSubscribed to market data"
54
+ puts "\n********* Receiving #{COUNT_OF_EVENTS} TickEvents, then canceling the subscription ***** \n\n"
55
+ STDIN.gets
56
+
57
+ #@market.each_pair { |id, _| ib.send_message :CancelMarketData, :id => id }
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This script subscribes to market data for a list of Options
4
+
5
+ require 'bundler/setup'
6
+ require 'ib/symbols'
7
+ COUNT_OF_EVENTS = 20
8
+ # Definition of what we want market data for. We have to keep track of what ticker id
9
+ # corresponds to what symbol ourselves, because the ticks don't include any other
10
+ # identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
11
+ contracts = [ IB::Symbols::Options.ge, IB::Symbols::Options.spy,
12
+ IB::Symbols::Options.aapl]
13
+ list_of_ids =[]
14
+
15
+ counter = 0
16
+
17
+ #contracts = [ IB::Option.new( symbol: 'ESTX50', exchange:'DTB', multiplier: 10, currency: 'EUR', strike: 3200, expiry: '202012', right: :put) ,IB::Symbols::Options.ge ]
18
+ # First, connect to IB TWS. Arbitrary :client_id is used to identify your script
19
+ ib = IB::Connection.new( client_id: 1116, port: 7496) do | gw| #, :port => 7496 # TWS
20
+
21
+ ## Subscribe to TWS alerts/errors
22
+ gw.subscribe(:Alert, :ManagedAccounts) { |msg| puts msg.to_human }
23
+ # set the log level
24
+ gw.logger.level = Logger::FATAL
25
+ # Subscribe to Ticker... events. The code passed in the block will be executed when
26
+ # any message of that type is received, with the received message as its argument.
27
+ # In this case, we just print out the tick.
28
+ #
29
+ # (N.B. The description field is not from IB TWS. It is defined
30
+ # locally in forex.rb, and is just arbitrary text.)
31
+ gw.subscribe(:TickPrice, :TickSize, :TickOption, :TickString, :TickRequestParameters) do |msg|
32
+ counter = counter + 1
33
+ if counter == COUNT_OF_EVENTS
34
+ puts "Cancelling market data subscription.."
35
+ list_of_ids.each { |id| ib.send_message :CancelMarketData, :id => id }
36
+ puts "Generally, the TWS sends additional TickEvents after the subscription is cancelled ... \n\n"
37
+ Thread.new do
38
+ sleep 1
39
+ puts "\n******** Press <Enter> to quit *********\n\n"
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ # Now we actually request market data for the symbols we're interested in.
46
+ #
47
+ # ### ticklist-values : lib/ib/messages/outgoing/request_marketdata.rb
48
+ ib.send_message :RequestMarketDataType, :market_data_type => :delayed
49
+ list_of_ids = contracts.map do |contract|
50
+ ib.send_message :RequestMarketData, :contract => contract , tick_list: [100,101,106]
51
+ end
52
+ # we modify contracts: { ticker_id => Contract } ( Will be used in the subscrption thread )
53
+ contracts = list_of_ids.zip( contracts ).to_h
54
+ puts "Contracts: \n\t #{contracts.map{|x,y| "#{x} :: #{y.to_human}"}.join("\n\t")} "
55
+ puts "\nSubscribed to market data"
56
+ puts "\n******** Press <Enter> to cancel subscriptions *********\n\n"
57
+ STDIN.gets
58
+ puts "Cancelling market data subscription.."
59
+
60
+ contracts.each_with_index { | contract, i| ib.send_message :CancelMarketData, :id => i+1 }
61
+
62
+ puts "\n******** Press <Enter> to quit.. *********\n\n"
63
+ STDIN.gets
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Subscribe to real time data for specific symbol from IB
4
+
5
+ require 'bundler/setup'
6
+ require 'ib/symbols'
7
+
8
+ contracts = {1 => IB::Symbols::Stocks[:vxx],
9
+ 9 => IB::Symbols::Forex[:gbpusd]
10
+ }
11
+
12
+ # Connect to IB TWS.
13
+ ib = IB::Connection.new :client_id => 1112 do | gw | #, :port => 7497 # TWS
14
+
15
+ # Subscribe to TWS alerts/errors
16
+ gw.subscribe(:Alert) { |msg| puts msg.to_human }
17
+
18
+ # Subscribe to RealTimeBar incoming events. We have to use message request_id
19
+ # to figure out what contract it's for.
20
+ gw.subscribe(IB::Messages::Incoming::RealTimeBar) do |msg|
21
+ puts contracts[msg.request_id].description + ": #{msg.to_human}"
22
+ end
23
+ end
24
+ contracts.each_pair do |request_id, contract|
25
+ ib.send_message IB::Messages::Outgoing::RequestRealTimeBars.new(
26
+ :request_id => request_id,
27
+ :contract => contract,
28
+ # :bar_size => 5, # Only 5 secs bars supported (hard coded in messages/outgoing/bar_requests)
29
+ :data_type => :trades, # possible values: :trades, :bid, :ask , :midpoint
30
+ :use_rth => false)
31
+ end
32
+
33
+ # So we need to interrupt manually when we do not want any more quotes.
34
+ puts "\n******** Press <Enter> to exit... *********\n\n"
35
+ STDIN.gets
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+ ##
3
+ ## This script connects to IB API and collects snaphot Data for given Contracts
4
+ ##
5
+ #
6
+ class Snapshot
7
+ def initialize
8
+ @contracts = Array.new
9
+ @prices = Hash.new
10
+ end
11
+
12
+
13
+ def add_contract *contract
14
+ contract.each do |c|
15
+ @contracts << c
16
+ end
17
+ end
18
+
19
+ def print_results
20
+ # @prices.each do |x,y|
21
+ # STDOUT.print " #{@contracts[x][:display_text] } \t" +
22
+ # y.collect{|x,y| "#{x}: #{y}"}.join(" \n\t\t\t ") +" \n"
23
+ # enda
24
+ @prices.each do |a,b|
25
+ contract = b.delete :contract
26
+ if contract.present?
27
+ puts contract.to_human
28
+ print b.inspect # [:bid_price], b[:ask_price], b[:high], b[:low], b[:close_price]
29
+ print"\n"
30
+ end
31
+ end
32
+ end
33
+
34
+
35
+ def process
36
+ ib = IB::Connection.current
37
+
38
+ count = @contracts.size
39
+ ib.subscribe(:Alert) do |msg|
40
+ if msg.code == 354 # Requested market data is not subscribed
41
+ count -=1 # wir zählen den Counter runter, so dass
42
+ puts "No Marketdata Subscription" # am Ende die Orderantwort ausgelöst wird
43
+ else
44
+ puts msg.message # unhandled Alert
45
+ end
46
+ end
47
+ # we collect price-events in @prices-Hash
48
+ ib.subscribe( :TickPrice){ |msg| @prices[msg.ticker_id][msg.type]=msg.price }
49
+ # When finished, print the results
50
+ ib.subscribe( :TickSnapshotEnd){ count -=1; print_results if count.zero? }
51
+ # fire the request
52
+ ib.send_message :RequestMarketDataType, :market_data_type => :delayed
53
+
54
+ @contracts.each do | contract |
55
+ request_id = ib.send_message :RequestMarketData, :contract => contract, :snapshot => 1
56
+ # connect contracts to prices
57
+ @prices[request_id] = {:contract => contract}
58
+ end
59
+ end
60
+
61
+ end # class
62
+
63
+ #### here it starts #######
64
+
65
+ require 'bundler/setup'
66
+ require 'ib/symbols'
67
+
68
+ # # Connect to IB TWS
69
+ IB::Connection.new client_id: 1112, port: 7496 do | gw | # , :port => 7497 do |gw|
70
+
71
+ # Set log level
72
+ gw.logger.level = Logger::FATAL
73
+ end
74
+
75
+ s = Snapshot.new
76
+ s.add_contract IB::Stock.new symbol: 'FAST', :con_id => 269120, :exchange => 'SMART'
77
+ s.add_contract IB::Stock.new :symbol => 'IBM'
78
+ s.add_contract IB::Symbols::Forex.eurusd
79
+ s.process
80
+
81
+ Thread.new do
82
+ sleep 3
83
+ puts "\n******** Press <Enter> to quit *********\n\n"
84
+ end
85
+ STDIN.gets
86
+ puts "done."
87
+
88
+
89
+ =begin
90
+ Expected Output
91
+
92
+ Market data farm is connecting:usfarm
93
+ Market data farm connection is OK:cashfarm
94
+ Market data farm is connecting:usfarm
95
+ Market data farm connection is OK:usfarm
96
+ Requested market data is not subscribed. Displaying delayed market data...
97
+ Requested market data is not subscribed. Displaying delayed market data...
98
+ <Stock: FAST USD>
99
+ {:delayed_bid=>0.578e2, :delayed_ask=>0.5784e2, :delayed_last=>0.5781e2, :delayed_high=>0.584e2, :delayed_low=>0.573e2, :delayed_close=>0.5737e2, :delayed_open=>0.0}
100
+ <Stock: IBM USD>
101
+ {:delayed_bid=>0.16083e3, :delayed_ask=>0.16085e3, :delayed_last=>0.16085e3, :delayed_high=>0.16125e3, :delayed_low=>0.15852e3, :delayed_close=>0.15812e3, :delayed_open=>0.0}
102
+ <Contract: EUR forex IDEALPRO USD>
103
+ {:high=>0.123835e1, :low=>0.12316e1, :close_price=>0.12368e1, :bid_price=>0.123218e1, :ask_price=>0.123219e1}
104
+
105
+ =end