Communitygithub.com

vishnup22/FinSight-AI

>- Portfolio allocation analysis across 2–10 US and/or Indian stocks using FinSight-AI. Computes equal-weight vs max-Sharpe optimal weights, correlation matrix, and portfolio-level risk metrics. Use when the user provides a list of tickers and asks for allocation, diversification, or portfolio optimisation. Does not produce per-stock narratives — use /analyse for that.

FinSight-AI 是什么?

FinSight-AI is a Claude Code agent skill that >- Portfolio allocation analysis across 2–10 US and/or Indian stocks using FinSight-AI. Computes equal-weight vs max-Sharpe optimal weights, correlation matrix, and portfolio-level risk metrics. Use when the user provides a list of tickers and asks for allocation, diversification, or portfolio optimisation. Does not produce per-stock narratives — use /analyse for that.

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/vishnup22/FinSight-AI/tree/HEAD/skills/portfolio

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Portfolio — equal-weight vs max-Sharpe optimisation

See reference.md for ticker formats.


Prerequisites

GET http://localhost:8000/health

Must return {"status": "ok"}. If not: tell user to run python backend/run.py.


Step 1 — Parse tickers

  • Extract all ticker symbols from the message. Uppercase, strip whitespace.
  • Minimum 2, maximum 10. Duplicates are rejected by the API — deduplicate silently and note it.
  • If fewer than 2 tickers are provided, ask for more before proceeding.

Step 2 — Submit portfolio job

POST http://localhost:8000/api/v1/portfolio
Content-Type: application/json

{"tickers": ["T1", "T2", "..."], "query": "Optimise allocation for maximum risk-adjusted return."}

Response: {"job_id": "<uuid>", "status": "pending", "message": "..."}

Tell user:

Portfolio job submitted for {n} tickers. Fetching 1-year price history and optimising… typically 15–30 s.


Step 3 — Poll status

GET http://localhost:8000/api/v1/status/{job_id}

Every 5 s until completed or failed.


Step 4 — Fetch result

GET http://localhost:8000/api/v1/result/{job_id}

Error case

If the result contains a top-level error key (e.g. "At least two tickers with overlapping price history are required"), explain the issue in plain language and stop:

Portfolio optimisation requires at least two tickers with overlapping trading history over the past year. Check that all tickers are valid and have sufficient history.

Field map

FieldPathNotes
Tickers usedtickersMay differ from input if some had no data
Price rowsprice_rowsNumber of overlapping trading days
Equal weightsequal_weight.weights{ticker: decimal} — multiply by 100 for %
Equal returnequal_weight.annual_return_pctAlready in %
Equal volatilityequal_weight.annual_volatility_pctAlready in %
Equal Sharpeequal_weight.sharpe_ratioAnnualised, risk-free = 5%
Equal VaRequal_weight.var_95_daily_pctAlready in %, daily
Optimal weightsoptimal.weights{ticker: decimal} — multiply by 100 for %
Optimal returnoptimal.annual_return_pctAlready in %
Optimal volatilityoptimal.annual_volatility_pctAlready in %
Optimal Sharpeoptimal.sharpe_ratioAnnualised, risk-free = 5%
Optimal VaRoptimal.var_95_daily_pctAlready in %, daily
Optimizer succeededoptimal.optimizer_successbool
Optimizer messageoptimal.optimizer_messageOnly relevant if success = false
Correlation matrixcorrelation_matrixNested dict {ticker: {ticker: corr}}
Portfolio VaRportfolio_var_95_daily_pctOptimal portfolio daily VaR, already in %

Step 5 — Interpret and present

Weights

Convert decimal weights to percentages (weight * 100, 1 decimal place). If any weight is 0.0% in the optimal portfolio, note that the optimiser excluded that asset (insufficient return or high correlation with others).

Sharpe ratio

  • < 0: portfolio returns less than the risk-free rate (5%); reconsider composition.
  • 0–1: poor risk-adjusted return.
  • 1–2: good.
  • 2: excellent.

Compare equal-weight Sharpe vs optimal Sharpe. If optimal Sharpe is higher, the concentrated weights are justified. If similar (difference < 0.1), the equal-weight portfolio is nearly as efficient and simpler to rebalance.

Correlation matrix

Interpret the pairwise correlations:

  • 0.80: highly correlated — these two assets move almost together; holding both adds little diversification.

  • 0.50–0.80: moderate correlation — some co-movement, partial diversification benefit.
  • < 0.30: low correlation — good diversification pair.
  • Near 0 or negative: strong diversifier.

Identify the highest-correlated pair and the lowest-correlated pair and call them out in the narrative.

VaR

Daily VaR at 95% confidence: on the worst 1-in-20 trading days, the portfolio has historically lost approximately {portfolio_var_95_daily_pct}%. Annualise a rough estimate only if helpful: multiply daily VaR by √252 ≈ 15.9 to approximate annual VaR (note this is a rough approximation).

Optimizer failure

If optimal.optimizer_success = false, say:

The optimiser did not converge ({optimal.optimizer_message}). Optimal weights fell back to equal weights — treat the "optimal" column as equal weight.

Indian stocks in the portfolio

If any ticker ends in .NS or .BO, note that INR-denominated assets introduce FX risk for USD-based investors. The correlation matrix reflects local-currency returns and does not capture INR/USD volatility.


Step 6 — Recommendation

After presenting the data, give a 2–3 sentence recommendation:

  • State whether to use equal-weight or optimal weights and why (Sharpe comparison).
  • Name the top 1–2 holdings in the optimal portfolio and what drives their weight.
  • Note any diversification concern (highly correlated pairs) or FX consideration.

Output

# Portfolio Analysis — {comma-separated tickers}

Price history: {price_rows} overlapping trading days (≈ {price_rows/252:.1f} years)

---

## Allocation Comparison

| Ticker   | Equal weight | Optimal weight |
|----------|-------------|----------------|
| {ticker} | {ew*100:.1f}% | {ow*100:.1f}% |
| …        | …            | …              |

---

## Portfolio Metrics

| Metric                   | Equal weight | Optimal (max Sharpe) |
|--------------------------|-------------|----------------------|
| Expected annual return   | {eq_ret}%   | {opt_ret}%           |
| Annual volatility        | {eq_vol}%   | {opt_vol}%           |
| Sharpe ratio             | {eq_sh}     | {opt_sh}             |
| VaR (95%, 1-day)         | {eq_var}%   | {opt_var}%           |

{If optimizer_success = false:
> ⚠ Optimiser did not converge ({optimizer_message}) — optimal weights equal equal weights.}

---

## Correlation Matrix

| Ticker | {t1} | {t2} | … |
|--------|------|------|---|
| {t1}   | 1.00 | …    | … |
| …      | …    | …    | … |

**Most correlated pair:** {t_a} / {t_b} at {corr:.2f} — limited diversification benefit.
**Least correlated pair:** {t_c} / {t_d} at {corr:.2f} — strongest diversification benefit.

---

## Recommendation

{2–3 sentences: equal vs optimal choice, key holdings rationale, any diversification or FX caveat.}

{If any .NS/.BO tickers:
> ⚠ Indian stocks ({list}) are INR-denominated. The correlation matrix reflects local-currency returns and does not capture INR/USD exchange rate risk for USD-based investors.}

Error recovery

SituationAction
Top-level error in resultExplain the issue; ask user to verify tickers and try again
A ticker dropped from tickers listNote it had insufficient or non-overlapping price history
optimizer_success = falseExplain fallback to equal weights; still show the metrics
Single .NS/.BO tickerNote FX risk; show it in the correlation matrix as usual

相关技能