ib-ruby 0.4.3 → 0.4.20
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/.gitignore +32 -0
- data/HISTORY +68 -0
- data/README.rdoc +9 -6
- data/VERSION +1 -1
- data/bin/account_info +29 -0
- data/bin/contract_details +37 -0
- data/bin/depth_of_market +43 -0
- data/bin/historic_data +62 -0
- data/bin/{RequestHistoricData → historic_data_cli} +46 -91
- data/bin/market_data +49 -0
- data/bin/option_data +45 -0
- data/bin/template +21 -0
- data/bin/time_and_sales +63 -0
- data/lib/ib-ruby/connection.rb +166 -0
- data/lib/ib-ruby/constants.rb +91 -0
- data/lib/ib-ruby/messages/incoming.rb +807 -0
- data/lib/ib-ruby/messages/outgoing.rb +573 -0
- data/lib/ib-ruby/messages.rb +8 -1445
- data/lib/ib-ruby/models/bar.rb +26 -0
- data/lib/ib-ruby/models/contract.rb +335 -0
- data/lib/ib-ruby/models/execution.rb +55 -0
- data/lib/ib-ruby/models/model.rb +20 -0
- data/lib/ib-ruby/models/order.rb +262 -0
- data/lib/ib-ruby/models.rb +11 -0
- data/lib/ib-ruby/socket.rb +50 -0
- data/lib/ib-ruby/symbols/forex.rb +32 -72
- data/lib/ib-ruby/symbols/futures.rb +47 -68
- data/lib/ib-ruby/symbols/options.rb +30 -0
- data/lib/ib-ruby/symbols/stocks.rb +23 -0
- data/lib/ib-ruby/symbols.rb +9 -0
- data/lib/ib-ruby.rb +7 -8
- data/lib/legacy/bin/account_info_old +36 -0
- data/lib/legacy/bin/historic_data_old +81 -0
- data/lib/legacy/bin/market_data_old +68 -0
- data/lib/legacy/datatypes.rb +485 -0
- data/lib/legacy/ib-ruby.rb +10 -0
- data/lib/legacy/ib.rb +226 -0
- data/lib/legacy/messages.rb +1458 -0
- data/lib/version.rb +2 -3
- data/spec/ib-ruby/models/contract_spec.rb +261 -0
- data/spec/ib-ruby/models/order_spec.rb +64 -0
- data/spec/ib-ruby_spec.rb +0 -131
- metadata +106 -76
- data/bin/AccountInfo +0 -67
- data/bin/HistoricToCSV +0 -111
- data/bin/RequestMarketData +0 -78
- data/bin/SimpleTimeAndSales +0 -98
- data/bin/ib-ruby +0 -8
- data/lib/ib-ruby/datatypes.rb +0 -400
- data/lib/ib-ruby/ib.rb +0 -242
data/.gitignore
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## Idea
|
17
|
+
.idea
|
18
|
+
.bundle
|
19
|
+
.rakeTasks
|
20
|
+
*.iml
|
21
|
+
|
22
|
+
## PROJECT::GENERAL
|
23
|
+
coverage
|
24
|
+
config
|
25
|
+
data
|
26
|
+
rdoc
|
27
|
+
pkg
|
28
|
+
log
|
29
|
+
tmp
|
30
|
+
|
31
|
+
## PROJECT::SPECIFIC
|
32
|
+
*.db
|
data/HISTORY
CHANGED
@@ -21,3 +21,71 @@
|
|
21
21
|
== 0.4.3 / 2011-09-05
|
22
22
|
|
23
23
|
* Old tests converted into specs
|
24
|
+
|
25
|
+
== 0.4.4 / 2011-09-05
|
26
|
+
|
27
|
+
* IB references and Java examples added
|
28
|
+
|
29
|
+
== 0.4.5 / 2011-09-06
|
30
|
+
|
31
|
+
* Sample scripts updated
|
32
|
+
|
33
|
+
== 0.4.6 / 2011-09-07
|
34
|
+
|
35
|
+
* CSV Downloader Java examples added
|
36
|
+
|
37
|
+
== 0.4.7 / 2011-09-12
|
38
|
+
|
39
|
+
* Datatypes turned into Models
|
40
|
+
|
41
|
+
== 0.4.8 / 2011-09-12
|
42
|
+
|
43
|
+
* IB::Messages::Outgoing code compacted using macros
|
44
|
+
|
45
|
+
== 0.4.9 / 2011-09-15
|
46
|
+
|
47
|
+
* IB::Messages::Incoming rewritten
|
48
|
+
|
49
|
+
== 0.4.10 / 2011-09-16
|
50
|
+
|
51
|
+
* Market data request now working
|
52
|
+
|
53
|
+
== 0.4.11 / 2011-09-17
|
54
|
+
|
55
|
+
* New scripts working
|
56
|
+
|
57
|
+
== 0.4.12 / 2011-09-18
|
58
|
+
|
59
|
+
* historic_data script now functional
|
60
|
+
|
61
|
+
== 0.4.13 / 2011-09-18
|
62
|
+
|
63
|
+
* time_and_sales script now working
|
64
|
+
|
65
|
+
== 0.4.14 / 2011-09-18
|
66
|
+
|
67
|
+
* DOM script added
|
68
|
+
|
69
|
+
== 0.4.15 / 2011-09-18
|
70
|
+
|
71
|
+
* Messages like RTBars etc implemented
|
72
|
+
|
73
|
+
== 0.4.16 / 2011-09-19
|
74
|
+
|
75
|
+
* Execution Model added
|
76
|
+
|
77
|
+
== 0.4.17 / 2011-09-19
|
78
|
+
|
79
|
+
* option_data script now working
|
80
|
+
|
81
|
+
== 0.4.18 / 2011-09-19
|
82
|
+
|
83
|
+
* IB::Connection#subscribe syntax changed
|
84
|
+
|
85
|
+
== 0.4.19 / 2011-09-19
|
86
|
+
|
87
|
+
* All IB messages implemented
|
88
|
+
|
89
|
+
== 0.4.20 / 2011-09-19
|
90
|
+
|
91
|
+
* IB::Connection#subscribe now accepts Symbols with message names
|
data/README.rdoc
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
=
|
1
|
+
= ib-ruby
|
2
2
|
by:: Arvicco
|
3
3
|
url:: http://github.com/arvicco/ib-ruby
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
This is a fork of http://github.com/wdevauld/ib-ruby by Wes Devauld,
|
6
|
+
that is in turn forked from http://github.com/pjlegato/ib-ruby by Paul Legato.
|
7
7
|
|
8
8
|
== DESCRIPTION:
|
9
9
|
|
10
10
|
Ruby Implementation of the Interactive Broker' TWS API
|
11
11
|
|
12
12
|
The goal of this fork is to modernize library structure (Bundler/Gemfile/etc) and
|
13
|
-
then roll out a new version based on latest IB TWS API.
|
13
|
+
then roll out a new version based on latest IB TWS API v.965.
|
14
14
|
|
15
15
|
== FEATURES/PROBLEMS:
|
16
16
|
|
@@ -39,8 +39,11 @@ connections on localhost.
|
|
39
39
|
First, start up Interactive Broker's Trader Work Station.
|
40
40
|
Ensure it is configured to allow API connections on localhost.
|
41
41
|
|
42
|
-
>> require 'ib-ruby'
|
43
|
-
>>
|
42
|
+
>> require 'ib-ruby'
|
43
|
+
>> ib = IB::Connection.new
|
44
|
+
>> ib.subscribe(IB::Messages::Incoming::Alert) { |msg| puts msg.to_human }
|
45
|
+
>> ib.subscribe(IB::Messages::Incoming::AccountValue) { |msg| puts msg.to_human }
|
46
|
+
>> ib.send IB::Messages::Outgoing::RequestAccountData.new :subscribe => true
|
44
47
|
|
45
48
|
== LICENSE:
|
46
49
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.20
|
data/bin/account_info
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script connects to IB API, subscribes to account info and prints out
|
4
|
+
# messages received from IB (update every 3 minute or so)
|
5
|
+
|
6
|
+
require 'pathname'
|
7
|
+
LIB_DIR = (Pathname.new(__FILE__).dirname + '../lib/').realpath.to_s
|
8
|
+
$LOAD_PATH.unshift LIB_DIR unless $LOAD_PATH.include?(LIB_DIR)
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'bundler/setup'
|
12
|
+
require 'ib-ruby'
|
13
|
+
|
14
|
+
# First, connect to IB TWS.
|
15
|
+
ib = IB::Connection.new
|
16
|
+
|
17
|
+
# Subscribe to TWS alerts/errors and account-related messages
|
18
|
+
# that TWS sends in response to account data request
|
19
|
+
ib.subscribe(:Alert, :AccountValue,
|
20
|
+
:PortfolioValue, :AccountUpdateTime) { |msg| puts msg.to_human }
|
21
|
+
|
22
|
+
ib.send :RequestAccountData, :subscribe => true
|
23
|
+
|
24
|
+
puts "\nSubscribing to IB account data"
|
25
|
+
puts "\n******** Press <Enter> to cancel... *********\n\n"
|
26
|
+
gets
|
27
|
+
puts "Cancelling account data subscription.."
|
28
|
+
|
29
|
+
ib.send :RequestAccountData, :subscribe => false
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script gets details for specific symbol from IB
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
LIB_DIR = (Pathname.new(__FILE__).dirname + '../lib/').realpath.to_s
|
7
|
+
$LOAD_PATH.unshift LIB_DIR unless $LOAD_PATH.include?(LIB_DIR)
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'bundler/setup'
|
11
|
+
require 'ib-ruby'
|
12
|
+
|
13
|
+
# Definition of what we want market data for. We have to keep track of what ticker id
|
14
|
+
# corresponds to what symbol ourselves, because the ticks don't include any other
|
15
|
+
# identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
|
16
|
+
@market = {123 => IB::Symbols::Stocks[:wfc],
|
17
|
+
125 => IB::Symbols::Options[:wfc20],
|
18
|
+
129 => IB::Symbols::Stocks[:wrong]}
|
19
|
+
|
20
|
+
# Connect to IB TWS.
|
21
|
+
ib = IB::Connection.new
|
22
|
+
|
23
|
+
# Subscribe to TWS alerts/errors
|
24
|
+
ib.subscribe(IB::Messages::Incoming::Alert) { |msg| puts msg.to_human }
|
25
|
+
|
26
|
+
# Now, subscribe to ContractData incoming events. The code passed in the block
|
27
|
+
# will be executed when a message of that type is received, with the received
|
28
|
+
# message as its argument. In this case, we just print out the data.
|
29
|
+
ib.subscribe(:ContractData) { |msg| puts msg.contract.inspect }
|
30
|
+
|
31
|
+
# Now we actually request historical data for the symbols we're interested in. TWS will
|
32
|
+
# respond with a HistoricalData message, which will be processed by the code above.
|
33
|
+
@market.each_pair do |id, contract|
|
34
|
+
ib.send :RequestContractData, :id => id, :contract => contract
|
35
|
+
end
|
36
|
+
|
37
|
+
sleep 3 # Wait for IB to respond to our request
|
data/bin/depth_of_market
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script connects to IB API and subscribes to L2 (depth of market) data for
|
4
|
+
# specific symbols
|
5
|
+
|
6
|
+
require 'pathname'
|
7
|
+
LIB_DIR = (Pathname.new(__FILE__).dirname + '../lib/').realpath.to_s
|
8
|
+
$LOAD_PATH.unshift LIB_DIR unless $LOAD_PATH.include?(LIB_DIR)
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'bundler/setup'
|
12
|
+
require 'ib-ruby'
|
13
|
+
|
14
|
+
# Definition of what we want L2 data for. We have to keep track of what ticker id
|
15
|
+
# corresponds to what symbol ourselves, because the ticks don't include any other
|
16
|
+
# identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
|
17
|
+
@market = {123 => IB::Symbols::Stocks[:wfc],
|
18
|
+
456 => IB::Symbols::Futures[:ym],
|
19
|
+
789 => IB::Symbols::Forex[:gbpusd]
|
20
|
+
}
|
21
|
+
|
22
|
+
# First, connect to IB TWS.
|
23
|
+
ib = IB::Connection.new
|
24
|
+
|
25
|
+
# Subscribe to TWS alerts/errors
|
26
|
+
ib.subscribe(:Alert) { |msg| puts msg.to_human }
|
27
|
+
|
28
|
+
# Subscribe to MarketDepth events.
|
29
|
+
ib.subscribe(:MarketDepth) do |msg|
|
30
|
+
puts @market[msg.data[:id]].description + ": " + msg.to_human
|
31
|
+
end
|
32
|
+
|
33
|
+
# Now we actually request market data for the symbols we're interested in.
|
34
|
+
@market.each_pair do |id, contract|
|
35
|
+
ib.send :RequestMarketDepth, :id => id, :contract => contract, :num_rows => 5
|
36
|
+
end
|
37
|
+
|
38
|
+
puts "\nSubscribed to market data"
|
39
|
+
puts "\n******** Press <Enter> to cancel... *********\n\n"
|
40
|
+
gets
|
41
|
+
puts "Cancelling market data subscription.."
|
42
|
+
|
43
|
+
@market.each_pair { |id, contract| ib.send :CancelMarketDepth, :id => id }
|
data/bin/historic_data
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script downloads historic data for specific symbols from IB
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
LIB_DIR = (Pathname.new(__FILE__).dirname + '../lib/').realpath.to_s
|
7
|
+
$LOAD_PATH.unshift LIB_DIR unless $LOAD_PATH.include?(LIB_DIR)
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'bundler/setup'
|
11
|
+
require 'ib-ruby'
|
12
|
+
|
13
|
+
### Configurable Options
|
14
|
+
Quiet = false # if Quiet == false, status data will be printed to STDERR
|
15
|
+
Timeout = 10 # How long to wait for messages from TWS before exiting, sec
|
16
|
+
|
17
|
+
# Definition of what we want data for. We have to keep track of what ticker id
|
18
|
+
# corresponds to what symbol ourselves, because the ticks don't include any other
|
19
|
+
# identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
|
20
|
+
@market = {123 => IB::Symbols::Stocks[:wfc],
|
21
|
+
456 => IB::Symbols::Futures[:ym],
|
22
|
+
789 => IB::Symbols::Forex[:gbpusd] # No historical market data for GBP/CASH@IDEALPRO Last 60
|
23
|
+
}
|
24
|
+
|
25
|
+
# Connect to IB TWS.
|
26
|
+
ib = IB::Connection.new
|
27
|
+
|
28
|
+
# Subscribe to TWS alerts/errors
|
29
|
+
ib.subscribe(IB::Messages::Incoming::Alert) { |msg| puts msg.to_human }
|
30
|
+
|
31
|
+
# Now, subscribe to HistoricalData incoming events. The code passed in the block
|
32
|
+
# will be executed when a message of that type is received, with the received
|
33
|
+
# message as its argument. In this case, we just print out the data.
|
34
|
+
#
|
35
|
+
# Note that we have to look the ticker id of each incoming message
|
36
|
+
# up in local memory to figure out what it's for.
|
37
|
+
ib.subscribe(IB::Messages::Incoming::HistoricalData) do |msg|
|
38
|
+
STDERR.puts @market[msg.data[:id]].description + ": " + msg.data[:count].to_s + " items:" unless Quiet
|
39
|
+
|
40
|
+
msg.data[:results].each do |datum|
|
41
|
+
@last_msg_time = Time.now.to_i
|
42
|
+
|
43
|
+
STDERR.puts " " + datum.to_s unless Quiet
|
44
|
+
#STDOUT.puts "#{datum.date},#{datum.open},#{datum.high},#{datum.low},#{datum.close},#{datum.volume}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Now we actually request historical data for the symbols we're interested in. TWS will
|
49
|
+
# respond with a HistoricalData message, which will be processed by the code above.
|
50
|
+
@market.each_pair do |id, contract|
|
51
|
+
ib.send IB::Messages::Outgoing::RequestHistoricalData.new(
|
52
|
+
:id => id,
|
53
|
+
:contract => contract,
|
54
|
+
:end_date_time => Time.now.to_ib,
|
55
|
+
:duration => '2 D', # ?
|
56
|
+
:bar_size => '1 min', #IB::OutgoingMessages::BAR_SIZES.key(:hour),
|
57
|
+
:what_to_show => :trades,
|
58
|
+
:use_rth => 1,
|
59
|
+
:format_date => 1)
|
60
|
+
end
|
61
|
+
|
62
|
+
sleep 5 # Wait for IB to respond to our request
|
@@ -1,77 +1,39 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# This library is free software; you can redistribute it and/or modify
|
6
|
-
# it under the terms of the GNU Lesser General Public License as
|
7
|
-
# published by the Free Software Foundation; either version 2.1 of the
|
8
|
-
# License, or (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This library is distributed in the hope that it will be useful, but
|
11
|
-
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
-
# Lesser General Public License for more details.
|
14
|
-
#
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
16
|
-
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
18
|
-
# 02110-1301 USA
|
19
|
-
#
|
20
|
-
|
21
|
-
require File.expand_path(
|
22
|
-
File.join(File.dirname(__FILE__), '..', 'lib', 'ib-ruby'))
|
3
|
+
# This script connects to IB API, and downloads historic data
|
4
|
+
# TODO: Fix the Historical command line client
|
23
5
|
|
24
6
|
require 'rubygems'
|
25
7
|
require 'time'
|
26
8
|
require 'duration'
|
9
|
+
require 'pathname'
|
27
10
|
require 'getopt/long'
|
11
|
+
require 'bundler/setup'
|
12
|
+
|
13
|
+
LIB_DIR = (Pathname.new(__FILE__).dirname + '../lib/').realpath.to_s
|
14
|
+
$LOAD_PATH.unshift LIB_DIR unless $LOAD_PATH.include?(LIB_DIR)
|
15
|
+
|
16
|
+
require 'ib-ruby'
|
28
17
|
|
29
18
|
include Getopt
|
30
19
|
|
31
20
|
opt = Getopt::Long.getopts(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
21
|
+
["--help", BOOLEAN],
|
22
|
+
["--end", REQUIRED],
|
23
|
+
["--security", REQUIRED],
|
24
|
+
["--duration", REQUIRED],
|
25
|
+
["--barsize", REQUIRED],
|
26
|
+
["--header", BOOLEAN],
|
27
|
+
["--dateformat", REQUIRED],
|
28
|
+
["--nonregularhours", BOOLEAN],
|
29
|
+
["--verbose", BOOLEAN],
|
30
|
+
["--veryverbose", BOOLEAN]
|
42
31
|
)
|
43
32
|
|
44
33
|
if opt["help"] || opt["security"].nil? || opt["security"].empty?
|
45
34
|
puts <<ENDHELP
|
46
35
|
|
47
|
-
|
48
|
-
|
49
|
-
This library is free software; you can redistribute it and/or modify
|
50
|
-
it under the terms of the GNU Lesser General Public License as
|
51
|
-
published by the Free Software Foundation; either version 2.1 of the
|
52
|
-
License, or (at your option) any later version.
|
53
|
-
|
54
|
-
This library is distributed in the hope that it will be useful, but
|
55
|
-
WITHOUT ANY WARRANTY; without even the implied warranty of
|
56
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
57
|
-
Lesser General Public License for more details.
|
58
|
-
|
59
|
-
You should have received a copy of the GNU Lesser General Public
|
60
|
-
License along with this library; if not, write to the Free Software
|
61
|
-
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
62
|
-
02110-1301 USA
|
63
|
-
|
64
|
-
The author and this software are not connected with Interactive
|
65
|
-
Brokers in any way, nor do they endorse us.
|
66
|
-
|
67
|
-
************************************************************************************
|
68
|
-
|
69
|
-
>> YOUR USE OF THIS PROGRAM IS ENTIRELY AT YOUR OWN RISK. <<
|
70
|
-
>> IT MAY CONTAIN POTENTIALLY COSTLY BUGS, ERRORS, ETC., BOTH KNOWN AND UNKNOWN. <<
|
71
|
-
>> DO NOT USE THIS SOFTWARE IF YOU ARE UNWILLING TO ACCEPT ALL RISK IN DOING SO. <<
|
72
|
-
|
73
|
-
************************************************************************************
|
74
|
-
|
36
|
+
***
|
75
37
|
|
76
38
|
This program requires a TWS running on localhost on the standard port
|
77
39
|
that uses API protocol version 15 or higher. Any modern TWS should
|
@@ -153,7 +115,7 @@ Possible values (from the IB documentation):
|
|
153
115
|
data in CSV format.
|
154
116
|
|
155
117
|
ENDHELP
|
156
|
-
|
118
|
+
|
157
119
|
exit
|
158
120
|
|
159
121
|
end
|
@@ -169,11 +131,9 @@ if DURATION > 86400
|
|
169
131
|
exit(1)
|
170
132
|
end
|
171
133
|
|
172
|
-
|
173
134
|
# This is the last time we want data for.
|
174
135
|
END_DATE_TIME = (opt["end"] && eval(opt["end"]).to_ib) || Time.now.to_ib
|
175
136
|
|
176
|
-
|
177
137
|
# This can be :trades, :midpoint, :bid, or :asked
|
178
138
|
WHAT = (opt["what"] && opt["what"].to_sym) || :trades
|
179
139
|
|
@@ -223,16 +183,11 @@ VERBOSE = !opt["verbose"].nil?
|
|
223
183
|
#
|
224
184
|
# Note that as of 4/07 there is no historical data available for forex spot.
|
225
185
|
#
|
226
|
-
@market =
|
227
|
-
{
|
228
|
-
123 => opt["security"]
|
229
|
-
}
|
230
|
-
|
186
|
+
@market = {123 => opt["security"]}
|
231
187
|
|
232
188
|
# First, connect to IB TWS.
|
233
189
|
ib = IB::IB.new
|
234
190
|
|
235
|
-
|
236
191
|
# Default level is quiet, only warnings printed.
|
237
192
|
# IB::IBLogger.level = Logger::Severity::ERROR
|
238
193
|
|
@@ -256,35 +211,35 @@ lastMessageTime = Queue.new # for communicating with the reader thread.
|
|
256
211
|
# up in local memory to figure out what security it relates to.
|
257
212
|
# The incoming message packet from TWS just identifies it by ticker id.
|
258
213
|
#
|
259
|
-
ib.subscribe(IB::IncomingMessages::HistoricalData, lambda {|msg|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
214
|
+
ib.subscribe(IB::IncomingMessages::HistoricalData, lambda { |msg|
|
215
|
+
STDERR.puts @market[msg.data[:req_id]].description + ": " + msg.data[:item_count].to_s("F") + " items:" if VERBOSE
|
216
|
+
|
217
|
+
msg.data[:history].each { |datum|
|
218
|
+
puts(if VERBOSE
|
219
|
+
datum.to_s
|
220
|
+
else
|
221
|
+
"#{datum.date},#{datum.open.to_s("F")},#{datum.high.to_s("F")},#{datum.low.to_s("F")}," +
|
222
|
+
"#{datum.close.to_s("F")},#{datum.volume},#{datum.wap.to_s("F")},#{datum.has_gaps}"
|
223
|
+
end
|
224
|
+
)
|
225
|
+
}
|
226
|
+
lastMessageTime.push(Time.now)
|
227
|
+
})
|
273
228
|
|
274
229
|
# Now we actually request historical data for the symbols we're
|
275
230
|
# interested in. TWS will respond with a HistoricalData message,
|
276
231
|
# which will be received by the code above.
|
277
232
|
|
278
|
-
@market.each_pair {|id, contract|
|
233
|
+
@market.each_pair { |id, contract|
|
279
234
|
msg = IB::OutgoingMessages::RequestHistoricalData.new({
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
235
|
+
:ticker_id => id,
|
236
|
+
:contract => contract,
|
237
|
+
:end_date_time => END_DATE_TIME,
|
238
|
+
:duration => DURATION, # seconds == 1 hour
|
239
|
+
:bar_size => BAR_SIZE, # 1 minute bars
|
240
|
+
:what_to_show => WHAT,
|
241
|
+
:use_RTH => REGULAR_HOURS_ONLY,
|
242
|
+
:format_date => DATE_FORMAT
|
288
243
|
})
|
289
244
|
ib.dispatch(msg)
|
290
245
|
}
|
data/bin/market_data
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script connects to IB API and subscribes to market data for specific symbols
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
LIB_DIR = (Pathname.new(__FILE__).dirname + '../lib/').realpath.to_s
|
7
|
+
$LOAD_PATH.unshift LIB_DIR unless $LOAD_PATH.include?(LIB_DIR)
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'bundler/setup'
|
11
|
+
require 'ib-ruby'
|
12
|
+
|
13
|
+
# Definition of what we want market data for. We have to keep track of what ticker id
|
14
|
+
# corresponds to what symbol ourselves, because the ticks don't include any other
|
15
|
+
# identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
|
16
|
+
@market = {123 => IB::Symbols::Forex[:gbpusd],
|
17
|
+
456 => IB::Symbols::Forex[:eurusd],
|
18
|
+
789 => IB::Symbols::Forex[:usdcad]}
|
19
|
+
|
20
|
+
# First, connect to IB TWS.
|
21
|
+
ib = IB::Connection.new
|
22
|
+
|
23
|
+
## Subscribe to TWS alerts/errors
|
24
|
+
ib.subscribe(:Alert) { |msg| puts msg.to_human }
|
25
|
+
|
26
|
+
# Subscribe to TickerPrice and TickerSize events. The code passed in the block will
|
27
|
+
# be executed when a message of that type is received, with the received message as its
|
28
|
+
# argument. In this case, we just print out the tick.
|
29
|
+
#
|
30
|
+
# Note that we have to look the ticker id of each incoming message
|
31
|
+
# up in local memory to figure out what it's for.
|
32
|
+
#
|
33
|
+
# (N.B. The description field is not from IB TWS. It is defined
|
34
|
+
# locally in forex.rb, and is just arbitrary text.)
|
35
|
+
ib.subscribe(:TickPrice, :TickSize) do |msg|
|
36
|
+
puts @market[msg.data[:id]].description + ": " + msg.to_human
|
37
|
+
end
|
38
|
+
|
39
|
+
# Now we actually request market data for the symbols we're interested in.
|
40
|
+
@market.each_pair do |id, contract|
|
41
|
+
ib.send :RequestMarketData, :id => id, :contract => contract
|
42
|
+
end
|
43
|
+
|
44
|
+
puts "\nSubscribed to market data"
|
45
|
+
puts "\n******** Press <Enter> to cancel... *********\n\n"
|
46
|
+
gets
|
47
|
+
puts "Cancelling market data subscription.."
|
48
|
+
|
49
|
+
@market.each_pair { |id, _| ib.send :CancelMarketData, :id => id }
|
data/bin/option_data
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script connects to IB API and subscribes to market data for specific symbols
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
LIB_DIR = (Pathname.new(__FILE__).dirname + '../lib/').realpath.to_s
|
7
|
+
$LOAD_PATH.unshift LIB_DIR unless $LOAD_PATH.include?(LIB_DIR)
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'bundler/setup'
|
11
|
+
require 'ib-ruby'
|
12
|
+
|
13
|
+
# Definition of what we want market data for. We have to keep track of what ticker id
|
14
|
+
# corresponds to what symbol ourselves, because the ticks don't include any other
|
15
|
+
# identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
|
16
|
+
@market = {123 => IB::Symbols::Options[:wfc20],
|
17
|
+
125 => IB::Symbols::Options[:z50]}
|
18
|
+
|
19
|
+
# First, connect to IB TWS.
|
20
|
+
ib = IB::Connection.new
|
21
|
+
|
22
|
+
## Subscribe to TWS alerts/errors
|
23
|
+
ib.subscribe(:Alert) { |msg| puts msg.to_human }
|
24
|
+
|
25
|
+
# Subscribe to Ticker... events. The code passed in the block will be executed when
|
26
|
+
# any message of that type is received, with the received message as its argument.
|
27
|
+
# In this case, we just print out the tick.
|
28
|
+
#
|
29
|
+
# (N.B. The description field is not from IB TWS. It is defined
|
30
|
+
# locally in forex.rb, and is just arbitrary text.)
|
31
|
+
ib.subscribe(:TickPrice, :TickSize, :TickOption) do |msg|
|
32
|
+
puts @market[msg.data[:id]].description + ": " + msg.to_human
|
33
|
+
end
|
34
|
+
|
35
|
+
# Now we actually request market data for the symbols we're interested in.
|
36
|
+
@market.each_pair do |id, contract|
|
37
|
+
ib.send :RequestMarketData, :id => id, :contract => contract
|
38
|
+
end
|
39
|
+
|
40
|
+
puts "\nSubscribed to market data"
|
41
|
+
puts "\n******** Press <Enter> to cancel... *********\n\n"
|
42
|
+
gets
|
43
|
+
puts "Cancelling market data subscription.."
|
44
|
+
|
45
|
+
@market.each_pair { |id, contract| ib.send :CancelMarketData, :id => id }
|
data/bin/template
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Your script description here...
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
LIB_DIR = (Pathname.new(__FILE__).dirname + '../lib/').realpath.to_s
|
7
|
+
$LOAD_PATH.unshift LIB_DIR unless $LOAD_PATH.include?(LIB_DIR)
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'bundler/setup'
|
11
|
+
require 'ib-ruby'
|
12
|
+
|
13
|
+
# Connect to IB TWS.
|
14
|
+
ib = IB::Connection.new
|
15
|
+
|
16
|
+
# Subscribe to TWS alerts/errors
|
17
|
+
ib.subscribe(IB::Messages::Incoming::Alert) { |msg| puts msg.to_human }
|
18
|
+
|
19
|
+
# Put your code here
|
20
|
+
# ...
|
21
|
+
|