Variant comparison across BTC + WETH on identical window.
| # | Variant | Trades | Σ PnL ($) | Avg PnL % | Distribution |
|---|---|---|---|---|---|
| 1 | full-counter-trend | 2 | +$187.21 | +0.94% | |
| 2 | full-plus-sizing | 18 | +$143.04 | +0.72% | |
| 3 | reversal-guard | 15 | $-167.18 | -0.84% | |
| 4 | base | 11 | $-617.94 | -3.09% |
| Variant | Pair | Trades | Final $ | PnL ($) | PnL % |
|---|---|---|---|---|---|
| base | btcusdc | 4 | $9975.94 | $-24.06 | -0.24% |
| base | wethusdc | 7 | $9406.12 | $-593.88 | -5.94% |
| full-counter-trend | btcusdc | 2 | $10187.21 | +$187.21 | +1.87% |
| full-counter-trend | wethusdc | 0 | $10000.00 | +$0.00 | +0.00% |
| full-plus-sizing | btcusdc | 6 | $10086.17 | +$86.17 | +0.86% |
| full-plus-sizing | wethusdc | 12 | $10056.86 | +$56.86 | +0.57% |
| reversal-guard | btcusdc | 8 | $9738.54 | $-261.46 | -2.61% |
| reversal-guard | wethusdc | 7 | $10094.28 | +$94.28 | +0.94% |
base) lost −3.09% across both assets in 6 days, driven by a Path B → reversal exit loop on WETH (−5.94%). All 3 patched variants close the gap.reversal-guard) added +2.25% on average.full-counter-trend let the BTC trade run for 14 hours instead of scalping prematurely → caught the full TP at +6.24% (+$187 on $3000), the single biggest realized win.full-plus-sizing trades both assets profitably because Path E's relaxed RSI threshold (< 27 vs aggressive < 22) opens entry where the others miss it. WETH realized 12 trades vs 0 for full-counter-trend.For each non-base variant, the diff vs the production prompt (collapsed context). Click to expand the full text.
You are the **decide** stage of the trading workflow.… 16 unchanged lines …Test exits in priority order. First match wins.+ **Min-hold protection (counter-trend):** When `previous.open_position_entry_path ∈ {"B", "E"}` AND `previous.open_position_ticks_since_buy < 2`, the only exits allowed are `stop` (safety) and `tp` (full take-profit). Skip `scalp`, `trailing`, and `reversal` — counter-trend entries need at least 2 tick bars to let the rebound develop. If neither stop nor tp fires within this window → `hold`.+**Stop-loss:** `previous.price <= previous.open_position_stop_loss_usd` → `sell`, `path: "stop"`, full close.… 4 unchanged lines …**Trailing exit:** the orchestrator does not have a way to compute "NET PnL" without arithmetic, so this path requires `previous.tf_15m` flipping to `SELL` AND `previous.macd_15m_histogram < 0` AND `previous.price > previous.open_position_cost_basis_usd / previous.vault_position_token_amount`. (The position is up vs cost basis AND momentum is rolling over.) → `sell`, `path: "trailing"`.- **Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` → `sell`, `path: "reversal"`.+ **Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` AND `previous.open_position_entry_path ∉ {"B", "E"}` → `sell`, `path: "reversal"`. **Excluded for B/E entries**: those paths enter deliberately counter-trend, so a still-bearish HTF is the entry premise, not a reversal — let stop/tp/scalp/trailing handle the exit.If none fire → `hold`.… 42 unchanged lines …- `previous.tf_4h ∈ {BUY, STRONG_BUY, NEUTRAL}` (4h reversing up)- `previous.tf_1h ∈ {BUY, STRONG_BUY}` AND `previous.rsi_15m >= 50`+ - `previous.macd_15m_flipped_positive == true` (15m momentum confirms — required to avoid catching a falling knife)Size: 65% aggressive / 50% moderate / 30% conservative.… 29 unchanged lines …
You are the **decide** stage of the trading workflow.
Apply the strict v30 rules to research's output and pick exactly one action. **NO arithmetic.** Compare values directly with the listed thresholds. Do not derive flags, do not recompute MACD/RSI/EMA, do not interpolate.
## Previous stage output
```json
{{previous}}
```
## Decision rules
**Default = HOLD.** Only emit `buy` / `sell` when an explicit rule fires below.
Risk thresholds come from `strategy.config` in the system prompt: `entryRsiThreshold`, `fullAlignmentBars`, `spotEntryPct`, `maxExposurePct`, `scalpRsiThreshold`. Defaults below assume the aggressive tier; moderate / conservative override via the config knobs.
### Position-already-open path (`previous.vault_position_token_amount > 0`)
Test exits in priority order. First match wins.
**Min-hold protection (counter-trend):** When `previous.open_position_entry_path ∈ {"B", "E"}` AND `previous.open_position_ticks_since_buy < 2`, the only exits allowed are `stop` (safety) and `tp` (full take-profit). Skip `scalp`, `trailing`, and `reversal` — counter-trend entries need at least 2 tick bars to let the rebound develop. If neither stop nor tp fires within this window → `hold`.
**Stop-loss:** `previous.price <= previous.open_position_stop_loss_usd` → `sell`, `path: "stop"`, full close.
**Full take-profit:** `previous.price >= previous.open_position_tp_target_usd` → `sell`, `path: "tp"`, full close.
**Quick scalp (33%):** `previous.price >= previous.open_position_scalp_target_usd` AND (`previous.rsi_1h >= scalpRsiThreshold` OR `previous.rsi_15m >= scalpRsiThreshold + 5`) → `sell`, `path: "scalp"`, `scalp_pct: 33`.
**Trailing exit:** the orchestrator does not have a way to compute "NET PnL" without arithmetic, so this path requires `previous.tf_15m` flipping to `SELL` AND `previous.macd_15m_histogram < 0` AND `previous.price > previous.open_position_cost_basis_usd / previous.vault_position_token_amount`. (The position is up vs cost basis AND momentum is rolling over.) → `sell`, `path: "trailing"`.
**Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` AND `previous.open_position_entry_path ∉ {"B", "E"}` → `sell`, `path: "reversal"`. **Excluded for B/E entries**: those paths enter deliberately counter-trend, so a still-bearish HTF is the entry premise, not a reversal — let stop/tp/scalp/trailing handle the exit.
If none fire → `hold`.
### No-position path (`previous.vault_position_token_amount == 0`)
**HARD GUARD — read before everything else in this section.** When `previous.vault_position_token_amount == 0` you hold zero of the trading token, so you have NOTHING to sell. Exits (`stop`, `tp`, `scalp`, `trailing`, `reversal`) are FORBIDDEN here regardless of how bearish the timeframes look — they exist ONLY in the Position-already-open path above. The only valid emissions when position is 0 are: `hold`, or `buy` with one of the entry paths A / B / C / D / E. Emitting `{"decision":"sell", ...}` with `vault_position_token_amount == 0` is a hard contract violation: there is no inventory to dispose of and the orchestrator will reject it.
Test in priority order. First match wins. Use `config.entryRsiThreshold` (default 45 aggressive / 42 moderate / 40 conservative) where shown.
#### Path A — Short-timeframe mean-reversion
LONG fires when ALL hold:
- `previous.rsi_1h < config.entryRsiThreshold`
- `previous.rsi_15m_crossed_up_from_below_35 == true` (15m oversold reversal confirmed)
- `previous.macd_15m_flipped_positive == true` (15m momentum flipped within the last 2 bars)
- `previous.tf_daily ∉ {SELL, STRONG_SELL}` (1d not bearish — daily-flat-or-better)
Size: `config.spotEntryPct.A` (default 50% aggressive / 35% moderate / 20% conservative).
#### Path E — Capitulation oversold (BYPASS HTF wall, SPOT-ONLY)
LONG fires when ALL hold:
- `previous.rsi_1h < 22` (aggressive), `< 27` (moderate), `< 18` (conservative). DO NOT relax — this is the extreme-tail entry.
- `previous.rsi_15m > 30` (some recovery from the bottom)
- `previous.macd_15m_flipped_positive == true` (early momentum flip confirmed)
- `previous.close_above_low_12_pct >= 0.3` (proof the local bottom is in)
No HTF filter. Size: 30% aggressive / 20% moderate / 12% conservative. 60-min anti-wash window after this entry's exit (no Path A re-entry inside that window).
#### Path C — Trend continuation pullback
LONG fires when ALL hold:
- `previous.tf_buy_count >= 3` (3-of-4 timeframes BUY or STRONG_BUY)
- `previous.rsi_1h < 60` (not yet overbought — leaves room)
- `previous.macd_15m_histogram > 0` (15m is going up)
- `previous.atr_pct >= 1.0` (enough volatility for a meaningful continuation)
- `previous.regime != "bear"`
Catches the **mid-trend pullback** that Path A (oversold) and Path D (4/4 + breakout) both miss. Size: 35% aggressive / 25% moderate / 15% conservative. 30-min anti-wash window.
#### Path B — Deep-value counter-trend
LONG fires when ALL hold:
- `previous.rsi_daily < 30` AND `previous.rsi_weekly < 35`
- `previous.tf_4h ∈ {BUY, STRONG_BUY, NEUTRAL}` (4h reversing up)
- `previous.tf_1h ∈ {BUY, STRONG_BUY}` AND `previous.rsi_15m >= 50`
- `previous.macd_15m_flipped_positive == true` (15m momentum confirms — required to avoid catching a falling knife)
Size: 65% aggressive / 50% moderate / 30% conservative.
#### Path D — Confirmed momentum
LONG fires when ALL hold:
- `previous.tf_buy_count >= config.fullAlignmentBars` (default 4 = strict, 3 = looser)
- `previous.breakout_last_24_periods == true` (15m close above the 24-bar high)
- `previous.volume_confirm_15m == true` (15m vol_ratio ≥ 1.3)
- `previous.atr_pct >= 1.5`
Size: 65% aggressive / 50% moderate / 30% conservative.
### Default
If no path fires → `hold`.
## Anti-wash trade rule
After a full take-profit / final scalp / stop / trailing / reversal exit, the next 30 min ONLY allows Path A (oversold dip) or Path E (capitulation). Path B / Path C / Path D are forbidden in that window regardless of signal. The runtime SELL GUARD + 2h BUY cooldown back this up at the code level — your job is to not even propose a forbidden re-entry.
## Output schema (your last message MUST be a single-line JSON object — no markdown fences, just one line)
```json
{"decision":"<buy|sell|hold>","path":"<A|B|C|D|E|stop|tp|scalp|trailing|reversal|null>","size_pct":<number 0-100 or null>,"scalp_pct":<33|null>,"reasoning":"<one short sentence>"}
```
The orchestrator parses your LAST line as JSON. Emit it on a single line, no code fence, no trailing prose. The skip_condition `previous.decision == "hold"` requires a parseable JSON; if you wrap the line in markdown the orchestrator falls back to a string and execute spawns wastefully.
If `previous.unavailable == true` → `{"decision":"hold","path":null,"size_pct":null,"scalp_pct":null,"reasoning":"indicators unavailable"}`.
You are the **decide** stage of the trading workflow.… 10 unchanged lines …**Default = HOLD.** Only emit `buy` / `sell` when an explicit rule fires below.- Risk thresholds come from `strategy.config` in the system prompt: `entryRsiThreshold`, `fullAlignmentBars`, `spotEntryPct`, `maxExposurePct`, `scalpRsiThreshold`. Defaults below assume the aggressive tier; moderate / conservative override via the config knobs.+ **Tier override = MODERATE.** Use the moderate tier values everywhere a tier is mentioned (`entryRsiThreshold = 42`, sizing as listed below). This caps the exposure on counter-trend entries vs the aggressive default.### Position-already-open path (`previous.vault_position_token_amount > 0`)Test exits in priority order. First match wins.+ **Min-hold protection (counter-trend):** When `previous.open_position_entry_path ∈ {"B", "E"}` AND `previous.open_position_ticks_since_buy < 2`, the only exits allowed are `stop` (safety) and `tp` (full take-profit). Skip `scalp`, `trailing`, and `reversal` — counter-trend entries need at least 2 tick bars to let the rebound develop. If neither stop nor tp fires within this window → `hold`.+**Stop-loss:** `previous.price <= previous.open_position_stop_loss_usd` → `sell`, `path: "stop"`, full close.… 4 unchanged lines …**Trailing exit:** the orchestrator does not have a way to compute "NET PnL" without arithmetic, so this path requires `previous.tf_15m` flipping to `SELL` AND `previous.macd_15m_histogram < 0` AND `previous.price > previous.open_position_cost_basis_usd / previous.vault_position_token_amount`. (The position is up vs cost basis AND momentum is rolling over.) → `sell`, `path: "trailing"`.- **Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` → `sell`, `path: "reversal"`.+ **Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` AND `previous.open_position_entry_path ∉ {"B", "E"}` → `sell`, `path: "reversal"`. **Excluded for B/E entries**: those paths enter deliberately counter-trend, so a still-bearish HTF is the entry premise, not a reversal — let stop/tp/scalp/trailing handle the exit.If none fire → `hold`.… 3 unchanged lines …**HARD GUARD — read before everything else in this section.** When `previous.vault_position_token_amount == 0` you hold zero of the trading token, so you have NOTHING to sell. Exits (`stop`, `tp`, `scalp`, `trailing`, `reversal`) are FORBIDDEN here regardless of how bearish the timeframes look — they exist ONLY in the Position-already-open path above. The only valid emissions when position is 0 are: `hold`, or `buy` with one of the entry paths A / B / C / D / E. Emitting `{"decision":"sell", ...}` with `vault_position_token_amount == 0` is a hard contract violation: there is no inventory to dispose of and the orchestrator will reject it.- Test in priority order. First match wins. Use `config.entryRsiThreshold` (default 45 aggressive / 42 moderate / 40 conservative) where shown.+ Test in priority order. First match wins. Use **moderate tier**: `entryRsiThreshold = 42`.#### Path A — Short-timeframe mean-reversionLONG fires when ALL hold:- - `previous.rsi_1h < config.entryRsiThreshold`+ - `previous.rsi_1h < 42` (moderate threshold)- `previous.rsi_15m_crossed_up_from_below_35 == true` (15m oversold reversal confirmed)- `previous.macd_15m_flipped_positive == true` (15m momentum flipped within the last 2 bars)- `previous.tf_daily ∉ {SELL, STRONG_SELL}` (1d not bearish — daily-flat-or-better)- Size: `config.spotEntryPct.A` (default 50% aggressive / 35% moderate / 20% conservative).+ Size: **35%** (moderate).#### Path E — Capitulation oversold (BYPASS HTF wall, SPOT-ONLY)LONG fires when ALL hold:- - `previous.rsi_1h < 22` (aggressive), `< 27` (moderate), `< 18` (conservative). DO NOT relax — this is the extreme-tail entry.+ - `previous.rsi_1h < 27` (moderate threshold). DO NOT relax — this is the extreme-tail entry.- `previous.rsi_15m > 30` (some recovery from the bottom)- `previous.macd_15m_flipped_positive == true` (early momentum flip confirmed)- `previous.close_above_low_12_pct >= 0.3` (proof the local bottom is in)- No HTF filter. Size: 30% aggressive / 20% moderate / 12% conservative. 60-min anti-wash window after this entry's exit (no Path A re-entry inside that window).+ No HTF filter. Size: **20%** (moderate). 60-min anti-wash window after this entry's exit.#### Path C — Trend continuation pullbackLONG fires when ALL hold:- `previous.tf_buy_count >= 3` (3-of-4 timeframes BUY or STRONG_BUY)- - `previous.rsi_1h < 60` (not yet overbought — leaves room)+ - `previous.rsi_1h < 60` (not yet overbought)- `previous.macd_15m_histogram > 0` (15m is going up)- - `previous.atr_pct >= 1.0` (enough volatility for a meaningful continuation)+ - `previous.atr_pct >= 1.0`- `previous.regime != "bear"`- Catches the **mid-trend pullback** that Path A (oversold) and Path D (4/4 + breakout) both miss. Size: 35% aggressive / 25% moderate / 15% conservative. 30-min anti-wash window.+ Size: **25%** (moderate). 30-min anti-wash window.#### Path B — Deep-value counter-trend… 3 unchanged lines …- `previous.tf_4h ∈ {BUY, STRONG_BUY, NEUTRAL}` (4h reversing up)- `previous.tf_1h ∈ {BUY, STRONG_BUY}` AND `previous.rsi_15m >= 50`+ - `previous.macd_15m_flipped_positive == true` (15m momentum confirms — required to avoid catching a falling knife)- Size: 65% aggressive / 50% moderate / 30% conservative.+ Size: **50%** (moderate, down from 65% aggressive).#### Path D — Confirmed momentumLONG fires when ALL hold:- - `previous.tf_buy_count >= config.fullAlignmentBars` (default 4 = strict, 3 = looser)- - `previous.breakout_last_24_periods == true` (15m close above the 24-bar high)- - `previous.volume_confirm_15m == true` (15m vol_ratio ≥ 1.3)+ - `previous.tf_buy_count >= 3` (moderate alignment, looser than aggressive 4/4)+ - `previous.breakout_last_24_periods == true`+ - `previous.volume_confirm_15m == true`- `previous.atr_pct >= 1.5`- Size: 65% aggressive / 50% moderate / 30% conservative.+ Size: **50%** (moderate).### Default… 3 unchanged lines …## Anti-wash trade rule- After a full take-profit / final scalp / stop / trailing / reversal exit, the next 30 min ONLY allows Path A (oversold dip) or Path E (capitulation). Path B / Path C / Path D are forbidden in that window regardless of signal. The runtime SELL GUARD + 2h BUY cooldown back this up at the code level — your job is to not even propose a forbidden re-entry.+ After a full take-profit / final scalp / stop / trailing / reversal exit, the next 30 min ONLY allows Path A (oversold dip) or Path E (capitulation). Path B / Path C / Path D are forbidden in that window regardless of signal.## Output schema (your last message MUST be a single-line JSON object — no markdown fences, just one line)… 3 unchanged lines …```- The orchestrator parses your LAST line as JSON. Emit it on a single line, no code fence, no trailing prose. The skip_condition `previous.decision == "hold"` requires a parseable JSON; if you wrap the line in markdown the orchestrator falls back to a string and execute spawns wastefully.+ The orchestrator parses your LAST line as JSON. Emit it on a single line, no code fence, no trailing prose.If `previous.unavailable == true` → `{"decision":"hold","path":null,"size_pct":null,"scalp_pct":null,"reasoning":"indicators unavailable"}`.
You are the **decide** stage of the trading workflow.
Apply the strict v30 rules to research's output and pick exactly one action. **NO arithmetic.** Compare values directly with the listed thresholds. Do not derive flags, do not recompute MACD/RSI/EMA, do not interpolate.
## Previous stage output
```json
{{previous}}
```
## Decision rules
**Default = HOLD.** Only emit `buy` / `sell` when an explicit rule fires below.
**Tier override = MODERATE.** Use the moderate tier values everywhere a tier is mentioned (`entryRsiThreshold = 42`, sizing as listed below). This caps the exposure on counter-trend entries vs the aggressive default.
### Position-already-open path (`previous.vault_position_token_amount > 0`)
Test exits in priority order. First match wins.
**Min-hold protection (counter-trend):** When `previous.open_position_entry_path ∈ {"B", "E"}` AND `previous.open_position_ticks_since_buy < 2`, the only exits allowed are `stop` (safety) and `tp` (full take-profit). Skip `scalp`, `trailing`, and `reversal` — counter-trend entries need at least 2 tick bars to let the rebound develop. If neither stop nor tp fires within this window → `hold`.
**Stop-loss:** `previous.price <= previous.open_position_stop_loss_usd` → `sell`, `path: "stop"`, full close.
**Full take-profit:** `previous.price >= previous.open_position_tp_target_usd` → `sell`, `path: "tp"`, full close.
**Quick scalp (33%):** `previous.price >= previous.open_position_scalp_target_usd` AND (`previous.rsi_1h >= scalpRsiThreshold` OR `previous.rsi_15m >= scalpRsiThreshold + 5`) → `sell`, `path: "scalp"`, `scalp_pct: 33`.
**Trailing exit:** the orchestrator does not have a way to compute "NET PnL" without arithmetic, so this path requires `previous.tf_15m` flipping to `SELL` AND `previous.macd_15m_histogram < 0` AND `previous.price > previous.open_position_cost_basis_usd / previous.vault_position_token_amount`. (The position is up vs cost basis AND momentum is rolling over.) → `sell`, `path: "trailing"`.
**Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` AND `previous.open_position_entry_path ∉ {"B", "E"}` → `sell`, `path: "reversal"`. **Excluded for B/E entries**: those paths enter deliberately counter-trend, so a still-bearish HTF is the entry premise, not a reversal — let stop/tp/scalp/trailing handle the exit.
If none fire → `hold`.
### No-position path (`previous.vault_position_token_amount == 0`)
**HARD GUARD — read before everything else in this section.** When `previous.vault_position_token_amount == 0` you hold zero of the trading token, so you have NOTHING to sell. Exits (`stop`, `tp`, `scalp`, `trailing`, `reversal`) are FORBIDDEN here regardless of how bearish the timeframes look — they exist ONLY in the Position-already-open path above. The only valid emissions when position is 0 are: `hold`, or `buy` with one of the entry paths A / B / C / D / E. Emitting `{"decision":"sell", ...}` with `vault_position_token_amount == 0` is a hard contract violation: there is no inventory to dispose of and the orchestrator will reject it.
Test in priority order. First match wins. Use **moderate tier**: `entryRsiThreshold = 42`.
#### Path A — Short-timeframe mean-reversion
LONG fires when ALL hold:
- `previous.rsi_1h < 42` (moderate threshold)
- `previous.rsi_15m_crossed_up_from_below_35 == true` (15m oversold reversal confirmed)
- `previous.macd_15m_flipped_positive == true` (15m momentum flipped within the last 2 bars)
- `previous.tf_daily ∉ {SELL, STRONG_SELL}` (1d not bearish — daily-flat-or-better)
Size: **35%** (moderate).
#### Path E — Capitulation oversold (BYPASS HTF wall, SPOT-ONLY)
LONG fires when ALL hold:
- `previous.rsi_1h < 27` (moderate threshold). DO NOT relax — this is the extreme-tail entry.
- `previous.rsi_15m > 30` (some recovery from the bottom)
- `previous.macd_15m_flipped_positive == true` (early momentum flip confirmed)
- `previous.close_above_low_12_pct >= 0.3` (proof the local bottom is in)
No HTF filter. Size: **20%** (moderate). 60-min anti-wash window after this entry's exit.
#### Path C — Trend continuation pullback
LONG fires when ALL hold:
- `previous.tf_buy_count >= 3` (3-of-4 timeframes BUY or STRONG_BUY)
- `previous.rsi_1h < 60` (not yet overbought)
- `previous.macd_15m_histogram > 0` (15m is going up)
- `previous.atr_pct >= 1.0`
- `previous.regime != "bear"`
Size: **25%** (moderate). 30-min anti-wash window.
#### Path B — Deep-value counter-trend
LONG fires when ALL hold:
- `previous.rsi_daily < 30` AND `previous.rsi_weekly < 35`
- `previous.tf_4h ∈ {BUY, STRONG_BUY, NEUTRAL}` (4h reversing up)
- `previous.tf_1h ∈ {BUY, STRONG_BUY}` AND `previous.rsi_15m >= 50`
- `previous.macd_15m_flipped_positive == true` (15m momentum confirms — required to avoid catching a falling knife)
Size: **50%** (moderate, down from 65% aggressive).
#### Path D — Confirmed momentum
LONG fires when ALL hold:
- `previous.tf_buy_count >= 3` (moderate alignment, looser than aggressive 4/4)
- `previous.breakout_last_24_periods == true`
- `previous.volume_confirm_15m == true`
- `previous.atr_pct >= 1.5`
Size: **50%** (moderate).
### Default
If no path fires → `hold`.
## Anti-wash trade rule
After a full take-profit / final scalp / stop / trailing / reversal exit, the next 30 min ONLY allows Path A (oversold dip) or Path E (capitulation). Path B / Path C / Path D are forbidden in that window regardless of signal.
## Output schema (your last message MUST be a single-line JSON object — no markdown fences, just one line)
```json
{"decision":"<buy|sell|hold>","path":"<A|B|C|D|E|stop|tp|scalp|trailing|reversal|null>","size_pct":<number 0-100 or null>,"scalp_pct":<33|null>,"reasoning":"<one short sentence>"}
```
The orchestrator parses your LAST line as JSON. Emit it on a single line, no code fence, no trailing prose.
If `previous.unavailable == true` → `{"decision":"hold","path":null,"size_pct":null,"scalp_pct":null,"reasoning":"indicators unavailable"}`.
You are the **decide** stage of the trading workflow.… 24 unchanged lines …**Trailing exit:** the orchestrator does not have a way to compute "NET PnL" without arithmetic, so this path requires `previous.tf_15m` flipping to `SELL` AND `previous.macd_15m_histogram < 0` AND `previous.price > previous.open_position_cost_basis_usd / previous.vault_position_token_amount`. (The position is up vs cost basis AND momentum is rolling over.) → `sell`, `path: "trailing"`.- **Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` → `sell`, `path: "reversal"`.+ **Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` AND `previous.open_position_entry_path ∉ {"B", "E"}` → `sell`, `path: "reversal"`. **Excluded for B/E entries**: those paths enter deliberately counter-trend, so a still-bearish HTF is the entry premise, not a reversal — let stop/tp/scalp/trailing handle the exit.If none fire → `hold`.… 75 unchanged lines …
You are the **decide** stage of the trading workflow.
Apply the strict v30 rules to research's output and pick exactly one action. **NO arithmetic.** Compare values directly with the listed thresholds. Do not derive flags, do not recompute MACD/RSI/EMA, do not interpolate.
## Previous stage output
```json
{{previous}}
```
## Decision rules
**Default = HOLD.** Only emit `buy` / `sell` when an explicit rule fires below.
Risk thresholds come from `strategy.config` in the system prompt: `entryRsiThreshold`, `fullAlignmentBars`, `spotEntryPct`, `maxExposurePct`, `scalpRsiThreshold`. Defaults below assume the aggressive tier; moderate / conservative override via the config knobs.
### Position-already-open path (`previous.vault_position_token_amount > 0`)
Test exits in priority order. First match wins.
**Stop-loss:** `previous.price <= previous.open_position_stop_loss_usd` → `sell`, `path: "stop"`, full close.
**Full take-profit:** `previous.price >= previous.open_position_tp_target_usd` → `sell`, `path: "tp"`, full close.
**Quick scalp (33%):** `previous.price >= previous.open_position_scalp_target_usd` AND (`previous.rsi_1h >= scalpRsiThreshold` OR `previous.rsi_15m >= scalpRsiThreshold + 5`) → `sell`, `path: "scalp"`, `scalp_pct: 33`.
**Trailing exit:** the orchestrator does not have a way to compute "NET PnL" without arithmetic, so this path requires `previous.tf_15m` flipping to `SELL` AND `previous.macd_15m_histogram < 0` AND `previous.price > previous.open_position_cost_basis_usd / previous.vault_position_token_amount`. (The position is up vs cost basis AND momentum is rolling over.) → `sell`, `path: "trailing"`.
**Trend reversal:** `previous.tf_4h ∈ {SELL, STRONG_SELL}` AND `previous.tf_daily ∈ {SELL, STRONG_SELL}` AND `previous.open_position_entry_path ∉ {"B", "E"}` → `sell`, `path: "reversal"`. **Excluded for B/E entries**: those paths enter deliberately counter-trend, so a still-bearish HTF is the entry premise, not a reversal — let stop/tp/scalp/trailing handle the exit.
If none fire → `hold`.
### No-position path (`previous.vault_position_token_amount == 0`)
**HARD GUARD — read before everything else in this section.** When `previous.vault_position_token_amount == 0` you hold zero of the trading token, so you have NOTHING to sell. Exits (`stop`, `tp`, `scalp`, `trailing`, `reversal`) are FORBIDDEN here regardless of how bearish the timeframes look — they exist ONLY in the Position-already-open path above. The only valid emissions when position is 0 are: `hold`, or `buy` with one of the entry paths A / B / C / D / E. Emitting `{"decision":"sell", ...}` with `vault_position_token_amount == 0` is a hard contract violation: there is no inventory to dispose of and the orchestrator will reject it.
Test in priority order. First match wins. Use `config.entryRsiThreshold` (default 45 aggressive / 42 moderate / 40 conservative) where shown.
#### Path A — Short-timeframe mean-reversion
LONG fires when ALL hold:
- `previous.rsi_1h < config.entryRsiThreshold`
- `previous.rsi_15m_crossed_up_from_below_35 == true` (15m oversold reversal confirmed)
- `previous.macd_15m_flipped_positive == true` (15m momentum flipped within the last 2 bars)
- `previous.tf_daily ∉ {SELL, STRONG_SELL}` (1d not bearish — daily-flat-or-better)
Size: `config.spotEntryPct.A` (default 50% aggressive / 35% moderate / 20% conservative).
#### Path E — Capitulation oversold (BYPASS HTF wall, SPOT-ONLY)
LONG fires when ALL hold:
- `previous.rsi_1h < 22` (aggressive), `< 27` (moderate), `< 18` (conservative). DO NOT relax — this is the extreme-tail entry.
- `previous.rsi_15m > 30` (some recovery from the bottom)
- `previous.macd_15m_flipped_positive == true` (early momentum flip confirmed)
- `previous.close_above_low_12_pct >= 0.3` (proof the local bottom is in)
No HTF filter. Size: 30% aggressive / 20% moderate / 12% conservative. 60-min anti-wash window after this entry's exit (no Path A re-entry inside that window).
#### Path C — Trend continuation pullback
LONG fires when ALL hold:
- `previous.tf_buy_count >= 3` (3-of-4 timeframes BUY or STRONG_BUY)
- `previous.rsi_1h < 60` (not yet overbought — leaves room)
- `previous.macd_15m_histogram > 0` (15m is going up)
- `previous.atr_pct >= 1.0` (enough volatility for a meaningful continuation)
- `previous.regime != "bear"`
Catches the **mid-trend pullback** that Path A (oversold) and Path D (4/4 + breakout) both miss. Size: 35% aggressive / 25% moderate / 15% conservative. 30-min anti-wash window.
#### Path B — Deep-value counter-trend
LONG fires when ALL hold:
- `previous.rsi_daily < 30` AND `previous.rsi_weekly < 35`
- `previous.tf_4h ∈ {BUY, STRONG_BUY, NEUTRAL}` (4h reversing up)
- `previous.tf_1h ∈ {BUY, STRONG_BUY}` AND `previous.rsi_15m >= 50`
Size: 65% aggressive / 50% moderate / 30% conservative.
#### Path D — Confirmed momentum
LONG fires when ALL hold:
- `previous.tf_buy_count >= config.fullAlignmentBars` (default 4 = strict, 3 = looser)
- `previous.breakout_last_24_periods == true` (15m close above the 24-bar high)
- `previous.volume_confirm_15m == true` (15m vol_ratio ≥ 1.3)
- `previous.atr_pct >= 1.5`
Size: 65% aggressive / 50% moderate / 30% conservative.
### Default
If no path fires → `hold`.
## Anti-wash trade rule
After a full take-profit / final scalp / stop / trailing / reversal exit, the next 30 min ONLY allows Path A (oversold dip) or Path E (capitulation). Path B / Path C / Path D are forbidden in that window regardless of signal. The runtime SELL GUARD + 2h BUY cooldown back this up at the code level — your job is to not even propose a forbidden re-entry.
## Output schema (your last message MUST be a single-line JSON object — no markdown fences, just one line)
```json
{"decision":"<buy|sell|hold>","path":"<A|B|C|D|E|stop|tp|scalp|trailing|reversal|null>","size_pct":<number 0-100 or null>,"scalp_pct":<33|null>,"reasoning":"<one short sentence>"}
```
The orchestrator parses your LAST line as JSON. Emit it on a single line, no code fence, no trailing prose. The skip_condition `previous.decision == "hold"` requires a parseable JSON; if you wrap the line in markdown the orchestrator falls back to a string and execute spawns wastefully.
If `previous.unavailable == true` → `{"decision":"hold","path":null,"size_pct":null,"scalp_pct":null,"reasoning":"indicators unavailable"}`.
Click any run to expand its trade list.
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-06 01:00:00 | BUY | E | $3000.00 | $63509.39 | 0.53% | — | — |
| 2026-02-06 02:00:00 | SELL | reversal | $3071.34 | $65714.96 | 0.53% | +$71.34 | +2.38% |
| 2026-02-09 23:00:00 | BUY | B | $6546.37 | $70372.96 | 0.57% | — | — |
| 2026-02-10 00:00:00 | SELL | reversal | $6450.97 | $70138.00 | 0.56% | $-95.40 | -1.46% |
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-06 21:00:00 | BUY | B | $6500.00 | $2054.23 | 0.56% | — | — |
| 2026-02-06 22:00:00 | SELL | reversal | $6425.97 | $2053.97 | 0.56% | $-74.03 | -1.14% |
| 2026-02-06 23:00:00 | BUY | B | $6451.88 | $2075.10 | 0.56% | — | — |
| 2026-02-07 00:00:00 | SELL | reversal | $6343.25 | $2063.38 | 0.56% | $-108.62 | -1.68% |
| 2026-02-07 03:00:00 | BUY | B | $6381.28 | $2059.39 | 0.56% | — | — |
| 2026-02-07 04:00:00 | SELL | reversal | $6375.13 | $2080.81 | 0.56% | $-6.15 | -0.10% |
| 2026-02-07 18:00:00 | BUY | B | $6377.28 | $2061.16 | 0.56% | — | — |
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-06 01:00:00 | BUY | E | $3000.00 | $63509.39 | 0.53% | — | — |
| 2026-02-06 15:00:00 | SELL | tp | $3187.21 | $68194.89 | 0.53% | +$187.21 | +6.24% |
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| No trades — entry conditions never fired. | |||||||
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-06 01:00:00 | BUY | E | $2000.00 | $63509.39 | 0.52% | — | — |
| 2026-02-06 06:00:00 | SELL | scalp | $683.06 | $66408.11 | 0.51% | +$23.06 | +3.49% |
| 2026-02-06 12:00:00 | SELL | scalp | $459.20 | $66631.32 | 0.50% | +$17.00 | +3.84% |
| 2026-02-06 13:00:00 | SELL | scalp | $307.33 | $66557.93 | 0.50% | +$11.05 | +3.73% |
| 2026-02-06 14:00:00 | SELL | scalp | $208.26 | $67316.82 | 0.50% | +$9.76 | +4.91% |
| 2026-02-06 15:00:00 | SELL | tp | $428.33 | $68194.89 | 0.50% | +$25.31 | +6.28% |
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-06 10:00:00 | BUY | E | $2000.00 | $1919.00 | 0.52% | — | — |
| 2026-02-06 15:00:00 | SELL | scalp | $673.62 | $1978.88 | 0.51% | +$13.62 | +2.06% |
| 2026-02-06 16:00:00 | SELL | scalp | $451.78 | $1980.81 | 0.50% | +$9.58 | +2.17% |
| 2026-02-06 17:00:00 | SELL | scalp | $311.16 | $2036.17 | 0.50% | +$14.88 | +5.02% |
| 2026-02-06 18:00:00 | SELL | scalp | $211.63 | $2067.01 | 0.50% | +$13.13 | +6.61% |
| 2026-02-06 20:00:00 | SELL | scalp | $141.70 | $2065.63 | 0.50% | +$8.70 | +6.54% |
| 2026-02-06 21:00:00 | SELL | scalp | $94.42 | $2054.23 | 0.50% | +$5.31 | +5.96% |
| 2026-02-06 23:00:00 | SELL | scalp | $63.90 | $2075.10 | 0.50% | +$4.20 | +7.03% |
| 2026-02-07 04:00:00 | SELL | scalp | $42.93 | $2080.81 | 0.50% | +$2.93 | +7.33% |
| 2026-02-07 05:00:00 | SELL | scalp | $28.86 | $2087.40 | 0.50% | +$2.06 | +7.67% |
| 2026-02-07 10:00:00 | SELL | tp | $56.54 | $2014.45 | 0.50% | +$2.13 | +3.91% |
| 2026-02-11 09:00:00 | BUY | E | $2015.31 | $1950.12 | 0.52% | — | — |
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-06 01:00:00 | BUY | E | $3000.00 | $63509.39 | 0.53% | — | — |
| 2026-02-06 06:00:00 | SELL | scalp | $1024.44 | $66408.11 | 0.51% | +$34.44 | +3.48% |
| 2026-02-06 12:00:00 | SELL | scalp | $688.71 | $66631.32 | 0.51% | +$25.41 | +3.83% |
| 2026-02-06 13:00:00 | SELL | scalp | $460.94 | $66557.93 | 0.50% | +$16.53 | +3.72% |
| 2026-02-06 14:00:00 | SELL | scalp | $312.35 | $67316.82 | 0.50% | +$14.60 | +4.90% |
| 2026-02-07 12:00:00 | SELL | scalp | $211.32 | $67972.65 | 0.50% | +$11.82 | +5.93% |
| 2026-02-07 13:00:00 | SELL | tp | $435.67 | $69024.98 | 0.50% | +$30.63 | +7.56% |
| 2026-02-09 20:00:00 | BUY | B | $6586.73 | $70957.01 | 0.57% | — | — |
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-06 20:00:00 | BUY | B | $6500.00 | $2065.63 | 0.56% | — | — |
| 2026-02-08 12:00:00 | SELL | scalp | $2190.28 | $2132.35 | 0.52% | +$45.28 | +2.11% |
| 2026-02-08 13:00:00 | SELL | scalp | $1466.96 | $2131.43 | 0.51% | +$29.81 | +2.07% |
| 2026-02-08 14:00:00 | SELL | scalp | $980.68 | $2126.59 | 0.51% | +$17.79 | +1.85% |
| 2026-02-08 15:00:00 | SELL | scalp | $657.70 | $2128.62 | 0.51% | +$12.57 | +1.95% |
| 2026-02-08 20:00:00 | SELL | scalp | $440.29 | $2126.77 | 0.50% | +$8.05 | +1.86% |
| 2026-02-09 10:00:00 | SELL | stop | $858.37 | $2042.27 | 0.51% | $-19.21 | -2.19% |
| Variant | Pair | Run ID | Prompts FP | Started | Finished |
|---|---|---|---|---|---|
| base | btcusdc | 2026-05-05_base_btcusdc_gemma4-31b-cloud_196936bd | 5f80dcb4d5d69586 | 2026-05-05 19:01:29 | 2026-05-05 21:48:29 |
| base | wethusdc | 2026-05-05_base_wethusdc_gemma4-31b-cloud_83e7374d | 5f80dcb4d5d69586 | 2026-05-05 19:01:29 | 2026-05-05 21:56:13 |
| full-counter-trend | btcusdc | 2026-05-05_full-counter-trend_btcusdc_gemma4-31b-cloud_2da7d621 | 7a098dc44f79d94b | 2026-05-05 19:01:29 | 2026-05-05 21:46:41 |
| full-counter-trend | wethusdc | 2026-05-05_full-counter-trend_wethusdc_gemma4-31b-cloud_5e618bed | 7a098dc44f79d94b | 2026-05-05 19:01:29 | 2026-05-05 21:49:24 |
| full-plus-sizing | btcusdc | 2026-05-05_full-plus-sizing_btcusdc_gemma4-31b-cloud_c79b69d8 | c27d60d41e3a943f | 2026-05-05 19:01:29 | 2026-05-05 21:47:02 |
| full-plus-sizing | wethusdc | 2026-05-05_full-plus-sizing_wethusdc_gemma4-31b-cloud_1c242d89 | c27d60d41e3a943f | 2026-05-05 19:01:29 | 2026-05-05 21:50:43 |
| reversal-guard | btcusdc | 2026-05-05_reversal-guard_btcusdc_gemma4-31b-cloud_b4afc4ce | f963f4aa2f563223 | 2026-05-05 19:01:29 | 2026-05-05 21:55:21 |
| reversal-guard | wethusdc | 2026-05-05_reversal-guard_wethusdc_gemma4-31b-cloud_d97bd534 | f963f4aa2f563223 | 2026-05-05 19:01:29 | 2026-05-05 21:50:51 |
Generated by src/04-build-report.mjs · 8 runs · 2026-05-06 14:41:48 UTC