File size: 5,793 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/usr/bin/env python3
"""
Script to compare summary card exposures with position details exposures,
using the same methods as the UI components.

This script loads portfolio data from a CSV file, calculates the summary card values,
and compares them with the sum of exposures from the position details as they would
appear in the UI.
"""

import os
import sys

import pandas as pd

# Add the src directory to the Python path
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))

from src.folio.components.summary_cards import format_summary_card_values
from src.folio.portfolio import process_portfolio_data


def load_portfolio_data(csv_path):
    """Load portfolio data from a CSV file."""
    try:
        df = pd.read_csv(csv_path)
        return df
    except Exception:
        return None


def compare_exposures():
    """Compare summary card exposures with position details exposures."""
    # Try to load the private portfolio data first
    private_csv_path = "private-data/portfolio-private.csv"
    sample_csv_path = "sample-data/sample-portfolio.csv"

    if os.path.exists(private_csv_path):
        df = load_portfolio_data(private_csv_path)
    elif os.path.exists(sample_csv_path):
        df = load_portfolio_data(sample_csv_path)
    else:
        return

    if df is None:
        return

    # Process the portfolio data
    result = process_portfolio_data(df)

    # Check the structure of the result
    if isinstance(result, tuple):
        if len(result) == 3:
            # Newer version: (groups, summary, cash_like_positions)
            groups, summary, cash_like_positions = result
        elif len(result) == 2:
            # Possible alternative: (groups, cash_like_positions)
            groups, cash_like_positions = result
            from src.folio.portfolio import calculate_portfolio_summary

            summary = calculate_portfolio_summary(groups, cash_like_positions, 0.0)
    else:
        # If result is not a tuple, it's likely just the groups
        groups = result
        from src.folio.portfolio import calculate_portfolio_summary

        summary = calculate_portfolio_summary(groups, [], 0.0)

    # Ensure we have a valid summary object
    if not hasattr(summary, "to_dict"):
        # Create a minimal summary for testing
        from src.folio.data_model import ExposureBreakdown, PortfolioSummary

        empty_exposure = ExposureBreakdown()
        summary = PortfolioSummary(
            net_market_exposure=0.0,
            portfolio_beta=0.0,
            long_exposure=empty_exposure,
            short_exposure=empty_exposure,
            options_exposure=empty_exposure,
        )

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

    # Extract the values from the formatted values
    formatted_values[0]
    net_exposure = formatted_values[1]
    formatted_values[3]
    beta_adjusted_net_exposure = formatted_values[4]
    long_exposure = formatted_values[5]
    short_exposure = formatted_values[7]
    options_exposure = formatted_values[9]
    formatted_values[11]

    # Calculate the sum of exposures from the position details as they would appear in the UI

    # Initialize counters for UI exposures
    total_ui_market_value = 0.0
    total_ui_beta_adjusted_exposure = 0.0
    total_ui_delta_exposure = 0.0

    # Process each group as it would be displayed in the UI

    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

        # Print the values for this group

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

    # 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_net_exposure)
    extract_numeric(long_exposure)
    extract_numeric(short_exposure)
    summary_options_exposure = extract_numeric(options_exposure)

    # Compare with summary card values

    # 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

    # Determine if the summary card values match the UI values
    if abs(summary_net_exposure - total_ui_market_value) < 0.01:
        pass
    else:
        pass

    if abs(summary_beta_adjusted_net_exposure - total_ui_beta_adjusted_exposure) < 0.01:
        pass
    else:
        pass

    if abs(summary_options_exposure - total_ui_delta_exposure) < 0.01:
        pass
    else:
        pass


if __name__ == "__main__":
    compare_exposures()