-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
95 lines (72 loc) · 2.44 KB
/
utils.py
File metadata and controls
95 lines (72 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"""
memo.py — Investment memo generation.
Produces a structured markdown memo that includes:
- Client profile summary
- Recommended allocation + rationale
- Suitability note
- Disclosure statement
- Review status
"""
from datetime import datetime
def build_memo(client: dict, pipeline: dict) -> str:
"""
Generate a complete investment memo as markdown text.
Parameters
----------
client : dict — the client profile from sample_data
pipeline : dict — output of logic.run_pipeline()
"""
w = pipeline["weights"]
suit = pipeline["suit"]
flags = pipeline["flags"]
flag_text = "\n".join(f"- {f}" for f in flags) if flags else "None"
review_status = "**Review required**" if flags else "No review flag triggered"
memo = f"""# Investment Memo
**Generated:** {datetime.now().strftime("%Y-%m-%d %H:%M")}
---
## 1. Client Profile
| Field | Value |
|-------|-------|
| Client ID | {client['client_id']} |
| Name | {client['name']} |
| Age | {client['age']} |
| Investment Horizon | {client['horizon_years']} years |
| Liquidity Need | {client['liquidity_need']} |
| Goal | {client['goal'].replace('_', ' ')} |
| Risk Score | {client['risk_score_100']} / 100 |
| Risk Bucket | {pipeline['bucket']} |
## 2. Recommended Allocation
| Asset | Weight |
|-------|--------|
| Equity | {w['Equity']:.1%} |
| Bond | {w['Bond']:.1%} |
| Gold | {w['Gold']:.1%} |
| Cash | {w['Cash']:.1%} |
## 3. Suitability Note
- Equity cap applied: {suit['equity_cap']:.0%}
- Cash floor applied: {suit['cash_floor']:.0%}
- Restricted products: {', '.join(suit['restricted']) if suit['restricted'] else 'None'}
## 4. Review Flags
{flag_text}
## 5. Status
{review_status}
Uncertainty level: **{pipeline['uncertainty'].upper()}**
## 6. Disclosure
> This output is generated by an automated decision-support prototype.
> It is intended for **educational purposes only** and does not constitute
> personalized investment advice.
>
> The model uses questionnaire-derived risk scores and preset return
> assumptions. It does **not** consider tax status, external holdings,
> recent market events, or individual financial circumstances beyond
> those captured in the client profile.
>
> This recommendation has **not** been reviewed by a human advisor
> unless explicitly noted above.
>
> If review flags are present, the recommendation should be evaluated
> by a qualified reviewer before any action is taken.
---
*End of memo*
"""
return memo