feat: add quant layer, portfolio-review, and strategy-backtest skills
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
fundamental-analysis: added statistical risk layer - normality test (Jarque-Bera) — validates Sharpe/VaR reliability - unit root test (ADF) — validates technical analysis applicability - rolling skew/kurtosis — tail risk monitoring - interpretation rules for crash risk detection portfolio-review (NEW): portfolio health check and similarity search - HRP optimization, correlation matrix, risk parity weights - t-SNE clustering for hidden correlations - stock similarity search for diversification - rule-engine BUY_MORE/HOLD/SELL per holding strategy-backtest (NEW): historical strategy validation - SMA crossover, RSI mean-reversion, buy-and-hold, momentum - comparison framework with Sharpe, max DD, win rate - validation workflow for trade-analyze recommendations Coverage: 67% → 79% of API endpoints (104/131)
This commit is contained in:
@@ -38,6 +38,18 @@ curl -sk "$BASE/api/v1/stock/{TICKER}/sortino?days=365"
|
||||
# Omega ratio (full distribution gain/loss)
|
||||
curl -sk "$BASE/api/v1/stock/{TICKER}/omega?days=365"
|
||||
|
||||
# Normality test (are returns normally distributed? If not, Sharpe/VaR underestimates risk)
|
||||
curl -sk "$BASE/api/v1/stock/{TICKER}/normality?days=365"
|
||||
|
||||
# Unit root test (does the price have a trend, or is it random walk?)
|
||||
curl -sk "$BASE/api/v1/stock/{TICKER}/unitroot?days=365"
|
||||
|
||||
# Rolling skewness (negative skew = increasing downside tail risk)
|
||||
curl -sk "$BASE/api/v1/stock/{TICKER}/rolling/skew?days=365&window=30"
|
||||
|
||||
# Rolling kurtosis (high = fat tails, extreme moves more likely)
|
||||
curl -sk "$BASE/api/v1/stock/{TICKER}/rolling/kurtosis?days=365&window=30"
|
||||
|
||||
# Share statistics (float, shares outstanding, short % of float)
|
||||
curl -sk "$BASE/api/v1/stock/{TICKER}/share-statistics"
|
||||
|
||||
@@ -81,10 +93,17 @@ curl -sk "$BASE/api/v1/calendar/earnings?start_date=$(date +%Y-%m-%d)&end_date=$
|
||||
- Beta: {value} — [defensive <0.8 / market ~1.0 / aggressive >1.2]
|
||||
- CAPM alpha: {%} — [outperforming / underperforming vs market]
|
||||
- Sharpe (1Y): {value} — [poor <0.5 / good >1.0 / excellent >2.0]
|
||||
- Sortino (1Y): {value} — [context vs Sharpe]
|
||||
- Sortino (1Y): {value} — Sortino > Sharpe suggests positive skew (good)
|
||||
- Max drawdown (1Y): {%}
|
||||
- Omega ratio: {value}
|
||||
|
||||
### Statistical Risk (Quant Layer)
|
||||
- Normality: {Jarque-Bera p-value} — [normal (p>0.05): Sharpe/VaR reliable / non-normal (p<0.05): use Sortino/Omega instead]
|
||||
- Unit root (ADF): {p-value} — [trend present (p<0.05): technicals valid / random walk (p>0.05): technicals unreliable]
|
||||
- Rolling skew (30d): {latest value} — [negative = growing downside tail / positive = upside tail / near 0 = symmetric]
|
||||
- Rolling kurtosis (30d): {latest value} — [>3 = fat tails, extreme moves likely / <3 = thin tails, well-behaved]
|
||||
- ⚠️ If non-normal + negative skew + high kurtosis = **elevated crash risk**, reduce position size
|
||||
|
||||
### Institutional & Ownership
|
||||
- Float: {shares} ({% of total})
|
||||
- Short % of float: {%} — [low <5% / moderate / high >15%]
|
||||
@@ -113,4 +132,7 @@ curl -sk "$BASE/api/v1/calendar/earnings?start_date=$(date +%Y-%m-%d)&end_date=$
|
||||
- Flag **earnings within 7 days** as a major catalyst/risk
|
||||
- Sortino > Sharpe for stocks with asymmetric return profiles
|
||||
- High short interest + upcoming catalyst = potential squeeze
|
||||
- Keep under 500 words
|
||||
- If normality test fails: Sharpe/VaR are unreliable, emphasize Sortino and Omega instead
|
||||
- If unit root test fails (random walk): de-emphasize technical signals in your assessment
|
||||
- Negative rolling skew + high kurtosis = crash risk flag — recommend smaller position
|
||||
- Keep under 600 words
|
||||
|
||||
140
openclaw-skills/portfolio-review/SKILL.md
Normal file
140
openclaw-skills/portfolio-review/SKILL.md
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
name: portfolio-review
|
||||
description: "Portfolio health check — optimization, correlation, risk parity, clustering, similarity analysis. Use when user asks about portfolio allocation, diversification, rebalancing, or finding similar stocks."
|
||||
user-invocable: true
|
||||
metadata: { "openclaw": { "emoji": "💼", "requires": { "bins": ["curl"] } } }
|
||||
---
|
||||
|
||||
# Portfolio Review
|
||||
|
||||
Professional portfolio analysis. Think like a portfolio manager at a wealth management firm.
|
||||
|
||||
**Trigger**: User mentions portfolio, allocation, diversification, rebalancing, "how should I weight", or "find stocks like X".
|
||||
|
||||
## Mode A: Portfolio Health Check
|
||||
|
||||
When user provides holdings or references MEMORY.md portfolio:
|
||||
|
||||
```bash
|
||||
BASE=https://invest-api.k8s.home
|
||||
|
||||
# Rule-engine analysis (BUY_MORE/HOLD/SELL per holding with confidence)
|
||||
curl -sk -X POST "$BASE/api/v1/portfolio/analyze" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"holdings": [{"symbol": "AAPL", "shares": 100, "buy_in_price": 150.0}, ...]}'
|
||||
|
||||
# HRP optimal weights (Hierarchical Risk Parity)
|
||||
curl -sk -X POST "$BASE/api/v1/portfolio/optimize" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbols": ["AAPL", "MSFT", "GOOGL", ...], "days": 365}'
|
||||
|
||||
# Correlation matrix (identify hidden correlations)
|
||||
curl -sk -X POST "$BASE/api/v1/portfolio/correlation" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbols": ["AAPL", "MSFT", "GOOGL", ...], "days": 365}'
|
||||
|
||||
# Risk parity weights (equal risk contribution)
|
||||
curl -sk -X POST "$BASE/api/v1/portfolio/risk-parity" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbols": ["AAPL", "MSFT", "GOOGL", ...], "days": 365}'
|
||||
|
||||
# Cluster analysis (which stocks behave similarly)
|
||||
curl -sk -X POST "$BASE/api/v1/portfolio/cluster" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbols": ["AAPL", "MSFT", "GOOGL", ...], "days": 180}'
|
||||
|
||||
# Per-stock risk metrics
|
||||
for SYMBOL in AAPL MSFT GOOGL; do
|
||||
curl -sk "$BASE/api/v1/stock/$SYMBOL/performance?days=365"
|
||||
done
|
||||
```
|
||||
|
||||
### Report Structure
|
||||
|
||||
```
|
||||
## Portfolio Review — {date}
|
||||
|
||||
### Holdings Summary
|
||||
| Symbol | Shares | Cost | Current | P&L | P&L% | Signal |
|
||||
|--------|--------|------|---------|-----|-------|--------|
|
||||
| {sym} | {n} | ${cost} | ${current} | ${pnl} | {%} | {BUY_MORE/HOLD/SELL} |
|
||||
|
||||
### Total Portfolio
|
||||
- Total value: ${sum}
|
||||
- Total P&L: ${sum} ({%})
|
||||
- Positions: {count}
|
||||
|
||||
### Diversification Analysis
|
||||
- Correlation highlights:
|
||||
- Highest pair: {A} ↔ {B} = {r} — ⚠️ if >0.8 = redundant exposure
|
||||
- Lowest pair: {A} ↔ {B} = {r} — ✅ good diversification
|
||||
- Clusters found: {n} groups
|
||||
- Cluster 1: [{symbols}] — {interpretation, e.g. "tech megacap"}
|
||||
- Cluster 2: [{symbols}] — {interpretation}
|
||||
- Diversification score: [well-diversified / concentrated / sector-heavy]
|
||||
|
||||
### Optimal Allocation
|
||||
| Symbol | Current Weight | HRP Weight | Risk Parity | Action |
|
||||
|--------|---------------|------------|-------------|--------|
|
||||
| {sym} | {%} | {%} | {%} | [increase/decrease/hold] |
|
||||
|
||||
### Risk Metrics per Holding
|
||||
| Symbol | Sharpe | Volatility | Max DD | Beta |
|
||||
|--------|--------|-----------|--------|------|
|
||||
| {sym} | {val} | {%} | {%} | {val} |
|
||||
|
||||
### Recommendations
|
||||
1. {Top priority action with reasoning}
|
||||
2. {Second action}
|
||||
3. {Third action}
|
||||
|
||||
### ⚠️ Alerts
|
||||
- {Any BUY_MORE or SELL signals from rule engine}
|
||||
- {Highly correlated pairs that should be reduced}
|
||||
- {Overweight positions vs optimal}
|
||||
```
|
||||
|
||||
## Mode B: Find Similar/Different Stocks
|
||||
|
||||
When user asks "find stocks like X" or "what's similar to X":
|
||||
|
||||
```bash
|
||||
# Find most similar stocks
|
||||
curl -sk -X POST "$BASE/api/v1/portfolio/similar" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbol": "{TICKER}", "universe": ["AAPL","MSFT","GOOGL","AMZN","META","NVDA","TSLA","JPM","V","WMT","JNJ","PG","XOM","CVX","HD"], "days": 180, "top_n": 5}'
|
||||
|
||||
# Cluster the target with potential alternatives
|
||||
curl -sk -X POST "$BASE/api/v1/portfolio/cluster" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbols": ["{TICKER}","AAPL","MSFT","GOOGL","AMZN","META","NVDA","TSLA","JPM","V","WMT","JNJ"], "days": 180}'
|
||||
```
|
||||
|
||||
### Report Structure
|
||||
|
||||
```
|
||||
## Stocks Similar to {TICKER}
|
||||
|
||||
### Most Similar (by return correlation)
|
||||
| Rank | Symbol | Correlation | Why Similar |
|
||||
|------|--------|-------------|-------------|
|
||||
| 1 | {sym} | {r} | {interpretation} |
|
||||
|
||||
### Most Different (diversification candidates)
|
||||
| Rank | Symbol | Correlation | Why Different |
|
||||
|------|--------|-------------|---------------|
|
||||
| 1 | {sym} | {r} | {interpretation} |
|
||||
|
||||
### Recommendation
|
||||
- To add exposure like {TICKER}: consider {top similar}
|
||||
- To hedge {TICKER}: consider {most different}
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
- Always read MEMORY.md for existing holdings before analysis
|
||||
- Correlation > 0.8 = redundant — flag for reduction
|
||||
- Correlation < 0.2 = good diversification pair
|
||||
- HRP is generally better than equal-weight for risk-adjusted returns
|
||||
- Risk parity = each position contributes equal risk (good for conservative portfolios)
|
||||
- Keep under 500 words
|
||||
130
openclaw-skills/strategy-backtest/SKILL.md
Normal file
130
openclaw-skills/strategy-backtest/SKILL.md
Normal file
@@ -0,0 +1,130 @@
|
||||
---
|
||||
name: strategy-backtest
|
||||
description: "Strategy backtesting — test SMA crossover, RSI, buy-and-hold, momentum strategies against historical data. Use when user wants to validate a trading idea or compare strategies."
|
||||
user-invocable: true
|
||||
metadata: { "openclaw": { "emoji": "🧪", "requires": { "bins": ["curl"] } } }
|
||||
---
|
||||
|
||||
# Strategy Backtest
|
||||
|
||||
Professional backtesting for strategy validation. Think like a quant researcher — data over intuition.
|
||||
|
||||
**Trigger**: User says "backtest", "test this strategy", "would this have worked", "compare strategies", or wants to validate a trade-analyze recommendation.
|
||||
|
||||
## Available Strategies
|
||||
|
||||
### 1. SMA Crossover (trend-following)
|
||||
|
||||
When short SMA crosses above long SMA → buy. Crosses below → sell.
|
||||
|
||||
```bash
|
||||
BASE=https://invest-api.k8s.home
|
||||
|
||||
curl -sk -X POST "$BASE/api/v1/backtest/sma-crossover" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbol": "{TICKER}", "short_window": 20, "long_window": 50, "days": 365, "initial_capital": 10000}'
|
||||
```
|
||||
|
||||
Best for: trending markets, medium-term holds.
|
||||
Weak in: sideways/choppy markets (many false signals).
|
||||
|
||||
### 2. RSI Mean Reversion
|
||||
|
||||
Buy when RSI < oversold threshold, sell when RSI > overbought threshold.
|
||||
|
||||
```bash
|
||||
curl -sk -X POST "$BASE/api/v1/backtest/rsi" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbol": "{TICKER}", "period": 14, "oversold": 30, "overbought": 70, "days": 365, "initial_capital": 10000}'
|
||||
```
|
||||
|
||||
Best for: range-bound stocks, mean-reverting behavior.
|
||||
Weak in: strong trends (catches falling knives).
|
||||
|
||||
### 3. Buy and Hold (benchmark)
|
||||
|
||||
Always run this as the baseline comparison.
|
||||
|
||||
```bash
|
||||
curl -sk -X POST "$BASE/api/v1/backtest/buy-and-hold" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbol": "{TICKER}", "days": 365, "initial_capital": 10000}'
|
||||
```
|
||||
|
||||
### 4. Momentum (multi-stock rotation)
|
||||
|
||||
Rank stocks by recent performance, hold top N, rebalance periodically.
|
||||
|
||||
```bash
|
||||
curl -sk -X POST "$BASE/api/v1/backtest/momentum" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"symbols": ["AAPL","MSFT","GOOGL","AMZN","NVDA","META","TSLA","JPM","V","WMT"], "lookback": 60, "top_n": 3, "rebalance_days": 30, "days": 365, "initial_capital": 10000}'
|
||||
```
|
||||
|
||||
Best for: diversified portfolios, capturing sector rotation.
|
||||
|
||||
## Standard Workflow
|
||||
|
||||
**Always run all 3 single-stock strategies + buy-and-hold for comparison:**
|
||||
|
||||
```bash
|
||||
# Run all 4 in one go
|
||||
curl -sk -X POST "$BASE/api/v1/backtest/buy-and-hold" -H "Content-Type: application/json" -d '{"symbol":"{TICKER}","days":365,"initial_capital":10000}'
|
||||
curl -sk -X POST "$BASE/api/v1/backtest/sma-crossover" -H "Content-Type: application/json" -d '{"symbol":"{TICKER}","short_window":20,"long_window":50,"days":365,"initial_capital":10000}'
|
||||
curl -sk -X POST "$BASE/api/v1/backtest/rsi" -H "Content-Type: application/json" -d '{"symbol":"{TICKER}","period":14,"oversold":30,"overbought":70,"days":365,"initial_capital":10000}'
|
||||
```
|
||||
|
||||
## Report Structure
|
||||
|
||||
```
|
||||
## {TICKER} Strategy Backtest — {date}
|
||||
### Period: {start_date} to {end_date} ({days} days)
|
||||
### Initial Capital: $10,000
|
||||
|
||||
### Strategy Comparison
|
||||
| Strategy | Return | Sharpe | Max DD | Win Rate | Trades |
|
||||
|----------|--------|--------|--------|----------|--------|
|
||||
| Buy & Hold | {%} | {val} | {%} | N/A | 1 |
|
||||
| SMA 20/50 | {%} | {val} | {%} | {%} | {n} |
|
||||
| RSI 14/30/70 | {%} | {val} | {%} | {%} | {n} |
|
||||
|
||||
### Winner: {strategy name}
|
||||
- Outperformed buy-and-hold by: {%}
|
||||
- Key advantage: {why it worked for this stock}
|
||||
|
||||
### Equity Curve Summary
|
||||
- Buy & Hold final: ${value}
|
||||
- Best strategy final: ${value}
|
||||
- Worst drawdown period: {date range}
|
||||
|
||||
### Strategy Suitability for {TICKER}
|
||||
- Stock behavior: [trending / mean-reverting / choppy]
|
||||
- Best fit: {strategy} because {reason}
|
||||
- Avoid: {strategy} because {reason}
|
||||
|
||||
### ⚠️ Backtest Caveats
|
||||
- No transaction costs or slippage included
|
||||
- Past performance ≠ future results
|
||||
- Optimized parameters may overfit
|
||||
- Consider out-of-sample testing (different time period)
|
||||
```
|
||||
|
||||
## Validation Workflow (after /trade-analyze)
|
||||
|
||||
When used to validate a trade-analyze recommendation:
|
||||
|
||||
1. Run buy-and-hold for baseline
|
||||
2. If trade-analyze recommended BUY based on technical signals:
|
||||
- Run SMA crossover to see if trend-following would have worked
|
||||
- Run RSI to see if mean-reversion entries would have worked
|
||||
3. Compare Sharpe ratios and max drawdowns
|
||||
4. Conclusion: "The data {supports / does not support} the trade-analyze recommendation because {reason}"
|
||||
|
||||
## Rules
|
||||
|
||||
- **Always include buy-and-hold as benchmark** — any strategy must beat it
|
||||
- Sharpe > 1.0 = good risk-adjusted returns
|
||||
- Max drawdown > 20% = strategy needs tighter risk management
|
||||
- Win rate < 40% can still be profitable if average win >> average loss
|
||||
- If all strategies underperform buy-and-hold → the stock rewards patience, not trading
|
||||
- Keep under 500 words
|
||||
Reference in New Issue
Block a user