ib-api 972.2 → 972.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/ib/connection.rb +13 -2
- data/lib/ib/messages/incoming/account_value.rb +5 -1
- data/lib/ib/messages/incoming/historical_data.rb +25 -5
- data/lib/ib/messages/outgoing/bar_requests.rb +4 -5
- data/lib/ib/support.rb +30 -15
- data/lib/models/ib/bag.rb +6 -0
- data/lib/models/ib/bar.rb +1 -1
- data/lib/models/ib/combo_leg.rb +22 -0
- data/lib/models/ib/contract.rb +31 -39
- data/lib/models/ib/spread.rb +22 -17
- metadata +3 -16
- data/example/README.md +0 -76
- data/example/account_info +0 -54
- data/example/account_positions +0 -30
- data/example/account_summary +0 -88
- data/example/cancel_orders +0 -74
- data/example/fa_accounts +0 -25
- data/example/fundamental_data +0 -40
- data/example/historic_data_cli +0 -186
- data/example/list_orders +0 -45
- data/example/portfolio_csv +0 -81
- data/example/scanner_data +0 -62
- data/example/template +0 -19
- data/example/tick_data +0 -28
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ib-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '972.
|
4
|
+
version: '972.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hartmut Bischoff
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -103,19 +103,6 @@ files:
|
|
103
103
|
- bin/console.yml
|
104
104
|
- bin/setup
|
105
105
|
- changelog.md
|
106
|
-
- example/README.md
|
107
|
-
- example/account_info
|
108
|
-
- example/account_positions
|
109
|
-
- example/account_summary
|
110
|
-
- example/cancel_orders
|
111
|
-
- example/fa_accounts
|
112
|
-
- example/fundamental_data
|
113
|
-
- example/historic_data_cli
|
114
|
-
- example/list_orders
|
115
|
-
- example/portfolio_csv
|
116
|
-
- example/scanner_data
|
117
|
-
- example/template
|
118
|
-
- example/tick_data
|
119
106
|
- lib/extensions/class-extensions.rb
|
120
107
|
- lib/ib-api.rb
|
121
108
|
- lib/ib/base.rb
|
@@ -197,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
197
184
|
- !ruby/object:Gem::Version
|
198
185
|
version: '0'
|
199
186
|
requirements: []
|
200
|
-
rubygems_version: 3.
|
187
|
+
rubygems_version: 3.2.3
|
201
188
|
signing_key:
|
202
189
|
specification_version: 4
|
203
190
|
summary: Ruby Implementation of the Interactive Brokers TWS API
|
data/example/README.md
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
## IB-RUBY EXAMPLES:
|
2
|
-
|
3
|
-
This folder contains sample scripts that demonstrate common ib-ruby use cases.
|
4
|
-
The scripts show you how to access account info, print real time quotes, retrieve
|
5
|
-
historic or fundamental data, request options calculations, place, list, and cancel orders.
|
6
|
-
You may also want to look into `spec/integration` directory for more scenarios,
|
7
|
-
use cases and examples of handling IB messages.
|
8
|
-
|
9
|
-
Normally you run these examples like this:
|
10
|
-
|
11
|
-
$ ruby example/list_orders
|
12
|
-
|
13
|
-
The examples are executable.
|
14
|
-
If you're on Unix-like platform, they can be called directly ( » ./{script} «)
|
15
|
-
|
16
|
-
The Examples assume a running Gateway-Application on Localhost. Please use a Demo-Account or run
|
17
|
-
the API in »read-only-mode«
|
18
|
-
|
19
|
-
## EXAMPLE DESCRIPTION:
|
20
|
-
|
21
|
-
*account_info* - Request your account info, current positions, portfolio values and so on
|
22
|
-
|
23
|
-
$ ruby example/account_info # or cd example; ./account_info
|
24
|
-
|
25
|
-
For Financial Advisors, you need to add the managed account you want info for:
|
26
|
-
|
27
|
-
$ ruby example/account_info U123456
|
28
|
-
|
29
|
-
*cancel_orders* - Cancel either all open orders, or specific order(s), by their (local) ids. Examples:
|
30
|
-
|
31
|
-
$ ruby example/cancel_orders
|
32
|
-
$ ruby example/cancel_orders 492 495
|
33
|
-
|
34
|
-
*contract_details* - Obtain detailed descriptions for specific Stock, Option, Forex, Futures and Bond contracts.
|
35
|
-
|
36
|
-
*contract_sample details* - Define Contract samples provided by java and python API-implementations
|
37
|
-
|
38
|
-
*depth_of_market* - Receive a stream of MarketDepth change events for Stock, Forex and Future symbols.
|
39
|
-
|
40
|
-
*fa_accounts* - Get info about accounts under management (for Financial Advisors).
|
41
|
-
|
42
|
-
*flex_query* - Run a pre-defined Flex query, receive and print Flex report. Example:
|
43
|
-
|
44
|
-
$ ruby example/flex_query 12345 # Flex query id pre-defined in Account Management
|
45
|
-
|
46
|
-
*fundamental_data* - Request and print fundamental data report for a specific stock.
|
47
|
-
|
48
|
-
*historic_data* - Receive 5 days of 1-hour trade data for Stock, Forex and Future symbols.
|
49
|
-
|
50
|
-
*historic_data_cli* - CLI script for historic data downloading. It has many options, for detailed help run:
|
51
|
-
|
52
|
-
$ ruby example/historic_data_cli
|
53
|
-
|
54
|
-
*list_orders* - List all open API orders.
|
55
|
-
|
56
|
-
*market_data* - Receive a stream of trade events for multiple Forex symbols.
|
57
|
-
|
58
|
-
*option_data* - Receive a stream of underlying, price and greeks calculations for multiple Option symbols.
|
59
|
-
|
60
|
-
*place_braket_order* - Place a braket order for Stock.
|
61
|
-
|
62
|
-
*place_combo_order* - Place an Option combo order (Google butterfly).
|
63
|
-
|
64
|
-
*place_order* - Place a simple limit order to buy Stock.
|
65
|
-
|
66
|
-
*portfolio_csv* - Exports your IB portfolio in a CSV format. Usage:
|
67
|
-
|
68
|
-
$ ruby example/portfolio_csv [account] > my_portfolio.csv
|
69
|
-
|
70
|
-
*real_time_data* - Subscribe to real time data for specific symbol.
|
71
|
-
|
72
|
-
*template* - A blank example to start a new script (setting up all the dependencies).
|
73
|
-
|
74
|
-
*tick_data* - Subscribe to extended tick types for a single stock symbol.
|
75
|
-
|
76
|
-
*time_and_sales* - Print out Time&Sales format for Futures symbols.
|
data/example/account_info
DELETED
@@ -1,54 +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 'bundler/setup'
|
7
|
-
require 'ib-api'
|
8
|
-
|
9
|
-
# Only for Advisor accounts: you can provide account_code such as U666777 (otherwise the last account is used)
|
10
|
-
account_code = ARGV[0] || ''
|
11
|
-
|
12
|
-
include IB
|
13
|
-
# Connect to IB TWS
|
14
|
-
accounts = []
|
15
|
-
ib = Connection.new client_id: 1113, port: 4002 do | gw | # :port => 7497 # TWS
|
16
|
-
|
17
|
-
# Subscribe to TWS alerts/errors and account-related messages
|
18
|
-
# that TWS sends in response to account data request
|
19
|
-
gw.subscribe(:Alert) do |msg|
|
20
|
-
## if an account is not given. but required, (Error 321 indicates this)
|
21
|
-
## fetch data from the last account detected. (The first is most probably the Advisor-Account)
|
22
|
-
if msg.code == 321
|
23
|
-
gw.send_message :RequestAccountData, :subscribe => true, :account_code => accounts.last
|
24
|
-
else
|
25
|
-
puts msg.to_human
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
## Print Account+Portfolio-Values
|
30
|
-
gw.subscribe(:AccountValue,
|
31
|
-
:PortfolioValue, :AccountUpdateTime) { |msg| puts msg.to_human }
|
32
|
-
|
33
|
-
## Just in case: put account-names into accounts-array
|
34
|
-
gw.subscribe(:ManagedAccounts){ |msg| accounts = msg.accounts_list.split ',' }
|
35
|
-
|
36
|
-
# Set log level
|
37
|
-
gw.logger.level = Logger::FATAL # DEBUG #FATAL
|
38
|
-
end
|
39
|
-
|
40
|
-
ib.send_message :RequestAccountData, :subscribe => true, :account_code => account_code
|
41
|
-
|
42
|
-
puts "\nSubscribing to IB account data"
|
43
|
-
|
44
|
-
## print message after recieving account-data
|
45
|
-
Thread.new do
|
46
|
-
sleep 3
|
47
|
-
puts "\n******** Press <Enter> to quit *********\n\n"
|
48
|
-
end
|
49
|
-
|
50
|
-
STDIN.gets
|
51
|
-
puts "Cancelling account data subscription.."
|
52
|
-
|
53
|
-
ib.send_message :RequestAccountData, :subscribe => false
|
54
|
-
sleep 2
|
data/example/account_positions
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script connects to IB API and subscribes to Position Values which are updated regulary
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'ib-api'
|
7
|
-
|
8
|
-
|
9
|
-
# connect to IB TWS.
|
10
|
-
|
11
|
-
|
12
|
-
ib = IB::Connection.new( :client_id => 1110) do | gw | #, :port => 7496 # TWS)
|
13
|
-
## Subcribe to forseable events before the connection is completed
|
14
|
-
## Subscribe to TWS alerts/errors
|
15
|
-
gw.subscribe(:Alert, :PositionData){ |msg| puts msg.to_human }
|
16
|
-
gw.logger.level = Logger::FATAL # DEBUG -- INFO -- WARN -- ERROR -- FATAL
|
17
|
-
end
|
18
|
-
|
19
|
-
Thread.new do
|
20
|
-
sleep 1
|
21
|
-
puts "\n******** Press <Enter> to quit *********\n\n"
|
22
|
-
end
|
23
|
-
# request the AccountSummary
|
24
|
-
ib.send_message :RequestPositions
|
25
|
-
|
26
|
-
STDIN.gets
|
27
|
-
puts "\n *** canceling Reqest ..."
|
28
|
-
ib.send_message :CancelPositions
|
29
|
-
sleep 1
|
30
|
-
puts "done."
|
data/example/account_summary
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script connects to IB API and subscribes to Account Summary Updates for certain tags
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'ib-api'
|
7
|
-
|
8
|
-
# Definition of what we want listed
|
9
|
-
# possible tags
|
10
|
-
# NetLiquidation,
|
11
|
-
# TotalCashValue - Total cash including futures pnl
|
12
|
-
# SettledCash - For cash accounts, this is the same as
|
13
|
-
# TotalCashValue
|
14
|
-
# AccruedCash - Net accrued interest
|
15
|
-
# BuyingPower - The maximum amount of marginable US stocks the
|
16
|
-
# account can buy
|
17
|
-
# EquityWithLoanValue - Cash + stocks + bonds + mutual funds
|
18
|
-
# PreviousDayEquityWithLoanValue,
|
19
|
-
# GrossPositionValue - The sum of the absolute value of all stock
|
20
|
-
# and equity option positions
|
21
|
-
# RegTEquity,
|
22
|
-
# RegTMargin,
|
23
|
-
# SMA - Special Memorandum Account
|
24
|
-
# InitMarginReq,
|
25
|
-
# MaintMarginReq,
|
26
|
-
# AvailableFunds,
|
27
|
-
# ExcessLiquidity,
|
28
|
-
# Cushion - Excess liquidity as a percentage of net liquidation value
|
29
|
-
# FullInitMarginReq,
|
30
|
-
# FullMaintMarginReq,
|
31
|
-
# FullAvailableFunds,
|
32
|
-
# FullExcessLiquidity,
|
33
|
-
# LookAheadNextChange - Time when look-ahead values take effect
|
34
|
-
# LookAheadInitMarginReq,
|
35
|
-
# LookAheadMaintMarginReq,
|
36
|
-
# LookAheadAvailableFunds,
|
37
|
-
# LookAheadExcessLiquidity,
|
38
|
-
# HighestSeverity - A measure of how close the account is to liquidation
|
39
|
-
# DayTradesRemaining - The Number of Open/Close trades a user
|
40
|
-
# could put on before Pattern Day Trading is detected. A value of "-1"
|
41
|
-
# means that the user can put on unlimited day trades.
|
42
|
-
# Leverage - GrossPositionValue / NetLiquidation
|
43
|
-
# $LEDGER - Single flag to relay all cash balance tags*, only in base
|
44
|
-
# currency.
|
45
|
-
# $LEDGER:CURRENCY - Single flag to relay all cash balance tags*, only in
|
46
|
-
# the specified currency.
|
47
|
-
# $LEDGER:ALL - Single flag to relay all cash balance tags* in all
|
48
|
-
#
|
49
|
-
tags = %w( NetLiquidation InitMarginReq DayTradesRemaining )
|
50
|
-
# connect to IB TWS.
|
51
|
-
|
52
|
-
|
53
|
-
ib = IB::Connection.new( :client_id => 1112) do | gw | #, :port => 7496 # TWS)
|
54
|
-
## Subcribe to forseable events before the connection is completed
|
55
|
-
## Subscribe to TWS alerts/errors
|
56
|
-
gw.subscribe(:Alert, :AccountSummary){ |msg| puts msg.to_human }
|
57
|
-
gw.logger.level = Logger::FATAL # DEBUG -- INFO -- WARN -- ERROR -- FATAL
|
58
|
-
end
|
59
|
-
|
60
|
-
Thread.new do
|
61
|
-
sleep 1
|
62
|
-
puts "\n******** Press <Enter> to quit *********\n\n"
|
63
|
-
end
|
64
|
-
# request the AccountSummary
|
65
|
-
request_id = ib.send_message :RequestAccountSummary, tags: tags.join(',')
|
66
|
-
|
67
|
-
STDIN.gets
|
68
|
-
puts "\n *** canceling Request ..."
|
69
|
-
ib.send_message :CancelAccountSummary, id: request_id
|
70
|
-
sleep 1
|
71
|
-
puts "done."
|
72
|
-
|
73
|
-
|
74
|
-
=begin
|
75
|
-
Expected Output
|
76
|
-
|
77
|
-
delta:~/workspace/ib-ruby/example$ ./account_summary
|
78
|
-
<AccountSummary: request_id 8111, account DU167349, tag DayTradesRemaining, value -1.0, currency >
|
79
|
-
<AccountSummary: request_id 8111, account DU167349, tag InitMarginReq, value 93402.16, currency EUR >
|
80
|
-
<AccountSummary: request_id 8111, account DU167349, tag NetLiquidation, value 990842.34, currency EUR >
|
81
|
-
<AccountSummary: request_id 8111, account DF167347, tag InitMarginReq, value 0.0, currency EUR >
|
82
|
-
<AccountSummary: request_id 8111, account DF167347, tag NetLiquidation, value 0.0, currency EUR >
|
83
|
-
<AccountSummary: request_id 8111, account DU167348, tag DayTradesRemaining, value -1.0, currency >
|
84
|
-
<AccountSummary: request_id 8111, account DU167348, tag InitMarginReq, value 135317.73, currency EUR >
|
85
|
-
<AccountSummary: request_id 8111, account DU167348, tag NetLiquidation, value 949599.26, currency EUR >
|
86
|
-
|
87
|
-
******** Press <Enter> to quit *********
|
88
|
-
=end
|
data/example/cancel_orders
DELETED
@@ -1,74 +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
|
-
# Accepts the port to connect to as first command-parameter, T)ws or G)ateway, which is the default
|
8
|
-
#
|
9
|
-
# Numeric Parameter are interpreted as keys for specific orders to kill
|
10
|
-
|
11
|
-
require 'bundler/setup'
|
12
|
-
require 'ib-api'
|
13
|
-
specified_port = ARGV[0] || 'Gateway'
|
14
|
-
port = case specified_port
|
15
|
-
when /^[gG]/
|
16
|
-
ARGV.shift # consume the first argument
|
17
|
-
4002
|
18
|
-
when /^[Tt]/
|
19
|
-
ARGV.shift # consume the first argument
|
20
|
-
7497
|
21
|
-
end
|
22
|
-
|
23
|
-
# First, connect to IB TWS.
|
24
|
-
ib = IB::Connection.new client_id: 1111, port: port do | gw |
|
25
|
-
|
26
|
-
# Subscribe to TWS alerts/errors and order-related messages
|
27
|
-
gw.subscribe(:Alert, :ManagedAccounts, :OpenOrder, :OrderStatus, :OpenOrderEnd) { |msg| puts msg.to_human }
|
28
|
-
# Set log level
|
29
|
-
gw.logger.level = Logger::FATAL # DEBUG -- INFO -- WARN -- ERROR -- FATAL
|
30
|
-
end
|
31
|
-
|
32
|
-
if ARGV.empty?
|
33
|
-
ib.send_message :RequestGlobalCancel
|
34
|
-
else
|
35
|
-
puts "ARGV: #{ARGV}"
|
36
|
-
# Will only work for Orders placed under the same :client_id
|
37
|
-
ib.cancel_order *ARGV
|
38
|
-
puts '-'*55
|
39
|
-
puts "Remaining Orders"
|
40
|
-
puts '-'*55
|
41
|
-
end
|
42
|
-
|
43
|
-
puts '-'*55
|
44
|
-
puts "Remaining Orders"
|
45
|
-
ib.send_message :RequestAllOpenOrders
|
46
|
-
puts '-'*55
|
47
|
-
|
48
|
-
sleep 3
|
49
|
-
|
50
|
-
|
51
|
-
## Expected output
|
52
|
-
#12:20:25.154 Connected to server, version: 137,
|
53
|
-
# connection time: 2018-02-27 12:20:25 +0000 local, 2018-02-27T12:20:25+00:00 remote.
|
54
|
-
#12:20:25.156 Got message 5 (IB::Messages::Incoming::OpenOrder)
|
55
|
-
#<OpenOrder: <Stock: WFC USD> <Order: LMT GTC buy 100.0 1.13 Submitted #1/1562725191 from 1112/DU167348 fee 0.0>>
|
56
|
-
#12:20:25.158 Got message 3 (IB::Messages::Incoming::OrderStatus)
|
57
|
-
#<OrderStatus: <OrderState: Submitted #1/1562725191 from 1112 filled 0.0/100.0 at 0.0/0.0 why_held >>
|
58
|
-
#12:20:25.197 Got message 53 (IB::Messages::Incoming::OpenOrderEnd)
|
59
|
-
#<OpenOrderEnd: >
|
60
|
-
#12:20:25.197 Got message 15 (IB::Messages::Incoming::ManagedAccounts)
|
61
|
-
#12:20:25.197 No subscribers for message IB::Messages::Incoming::ManagedAccounts!
|
62
|
-
#12:20:25.197 Got message 9 (IB::Messages::Incoming::NextValidId)
|
63
|
-
#12:20:25.197 Got next valid order id: 2.
|
64
|
-
#12:20:25.254 Got message 5 (IB::Messages::Incoming::OpenOrder)
|
65
|
-
#<OpenOrder: <Stock: WFC USD> <Order: LMT GTC buy 100.0 1.13 PendingCancel #1/1562725191 from 1112/DU167348 fee 0.0>>
|
66
|
-
#12:20:25.256 Got message 3 (IB::Messages::Incoming::OrderStatus)
|
67
|
-
#<OrderStatus: <OrderState: PendingCancel #1/1562725191 from 1112 filled 0.0/100.0 at 0.0/0.0 why_held >>
|
68
|
-
#12:20:25.297 Got message 53 (IB::Messages::Incoming::OpenOrderEnd)
|
69
|
-
#<OpenOrderEnd: >
|
70
|
-
#12:20:25.342 Got message 3 (IB::Messages::Incoming::OrderStatus)
|
71
|
-
#<OrderStatus: <OrderState: Cancelled #1/1562725191 from 1112 filled 0.0/100.0 at 0.0/0.0 why_held >>
|
72
|
-
#12:20:25.343 Got message 4 (IB::Messages::Incoming::Alert)
|
73
|
-
#TWS Error 202: Order Canceled - reason:
|
74
|
-
##
|
data/example/fa_accounts
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This script receives Financial Adviser and Managed Accounts info
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'ib-api'
|
7
|
-
|
8
|
-
# First, connect to IB TWS.
|
9
|
-
ib = IB::Connection.new client_id: 1114, port: 4002 #, :port => 7496 # TWS
|
10
|
-
|
11
|
-
# Subscribe to TWS alerts/errors and FA/managed account info
|
12
|
-
ib.subscribe(:Alert, :ManagedAccounts, :ReceiveFA) { |msg| puts msg.to_human }
|
13
|
-
|
14
|
-
##
|
15
|
-
## type of Financial Advisor configuration data
|
16
|
-
# being received from TWS. Valid values include:
|
17
|
-
# 1 = GROUPS, 2 = PROFILE, 3 = ACCOUNT ALIASES
|
18
|
-
|
19
|
-
ib.send_message :RequestFA, fa_data_type: 3
|
20
|
-
ib.send_message :RequestManagedAccounts
|
21
|
-
|
22
|
-
ib.wait_for :ReceiveFA
|
23
|
-
|
24
|
-
|
25
|
-
|
data/example/fundamental_data
DELETED
@@ -1,40 +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 'bundler/setup'
|
7
|
-
|
8
|
-
require 'ib-api'
|
9
|
-
|
10
|
-
# allocate two variables
|
11
|
-
request_id, snapshot_data = nil
|
12
|
-
|
13
|
-
ib = IB::Connection.new port: 7496, :client_id => 1112 do | gw | #, :port => 7496 # TWS
|
14
|
-
gw.subscribe(:Alert) { |msg| puts msg.to_human }
|
15
|
-
|
16
|
-
# Fundamental Data will arrive in XML format, we need to parse it
|
17
|
-
gw.subscribe(:FundamentalData) { |msg| snapshot_data = msg.xml if msg.request_id == request_id }
|
18
|
-
end
|
19
|
-
|
20
|
-
# Request Fundamental Data for IBM. Possible report types:
|
21
|
-
# 'estimates' - Estimates
|
22
|
-
# 'finstat' - Financial statements
|
23
|
-
# 'snapshot' - Summary
|
24
|
-
request_id = ib.send_message :RequestFundamentalData,
|
25
|
-
:contract => IB::Stock.new( symbol: 'ibm' ),
|
26
|
-
:report_type => 'snapshot'
|
27
|
-
|
28
|
-
# Needs some time to receive and parse XML. Standard timeout of 1 sec is just too low.
|
29
|
-
ib.wait_for :FundamentalData
|
30
|
-
|
31
|
-
# Now just extract and use all the fundamental data you needed
|
32
|
-
puts snapshot_data[:ReportSnapshot][:TextInfo][:Text]
|
33
|
-
|
34
|
-
pp snapshot_data[:ReportSnapshot][:Ratios]
|
35
|
-
STDIN.gets
|
36
|
-
|
37
|
-
puts "Displaying the complete transmitted data:"
|
38
|
-
puts ""
|
39
|
-
|
40
|
-
pp snapshot_data
|
data/example/historic_data_cli
DELETED
@@ -1,186 +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
|
-
require 'ib-api'
|
9
|
-
|
10
|
-
include Getopt
|
11
|
-
|
12
|
-
opt = Getopt::Long.getopts(
|
13
|
-
["--help", BOOLEAN],
|
14
|
-
["--end", REQUIRED],
|
15
|
-
["--port", REQUIRED],
|
16
|
-
["--security", REQUIRED],
|
17
|
-
["--duration", REQUIRED],
|
18
|
-
["--barsize", REQUIRED],
|
19
|
-
["--csv", BOOLEAN],
|
20
|
-
["--dateformat", REQUIRED],
|
21
|
-
["--nonregularhours", BOOLEAN],
|
22
|
-
["--what", OPTIONAL]
|
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:202101:200: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"]) || '4002'
|
130
|
-
|
131
|
-
lastMessageTime = Queue.new # for communicating with the reader thread.
|
132
|
-
|
133
|
-
# First, connect to IB TWS.
|
134
|
-
ib = IB::Connection.new( :client_id => 1112, :port => PORT) do | gw|
|
135
|
-
|
136
|
-
# Subscribe to TWS alerts/errors
|
137
|
-
gw.subscribe(:Alert) { |msg| puts msg.to_human }
|
138
|
-
|
139
|
-
|
140
|
-
# Subscribe to incoming HistoricalData events. The code passed in the
|
141
|
-
# block will be executed when a message of the subscribed type is
|
142
|
-
# received, with the received message as its argument. In this case,
|
143
|
-
# we just print out the data.
|
144
|
-
#
|
145
|
-
# Note that we have to look the ticker id of each incoming message
|
146
|
-
# up in local memory to figure out what security it relates to.
|
147
|
-
# The incoming message packet from TWS just identifies it by ticker id.
|
148
|
-
#
|
149
|
-
gw.subscribe(:HistoricalData) do |msg|
|
150
|
-
if opt["csv"]
|
151
|
-
puts "date,time,open,high,low,close,volume,wap,has_gaps"
|
152
|
-
msg.results.each do |datum|
|
153
|
-
puts "#{datum.time},#{datum.open},#{datum.high},#{datum.low}," +
|
154
|
-
"#{datum.close},#{datum.volume},#{datum.wap},#{datum.has_gaps}"
|
155
|
-
end
|
156
|
-
n
|
157
|
-
STDERR.puts "Received #{msg.count} items:"
|
158
|
-
msg.results.each { |datum| puts datum.to_s }
|
159
|
-
end
|
160
|
-
lastMessageTime.push(Time.now)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
# Now we actually request historical data for the symbols we're
|
164
|
-
# interested in. TWS will respond with a HistoricalData message,
|
165
|
-
# which will be received by the code above.
|
166
|
-
ib.send_message :RequestHistoricalData,
|
167
|
-
:request_id => 123,
|
168
|
-
:contract => opt["security"],
|
169
|
-
:end_date_time => END_DATE_TIME,
|
170
|
-
:duration => DURATION, # seconds == 1 hour
|
171
|
-
:bar_size => BAR_SIZE, # 1 minute bars
|
172
|
-
:what_to_show => WHAT,
|
173
|
-
:use_RTH => REGULAR_HOURS_ONLY,
|
174
|
-
:keep_up_todate => 0,
|
175
|
-
:format_date => DATE_FORMAT
|
176
|
-
|
177
|
-
# A complication here is that IB does not send any indication when all historic data
|
178
|
-
# is done being delivered. So we have to guess - when there is no more new data for
|
179
|
-
# some period, we interpret that as "end of data" and exit.
|
180
|
-
sleep 2
|
181
|
-
while true
|
182
|
-
lastTime = lastMessageTime.pop # blocks until a message is ready on the queue
|
183
|
-
sleep 0.1 # .. wait ..
|
184
|
-
exit if lastMessageTime.empty? # if still no more messages after 2 more seconds, exit.
|
185
|
-
end
|
186
|
-
|