Asteria Investment Office — Operational Skill
Environment
All tasks use the shared Asteria API at http://34.46.77.124:8010. Treat the API as the current book of record. Local payload files (in input/payloads/) are intake context — they may contain stale marks, outdated worksheets, or pre-refresh preferences. When the API and a local payload disagree, the API wins.
The current environment as_of_date is 2026-05-29. Always set as_of_date to this value in outputs. Set data_precedence to "current_environment_over_stale_payload" whenever the local payload contains stale/older data that the API supersedes.
Key endpoints
| Endpoint |
Use |
GET /api/catalog |
Inventory of all IDs (bonds, indices, issuers, portfolios, policies, opportunity sets) |
GET /api/portfolios |
List all portfolios with metadata, constraint policy, and current MV |
GET /api/portfolios/<id> |
Full portfolio detail including holdings (instrument_id, quantity_usd_m, sleeve, asset_class, notes) |
GET /api/instruments/bonds |
Bond master: instrument_id, issuer_id, rating, rating_bucket (IG/HY), modified_duration_years, yield_to_maturity_pct, coupon_pct, maturity, sector, subsector, spread_bps, candidate flag, energy_linked flag, recommended_theme_tags |
GET /api/issuers |
Issuer master: issuer_id, issuer_name, sector, subsector, rating_bucket, credit_outlook, watchlist flag, research_tags |
GET /api/indices |
Index metadata: index_id, display_name, region, currency, frequency, level date range |
GET /api/index-levels |
All index monthly levels (12 points: 2025-05-30 through 2026-04-30) |
GET /api/index-levels/<id> |
Single index levels |
GET /api/policies |
All policy thresholds including allocation mapping, correlation defaults, credit defaults, credit risk reduction, multi-asset defaults |
GET /api/allocation/opportunity-sets |
Opportunity-set taxonomy (opportunity_set, asset_class, sub_asset_class, display_order) |
GET /api/allocation/prior-views |
Prior-quarter views (opportunity_set, quarter, previous_quarter, view, conviction) — key for computing change |
GET /api/macro-signals |
Q2/Q3 2026 signal scores per opportunity_set (score, rationale_code, drivers, quarter) |
GET /api/market/energy |
Energy commodity signals and pitch themes |
Workflow: Always start by reading the API
- Fetch
/api/catalog to orient on available IDs.
- Read the answer template (
input/payloads/answer_template.json) for the required output shape, key names, enum values, ordering rules, and numeric precision.
- Read the payload (desk request, review request, allocation request, risk memo, committee request) for the task's scope — which portfolio, which instruments/indices/opportunity-sets are in play, and any stale data warnings.
- Fetch the portfolio (
/api/portfolios/<id>) for current holdings and constraint policy.
- Fetch the relevant policy (
/api/policies) — the portfolio's constraint_policy_id tells you which thresholds apply.
- Fetch supporting data (bonds, issuers, indices, index-levels, macro-signals, prior-views, opportunity-sets) relevant to the task.
Task archetypes and computation rules
A. Credit trade / rebalance (bond portfolios)
Selecting bonds:
- Prefer bonds where
candidate: true.
- For energy-linked mandates, prefer
energy_linked: true.
- Avoid issuers where
watchlist: true (from /api/issuers). If the task requires avoiding watchlist buys, never propose a BUY for a watchlisted issuer's bonds.
- If the task requires selling watchlist positions, identify holdings whose issuer has
watchlist: true.
- For income/carry objectives, prefer higher
yield_to_maturity_pct while respecting constraint policy.
Post-trade metrics — key formulas:
total_market_value_usd_m (precision 1 or 2, follow template):
= sum of all holding market values after proposed trades
= current portfolio MV + net new buy notional (for buy-only)
= current portfolio MV (for rotation/rebalance — MV is preserved unless funded)
For a rotation (sell to fund buy), total MV stays at the pre-trade level. For a buy package funded from new sleeve allocation, total MV = pre-trade MV + total buy notional.
HY allocation pct (precision 2):
hy_allocation_pct = (sum of HY-bucket holding quantities) / total MV * 100
Where HY bucket = bonds whose rating_bucket is "HY" in the bond master.
weighted_modified_duration_years (precision 2):
weighted_duration = sum(quantity_i / total_MV * duration_i) for all holdings
weighted_yield_to_maturity_pct (precision 2):
weighted_YTM = sum(quantity_i / total_MV * YTM_i) for all holdings
hy_reduction_pct_points (precision 2):
hy_reduction = pre_trade_hy_pct - post_trade_hy_pct
post_trade_watchlist_exposure_usd_m (precision 1):
= sum of quantities of all holdings whose issuer has watchlist: true after trades
Constraint checks (booleans):
- hy_cap_pass:
post_trade_hy_allocation_pct <= max_hy_allocation_pct (from policy)
- duration_band_pass:
duration_band_years[0] <= post_trade_duration <= duration_band_years[1]
- selected_issuer_diversification_pass: no single issuer among the BUY selections exceeds
issuer_concentration_limit_pct of total MV (check if any issuer appears on more than one selected ticket)
- selected_subsector_diversification_pass: at least
subsector_min_count_for_diversified distinct subsectors among BUY selections
- watchlist_avoidance_pass: no BUY ticket is for a watchlisted issuer
- target_hy_reduction_met:
hy_reduction_pct_points >= target_hy_reduction_pct from policy
- watchlist_exposure_cleared:
post_trade_watchlist_exposure == 0
Trade ordering in output:
- Template specifies the rule. Common patterns: SELL before BUY, then alphabetical by
instrument_id within each action group. Or: sort ascending by instrument_id.
B. Equity correlation review
Computing Pearson correlation from index levels:
- Filter index levels to the review window (from
level_start_date through level_end_date). Both endpoints are included — the first date is the base for the first return.
- Compute monthly simple returns for each index:
r_t = (level_t / level_{t-1}) - 1
where t and t-1 are consecutive monthly observation dates.
- The number of return observations = number of level dates minus 1.
- Compute Pearson correlation between each pair of return series. Round to 3 decimal places.
- Include all requested indices in
index_set, sorted alphabetically.
Extreme pairs:
- highest_positive: the pair with the largest positive correlation (closest to +1.0). If ties, pick alphabetically.
- lowest: the pair with the most negative correlation (closest to -1.0). This is the lowest numeric value, not the lowest absolute value.
- Each pair's index IDs must be sorted alphabetically within the pair.
Concentration / dependence check:
- Compare the highest correlation against
correlation_high_threshold (default 0.8 from POL_CORRELATION_DEFAULT).
china_asia_dependence_flag: true if the China-related pair exceeds the high threshold AND involves IDX_CHINA + an Asia/Emerging index.
high_threshold_breached: true if any pair exceeds correlation_high_threshold.
primary_code: "CHINA_ASIA_DEPENDENCE" if China concentration is the primary concern, "GLOBAL_DEVELOPED_OVERLAP" for developed-market overlaps, "NO_MATERIAL_CONCENTRATION" if no threshold breached.
Diversification candidates:
- Indices that appear in the lowest-correlation pair (the best diversifier) OR that have pairwise correlations below
correlation_low_threshold (default 0.2). Sorted alphabetically.
Sleeve actions:
- For concentrated sleeves:
"trim".
- For diversification candidates:
"add".
- Sorted alphabetically by
sleeve name (or by the order in the template).
C. Allocation view refresh
Determining active view (UW / N / OW):
From /api/policies → allocation_mapping.view_score_thresholds:
score >= OW_min (0.35) → "OW"
score <= UW_max (-0.35) → "UW"
- Otherwise →
"N"
Determining conviction (LOW / MEDIUM / HIGH):
From /api/policies → allocation_mapping.conviction_thresholds:
|score| >= HIGH_abs_min (0.7) → "HIGH"
|score| >= MEDIUM_abs_min (0.35) → "MEDIUM"
- Otherwise →
"LOW"
Determining change (UP / DOWN / UNCHANGED):
Compare current view to prior-quarter view (from /api/allocation/prior-views):
- Map views to ranks: UW = -1, N = 0, OW = +1 (from
view_rank in policy).
- If current rank > prior rank →
"UP"
- If current rank < prior rank →
"DOWN"
- If equal →
"UNCHANGED"
Rationale code:
- Use the
rationale_code from /api/macro-signals for the given opportunity_set and target quarter.
- The signal score column is also the
signal_score field (precision 3).
Prior view:
- From
/api/allocation/prior-views: look up the view for the opportunity_set where previous_quarter matches the task's prior quarter.
- Important: The prior-views endpoint returns entries where
quarter is the target quarter and previous_quarter is the prior quarter. Match on both opportunity_set and previous_quarter.
Risk overlay:
- Select the overlay whose
primary_action best matches the dominant tilt across views:
"DURATION_QUALITY_TILT" / "tilt_to_duration_quality" — when OW duration/IG, UW HY
"CREDIT_RISK_REDUCTION" / "trim_credit_beta" — when reducing credit risk
"EQUITY_BETA_EXTENSION" / "add_cyclical_equity_beta" — when adding equity exposure
"CURRENCY_DEFENSIVE_HEDGE" / "add_currency_hedge" — when hedging currency
"NO_OVERLAY" / "hold_policy_weights" — when no significant tilt
rationale_codes: List the rationale codes of the views that drive the overlay decision, in business priority order (strongest/clearest signal first).
Ordering:
allocation_views list: follow the order of focus_opportunity_sets from the request payload (not alphabetical).
rationale_codes list: business priority order, highest priority first.
D. Multi-asset committee (hybrid: correlation + allocation)
This archetype combines correlation review and allocation views into a single JSON.
Correlation summary:
- Compute Pearson correlations on the subset of indices named in the request.
highest_concentration: the pair with the highest positive correlation.
best_diversifier: the pair with the lowest (most negative) correlation.
- Pairs sorted alphabetically within each
pair list.
Target sleeve actions:
- Based on correlation findings and allocation views:
"trim" concentrated sleeves, "add" diversifying sleeves, "hedge" currency sleeves with negative signals.
Allocation views for each opportunity set:
- Include
prior_view (from /api/allocation/prior-views), signal_score (from /api/macro-signals), view (derived from score), change (vs prior), conviction (from score magnitude), rationale_code (from macro-signals).
- Round
signal_score to 3 decimal places.
Rebalance trigger:
"correlation_cap_breach" — when a correlation pair exceeds the high threshold.
"hy_cap_pressure" — when HY allocation is near/above cap.
"duration_drift" — when duration is outside the band.
"watchlist_concentration" — when watchlist exposure is material.
"committee_review" — when escalated for general review.
portfolio_risk_concentration_flag: true when any material concentration or threshold breach is identified.
next_step: "approve_with_monitoring" when there are actions but no hard constraint breach; "approve_rotation" for clean rotations; "defer_pending_risk_review" when material risks need further review; "reject_constraint_breach" for hard breaches.
Precision rules (by field type)
| Data type |
Precision |
Example |
notional_usd_m / quantity_usd_m |
1 decimal |
4.0, 12.0 |
total_market_value_usd_m |
Check template: 1 or 2 decimals |
68.0 or 78.00 |
hy_allocation_pct |
2 decimals |
13.24 |
weighted_modified_duration_years |
2 decimals |
3.28 |
weighted_yield_to_maturity_pct |
2 decimals |
5.80 → 5.8 (trailing zeros omitted per template; follow template's actual output format) |
hy_reduction_pct_points |
2 decimals |
25.64 |
post_trade_watchlist_exposure_usd_m |
1 decimal |
0.0 |
correlation |
3 decimals |
0.974, -0.825 |
signal_score |
3 decimals |
-0.373, 0.732 |
return_observations |
integer |
11 |
Critical: Match the precision declared in the template's properties for each field. If the template says precision: 2 for a field and the answer for train_001 shows 5.8 not 5.80, the format strips trailing zeros — match the number of significant decimal places shown in the template specification but don't pad trailing zeros unless the template explicitly formats them.
Ordering rules
- Trade lists: SELL before BUY, then alphabetical by
instrument_id within each action group. If the template says "sort ascending by instrument_id" without action grouping, sort globally.
- Index lists: Always alphabetical ascending by index ID (
IDX_...).
- Pair IDs: Both IDs within a pair sorted alphabetically.
- Allocation views: Follow the order in the request payload's
focus_opportunity_sets or the template's item_order.
- Sleeve actions: Alphabetically by
sleeve name, or by template's item_order.
- Diversification candidates: Alphabetically by index ID.
- Watchlist sell IDs: Alphabetically by instrument ID.
- Rationale codes in risk_overlay: Business priority order, highest/c strongest signal first.
Enumeration conventions
- Actions:
BUY, SELL, HOLD, NO_TRADE
- Sleeve actions:
trim, add, hold, hedge, monitor, rotate
- Views:
UW (underweight), N (neutral), OW (overweight)
- Change:
UP, DOWN, UNCHANGED
- Conviction:
LOW, MEDIUM, HIGH
- Rating buckets:
IG (investment grade: AAA through BBB-), HY (high yield: BB+ and below)
- Data precedence:
current_environment_over_stale_payload, local_payload_over_current_environment, no_conflict_found
- Sales target segments:
insurance_general_account, pension_liability_matching, multi_asset_income, private_bank_income, endowment_opportunistic
- Themes:
lng_export_tailwind, oil_oversupply_caution, midstream_stability, transition_bond_selectivity, avoid_watchlist_yield_trap
- Risk note codes:
hy_cap_pressure, watchlist_concentration, duration_preservation, carry_tradeoff, no_action
- Rebalance triggers:
correlation_cap_breach, hy_cap_pressure, duration_drift, watchlist_concentration, committee_review
- Next steps:
approve_rotation, defer_pending_risk_review, approve_with_monitoring, reject_constraint_breach
- Correlation concentration codes:
CHINA_ASIA_DEPENDENCE, GLOBAL_DEVELOPED_OVERLAP, NO_MATERIAL_CONCENTRATION
- Overlay codes:
DURATION_QUALITY_TILT, CREDIT_RISK_REDUCTION, EQUITY_BETA_EXTENSION, CURRENCY_DEFENSIVE_HEDGE, NO_OVERLAY
- Primary actions:
tilt_to_duration_quality, trim_credit_beta, add_cyclical_equity_beta, add_currency_hedge, hold_policy_weights
Common pitfalls
Stale payload data: The local payload may have stale marks, old quantities, or outdated worksheet snapshots. Always reconcile against the API's current portfolio and instrument records. The stale snapshot is intake context — not the source of truth.
Wrong policy: Each portfolio has a constraint_policy_id. Credit default (POL_CREDIT_DEFAULT) and credit risk reduction (POL_CREDIT_RISK_REDUCTION) have different target_hy_reduction_pct values (0.0 vs 4.0). Multi-asset policies (POL_MULTI_ASSET_DEFAULT, POL_MULTI_ASSET_RISK) stack sub-policies. Always check which policy applies.
Correlation window: The window is level_start_date through level_end_date inclusive at both ends. The number of return observations = (number of levels) - 1. A 12-date window yields 11 return observations. Use only the dates within the window — do not include earlier or later observations.
Simple returns, not log returns: The formula is (L_t / L_{t-1}) - 1, not ln(L_t / L_{t-1}).
HY classification: HY is determined by rating_bucket, not by the spread or yield. A BB bond is HY even if its spread is modest.
Weighted metrics are market-value-weighted: Each holding's contribution to portfolio duration or YTM is proportional to its quantity divided by total portfolio market value.
Change direction: Compare current view rank minus prior view rank. If prior was N (0) and current is OW (+1), that's UP. If prior was OW (+1) and current is N (0), that's DOWN.
Signal score vs conviction: Signal score determines the view AND conviction independently. View uses the signal score threshold (±0.35). Conviction uses the absolute signal score magnitude (≥0.7 = HIGH, ≥0.35 = MEDIUM, else LOW).
Post-trade MV for rotation: In a rotation (sell to fund buy), total MV does NOT change — you are swapping one set of holdings for another. In a new-money buy, total MV = current MV + new buy notional.
Watchlist avoidance is per issuer: The /api/issuers endpoint has the watchlist boolean. If any issuer is watchlisted, all its bonds are off-limits for BUY actions when watchlist avoidance is required.
Output template is authoritative: Always read the template JSON for exact key names, required fields, enum values, and ordering rules. Templates differ between tasks even within the same archetype.
Trailing zeros in JSON numbers: Python's json.dumps may output 5.8 for a float 5.80. If the template requires exactly 2 decimal places (precision: 2), you may need to format the number as 5.8 (minimal representation) or 5.80 (padded). Follow the convention shown in the template's answer examples — train outputs show minimal decimal representation (e.g., 5.8 not 5.80).
1---2name: fewshot-attempt-03-343description: Asteria Investment Office — Operational Skill4---5# Asteria Investment Office — Operational Skill67## Environment89All tasks use the shared Asteria API at `http://34.46.77.124:8010`. Treat the API as the **current book of record**. Local payload files (in `input/payloads/`) are intake context — they may contain **stale marks, outdated worksheets, or pre-refresh preferences**. When the API and a local payload disagree, the API wins.1011The current environment `as_of_date` is **2026-05-29**. Always set `as_of_date` to this value in outputs. Set `data_precedence` to `"current_environment_over_stale_payload"` whenever the local payload contains stale/older data that the API supersedes.1213### Key endpoints1415| Endpoint | Use |16|---|---|17| `GET /api/catalog` | Inventory of all IDs (bonds, indices, issuers, portfolios, policies, opportunity sets) |18| `GET /api/portfolios` | List all portfolios with metadata, constraint policy, and current MV |19| `GET /api/portfolios/<id>` | Full portfolio detail including holdings (instrument_id, quantity_usd_m, sleeve, asset_class, notes) |20| `GET /api/instruments/bonds` | Bond master: instrument_id, issuer_id, rating, rating_bucket (IG/HY), modified_duration_years, yield_to_maturity_pct, coupon_pct, maturity, sector, subsector, spread_bps, candidate flag, energy_linked flag, recommended_theme_tags |21| `GET /api/issuers` | Issuer master: issuer_id, issuer_name, sector, subsector, rating_bucket, credit_outlook, watchlist flag, research_tags |22| `GET /api/indices` | Index metadata: index_id, display_name, region, currency, frequency, level date range |23| `GET /api/index-levels` | All index monthly levels (12 points: 2025-05-30 through 2026-04-30) |24| `GET /api/index-levels/<id>` | Single index levels |25| `GET /api/policies` | All policy thresholds including allocation mapping, correlation defaults, credit defaults, credit risk reduction, multi-asset defaults |26| `GET /api/allocation/opportunity-sets` | Opportunity-set taxonomy (opportunity_set, asset_class, sub_asset_class, display_order) |27| `GET /api/allocation/prior-views` | Prior-quarter views (opportunity_set, quarter, previous_quarter, view, conviction) — key for computing `change` |28| `GET /api/macro-signals` | Q2/Q3 2026 signal scores per opportunity_set (score, rationale_code, drivers, quarter) |29| `GET /api/market/energy` | Energy commodity signals and pitch themes |3031---3233## Workflow: Always start by reading the API34351. **Fetch `/api/catalog`** to orient on available IDs.362. **Read the answer template** (`input/payloads/answer_template.json`) for the required output shape, key names, enum values, ordering rules, and numeric precision.373. **Read the payload** (desk request, review request, allocation request, risk memo, committee request) for the task's scope — which portfolio, which instruments/indices/opportunity-sets are in play, and any stale data warnings.384. **Fetch the portfolio** (`/api/portfolios/<id>`) for current holdings and constraint policy.395. **Fetch the relevant policy** (`/api/policies`) — the portfolio's `constraint_policy_id` tells you which thresholds apply.406. **Fetch supporting data** (bonds, issuers, indices, index-levels, macro-signals, prior-views, opportunity-sets) relevant to the task.4142---4344## Task archetypes and computation rules4546### A. Credit trade / rebalance (bond portfolios)4748**Selecting bonds:**49- Prefer bonds where `candidate: true`.50- For energy-linked mandates, prefer `energy_linked: true`.51- Avoid issuers where `watchlist: true` (from `/api/issuers`). If the task requires avoiding watchlist buys, never propose a BUY for a watchlisted issuer's bonds.52- If the task requires selling watchlist positions, identify holdings whose issuer has `watchlist: true`.53- For income/carry objectives, prefer higher `yield_to_maturity_pct` while respecting constraint policy.5455**Post-trade metrics — key formulas:**5657**total_market_value_usd_m** (precision 1 or 2, follow template):58```59= sum of all holding market values after proposed trades60= current portfolio MV + net new buy notional (for buy-only)61= current portfolio MV (for rotation/rebalance — MV is preserved unless funded)62```63For a rotation (sell to fund buy), total MV stays at the pre-trade level. For a buy package funded from new sleeve allocation, total MV = pre-trade MV + total buy notional.6465**HY allocation pct** (precision 2):66```67hy_allocation_pct = (sum of HY-bucket holding quantities) / total MV * 10068```69Where HY bucket = bonds whose `rating_bucket` is `"HY"` in the bond master.7071**weighted_modified_duration_years** (precision 2):72```73weighted_duration = sum(quantity_i / total_MV * duration_i) for all holdings74```7576**weighted_yield_to_maturity_pct** (precision 2):77```78weighted_YTM = sum(quantity_i / total_MV * YTM_i) for all holdings79```8081**hy_reduction_pct_points** (precision 2):82```83hy_reduction = pre_trade_hy_pct - post_trade_hy_pct84```8586**post_trade_watchlist_exposure_usd_m** (precision 1):87```88= sum of quantities of all holdings whose issuer has watchlist: true after trades89```9091**Constraint checks (booleans):**92- **hy_cap_pass**: `post_trade_hy_allocation_pct <= max_hy_allocation_pct` (from policy)93- **duration_band_pass**: `duration_band_years[0] <= post_trade_duration <= duration_band_years[1]`94- **selected_issuer_diversification_pass**: no single issuer among the BUY selections exceeds `issuer_concentration_limit_pct` of total MV (check if any issuer appears on more than one selected ticket)95- **selected_subsector_diversification_pass**: at least `subsector_min_count_for_diversified` distinct subsectors among BUY selections96- **watchlist_avoidance_pass**: no BUY ticket is for a watchlisted issuer97- **target_hy_reduction_met**: `hy_reduction_pct_points >= target_hy_reduction_pct` from policy98- **watchlist_exposure_cleared**: `post_trade_watchlist_exposure == 0`99100**Trade ordering in output:**101- Template specifies the rule. Common patterns: SELL before BUY, then alphabetical by `instrument_id` within each action group. Or: sort ascending by `instrument_id`.102103---104105### B. Equity correlation review106107**Computing Pearson correlation from index levels:**1081091. Filter index levels to the review window (from `level_start_date` through `level_end_date`). Both endpoints are included — the first date is the base for the first return.1102. Compute **monthly simple returns** for each index:111 ```112 r_t = (level_t / level_{t-1}) - 1113 ```114 where `t` and `t-1` are consecutive monthly observation dates.1153. The number of return observations = number of level dates minus 1.1164. Compute **Pearson correlation** between each pair of return series. Round to **3 decimal places**.1175. Include all requested indices in `index_set`, sorted alphabetically.118119**Extreme pairs:**120- **highest_positive**: the pair with the largest positive correlation (closest to +1.0). If ties, pick alphabetically.121- **lowest**: the pair with the most negative correlation (closest to -1.0). This is the *lowest* numeric value, not the lowest absolute value.122- Each pair's index IDs must be sorted alphabetically within the pair.123124**Concentration / dependence check:**125- Compare the highest correlation against `correlation_high_threshold` (default 0.8 from `POL_CORRELATION_DEFAULT`).126- `china_asia_dependence_flag`: true if the China-related pair exceeds the high threshold AND involves IDX_CHINA + an Asia/Emerging index.127- `high_threshold_breached`: true if any pair exceeds `correlation_high_threshold`.128- `primary_code`: `"CHINA_ASIA_DEPENDENCE"` if China concentration is the primary concern, `"GLOBAL_DEVELOPED_OVERLAP"` for developed-market overlaps, `"NO_MATERIAL_CONCENTRATION"` if no threshold breached.129130**Diversification candidates:**131- Indices that appear in the lowest-correlation pair (the best diversifier) OR that have pairwise correlations below `correlation_low_threshold` (default 0.2). Sorted alphabetically.132133**Sleeve actions:**134- For concentrated sleeves: `"trim"`.135- For diversification candidates: `"add"`.136- Sorted alphabetically by `sleeve` name (or by the order in the template).137138---139140### C. Allocation view refresh141142**Determining active view (`UW` / `N` / `OW`):**143144From `/api/policies` → `allocation_mapping.view_score_thresholds`:145- `score >= OW_min` (0.35) → `"OW"`146- `score <= UW_max` (-0.35) → `"UW"`147- Otherwise → `"N"`148149**Determining conviction (`LOW` / `MEDIUM` / `HIGH`):**150151From `/api/policies` → `allocation_mapping.conviction_thresholds`:152- `|score| >= HIGH_abs_min` (0.7) → `"HIGH"`153- `|score| >= MEDIUM_abs_min` (0.35) → `"MEDIUM"`154- Otherwise → `"LOW"`155156**Determining change (`UP` / `DOWN` / `UNCHANGED`):**157158Compare current view to prior-quarter view (from `/api/allocation/prior-views`):159- Map views to ranks: UW = -1, N = 0, OW = +1 (from `view_rank` in policy).160- If current rank > prior rank → `"UP"`161- If current rank < prior rank → `"DOWN"`162- If equal → `"UNCHANGED"`163164**Rationale code:**165- Use the `rationale_code` from `/api/macro-signals` for the given opportunity_set and target quarter.166- The signal score column is also the `signal_score` field (precision 3).167168**Prior view:**169- From `/api/allocation/prior-views`: look up the `view` for the opportunity_set where `previous_quarter` matches the task's prior quarter.170- **Important**: The prior-views endpoint returns entries where `quarter` is the target quarter and `previous_quarter` is the prior quarter. Match on both `opportunity_set` and `previous_quarter`.171172**Risk overlay:**173- Select the overlay whose `primary_action` best matches the dominant tilt across views:174 - `"DURATION_QUALITY_TILT"` / `"tilt_to_duration_quality"` — when OW duration/IG, UW HY175 - `"CREDIT_RISK_REDUCTION"` / `"trim_credit_beta"` — when reducing credit risk176 - `"EQUITY_BETA_EXTENSION"` / `"add_cyclical_equity_beta"` — when adding equity exposure177 - `"CURRENCY_DEFENSIVE_HEDGE"` / `"add_currency_hedge"` — when hedging currency178 - `"NO_OVERLAY"` / `"hold_policy_weights"` — when no significant tilt179- `rationale_codes`: List the rationale codes of the views that drive the overlay decision, in business priority order (strongest/clearest signal first).180181**Ordering:**182- `allocation_views` list: follow the order of `focus_opportunity_sets` from the request payload (not alphabetical).183- `rationale_codes` list: business priority order, highest priority first.184185---186187### D. Multi-asset committee (hybrid: correlation + allocation)188189This archetype combines correlation review and allocation views into a single JSON.190191**Correlation summary:**192- Compute Pearson correlations on the subset of indices named in the request.193- `highest_concentration`: the pair with the highest positive correlation.194- `best_diversifier`: the pair with the lowest (most negative) correlation.195- Pairs sorted alphabetically within each `pair` list.196197**Target sleeve actions:**198- Based on correlation findings and allocation views: `"trim"` concentrated sleeves, `"add"` diversifying sleeves, `"hedge"` currency sleeves with negative signals.199200**Allocation views for each opportunity set:**201- Include `prior_view` (from `/api/allocation/prior-views`), `signal_score` (from `/api/macro-signals`), `view` (derived from score), `change` (vs prior), `conviction` (from score magnitude), `rationale_code` (from macro-signals).202- Round `signal_score` to 3 decimal places.203204**Rebalance trigger:**205- `"correlation_cap_breach"` — when a correlation pair exceeds the high threshold.206- `"hy_cap_pressure"` — when HY allocation is near/above cap.207- `"duration_drift"` — when duration is outside the band.208- `"watchlist_concentration"` — when watchlist exposure is material.209- `"committee_review"` — when escalated for general review.210211**portfolio_risk_concentration_flag:** `true` when any material concentration or threshold breach is identified.212213**next_step:** `"approve_with_monitoring"` when there are actions but no hard constraint breach; `"approve_rotation"` for clean rotations; `"defer_pending_risk_review"` when material risks need further review; `"reject_constraint_breach"` for hard breaches.214215---216217## Precision rules (by field type)218219| Data type | Precision | Example |220|---|---|---|221| `notional_usd_m` / `quantity_usd_m` | 1 decimal | `4.0`, `12.0` |222| `total_market_value_usd_m` | Check template: 1 or 2 decimals | `68.0` or `78.00` |223| `hy_allocation_pct` | 2 decimals | `13.24` |224| `weighted_modified_duration_years` | 2 decimals | `3.28` |225| `weighted_yield_to_maturity_pct` | 2 decimals | `5.80` → `5.8` (trailing zeros omitted per template; follow template's actual output format) |226| `hy_reduction_pct_points` | 2 decimals | `25.64` |227| `post_trade_watchlist_exposure_usd_m` | 1 decimal | `0.0` |228| `correlation` | 3 decimals | `0.974`, `-0.825` |229| `signal_score` | 3 decimals | `-0.373`, `0.732` |230| `return_observations` | integer | `11` |231232**Critical**: Match the precision declared in the template's `properties` for each field. If the template says `precision: 2` for a field and the answer for train_001 shows `5.8` not `5.80`, the format strips trailing zeros — match the number of significant decimal places shown in the template specification but don't pad trailing zeros unless the template explicitly formats them.233234---235236## Ordering rules2372381. **Trade lists**: SELL before BUY, then alphabetical by `instrument_id` within each action group. If the template says "sort ascending by instrument_id" without action grouping, sort globally.2392. **Index lists**: Always alphabetical ascending by index ID (`IDX_...`).2403. **Pair IDs**: Both IDs within a pair sorted alphabetically.2414. **Allocation views**: Follow the order in the request payload's `focus_opportunity_sets` or the template's `item_order`.2425. **Sleeve actions**: Alphabetically by `sleeve` name, or by template's `item_order`.2436. **Diversification candidates**: Alphabetically by index ID.2447. **Watchlist sell IDs**: Alphabetically by instrument ID.2458. **Rationale codes in risk_overlay**: Business priority order, highest/c strongest signal first.246247---248249## Enumeration conventions250251- **Actions**: `BUY`, `SELL`, `HOLD`, `NO_TRADE`252- **Sleeve actions**: `trim`, `add`, `hold`, `hedge`, `monitor`, `rotate`253- **Views**: `UW` (underweight), `N` (neutral), `OW` (overweight)254- **Change**: `UP`, `DOWN`, `UNCHANGED`255- **Conviction**: `LOW`, `MEDIUM`, `HIGH`256- **Rating buckets**: `IG` (investment grade: AAA through BBB-), `HY` (high yield: BB+ and below)257- **Data precedence**: `current_environment_over_stale_payload`, `local_payload_over_current_environment`, `no_conflict_found`258- **Sales target segments**: `insurance_general_account`, `pension_liability_matching`, `multi_asset_income`, `private_bank_income`, `endowment_opportunistic`259- **Themes**: `lng_export_tailwind`, `oil_oversupply_caution`, `midstream_stability`, `transition_bond_selectivity`, `avoid_watchlist_yield_trap`260- **Risk note codes**: `hy_cap_pressure`, `watchlist_concentration`, `duration_preservation`, `carry_tradeoff`, `no_action`261- **Rebalance triggers**: `correlation_cap_breach`, `hy_cap_pressure`, `duration_drift`, `watchlist_concentration`, `committee_review`262- **Next steps**: `approve_rotation`, `defer_pending_risk_review`, `approve_with_monitoring`, `reject_constraint_breach`263- **Correlation concentration codes**: `CHINA_ASIA_DEPENDENCE`, `GLOBAL_DEVELOPED_OVERLAP`, `NO_MATERIAL_CONCENTRATION`264- **Overlay codes**: `DURATION_QUALITY_TILT`, `CREDIT_RISK_REDUCTION`, `EQUITY_BETA_EXTENSION`, `CURRENCY_DEFENSIVE_HEDGE`, `NO_OVERLAY`265- **Primary actions**: `tilt_to_duration_quality`, `trim_credit_beta`, `add_cyclical_equity_beta`, `add_currency_hedge`, `hold_policy_weights`266267---268269## Common pitfalls2702711. **Stale payload data**: The local payload may have stale marks, old quantities, or outdated worksheet snapshots. Always reconcile against the API's current portfolio and instrument records. The stale snapshot is intake context — not the source of truth.2722732. **Wrong policy**: Each portfolio has a `constraint_policy_id`. Credit default (`POL_CREDIT_DEFAULT`) and credit risk reduction (`POL_CREDIT_RISK_REDUCTION`) have different `target_hy_reduction_pct` values (0.0 vs 4.0). Multi-asset policies (`POL_MULTI_ASSET_DEFAULT`, `POL_MULTI_ASSET_RISK`) stack sub-policies. Always check which policy applies.2742753. **Correlation window**: The window is `level_start_date` through `level_end_date` inclusive at both ends. The number of return observations = (number of levels) - 1. A 12-date window yields 11 return observations. Use only the dates within the window — do not include earlier or later observations.2762774. **Simple returns, not log returns**: The formula is `(L_t / L_{t-1}) - 1`, not `ln(L_t / L_{t-1})`.2782795. **HY classification**: HY is determined by `rating_bucket`, not by the spread or yield. A BB bond is HY even if its spread is modest.2802816. **Weighted metrics are market-value-weighted**: Each holding's contribution to portfolio duration or YTM is proportional to its quantity divided by total portfolio market value.2822837. **Change direction**: Compare current view rank minus prior view rank. If prior was N (0) and current is OW (+1), that's UP. If prior was OW (+1) and current is N (0), that's DOWN.2842858. **Signal score vs conviction**: Signal score determines the view AND conviction independently. View uses the signal score threshold (±0.35). Conviction uses the absolute signal score magnitude (≥0.7 = HIGH, ≥0.35 = MEDIUM, else LOW).2862879. **Post-trade MV for rotation**: In a rotation (sell to fund buy), total MV does NOT change — you are swapping one set of holdings for another. In a new-money buy, total MV = current MV + new buy notional.28828910. **Watchlist avoidance is per issuer**: The `/api/issuers` endpoint has the `watchlist` boolean. If any issuer is watchlisted, all its bonds are off-limits for BUY actions when watchlist avoidance is required.29029111. **Output template is authoritative**: Always read the template JSON for exact key names, required fields, enum values, and ordering rules. Templates differ between tasks even within the same archetype.29229312. **Trailing zeros in JSON numbers**: Python's `json.dumps` may output `5.8` for a float `5.80`. If the template requires exactly 2 decimal places (precision: 2), you may need to format the number as `5.8` (minimal representation) or `5.80` (padded). Follow the convention shown in the template's answer examples — train outputs show minimal decimal representation (e.g., `5.8` not `5.80`).