This function either fetches or sets up a subscription to receive the data that appear in the "Account Window" window of Trader Workstation for the single account specified in the acctCode input. Unlike req_account_updates_multi(), req_account_updates() can only subscribe to one account at a time.

req_account_updates(
  acctCode = "All",
  subscribe = TRUE,
  channel = NULL,
  return_data = is.null(channel) && subscribe
)

Arguments

acctCode

Character vector of length 1 containing the Account ID of the account for which updates are sought. Possible choices include any one of the elements of the output of req_managed_accts().

subscribe

Boolean. If TRUE, then a subscription is started and the socket passed in as channel will continue to receive updated account info from Interactive Brokers every time read_sock_drawer() is called and an update is available on the socket.

channel

One of the following:

  • Not Specified (Default): Opens a new connection to IB, uses it to issue the request and retrieve the response, and closes connection behind itself upon completion.

  • The Name of a Sock: Character vector, length 1. The name of an open, connected socket in the sock_drawer; e.g., "master", "tws", or "sock_123"

  • Numeric Client ID: Numeric, length 1. The client ID for which open orders are to be retrieved; e.g., 0, 874, 123. If a client ID is passed, and no socket in the sock_drawer is connected on that ID, then a new socket will be opened on that ID, and closed upon function exit.

  • A sockconn Connection: An open connection object of class "sockconn", connected to the IB API; e.g., sock_drawer$tws

return_data

Boolean of length 1. Defaults to TRUE unless argument channel is specified. If FALSE, data retrieved by the function will be returned as the funciton's output. If TRUE, then a Boolean succeses flag will be returned as the function's output indicating the success (TRUE) or failure (FALSE) of the function's attempt to transceive data to/from IB. Data in the treasury is always updated regardless of the value passed as return_data in the function call.

Value

This function is called for its side effect of updating the treasury, which takes place every time the function executes. Additionally, the function's return value depends upon the value passed in as return_data as follows:

  • If return_data == FALSE: A Boolean success flag, returned invisibly, indicating that the function executed correctly and updated the treasury with any new data retrieved.

  • If return_data == TRUE: Any new data retrieved will be returned in a tibble in addition to being added to the treasury. If no new data is available, returns NULL.

return_data defaults to TRUE unless channel is specified.

Details

Account Keys: Several values of param in the ACCOUNTS element of the output may or may not display suffixes; for example, the param AccruedDividend. The meaning of these suffixes is as follows:

  • "-C": Applies to commodities

  • "-S": Applies to stocks

  • no suffix: Values reported are totals

"All" Option: If you use a Financial Advisory (FA) account structure, then you have the option of requesting account updates for all of the sub-accounts that fall under the master account. To do this, append the letter "A" to the end of the master account's ID and pass this value to req_account_updates() as acctCode; for example, "F7654321A".

No "cancel_" function, use subscribe = FALSE: Unlike req_account_summary() and req_account_updates_multi(), req_account_updates() does not have a companion function that cancels the subscription. Instead, subscriptions are canceled on a socket by calling req_account_updates() with subscribe = FALSE. See the Examples section below.

One account at a time / Overwriting subscriptions: Even if you use different sockets, IB's API protocol is set up in such a way that you may only have one active req_account_updates() subscription running at any given time. If you request another subscription, the new one will simply overwrite the old one without an error message.

Single Account: If the user has access to only one account, then supplying a value for acctCode is not necessary and may be left blank in the function call.

Time Zone: Interactive Brokers' servers use a very simple hour:minute formatted timestamp the response data reported by req_account_updates() in the acct_update_time column of the output. The timestamp does not include a time zone because it is understood that the times reported are denominated in terms of the time zone set by clicking the "More Options" link in the login window of either TWS or IBG.

Cancelling subscriptions: Use the command req_account_updates(subscribe = FALSE). When cancelling a subscription made by req_account_updates() in InteractiveTradeR, any value passed in as channel is ignored, so it can be left out entirely. This shortcut follows as consequence of the fact that IB only allows one req_account_updates() subscription at a time.

Behavior

IB's documentation states that subscribed socket's account updates data will be updated every three (3) minutes unless there is a position change, in which case updates will be sent immediately. However, during market hours, you may observe much shorter, more frequent update intervals. You can explore your actual observed update frequency by experimenting with Example 3 in the "Examples" section below.

