romankurnovskii

create-strategy Skill

用于从零创建新的 Etemaro LP 策略,或在现有预设基础上调整。当用户要求"创建策略""添加新策略""设置策略""配置 LP 策略""我该用什么策略""微调策略""修改策略",或任何涉及 Etemaro 策略设置、定制或部署配置的请求时使用。当用户描述交易目标(如"我想做多 SOL""我想在稳定币交易对上赚手续费""我有一个波动大的代币")并需要转化为具体配置时也应触发。

安装方式:把技能目录放入 ~/.claude/skills/(Claude Code)或在 claude.ai 设置中启用;也可复制右侧安装命令一键添加。

查看源码

技能指令原文(SKILL.md)

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

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)?

  1. Capital per position (SOL) — how much SOL per position? (Drives deployAmountSol / positionSizePct.)
  2. Exit preference — take profit at a %/threshold, trail the price, or let it run and re-seed?
  3. 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):

"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

name=.

  • 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)

"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)

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

screening (token-type filters)

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

"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)

"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):

{
  "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..v-.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:

# 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

[ ] 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 |