Sharpe Optimizer
Risk-adjusted return. Higher = better per unit of pain.
Sharpe is your return divided by how bumpy the ride was. Above 1 is good, above 2 is rare, above 3 is suspicious. Sortino is the same idea but only counts the bumps that hurt (downside vol). The simplest 'is this strategy any good?' number that exists.
Sharpe is return divided by how bumpy the ride was. >1 is good. >2 is rare. >3 is suspicious. Sortino is the same idea but only counts the bumps that hurt (downside vol). The classic risk-adjusted-return summary — every fund manager reports it, every retail trader should know what their own Sharpe is.
Sharpe = √252 · mean / σ ; Sortino uses downside σ
Real Sharpe Optimizer bot, running on real Yahoo data when the symbol is available. Drag the params — the bot re-runs instantly.
This is the actual code the bot runs — not a re-explanation, not a simplified version. Whatever ships here is what executes when you press Run All in the workbench. Read it, copy it, fork it, build a better one.
const sharpeBot: BotDef = {
id: "sharpe",
name: "Sharpe Optimizer",
category: "risk",
glyph: "★",
tagline: "Risk-adjusted return. Higher = better per unit of pain.",
formula: "Sharpe = √252 · mean / σ ; Sortino uses downside σ",
params: [
{ key: "lookback", label: "Lookback bars", kind: "number", default: 252, min: 30, max: 504, step: 1 },
{ key: "rf", label: "Risk-free / day", kind: "number", default: 0.0001, min: 0, max: 0.001, step: 0.0001 },
],
run: (ctx, p): BotResult => {
const lb = Math.round(num(p, "lookback", 252));
const rf = num(p, "rf", 0.0001);
const px = closes(ctx.candles).slice(-lb);
const r = returns(px);
const sh = sharpe(r, rf);
const so = sortino(r, rf);
const eq: number[] = [1];
for (let i = 0; i < r.length; i++) eq.push(eq[eq.length - 1] * (1 + r[i]));
const dd = maxDrawdown(eq).dd;
const totalRet = eq[eq.length - 1] - 1;
return {
signals: [],
metrics: [
{ key: "sharpe", label: "Sharpe", value: fmtNum(sh, 2), tone: sh > 1 ? "bull" : sh > 0 ? "neutral" : "bear" },
{ key: "sortino", label: "Sortino", value: fmtNum(so, 2), tone: so > 1 ? "bull" : "neutral" },
{ key: "ret", label: `${px.length}d return`, value: fmtPct(totalRet), tone: totalRet > 0 ? "bull" : "bear" },
{ key: "dd", label: "Max DD", value: fmtPct(dd), tone: dd < -0.2 ? "bear" : dd < -0.1 ? "warn" : "neutral" },
],
summary: `Sharpe ${sh.toFixed(2)} · Sortino ${so.toFixed(2)} · Max DD ${(dd * 100).toFixed(1)}% over ${px.length} bars.`,
beginner:
"Sharpe is return divided by how bumpy the ride was. >1 is good. >2 is rare. >3 is suspicious. Sortino is the same idea but only counts the bumps that hurt (downside).",
verdict: {
side: sh > 1 ? "buy" : sh < 0 ? "warn" : "hold",
text: sh > 1
? "Quality risk-adjusted return — buy-and-hold is paying."
: sh > 0
? "Positive but mediocre. Look for better setups."
: "Negative Sharpe — paying for pain. Cash > this asset right now.",
confidence: Math.min(1, Math.abs(sh) / 3),
},
equity: eq,
};
},
};id— unique key the workbench uses to find the bot.params— the sliders + inputs you see on the cell.run(ctx, p)— the function that gets called with candles + your params and returns the verdict.verdict— the BUY / SELL / HOLD pill at the top of the cell.metrics— the small stat boxes shown in the cell body.
- Copy the whole block above.
- On /quant, click + Import your bot in the bot library.
- Paste, hit save. It hot-loads into your workspace.
- Edit any param defaults or logic to your taste — it's now yours.
- ·Comparing strategies on apples-to-apples basis. A 30% return with 60% vol (Sharpe 0.5) is worse than a 15% return with 10% vol (Sharpe 1.5).
- ·Long-horizon evaluation. Sharpe needs ≥30 monthly observations or ≥250 daily to be reliable.
- ·Position sizing across uncorrelated edges. Equal-Sharpe weighting is provably near-optimal for portfolio construction.
- ·Skewed distributions. Sharpe punishes upside vol; if your strategy has rare big wins, Sharpe undersells it.
- ·Short windows. Sharpe over a 3-month sample has wildly variable estimates.
- ·Comparing across asset classes. Sharpe of a bond strategy vs a crypto strategy isn't directly meaningful.
BUY when Sharpe > 1 (quality risk-adjusted return). HOLD between 0 and 1 (positive but mediocre). WARN when Sharpe < 0 (negative edge — paying for pain). Sortino > Sharpe means your returns are positively skewed (good); Sortino < Sharpe is rare and concerning.