ib-api 972.2 → 972.3
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.
- 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
|
-
|