folio / scripts /compare_exposures_ui.py
dystomachina's picture
Initial commit for Folio project
ce4bc73
#!/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()