Update app.py
Browse files
app.py
CHANGED
|
@@ -115,13 +115,15 @@ def plot_ladder(df: pd.DataFrame):
|
|
| 115 |
pivot = df.pivot(index="time_bucket", columns="bucket", values="amount").fillna(0)
|
| 116 |
order = ["T+1", "T+2..7", "T+8..30", "T+31+"]
|
| 117 |
pivot = pivot.reindex(order)
|
|
|
|
|
|
|
| 118 |
fig, ax = plt.subplots(figsize=(7, 4))
|
| 119 |
assets = pivot["Assets"] if "Assets" in pivot.columns else zeros_like_index(pivot.index)
|
| 120 |
sof = pivot["SoF"] if "SoF" in pivot.columns else zeros_like_index(pivot.index)
|
| 121 |
ax.bar(pivot.index, assets, label="Assets")
|
| 122 |
ax.bar(pivot.index, -sof, label="SoF")
|
| 123 |
ax.axhline(0, color="gray", lw=1)
|
| 124 |
-
ax.set_ylabel("LKR")
|
| 125 |
ax.set_title("Maturity Ladder (Assets vs SoF)")
|
| 126 |
ax.legend()
|
| 127 |
fig.tight_layout()
|
|
@@ -171,11 +173,9 @@ def irr_sql(cols: List[str]) -> str:
|
|
| 171 |
return f"""
|
| 172 |
SELECT
|
| 173 |
bucket,
|
| 174 |
-
SUM(Portfolio_value) AS
|
| 175 |
-
SUM(Portfolio_value * {t_expr}) / NULLIF(SUM(Portfolio_value),0) AS dur_mac,
|
| 176 |
-
SUM(Portfolio_value * ({t_expr})/(1+({y_expr}))) / NULLIF(SUM(Portfolio_value),0) AS dur_mod
|
| 177 |
FROM {VIEW_FQN}
|
| 178 |
-
GROUP BY bucket
|
| 179 |
"""
|
| 180 |
|
| 181 |
# =========================
|
|
@@ -210,17 +210,20 @@ def run_dashboard() -> Tuple[str, str, str, str, str, Any, pd.DataFrame, pd.Data
|
|
| 210 |
# 4) Ladder & IRR
|
| 211 |
ladder = conn.execute(LADDER_SQL).fetchdf()
|
| 212 |
irr = conn.execute(irr_sql(cols)).fetchdf()
|
|
|
|
|
|
|
|
|
|
| 213 |
|
| 214 |
# 5) Chart
|
| 215 |
fig = plot_ladder(ladder)
|
| 216 |
|
| 217 |
-
status = "✅ OK"
|
| 218 |
return (
|
| 219 |
status,
|
| 220 |
as_of,
|
| 221 |
-
f"{assets_t1:,.
|
| 222 |
-
f"{sof_t1:,.
|
| 223 |
-
f"{net_gap:,.
|
| 224 |
fig,
|
| 225 |
ladder,
|
| 226 |
irr,
|
|
@@ -256,9 +259,9 @@ with gr.Blocks(title=APP_TITLE) as demo:
|
|
| 256 |
as_of = gr.Textbox(label="As of date", interactive=False)
|
| 257 |
|
| 258 |
with gr.Row():
|
| 259 |
-
a1 = gr.Textbox(label="Assets T+1 (LKR)", interactive=False)
|
| 260 |
-
a2 = gr.Textbox(label="SoF T+1 (LKR)", interactive=False)
|
| 261 |
-
a3 = gr.Textbox(label="Net Gap T+1 (LKR)", interactive=False)
|
| 262 |
|
| 263 |
chart = gr.Plot(label="Maturity Ladder")
|
| 264 |
ladder_df = gr.Dataframe(label="Ladder Detail")
|
|
|
|
| 115 |
pivot = df.pivot(index="time_bucket", columns="bucket", values="amount").fillna(0)
|
| 116 |
order = ["T+1", "T+2..7", "T+8..30", "T+31+"]
|
| 117 |
pivot = pivot.reindex(order)
|
| 118 |
+
# Convert to millions for plotting
|
| 119 |
+
pivot = pivot / 1_000_000
|
| 120 |
fig, ax = plt.subplots(figsize=(7, 4))
|
| 121 |
assets = pivot["Assets"] if "Assets" in pivot.columns else zeros_like_index(pivot.index)
|
| 122 |
sof = pivot["SoF"] if "SoF" in pivot.columns else zeros_like_index(pivot.index)
|
| 123 |
ax.bar(pivot.index, assets, label="Assets")
|
| 124 |
ax.bar(pivot.index, -sof, label="SoF")
|
| 125 |
ax.axhline(0, color="gray", lw=1)
|
| 126 |
+
ax.set_ylabel("LKR (mn)")
|
| 127 |
ax.set_title("Maturity Ladder (Assets vs SoF)")
|
| 128 |
ax.legend()
|
| 129 |
fig.tight_layout()
|
|
|
|
| 173 |
return f"""
|
| 174 |
SELECT
|
| 175 |
bucket,
|
| 176 |
+
SUM(Portfolio_value) / 1000000.0 AS "Portfolio Value (mn)"
|
|
|
|
|
|
|
| 177 |
FROM {VIEW_FQN}
|
| 178 |
+
GROUP BY bucket
|
| 179 |
"""
|
| 180 |
|
| 181 |
# =========================
|
|
|
|
| 210 |
# 4) Ladder & IRR
|
| 211 |
ladder = conn.execute(LADDER_SQL).fetchdf()
|
| 212 |
irr = conn.execute(irr_sql(cols)).fetchdf()
|
| 213 |
+
# Format IRR dataframe to 2 decimal places
|
| 214 |
+
if "Portfolio Value (mn)" in irr.columns:
|
| 215 |
+
irr["Portfolio Value (mn)"] = irr["Portfolio Value (mn)"].map('{:,.2f}'.format)
|
| 216 |
|
| 217 |
# 5) Chart
|
| 218 |
fig = plot_ladder(ladder)
|
| 219 |
|
| 220 |
+
status = f"✅ OK (as of {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')})"
|
| 221 |
return (
|
| 222 |
status,
|
| 223 |
as_of,
|
| 224 |
+
f"{(assets_t1 / 1_000_000):,.2f}",
|
| 225 |
+
f"{(sof_t1 / 1_000_000):,.2f}",
|
| 226 |
+
f"{(net_gap / 1_000_000):,.2f}",
|
| 227 |
fig,
|
| 228 |
ladder,
|
| 229 |
irr,
|
|
|
|
| 259 |
as_of = gr.Textbox(label="As of date", interactive=False)
|
| 260 |
|
| 261 |
with gr.Row():
|
| 262 |
+
a1 = gr.Textbox(label="Assets T+1 (LKR mn)", interactive=False)
|
| 263 |
+
a2 = gr.Textbox(label="SoF T+1 (LKR mn)", interactive=False)
|
| 264 |
+
a3 = gr.Textbox(label="Net Gap T+1 (LKR mn)", interactive=False)
|
| 265 |
|
| 266 |
chart = gr.Plot(label="Maturity Ladder")
|
| 267 |
ladder_df = gr.Dataframe(label="Ladder Detail")
|