Prune

the commit log

Every cut, with its receipt

7 versions of one file. Each shows what prompted the cut, the diff, and what the candles paid for it while it ran, including the 1 cut back off.

Real candles, paper money, no live trading. SOL-USD 15m from Coinbase Exchange, Oct 8, 2026 to Oct 28, 2026 UTC. v0.1 to v0.6 were written by hand. From v0.7 the agent writes each cut and runs it forward on paper.

paper book across all versions · backtest$400 → $398.32-0.42%
  1. v0.1

    first growth

    written by hand

    ran Oct 8, 00:00 to Oct 11, 00:00 UTC · strategies/v0.1.mjs · first file

    cold start. No history, a $400 paper book and one pair.

    Buy when RSI(7) turns back up through 30, sell when it reaches 70, never hold longer than 48 bars (12 hours). No trend filter, no stop. I want to see what the raw signal is worth before I start cutting.

    strategy.mjs+23−0first file
    1+// strategy.mjs: what the agent runs on every closed 15-minute SOL-USD bar.
    2+
    3+export const config = {
    4+ rsiLen: 7,
    5+ rsiBuy: 30,
    6+ rsiExit: 70,
    7+ risk: 0.7,
    8+ maxHold: 48,
    9+};
    10+
    11+export function onBar(s, f) {
    12+ const r = f.rsi(config.rsiLen);
    13+
    14+ if (s.flat) {
    15+ if (r.crossUp(config.rsiBuy)) {
    16+ return s.long(config.risk);
    17+ }
    18+ return;
    19+ }
    20+
    21+ if (r.value >= config.rsiExit) return s.close("signal");
    22+ if (s.held >= config.maxHold) return s.close("timeout");
    23+}

    return

    -1.63%

    -$6.53

    SOL same days

    -5.36%

    buy and hold

    trades

    7

    5 green

    in the market

    46%

    max dd 4.55%

    fills under v0.1 (backtest)
    • 08/10 04:30$115.50 → $108.5512h 15mtimeout-6.11%
    • 08/10 18:30$107.81 → $109.401h 45msignal+1.37%
    • 09/10 00:45$109.22 → $110.172h 15msignal+0.77%
    • 09/10 11:00$109.68 → $111.111hsignal+1.20%
    • 09/10 14:00$109.54 → $109.5111h 15msignal-0.14%
    • 10/10 11:00$109.64 → $110.283h 30msignal+0.48%
    • 10/10 18:30$109.93 → $110.291hsignal+0.23%
  2. v0.2

    a dip is not a direction

    written by hand

    ran Oct 11, 00:00 to Oct 14, 00:00 UTC · strategies/v0.2.mjs · cut from v0.1

    v0.1 won 5 of its 7 trades and still lost money. One dip-buy was held 12 hours while SOL kept sliding, and lost 6%.

    Only buy the dip when the close is above its one-day EMA(96). A bounce inside a falling market is the trade that kept hurting. This should cost me trades. It should cost me more of the bad ones.

    trend filteroff→ema(96)
    strategy.mjs+3−1v0.1 → v0.2
    ⋯ 4 unchanged
    5 rsiBuy: 30,
    6 rsiExit: 70,
    7+ emaLen: 96,
    8 risk: 0.7,
    9 maxHold: 48,
    ⋯ 2 unchanged
    12 export function onBar(s, f) {
    13 const r = f.rsi(config.rsiLen);
    14+ const trend = f.bar.close > f.ema(config.emaLen).value;
    15
    16 if (s.flat) {
    15- if (r.crossUp(config.rsiBuy)) {
    17+ if (r.crossUp(config.rsiBuy) && trend) {
    18 return s.long(config.risk);
    19 }
    ⋯ 6 unchanged

    return

    -1.98%

    -$7.79

    SOL same days

    -2.96%

    buy and hold

    trades

    2

    1 green

    in the market

    22%

    max dd 2.88%

    fills under v0.2 (backtest)
    • 11/10 21:45$110.66 → $111.453h 15msignal+0.62%
    • 12/10 09:15$111.74 → $108.0112h 15mtimeout-3.43%
  3. v0.3

    cap the tail

    written by hand

    ran Oct 14, 00:00 to Oct 17, 00:00 UTC · strategies/v0.3.mjs · cut from v0.2

    one v0.2 trade had no floor under it and lost 3.4% before the clock closed it.

    A hard stop 2% under the entry, filled as a resting order, and a 40-bar cap instead of 48. The stop will fire on noise sometimes. What I am buying is a known worst case.

    hard stopoff→2%max hold48 bars→40 bars
    strategy.mjs+4−1v0.2 → v0.3
    ⋯ 5 unchanged
    6 rsiExit: 70,
    7 emaLen: 96,
    8+ stop: 0.02,
    9 risk: 0.7,
    9- maxHold: 48,
    10+ maxHold: 40,
    11 };
    12
    ⋯ 9 unchanged
    22 }
    23
    24+ const stopPx = s.entry * (1 - config.stop);
    25+ if (f.bar.low <= stopPx) return s.close("stop", stopPx);
    26 if (r.value >= config.rsiExit) return s.close("signal");
    27 if (s.held >= config.maxHold) return s.close("timeout");
    ⋯ 1 unchanged

    return

    +1.11%

    +$4.26

    SOL same days

    -2.25%

    buy and hold

    trades

    2

    2 green

    in the market

    9%

    max dd 0.56%

    fills under v0.3 (backtest)
    • 15/10 23:45$105.33 → $106.045h 30msignal+0.57%
    • 16/10 10:30$105.92 → $107.1045msignal+1.01%
  4. v0.4

    skip the quiet hours

    written by hand

    ran Oct 17, 00:00 to Oct 20, 00:00 UTC · strategies/v0.4.mjs · cut from v0.3

    a hunch: entries on thin volume are the ones that drift.

    Entries now also need volume 1.2x its 24-bar average, and after a losing trade I stand down for 8 bars. Fewer trades. I know this also skips quiet bars that turn into loud ones.

    volume gateoff→1.2xcooldownoff→8 bars
    strategy.mjs+5−1v0.3 → v0.4
    ⋯ 5 unchanged
    6 rsiExit: 70,
    7 emaLen: 96,
    8+ volMult: 1.2,
    9 stop: 0.02,
    10 risk: 0.7,
    11+ cooldown: 8,
    12 maxHold: 40,
    13 };
    ⋯ 2 unchanged
    16 const r = f.rsi(config.rsiLen);
    17 const trend = f.bar.close > f.ema(config.emaLen).value;
    18+ const busy = f.vol.now > f.vol.avg(24) * config.volMult;
    19
    20 if (s.flat) {
    18- if (r.crossUp(config.rsiBuy) && trend) {
    21+ if (s.sinceLoss < config.cooldown) return;
    22+ if (r.crossUp(config.rsiBuy) && trend && busy) {
    23 return s.long(config.risk);
    24 }
    ⋯ 8 unchanged

    return

    +0.27%

    +$1.07

    SOL same days

    +0.62%

    buy and hold

    trades

    1

    1 green

    in the market

    10%

    max dd 0.78%

    fills under v0.4 (backtest)
    • 19/10 15:00$104.64 → $105.167h 15msignal+0.39%
  5. v0.5

    let the winner run

    written by hand

    ran Oct 20, 00:00 to Oct 23, 00:00 UTC · strategies/v0.5.mjs · cut from v0.4

    every winner so far was closed by RSI 70. I wanted to know what holding longer is worth.

    The RSI exit comes out. A trailing exit 1.5% under the highest high since entry replaces it, and a trade can now last 64 bars. The stop protects the entry, the trail protects the gain.

    rsi exit70→offtrailing exitoff→1.5%max hold40 bars→64 bars
    strategy.mjs+3−3v0.4 → v0.5
    ⋯ 3 unchanged
    4 rsiLen: 7,
    5 rsiBuy: 30,
    6- rsiExit: 70,
    6 emaLen: 96,
    7 volMult: 1.2,
    8 stop: 0.02,
    9+ trail: 0.015,
    10 risk: 0.7,
    11 cooldown: 8,
    12- maxHold: 40,
    12+ maxHold: 64,
    13 };
    14
    ⋯ 13 unchanged
    28 const stopPx = s.entry * (1 - config.stop);
    29 if (f.bar.low <= stopPx) return s.close("stop", stopPx);
    30- if (r.value >= config.rsiExit) return s.close("signal");
    30+ if (f.bar.close <= s.peak * (1 - config.trail)) return s.close("trail");
    31 if (s.held >= config.maxHold) return s.close("timeout");
    32 }

    return

    +1.38%

    +$5.41

    SOL same days

    -1.34%

    buy and hold

    trades

    1

    1 green

    in the market

    23%

    max dd 0.82%

    fills under v0.5 (backtest)
    • 21/10 05:15$105.90 → $108.1116h 15mtimeout+1.98%
  6. v0.5.1

    require the mean to be rising

    revertedwritten by hand

    ran Oct 23, 00:00 to Oct 26, 00:00 UTC · strategies/v0.5.1.mjs · cut from v0.5

    a hunch, and the run says it was a bad one.

    A second trend rule: the EMA(96) must be higher than it was 24 bars ago. It made no trades at all in its three days. Over the 24 earlier weeks it made exactly the same trades as v0.5, so the rule never changed a single decision. A rule that never fires is dead wood. Reverted.

    trend slopeoff→24 bars
    strategy.mjs+5−2v0.5 → v0.5.1
    ⋯ 4 unchanged
    5 rsiBuy: 30,
    6 emaLen: 96,
    7+ slope: 24,
    8 volMult: 1.2,
    9 stop: 0.02,
    ⋯ 6 unchanged
    16 export function onBar(s, f) {
    17 const r = f.rsi(config.rsiLen);
    17- const trend = f.bar.close > f.ema(config.emaLen).value;
    18+ const mean = f.ema(config.emaLen);
    19+ const trend = f.bar.close > mean.value;
    20+ const rising = mean.value > mean.ago(config.slope);
    21 const busy = f.vol.now > f.vol.avg(24) * config.volMult;
    22
    23 if (s.flat) {
    24 if (s.sinceLoss < config.cooldown) return;
    22- if (r.crossUp(config.rsiBuy) && trend && busy) {
    25+ if (r.crossUp(config.rsiBuy) && trend && rising && busy) {
    26 return s.long(config.risk);
    27 }
    ⋯ 8 unchanged

    return

    0.00%

    +$0.00

    SOL same days

    -2.21%

    buy and hold

    trades

    0

    0 green

    in the market

    0%

    max dd 0.00%

    fills under v0.5.1 (backtest)

    no trades in these three days

  7. v0.6

    prune back to the branch that held

    written by hand

    ran Oct 26, 00:00 to Oct 29, 00:00 UTC · strategies/v0.6.mjs · cut from v0.5

    over 24 earlier weeks, v0.4 and v0.5 finished positive less often than plain v0.3. Every rule I added after v0.3 made it worse.

    Cut the volume gate, the cooldown and the trail. Put the RSI exit back. This is v0.3's logic again, with 90% of the book per entry instead of 70%. Caveat: I picked this by looking at those earlier weeks, so for v0.6 they are no longer out-of-sample. Only its own three live days are fresh.

    rsi exitoff→70volume gate1.2x→offtrailing exit1.5%→offbook per entry70%→90%cooldown8 bars→offmax hold64 bars→40 bars
    strategy.mjs+5−9v0.5 → v0.6
    ⋯ 3 unchanged
    4 rsiLen: 7,
    5 rsiBuy: 30,
    6+ rsiExit: 70,
    7 emaLen: 96,
    7- volMult: 1.2,
    8 stop: 0.02,
    9- trail: 0.015,
    10- risk: 0.7,
    11- cooldown: 8,
    12- maxHold: 64,
    9+ risk: 0.9,
    10+ maxHold: 40,
    11 };
    12
    ⋯ 1 unchanged
    14 const r = f.rsi(config.rsiLen);
    15 const trend = f.bar.close > f.ema(config.emaLen).value;
    18- const busy = f.vol.now > f.vol.avg(24) * config.volMult;
    16
    17 if (s.flat) {
    21- if (s.sinceLoss < config.cooldown) return;
    22- if (r.crossUp(config.rsiBuy) && trend && busy) {
    18+ if (r.crossUp(config.rsiBuy) && trend) {
    19 return s.long(config.risk);
    20 }
    ⋯ 3 unchanged
    24 const stopPx = s.entry * (1 - config.stop);
    25 if (f.bar.low <= stopPx) return s.close("stop", stopPx);
    30- if (f.bar.close <= s.peak * (1 - config.trail)) return s.close("trail");
    26+ if (r.value >= config.rsiExit) return s.close("signal");
    27 if (s.held >= config.maxHold) return s.close("timeout");
    28 }

    return

    +0.48%

    +$1.89

    SOL same days

    +1.07%

    buy and hold

    trades

    1

    1 green

    in the market

    1%

    max dd 0.12%

    fills under v0.6 (backtest)
    • 26/10 14:15$101.24 → $101.8845msignal+0.53%