91 lines
3.0 KiB
Python
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
|
|
)
|