ib-symbols 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.
@@ -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