ib-ruby 0.5.16 → 0.5.17
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.
- data/HISTORY +4 -0
- data/VERSION +1 -1
- data/lib/ib-ruby/connection.rb +11 -7
- data/lib/ib-ruby/messages/incoming.rb +31 -27
- data/lib/ib-ruby/models/order.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- metadata +2 -2
data/HISTORY
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.17
|
data/lib/ib-ruby/connection.rb
CHANGED
@@ -19,7 +19,7 @@ module IB
|
|
19
19
|
|
20
20
|
CLIENT_VERSION = 48 # Was 27 in original Ruby code
|
21
21
|
SERVER_VERSION = 53 # Minimal server version. Latest, was 38 in current Java code.
|
22
|
-
DEFAULT_OPTIONS = {:host =>
|
22
|
+
DEFAULT_OPTIONS = {:host =>'127.0.0.1',
|
23
23
|
:port => '4001', # IB Gateway connection (default)
|
24
24
|
#:port => '7496', # TWS connection, with annoying pop-ups
|
25
25
|
:client_id => nil, # Will be randomly assigned
|
@@ -45,7 +45,6 @@ module IB
|
|
45
45
|
@server = Hash.new
|
46
46
|
|
47
47
|
connect if @options[:connect]
|
48
|
-
start_reader if @options[:reader]
|
49
48
|
Connection.current = self
|
50
49
|
end
|
51
50
|
|
@@ -58,7 +57,7 @@ module IB
|
|
58
57
|
end
|
59
58
|
|
60
59
|
def connect
|
61
|
-
raise
|
60
|
+
raise "Already connected!" if connected?
|
62
61
|
|
63
62
|
# TWS always sends NextValidID message at connect - save this id
|
64
63
|
self.subscribe(:NextValidID) do |msg|
|
@@ -71,7 +70,7 @@ module IB
|
|
71
70
|
# Secret handshake
|
72
71
|
@server[:socket].send(CLIENT_VERSION)
|
73
72
|
@server[:version] = @server[:socket].read_int
|
74
|
-
raise
|
73
|
+
raise "TWS version >= #{SERVER_VERSION} required." if @server[:version] < SERVER_VERSION
|
75
74
|
|
76
75
|
@server[:local_connect_time] = Time.now()
|
77
76
|
@server[:remote_connect_time] = @server[:socket].read_string
|
@@ -86,6 +85,8 @@ module IB
|
|
86
85
|
log.info "Connected to server, version: #{@server[:version]}, connection time: " +
|
87
86
|
"#{@server[:local_connect_time]} local, " +
|
88
87
|
"#{@server[:remote_connect_time]} remote."
|
88
|
+
|
89
|
+
start_reader if @options[:reader] # Allows reconnect
|
89
90
|
end
|
90
91
|
|
91
92
|
alias open connect # Legacy alias
|
@@ -95,9 +96,11 @@ module IB
|
|
95
96
|
@reader_running = false
|
96
97
|
@server[:reader].join
|
97
98
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
if connected?
|
100
|
+
@server[:socket].close
|
101
|
+
@server = Hash.new
|
102
|
+
@connected = false
|
103
|
+
end
|
101
104
|
end
|
102
105
|
|
103
106
|
alias close disconnect # Legacy alias
|
@@ -152,6 +155,7 @@ module IB
|
|
152
155
|
else
|
153
156
|
raise ArgumentError.new "Only able to send outgoing IB messages"
|
154
157
|
end
|
158
|
+
raise "Not able to send messages, IB not connected!" unless connected?
|
155
159
|
message.send_to(@server)
|
156
160
|
end
|
157
161
|
|
@@ -55,8 +55,14 @@ module IB
|
|
55
55
|
@data.has_key?(:id) ? @data[:id] : super
|
56
56
|
end
|
57
57
|
|
58
|
+
def respond_to? method
|
59
|
+
getter = method.to_s.sub(/=$/, '').to_sym
|
60
|
+
@data.has_key?(method) || @data.has_key?(getter) || super
|
61
|
+
end
|
62
|
+
|
58
63
|
protected
|
59
64
|
|
65
|
+
# TODO: method compilation instead of method_missing
|
60
66
|
def method_missing method, *args
|
61
67
|
getter = method.to_s.sub(/=$/, '').to_sym
|
62
68
|
if @data.has_key? method
|
@@ -68,11 +74,6 @@ module IB
|
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
71
|
-
def respond_to? method
|
72
|
-
getter = method.to_s.sub(/=$/, '').to_sym
|
73
|
-
@data.has_key?(method) || @data.has_key?(getter) || super
|
74
|
-
end
|
75
|
-
|
76
77
|
# Every message loads received message version first
|
77
78
|
def load
|
78
79
|
@data[:version] = @socket.read_int
|
@@ -156,11 +157,11 @@ module IB
|
|
156
157
|
[:last_fill_price, :decimal],
|
157
158
|
[:client_id, :int],
|
158
159
|
[:why_held, :string] do
|
159
|
-
"<OrderStatus: #{
|
160
|
-
" @ last/avg: #{
|
161
|
-
(
|
162
|
-
(
|
163
|
-
" id/perm: #{
|
160
|
+
"<OrderStatus: #{status} filled: #{filled}/#{remaining + filled}" +
|
161
|
+
" @ last/avg: #{last_fill_price}/#{average_fill_price}" +
|
162
|
+
(parent_id > 0 ? "parent_id: #{parent_id}" : "") +
|
163
|
+
(why_held != "" ? "why_held: #{why_held}" : "") +
|
164
|
+
" id/perm: #{id}/#{perm_id}>"
|
164
165
|
end
|
165
166
|
|
166
167
|
|
@@ -168,17 +169,17 @@ module IB
|
|
168
169
|
[:value, :string],
|
169
170
|
[:currency, :string],
|
170
171
|
[:account_name, :string]) do
|
171
|
-
"<AccountValue: #{
|
172
|
+
"<AccountValue: #{account_name}, #{key}=#{value} #{currency}>"
|
172
173
|
end
|
173
174
|
|
174
175
|
AccountUpdateTime = def_message(8, [:time_stamp, :string]) do
|
175
|
-
"<AccountUpdateTime: #{
|
176
|
+
"<AccountUpdateTime: #{time_stamp}>"
|
176
177
|
end
|
177
178
|
|
178
179
|
# This message is always sent by TWS automatically at connect.
|
179
180
|
# The IB::Connection class subscribes to it automatically and stores
|
180
181
|
# the order id in its @next_order_id attribute.
|
181
|
-
NextValidID = def_message(9, [:id, :int]) { "<NextValidID: #{
|
182
|
+
NextValidID = def_message(9, [:id, :int]) { "<NextValidID: #{id}>" }
|
182
183
|
|
183
184
|
NewsBulletins =
|
184
185
|
def_message 14, [:id, :int], # unique incrementing bulletin ID.
|
@@ -214,18 +215,18 @@ module IB
|
|
214
215
|
FundamentalData = def_message 50, [:id, :int], # request_id
|
215
216
|
[:data, :string]
|
216
217
|
|
217
|
-
ContractDataEnd = def_message(52, [:id, :int]) { "<ContractDataEnd: #{
|
218
|
+
ContractDataEnd = def_message(52, [:id, :int]) { "<ContractDataEnd: #{id}>" } # request_id
|
218
219
|
|
219
220
|
OpenOrderEnd = def_message(53) { "<OpenOrderEnd>" }
|
220
221
|
|
221
222
|
AccountDownloadEnd = def_message(54, [:account_name, :string]) do
|
222
|
-
"<AccountDownloadEnd: #{
|
223
|
+
"<AccountDownloadEnd: #{account_name}}>"
|
223
224
|
end # request_id
|
224
225
|
|
225
226
|
|
226
|
-
ExecutionDataEnd = def_message
|
227
|
+
ExecutionDataEnd = def_message(55, [:id, :int]) { "<ExecutionDataEnd: #{id}>" } # request_id
|
227
228
|
|
228
|
-
TickSnapshotEnd = def_message
|
229
|
+
TickSnapshotEnd = def_message(57, [:id, :int]) { "<TickSnapshotEnd: #{id}>" } # request_id
|
229
230
|
|
230
231
|
### Actual message classes (long definitions):
|
231
232
|
|
@@ -344,10 +345,9 @@ module IB
|
|
344
345
|
end
|
345
346
|
|
346
347
|
def to_human
|
347
|
-
"<TickOption #{type} for #{
|
348
|
-
"option @ #{
|
349
|
-
"
|
350
|
-
"theta #{@data[:theta]}, pv_dividend #{@data[:pv_dividend]}>"
|
348
|
+
"<TickOption #{type} for #{:id}: underlying @ #{under_price}, "+
|
349
|
+
"option @ #{option_price}, IV #{implied_volatility}%, delta #{delta}, " +
|
350
|
+
"gamma #{gamma}, vega #{vega}, theta #{theta}, pv_dividend #{pv_dividend}>"
|
351
351
|
end
|
352
352
|
end # TickOption
|
353
353
|
TickOptionComputation = TickOption
|
@@ -373,8 +373,8 @@ module IB
|
|
373
373
|
end
|
374
374
|
|
375
375
|
def to_human
|
376
|
-
"<#{self.class.to_s.split(
|
377
|
-
"#{
|
376
|
+
"<#{self.class.to_s.split(/::/).last}: #{operation} #{side} @ "+
|
377
|
+
"#{position} = #{price} x #{size}>"
|
378
378
|
end
|
379
379
|
end
|
380
380
|
|
@@ -415,13 +415,14 @@ module IB
|
|
415
415
|
"TWS #{ error? ? 'Error' : system? ? 'System' : 'Warning'
|
416
416
|
} Message #{code}: #{message}"
|
417
417
|
end
|
418
|
-
end # class
|
418
|
+
end # class Alert
|
419
419
|
Error = Alert
|
420
420
|
ErrorMessage = Alert
|
421
421
|
|
422
422
|
class OpenOrder < AbstractMessage
|
423
423
|
@message_id = 5
|
424
424
|
|
425
|
+
# TODO: Add id accessor to unify with OrderStatus message
|
425
426
|
attr_accessor :order, :contract
|
426
427
|
|
427
428
|
def load
|
@@ -657,6 +658,10 @@ module IB
|
|
657
658
|
:cumulative_quantity => @socket.read_int,
|
658
659
|
:average_price => @socket.read_decimal
|
659
660
|
end
|
661
|
+
|
662
|
+
def to_human
|
663
|
+
"<HistoricalData: req: #{id}, #{item_count} items, #{start_date} to #{end_date}>"
|
664
|
+
end
|
660
665
|
end # ExecutionData
|
661
666
|
|
662
667
|
# HistoricalData contains following @data:
|
@@ -702,8 +707,7 @@ module IB
|
|
702
707
|
end
|
703
708
|
|
704
709
|
def to_human
|
705
|
-
"<HistoricalData: req id #{
|
706
|
-
} items, from #{@data[:start_date_str]} to #{@data[:end_date_str]}>"
|
710
|
+
"<HistoricalData: req: #{id}, #{item_count} items, #{start_date} to #{end_date}>"
|
707
711
|
end
|
708
712
|
end # HistoricalData
|
709
713
|
|
@@ -818,7 +822,7 @@ module IB
|
|
818
822
|
end
|
819
823
|
|
820
824
|
def to_human
|
821
|
-
"<RealTimeBar: req
|
825
|
+
"<RealTimeBar: req: #{id}, #{bar}>"
|
822
826
|
end
|
823
827
|
end # RealTimeBar
|
824
828
|
RealTimeBars = RealTimeBar
|
data/lib/ib-ruby/models/order.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ib-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.5.
|
5
|
+
version: 0.5.17
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Paul Legato
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2012-02-
|
14
|
+
date: 2012-02-12 00:00:00 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|