Scoring a 'hold' from daily_stock_analysis — the four price levels that only hold together as a counterfactual

daily_stock_analysis called NVDA a hold. I placed that decision as a real order without touching the account. The market was closed, so the verdict came back un

Scoring a 'hold' from daily_stock_analysis — the four price levels that only hold together as a counterfactual

You've finished this article successfully if you can take one hold from your own tool and move its price levels into two counterfactual orders — long and short — without inventing a single number. And, for US equities, check the session first.

What this does At the moment a tool says "don't buy now", places the order that buys now and the order that sells now, and carries both to completion without touching the account
Who it's for Anyone whose tool emits price levels alongside its verdict and has never checked whether those levels hold together as an order
Who it isn't for Anyone trying to measure US equities during Korean daylight hours. Closed means unmeasured — and that is half of this article
What you end up with A comparison showing exactly where the tool's four levels stand up and where they collapse, plus a recipe that checks the session and stops on its own
Cost No code cost · no model cost · a weltiq pro account
Time / difficulty 20 minutes if you already have the tool's records · medium (curl, JSON)
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 · US equities closed (section 5 states the limits plainly)
Disclosure The author is paid by weltiq for this series. The main verdict came back unmeasured, and rather than hide that I made it part of the article

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 daily_stock_analysis in part 25. Its signature output is one verdict plus four price levels. Feed it NVDA and you get this (raw/levels-verbatim.txt, batch run 1):

symbol: NVDA
decision_type: hold      operation_advice: 관망     confidence_level: 중간
ideal_buy: 219.01   secondary_buy: 219.16   stop_loss: 218.9   take_profit: 230.0

The NVDA decision dashboard. 227.38 dollars at the top, strategy "hold", trend "sideways", and four price cards below. Look at the fact that **the verdict and the four levels sit on the same screen** — this tool says "don't buy" and hands you a price to buy at in the same breath

It shows its working too (RUN-LOG.md:123): close 227.38 · MA5 219.01 · MA20 219.36 · gap +3.82% · MACD DIF 1.4828 < DEA 1.5377 · resistance 234.50. And five independent runs all came back hold (RUN-LOG.md:125) — this is not a wobbly verdict.

The four price cards, enlarged. The ideal-buy card explains that "the trend is inverted and this price is below MA20, so it is not an order price". **The tool is telling you itself that this number is not an order right now** — that one line is the whole of section 2

Those four levels don't hold together on transfer

In the earlier transfer check (part 3) I pushed the four levels straight into an order. This is what happened.

Field On transfer
stop_loss 218.90 goes in
take_profit 230.00 goes in
ideal_buy 219.01 no field for it — a trial order has no entry-condition slot
secondary_buy 219.16 no field for it

Half of the tool's signature output is dropped. And the surviving half sits oddly: ideal_buy 219.01 and stop_loss 218.90 are 0.05% apart. Buy at 219.01, stop at 218.90, and your stop distance is 0.05%. In run 2, the stop (219.36) came out above the buy price (219.01) (docs/tutorials/a/25-daily-stock-analysis.md:184).

A side finding: send that inverted pair anyway and you get 201. The contract only checks take_profit > stop_loss. It does not catch contradictions with the entry price.

That's the blank. The verdict is the same five times out of five, nobody has measured whether it was right, and the levels shipped with it fall apart when moved into an order.


2. Why this stayed empty

The scorecard for "decided not to buy" has been missing for a simple reason.

To measure it you have to actually buy, and buying moves the account. Capital gets tied up, the loss budget gets eaten, and the result lands in your performance numbers. The act of measuring damages the thing being measured.

This tool makes it especially stark. To measure the hold you have to buy at 227.38 — the exact price the tool told you not to buy at. Nobody does that with a live account.

The trades you decided not to take get a scorecard too. Without your account moving.

A trial order carries that judgment to completion on a separate ledger that never touches your balance, P&L, loss limits or performance totals.

And this is where the four levels find their places

This is the heart of the piece.

On transfer, ideal_buy 219.01 is the entry. Put it there and the 218.90 stop sits 0.05% away, and in run 2 it inverts outright. The set doesn't stand up.

In a counterfactual the entry is the current price. You don't wait for the 219.01 the tool asked for; you buy now. The moment you do, the arrangement changes.

Transfer (entry = ideal_buy 219.01) Counterfactual (entry = current 227.30)
stop_loss 218.90 0.05% from entry — barely a stop below entry — a stop, properly
take_profit 230.00 +5.0% from entry above entry — a target, properly
run 2 stop_loss 219.36 above the buy price — inverted below entry — no problem
Does the set stand up no yes

The same numbers are unusable on transfer and usable as a counterfactual. The tool didn't emit bad values; it emitted parts for a wait-for-the-dip order, and those parts don't fit the buy-now order. Move the entry to the current price and they find their places.


3. The recipe — the thing that actually runs

The recipe is here: 08-trial-order-daily-stock-analysis-wait.sh. Five steps.

