@quantoracle/agentkit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/dist/index.cjs +453 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +259 -0
- package/dist/index.d.ts +259 -0
- package/dist/index.js +442 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# QuantOracle for Coinbase AgentKit
|
|
2
|
+
|
|
3
|
+
Deterministic quant finance math for autonomous agents built with [Coinbase AgentKit](https://github.com/coinbase/agentkit).
|
|
4
|
+
|
|
5
|
+
> 📖 **Read the full integration comparison:** [AgentKit vs LangChain vs Direct HTTP — picking the right integration for paid agent APIs](https://dev.to/quantoracle/agentkit-vs-langchain-vs-direct-http-picking-the-right-integration-for-paid-agent-apis-2582) (dev.to, May 2026)
|
|
6
|
+
|
|
7
|
+
> **Why this exists:** AI agents trying to compute Black-Scholes prices, Kelly fractions, or Monte Carlo simulations in-context drift. The numbers are wrong, the Greeks are hallucinated, and the agent can't tell. QuantOracle is grounded math: same inputs, same outputs, every time. Free tier covers calculator endpoints; paid composites (full risk audit, hedge recommendations) settle automatically via your AgentKit wallet using x402 micropayments on Base or Solana.
|
|
8
|
+
|
|
9
|
+
## What this provides
|
|
10
|
+
|
|
11
|
+
5 high-leverage actions covering the financial decisions an autonomous trading or finance agent typically faces:
|
|
12
|
+
|
|
13
|
+
| Action | What it does | Cost |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `price_option` | Black-Scholes pricing with full Greeks (delta, gamma, vega, theta, rho) | Free |
|
|
16
|
+
| `calculate_kelly` | Kelly Criterion optimal sizing (full / half / quarter Kelly) | Free |
|
|
17
|
+
| `simulate_portfolio` | Monte Carlo simulation with contributions, withdrawals, probability of ruin | Free |
|
|
18
|
+
| `assess_portfolio_risk` | Composite audit: Sharpe, Sortino, Calmar, max DD, VaR, CVaR, Kelly, Hurst | $0.04 USDC via x402 |
|
|
19
|
+
| `recommend_hedge` | Ranked hedge structures (collar, protective put, partial put, inverse) for any position | $0.04 USDC via x402 |
|
|
20
|
+
|
|
21
|
+
The full QuantOracle API has 73 endpoints; this provider exposes a curated subset. For the long tail (exotic options, FX models, technical indicators, etc.), agents can call the raw API at `https://api.quantoracle.dev/v1/*` directly.
|
|
22
|
+
|
|
23
|
+
## Free tier
|
|
24
|
+
|
|
25
|
+
- **1,000 calls per IP per day**, no signup, no API key
|
|
26
|
+
- Covers `price_option`, `calculate_kelly`, `simulate_portfolio` for almost any agent
|
|
27
|
+
- Resets daily at 00:00 UTC
|
|
28
|
+
|
|
29
|
+
## Paid endpoints (x402)
|
|
30
|
+
|
|
31
|
+
`assess_portfolio_risk` and `recommend_hedge` are composite endpoints that wrap 5-15 calculator calls into a single response. They cost $0.04 USDC each, settled on-chain via the [x402 protocol](https://github.com/coinbase/x402) on Base mainnet or Solana mainnet.
|
|
32
|
+
|
|
33
|
+
**Your AgentKit wallet handles payment automatically.** No API key, no signup, no billing setup. The wallet just needs to hold a small amount of USDC on Base or Solana.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
The action provider files live alongside your AgentKit project:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# 1. Create a new AgentKit project (or use an existing one)
|
|
41
|
+
npx create-onchain-agent
|
|
42
|
+
|
|
43
|
+
# 2. Copy the QuantOracle action provider files into your project
|
|
44
|
+
mkdir -p src/quantoracle
|
|
45
|
+
curl -sL https://raw.githubusercontent.com/QuantOracledev/quantoracle/main/integrations/agentkit/quantoracleActionProvider.ts -o src/quantoracle/quantoracleActionProvider.ts
|
|
46
|
+
curl -sL https://raw.githubusercontent.com/QuantOracledev/quantoracle/main/integrations/agentkit/schemas.ts -o src/quantoracle/schemas.ts
|
|
47
|
+
curl -sL https://raw.githubusercontent.com/QuantOracledev/quantoracle/main/integrations/agentkit/constants.ts -o src/quantoracle/constants.ts
|
|
48
|
+
curl -sL https://raw.githubusercontent.com/QuantOracledev/quantoracle/main/integrations/agentkit/index.ts -o src/quantoracle/index.ts
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or clone the QuantOracle repo and copy the directory:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/QuantOracledev/quantoracle
|
|
55
|
+
cp -r quantoracle/integrations/agentkit ./src/quantoracle
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { AgentKit, CdpEvmWalletProvider } from "@coinbase/agentkit";
|
|
62
|
+
import { quantoracleActionProvider } from "./quantoracle";
|
|
63
|
+
|
|
64
|
+
const walletProvider = await CdpEvmWalletProvider.configureWithWallet({
|
|
65
|
+
apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
66
|
+
apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
67
|
+
networkId: "base-mainnet",
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const agentkit = await AgentKit.from({
|
|
71
|
+
walletProvider,
|
|
72
|
+
actionProviders: [quantoracleActionProvider()],
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// The agent now has 5 new actions:
|
|
76
|
+
// price_option, calculate_kelly, simulate_portfolio,
|
|
77
|
+
// assess_portfolio_risk, recommend_hedge
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
A complete runnable example is at [`example-agent.ts`](./example-agent.ts). Additional examples:
|
|
81
|
+
|
|
82
|
+
- [`example-agent-solana.ts`](./example-agent-solana.ts) — Same agent but routes x402 payments through a Solana mainnet wallet (SPL USDC) instead of Base. Useful for agents already operating in the Solana ecosystem.
|
|
83
|
+
- [`example-chained-workflow.ts`](./example-chained-workflow.ts) — Scripted demo showing the natural `assess_portfolio_risk` → `recommend_hedge` chained workflow. Pre-baked prompts walk the agent through risk audit → hedge analysis → final recommendation. Spends ~$0.08 USDC per run on real x402 settlements.
|
|
84
|
+
|
|
85
|
+
For a side-by-side comparison of integration patterns (direct HTTP vs AgentKit vs LangChain Python), see [`COMPARISONS.md`](./COMPARISONS.md).
|
|
86
|
+
|
|
87
|
+
## Example agent prompts
|
|
88
|
+
|
|
89
|
+
Try these in your AgentKit chat:
|
|
90
|
+
|
|
91
|
+
- _"Price a 30-day NVDA call with strike $185, spot $180, 28% IV"_ → uses `price_option`
|
|
92
|
+
- _"I have 55% win rate, $150 avg win, $100 avg loss — what's my Kelly?"_ → uses `calculate_kelly`
|
|
93
|
+
- _"Simulate $100K over 30 years with 7% return, 16% vol, 4% withdrawal"_ → uses `simulate_portfolio`
|
|
94
|
+
- _"Audit risk on my last 252 daily returns: [...]"_ → uses `assess_portfolio_risk` (paid)
|
|
95
|
+
- _"Recommend hedges for my $100K long NVDA position over 30 days"_ → uses `recommend_hedge` (paid)
|
|
96
|
+
|
|
97
|
+
## Try without code
|
|
98
|
+
|
|
99
|
+
15 free interactive calculators backed by the same engine are at **[quantoracle.dev](https://quantoracle.dev)** — useful for verifying outputs before wiring the action provider into your agent.
|
|
100
|
+
|
|
101
|
+
## Why deterministic finance math matters for agents
|
|
102
|
+
|
|
103
|
+
Three failure modes when LLMs do financial math in-context:
|
|
104
|
+
|
|
105
|
+
1. **Black-Scholes calculations drift.** GPT-4o's Greeks are wrong by 5-30% depending on moneyness. The agent can't tell.
|
|
106
|
+
2. **Compound interest computations skip steps.** A 30-year projection at 8% loses meaningful precision over many tokens.
|
|
107
|
+
3. **Kelly and VaR formulas are mis-applied.** LLMs often confuse arithmetic vs geometric returns or fail to annualize correctly.
|
|
108
|
+
|
|
109
|
+
Grounded tools fix all three: the API is bytes-exact against textbook implementations (Hull, Wilmott, Lopez de Prado), tested across 120 accuracy benchmarks, and returns the same value for the same inputs every time. The agent can cite a specific tool call as the source for any number it presents.
|
|
110
|
+
|
|
111
|
+
## Repository
|
|
112
|
+
|
|
113
|
+
Source: [github.com/QuantOracledev/quantoracle](https://github.com/QuantOracledev/quantoracle)
|
|
114
|
+
API: [api.quantoracle.dev](https://api.quantoracle.dev)
|
|
115
|
+
Calculators: [quantoracle.dev](https://quantoracle.dev)
|
|
116
|
+
OpenAPI spec: [api.quantoracle.dev/openapi.json](https://api.quantoracle.dev/openapi.json)
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT — same as the rest of QuantOracle.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
var agentkit = require('@coinbase/agentkit');
|
|
5
|
+
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
var PriceOptionSchema = zod.z.object({
|
|
9
|
+
S: zod.z.number().positive().describe("Spot price of the underlying"),
|
|
10
|
+
K: zod.z.number().positive().describe("Strike price"),
|
|
11
|
+
T: zod.z.number().positive().describe("Time to expiry in years (0.083 = 30 days)"),
|
|
12
|
+
r: zod.z.number().describe("Risk-free interest rate as decimal (0.05 = 5%)"),
|
|
13
|
+
sigma: zod.z.number().positive().describe("Annualized volatility as decimal (0.28 = 28%)"),
|
|
14
|
+
option_type: zod.z.enum([
|
|
15
|
+
"call",
|
|
16
|
+
"put"
|
|
17
|
+
]).default("call").describe("Option type \u2014 call or put")
|
|
18
|
+
}).describe("Black-Scholes option pricing with full Greeks. Returns price, breakeven, probability ITM, and all first-order Greeks (delta, gamma, vega, theta, rho).");
|
|
19
|
+
var CalculateKellySchema = zod.z.object({
|
|
20
|
+
win_rate: zod.z.number().min(0.01).max(0.99).describe("Probability of winning (0-1)"),
|
|
21
|
+
avg_win: zod.z.number().positive().describe("Average dollar amount won on winning trades"),
|
|
22
|
+
avg_loss: zod.z.number().positive().describe("Average dollar amount lost on losing trades (positive number)")
|
|
23
|
+
}).describe("Kelly Criterion optimal bet sizing. Returns full-, half-, and quarter-Kelly fractions plus edge and payoff ratio. Use half- or quarter-Kelly in real trading because edge estimates are noisy.");
|
|
24
|
+
var SimulatePortfolioSchema = zod.z.object({
|
|
25
|
+
initial_value: zod.z.number().positive().describe("Starting portfolio value"),
|
|
26
|
+
annual_return: zod.z.number().describe("Expected annual return as decimal (0.08 = 8%)"),
|
|
27
|
+
annual_vol: zod.z.number().positive().describe("Annual volatility as decimal (0.18 = 18%)"),
|
|
28
|
+
years: zod.z.number().positive().max(30).describe("Time horizon in years (max 30)"),
|
|
29
|
+
simulations: zod.z.number().int().min(100).max(2500).default(1e3).describe("Number of Monte Carlo paths (100-2500; 1000 default)"),
|
|
30
|
+
contributions: zod.z.number().min(0).default(0).describe("Annual contribution amount (set 0 if none)"),
|
|
31
|
+
withdrawal_rate: zod.z.number().min(0).max(0.5).default(0).describe("Annual withdrawal rate as decimal (0.04 = 4%)")
|
|
32
|
+
}).describe("Monte Carlo portfolio simulation. Returns distribution of terminal outcomes (P5/P25/median/P75/P95), probability of loss, probability of doubling, and probability of ruin under withdrawals.");
|
|
33
|
+
var AssessPortfolioRiskSchema = zod.z.object({
|
|
34
|
+
returns: zod.z.array(zod.z.number()).min(30).max(5e3).describe("Array of historical periodic returns as decimals (0.012 = 1.2%). Daily returns assumed; 30-5000 observations."),
|
|
35
|
+
risk_free_rate: zod.z.number().default(0.04).describe("Annual risk-free rate as decimal (0.04 = 4%)"),
|
|
36
|
+
annualization_factor: zod.z.number().int().default(252).describe("252 for daily returns, 52 for weekly, 12 for monthly")
|
|
37
|
+
}).describe("Composite full risk analysis: Sharpe, Sortino, Calmar, max drawdown, VaR, CVaR, Hurst exponent, and Kelly. PAID endpoint ($0.04 per call, settled in USDC). AgentKit's wallet pays automatically.");
|
|
38
|
+
var RecommendHedgeSchema = zod.z.object({
|
|
39
|
+
position_type: zod.z.enum([
|
|
40
|
+
"long_stock",
|
|
41
|
+
"short_stock",
|
|
42
|
+
"long_crypto",
|
|
43
|
+
"long_options"
|
|
44
|
+
]).describe("Type of position to hedge"),
|
|
45
|
+
position_value: zod.z.number().positive().describe("Current dollar value of the position"),
|
|
46
|
+
asset_price: zod.z.number().positive().describe("Current spot price of the underlying"),
|
|
47
|
+
volatility: zod.z.number().positive().describe("Annualized volatility of the underlying as decimal (0.28 = 28%)"),
|
|
48
|
+
time_horizon_days: zod.z.number().int().positive().default(30).describe("Hedge time horizon in days"),
|
|
49
|
+
max_hedge_cost_pct: zod.z.number().min(0).max(0.5).default(0.05).describe("Maximum hedge cost as fraction of position (0.05 = 5%)"),
|
|
50
|
+
r: zod.z.number().default(0.05).describe("Risk-free rate as decimal")
|
|
51
|
+
}).describe("Recommend ranked hedge structures (collar, protective put, partial put, inverse) for an existing position. Returns each structure's cost, downside protection, and upside cap. PAID endpoint ($0.04 per call, settled in USDC). AgentKit's wallet pays automatically.");
|
|
52
|
+
|
|
53
|
+
// constants.ts
|
|
54
|
+
var QUANTORACLE_BASE_URL = process.env.QUANTORACLE_API_URL ?? "https://api.quantoracle.dev";
|
|
55
|
+
var FREE_TIER_DAILY_LIMIT = 1e3;
|
|
56
|
+
var USER_AGENT = "QuantOracle-AgentKit/1.0";
|
|
57
|
+
|
|
58
|
+
// quantoracleActionProvider.ts
|
|
59
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
60
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
61
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
62
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
63
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
64
|
+
}
|
|
65
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
66
|
+
function _ts_metadata(k, v) {
|
|
67
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
68
|
+
}
|
|
69
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
70
|
+
var QuantOracleActionProvider = class extends agentkit.ActionProvider {
|
|
71
|
+
static {
|
|
72
|
+
__name(this, "QuantOracleActionProvider");
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Constructor for QuantOracleActionProvider. No configuration required —
|
|
76
|
+
* the free tier covers the calculator endpoints, and paid composites use
|
|
77
|
+
* AgentKit's wallet to settle x402 payments.
|
|
78
|
+
*/
|
|
79
|
+
constructor() {
|
|
80
|
+
super("quantoracle", []);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* QuantOracle works on any network because the calculations are pure math
|
|
84
|
+
* (no on-chain reads). x402 settlements for paid endpoints work on Base
|
|
85
|
+
* mainnet and Solana mainnet, but the agent doesn't need to be on those
|
|
86
|
+
* networks to call the free-tier calculators.
|
|
87
|
+
*
|
|
88
|
+
* @returns true for any network
|
|
89
|
+
*/
|
|
90
|
+
supportsNetwork = /* @__PURE__ */ __name((_network) => true, "supportsNetwork");
|
|
91
|
+
/**
|
|
92
|
+
* Price a European call or put option using Black-Scholes. Returns the
|
|
93
|
+
* theoretical fair value plus the full Greek profile (delta, gamma, vega,
|
|
94
|
+
* theta, rho). Use this before placing options orders to verify market
|
|
95
|
+
* prices are reasonable, or to compute expected option PnL given a view
|
|
96
|
+
* on the underlying.
|
|
97
|
+
*
|
|
98
|
+
* @param args - Spot price, strike, time to expiry, rate, vol, type
|
|
99
|
+
* @returns Markdown-formatted summary with price, breakeven, and Greeks
|
|
100
|
+
*/
|
|
101
|
+
async priceOption(args) {
|
|
102
|
+
try {
|
|
103
|
+
const data = await this.callApi("/v1/options/price", args);
|
|
104
|
+
const ms = data.ms ?? 0;
|
|
105
|
+
const greeks = data.greeks ?? {};
|
|
106
|
+
return [
|
|
107
|
+
`**${args.option_type.toUpperCase()} on $${args.S} underlying, $${args.K} strike, ${(args.T * 365).toFixed(0)}d to expiry, ${(args.sigma * 100).toFixed(1)}% IV**`,
|
|
108
|
+
``,
|
|
109
|
+
`- Price: $${data.price.toFixed(4)}`,
|
|
110
|
+
`- Breakeven: $${data.breakeven.toFixed(2)}`,
|
|
111
|
+
`- Probability ITM: ${(data.prob_itm * 100).toFixed(1)}%`,
|
|
112
|
+
`- Delta: ${greeks.delta.toFixed(4)}`,
|
|
113
|
+
`- Gamma: ${greeks.gamma.toFixed(4)}`,
|
|
114
|
+
`- Vega: ${greeks.vega.toFixed(4)}`,
|
|
115
|
+
`- Theta (per day): ${greeks.theta.toFixed(4)}`,
|
|
116
|
+
`- Rho: ${greeks.rho.toFixed(4)}`,
|
|
117
|
+
``,
|
|
118
|
+
`_Computed in ${ms.toFixed(0)}ms via QuantOracle._`
|
|
119
|
+
].join("\n");
|
|
120
|
+
} catch (err) {
|
|
121
|
+
return `Failed to price option: ${err instanceof Error ? err.message : String(err)}`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Calculate Kelly Criterion optimal bet/position sizing. Returns full-,
|
|
126
|
+
* half-, and quarter-Kelly fractions. Use this to derive a defensible
|
|
127
|
+
* risk-per-trade fraction from your strategy's win rate and average
|
|
128
|
+
* win/loss profile, BEFORE sizing the position.
|
|
129
|
+
*
|
|
130
|
+
* @param args - Win rate, average win, average loss
|
|
131
|
+
* @returns Markdown-formatted summary with Kelly variants and edge analysis
|
|
132
|
+
*/
|
|
133
|
+
async calculateKelly(args) {
|
|
134
|
+
try {
|
|
135
|
+
const data = await this.callApi("/v1/risk/kelly", {
|
|
136
|
+
mode: "discrete",
|
|
137
|
+
...args
|
|
138
|
+
});
|
|
139
|
+
const fullKelly = data.full_kelly * 100;
|
|
140
|
+
const halfKelly = data.half_kelly * 100;
|
|
141
|
+
const quarterKelly = data.quarter_kelly * 100;
|
|
142
|
+
const recommendation = data.recommended.replace(/_/g, " ").toLowerCase();
|
|
143
|
+
return [
|
|
144
|
+
`**Kelly sizing for ${(args.win_rate * 100).toFixed(1)}% win rate, $${args.avg_win} avg win, $${args.avg_loss} avg loss**`,
|
|
145
|
+
``,
|
|
146
|
+
`- Full Kelly: ${fullKelly.toFixed(2)}%`,
|
|
147
|
+
`- Half Kelly: ${halfKelly.toFixed(2)}% _(typical for risk-tolerant)_`,
|
|
148
|
+
`- Quarter Kelly: ${quarterKelly.toFixed(2)}% _(safer; recommended)_`,
|
|
149
|
+
`- Edge: ${data.edge.toFixed(2)}%`,
|
|
150
|
+
`- Payoff ratio: ${data.payoff_ratio.toFixed(2)}\xD7`,
|
|
151
|
+
`- **Recommendation:** ${recommendation}`,
|
|
152
|
+
``,
|
|
153
|
+
fullKelly < 0 ? `_Negative edge \u2014 this strategy has negative expected value. Do not deploy capital._` : `_Computed via QuantOracle._`
|
|
154
|
+
].join("\n");
|
|
155
|
+
} catch (err) {
|
|
156
|
+
return `Failed to calculate Kelly: ${err instanceof Error ? err.message : String(err)}`;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Run a Monte Carlo portfolio simulation to project the distribution of
|
|
161
|
+
* terminal outcomes. Use this to assess sequence-of-returns risk before
|
|
162
|
+
* deploying a strategy or to validate retirement-withdrawal sustainability.
|
|
163
|
+
*
|
|
164
|
+
* @param args - Initial value, return/vol assumptions, time horizon, contributions/withdrawals
|
|
165
|
+
* @returns Markdown-formatted summary with distribution percentiles and probability events
|
|
166
|
+
*/
|
|
167
|
+
async simulatePortfolio(args) {
|
|
168
|
+
try {
|
|
169
|
+
const data = await this.callApi("/v1/simulate/montecarlo", args);
|
|
170
|
+
const t = data.terminal;
|
|
171
|
+
const probLoss = (data.prob_loss * 100).toFixed(1);
|
|
172
|
+
const probRuin = (data.prob_ruin * 100).toFixed(2);
|
|
173
|
+
const cagr = (data.cagr * 100).toFixed(2);
|
|
174
|
+
const fmt = /* @__PURE__ */ __name((v) => `$${v.toLocaleString(void 0, {
|
|
175
|
+
maximumFractionDigits: 0
|
|
176
|
+
})}`, "fmt");
|
|
177
|
+
return [
|
|
178
|
+
`**Monte Carlo: $${args.initial_value.toLocaleString()} over ${args.years} years, ${(args.annual_return * 100).toFixed(1)}% return, ${(args.annual_vol * 100).toFixed(1)}% vol**`,
|
|
179
|
+
``,
|
|
180
|
+
`_Distribution of terminal outcomes (across ${args.simulations.toLocaleString()} simulated paths):_`,
|
|
181
|
+
`- Median: ${fmt(t.median)}`,
|
|
182
|
+
`- 5th percentile (worst 5%): ${fmt(t.p5)}`,
|
|
183
|
+
`- 95th percentile (best 5%): ${fmt(t.p95)}`,
|
|
184
|
+
`- Median CAGR: ${cagr}%`,
|
|
185
|
+
``,
|
|
186
|
+
`**Probability events:**`,
|
|
187
|
+
`- Loss vs starting value: ${probLoss}%`,
|
|
188
|
+
`- Probability of ruin (portfolio depleted): ${probRuin}%`,
|
|
189
|
+
``,
|
|
190
|
+
`_Computed in ${data.ms.toFixed(0)}ms via QuantOracle._`
|
|
191
|
+
].join("\n");
|
|
192
|
+
} catch (err) {
|
|
193
|
+
return `Failed to simulate: ${err instanceof Error ? err.message : String(err)}`;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Compute a full risk-adjusted-return audit: Sharpe, Sortino, Calmar, max
|
|
198
|
+
* drawdown, VaR, CVaR, Kelly. PAID composite endpoint ($0.04 per call,
|
|
199
|
+
* settled in USDC via x402 — AgentKit's wallet handles payment automatically
|
|
200
|
+
* when the free tier is exceeded).
|
|
201
|
+
*
|
|
202
|
+
* @param args - Historical returns array, risk-free rate, annualization factor
|
|
203
|
+
* @returns Markdown-formatted comprehensive risk summary
|
|
204
|
+
*/
|
|
205
|
+
async assessPortfolioRisk(args) {
|
|
206
|
+
try {
|
|
207
|
+
const data = await this.callApi("/v1/risk/full-analysis", args);
|
|
208
|
+
const sharpe = data.sharpe?.sharpe_ratio ?? 0;
|
|
209
|
+
const sortino = data.sortino?.sortino_ratio ?? 0;
|
|
210
|
+
const calmar = data.calmar?.calmar_ratio ?? 0;
|
|
211
|
+
const maxDd = data.drawdown?.max_drawdown ?? 0;
|
|
212
|
+
const varBlock = data.var;
|
|
213
|
+
const var95 = varBlock?.var_results?.["95"]?.var_pct ?? 0;
|
|
214
|
+
const cvar95 = varBlock?.var_results?.["95"]?.cvar_pct ?? 0;
|
|
215
|
+
const kelly = data.kelly?.kelly_fraction ?? 0;
|
|
216
|
+
const hurst = data.hurst?.hurst_exponent ?? 0;
|
|
217
|
+
return [
|
|
218
|
+
`**Risk audit on ${args.returns.length} observations** _(paid via x402, $0.04 USDC)_`,
|
|
219
|
+
``,
|
|
220
|
+
`**Risk-adjusted return:**`,
|
|
221
|
+
`- Sharpe ratio: ${sharpe.toFixed(2)}`,
|
|
222
|
+
`- Sortino ratio: ${sortino.toFixed(2)}`,
|
|
223
|
+
`- Calmar ratio: ${calmar.toFixed(2)}`,
|
|
224
|
+
``,
|
|
225
|
+
`**Tail risk:**`,
|
|
226
|
+
`- Max drawdown: ${(maxDd * 100).toFixed(2)}%`,
|
|
227
|
+
`- VaR (95%): ${var95.toFixed(2)}%`,
|
|
228
|
+
`- CVaR / Expected Shortfall (95%): ${cvar95.toFixed(2)}%`,
|
|
229
|
+
``,
|
|
230
|
+
`**Sizing & regime:**`,
|
|
231
|
+
`- Kelly fraction: ${(kelly * 100).toFixed(2)}%`,
|
|
232
|
+
`- Hurst exponent: ${hurst.toFixed(3)} ${hurst > 0.6 ? "_(trending)_" : hurst < 0.4 ? "_(mean-reverting)_" : "_(random walk)_"}`,
|
|
233
|
+
``,
|
|
234
|
+
`_Composite analysis via QuantOracle. Settled on-chain via x402._`
|
|
235
|
+
].join("\n");
|
|
236
|
+
} catch (err) {
|
|
237
|
+
return `Failed to assess risk: ${err instanceof Error ? err.message : String(err)}`;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Recommend ranked hedge structures for an existing position. PAID
|
|
242
|
+
* composite endpoint ($0.04 per call, settled in USDC via x402).
|
|
243
|
+
*
|
|
244
|
+
* @param args - Position details and hedge parameters
|
|
245
|
+
* @returns Markdown-formatted ranked list of hedge structures
|
|
246
|
+
*/
|
|
247
|
+
async recommendHedge(args) {
|
|
248
|
+
try {
|
|
249
|
+
const data = await this.callApi("/v1/hedging/recommend", args);
|
|
250
|
+
const structures = data.structures ?? [];
|
|
251
|
+
const lines = [
|
|
252
|
+
`**Hedge recommendations for $${args.position_value.toLocaleString()} ${args.position_type} position over ${args.time_horizon_days} days** _(paid via x402, $0.04 USDC)_`,
|
|
253
|
+
``
|
|
254
|
+
];
|
|
255
|
+
for (let i = 0; i < structures.length; i++) {
|
|
256
|
+
const s = structures[i];
|
|
257
|
+
lines.push(`**${i + 1}. ${s.name}** \u2014 cost ${(s.cost_pct * 100).toFixed(2)}% ($${s.cost_dollars.toFixed(2)}), floor ${(s.downside_floor * 100).toFixed(1)}%${s.upside_cap ? `, upside cap ${(s.upside_cap * 100).toFixed(1)}%` : ", unlimited upside"}`);
|
|
258
|
+
if (s.legs) {
|
|
259
|
+
for (const leg of s.legs) {
|
|
260
|
+
lines.push(` - ${leg.action} ${leg.quantity}\xD7 ${leg.type} @ $${leg.strike.toFixed(2)} (premium $${leg.premium.toFixed(2)})`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
lines.push(``);
|
|
264
|
+
}
|
|
265
|
+
return lines.join("\n");
|
|
266
|
+
} catch (err) {
|
|
267
|
+
return `Failed to recommend hedge: ${err instanceof Error ? err.message : String(err)}`;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Internal helper. Posts JSON to a QuantOracle endpoint and returns the
|
|
272
|
+
* parsed response. Throws on non-2xx responses, including 402 Payment
|
|
273
|
+
* Required when the free tier is exceeded — at which point AgentKit's
|
|
274
|
+
* wallet should auto-retry with x402 payment headers (depending on your
|
|
275
|
+
* walletProvider setup).
|
|
276
|
+
*
|
|
277
|
+
* @param path - Endpoint path beginning with /v1/...
|
|
278
|
+
* @param body - JSON-serializable request body
|
|
279
|
+
* @returns Parsed JSON response
|
|
280
|
+
*/
|
|
281
|
+
async callApi(path, body) {
|
|
282
|
+
const res = await fetch(`${QUANTORACLE_BASE_URL}${path}`, {
|
|
283
|
+
method: "POST",
|
|
284
|
+
headers: {
|
|
285
|
+
"Content-Type": "application/json",
|
|
286
|
+
"User-Agent": USER_AGENT,
|
|
287
|
+
"X-Source": "agentkit"
|
|
288
|
+
},
|
|
289
|
+
body: JSON.stringify(body)
|
|
290
|
+
});
|
|
291
|
+
if (!res.ok) {
|
|
292
|
+
let detail = "";
|
|
293
|
+
try {
|
|
294
|
+
const j = await res.json();
|
|
295
|
+
detail = JSON.stringify(j).slice(0, 200);
|
|
296
|
+
} catch {
|
|
297
|
+
}
|
|
298
|
+
throw new Error(`QuantOracle ${path} returned ${res.status}: ${detail}`);
|
|
299
|
+
}
|
|
300
|
+
return await res.json();
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
_ts_decorate([
|
|
304
|
+
agentkit.CreateAction({
|
|
305
|
+
name: "price_option",
|
|
306
|
+
description: `
|
|
307
|
+
Price a European call or put option using Black-Scholes with full Greeks.
|
|
308
|
+
Returns the option's theoretical price, breakeven, probability ITM, and
|
|
309
|
+
all first-order Greeks (delta, gamma, vega, theta, rho).
|
|
310
|
+
|
|
311
|
+
Use this when:
|
|
312
|
+
- Verifying that a market option price is reasonable before placing an order
|
|
313
|
+
- Estimating PnL on an existing options position given a view on the underlying
|
|
314
|
+
- Computing position deltas for portfolio hedging decisions
|
|
315
|
+
- Sizing options trades based on Greek exposures
|
|
316
|
+
|
|
317
|
+
Inputs: spot price, strike, time to expiry (in years; 30 days = 0.083),
|
|
318
|
+
risk-free rate, volatility, option type (call or put).
|
|
319
|
+
`,
|
|
320
|
+
schema: PriceOptionSchema
|
|
321
|
+
}),
|
|
322
|
+
_ts_metadata("design:type", Function),
|
|
323
|
+
_ts_metadata("design:paramtypes", [
|
|
324
|
+
typeof zod.z === "undefined" || typeof zod.z.infer === "undefined" ? Object : zod.z.infer
|
|
325
|
+
]),
|
|
326
|
+
_ts_metadata("design:returntype", Promise)
|
|
327
|
+
], QuantOracleActionProvider.prototype, "priceOption", null);
|
|
328
|
+
_ts_decorate([
|
|
329
|
+
agentkit.CreateAction({
|
|
330
|
+
name: "calculate_kelly",
|
|
331
|
+
description: `
|
|
332
|
+
Calculate Kelly Criterion optimal bet sizing given a strategy's win rate
|
|
333
|
+
and average win/loss amounts. Returns the full-, half-, and quarter-Kelly
|
|
334
|
+
fractions, the edge per dollar risked, and the payoff ratio.
|
|
335
|
+
|
|
336
|
+
Use this when:
|
|
337
|
+
- Deriving the risk-per-trade fraction for a position-sizing system
|
|
338
|
+
- Comparing two strategies head-to-head (higher Kelly = better edge per unit risk)
|
|
339
|
+
- Validating that a strategy is positive-expected-value before deploying capital
|
|
340
|
+
|
|
341
|
+
The formula assumes binary outcomes with fixed amounts (suits options trades,
|
|
342
|
+
event-driven bets, or any discrete win/loss strategy). For continuous-return
|
|
343
|
+
strategies, see the QuantOracle API endpoint /v1/risk/kelly with mode=continuous.
|
|
344
|
+
|
|
345
|
+
Most professionals use half- or quarter-Kelly because edge estimates are noisy
|
|
346
|
+
and overestimating edge causes severe overbetting.
|
|
347
|
+
`,
|
|
348
|
+
schema: CalculateKellySchema
|
|
349
|
+
}),
|
|
350
|
+
_ts_metadata("design:type", Function),
|
|
351
|
+
_ts_metadata("design:paramtypes", [
|
|
352
|
+
typeof zod.z === "undefined" || typeof zod.z.infer === "undefined" ? Object : zod.z.infer
|
|
353
|
+
]),
|
|
354
|
+
_ts_metadata("design:returntype", Promise)
|
|
355
|
+
], QuantOracleActionProvider.prototype, "calculateKelly", null);
|
|
356
|
+
_ts_decorate([
|
|
357
|
+
agentkit.CreateAction({
|
|
358
|
+
name: "simulate_portfolio",
|
|
359
|
+
description: `
|
|
360
|
+
Run a Monte Carlo simulation projecting the distribution of portfolio
|
|
361
|
+
outcomes over a chosen time horizon. Returns terminal-value percentiles
|
|
362
|
+
(P5/P25/median/P75/P95), probability of loss, probability of doubling,
|
|
363
|
+
and probability of ruin under withdrawals.
|
|
364
|
+
|
|
365
|
+
Use this when:
|
|
366
|
+
- Stress-testing a withdrawal-rate plan (e.g. "is 4% sustainable for 30 years?")
|
|
367
|
+
- Comparing portfolio strategies head-to-head
|
|
368
|
+
- Quantifying sequence-of-returns risk for retirement-style allocations
|
|
369
|
+
- Showing a user the realistic range of outcomes (not just expected return)
|
|
370
|
+
|
|
371
|
+
The simulation uses geometric Brownian motion (log-normal returns) \u2014 a
|
|
372
|
+
standard textbook assumption that is reasonable for diversified portfolios
|
|
373
|
+
but underestimates fat-tail risk for high-vol single-asset strategies.
|
|
374
|
+
`,
|
|
375
|
+
schema: SimulatePortfolioSchema
|
|
376
|
+
}),
|
|
377
|
+
_ts_metadata("design:type", Function),
|
|
378
|
+
_ts_metadata("design:paramtypes", [
|
|
379
|
+
typeof zod.z === "undefined" || typeof zod.z.infer === "undefined" ? Object : zod.z.infer
|
|
380
|
+
]),
|
|
381
|
+
_ts_metadata("design:returntype", Promise)
|
|
382
|
+
], QuantOracleActionProvider.prototype, "simulatePortfolio", null);
|
|
383
|
+
_ts_decorate([
|
|
384
|
+
agentkit.CreateAction({
|
|
385
|
+
name: "assess_portfolio_risk",
|
|
386
|
+
description: `
|
|
387
|
+
Run a comprehensive risk audit on a return series. Returns Sharpe ratio,
|
|
388
|
+
Sortino ratio, Calmar ratio, max drawdown, VaR (95%/99%), CVaR (Expected
|
|
389
|
+
Shortfall), Kelly fraction, and Hurst exponent (regime indicator).
|
|
390
|
+
|
|
391
|
+
Use this when:
|
|
392
|
+
- Evaluating a backtest before deploying real capital
|
|
393
|
+
- Auditing an existing strategy's risk-adjusted performance
|
|
394
|
+
- Comparing two strategies on multiple risk dimensions in one call
|
|
395
|
+
- Generating a one-page risk summary for a stakeholder
|
|
396
|
+
|
|
397
|
+
PAID composite endpoint: $0.04 per call, settled in USDC via x402 on Base
|
|
398
|
+
or Solana. AgentKit's wallet pays automatically \u2014 no API key, no signup.
|
|
399
|
+
The savings vs running 8 separate calculator calls is meaningful both in
|
|
400
|
+
cost and in latency.
|
|
401
|
+
|
|
402
|
+
Requires at least 30 observations of historical returns; 252+ recommended
|
|
403
|
+
for statistical significance.
|
|
404
|
+
`,
|
|
405
|
+
schema: AssessPortfolioRiskSchema
|
|
406
|
+
}),
|
|
407
|
+
_ts_metadata("design:type", Function),
|
|
408
|
+
_ts_metadata("design:paramtypes", [
|
|
409
|
+
typeof zod.z === "undefined" || typeof zod.z.infer === "undefined" ? Object : zod.z.infer
|
|
410
|
+
]),
|
|
411
|
+
_ts_metadata("design:returntype", Promise)
|
|
412
|
+
], QuantOracleActionProvider.prototype, "assessPortfolioRisk", null);
|
|
413
|
+
_ts_decorate([
|
|
414
|
+
agentkit.CreateAction({
|
|
415
|
+
name: "recommend_hedge",
|
|
416
|
+
description: `
|
|
417
|
+
Recommend ranked hedge structures (collar, protective put, partial put,
|
|
418
|
+
inverse) for an existing position. Each recommendation includes the cost
|
|
419
|
+
as a percentage of position value, the downside protection floor, and the
|
|
420
|
+
upside cap (if any).
|
|
421
|
+
|
|
422
|
+
Use this when:
|
|
423
|
+
- An agent holding a long position wants to limit downside before an event
|
|
424
|
+
(earnings, FOMC, FDA decision) without selling
|
|
425
|
+
- An agent needs to compare hedge strategies head-to-head by cost vs protection
|
|
426
|
+
- Programmatic risk management of crypto positions ahead of high-vol periods
|
|
427
|
+
|
|
428
|
+
PAID composite endpoint: $0.04 per call, settled in USDC via x402 on Base or
|
|
429
|
+
Solana. AgentKit's wallet pays automatically. The output is a ranked table
|
|
430
|
+
the agent can present to a user or use directly to place hedge orders.
|
|
431
|
+
`,
|
|
432
|
+
schema: RecommendHedgeSchema
|
|
433
|
+
}),
|
|
434
|
+
_ts_metadata("design:type", Function),
|
|
435
|
+
_ts_metadata("design:paramtypes", [
|
|
436
|
+
typeof zod.z === "undefined" || typeof zod.z.infer === "undefined" ? Object : zod.z.infer
|
|
437
|
+
]),
|
|
438
|
+
_ts_metadata("design:returntype", Promise)
|
|
439
|
+
], QuantOracleActionProvider.prototype, "recommendHedge", null);
|
|
440
|
+
var quantoracleActionProvider = /* @__PURE__ */ __name(() => new QuantOracleActionProvider(), "quantoracleActionProvider");
|
|
441
|
+
|
|
442
|
+
exports.AssessPortfolioRiskSchema = AssessPortfolioRiskSchema;
|
|
443
|
+
exports.CalculateKellySchema = CalculateKellySchema;
|
|
444
|
+
exports.FREE_TIER_DAILY_LIMIT = FREE_TIER_DAILY_LIMIT;
|
|
445
|
+
exports.PriceOptionSchema = PriceOptionSchema;
|
|
446
|
+
exports.QUANTORACLE_BASE_URL = QUANTORACLE_BASE_URL;
|
|
447
|
+
exports.QuantOracleActionProvider = QuantOracleActionProvider;
|
|
448
|
+
exports.RecommendHedgeSchema = RecommendHedgeSchema;
|
|
449
|
+
exports.SimulatePortfolioSchema = SimulatePortfolioSchema;
|
|
450
|
+
exports.USER_AGENT = USER_AGENT;
|
|
451
|
+
exports.quantoracleActionProvider = quantoracleActionProvider;
|
|
452
|
+
//# sourceMappingURL=index.cjs.map
|
|
453
|
+
//# sourceMappingURL=index.cjs.map
|