Variant comparison across BTC + WETH on identical window.
| # | Variant | Trades | Σ PnL ($) | Avg PnL % | Distribution |
|---|---|---|---|---|---|
| 1 | base | 0 | +$0.00 | +0.00% | |
| 2 | full-counter-trend | 0 | +$0.00 | +0.00% | |
| 3 | full-plus-sizing | 4 | $-37.00 | -0.18% | |
| 4 | no-bear-pathB | 4 | $-37.00 | -0.18% |
| Variant | Pair | Trades | Final $ | PnL ($) | PnL % |
|---|---|---|---|---|---|
| base | btcusdc | 0 | $10000.00 | +$0.00 | +0.00% |
| base | wethusdc | 0 | $10000.00 | +$0.00 | +0.00% |
| full-counter-trend | btcusdc | 0 | $10000.00 | +$0.00 | +0.00% |
| full-counter-trend | wethusdc | 0 | $10000.00 | +$0.00 | +0.00% |
| full-plus-sizing | btcusdc | 2 | $10021.21 | +$21.21 | +0.21% |
| full-plus-sizing | wethusdc | 2 | $9941.79 | $-58.21 | -0.58% |
| no-bear-pathB | btcusdc | 2 | $10021.21 | +$21.21 | +0.21% |
| no-bear-pathB | wethusdc | 2 | $9941.79 | $-58.21 | -0.58% |
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.… 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)+ - `previous.regime != "bear"` (DO NOT fire Path B inside a bear regime — historical evidence shows Path B + bear → reversal exit loop with net negative expectation)- 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)
- `previous.regime != "bear"` (DO NOT fire Path B inside a bear regime — historical evidence shows Path B + bear → reversal exit loop with net negative expectation)
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"}`.
Click any run to expand its trade list.
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| No trades — entry conditions never fired. | |||||||
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| No trades — entry conditions never fired. | |||||||
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| No trades — entry conditions never fired. | |||||||
| 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 08:00:00 | SELL | trailing | $2021.21 | $64856.00 | 0.52% | +$21.21 | +1.06% |
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-01 18:00:00 | BUY | E | $2000.00 | $2313.96 | 0.52% | — | — |
| 2026-02-02 00:00:00 | SELL | stop | $1941.79 | $2270.15 | 0.52% | $-58.21 | -2.91% |
| 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 08:00:00 | SELL | trailing | $2021.21 | $64856.00 | 0.52% | +$21.21 | +1.06% |
| sim_ts | side | path | amount $ | price $ | cost % | realized $ | realized % |
|---|---|---|---|---|---|---|---|
| 2026-02-01 18:00:00 | BUY | E | $2000.00 | $2313.96 | 0.52% | — | — |
| 2026-02-02 00:00:00 | SELL | stop | $1941.79 | $2270.15 | 0.52% | $-58.21 | -2.91% |
| Variant | Pair | Run ID | Prompts FP | Started | Finished |
|---|---|---|---|---|---|
| base | btcusdc | 2026-05-06_base_btcusdc_gpt-oss-120b_2ecc3533 | 5f80dcb4d5d69586 | 2026-05-06 16:48:11 | 2026-05-06 21:59:58 |
| base | wethusdc | 2026-05-06_base_wethusdc_gpt-oss-120b_f4a0200c | 5f80dcb4d5d69586 | 2026-05-06 16:48:11 | 2026-05-06 21:53:12 |
| full-counter-trend | btcusdc | 2026-05-06_full-counter-trend_btcusdc_gpt-oss-120b_d9266341 | 7a098dc44f79d94b | 2026-05-06 16:48:11 | 2026-05-06 21:49:05 |
| full-counter-trend | wethusdc | 2026-05-06_full-counter-trend_wethusdc_gpt-oss-120b_95575125 | 7a098dc44f79d94b | 2026-05-06 16:48:11 | 2026-05-06 21:45:35 |
| full-plus-sizing | btcusdc | 2026-05-06_full-plus-sizing_btcusdc_gpt-oss-120b_31fa40ad | c27d60d41e3a943f | 2026-05-06 16:48:11 | 2026-05-06 21:57:43 |
| full-plus-sizing | wethusdc | 2026-05-06_full-plus-sizing_wethusdc_gpt-oss-120b_a23a219b | c27d60d41e3a943f | 2026-05-06 16:48:11 | 2026-05-06 21:45:11 |
| no-bear-pathB | btcusdc | 2026-05-06_no-bear-pathB_btcusdc_gpt-oss-120b_d2d72fd5 | 1c4fe6a536c9d03a | 2026-05-06 16:48:11 | 2026-05-06 21:59:30 |
| no-bear-pathB | wethusdc | 2026-05-06_no-bear-pathB_wethusdc_gpt-oss-120b_b90dc6d4 | 1c4fe6a536c9d03a | 2026-05-06 16:48:11 | 2026-05-06 21:55:23 |
Generated by src/04-build-report.mjs · 8 runs · 2026-05-07 05:14:53 UTC