ACCOUNTS and PORTFOLIO VALUE Treasury Objects

req_account_updates() updates the ACCOUNTS and PORTFOLIO VALUE objects in the treasury. Their structure is set forth as follows:

ACCOUNTS: A tibble in which each row represents a parameter pertaining to a particular account. Has the following columns:

  • tag <chr>: Name of account parameter, (e.g., "DayTradesRemaining")

  • tag_value <chr>: Value of the param (e.g., "3")

  • currency <chr>: 3-letter currency abbreviation if tag_value is a monetary amount, "" otherwise.

  • account <chr>: Account ID of the account to which the data applies. Included so that ACCOUNTS data returned for different accounts can be combined without losing track of which account applies to which data.

PORTFOLIO_VALUE: A tibble in which every row represents an asset held in an account. Has the following columns:

  • account <chr>: Account ID of the account to which the data applies. Included so that PORTFOLIO_VALUE data returned for different accounts can be combined without losing track of which account applies to which data.

  • con_id <chr>: Interactive Brokers' unique contract ID for the asset.

  • symbol <chr>: The exchange symbol under which the asset is traded, e.g., "FB", "AAPL", "IBM".

  • sec_type <chr>: Three-letter abbreviation for the class of the asset in the row, e.g., "STK", "CFD", "BOND", and so on.

  • last_trade_date_or_contract_month For options & futures, the last trading day or contract month (as applicable), in YYYYMMDD ("\

  • strike <numeric>: Strike price of asset, if applicable.

  • right <chr>: If applicable, the "right" parameter of a contract, e.g. "C" (right to buy, for a call), "P" (right to sell, put).

  • multiplier <dbl>: The "lot size" of a contract, if applicable; e.g., an options contract that affects 100 shares of underlying. Numeric.

  • primary_exchange <chr>: Main exchange on which a contract is traded, e.g., "NASDAQ", "NYSE".

  • currency <chr>: 3-letter abbreviation of the currency in which the contract is traded, e.g. "USD", "HKD".

  • local_symbol <chr>: The symbol under which the contract is traded in its primary exchange.

  • trading_class <chr>: Code that classifies an asset based on the manner in which it is traded. Stocks, for example, have trading_class = "NMS" denoting the United States' National Market System for equities.

  • position <dbl>: Numeric, long or short. Denotes how many of the contracts are held. Don't forget multiplier, if applicable!

  • market_price <numeric>: The market price of the contract on a per-contract basis as measured at time = acct_update_time.

  • market_value <numeric>: market_price * position; i.e., market value of the account's position in a particular contract.

  • average_cost <numeric>: The effective price of the account's overall position in the asset, including transaction costs.

  • unrealized_PNL <numeric>: Equals market_value - average_cost * position and gives the profit or loss that would result if the position were closed at market_price. Does not take into account transction costs of closing the position.

  • realized_PNL <numeric>: Gives the real-world, historical profit or loss earned on positions that are now closed. Includes transaction costs.

See also

Examples

# Clear out the treasury, sock drawer, and subscriptions clean_slate() #### #### Example 1: Fetch account update for one account #### # Pick a random account for this example or specify one yourself, # e.g., acct <- "DU1234567" acct <- sample(req_managed_accts(), 1) acct
#> [1] "DU1267862"
# Fetch account updates for the account, without starting a subscription req_account_updates(acct)
#> $ACCOUNTS #> # A tibble: 171 x 4 #> account tag tag_value currency #> * <chr> <chr> <chr> <chr> #> 1 DU1267862 AccountType INDIVIDUAL "" #> 2 DU1267862 AccountCode DU1267862 "" #> 3 DU1267862 AccountReady TRUE "" #> 4 DU1267862 Cushion 0.998042 "" #> 5 DU1267862 DayTradesRemaining -1 "" #> 6 DU1267862 DayTradesRemainingT+1 -1 "" #> 7 DU1267862 DayTradesRemainingT+2 -1 "" #> 8 DU1267862 DayTradesRemainingT+3 -1 "" #> 9 DU1267862 DayTradesRemainingT+4 -1 "" #> 10 DU1267862 Leverage-S 0.00 "" #> # … with 161 more rows #> #> $PORTFOLIO_VALUE #> # A tibble: 3 x 14 #> account con_id symbol sec_type primary_exchange currency local_symbol #> <chr> <chr> <chr> <chr> <chr> <chr> <chr> #> 1 DU1267… 14094 BMW STK IBIS EUR BMW #> 2 DU1267… 43645… IBKR STK NASDAQ USD IBKR #> 3 DU1267… 9408 MCD STK NYSE USD MCD #> # … with 7 more variables: trading_class <chr>, position <chr>, #> # market_price <chr>, market_value <chr>, average_cost <chr>, #> # unrealized_PNL <chr>, realized_PNL <chr> #>
# Print the ACCOUNTS treasury$ACCOUNTS
#> # A tibble: 171 x 4 #> account tag tag_value currency #> * <chr> <chr> <chr> <chr> #> 1 DU1267862 AccountType INDIVIDUAL "" #> 2 DU1267862 AccountCode DU1267862 "" #> 3 DU1267862 AccountReady TRUE "" #> 4 DU1267862 Cushion 0.998042 "" #> 5 DU1267862 DayTradesRemaining -1 "" #> 6 DU1267862 DayTradesRemainingT+1 -1 "" #> 7 DU1267862 DayTradesRemainingT+2 -1 "" #> 8 DU1267862 DayTradesRemainingT+3 -1 "" #> 9 DU1267862 DayTradesRemainingT+4 -1 "" #> 10 DU1267862 Leverage-S 0.00 "" #> # … with 161 more rows
# Print the PORTFOLIO_VALUE treasury$PORTFOLIO_VALUE # empty list if no positions
#> # A tibble: 3 x 14 #> account con_id symbol sec_type primary_exchange currency local_symbol #> * <chr> <chr> <chr> <chr> <chr> <chr> <chr> #> 1 DU1267… 14094 BMW STK IBIS EUR BMW #> 2 DU1267… 43645… IBKR STK NASDAQ USD IBKR #> 3 DU1267… 9408 MCD STK NYSE USD MCD #> # … with 7 more variables: trading_class <chr>, position <chr>, #> # market_price <chr>, market_value <chr>, average_cost <chr>, #> # unrealized_PNL <chr>, realized_PNL <chr>
#### #### Example 2: Fetch account update data for many accounts #### clean_slate() # clean slate (optional) treasury$ACCOUNTS # should return NULL
#> NULL
treasury$PORTFOLIO_VALUE # should return NULL
#> NULL
# Fetch account updates for all of your accounts using the walk() function # from the purrr package: req_managed_accts() %>% purrr::walk( function(account){ # Sys.sleep(1/50) req_account_updates(acctCode = account) } ) # Uncomment the "Sys.sleep(1/50)" to pause execution for one fiftieth of a # second between each call to req_account_updates(). The reason you may want # to do this is that Interactive brokers only allows, at max, 50 API calls per # second. If you have more than 50 accounts and a fast computer & connection, # the "Sys.sleep(1/50)" prevents you from exceeding the limit. # Check that all accounts are represented in ACCOUNTS: identical( sort(unique(treasury$ACCOUNTS$account)), sort(req_managed_accts()) )
#> [1] TRUE
#### #### Example 3: Persistent account update subscriptions #### # To create an ongoing subscription that continuously collects account # updates, make the same calls to req_account_updates() as above, but use a # persistent socket. clean_slate() # clean slate, optional treasury$ACCOUNTS # should return NULL
#> NULL
treasury$PORTFOLIO_VALUE # should return NULL
#> NULL
# Open up a socket create_new_connections(1) # Pick pick two random accounts, or replace the "sample()" with an account code # (e.g., "DU7654321") as desired. acct2 <- sample(req_managed_accts(), 2) # Make the call, this time with channel = "async" acct2 %>% purrr::walk( function(account){ req_account_updates(account, channel = "async") } ) # Within three minutes of starting the subscription, take a look at the # ACCOUNTS and PORTFOLIO_VALUE objects in the treasury: treasury$ACCOUNTS
#> # A tibble: 289 x 4 #> account tag tag_value currency #> * <chr> <chr> <chr> <chr> #> 1 DF1267859 AccountType INDIVIDUAL "" #> 2 DF1267859 AccountCode DF1267859 "" #> 3 DF1267859 AccountReady TRUE "" #> 4 DF1267859 Cushion 1 "" #> 5 DF1267859 Leverage-S 0.00 "" #> 6 DF1267859 LookAheadNextChange 0 "" #> 7 DF1267859 NLVAndMarginInReview FALSE "" #> 8 DF1267859 SegmentTitle-C US Commodities "" #> 9 DF1267859 SegmentTitle-S US Securities "" #> 10 DF1267859 TradingType-S STKNOPT "" #> # … with 279 more rows
treasury$PORTFOLIO_VALUE
#> # A tibble: 4 x 14 #> account con_id symbol sec_type primary_exchange currency local_symbol #> * <chr> <chr> <chr> <chr> <chr> <chr> <chr> #> 1 DU1267… 11017… DUK STK NYSE USD DUK #> 2 DU1267… 43645… IBKR STK NASDAQ USD IBKR #> 3 DU1267… 9408 MCD STK NYSE USD MCD #> 4 DU1267… 48157… NVDA STK NASDAQ USD NVDA #> # … with 7 more variables: trading_class <chr>, position <chr>, #> # market_price <chr>, market_value <chr>, average_cost <chr>, #> # unrealized_PNL <chr>, realized_PNL <chr>
# See when they were last updated: acc_val_update_time <- attr(treasury$ACCOUNTS, "last_updated") acc_val_update_time
#> [1] "2020-03-17 13:15:31 EDT"
port_val_update_time <- attr(treasury$PORTFOLIO_VALUE, "last_updated") port_val_update_time
#> [1] "2020-03-17 13:15:31 EDT"
# Soon after creating the subscription, try to update the treasury objects by # calling read_sock_drawer(): read_sock_drawer() # If you're quick enough, you won't get any updated information because IB has # not sent updated data to the socket. # Note that you now have an "account_updates" entry in subscriptions for the # account you're now following: subscriptions$account_updates
#> # A tibble: 2 x 4 #> req_name req_id conn_row client_id #> <chr> <dbl> <dbl> <int> #> 1 DU1267864 7 4 1 #> 2 DF1267859 8 4 1
# Wait a little over 3 minutes Sys.sleep(200) # Keep calling... read_sock_drawer() # ...a few times, waiting 10 or 20 seconds in between calls. After 3 minutes # have passed -- but probably before that -- you should see either or both of # the ACCOUNTS and PORTFOLIO_VALUE objects update. # After updating, take a look in the treasury: treasury$ACCOUNTS
#> # A tibble: 289 x 4 #> account tag tag_value currency #> * <chr> <chr> <chr> <chr> #> 1 DF1267859 AccountType INDIVIDUAL "" #> 2 DF1267859 AccountCode DF1267859 "" #> 3 DF1267859 AccountReady TRUE "" #> 4 DF1267859 Cushion 1 "" #> 5 DF1267859 Leverage-S 0.00 "" #> 6 DF1267859 LookAheadNextChange 0 "" #> 7 DF1267859 NLVAndMarginInReview FALSE "" #> 8 DF1267859 SegmentTitle-C US Commodities "" #> 9 DF1267859 SegmentTitle-S US Securities "" #> 10 DF1267859 TradingType-S STKNOPT "" #> # … with 279 more rows
treasury$PORTFOLIO_VALUE
#> # A tibble: 4 x 14 #> account con_id symbol sec_type primary_exchange currency local_symbol #> * <chr> <chr> <chr> <chr> <chr> <chr> <chr> #> 1 DU1267… 11017… DUK STK NYSE USD DUK #> 2 DU1267… 43645… IBKR STK NASDAQ USD IBKR #> 3 DU1267… 9408 MCD STK NYSE USD MCD #> 4 DU1267… 48157… NVDA STK NASDAQ USD NVDA #> # … with 7 more variables: trading_class <chr>, position <chr>, #> # market_price <chr>, market_value <chr>, average_cost <chr>, #> # unrealized_PNL <chr>, realized_PNL <chr>
# And compare update times: acc_val_update_time
#> [1] "2020-03-17 13:15:31 EDT"
attr(treasury$ACCOUNTS,"last_updated")
#> [1] "2020-03-17 13:15:31 EDT"
port_val_update_time
#> [1] "2020-03-17 13:15:31 EDT"
attr(treasury$PORTFOLIO_VALUE, "last_updated")
#> [1] "2020-03-17 13:15:31 EDT"
#### Example 4: Cancelling Subscriptions # Cancel the subscription created in Example 3 with: req_account_updates(acct2, subscribe = FALSE)