Step What
⓪ session GET /v1/capabilities to see whether us-equity is open. If it's closed, stop
① plant One long and one short, carrying a client_tracking_id
② recover GET /v1/forward-tests?tracking=<run id> — exact match, scoped to my account
③ 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

The intent stays with the tool. All that goes to the server is client_order_id, client_tracking_id and string metadata; the verdict (관망), the confidence (중간) and the MACD reasoning live only in tool_log.csv. If you need a number in metadata, carry it as a string — a float is rejected by canonical_json under its determinism rule and comes back 500.

Why long is long and short is short

Long — the tool said "buy if it comes down to 219.01, not now". So we do the opposite and buy at market now. The exit conditions are the tool's own numbers, unchanged:

{"symbol": "NVDA", "side": "long",
 "exit_plan": {"stop_loss": "218.90", "take_profit": "230.00", "close_after_seconds": 600}}

Short — this tool explicitly implied downside: a MACD dead cross, inverted moving averages, a +3.82% gap above MA5, and "no chasing: do not buy above +5% over the 5-day line". There is no disclaimer saying this is not a prediction of a decline. So a short went out as well. Both levels are the tool's numbers with only their roles swapped:

{"symbol": "NVDA", "side": "short",
 "exit_plan": {"take_profit": "219.01", "stop_loss": "234.50", "close_after_seconds": 600}}

219.01 is the tool's ideal_buy (= MA5), i.e. the pullback destination the tool named. 234.50 is the tool's resistance, identical across 3 of 3 chat runs. Not one new number was created.

One disclosure goes with the short: borrow fees on US equity shorts are computed as zero. Over ten minutes that barely registers, but hold one for long and the record flatters the market.


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

Both were 201, and neither filled.

Case Response Entry Exit close_reason Fees Net P&L
NVDA long (buy now) 201 — — rejected:market_closed 0 —
NVDA short (sell the pullback) 201 — — rejected:market_closed 0 —

"Was the hold right" is unmeasured this round.

Here is the measured session at run time.

venue=us-equity  local_time=2026-09-28T00:27-04:00  is_open=False  state=closed
next_open=2026-09-28T09:30-04:00   (= 22:30 KST)

Our screen — accepted with 201, then returned from placement as rejected:market_closed. Look at the fact that **acceptance (201) and placement (rejection) are separate stages**: direction and exit plan both passed validation, and the session is what stopped it

I did not fake the clock. A fill obtained around a closed session isn't a fill that passed the live rules. That's why step ⓪ of the recipe checks the session and stops on its own when it's closed. Run the same script between 22:30 and 05:00 KST and it lands on the same criterion.

Being unmeasured is free, and that was measured too

This rejection doesn't consume quota. In the same round, 16 submissions left used at 7, and 7 is exactly the number of crypto entries that actually filled — all 9 rejected:market_closed cases were refunded, because none of them ever filled.

And the account did not move. Comparing all nine account-related tables before and after gave complete equality (account_unchanged_vs_T0: true).

Our trial list — this run's cases gathered under one tracking id. Look at the **status column**: cases accepted without a fill and cases that ran to completion are distinguishable in the same list

What this round did answer

The main verdict is unmeasured. But the question from section 2 got an answer — moved into a counterfactual arrangement, the tool's levels pass acceptance validation as they are. Long gives stop 218.90 < entry < tp 230.00; short gives tp 219.01 < entry < sl 234.50. Neither came back 422.

The numbers I had written up as "not a viable order set" clear the contract purely because the entry moved. That is confirmed independently of the closed session, because acceptance validation runs before the session stage.

The Ask screen. Question history on the left; on the right, a MACD DIF 1.4828 < DEA 1.5377 table and a conditional trade plan. Look at **"the conditional trade plan I propose"** — the tool states its plan in prose. Executing that plan now, instead of waiting for its condition, is this article's counterfactual


5. What this combination can't tell you

① One sample says nothing. Here the sample is zero — the market was closed, so nothing filled. Even one verdict wouldn't settle whether the hold was right. You need a distribution.

② A counterfactual measures one side only. It measures "what if I had bought". "What did not buying save me" is still a judgment.

③ We don't say the tool was right or wrong. We measure and record. What this article says is not "the hold was correct" but "here is how you measure that hold, and this time the market was closed so I couldn't".

④ Unmeasured means unmeasured. Don't fill it with a zero. Not measuring and measuring zero are different things. These two cases must be excluded from any scoring table.

⑤ I chose the entry price. The tool never said "buy now". The entry timing of the counterfactual is mine, and that choice produces the result. Firing at the instant of the judgment is what removes the choice, and this was a late batch, so it didn't.

⑥ The tool's horizon and my window differ. Its levels assume a daily horizon; this window was ten minutes. A separate set matched to the tool's horizon is needed.

⑦ Borrow fees on US equity shorts are zero. Invisible over ten minutes, material over days, and always in the direction that flatters the record.


6. When to use this, and when not to

Use it when:

Don't use it when:


Evidence for this article: axis A counterfactual log · per-case request/response originals · transfer verdict · recipe. The original tool run is in part 25, daily_stock_analysis.