File size: 5,435 Bytes
ce4bc73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""End-to-end tests for exposure calculations."""

from src.folio.components.summary_cards import format_summary_card_values
from src.folio.formatting import format_currency


class TestExposures:
    """Test exposure calculations."""

    def test_summary_cards_match_position_details(self, processed_portfolio):
        """Test that summary card values match position details."""
        # Get the processed portfolio data
        groups, summary, summary_dict = processed_portfolio

        # Get the summary card values
        formatted_values = format_summary_card_values(summary_dict)

        # Extract the values from the formatted values
        formatted_values[0]  # Portfolio Value
        net_exposure = formatted_values[1]  # Net Exposure
        formatted_values[2]  # Net Exposure Percent
        beta_adjusted_exposure = formatted_values[3]  # Beta-Adjusted Net Exposure
        formatted_values[4]  # Beta-Adjusted Net Exposure Percent
        long_exposure = formatted_values[5]  # Long Exposure
        formatted_values[6]  # Long Exposure Percent
        short_exposure = formatted_values[7]  # Short Exposure
        formatted_values[8]  # Short Exposure Percent
        options_exposure = formatted_values[9]  # Options Exposure
        formatted_values[10]  # Options Exposure Percent
        formatted_values[11]  # Cash Value
        formatted_values[12]  # Cash Percent

        # Extract numeric values from formatted strings
        def extract_numeric(value):
            return float(value.replace("$", "").replace(",", ""))

        summary_net_exposure = extract_numeric(net_exposure)
        summary_beta_adjusted_net_exposure = extract_numeric(beta_adjusted_exposure)
        summary_long_exposure = extract_numeric(long_exposure)
        summary_short_exposure = extract_numeric(short_exposure)
        summary_options_exposure = extract_numeric(options_exposure)

        # Calculate position details exposures as they would appear in the UI
        total_ui_market_value = 0.0
        total_ui_beta_adjusted_exposure = 0.0
        total_ui_delta_exposure = 0.0

        for group in groups:
            # Get values as they would be displayed in the UI
            market_value = (
                group.net_exposure
            )  # This is what's shown as "Total Value" in the UI
            beta_adjusted = (
                group.beta_adjusted_exposure
            )  # This is what's shown as "Beta-Adjusted Exposure" in the UI
            delta_exposure = (
                group.total_delta_exposure
            )  # This is what's shown as "Total Delta Exposure" in the UI

            # Add to totals
            total_ui_market_value += market_value
            total_ui_beta_adjusted_exposure += beta_adjusted
            total_ui_delta_exposure += delta_exposure

        # Calculate long and short exposures from UI values
        ui_long_exposure = 0.0
        ui_short_exposure = 0.0

        for group in groups:
            if group.stock_position:
                stock = group.stock_position
                if stock.quantity >= 0:  # Long position
                    ui_long_exposure += stock.market_value
                else:  # Short position
                    ui_short_exposure += stock.market_value  # Already negative

            # Process option positions
            for opt in group.option_positions:
                if opt.delta_exposure >= 0:  # Long position
                    ui_long_exposure += opt.delta_exposure
                else:  # Short position
                    ui_short_exposure += opt.delta_exposure  # Already negative

        # Print detailed debug information
        for _key, value in summary_dict.items():
            if isinstance(value, dict):
                for _subkey, _subvalue in value.items():
                    pass
            else:
                pass

        summary_dict.get("pending_activity_value", 0.0)

        # Test that summary card values match position details
        assert abs(summary_net_exposure - total_ui_market_value) < 0.01, (
            f"Net Exposure in summary cards ({format_currency(summary_net_exposure)}) does not match the total market value shown in the UI ({format_currency(total_ui_market_value)})"
        )

        assert (
            abs(summary_beta_adjusted_net_exposure - total_ui_beta_adjusted_exposure)
            < 0.01
        ), (
            f"Beta-Adjusted Net Exposure in summary cards ({format_currency(summary_beta_adjusted_net_exposure)}) does not match the total beta-adjusted exposure shown in the UI ({format_currency(total_ui_beta_adjusted_exposure)})"
        )

        assert abs(summary_long_exposure - ui_long_exposure) < 0.01, (
            f"Long Exposure in summary cards ({format_currency(summary_long_exposure)}) does not match the calculated long exposure ({format_currency(ui_long_exposure)})"
        )

        assert abs(summary_short_exposure - ui_short_exposure) < 0.01, (
            f"Short Exposure in summary cards ({format_currency(summary_short_exposure)}) does not match the calculated short exposure ({format_currency(ui_short_exposure)})"
        )

        assert abs(summary_options_exposure - total_ui_delta_exposure) < 0.01, (
            f"Options Exposure in summary cards ({format_currency(summary_options_exposure)}) does not match the total delta exposure shown in the UI ({format_currency(total_ui_delta_exposure)})"
        )