# The Futures constant is currently for testing purposes. It guesses the front month # currency future using a crude algorithm that does not take into account expiry/rollover day. # This will be valid most of the time, but near/after expiry day the next quarter's contract # takes over as the volume leader. # # # Note that the :description field is particular to ib-ruby, and is NOT part of the standard TWS API. # It is never transmitted to IB. It's purely used clientside, and you can store any arbitrary string that # you may find useful there. # module IB module Symbols # Get the next valid quarter month >= today, for finding the # front month of quarterly futures. # # N.B. This will not work as expected near/after expiration during that month, as # volume rolls over to the next quarter even though the current month is still valid! def self.next_quarter_month(time) sprintf("%02d", [3, 6, 9, 12].find { |month| month >= time.month }) end def self.next_quarter_year(time) if self.next_quarter_month(time).to_i < time.month time.year + 1 else time.year end end # # WARNING: This is currently broken. It returns the next # quarterly expiration month after the current month. Many futures # instruments have monthly contracts for the near months. This # method will not work for such contracts; it will return the next # quarter after the current month, even though the present month # has the majority of the trading volume. # # For example, in early November of 2011, many contracts have the # vast majority of their volume in the Nov 2011 contract, but this # method will return the Dec 2011 contract instead. # def self.next_expiry(time) "#{ self.next_quarter_year(time) }#{ self.next_quarter_month(time) }" end # # Convenience method; generates a Models::Contract instance for a futures # contract with the given parameters. # # If expiry is nil, it will use the end month of the current # quarter. This will be wrong for most contracts most of the time, # since most contracts have the majority of their volume in a # nearby intraquarter month. # # It is recommended that you specify an expiration date manually # until next_expiry is fixed. Expiry should be a string in the # format "YYYYMM", where YYYY is the 4 digit year and MM is the 2 # digit month. For example, November 2011 is "201111". # def self.future(base_symbol, exchange, currency, description="", expiry=nil) Models::Contract.new(:symbol => base_symbol, :expiry => expiry.nil? ? self.next_expiry(Time.now) : expiry, :exchange => exchange, :currency => currency, :sec_type => SECURITY_TYPES[:future], :description => description) end Futures ={ :ym => Models::Contract.new(:symbol => "YM", :expiry => self.next_expiry(Time.now), :exchange => "ECBOT", :currency => "USD", :sec_type => SECURITY_TYPES[:future], :description => "Mini Dow Jones Industrial"), :es => Models::Contract.new(:symbol => "ES", :expiry => self.next_expiry(Time.now), :exchange => "GLOBEX", :currency => "USD", :sec_type => SECURITY_TYPES[:future], :multiplier => 50, :description => "E-Mini S&P 500"), :gbp => Models::Contract.new(:symbol => "GBP", :expiry => self.next_expiry(Time.now), :exchange => "GLOBEX", :currency => "USD", :sec_type => SECURITY_TYPES[:future], :multiplier => 62500, :description => "British Pounds"), :eur => Models::Contract.new(:symbol => "EUR", :expiry => self.next_expiry(Time.now), :exchange => "GLOBEX", :currency => "USD", :sec_type => SECURITY_TYPES[:future], :multiplier => 12500, :description => "Euro FX"), :jpy => Models::Contract.new(:symbol => "JPY", :expiry => self.next_expiry(Time.now), :exchange => "GLOBEX", :currency => "USD", :sec_type => SECURITY_TYPES[:future], :multiplier => 12500000, :description => "Japanese Yen"), :hsi => Models::Contract.new(:symbol => "HSI", :expiry => self.next_expiry(Time.now), :exchange => "HKFE", :currency => "HKD", :sec_type => SECURITY_TYPES[:future], :multiplier => 50, :description => "Hang Seng Index") } end end