ib-api 972.2 → 972.3

Sign up to get free protection for your applications and to get access to all the features.
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.2'
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-02-23 00:00:00.000000000 Z
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.0.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
@@ -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."
@@ -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
@@ -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
-
@@ -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
@@ -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
-