Files
2025-12-09 12:13:01 +01:00

91 lines
3.0 KiB
Python

"""Rich rendering for 13F holdings reports."""
from rich import box
from rich.console import Group
from rich.panel import Panel
from rich.table import Column, Table
__all__ = ['render_rich', 'infotable_summary']
def infotable_summary(thirteen_f):
"""
Create a summary DataFrame of the information table for display.
Args:
thirteen_f: ThirteenF instance
Returns:
pd.DataFrame or None: Summary of holdings sorted by value
"""
if thirteen_f.has_infotable():
infotable = thirteen_f.infotable
if infotable is not None and len(infotable) > 0:
return (infotable
.filter(['Issuer', 'Class', 'Cusip', 'Ticker', 'Value', 'SharesPrnAmount', 'Type', 'PutCall',
'SoleVoting', 'SharedVoting', 'NonVoting'])
.rename(columns={'SharesPrnAmount': 'Shares'})
.assign(Value=lambda df: df.Value,
Type=lambda df: df.Type.fillna('-'),
Ticker=lambda df: df.Ticker.fillna(''))
.sort_values(['Value'], ascending=False)
)
return None
def render_rich(thirteen_f):
"""
Create Rich Panel display for a 13F filing.
Args:
thirteen_f: ThirteenF instance
Returns:
Panel: Rich Panel containing filing summary and holdings table
"""
title = f"{thirteen_f.form} Holding Report for {thirteen_f.filing.company} for period {thirteen_f.report_period}"
summary = Table(
"Report Period",
Column("Investment Manager", style="bold deep_sky_blue1"),
"Signed By",
"Holdings",
"Value",
"Accession Number",
"Filed",
box=box.SIMPLE)
summary.add_row(
thirteen_f.report_period,
thirteen_f.investment_manager.name if thirteen_f.investment_manager else thirteen_f.manager_name,
thirteen_f.signer or "-",
str(thirteen_f.total_holdings or "-"),
f"${thirteen_f.total_value:,.0f}" if thirteen_f.total_value else "-",
thirteen_f.filing.accession_no,
thirteen_f.filing_date
)
content = [summary]
# info table
infotable_summary_df = infotable_summary(thirteen_f)
if infotable_summary_df is not None:
table = Table("", "Issuer", "Class", "Cusip", "Ticker", "Value", "Type", "Shares", "Put/Call",
row_styles=["bold", ""],
box=box.SIMPLE)
for index, row in enumerate(infotable_summary_df.itertuples()):
table.add_row(str(index),
row.Issuer,
row.Class,
row.Cusip,
row.Ticker,
f"${row.Value:,.0f}",
row.Type,
f"{int(row.Shares):,.0f}",
row.PutCall
)
content.append(table)
return Panel(
Group(*content), title=title, subtitle=title
)