Initial commit
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"""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
|
||||
)
|
||||
Reference in New Issue
Block a user