create-strategy · v2.0.0 · 2026-09-22 · sha256 1456b953919c4336

create-strategy v2.0.0A

Immutable. This exact content is served forever at /api/v1/blob/1456b953919c4336.

---
name: create-strategy
description: >
  Guide for creating a new Etemaro LP strategy from scratch or adapting an existing preset.
  Use this skill whenever a user asks to "create a strategy", "add a new strategy", "set up a strategy",
  "configure LP strategy", "what strategy should I use", "tweak my strategy", "change my strategy", or any
  variant involving Etemaro strategy setup, customization, or deployment configuration. Also trigger when the
  user describes a trading goal (e.g. "I want to go bullish on SOL", "I want to earn fees on a stable pair",
  "I have a volatile token") and needs it translated into a concrete config. Strategies are immutable by
  default: this skill always creates a NEW strategy (new id) and a NEW config file, and never edits or
  overwrites an existing strategy without explicit user confirmation.
metadata:
  version: 2.0.0
  author: etemaro
license: MIT
---

# Create Strategy — Etemaro

This skill walks an agent through creating or selecting an LP strategy for the Etemaro trading daemon,
then generates a ready-to-use config patch and (when needed) a new strategy-library entry.

---

## Strategy Immutability (Non-Negotiable)

Strategies and their config files are **immutable by default**.

- **"Create a strategy" ⇒ always create a NEW strategy.** New unique library `id`, new versioned config
  file. Never rename, overwrite, or edit an existing entry or config.
- Applies to: entries in `config/shared/strategy-library.json`, and config files under
  `config/instances/`.
- **Bundled presets are read-only.** `config/shared/strategy-library.shared.json` (and its source of truth
  `packages/core/src/domain/strategy-library-shared.ts`) ship with the repo. Never edit them in place —
  copy to a new private entry instead.
- **If the agent believes an existing strategy needs to change** (market conditions shifted, performance is
  bad, a filter is wrong):
  1. **STOP.** Do not edit.
  2. State the exact field(s), current value(s), and proposed value(s).
  3. Give the reason and evidence (logs, metrics, `file:line`).
  4. **Ask for explicit user confirmation.**
  5. Recommend creating a **new variant** (copy the old entry/config → new id + new config file) so the
     original stays intact and comparable. This is the default suggestion, even with confirmation.

### Only exception: missing / malformed required data

When a strategy or config is **missing required data or is malformed**, fix the minimum needed to restore
validity — no separate confirmation gate, but report exactly what changed:

- Missing required string `id` or `name`.
- Invalid JSON / a parse error.
- `strategy.activeStrategyId` pointing at a non-existent library id.
- Active strategy missing `smartWalletListId` while the smart-wallet entry source is active.
- Legacy snake_case keys (`lp_strategy`, `token_criteria`, `exit.take_profit_pct`, …).
- Missing `screening.market.enabled` / `screening.smartWallets.enabled` so no entry source resolves.

While fixing, **do not change intent or behavior** — only restore the missing/broken data.

### Decision flow

```text
User asks to change an existing strategy/config?
  ├─ missing or invalid required data?  → fix in place (minimal), report the change
  └─ otherwise                          → propose change → ask confirmation → recommend NEW variant

User asks to create or tune a strategy?
  → always create a NEW library id + a NEW config file
```

### Why this matters

Library entries are mostly **metadata** — see the next section. Editing an entry in place usually does not
change bot behavior; behavior lives in the agent config. So "changing" a strategy means shipping a new
config + a new entry, which also preserves the ability to compare runs.

---

## What Actually Controls Runtime Behavior

Read this before "adjusting a strategy" — it determines where a change has to go.

| Setting | Where | Effect |
| --- | --- | --- |
| `strategy.activeStrategyId` | agent config | Selects the active library entry (context + smart-wallet list). **USED** |
| `strategy.strategyMeteora` | agent config | Actual deploy shape: `spot` \| `curve` \| `bid_ask`. **USED** |
| `strategy.minBinsBelow` / `maxBinsBelow` / `defaultBinsBelow` / `minSafeBinsBelow` | agent config | Bin range below active bin. **USED** |
| `management.*` | agent config | Stop-loss, take-profit, trailing, sizing, cooldowns. **USED** |
| `screening.common` / `market` / `smartWallets` | agent config | Pool filters and entry source. **USED** |
| `opportunity.*` | agent config | Opportunity poller + smart-wallet score bonus. **USED** |
| `risk.maxPositions` / `maxDeployAmount` | agent config | Global capital caps. **USED** |
| `smartWalletListId` | library entry | Startup validation + smart-wallet screening. **USED** |
| `lpStrategy`, `tokenCriteria`, `range`, `exit.takeProfitPct`, `bestFor`, `raw` | library entry | Stored / descriptive. `condition`, `notes`, `bestFor` feed the LLM strategy context; the rest are **not** read at deploy. |

