Moss raised its target ratio 3.0 → 3.3 after seeing our fees — I hung both targets on the same quote
Fed our real cost record, Moss raised `tp_rr_ratio` from 3.0 to 3.3. Hanging both targets on the same quote at the same instant showed that the 3.3 it chose can
Moss raised its target ratio 3.0 → 3.3 after seeing our fees — I hung both targets on the same quoteYou've finished this article successfully if you can take one field a tool changed after feedback, hang the before and after values on the same millisecond, and read from the records what that single field changed.
| What this does | Translates the parameter a tool changed after seeing our cost record into price levels, hangs the before and after values on the same quote, and reads only that field's effect |
| Who it's for | Anyone who has fed execution records back into a tool to revise its settings and never confirmed whether the revision helped |
| Who it isn't for | Anyone whose tool emits only ratios and no per-trade levels. Without an anchor to translate from, this path doesn't stand up |
| What you end up with | A comparison of how the before and after targets diverge on one identical fill, plus the recipe that produces it |
| Cost | No code cost · no model cost · a weltiq pro account. N arms = N units of quota |
| Time / difficulty | 20 minutes · medium (curl, JSON, plus a ratio-to-level conversion) |
| Relationship to weltiq | This whole article is that — it's a procedure piece, so there's no separate integration section |
| Test environment / date | 2026-09-28 (KST) · isolated server, synthetic quotes (section 5 states the limits plainly) |
| Disclosure | The author is paid by weltiq for this series. The fact that the tool's revision killed its own evidence is written down as well |
The human-side lines are real commands rewritten as dialogue; the outputs are measured and the numbers are untouched.
1. The blank this tool kept leaving
I ran moss-trade-bot-skills in part 15. Give it one sentence of mission and an LLM fills in all 36 parameters, then runs its own backtest on that configuration and grades itself.
Moss filling in all 36 fields. One sentence of mission produces this much at once. Look at the fact that **every field is a ratio or a multiplier** — tp_rr_ratio, sl_atr_mult, risk_per_trade … not one absolute price. That is what bites in section 3
And its own backtest has no fees.
The two engines compared. Look at **zero occurrences of any fee string** — there is no line in Moss's backtest code that handles commission. If cost is zero inside its own world, a reason to revise settings because of cost can never arise there
So I fed it our cost record verbatim — pnl -98.02 fees 247.83, handed over as one line with no processing. Moss revised six of the 36 fields, and five of the six reasons mention fees.
Moss revising six fields after receiving the weltiq record. The blue line at the top is everything I handed over; below is the tool's answer. Look at the highlighted word **"수수료" (fees)** — an item that does not exist in its own backtest appears in five of the six reasons
One of them is the subject of this article.
| Field | Before | After | Moss's stated reason |
|---|---|---|---|
tp_rr_ratio |
3.0 | 3.3 | "높은 수수료 부담을 감안해 이익 실현 시 비용을 흡수할 여지를 늘린다" |
Of the six revised fields, this is the only one translatable into a price level. The rest are entry thresholds, moving-average periods, per-trade risk — things that don't descend to the levels of a single order.
That's the blank. Moss said it changed to 3.3, and nobody measured whether that was an improvement. Measuring it means running 3.0 and 3.3 under identical conditions, and those conditions never existed.
2. Why this stayed empty
Inside Moss's own world the question cannot even arise.
Its backtest has zero fees, so there's no reason to raise the ratio, and no way to see which trades die once it is raised. The evidence for the feedback comes from outside, and there is nowhere inside to check it.
Checking it outside means running 3.0 and 3.3 side by side, and the moment you execute, keeping everything else equal is hard.
- Run them one after the other and the time differs, and different time means a different entry price
- Run them at once and the positions mix and share capital, so the quantities differ
- Backtest them again and that's a replay of the past — real costs, tick grid and minimum notional all behave the way that engine assumes. Those assumptions were Moss's problem to begin with
Change one field and fire into the same instant and the same quote, and the difference can only come from that field.
A trial order doesn't use the balance and the server sets the quantity, so the two arms never compete for capital. Fire in the same millisecond and they see the same quote.
3. The recipe — the thing that actually runs
The recipe is here: 10-trial-order-moss-cost-feedback-ab.sh.
| Step | What |
|---|---|
| ⓪ translate | Derive price levels from the ratios and snap them to the tick grid. Write out the whole derivation |
| ① plant | Fire the two arms simultaneously. Same client_tracking_id; metadata.arm separates them |
| ② recover | GET /v1/forward-tests?tracking=<run id> |
| ③ execution record | GET /v1/forward-tests/orders?format=csv&tracking=… — the whole account in one call |
| ④ join | Join to the tool's log on tracking id + client_order_id, and count whether published_at matches across arms |
The intent stays with the tool. All that goes to the server is client_order_id, client_tracking_id and string metadata; neither the name tp_rr_ratio nor Moss's reason for raising it ever leaves tool_log.csv. A float in metadata is rejected by canonical_json under its determinism rule and comes back 500, so 3.3 went as a string too.
Ratio to level — the whole derivation
Moss's records carry ratios and no absolute levels. The anchor is the tool's own trade row (21-moss-own-backtest-30d.json trades[1]): SHORT · entry 76863.2 → exit 75943.85 · exit_reason: take_profit · pnl_pct 0.1196.
기록된 tp 거리 = 76863.2 − 75943.85 = 919.35 (rr 3.0 에서 실제로 난 거리)
→ sl 거리 = 919.35 / 3.0 = 306.45
→ SL = 76863.2 + 306.45 = 77169.65 → 77169.6 (틱 0.1, 버림)
rr 3.3 의 tp 거리 = 306.45 × 3.3 = 1011.285
→ TP(비교군) = 76863.2 − 1011.285 = 75851.915 → 75851.9 (틱 0.1, 버림)
TP(기준안) = 75943.85 → 75943.8 (틱 0.1, 버림 — 숏 목표가는 내리는 쪽이 보수적)
sl_atr_mult stayed at 2.0 — an unchanged field — so the stop distance doesn't change either, and both arms got the same stop. Entry, direction and deadline are also identical. The only difference is the target.
The raw value doesn't go in as-is
75943.85 is not a multiple of the 0.1 tick on binance-usdm BTCUSDT. The transfer check confirmed it by sending the raw value.
422 invalid_take_profit "75943.85 is not a multiple of tick 0.1"
Omit the deadline and you hit 422 exit_plan_deadline_required first — deadline validation runs before price validation.
The venue had to change
binance-spot has shortable=false and won't take a short, so this ran on binance-usdm (tick 0.1 · lot 0.001 · minimum notional 50 USDT). That is also a changed field, but since both arms use the same venue it is a constant inside the comparison.
Environment for the numbers below: an isolated temporary server · synthetic quotes · not production · the P&L is not a market fact.
4. What came back
The two arms went out at 13:28:50.398 and .406 — 8 milliseconds apart.
| Arm | tp_rr_ratio |
Target | Accepted (KST) | Entry fill | Entry quote published | Exit | exit_trigger |
exit_trigger_px |
close_reason |
Fees | Net P&L | Elapsed |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
15-rr-30 (recorded) |
3.0 | 75943.8 | 13:28:50.398 | 76855.363685 | 13:28:51.240 | 75951.444375 | take_profit |
75943.8 | take_profit |
0.07640340 | +0.827515910 | 2.9s |
15-rr-33 (Moss's revision) |
3.3 | 75851.9 | 13:28:50.406 | 76855.363685 | 13:28:51.240 | 75951.444375 | — | — | close_after |
0.07640340 | +0.827515910 | 46.0s |
Both entry fills, and the publication time of the quote they referenced, match to the millisecond. One quote filled both.
Our trial detail with the one-field-apart arms lined up. Look at the **close_reason column** — one says take_profit, the other close_after. Same fill, same exit price, and yet **why they closed diverged**
Did that field decide the outcome — yes, and painfully
Where the market actually went was 75943.85. That value
- reaches rr 3.0's target of 75943.8 →
take_profitat 2.9 seconds - falls 91.95 short of rr 3.3's target of 75851.9 → can't close at target, hits the deadline instead
The 3.3 that Moss raised after looking at fees cannot close, at target, the very trade that grounded that fee judgment.
That doesn't make the feedback wrong. Pushing the target further out to absorb cost is a sensible move. What it does mean is that the price of the move is invisible inside Moss's own world — a zero-fee backtest has no such thing as "a trade that died because the target moved". Hang both targets on the same quote at the same instant and you see it immediately.
The net P&L is identical for both arms, +0.827515910 to the last decimal, because the synthetic quote doesn't move after the exit and the deadline close landed at the same price. What diverged is not the P&L but the why and the when — and when you're validating feedback, that is exactly the information you need.
The export view, where each arm's record comes out as CSV. Look at the trailing columns — exit_trigger, exit_trigger_px and close_reason are what let you read "why didn't 3.3 close at target" from a spreadsheet
How many arms, and what it costs
| Measured | |
|---|---|
| 6 arms fired at once into one quote | 6/6 came back 201, zero failures or rejections, 0.02 seconds total, acceptance times spread over 6.5 milliseconds. No blocking code path |
| Quota | N arms = N units. Part 15's two arms took used from 5 to 7 |
| Resend / rejection / exit | 0 units (same body resend 200 · different body 409 · automatic exits are counted: false) |
On the pro tier's 1,000 a month, a two-arm comparison runs 500 times a month. Even a pair per feedback cycle leaves plenty over.
5. What this combination can't tell you
① One sample says nothing. The above is a single trade. It absolutely does not mean 3.3 is worse than 3.0 — it means that in this one trade 3.3 couldn't close at target. In another trade 3.3 might capture much more, which is the reason to raise the ratio in the first place. You need a distribution.
② A counterfactual measures one side only. It measures "how it closed with 3.3 set". "What 3.3 earned me extra" is still a judgment — the trades that ran further because the target was further out don't enter this window.
③ We don't say Moss's revision was right or wrong. We measure and record. The table says "that revision stopped this one trade closing at target", and nothing beyond it.
④ The P&L is not a market fact. It's arithmetic on synthetic quotes. What stands here is the ratio-comparison design.
⑤ The levels are derived. 75851.9 is not a number in Moss's records — I derived it from the tool's trade row. Change the derivation rule (section 3) and the number changes, and the conclusion might change with it. The only value the tool emitted is the ratio 3.3.
⑥ An unfilled arm never records the quote it saw. Both arms filled here, but a limit-price comparison in another round produced an unfilled one. reference_px is only the reference at acceptance, and published_at exists only after a fill. On top of that, an unfilled arm's close_after_seconds clock never even starts — it produces no result at all inside the observation window.
⑦ "Same quote" is circumstantial, not identification. Quote snapshots have no id. published_at matching to the millisecond is the best available evidence.
⑧ Recovering an experiment by tracking id opened right after this run. When this round ran there was no cross-lookup on ?tracking=, so recovery actually happened via the tag. The recipe uses the opened path, but the measurements above did not prove it.
6. When to use this, and when not to
Use it when:
- you have fed execution records back into a tool and it revised its settings. Put one revised field up like this and the price of the revision is immediately visible
- the tool emits per-trade levels. You need an array like Moss's
trades[], with entry, exit and reason, to have an anchor for translating ratios into levels - the question is "which condition fires first". Trigger, trigger quote and timing are recorded per arm
Don't use it when:
- you want a P&L difference. Pin the quote and the P&L doesn't diverge. What diverges is the trigger
- the tool emits only ratios and no trade list. In another round I tried to compare two grid optima and got stuck — that tool's grid results carry no per-trade entry and exit levels, so "how do the two optima diverge on the same bar" cannot be answered from the records
- you change two or more fields at once. Switch venue and the fee isn't the only thing that moves: lot size and minimum notional move too, splitting the quantities by a factor of 13
- you want to judge feedback from one trade. A pair costs 2 units and 500 pairs a month are available. There is no reason to stop at one
Evidence for this article: axis B comparison log · per-case request/response originals · transfer verdict · recipe. The original tool run is in part 15, moss-trade-bot-skills.