Class: IB::Messages::Incoming::AbstractMessage

Inherits:
AbstractMessage show all
Defined in:
lib/ib/messages/incoming/abstract_message.rb

Direct Known Subclasses

AbstractTick

Instance Attribute Summary collapse

Attributes inherited from AbstractMessage

#created_at, #data

Instance Method Summary collapse

Methods inherited from AbstractMessage

data_map, message_id, #message_id, message_type, #message_type, properties?, #request_id, #to_human, version

Constructor Details

#initialize(source) ⇒ AbstractMessage

Create incoming message from a given source (IB Socket or data Hash)



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/ib/messages/incoming/abstract_message.rb', line 29

def initialize source
	@created_at = Time.now
	if source.is_a?(Hash)  # Source is a @data Hash
		@data = source
		@buffer =[] # initialize empty buffer, indicates a successful initializing
	else
		@buffer = source
			### DEBUG  DEBUG  DEBUG  RAW STREAM                            ###############
			#  if uncommented, the raw-input from the tws is included in the logging
##		  puts "BUFFER :> #{buffer.inspect} "
			### DEBUG  DEBUG  DEBUG  RAW STREAM                            ###############
		@data = Hash.new
		self.load
	end
end

Instance Attribute Details

#bufferObject

is an array



15
16
17
# File 'lib/ib/messages/incoming/abstract_message.rb', line 15

def buffer
  @buffer
end

Instance Method Details

#check_version(actual, expected) ⇒ Object



21
22
23
24
25
26
# File 'lib/ib/messages/incoming/abstract_message.rb', line 21

def check_version actual, expected
	unless actual == expected || expected.is_a?(Array) && expected.include?(actual)
		puts self.class.name
		error "Unsupported version #{actual} received, expected #{expected}"
	end
end

#loadObject

Every message loads received message version first Override the load method in your subclass to do actual reading into @data.



58
59
60
61
62
63
64
# File 'lib/ib/messages/incoming/abstract_message.rb', line 58

def load
	unless self.class.version.zero?
		@data[:version] = buffer.read_int
		check_version @data[:version], self.class.version
	end
	simple_load
end

#load_map(*map) ⇒ Object

Load @data from the buffer according to the given data map.

map is a series of Arrays in the format of

[ :name, :type ], [  :group, :name, :type]

type identifiers must have a corresponding read_type method on the buffer-class (read_int, etc.). group is used to lump together aggregates, such as Contract or Order fields



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ib/messages/incoming/abstract_message.rb', line 72

def load_map(*map)
	map.each do |instruction|
		# We determine the function of the first element
		head = instruction.first
		case head
		when Integer # >= Version condition: [ min_version, [map]]
			load_map *instruction.drop(1) if version >= head

		when Proc # Callable condition: [ condition, [map]]
			load_map *instruction.drop(1) if head.call

		when true # Pre-condition already succeeded!
			load_map *instruction.drop(1)

		when nil, false # Pre-condition already failed! Do nothing...

		when Symbol # Normal map
			group, name, type, block =
				if  instruction[2].nil? || instruction[2].is_a?(Proc)  # lambda's are Proc's
					[nil] + instruction # No group, [ :name, :type, (:block) ]
				else
					instruction # [ :group, :name, :type, (:block)]
				end
			begin
				data = @buffer.__send__("read_#{type}", &block)
			rescue IB::LoadError, NoMethodError => e
				error "Reading #{self.class}: #{e.class}: #{e.message}  --> Instruction: #{name}" , :reader, false
			end
			# debug	      puts data.inspect
			if group
				@data[group] ||= {}
				@data[group][name] = data
			else
				@data[name] = data
			end
		else
			error "Unrecognized instruction #{instruction}"
		end
	end
end

#simple_loadObject

more recent messages omit the transmission of a version thus just load the parameter-map



51
52
53
54
55
# File 'lib/ib/messages/incoming/abstract_message.rb', line 51

def simple_load
	load_map *self.class.data_map
rescue IB::Error  => e
	error "Reading #{self.class}: #{e.class}: #{e.message}", :load, e.backtrace
end

#valid?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'lib/ib/messages/incoming/abstract_message.rb', line 45

def valid?
	@buffer.empty?
end

#versionObject

Per message, received messages may have the different versions



17
18
19
# File 'lib/ib/messages/incoming/abstract_message.rb', line 17

def version # Per message, received messages may have the different versions
	@data[:version]
end