ib-ruby 0.8.4 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/HISTORY +3 -0
- data/README.md +29 -9
- data/VERSION +1 -1
- data/app/assets/javascripts/ib/bars.js +2 -0
- data/app/assets/javascripts/ib/executions.js +2 -0
- data/app/assets/javascripts/ib/order_states.js +2 -0
- data/app/assets/stylesheets/ib/bars.css +4 -0
- data/app/assets/stylesheets/ib/executions.css +4 -0
- data/app/assets/stylesheets/ib/order_states.css +4 -0
- data/app/controllers/ib/bars_controller.rb +87 -0
- data/app/controllers/ib/combo_legs_controller.rb +87 -0
- data/app/controllers/ib/contract_details_controller.rb +87 -0
- data/app/controllers/ib/contracts_controller.rb +87 -0
- data/app/controllers/ib/executions_controller.rb +87 -0
- data/app/controllers/ib/order_states_controller.rb +87 -0
- data/app/controllers/ib/orders_controller.rb +87 -0
- data/app/helpers/ib/bars_helper.rb +4 -0
- data/app/helpers/ib/combo_legs_helper.rb +4 -0
- data/app/helpers/ib/contract_details_helper.rb +4 -0
- data/app/helpers/ib/contracts_helper.rb +4 -0
- data/app/helpers/ib/executions_helper.rb +4 -0
- data/app/helpers/ib/order_states_helper.rb +4 -0
- data/app/helpers/ib/orders_helper.rb +4 -0
- data/app/views/ib/bars/_form.html.erb +57 -0
- data/app/views/ib/bars/edit.html.erb +6 -0
- data/app/views/ib/bars/index.html.erb +41 -0
- data/app/views/ib/bars/new.html.erb +5 -0
- data/app/views/ib/bars/show.html.erb +55 -0
- data/app/views/ib/combo_legs/_form.html.erb +53 -0
- data/app/views/ib/combo_legs/edit.html.erb +6 -0
- data/app/views/ib/combo_legs/index.html.erb +39 -0
- data/app/views/ib/combo_legs/new.html.erb +5 -0
- data/app/views/ib/combo_legs/show.html.erb +55 -0
- data/app/views/ib/contract_details/_form.html.erb +141 -0
- data/app/views/ib/contract_details/edit.html.erb +6 -0
- data/app/views/ib/contract_details/index.html.erb +83 -0
- data/app/views/ib/contract_details/new.html.erb +5 -0
- data/app/views/ib/contract_details/show.html.erb +160 -0
- data/app/views/ib/contracts/_form.html.erb +77 -0
- data/app/views/ib/contracts/edit.html.erb +6 -0
- data/app/views/ib/contracts/index.html.erb +53 -0
- data/app/views/ib/contracts/new.html.erb +5 -0
- data/app/views/ib/contracts/show.html.erb +85 -0
- data/app/views/ib/executions/_form.html.erb +77 -0
- data/app/views/ib/executions/edit.html.erb +6 -0
- data/app/views/ib/executions/index.html.erb +51 -0
- data/app/views/ib/executions/new.html.erb +5 -0
- data/app/views/ib/executions/show.html.erb +80 -0
- data/app/views/ib/order_states/_form.html.erb +93 -0
- data/app/views/ib/order_states/edit.html.erb +6 -0
- data/app/views/ib/order_states/index.html.erb +59 -0
- data/app/views/ib/order_states/new.html.erb +5 -0
- data/app/views/ib/order_states/show.html.erb +100 -0
- data/app/views/ib/orders/_form.html.erb +353 -0
- data/app/views/ib/orders/edit.html.erb +6 -0
- data/app/views/ib/orders/index.html.erb +193 -0
- data/app/views/ib/orders/new.html.erb +5 -0
- data/app/views/ib/orders/show.html.erb +435 -0
- data/bin/scaffold.rb +29 -0
- data/config/routes.rb +8 -1
- data/db/config.yml +5 -0
- data/db/migrate/101_add_ib_executions.rb +3 -0
- data/db/migrate/111_add_ib_bars.rb +6 -0
- data/db/migrate/121_add_ib_order_states.rb +8 -0
- data/db/migrate/131_add_ib_orders.rb +24 -0
- data/db/migrate/141_add_ib_combo_legs.rb +6 -0
- data/db/migrate/151_add_ib_underlyings.rb +3 -0
- data/db/migrate/161_add_ib_contract_details.rb +11 -0
- data/db/migrate/171_add_ib_contracts.rb +8 -1
- data/db/schema.rb +6 -5
- data/lib/ib/base.rb +3 -1
- data/lib/ib/base_properties.rb +26 -15
- data/lib/ib/connection.rb +3 -2
- data/lib/ib/errors.rb +16 -9
- data/lib/ib/extensions.rb +6 -4
- data/lib/ib/symbols.rb +10 -3
- data/lib/ib/symbols/forex.rb +49 -64
- data/lib/ib/symbols/futures.rb +2 -3
- data/lib/ib/symbols/options.rb +2 -1
- data/lib/ib/symbols/stocks.rb +2 -1
- data/lib/models/ib/bar.rb +6 -2
- data/lib/models/ib/combo_leg.rb +4 -3
- data/lib/models/ib/contract.rb +9 -5
- data/lib/models/ib/contract_detail.rb +1 -1
- data/lib/models/ib/execution.rb +3 -1
- data/lib/models/ib/order.rb +22 -20
- data/lib/models/ib/order_state.rb +4 -2
- data/lib/models/ib/underlying.rb +3 -4
- data/spec/README.md +12 -10
- data/spec/ib/symbols/symbols_spec.rb +10 -0
- data/spec/integration_helper.rb +1 -1
- data/spec/model_helper.rb +9 -8
- data/spec/models/ib/combo_leg_spec.rb +29 -28
- data/spec/models/ib/contract_detail_spec.rb +4 -1
- data/spec/models/ib/contract_spec.rb +66 -58
- data/spec/models/ib/execution_spec.rb +50 -44
- data/spec/models/ib/order_spec.rb +2 -2
- data/spec/order_helper.rb +5 -4
- data/spec/spec_helper.rb +3 -3
- metadata +59 -35
- data/app/models/ib/underlying.rb +0 -5
- data/bin/account_info +0 -29
- data/bin/cancel_orders +0 -27
- data/bin/contract_details +0 -35
- data/bin/depth_of_market +0 -43
- data/bin/fa_accounts +0 -22
- data/bin/fundamental_data +0 -39
- data/bin/historic_data +0 -51
- data/bin/historic_data_cli +0 -182
- data/bin/list_orders +0 -28
- data/bin/market_data +0 -41
- data/bin/option_data +0 -44
- data/bin/place_combo_order +0 -58
- data/bin/place_order +0 -27
- data/bin/template +0 -18
- data/bin/tick_data +0 -26
- data/bin/time_and_sales +0 -53
data/app/models/ib/underlying.rb
DELETED
data/bin/account_info
DELETED
@@ -1,29 +0,0 @@
|
|
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 'rubygems'
|
7
|
-
require 'bundler/setup'
|
8
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
9
|
-
require 'ib-ruby'
|
10
|
-
|
11
|
-
# First, connect to IB TWS.
|
12
|
-
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
13
|
-
|
14
|
-
# Set log level
|
15
|
-
log.level = Logger::FATAL
|
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_message :RequestAccountData, :subscribe => true
|
23
|
-
|
24
|
-
puts "\nSubscribing to IB account data"
|
25
|
-
puts "\n******** Press <Enter> to cancel... *********\n\n"
|
26
|
-
STDIN.gets
|
27
|
-
puts "Cancelling account data subscription.."
|
28
|
-
|
29
|
-
ib.send_message :RequestAccountData, :subscribe => false
|
data/bin/cancel_orders
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script allows you to cancel either a set of open Orders by their ids,
|
4
|
-
# or ALL Orders opened via IB API at once. The latter is useful when your
|
5
|
-
# robot goes crazy and opens gazillions of wrong limit orders.
|
6
|
-
|
7
|
-
require 'rubygems'
|
8
|
-
require 'bundler/setup'
|
9
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
10
|
-
require 'ib-ruby'
|
11
|
-
|
12
|
-
# First, connect to IB TWS.
|
13
|
-
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
14
|
-
|
15
|
-
# Subscribe to TWS alerts/errors and order-related messages
|
16
|
-
ib.subscribe(:Alert, :OpenOrder, :OrderStatus, :OpenOrderEnd) { |msg| puts msg.to_human }
|
17
|
-
|
18
|
-
if ARGV.empty?
|
19
|
-
ib.send_message :RequestGlobalCancel
|
20
|
-
else
|
21
|
-
# Will only work for Orders placed under the same :client_id
|
22
|
-
ib.cancel_order *ARGV
|
23
|
-
end
|
24
|
-
|
25
|
-
ib.send_message :RequestAllOpenOrders
|
26
|
-
|
27
|
-
sleep 3
|
data/bin/contract_details
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script gets details for specific contract from IB
|
4
|
-
|
5
|
-
require 'rubygems'
|
6
|
-
require 'bundler/setup'
|
7
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
8
|
-
require 'ib-ruby'
|
9
|
-
|
10
|
-
# Definition of what we want market data for. We have to keep track of what ticker id
|
11
|
-
# corresponds to what symbol ourselves, because the ticks don't include any other
|
12
|
-
# identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
|
13
|
-
@market = {122 => IB::Symbols::Stocks[:wfc],
|
14
|
-
133 => IB::Symbols::Options[:wfc20],
|
15
|
-
144 => IB::Symbols::Stocks[:wrong]}
|
16
|
-
|
17
|
-
# Connect to IB TWS.
|
18
|
-
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
19
|
-
|
20
|
-
# Subscribe to TWS alerts/errors
|
21
|
-
ib.subscribe(IB::Messages::Incoming::Alert) { |msg| puts msg.to_human }
|
22
|
-
|
23
|
-
# Now, subscribe to ContractData incoming events. The code passed in the block
|
24
|
-
# will be executed when a message of that type is received, with the received
|
25
|
-
# message as its argument. In this case, we just print out the data.
|
26
|
-
ib.subscribe(:ContractData) { |msg| puts msg.contract.inspect }
|
27
|
-
|
28
|
-
# Now we actually request Contract details for the symbols we're interested in. TWS will
|
29
|
-
# respond with ContractData messages, which will be processed by the code above.
|
30
|
-
@market.each_pair do |id, contract|
|
31
|
-
ib.send_message :RequestContractData, :id => id, :contract => contract
|
32
|
-
end
|
33
|
-
|
34
|
-
# Wait for IB to respond to our request
|
35
|
-
ib.wait_for :ContractDataEnd
|
data/bin/depth_of_market
DELETED
@@ -1,43 +0,0 @@
|
|
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 'rubygems'
|
7
|
-
require 'bundler/setup'
|
8
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
9
|
-
require 'ib-ruby'
|
10
|
-
|
11
|
-
# Definition of what we want L2 data for. We have to keep track of what ticker id
|
12
|
-
# corresponds to what symbol ourselves, because the ticks don't include any other
|
13
|
-
# identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
|
14
|
-
@market = {123 => IB::Symbols::Stocks[:wfc],
|
15
|
-
456 => IB::Symbols::Futures[:es],
|
16
|
-
789 => IB::Symbols::Forex[:gbpusd]
|
17
|
-
}
|
18
|
-
|
19
|
-
# First, connect to IB TWS.
|
20
|
-
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
21
|
-
|
22
|
-
# Subscribe to TWS alerts/errors
|
23
|
-
ib.subscribe(:Alert) { |msg| puts msg.to_human }
|
24
|
-
|
25
|
-
# Subscribe to MarketDepth events.
|
26
|
-
ib.subscribe(:MarketDepth) do |msg|
|
27
|
-
puts @market[msg.request_id].description + ": " + msg.to_human
|
28
|
-
end
|
29
|
-
|
30
|
-
# Now we actually request L2 market data for the symbols we're interested in.
|
31
|
-
@market.each_pair do |id, contract|
|
32
|
-
ib.send_message :RequestMarketDepth,
|
33
|
-
:id => id,
|
34
|
-
:contract => contract,
|
35
|
-
:num_rows => 5
|
36
|
-
end
|
37
|
-
|
38
|
-
puts "\nSubscribed to market data"
|
39
|
-
puts "\n******** Press <Enter> to cancel... *********\n\n"
|
40
|
-
STDIN.gets
|
41
|
-
puts "Cancelling market data subscription.."
|
42
|
-
|
43
|
-
@market.each_pair { |id, contract| ib.send_message :CancelMarketDepth, :id => id }
|
data/bin/fa_accounts
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script receives Financial Adviser and Managed Accounts info
|
4
|
-
|
5
|
-
require 'rubygems'
|
6
|
-
require 'bundler/setup'
|
7
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
8
|
-
require 'ib-ruby'
|
9
|
-
|
10
|
-
# First, connect to IB TWS.
|
11
|
-
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
12
|
-
|
13
|
-
# Subscribe to TWS alerts/errors and FA/managed account info
|
14
|
-
ib.subscribe(:Alert, :ManagedAccounts, :ReceiveFA) { |msg| puts msg.to_human }
|
15
|
-
|
16
|
-
ib.send_message :RequestFA
|
17
|
-
ib.send_message :RequestManagedAccounts
|
18
|
-
|
19
|
-
ib.wait_for :Alert
|
20
|
-
|
21
|
-
puts "\n******** Press <Enter> to cancel... *********\n\n"
|
22
|
-
STDIN.gets
|
data/bin/fundamental_data
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script downloads Fundamental data for specific symbols from IB
|
4
|
-
# This only works IF you have Reuters data subscription!
|
5
|
-
|
6
|
-
require 'rubygems'
|
7
|
-
require 'bundler/setup'
|
8
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
9
|
-
|
10
|
-
require 'ib-ruby'
|
11
|
-
require 'xmlsimple'
|
12
|
-
require 'pp'
|
13
|
-
|
14
|
-
|
15
|
-
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
16
|
-
|
17
|
-
ib.subscribe(:Alert) { |msg| puts msg.to_human }
|
18
|
-
|
19
|
-
# Fundamental Data will arrive as XML, parse it
|
20
|
-
ib.subscribe(:FundamentalData) { |msg| @xml = XmlSimple.xml_in(msg.data) }
|
21
|
-
|
22
|
-
ibm = IB::Contract.new :symbol => 'IBM',
|
23
|
-
:exchange => 'NYSE',
|
24
|
-
:currency => 'USD',
|
25
|
-
:sec_type => 'STK'
|
26
|
-
|
27
|
-
# Request Fundamental Data for IBM. Possible report types:
|
28
|
-
# 'estimates' - Estimates
|
29
|
-
# 'finstat' - Financial statements
|
30
|
-
# 'snapshot' - Summary
|
31
|
-
ib.send_message :RequestFundamentalData,
|
32
|
-
:id => 10,
|
33
|
-
:contract => ibm,
|
34
|
-
:report_type => 'snapshot'
|
35
|
-
|
36
|
-
# Needs some time to receive and parse XML. Standard timeout of 1 sec is just too low.
|
37
|
-
ib.wait_for(30) { @xml}
|
38
|
-
|
39
|
-
pp @xml
|
data/bin/historic_data
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script downloads historic data for specific symbols from IB
|
4
|
-
|
5
|
-
require 'rubygems'
|
6
|
-
require 'bundler/setup'
|
7
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
8
|
-
require 'ib-ruby'
|
9
|
-
|
10
|
-
# Definition of what we want data for. We have to keep track of what ticker id
|
11
|
-
# corresponds to what symbol ourselves, because the ticks don't include any other
|
12
|
-
# identifying information. The choice of ticker ids is, as far as I can tell, arbitrary.
|
13
|
-
@market = {123 => IB::Symbols::Stocks[:wfc],
|
14
|
-
456 => IB::Symbols::Futures[:ym],
|
15
|
-
789 => IB::Symbols::Forex[:gbpusd] # No historical data for GBP/CASH@IDEALPRO
|
16
|
-
}
|
17
|
-
|
18
|
-
# Connect to IB TWS.
|
19
|
-
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
20
|
-
|
21
|
-
# Subscribe to TWS alerts/errors
|
22
|
-
ib.subscribe(:Alert) { |msg| puts msg.to_human }
|
23
|
-
|
24
|
-
# Subscribe to HistoricalData incoming events. The code passed in the block
|
25
|
-
# will be executed when a message of that type is received, with the received
|
26
|
-
# message as its argument. In this case, we just print out the data.
|
27
|
-
#
|
28
|
-
# Note that we have to look the ticker id of each incoming message
|
29
|
-
# up in local memory to figure out what it's for.
|
30
|
-
ib.subscribe(IB::Messages::Incoming::HistoricalData) do |msg|
|
31
|
-
puts @market[msg.request_id].description + ": #{msg.count} items:"
|
32
|
-
msg.results.each { |entry| puts " #{entry}" }
|
33
|
-
@last_msg_time = Time.now.to_i
|
34
|
-
end
|
35
|
-
|
36
|
-
# Now we actually request historical data for the symbols we're interested in. TWS will
|
37
|
-
# respond with a HistoricalData message, which will be processed by the code above.
|
38
|
-
@market.each_pair do |id, contract|
|
39
|
-
ib.send_message IB::Messages::Outgoing::RequestHistoricalData.new(
|
40
|
-
:request_id => id,
|
41
|
-
:contract => contract,
|
42
|
-
:end_date_time => Time.now.to_ib,
|
43
|
-
:duration => '2 D', # ?
|
44
|
-
:bar_size => '1 min', # IB::BAR_SIZES.key(:hour)?
|
45
|
-
:what_to_show => :trades,
|
46
|
-
:use_rth => 1,
|
47
|
-
:format_date => 1)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Wait for IB to respond to our request
|
51
|
-
sleep 0.1 until @last_msg_time && @last_msg_time < Time.now.to_i + 0.5
|
data/bin/historic_data_cli
DELETED
@@ -1,182 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# This script connects to IB API, and downloads historic data
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
|
-
require 'time'
|
6
|
-
require 'getopt/long'
|
7
|
-
require 'bundler/setup'
|
8
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
9
|
-
require 'ib-ruby'
|
10
|
-
|
11
|
-
include Getopt
|
12
|
-
|
13
|
-
opt = Getopt::Long.getopts(
|
14
|
-
["--help", BOOLEAN],
|
15
|
-
["--end", REQUIRED],
|
16
|
-
["--port", REQUIRED],
|
17
|
-
["--security", REQUIRED],
|
18
|
-
["--duration", REQUIRED],
|
19
|
-
["--barsize", REQUIRED],
|
20
|
-
["--csv", BOOLEAN],
|
21
|
-
["--dateformat", REQUIRED],
|
22
|
-
["--nonregularhours", BOOLEAN]
|
23
|
-
)
|
24
|
-
|
25
|
-
if opt["help"] || opt["security"].nil? || opt["security"].empty?
|
26
|
-
puts <<ENDHELP
|
27
|
-
|
28
|
-
This program requires a TWS or Gateway running on localhost.
|
29
|
-
|
30
|
-
----------
|
31
|
-
|
32
|
-
One argument is required: --security, the security specification you want, in
|
33
|
-
"long serialized IB-Ruby" format. This is a colon-separated string of the format:
|
34
|
-
|
35
|
-
symbol:security_type:expiry:strike:right:multiplier:exchange:primary_exchange:currency:local_symbol
|
36
|
-
|
37
|
-
Fields not needed for a particular security should be left blank (e.g. strike and right are only relevant for options.)
|
38
|
-
|
39
|
-
For example, to query the Apple 500 Strike Call expiring in January 2013, use:
|
40
|
-
|
41
|
-
$ historic_data_cli --security AAPL:OPT:201301:500:CALL::SMART::USD:
|
42
|
-
|
43
|
-
Consult contract.rb for allowed values, and see also the examples in the symbols/ directory
|
44
|
-
(load them in irb and run security#serialize_ib_ruby to see the appropriate string.)
|
45
|
-
|
46
|
-
----------
|
47
|
-
|
48
|
-
Options:
|
49
|
-
|
50
|
-
--end is is the last time we want data for. The default is now.
|
51
|
-
This is eval'ed by Ruby, so you can use a Ruby expression, which must return a Time object.
|
52
|
-
|
53
|
-
--duration is time period before --end, in seconds. The default is 86400 sec (1 day).
|
54
|
-
TWS imposes limit of 86400 sec (1 day) worth of historic data per request.
|
55
|
-
|
56
|
-
--what determines what the data will be comprised of. This can be
|
57
|
-
"trades", "midpoint", "bid", or "ask". The default is "trades".
|
58
|
-
|
59
|
-
--barsize determines how long each bar will be.
|
60
|
-
|
61
|
-
Possible bar values (from the IB documentation):
|
62
|
-
Values less than 30 sec do not appear to work for some securities.
|
63
|
-
|
64
|
-
sec1 = 1 sec
|
65
|
-
sec5 = 5 sec
|
66
|
-
sec15 = 15 sec
|
67
|
-
sec30 = 30 sec
|
68
|
-
min1 = 1 minute
|
69
|
-
min2 = 2 minutes
|
70
|
-
min5 = 5 minutes
|
71
|
-
min15 = 15 minutes (default)
|
72
|
-
min30 = 30 minutes
|
73
|
-
hour1 = 1 hour
|
74
|
-
day1 = 1 day
|
75
|
-
|
76
|
-
--nonregularhours : Normally, only data from the instrument's regular trading
|
77
|
-
hours is returned. If --nonregularhours is given, all data available during the time
|
78
|
-
span requested is returned, even for time intervals when the market was illiquid.
|
79
|
-
|
80
|
-
--dateformat : 1 (default) human-readable time/date format, like "20050307 11:32:16".
|
81
|
-
If you set it to 2 instead, you will get UNIX epoch offsets (seconds since Jan 1, 1970).
|
82
|
-
|
83
|
-
--csv : print out the historic data in CSV format, with header.
|
84
|
-
|
85
|
-
--port : 4001 for Gateway (default), 7496 for TWS, or your custom port
|
86
|
-
|
87
|
-
ENDHELP
|
88
|
-
exit
|
89
|
-
end
|
90
|
-
|
91
|
-
### Parameters
|
92
|
-
|
93
|
-
# DURATION is how much historic data we want, in seconds, before END_DATE_TIME.
|
94
|
-
DURATION = (opt["duration"] && opt["duration"].to_i) || 86400
|
95
|
-
|
96
|
-
if DURATION > 86400
|
97
|
-
STDERR.puts("\nTWS rejects --duration longer than 86400 seconds (1 day).\n")
|
98
|
-
exit(1)
|
99
|
-
end
|
100
|
-
|
101
|
-
# This is the last time we want data for.
|
102
|
-
END_DATE_TIME = (opt["end"] && eval(opt["end"]).to_ib) || Time.now.to_ib
|
103
|
-
|
104
|
-
# This can be :trades, :midpoint, :bid, or :asked
|
105
|
-
WHAT = (opt["what"] && opt["what"].to_sym) || :trades
|
106
|
-
|
107
|
-
|
108
|
-
# Values less than 4 do not appear to actually work; they are rejected by the server.
|
109
|
-
#
|
110
|
-
BAR_SIZE = (opt["barsize"] && opt["barsize"].to_sym) || :min15
|
111
|
-
|
112
|
-
# If REGULAR_HOURS_ONLY is set to 0, all data available during the time
|
113
|
-
# span requested is returned, even data bars covering time
|
114
|
-
# intervals where the market in question was illiquid. If useRTH
|
115
|
-
# has a non-zero value, only data within the "Regular Trading
|
116
|
-
# Hours" of the product in question is returned, even if the time
|
117
|
-
# span requested falls partially or completely outside of them.
|
118
|
-
|
119
|
-
REGULAR_HOURS_ONLY = opt["nonregularhours"] ? 0 : 1
|
120
|
-
|
121
|
-
# Using a DATE_FORMAT of 1 will cause the dates in the returned
|
122
|
-
# messages with the historic data to be in a text format, like
|
123
|
-
# "20050307 11:32:16". If you set :format_date to 2 instead, you
|
124
|
-
# will get an offset in seconds from the beginning of 1970, which
|
125
|
-
# is the same format as the UNIX epoch time.
|
126
|
-
|
127
|
-
DATE_FORMAT = (opt["dateformat"] && opt["dateformat"].to_i) || 1
|
128
|
-
|
129
|
-
PORT = (opt["port"] && opt["port"]) || '4001'
|
130
|
-
|
131
|
-
# First, connect to IB TWS.
|
132
|
-
ib = IB::Connection.new :client_id => 1112 #, :port => 7496 # TWS
|
133
|
-
|
134
|
-
# Subscribe to TWS alerts/errors
|
135
|
-
ib.subscribe(:Alert) { |msg| puts msg.to_human }
|
136
|
-
|
137
|
-
lastMessageTime = Queue.new # for communicating with the reader thread.
|
138
|
-
|
139
|
-
# Subscribe to incoming HistoricalData events. The code passed in the
|
140
|
-
# block will be executed when a message of the subscribed type is
|
141
|
-
# received, with the received message as its argument. In this case,
|
142
|
-
# we just print out the data.
|
143
|
-
#
|
144
|
-
# Note that we have to look the ticker id of each incoming message
|
145
|
-
# up in local memory to figure out what security it relates to.
|
146
|
-
# The incoming message packet from TWS just identifies it by ticker id.
|
147
|
-
#
|
148
|
-
ib.subscribe(:HistoricalData) do |msg|
|
149
|
-
if opt["csv"]
|
150
|
-
puts "date,time,open,high,low,close,volume,wap,has_gaps"
|
151
|
-
msg.results.each do |datum|
|
152
|
-
puts "#{datum.time},#{datum.open},#{datum.high},#{datum.low}," +
|
153
|
-
"#{datum.close},#{datum.volume},#{datum.wap},#{datum.has_gaps}"
|
154
|
-
end
|
155
|
-
else
|
156
|
-
STDERR.puts "Received #{msg.count} items:"
|
157
|
-
msg.results.each { |datum| puts datum.to_s }
|
158
|
-
end
|
159
|
-
lastMessageTime.push(Time.now)
|
160
|
-
end
|
161
|
-
|
162
|
-
# Now we actually request historical data for the symbols we're
|
163
|
-
# interested in. TWS will respond with a HistoricalData message,
|
164
|
-
# which will be received by the code above.
|
165
|
-
ib.send_message :RequestHistoricalData,
|
166
|
-
:request_id => 123,
|
167
|
-
:contract => opt["security"],
|
168
|
-
:end_date_time => END_DATE_TIME,
|
169
|
-
:duration => DURATION, # seconds == 1 hour
|
170
|
-
:bar_size => BAR_SIZE, # 1 minute bars
|
171
|
-
:what_to_show => WHAT,
|
172
|
-
:use_RTH => REGULAR_HOURS_ONLY,
|
173
|
-
:format_date => DATE_FORMAT
|
174
|
-
|
175
|
-
# A complication here is that IB does not send any indication when all historic data is done being delivered.
|
176
|
-
# So we have to guess - when there is no more new data for some period, we interpret that as "end of data" and exit.
|
177
|
-
while true
|
178
|
-
lastTime = lastMessageTime.pop # blocks until a message is ready on the queue
|
179
|
-
sleep 2 # .. wait ..
|
180
|
-
exit if lastMessageTime.empty? # if still no more messages after 2 more seconds, exit.
|
181
|
-
end
|
182
|
-
|
data/bin/list_orders
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script retrieves list of all Orders from TWS
|
4
|
-
|
5
|
-
require 'rubygems'
|
6
|
-
require 'bundler/setup'
|
7
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
8
|
-
require 'ib-ruby'
|
9
|
-
|
10
|
-
# Connect to IB as 0 (TWS) to retrieve all Orders, including TWS-generated ones
|
11
|
-
ib = IB::Connection.new :client_id => 0 #, :port => 7496 # TWS
|
12
|
-
|
13
|
-
# Subscribe to TWS alerts/errors and order-related messages
|
14
|
-
@counter = 0
|
15
|
-
|
16
|
-
ib.subscribe(:Alert, :OrderStatus, :OpenOrderEnd) { |msg| puts msg.to_human }
|
17
|
-
|
18
|
-
ib.subscribe(:OpenOrder) do |msg|
|
19
|
-
@counter += 1
|
20
|
-
puts "#{@counter}: #{msg.to_human}"
|
21
|
-
#pp msg.order
|
22
|
-
end
|
23
|
-
|
24
|
-
ib.send_message :RequestAllOpenOrders
|
25
|
-
|
26
|
-
# Wait for IB to respond to our request
|
27
|
-
ib.wait_for :OpenOrderEnd
|
28
|
-
sleep 1 # Let printer do the job
|