P&L data in the Account Window
UnRealized and Realized P&L is sent to the API function IBApi.EWrapper.updateAccountValue function after a subscription request is made with IBApi.EClient.reqAccountUpdates. This information corresponds to the data in the TWS Account Window, and has a different source of information, a different update frequency, and different reset schedule than PnL data in the TWS Portfolio Window and associated API functions (below). In particular, the unrealized P&L information shown in the TWS Account Window which is sent to updatePortfolioValue will update either (1) when a trade for that particular instrument occurs or (2) every 3 minutes. The realized P&L data in the TWS Account Window is reset to 0 once per day.
- It is important to keep in mind that the P&L data shown in the Account Window and Portfolio Window will sometimes differ because there is a different source of information and a different reset schedule.
P&L data in the Portfolio Window
Beginning with API v973.03, requests can be made to receive real time updates about the daily P&L and unrealized P&L for an account, or for individual positions. Financial Advisors can also request P&L figures for 'All' subaccounts, or for a portfolio model. In API v973.05+/TWS v968+ this is further extended to include realized P&L information at the account or individual position level.
These newer P&L API functions demonstrated below return the data which is displayed in the TWS Portfolio Window in current versions of TWS (v963+). As such, the P&L values are calculated based on the reset schedule specified in TWS Global Configuration (by default an instrument-specific reset schedule) and this setting affects values sent to the associated API functions as well. Also in TWS, P&L data from virtual forex positions will be included in the account P&L if and only if the Virtual Fx section of the Account Window is expanded.
-
-
-
-
-
Note: the P&L functions in Python API are available starting in API v973.06+.
P&L subscription requests for individual positions
Subscribe using the IBApi::EClient::reqPnLSingle function Cannot be used with IBroker accounts configured for on-demand lookup with account = 'All'
-
client.reqPnLSingle(17001, "DUD00029", "", 268084);
-
client.reqPnLSingle(17001, "DUD00029", "", 268084);
-
client.reqPnLSingle(17001, "DUD00029", "", 268084)
-
m_pClient->reqPnLSingle(7002, "DUD00029", "", 268084);
-
1 self.reqPnLSingle(17002,
"DU111519",
"", 8314)
Currently updates are returned to IBApi.EWrapper.pnlSingle approximately once per second. *subject to change in the future
-
public void pnlSingle(int reqId, decimal pos, double dailyPnL, double unrealizedPnL, double realizedPnL, double value)
{
Console.WriteLine("PnL Single. Request Id: {0}, Pos {1}, Daily PnL {2}, Unrealized PnL {3}, Realized PnL: {4}, Value: {5}", reqId, Util.DecimalMaxString(pos), Util.DoubleMaxString(dailyPnL), Util.DoubleMaxString(unrealizedPnL),
Util.DoubleMaxString(realizedPnL), Util.DoubleMaxString(value));
}
-
@Override
public void pnlSingle(int reqId, Decimal pos, double dailyPnL, double unrealizedPnL, double realizedPnL, double value) {
System.out.println(EWrapperMsgGenerator.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value));
}
-
Public Sub pnlSingle(reqId As Integer, pos As Decimal, dailyPnL As Double, unrealizedPnL As Double, realizedPnL As Double, value As Double) Implements EWrapper.pnlSingle
Console.WriteLine("PnL Single. Request Id: {0}, pos: {1}, daily PnL: {2}, unrealized PnL: {3}, realized PnL: {4}, value: {5}", reqId, Util.DecimalMaxString(pos),
Util.DoubleMaxString(dailyPnL), Util.DoubleMaxString(unrealizedPnL), Util.DoubleMaxString(realizedPnL), Util.DoubleMaxString(value))
End Sub
-
void TestCppClient::pnlSingle(int reqId, Decimal pos, double dailyPnL, double unrealizedPnL, double realizedPnL, double value) {
printf("PnL Single. ReqId: %d, pos: %s, daily PnL: %s, unrealized PnL: %s, realized PnL: %s, value: %s\n", reqId, DecimalFunctions::decimalStringToDisplay(pos).c_str(), Utils::doubleMaxString(dailyPnL).c_str(),
Utils::doubleMaxString(unrealizedPnL).c_str(), Utils::doubleMaxString(realizedPnL).c_str(), Utils::doubleMaxString(value).c_str());
}
-
1 def pnlSingle(self, reqId: int, pos: Decimal, dailyPnL: float,
2 unrealizedPnL: float, realizedPnL: float, value: float):
3 super().pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value)
4 print(
"Daily PnL Single. ReqId:", reqId,
"Position:", decimalMaxString(pos),
5 "DailyPnL:", floatMaxString(dailyPnL),
"UnrealizedPnL:", floatMaxString(unrealizedPnL),
6 "RealizedPnL:", floatMaxString(realizedPnL),
"Value:", floatMaxString(value))
- If a P&L subscription request is made for an invalid conId or contract not in the account, there will not be a response.
- As elsewhere in the API, a max double value will indicate an 'unset' value. This corresponds to an empty cell in TWS.
- Introducing broker accounts without a large number of subaccounts (<50) can receive aggregate data by specifying the account as "All".
- *Cannot be used with IBroker accounts configured for on-demand lookup with account = 'All'
Subscriptions are cancelled using the IBApi::EClient::cancelPnLSingle function:
-
client.cancelPnLSingle(17001);
-
client.cancelPnLSingle(17001);
-
client.cancelPnLSingle(17001)
-
m_pClient->cancelPnLSingle(7002);
-
1 self.cancelPnLSingle(17002)
P&L subscription requests for accounts
Subscribe using the IBApi::EClient::reqPnL function:
-
client.reqPnL(17001, "DUD00029", "");
-
client.reqPnL(17001, "DUD00029", "");
-
client.reqPnL(17001, "DUD00029", "")
-
m_pClient->reqPnL(7001, "DUD00029", "");
-
1 self.reqPnL(17001,
"DU111519",
"")
- Introducing broker accounts with less than 50 subaccounts can receive aggregate PnL for all subaccounts by specifying 'All' as the account code.
- With requests for advisor accounts with many subaccounts and/or positions can take several seconds for aggregated P&L to be computed and returned.
- For account P&L data the TWS setting "Prepare portfolio PnL data when downloading positions" must be checked.
Updates are sent to IBApi.EWrapper.pnl
-
public void pnl(int reqId, double dailyPnL, double unrealizedPnL, double realizedPnL)
{
Console.WriteLine("PnL. Request Id: {0}, Daily PnL: {1}, Unrealized PnL: {2}, Realized PnL: {3}", reqId, Util.DoubleMaxString(dailyPnL), Util.DoubleMaxString(unrealizedPnL), Util.DoubleMaxString(realizedPnL));
}
-
@Override
public void pnl(int reqId, double dailyPnL, double unrealizedPnL, double realizedPnL) {
System.out.println(EWrapperMsgGenerator.pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL));
}
-
Public Sub pnl(reqId As Integer, dailyPnL As Double, unrealizedPnL As Double, realizedPnL As Double) Implements EWrapper.pnl
Console.WriteLine("PnL. Request Id: {0}, daily PnL: {1}, unrealized PnL: {2}, realized PnL: {3}", reqId, Util.DoubleMaxString(dailyPnL), Util.DoubleMaxString(unrealizedPnL), Util.DoubleMaxString(realizedPnL))
End Sub
-
void TestCppClient::pnl(int reqId, double dailyPnL, double unrealizedPnL, double realizedPnL) {
printf("PnL. ReqId: %d, daily PnL: %s, unrealized PnL: %s, realized PnL: %s\n", reqId, Utils::doubleMaxString(dailyPnL).c_str(), Utils::doubleMaxString(unrealizedPnL).c_str(),
Utils::doubleMaxString(realizedPnL).c_str());
}
-
1 def pnl(self, reqId: int, dailyPnL: float,
2 unrealizedPnL: float, realizedPnL: float):
3 super().pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL)
4 print(
"Daily PnL. ReqId:", reqId,
"DailyPnL:", floatMaxString(dailyPnL),
5 "UnrealizedPnL:", floatMaxString(unrealizedPnL),
"RealizedPnL:", floatMaxString(realizedPnL))
Cancel unnecessary subscriptions with the IBApi::EClient::cancelPnL function:
-
-
-
-
m_pClient->cancelPnL(7001);
-