There is **no `bins_above` config field** and no ratio field: directional bias is expressed through
`strategyMeteora` (shape) plus the `*BinsBelow` counts.

---

## Phase 1: Gather Minimum Required Information

Collect the following from the user. Ask as a single, concise message — don't split into separate turns
unless an answer is ambiguous. Extract anything already given in the conversation and ask only for what is
missing.

### Checklist (all required)

1. **Directional view** — bullish, bearish, or neutral on the token?
2. **Token type** — volatile/narrative, stable/high-volume pool, or blue-chip (SOL, ETH)?
3. **Risk tolerance** — conservative (tight stop-loss, quick exits), moderate, aggressive (hold through
   dips, re-seed)?
4. **Capital per position (SOL)** — how much SOL per position? (Drives `deployAmountSol` / `positionSizePct`.)
5. **Exit preference** — take profit at a %/threshold, trail the price, or let it run and re-seed?
6. **Smart-wallet tracking** — gate entry on smart-wallet presence (KOL/alpha wallets)? Affects
   `opportunity.smartWalletScoreBonus` and the opportunity poller.

---

## Phase 2: Review the Strategy Library

The library is **two files, merged at runtime**:

| File | Contents | Editable? |
| --- | --- | --- |
| `config/shared/strategy-library.shared.json` | Bundled open-source presets (5) | **Read-only** |
| `config/shared/strategy-library.json` | Private/user strategies (where new entries go) | New entries only |

Merged by `StrategyLibraryManager.loadMerged()` (`packages/core/src/domain/strategy-library.ts:76-108`):
private **overrides** shared on an id collision and logs a warning. Prefer private entries first, then
shared presets; only create something new if nothing fits.

Read both files. Bundled presets:

| ID | Name | LP Shape | Best For |
| --- | --- | --- | --- |
| `custom_ratio_spot` | Custom Ratio Spot | spot | Directional bias, earn fees both ways |
| `single_sided_reseed` | Single-Sided Bid-Ask + Re-seed | bid_ask | Volatile tokens, DCA-out on dip |
| `fee_compounding` | Fee Compounding | any | Stable volume pools, compounding yield |
| `multi_layer` | Multi-Layer | mixed | Custom distributions, one position |
| `partial_harvest` | Partial Harvest | any | High-fee pools, incremental profit-taking |

Private examples already present: `copy_trade_lag`, `smart_wallet_follow`
(see `docs/strategies/README-smart-wallet-follow.md` for a worked example).

### Recommendation Logic

Map the user's intent to an existing strategy **first**. Only propose a new one if no existing strategy
fits.

| User Intent | Recommended Strategy |
| --- | --- |
| Bullish / bearish directional view | `custom_ratio_spot` |
| Volatile token, exit on dump | `single_sided_reseed` |
| Stable pair, maximize yield | `fee_compounding` |
| Custom bin distribution | `multi_layer` |
| Lock in gains incrementally | `partial_harvest` |
| Neutral / range-bound | `fee_compounding` or `multi_layer` |

Present the recommendation with a one-sentence rationale. Example:

> "Based on your bullish view, I'd recommend `custom_ratio_spot` — it places more liquidity below the
> current price so you earn fees as the token rises, with a shape that leans into the move."

Then state the immutability rule and ask: **"Use this existing strategy in a new config, or create a new
strategy entry from scratch?"** Either way a **new config file** is produced.

---

## Phase 3: Smart-Wallet Decision

Ask (if not already answered in Phase 1):

> "Do you want to track smart wallets (KOL/alpha wallets) for this strategy? If enabled, the opportunity
> poller gives a score bonus to pools where tracked wallets are LPs, letting the agent enter pools it
> would otherwise skip."

