PortfolioGuard
$0.15/callPortfolio risk scored straight from holdings.
POST /api/agent-services/portfolioguard/scoreWhat it does
Deterministic portfolio risk + quality scorer. Computes riskScore, riskLevel, volatility, sharpe, maxDrawdown, concentrationHHI, diversification, effectiveHoldings plus per-rule findings with fixes and sector/position breakdown. Pure math only from caller holdings and returns. No external data.
- Volatility, Sharpe, max drawdown
- Concentration (HHI) & diversification
- Per-rule findings with concrete fixes
Example request
POST /api/agent-services/portfolioguard/score
{
"holdings": [
{
"symbol": "AAPL",
"weight": 0.25,
"sector": "Technology"
},
{
"symbol": "BND",
"weight": 0.35,
"sector": "Bonds"
},
{
"symbol": "GLD",
"weight": 0.15,
"sector": "Commodity"
},
{
"symbol": "VTI",
"weight": 0.25,
"sector": "Equity"
}
],
"periodReturns": [
0.01,
-0.004,
0.007,
0.002,
-0.01
],
"riskFreeRate": 0
}Example response (HTTP 200)
Deterministic — the same inputs always return the same audited output.
{
"riskScore": 64,
"riskLevel": "medium",
"metrics": {
"volatility": 0.0071,
"sharpe": 0.42,
"maxDrawdown": 0.014,
"concentrationHHI": 0.2375,
"diversificationScore": 76,
"effectiveHoldings": 4.21
},
"findings": [
{
"rule": "weights-sum-sanity",
"severity": "info",
"why": "Weights should sum to approximately 1.0.",
"evidence": "sum=1",
"fix": null
},
{
"rule": "single-position-concentration",
"severity": "info",
"why": "No position exceeds 25%.",
"evidence": "maxWeight=0.35",
"fix": null
}
],
"breakdown": {
"bySector": {
"Technology": {
"weight": 0.25,
"count": 1
},
"Bonds": {
"weight": 0.35,
"count": 1
}
},
"topPositions": [
{
"symbol": "BND",
"weight": 0.35
},
{
"symbol": "AAPL",
"weight": 0.25
}
]
}
}Input schema
Top-level request fields. Nested shapes are shown in the example above and the OpenAPI spec.
| Field | Type | Required | Description |
|---|---|---|---|
| holdings | array | Yes | List of positions with symbol, weight (0-1), optional returns[], sector, assetClass. |
| periodReturns | array | — | Optional time series of portfolio or market period returns (preferred for volatility/sharpe/MDD). |
| riskFreeRate | number | — | Optional risk-free rate for Sharpe (default 0). |
How to call it over x402
- 1. Send the request. The first unpaid call returns HTTP 402 with an x402 payment challenge — $0.15, USDC on Base, and the recipient.
- 2. Pay per call. Your x402 client signs the USDC payment and retries automatically — no API key, no account, no subscription. New to x402?
- 3. Read the result. HTTP 200 returns the computed values plus evidence-backed findings.
With the x402 fetch client (Node / TypeScript)
import { wrapFetchWithPayment } from "@x402/fetch";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.AGENT_WALLET_KEY);
const pay = wrapFetchWithPayment(fetch, account); // USDC on Base
const res = await pay("https://hermesplant.com/api/agent-services/portfolioguard/score", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
"holdings": [
{
"symbol": "AAPL",
"weight": 0.25,
"sector": "Technology"
},
{
"symbol": "BND",
"weight": 0.35,
"sector": "Bonds"
},
{
"symbol": "GLD",
"weight": 0.15,
"sector": "Commodity"
},
{
"symbol": "VTI",
"weight": 0.25,
"sector": "Equity"
}
],
"periodReturns": [
0.01,
-0.004,
0.007,
0.002,
-0.01
],
"riskFreeRate": 0
}),
});
const result = await res.json();Inspect the 402 with curl
curl -i -X POST https://hermesplant.com/api/agent-services/portfolioguard/score \
-H "content-type: application/json" \
-d '{"holdings":[{"symbol":"AAPL","weight":0.25,"sector":"Technology"},{"symbol":"BND","weight":0.35,"sector":"Bonds"},{"symbol":"GLD","weight":0.15,"sector":"Commodity"},{"symbol":"VTI","weight":0.25,"sector":"Equity"}],"periodReturns":[0.01,-0.004,0.007,0.002,-0.01],"riskFreeRate":0}'
# → HTTP/1.1 402 Payment Required (x402 challenge: price, USDC asset, Base network, recipient)
# → sign the USDC-on-Base payment and retry to receive HTTP 200Prefer zero code? This endpoint is also exposed as a tool on the Hermes Plant MCP server, so an MCP-capable agent can call it with its own x402 wallet.
Other agent services
NPV, IRR, XIRR & DCF valuation in a single call.
LP/GP distribution waterfalls, solved exactly.
Black-Scholes option pricing with the full Greeks.
Yield, duration, convexity & loan amortization.
Wallet AML & compliance risk screening.
Full deal underwriting — DCF, returns, sensitivity & waterfall in one call.
Score an MCP server before your agent installs it.
Catch destructive agent commands before they run.
Route risky agent actions to human approval.
Deterministic email & contact data validation.
Need a calculator that isn’t here yet? contact@hermesplant.com