Skip to content
This repository was archived by the owner on Aug 10, 2021. It is now read-only.

Request Marketdata

topofocus edited this page May 8, 2018 · 21 revisions

The API offers the :RequestMarketData` message to address the gathering of market-related information

> C.send_message :RequestMarketData, contract: IB::Symbols::Stocks.wfc, snapshot: true
# or
> C.send_message :RequestMarketData, contract: IB::Symbols::Stocks.wfc, ticklist: [106,107]

where items in :ticklist further specify the request (details in messages/outgoing/request_marketdata). Most significant are:

 100 - Option Volume (stocks) -> returned Tick-IDs: 29, 30
 101 - Option Open Interest (stocks)             -> 27, 28
 104 - Historical Volatility                     -> 23
 105 - Average Opt Volume
 106 - Option Implied Volatility (impvolat)      -> 24
 107                             (climpvlt)        
 411 - Realtime Historical Volatility            -> 58

The example dir contains a simple market-data script.

A more condensed approach using the gateway:

require 'bundler/setup'
require 'ib-gateway'
IB::Gateway.new client_id:1134
if ( ib = IB::Gateway.tws).present?
  contracts = [  IB::Symbols::Futures.es,  IB::Symbols::Forex.gbpusd ]
  ib.subscribe(:TickPrice, :TickSize, :TickString) do |msg|
    puts contracts.find{|x| x.con_id == msg.ticker_id}.symbol + ": " + msg.to_human + "\t (press enter to cancel)"
  end
  contracts.each do | contract|
    contract.verify! 
    ib.send_message :RequestMarketData, :id => contract.con_id, :contract => contract
  end

  STDIN.gets
else
  puts 'No TWS'
end

This small script follows exact the paradigm of ib-ruby. It sends messages and allocates the received information accordingly. Its not very rubish, though.

The data gathered through send_message :RequestMarketData are related to IB::Contract. It seems natural to assign them directly. IB::Contract offers two link-possibilities: :bars and misc, which offers a more sophisticated, object orientated solution.

Assign snapshot-data to :bars association of IB::Contract

Extend IB::Contract with a method to assign the gathered data to the :bars-association

module IB
    class Contract
	def associate_ticdata

		tws=  IB::Gateway.tws 		 # get the initialized ib-ruby instance
		the_id =  nil
		finalize= false
		#  switch to delayed data
		tws.send_message :RequestMarketDataType, :market_data_type => :delayed

		s_id = tws.subscribe(:TickSnapshotEnd) { |msg|	finalize = true	if msg.ticker_id == the_id }
				
		sub_id = tws.subscribe(:TickPrice, :TickSize,  :TickGeneric) do |msg|
			    self.bars << msg.the_data if msg.ticker_id == the_id 
			end

		# initialize »the_id« that is used to identify the received tick messages
		# by firing the market data request
		the_id = tws.send_message :RequestMarketData,  contract: self , snapshot: true 

		#keep the method-call running until the request finished
		#and cancel subscriptions to the message handler.
		Thread.new do 
                  i=0; loop{ i+=1; sleep 0.1; break if finalize || y > 1000 }
                  tws.unsubscribe sub_id 
                  tws.unsubscribe s_id
                  puts "#{symbol} data gathered" 
                end  # method returns the (running) thread

	end # def 
    end # class
end # module

Call it with a list of contract-samples:

require 'bundler/setup'
require 'ib-gateway'
  IB::Gateway.new  get_account_data: false, client_id: 1002, port: 4002 do |ib|
    ib.subscribe(:Alert ) { |msg| puts msg.to_human }
  end
  selected_stocks = []
  ['T', 'VZ', 'BMY', 'DE', 'KO', 'CAT', 'FL', 'IBM', 'K','GE'].each do | stock |
        IB::Stock.new( symbol: stock ).verify{| contract | selected_stocks << contract } 
  end
  threads = selected_stocks.map &:associate_ticdata 
	
  threads.each &:join   # wait until all processes terminated

puts "FINISHED"
puts "gathered data:"
puts selected_stocks.map{|x| "#{x.symbol} --> #{x.bars.inspect} "}.join("\n")

OUTPUT

VZ data gathered
(...)
FINISHED
gathered data:
T --> [{:tick_type=>66, :price=>0.3221e2, :size=>128, :can_auto_execute=>0}, {:tick_type=>67, :price=>0.3222e2, :size=>155, :can_auto_execute=>0}, {:tick_type=>68, :price=>0.3221e2, :size=>100, :can_auto_execute=>0}, {:tick_type=>72, :price=>0.3227e2, :size=>0, :can_auto_execute=>0}, {:tick_type=>73, :price=>0.3182e2, :size=>0, :can_auto_execute=>0}, {:tick_type=>74, :size=>53769}, {:tick_type=>75, :price=>0.3194e2, :size=>0, :can_auto_execute=>0}, {:tick_type=>76, :price=>0.0, :size=>0, :can_auto_execute=>0}] 
VZ --> [{:tick_type=>66, :price=>0.4827e2, :size=>30, :can_auto_execute=>0}
(...)

Clone this wiki locally