Canonical config fields (nested under `opportunity` — the flat `opportunityPollEnabled` /
`opportunitySmartWalletBonus` / `opportunityMinScore` names are legacy aliases only):

```json
"opportunity": {
  "enabled": true,
  "minScore": 40,
  "smartWalletScoreBonus": 20
}
```

- **Yes** → `opportunity.enabled: true`, `opportunity.smartWalletScoreBonus: 20` (or higher). Set
  `smartWalletListId` on the new library entry and make sure that list exists in
  `config/shared/smart-wallets.json`. Populate via Telegram:
  `add smart wallet <address> name=<label> category=alpha type=lp`.
- **No** → `opportunity.smartWalletScoreBonus: 0`.

**Entry source** is derived, not set directly: `Config.ts:96` computes
`entrySource = screening.market.enabled ? 'market' : 'smart_wallets'`. Exactly one of
`screening.market.enabled` / `screening.smartWallets.enabled` must be `true`.

- `entrySource: market` → smart wallets are an optional boost; a missing `smartWalletListId` only skips the
  bonus.
- `entrySource: smart_wallets` → the active strategy **must** define `smartWalletListId`, or startup
  validation fails.

---

## Phase 4: Build the Config Patch

### Document reading order

Read these **in this order** before generating config — each layers on the previous:

1. `docs/ARCHITECTURE.md` — how the strategy library feeds deploy decisions
2. `docs/CONFIGURATION.md` — full field reference (types, defaults, env vars)
3. `config/templates/agent-config.example.json` — canonical template

### How to generate

**Copy the entire `config/templates/agent-config.example.json` first**, then change only the fields that
differ. This guarantees no required field is missed. The schema is strict:
`packages/core/src/config/schema.ts` — unknown keys fail validation.

Sections you will normally change:

#### `strategy` (required)

```json
"strategy": {
  "activeStrategyId": "<new_or_existing_id>",
  "strategyMeteora": "bid_ask|spot|curve",
  "minBinsBelow": 35,
  "maxBinsBelow": 69,
  "defaultBinsBelow": 69,
  "minSafeBinsBelow": 10
}
```

- `activeStrategyId` selects the library entry (must exist in the merged library).
- `strategyMeteora` is the deploy shape: `spot` (centered), `bid_ask` (edge-weighted / below),
  `curve` (curve).
- Bias: bullish/bearish is shaped by `strategyMeteora` + the `*BinsBelow` counts (and, for
  `single_sided_reseed`, token-only entry). There is no `bins_above` field.

#### `management` (risk / exit)

| Risk Level | `stopLossPct` | `takeProfitPct` | `trailingTakeProfit` | `outOfRangeWaitMinutes` |
| --- | --- | --- | --- | --- |
| Conservative | -15 | 3 | true | 15 |
| Moderate | -30 | 5 | true | 30 |
| Aggressive | -50 | 10 | false | 60 |

Also set: `deployAmountSol` (from capital-per-position), `positionSizePct` (deployAmountSol /
available SOL), and trailing fields `trailingTriggerPct` / `trailingDropPct` when trailing is on.

#### `opportunity` (smart-wallet gating)

```json
"opportunity": { "enabled": true, "minScore": 40, "smartWalletScoreBonus": 20 }
```

#### `screening` (token-type filters)

Filters live under **`screening.common`** (plus the `market` / `smartWallets` source blocks):

```json
"screening": {
  "common": { "minOrganic": 60, "minHolders": 500, "minBinStep": 80, "maxBinStep": 125,
              "minTvl": 10000, "maxTvl": 150000 },
  "market": { "enabled": true },
  "smartWallets": { "enabled": false }
}
```

| Token Type | `minOrganic` | `minHolders` | `minBinStep` | `maxBinStep` | `minTvl` | `maxTvl` |
| --- | --- | --- | --- | --- | --- | --- |
| Volatile/narrative | 60 | 500 | 80 | 125 | 10000 | 150000 |
| Stable/high-volume | 70 | 2000 | 1 | 50 | 100000 | 5000000 |
| Blue-chip (SOL/ETH) | 80 | 5000 | 1 | 25 | 500000 | 10000000 |

#### `risk` (global caps)

```json
"risk": { "maxPositions": 1, "maxDeployAmount": 50 }
```

