Class: IB::IB

Inherits:
Object
  • Object
show all
Defined in:
lib/ib-ruby/ib.rb

Constant Summary collapse

Tws_client_version =
27

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options_in = {}) ⇒ IB

Returns a new instance of IB.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/ib-ruby/ib.rb', line 75

def initialize(options_in = {})
  @options = {
    :ip => TWS_IP_ADDRESS,
    :port => TWS_PORT,
  }.merge(options_in)

  @connected = false
  @next_order_id = nil
  @server = Hash.new # information about server and server connection state

  # Message listeners.
  # Key is the message class to listen for.
  # Value is an Array of Procs. The proc will be called with the populated message instance as its argument when
  # a message of that type is received.
  @listeners = Hash.new { |hash, key|
    hash[key] = Array.new
  }


  #logger.debug("IB#init: Initializing...")

  self.open(@options)

end

Instance Attribute Details

#next_order_idObject (readonly)

Returns the value of attribute next_order_id.



73
74
75
# File 'lib/ib-ruby/ib.rb', line 73

def next_order_id
  @next_order_id
end

Instance Method Details

#closeObject



159
160
161
162
163
164
165
166
# File 'lib/ib-ruby/ib.rb', line 159

def close
  @server[:reader_thread].kill # Thread uses blocking I/O, so join is useless.
  @server[:socket].close()
  @server = Hash.new
  @@server_version = nil
  @connected = false
  #logger.debug("Disconnected.")
end

#dispatch(message) ⇒ Object

Send an outgoing message.

Raises:

  • (Exception)


189
190
191
192
193
194
195
# File 'lib/ib-ruby/ib.rb', line 189

def dispatch(message)
  raise Exception.new("dispatch() must be given an OutgoingMessages::AbstractMessage subclass") unless
    message.is_a?(OutgoingMessages::AbstractMessage)

  #logger.info("Sending message " + message.inspect)
  message.send(@server)
end

#open(options_in = {}) ⇒ Object

Raises:

  • (Exception)


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/ib-ruby/ib.rb', line 105

def open(options_in = {})
  raise Exception.new("Already connected!") if @connected

  opts = {
    :ip => "127.0.0.1",
    :port => "7496"
  }.merge(options_in)


  # Subscribe to the NextValidID message from TWS that is always
  # sent at connect, and save the id.
  self.subscribe(IncomingMessages::NextValidID, lambda {|msg|
                   @next_order_id = msg.data[:order_id]
                   #logger.info { "Got next valid order id #{@next_order_id}." }
                 })

  @server[:socket] = IBSocket.open(@options[:ip], @options[:port])
  #logger.info("* TWS socket connected to #{@options[:ip]}:#{@options[:port]}.")

  # Sekrit handshake.
  #logger.debug("\tSending client version #{Tws_client_version}..")

  @server[:socket].send(Tws_client_version)
  @server[:version] = @server[:socket].read_int
  @@server_version = @server[:version]
  @server[:local_connect_time] = Time.now()

  #logger.debug("\tGot server version: #{@server[:version]}.")

  # Server version >= 20 sends the server time back.
  if @server[:version] >= 20
    @server[:remote_connect_time] = @server[:socket].read_string
    #logger.debug("\tServer connect time: #{@server[:remote_connect_time]}.")
  end

  # Server version >= 3 wants an arbitrary client ID at this point. This can be used
  # to identify subsequent communications.
  if @server[:version] >= 3
    @server[:client_id] = SHA1.digest(Time.now.to_s + $$.to_s).unpack("C*").join.to_i % 999999999
    @server[:socket].send(@server[:client_id])
    #logger.debug("\tSent client id # #{@server[:client_id]}.")
  end

  #logger.debug("Starting reader thread..")
  Thread.abort_on_exception = true
  @server[:reader_thread] = Thread.new {
    self.reader
  }

  @connected = true
end

#server_versionObject

init



100
101
102
# File 'lib/ib-ruby/ib.rb', line 100

def server_version
  @server[:version]
end

#subscribe(messageClass, code) ⇒ Object

Subscribe to incoming message events of type messageClass. code is a Proc that will be called with the message instance as its argument.

Raises:

  • (Exception)


178
179
180
181
182
183
184
# File 'lib/ib-ruby/ib.rb', line 178

def subscribe(messageClass, code)
  raise(Exception.new("Invalid argument type (#{messageClass}, #{code.class}) - " +
                      " must be (IncomingMessages::AbstractMessage, Proc)")) unless
    messageClass <= IncomingMessages::AbstractMessage && code.is_a?(Proc)

  @listeners[messageClass].push(code)
end

#to_sObject



170
171
172
# File 'lib/ib-ruby/ib.rb', line 170

def to_s
  "IB Connector: #{ @connected ? "connected." : "disconnected."}"
end