Skip to main content

ibkr_flex_statement/
fifo_performance_summary.rs

1use crate::statement_section::StatementSection;
2
3use super::node_utils::NodeWrapper;
4use super::time_utils;
5use anyhow::Result;
6
7#[derive(Debug, PartialEq)]
8pub struct FIFOPerformanceSummary {
9    pub account_id: String,
10    pub timestamp_eod_ms: i64,
11
12    pub ticker: Option<String>,
13    pub conid: Option<u32>,
14    pub listing_exchange: Option<String>,
15
16    pub realized_st_profit: f64,
17    pub realized_st_loss: f64,
18    pub unrealized_st_profit: f64,
19    pub unrealized_st_loss: f64,
20
21    pub realized_lt_profit: f64,
22    pub realized_lt_loss: f64,
23    pub unrealized_lt_profit: f64,
24    pub unrealized_lt_loss: f64,
25
26    pub total_realized_pnl: f64,
27    pub total_fifo_pnl: f64,
28}
29
30impl StatementSection for FIFOPerformanceSummary {
31    fn from_node(node: &NodeWrapper) -> Result<FIFOPerformanceSummary> {
32        Ok(FIFOPerformanceSummary {
33            account_id: node.get_attribute("accountId")?,
34            timestamp_eod_ms: time_utils::trading_eod_after_hours_timestamp_ms(
35                node.node.attribute("reportDate").unwrap(),
36            )?,
37
38            ticker: node.get_attribute_opt("symbol"),
39            conid: node.parse_attribute_opt("conid")?,
40            listing_exchange: node.get_attribute_opt("listingExchange"),
41
42            realized_st_profit: node.parse_attribute("realizedSTProfit")?,
43            realized_st_loss: node.parse_attribute("realizedSTLoss")?,
44            unrealized_st_profit: node.parse_attribute("unrealizedSTProfit")?,
45            unrealized_st_loss: node.parse_attribute("unrealizedSTLoss")?,
46
47            realized_lt_profit: node.parse_attribute("realizedLTProfit")?,
48            realized_lt_loss: node.parse_attribute("realizedLTLoss")?,
49            unrealized_lt_profit: node.parse_attribute("unrealizedLTProfit")?,
50            unrealized_lt_loss: node.parse_attribute("unrealizedLTLoss")?,
51
52            total_realized_pnl: node.parse_attribute("totalRealizedPnl")?,
53            total_fifo_pnl: node.parse_attribute("totalFifoPnl")?,
54        })
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use crate::Parser;
62    use anyhow::Result;
63
64    const PARTIAL_STATEMENT_EXAMPLE: &str = r##"
65        <FlexQueryResponse queryName="example-query" type="AF">
66            <FlexStatements count="1">
67                <FlexStatement accountId="U1234567" fromDate="2025-04-25" toDate="2025-04-25" period="LastBusinessDay" whenGenerated="2025-04-26;13:34:28 EDT">
68                    <AccountInformation accountId="U1234567" accountType="Individual" customerType="Individual" accountCapabilities="Portfolio Margin" tradingPermissions="Stocks,Options,Warrants,Forex,Futures,Crypto Currencies,Mutual Funds,Fully Paid Stock Loan" />
69                    <FIFOPerformanceSummaryInBase>
70                        <FIFOPerformanceSummaryUnderlying accountId="U1234567" assetCategory="STK" symbol="ARGX" conid="276343981" listingExchange="NASDAQ" reportDate="2025-04-25" realizedSTProfit="0" realizedSTLoss="-636.4413056" realizedLTProfit="0" realizedLTLoss="0" totalRealizedPnl="-636.4413056" unrealizedProfit="0" unrealizedLoss="0" unrealizedSTProfit="0" unrealizedSTLoss="0" unrealizedLTProfit="0" unrealizedLTLoss="0" totalFifoPnl="-636.4413056" />
71                        <FIFOPerformanceSummaryUnderlying accountId="U1234567" assetCategory="STK" symbol="GEO" conid="158655765" listingExchange="NYSE" reportDate="2025-04-25" realizedSTProfit="0" realizedSTLoss="-1375.50915991" realizedLTProfit="0" realizedLTLoss="0" totalRealizedPnl="-1375.50915991" unrealizedProfit="0" unrealizedLoss="0" unrealizedSTProfit="0" unrealizedSTLoss="0" unrealizedLTProfit="0" unrealizedLTLoss="0" totalFifoPnl="-1375.50915991" />
72                        <FIFOPerformanceSummaryUnderlying accountId="U1234567" assetCategory="STK" symbol="GRPN" conid="426480582" listingExchange="NASDAQ" reportDate="2025-04-25" realizedSTProfit="0" realizedSTLoss="1607.307677" realizedLTProfit="0" realizedLTLoss="0" totalRealizedPnl="1607.307677" unrealizedProfit="77.771818" unrealizedLoss="-868.095492" unrealizedSTProfit="77.771818" unrealizedSTLoss="-868.095492" unrealizedLTProfit="0" unrealizedLTLoss="0" totalFifoPnl="816.984003" />
73                        <FIFOPerformanceSummaryUnderlying accountId="U1234567" assetCategory="STK" symbol="META" conid="107113386" listingExchange="NASDAQ" reportDate="2025-04-25" realizedSTProfit="0" realizedSTLoss="0" realizedLTProfit="0" realizedLTLoss="0" totalRealizedPnl="0" unrealizedProfit="8598.681628" unrealizedLoss="-4398.965111" unrealizedSTProfit="8598.681628" unrealizedSTLoss="-4398.965111" unrealizedLTProfit="0" unrealizedLTLoss="0" totalFifoPnl="4199.716517" />
74                        <FIFOPerformanceSummaryUnderlying accountId="U1234567" assetCategory="STK" symbol="NFLX" conid="15124833" listingExchange="NASDAQ" reportDate="2025-04-25" realizedSTProfit="0" realizedSTLoss="0" realizedLTProfit="0" realizedLTLoss="0" totalRealizedPnl="0" unrealizedProfit="18081.807156" unrealizedLoss="0" unrealizedSTProfit="18081.807156" unrealizedSTLoss="0" unrealizedLTProfit="0" unrealizedLTLoss="0" totalFifoPnl="18081.807156" />
75                        <FIFOPerformanceSummaryUnderlying accountId="U1234567" assetCategory="STK" symbol="PLTR" conid="444857009" listingExchange="NASDAQ" reportDate="2025-04-25" realizedSTProfit="0" realizedSTLoss="0" realizedLTProfit="0" realizedLTLoss="0" totalRealizedPnl="0" unrealizedProfit="24855.882465" unrealizedLoss="0" unrealizedSTProfit="24855.882465" unrealizedSTLoss="0" unrealizedLTProfit="0" unrealizedLTLoss="0" totalFifoPnl="24855.882465" />
76                        <FIFOPerformanceSummaryUnderlying accountId="U1234567" assetCategory="STK" symbol="TQQQ" conid="72539702" listingExchange="NASDAQ" reportDate="2025-04-25" realizedSTProfit="0" realizedSTLoss="0" realizedLTProfit="0" realizedLTLoss="0" totalRealizedPnl="0" unrealizedProfit="42178.328575" unrealizedLoss="-39340.67993" unrealizedSTProfit="42178.328575" unrealizedSTLoss="-39340.67993" unrealizedLTProfit="0" unrealizedLTLoss="0" totalFifoPnl="2837.648645" />
77                        <FIFOPerformanceSummaryUnderlying accountId="U1234567" assetCategory="STK" symbol="TSLA" conid="76792991" listingExchange="NASDAQ" reportDate="2025-04-25" realizedSTProfit="0" realizedSTLoss="199.59291494" realizedLTProfit="0" realizedLTLoss="0" totalRealizedPnl="199.59291494" unrealizedProfit="33175.116277" unrealizedLoss="-226.596415" unrealizedSTProfit="33175.116277" unrealizedSTLoss="-226.596415" unrealizedLTProfit="0" unrealizedLTLoss="0" totalFifoPnl="33148.11277694" />
78                        <FIFOPerformanceSummaryUnderlying
79                            accountId="U1234567"
80                            assetCategory="STK"
81                            symbol="TTWO"
82                            conid="6478131"
83                            listingExchange="NASDAQ"
84                            reportDate="2025-04-25"
85                            realizedSTProfit="0"
86                            realizedSTLoss="0"
87                            realizedLTProfit="0"
88                            realizedLTLoss="0"
89                            totalRealizedPnl="0"
90                            unrealizedProfit="4089.983554"
91                            unrealizedLoss="0"
92                            unrealizedSTProfit="4089.983554"
93                            unrealizedSTLoss="0"
94                            unrealizedLTProfit="0"
95                            unrealizedLTLoss="0"
96                            totalFifoPnl="4089.983554" />
97
98                        <FIFOPerformanceSummaryUnderlying
99                            accountId="U1234567"
100                            assetCategory=""
101                            symbol=""
102                            conid=""
103                            listingExchange=""
104                            reportDate="2025-04-25"
105                            realizedSTProfit="0"
106                            realizedSTLoss="-205.04987357"
107                            realizedLTProfit="0"
108                            realizedLTLoss="0"
109                            totalRealizedPnl="-205.04987357"
110                            unrealizedProfit="131057.571473"
111                            unrealizedLoss="-44834.337024864"
112                            unrealizedSTProfit="131057.571473"
113                            unrealizedSTLoss="-44834.337024864"
114                            unrealizedLTProfit="0"
115                            unrealizedLTLoss="0"
116                            totalFifoPnl="86018.184574566" />
117                    </FIFOPerformanceSummaryInBase>
118                </FlexStatement>
119            </FlexStatements>
120         </FlexQueryResponse>
121    "##;
122
123    #[test]
124    fn fifo_performance_summaries_parse() -> Result<()> {
125        let statements = Parser::new()?.parse_flex_query_response(PARTIAL_STATEMENT_EXAMPLE)?;
126        assert_eq!(statements.len(), 1);
127        let result = &statements[0];
128
129        // Ensure we got two equity summaries.
130        assert_eq!(result.fifo_performance_summaries.len(), 10);
131
132        assert_eq!(
133            result.fifo_performance_summaries[8],
134            FIFOPerformanceSummary {
135                account_id: "U1234567".to_string(),
136                ticker: Some("TTWO".to_string()),
137                conid: Some(6478131),
138                listing_exchange: Some("NASDAQ".to_string()),
139                timestamp_eod_ms: result.fifo_performance_summaries[8].timestamp_eod_ms,
140                realized_st_profit: 0.0,
141                realized_st_loss: 0.0,
142                unrealized_st_profit: 4089.983554,
143                unrealized_st_loss: 0.0,
144                realized_lt_profit: 0.0,
145                realized_lt_loss: 0.0,
146                unrealized_lt_profit: 0.0,
147                unrealized_lt_loss: 0.0,
148                total_realized_pnl: 0.0,
149                total_fifo_pnl: 4089.983554,
150            }
151        );
152
153        assert_eq!(
154            result.fifo_performance_summaries[9],
155            FIFOPerformanceSummary {
156                account_id: "U1234567".to_string(),
157                ticker: None,
158                conid: None,
159                listing_exchange: None,
160                timestamp_eod_ms: result.fifo_performance_summaries[9].timestamp_eod_ms,
161                realized_st_profit: 0.0,
162                realized_st_loss: -205.04987357,
163                unrealized_st_profit: 131057.571473,
164                unrealized_st_loss: -44834.337024864,
165                realized_lt_profit: 0.0,
166                realized_lt_loss: 0.0,
167                unrealized_lt_profit: 0.0,
168                unrealized_lt_loss: 0.0,
169                total_realized_pnl: -205.04987357,
170                total_fifo_pnl: 86018.184574566,
171            }
172        );
173        Ok(())
174    }
175}