### New strategy-library entry (only when creating)

Add a **new** entry under `strategies` in `config/shared/strategy-library.json`. Canonical schema
(`packages/core/src/domain/strategy-validation.ts:56-97`):

```json
{
  "id": "<new_snake_case_id>",
  "name": "<Human Readable Name>",
  "author": "custom",
  "smartWalletListId": "<list id — omit when unused>",
  "lpStrategy": "bid_ask|spot|curve|mixed|any",
  "tokenCriteria": { "notes": "<when to use>" },
  "entry": { "condition": "<entry trigger>", "singleSide": "sol|token", "notes": "<deployment notes>" },
  "range": { "type": "tight|default|wide|panda|custom", "binsBelowPct": 100, "notes": "<range notes>" },
  "exit": { "takeProfitPct": 10, "notes": "<exit rules>" },
  "bestFor": "<one-line summary>",
  "raw": "<optional source text>",
  "addedAt": "<ISO timestamp>",
  "updatedAt": "<ISO timestamp>"
}
```

Rules:

- The library **key must equal `id`** (lookup uses the key).
- `id` is slugified on save (lowercase, `_`, alphanumeric) — use `snake_case`.
- Nested allowed keys — `tokenCriteria`: `min_mcap`, `min_age_days`, `requires_kol`, `notes`;
  `entry`: `condition`, `price_change_threshold_pct`, `singleSide`, `notes`;
  `range`: `type`, `binsBelowPct`, `notes`; `exit`: `takeProfitPct`, `notes`.
- Snake_case top-level keys are **ignored** (`lp_strategy`, `added_at`, …) — always camelCase.
- Do **not** modify existing entries.

---

## Phase 5: Output

Present the result as clearly labeled blocks.

### Block A — Config patch file

Write a **new** file (never overwrite an existing one):

`config/instances/agent-config.<major-strategy-short-idea>.v<YYMMDD>-<counter>.json`

e.g. `config/instances/agent-config.smart-wallet-follow.v260913-1.json`. If the counter already exists, bump it.

The file must be a complete valid JSON config (all template fields, overrides applied). Run it with:

```bash
# safe dry-run first
AGENT_CONFIG_PATH=config/instances/<file> npm run dev
# live (after dry-run verification)
AGENT_CONFIG_PATH=config/instances/<file> npm start
```

### Block B — Strategy library entry (only if new)

Show the full JSON entry to append under `strategies` in `config/shared/strategy-library.json`. The
new strategy is activated by setting `strategy.activeStrategyId` to its id in the new config file (or via
the `set_active_strategy` tool). There is no `set-active-strategy` CLI command.

### Block C — Verification checklist

```text
[ ] Config validates:  AGENT_CONFIG_PATH=config/instances/<file> npm run validate:config
[ ] Strategy validates: npm run validate:strategy -- config/shared/strategy-library.json
[ ] Env vars: HELIUS_API_KEY (wallet/valuation), JUPITER_API_KEY (swaps), RPC_URL (optional),
              LLM_API_KEY / LLM_MODEL (or a direct llm.defaultModel)
[ ] dryRun: true  <- test before going live
[ ] Smart wallets: <populated list ID / not needed>
[ ] activeStrategyId: <id>
[ ] Original strategy/config left untouched (immutability)
```

---

## Reference Quick Map

| Need | Read |
| --- | --- |
| All config fields + types + env vars | `docs/CONFIGURATION.md` |
| Field defaults / canonical template | `config/templates/agent-config.example.json` |
| Bundled presets (read-only) | `config/shared/strategy-library.shared.json` |
| Private strategies (new entries go here) | `config/shared/strategy-library.json` |
| Strategy schema + validation rules | `packages/core/src/domain/strategy-validation.ts` |
| Merge / active-pointer behavior | `packages/core/src/domain/strategy-library.ts` |
| Worked strategy example | `docs/strategies/README-smart-wallet-follow.md` |
| Smart-wallet tracking setup | `docs/QA.md` → Smart Wallets section |
| Architecture (strategy at deploy) | `docs/ARCHITECTURE.md` → Strategy Library section |
| CLI strategy commands | `docs/USAGE_GUIDE.md` → Strategy management; `etemaro strategy validate` |
| Validate a strategy JSON | `etemaro-strategy-validator` skill |