moss-trade-bot-skills — one sentence in, a 36-field trading strategy out
Give Moss a one-sentence mission and it fills all 36 parameters and grades them with its own backtest. Those 36 fields were carried into a weltiq paper slot to
Part 15. moss-trade-bot-skills — the factory that fills 36 strategy fields from one sentenceDone when: you have pulled a 36-field strategy configuration out of a one-sentence mission, moved it into a different engine that charges fees, and re-measured the same 30 days there.
| What it does | Takes one plain-language sentence, fills in all 36 parameters, and grades that configuration with its own backtest |
| Who it fits | Anyone who has a strategy idea and finds turning it into numbers daunting — and who intends to measure that draft once more somewhere that has costs |
| Who it doesn't fit | Anyone who would trust the score as-is and commit capital (the self-grading has no fees) · anyone expecting it to pick instruments · anyone who wants a dashboard |
| What you end up with | 36 fields from one sentence, that configuration's self-graded score, and the same 30 days re-measured on an engine that charges fees |
| What you need · cost | Code free (MIT-0) · Model your agent's LLM calls (this article: $0.005365) · Market data free · weltiq only if you follow section 5 |
| Time · difficulty | 36 fields in a single exchange. Difficulty low-medium — you drop one folder where your agent can see it |
| Relationship to weltiq | It only decides, and leaves the execution seat empty. weltiq went into that empty seat and I counted how many of the 36 fields cross over (section 5). The resident feedback loop, though, did not close |
| Test environment · date | macOS 26.6.2 · arm64 · Python 3.14 · skill moss-trade-bot-factory-en-1.0.3 · 2026-09-21 20:50–21:20 KST (commands and numbers) / 2026-09-22 (screens) |
| Disclosure | weltiq pays me to write this series. Everything said about the tool comes from runs I did myself |
The human sentences are the commands I actually typed, rewritten as conversation. The output is measured and the numbers are untouched. Where I cut something for length, I say so. Every order is simulated and there was not one live-account order. None of this is a trading opinion. The raw logs are in the verification record.
1. What this is
moss-site/moss-trade-bot-skills is a bundle of agent skills. It is not a Python library and not an MCP server — it is one SKILL.md plus bundled scripts. Tell an agent like Claude Code or Codex to "install this skill" and the agent reads it and follows it; the instructions are the body of the thing.
Which means what sits in the deciding seat is not this repository's code but the LLM that read this repository's instructions. The code is on the calculator side, taking the numbers that LLM filled in and running a backtest. That distinction matters throughout this article.
There are three steps. (1) The user describes a trading style in one sentence. (2) The LLM fills in all 36 parameters — it does not ask field by field; inference rules like "for trend following, both directions at 0.5" and "if aggressive, 15 to 25 times" are baked into the instructions. (3) It runs its own backtest with those parameters and grades itself.
| Item | Value | How it was checked |
|---|---|---|
| URL | github.com/moss-site/moss-trade-bot-skills |
|
| License | MIT-0 (No Attribution — you do not even have to credit the author) | GitHub API |
| Stars | ★385 · 34 forks (observed 2026-09-21) | GitHub API |
| Last push | 2026-09-09 | GitHub API |
| Created | 2026-04-15 · 2 open issues · not archived | GitHub API |
| Distribution shape | 12 skill version folders inside the repository (1.0.21 ~ 1.0.27, en-1.0.3) |
ls |
| Parameters | 36 (scripts/params_schema.json) |
counted below |
The repository description says "bit-exact between backtest and live execution". Whether that claim is true is not covered here — I did not attach to Moss's live platform (ai.moss.site). What I measured is "what happens when you move that configuration to a different execution engine."
2. Installing
There are only two prerequisites — Python 3.14 (the skill digs a .venv inside its own folder) and no money at all. The official route is to have your agent do it.
What you say
If you want to type it yourselfInstall this skill: https://github.com/moss-site/moss-trade-bot-skills/tree/v1.0.28/moss-trade-bot-factory
git clone --depth 1 https://github.com/moss-site/moss-trade-bot-skills
cd moss-trade-bot-skills/moss-trade-bot-factory-en-1.0.3
python3 scripts/setup_env.py
The screen after installation finishes
The screen after installation finishes. Three places to look — the 12 at the top means there are twelve folders in the repository that carry a SKILL.md (which one to install is settled just below), the Local virtualenv ready: and Only packages from scripts/requirements.txt were installed. in the middle are the evidence that this tool touched nothing outside its own folder, and the last four lines are where an agent recognises this folder as a skill — name: and user-invocable: true.
The declared dependencies are four lines (pandas, numpy, ccxt, scipy) and 27 packages including what they pull in. I did not time the installation — that is unverified. It does not modify the system Python, it installs nothing beyond the bundled requirements.txt, and it reads no environment variables.
Where it gets stuck
| Symptom | Cause | Fix |
|---|---|---|
| I don't know which folder to install | 12 version folders, and the folder names and the skill name: do not line up, so three pairs share a name |
Keep exactly one edition at a time. For English, moss-trade-bot-factory-en-1.0.3 |
| The agent never picks up the skill | Folder location | Drop the whole folder under ~/.claude/skills/. If you created that directory after the session started, restart the agent |
| I can't tell whether it fired | If it does not fire, the agent just answers plausibly out of its own knowledge | Three tells — it asks whether to install the .venv · it asks "shall I turn on weekly evolution?" · all 36 fields come back at once with no field-by-field questions |
data_cache/ is empty |
It is fetched on first run | That is normal |
| The backtest won't run | You used the system Python | {skill folder}/.venv/bin/python |
3. The first result
There is no dashboard. No web UI, no TUI — the conversation output and the terminal output are all of it, with no command to start, no address and no login. (The maker's hosting platform ai.moss.site does have a dashboard, but that is outside the skill and this article did not attach to it.)
The smallest example is giving it a one-sentence mission.
What you say — typed in Korean, meaning "trade Bitcoin and make me a profit. And explain why you did what you did."
비트코인을 거래해서 수익을 내줘. 그리고 왜 그렇게 했는지 설명해줘.
What comes back (measured — the fields a person looks at first, out of the 36)
BTC Balanced Trend Compounding (BTC稳健趋势复利策略)
direction long_bias 0.5 -> both ways
leverage base 10x / max 15x
signal weights trend 0.35 · momentum 0.25 · mean reversion 0.10 · volume 0.15 · volatility 0.15
entry/exit entry 0.25 / exit 0.10
moving averages 10 / 50 RSI 14 MACD 12/26/9 Bollinger 20 x 2.0
stop/target ATR x 2.0 / RR 3.0 trailing stop on (triggers at 2%, ATR x 1.5)
rolling on (reinvest 50% of unrealized gains at 30%, max 2 times)
regime sensitivity 0.65, exit when the regime turns
Moss filling in all 36 fields
The defining picture of this article. The only thing the human supplied is the one blue line; everything else is the tool's output. Three places to look — the yellow entry_threshold, long_bias and base_leverage are the fields that actually decide "aggressive or conservative", and the red trend_strength_min, rsi_overbought and rsi_oversold are filled in dutifully but never read by the engine (counted in section 5). And the 36 at the bottom — all of them filled at once, with no field-by-field questions.
And it attaches the "why" in its own words.
"사용자가 구체적인 위험 성향을 제시하지 않았기 때문에, 비트코인의 상승과 하락을 모두 거래하는 중립적 추세추종 전략으로 설정했습니다. … 10배 레버리지와 ATR 기반 손절, 이동 손절을 사용하고 수익이 난 포지션만 제한적으로 롤링해 수익 확대와 손실 관리의 균형을 맞췄습니다." — Moss's own output, in Korean (2026-09-21). In English: "Because the user gave no specific risk preference, I set this up as a neutral trend-following strategy that trades both bitcoin's rises and its falls. … It uses 10x leverage, an ATR-based stop and a trailing stop, and rolls only positions already in profit, in a limited way, to balance growing the gains against managing the losses."
This is what it looks like when it works. All 36 fields filled, nothing left blank, and a "why" attached.
Next the skill grades itself with its own backtest. Here is the result against the bundled CSV (2025-10-06 to 2026-03-03, BTC/USDT 15-minute candles, 148 days, capital 10,000).
total_return 1.14% sharpe 0.125 max_drawdown 17.88%
win_rate 34.6% profit_factor 1.008 total_trades 280
Moss running its own backtest
The self-grading running. Two places to look — the 2.626 total at the top: 148 days of 15-minute candles finishes in 2.6 seconds. And the red profit_factor 1.0079… below: it barely clears 1. This screen came from re-running the same parameters against the same bundled CSV the next day, and it matched the previous day's value to the last decimal. The calculator itself is deterministic.
Win rate 34.6%, profit factor 1.008. Remember those numbers. They come back in the very next section.
4. The best way to use it — measuring the self-grading once more
This tool's real value is not "it fills 36 fields" but "it fills them in and grades itself." Except nobody looks at what assumptions that grading rests on. In the whole of scripts/core/backtest.py, not one string relating to fees, slippage or the order book appears.
grep -rniE "fee|commission|slippage|taker|maker" core/*.py *.py
# (no output — exit code 1)
So the self-grading is zero fees, zero slippage, and stops and targets fill exactly at that price inside the candle. The profit factor of 1.008 in section 3 is a number from that world, and it means "pay a single unit of fee and it goes negative."
So I put the same parameters, the same instrument and the same 30 days into two engines. I fetched 2026-08-22 to 09-20 fresh with Moss's fetch_data.py, ran the Moss backtest, and ran the same window through a weltiq replay.
| Moss self-grading | weltiq replay | |
|---|---|---|
| Period · instrument · candle | 2026-08-22 ~ 09-20 · BTC/USDT · 15 min | same (2,877 candles) |
| Leverage | 10x | none (the strategy container has no field for it) |
| Fees | 0 | exchange profile (USDT-M taker 5bp) |
| Fills | stop and target at exactly that price inside the candle | on candle close, only protective stops execute between candles |
| Trades | 65 | 52 |
| Result | −3.02% (PF 0.866, win rate 26.2%) | realized P&L −98.02 · fees −247.83 → net −345.86 (−3.46%) |
Zero fee strings and the two engines compared
Look at the single line at the top — across the entire backtest engine, fee, commission, slippage, taker and maker appear not once (it is a 344-line file). Below that is the same configuration run in two worlds; -3.02% and -3.46% look similar, but the small print under each line is completely different.
The two numbers look similar and their insides are nothing alike. Moss's −3.02% is a loss produced by moving hard at 10x leverage; weltiq's −3.46% was produced with no leverage at all, and 70% of the loss is fees (−247.83 out of −345.86).
Keeping the fill times, sizes and prices and swapping only the rate makes the structure clearer still (measured, shortened).
497 fills · turnover 237,578 USDT · actual fees 137.68 (average 5.795bp)
binance-usdm taker 5.0bp -> 118.79 (-13.7% vs actual)
bybit-linear taker 5.5bp -> 130.67 (-5.1% vs actual)
if all of it had filled as maker -> 47.52
assumption: same prices, same sizes; the fills themselves are not re-simulated
All maker and the fees would be a third. In other words this strategy's cost structure is dominated by hitting the market often, not by the rate. The maker figure is only arithmetic, though, and whether it would really have been filled at that quote is not answered (execution_resimulation: false).
One thing that cannot be done: there is no way to put fees into Moss. Neither the parameters nor the code has a field for it.
5. Moving it to weltiq — an integration experiment
The order a person carries it in
Moss's conclusion is 36 parameters, not an order. So carrying it over means "rewriting those numbers as a rule document," and four steps do it.
(1) write the rule document POST /v1/strategy-rules
(2) write the thesis yourself POST /v1/ai/thesis
(3) set the stop conditions POST /v1/containers (stop_max_loss and stop_after_hours required)
(4) it runs unattended. The container keeps to the rule with both the human and Moss switched off
Steps (2) and (3) cannot be skipped. Leave them out and the stop side returns {"loc":["body","stop_max_loss"],"msg":"Field required"}, and the thesis side returns {"code":"thesis_required"} with three questions — write in one sentence why this strategy makes money, under what market conditions the logic breaks, and the invalidation condition as a number. Those two gates are the boundary of the autonomy.
How many of the 36 carry over — from 2 to 25
The first time the same 36 went into a template-based container, what crossed over was fast_ma_period 10 and slow_ma_period 50 — two, and nothing else. The other 34 were recorded as "no field" rather than approximated.
Then POST /v1/strategy-rules, the entrance for submitting the internal rule grammar with an API key, opened, so I carried the same 36 over again. I read Moss's decision function, core/decision.py, confirmed what calculation each parameter actually feeds into, and rewrote the same calculation as a weltiq computation graph — I moved the formulas, not eyeballed values. The document that came out has 277 nodes and 4 order rules, holding the weighted composition of five signals, the regime modulation, the ATR stop, the RR target and the trailing stop.
| Count | Which fields | |
|---|---|---|
| Carried over | 25 | 5 signal weights · 2 entry/exit thresholds · direction (long_bias) · 2 moving averages · RSI period · 3 MACD · 2 Bollinger · risk per trade · max weight · ATR stop · RR target · 3 trailing stop · 2 regime |
| Could not be carried | 11 | below |
The 11 that could not be carried are three kinds, and the distinction matters.
| Count | Fields | Why | |
|---|---|---|---|
| Fields Moss does not use either | 3 | trend_strength_min rsi_overbought rsi_oversold |
They are in the schema and the LLM fills them, but nothing anywhere in the engine code reads them (0 references). There was nothing to carry in the first place |
| Fields weltiq does not have | 3 | base_leverage max_leverage supertrend_mult |
There is no leverage field, and supertrend is a recursive band with no counterpart in the allowed operation list |
| Fields whose meaning changes | 5 | the 5 rolling_* |
Staged entry (up to 3 stages) exists in the grammar, but Moss's rolling trigger is unrealized gain at 30% of the leveraged margin, which is not the same statement on a side with no leverage. And staged entry requires fixed-quantity sizing, so it and risk_per_trade are one or the other |
2 → 25. And 3 of the 11 that did not make it are not Moss's loss either. The real blanks are 8.
The three places where something was approximated, stated precisely. -
max_position_pct 0.5was carried over as a fixed quantity cap based on the price on the observation day (0.0602 BTC). Moss's side is a ratio of equity, so if the price moves a lot they diverge - Moss's Bollinger standard deviation is the sample one (÷n−1) and weltiq's is the population one (÷n). At a period of 20 the difference is small, but it is not zero - The smoothing on the regime call (192 candles) was not carried over. Moss requires the regime to hold for 192 candles before it accepts a change; the weltiq document accepts it on the candle where it changes
So the best combination is this. Give Moss only the job of "filling the 36 fields," and leave the grading in a world with costs and fills to weltiq. What this combination does not give you is leverage. Moss's 10x becomes 1x on weltiq's side, which means the sizes of the two P&L figures were never comparable to begin with.
How far it went round — and where it stopped
I built a rule document from the 25 that carried over, drew the boundary (BTC/USDT futures, capital 10,000, stop at 200 cumulative loss, auto-terminate after 2 hours) and brought up a container. Here is the 30-day replay.
n_bars 2877 · n_fills 105 · n_trades 52
pnl -98.02 fees 247.83 (realized P&L and fees come back separately)
I handed this output back to Moss unprocessed and asked it to decide again. The only thing the human did was carry it across.
"외부 기록에서는 52개 거래와 105회 체결로 총 수수료 247.83이 발생했고, 총손익 98.02의 손실보다 수수료 부담이 커 비용과 과도한 거래 빈도가 핵심 문제로 보였다. 레버리지는 해당 venue에서 적용되지 않았고 supertrend와 rolling도 실행되지 않았으므로, 이번 조정은 실제로 적용된 신호와 위험관리 파라미터에 집중했다. 진입 임계값과 이동평균 기간을 소폭 높여 저확신 신호를 줄이고, 손실 위험 및 최대 포지션을 낮췄다. 목표 위험보상비는 조금 높여 거래당 비용을 감당할 수 있는 수익 여지를 확보했다." — Moss's own output, in Korean (2026-09-21 21:15 KST). In English: "In the external record, 52 trades and 105 fills produced 247.83 in total fees, and since the fee burden is larger than the 98.02 total loss, cost and excessive trading frequency looked like the core problem. Leverage was not applied on that venue and supertrend and rolling did not execute either, so this adjustment concentrated on the signal and risk-management parameters that were actually applied. I raised the entry threshold and the moving-average periods slightly to cut low-conviction entries, and lowered the loss risk and the maximum position. I raised the target reward-to-risk ratio a little to secure room for profit that can absorb the per-trade cost."
Moss changing six fields after receiving weltiq's record
The revision in progress. The single blue line at the top is everything that was handed over (unprocessed), and below is the tool's answer. Look at the word 수수료 — "fees" — highlighted in yellow: an item that does not even exist in its own backtest is in the reasoning for five of the six fields. The red risk_per_trade and max_position_pct are fields Moss itself declares "locked during the evolution pass", and they changed anyway.
| Field | Before | After | Moss's stated reason |
|---|---|---|---|
entry_threshold |
0.25 | 0.275 | "cuts low-conviction entries and unnecessary fills" |
fast_ma_period |
10 | 11 | "slows the reaction to short-term noise slightly" |
slow_ma_period |
50 | 55 | "strengthens trend confirmation and reduces frequent direction changes" |
risk_per_trade |
0.08 | 0.072 | "lowers per-trade risk given the loss confirmed in external execution" |
max_position_pct |
0.5 | 0.45 | "lowers the position cap to limit exposure to volatility and fill costs" |
tp_rr_ratio |
3.0 | 3.3 | "widens the room to absorb costs when taking profit, given the high fee burden" |
Five of the six reasons contain "fees." It revised its settings looking at a cost that does not even exist in its own backtest — feedback its own world could never produce. (risk_per_trade and max_position_pct are locked in Moss's own evolution rules as "character parameters — change them and the code reverts them", and Moss's LLM changed them anyway. Following the principle that a tool's decision is not corrected, I carried them across as they were.)
I rebuilt the document from the revised 25 fields, submitted it, wrote a new thesis and brought up a new container.
The weltiq strategy container detail — the revised 25 fields as one rule line
One image covers weltiq's side. The 25 fields Moss revised, hardened into one rule line and attached to the container. Three places to look — the 0.275 and × 3.3 in the grey line under the title are exactly the values Moss just produced, and 보호 손절 12% (a 12% protective stop) is the boundary the grammar enforces. The ai tag below that marks this container as created through a tool path (source=ai) rather than by hand. ORDERS 0, FILLS 0 and the user in the Auto-stop field are exactly as they were, undressed — it means a person stopped it before the 2-hour limit ran out and before the 15-minute warm-up had even finished.
This is what was confirmed here. Decision → rule → replay record → decide again → a new container created.
I cannot write that the loop closed. What was fed back to Moss was not a record left by a resident run but a 30-day replay result, and the two containers both had zero fills — I stopped the second before its 15-minute warm-up had even finished. "Took the record a resident run left behind and ran it resident again" is unverified in this article.
Whether the revised configuration was actually better also could not be measured. From the second replay onward, orders were rejected in bulk (accepted 105 first, then accepted 55, direction_conflict 166). The lock that prevents holding a long and a short on the same instrument at once persists at the account level, and because the first replay ended with an open position, the long-side lock was never released. Putting two numbers from a contaminated state side by side is not a comparison, so this stays unverified — it is a weltiq-side known issue.
6. After using it
What was good
- One sentence fills 36 fields. The decision not to ask field by field is bold, and it really does come back with no blanks
- It does not touch anything outside its own folder. No package beyond the bundled
requirements.txt, no environment variables read - It always attaches a "why". And when it revises, a reason per field. There is no better output shape for running feedback
- It is fast and deterministic. A 148-day 15-minute-candle backtest takes 2.6 seconds, and re-running it the next day matched to the last decimal. MIT-0, so not even an attribution obligation
What fell short
- Its self-grading has no fees and no slippage. That is why a profit factor of 1.008 comes out, and it is stated nowhere in the README or the output. The biggest weakness
- Stops and targets fill at exactly that price inside the candle. That is the single largest divergence from real fills, and the assumption is never surfaced
- 3 of the 36 parameters are never used. The LLM dutifully fills
trend_strength_min,rsi_overboughtandrsi_oversold, and the engine never reads them. The user is led to believe they tuned something - Its own LLM breaks its own evolution rules. The character parameters are documented as locked, and the evolution pass changed two of them. When you carry it outside, a person has to look
Cost
| Item | Value |
|---|---|
| Code · market data | Free (MIT-0) |
| Model | $0.005365 for this entire article (agent LLM calls) |
| Time | One exchange from mission to 36 fields · 148-day self-backtest in 2.6 seconds |
Who it does not fit is anyone who would trust the score it produces and commit capital on it. This tool's score is a score from a world without fees, and that is not a criticism of the tool but a matter of knowing where a score came from.
7. Coming next
Part 16 is OpenAlice (★7.1k).
Where Moss "fills 36 fields and leaves execution on its own platform," OpenAlice is a thing whose README tells you itself to "start with the simulator or paper." They come in at a different place — Moss meshed through the output format of its decision, OpenAlice through the order of the execution stages. And the round trip this part could not get, part 16 actually gets.
Getting ready for weltiq — 3 lines 1. Sign up: {{CTA_URL}} 2. My page → Connections, issue an API key 3.
claude mcp add weltiq --header "Authorization: Bearer <key>" https://weltiq.ai/mcpThat is where to look when you want the 36 fields Moss filled re-measured in a world that charges fees.
Every command, output and number in this article came from actual runs on 2026-09-21 (commands) and 2026-09-22 (screens). No real money moved; everything is simulated. None of it is a trading opinion. The trial and error, raw logs and per-field detail not printed here are in the verification record.