AI trading structured output validation checks whether an AI proposal has the required fields, whether those fields describe a coherent trade, and whether the current account rules permit it. Valid JSON only establishes a parseable format. Keep schema checks, market checks and authorization outside the model, and stop execution when any required check is unresolved.
A neat object can still request the wrong instrument, use quote currency where base quantity was expected, or spend cash already committed to another order. This guide builds a validation worksheet around one fictional spot proposal. It describes a general design and evaluation method, not a claim that every control below is implemented in KLINEO.
A schema describes a proposal; it does not approve one
Structured output turns an open-ended paragraph into fields that software can inspect. A schema can restrict field names, types and allowed values. In JSON Schema, defining a property does not make it mandatory: required must specify that obligation. Extra properties are allowed by default unless restricted, for example with additionalProperties: false. JSON Schema's object reference explains these distinctions.
Those checks answer whether the object fits its contract. They do not establish that a balance is available, a price is current or a trade is authorized. A field containing "approved": true is still a model assertion unless a trusted authorization process supplied it.
Provider features can reduce formatting failures, but their supported schema subsets and failure states differ. OpenAI's documentation, for example, distinguishes schema-constrained Structured Outputs from JSON mode, warns that structured results can contain mistakes, and documents refusals and incomplete responses. Inspect the actual response status before consuming a parsed object. OpenAI's structured-output guide.
OWASP similarly recommends validating model responses before backend functions consume them. Apply that principle to the trade boundary: the execution service should treat the proposal as an input to check. OWASP guidance on improper output handling.
Keep the contract narrow and the authority separate
The following is an illustrative field contract, not a complete exchange request or a ready-to-deploy schema. Its purpose is to make units and missing evidence visible.
| Proposal field | Contract question | Independent check |
|---|---|---|
schema_version | Is this a supported version? | Route only to the matching validator; reject unknown versions. |
decision | Is the value hold or propose? | hold must never create an order. |
instrument_id | Is there an exact instrument identifier? | Resolve it in a trusted venue and market registry. |
side, order_type | Are the values from allowed enumerations? | Check that the strategy permits that combination. |
base_quantity | Is the unit explicitly base asset? | Parse a positive decimal and check current quantity rules. |
limit_price_quote | Is the price denominated in the pair's quote asset? | Check price increments, bounds and order-type requirements. |
snapshot_id | Does the field reference supplied evidence? | Resolve it against an independently recorded snapshot and clock. |
One implementation choice is to represent decimal quantities as constrained strings, then parse them with decimal arithmetic. That avoids assuming a binary floating-point representation will preserve every exchange increment exactly. A string alone provides no numerical validation: empty text, negative values and unsupported notation still need explicit handling.
The application should bind account, environment, credential scope and policy version through trusted configuration. Letting the model choose an account or turn a paper proposal into a live order expands its authority. The prompt-injection guide explains why research text cannot grant that authority.
Provide a legitimate no-action result. If the required evidence is missing, the model needs a defined way to return hold with a reason rather than filling mandatory trade fields with guesses. The validator must enforce the field rules for each decision branch.
Work through a proposal that looks valid
Assume this fictional contract accepts a spot buy-limit proposal for a permitted BTC/USDT instrument. All prices, quantities, limits and increments below are invented for this exercise; they are neither current exchange settings nor suggested trading parameters.
The proposal requests 0.004 BTC at 60,000 USDT per BTC. Its limit notional is 0.004 × 60,000 = 240 USDT. The schema accepts the values, and the illustrative price and quantity increments accept them too.
Now apply the independent policy. The example allows at most 250 USDT per order and 300 USDT in total committed purchase notional, including pending orders. Another pending order already reserves 100 USDT.
| Validation step | Calculation or observation | Result |
|---|---|---|
| Required fields and allowed values | Proposal fits the selected contract | Pass |
| Per-order limit | 240 ≤ 250 USDT | Pass |
| Total commitment | 100 + 240 = 340 USDT; ceiling is 300 | Reject |
| Remaining capacity | 300 − 100 = 200 USDT | Insufficient for this proposal |
This commitment ceiling is a simplified budget policy, not a loss cap. A production policy also needs a defined treatment of fees and other reservations. When requests arrive concurrently, reservation must preserve the aggregate ceiling; two requests cannot each spend the same remaining capacity.
The correct outcome is no submission. Asking the model whether it is “sure” does not change the arithmetic. Quietly reducing quantity also changes the proposal. If resizing is allowed, create the revised candidate, recompute its checks and obtain any required approval for that exact candidate.
Check units, precision and clocks after parsing
Consider three mutations of the same fictional proposal.
First, base_quantity becomes "240" because the model has copied the quote notional into the quantity field. It may satisfy a loose decimal-string schema, but it now describes 240 BTC. Independent notional and quantity checks should reject it. Naming units clearly reduces ambiguity; recalculating the amount catches this particular error.
Second, the quantity becomes "0.00333". If the illustrative quantity increment is 0.0001 BTC, this value fails that increment. Rounding down to 0.0033 would produce 198 USDT at the same price, but it is a changed candidate that needs validation again. Passing one filter cannot justify ignoring another.
Binance Spot documents separate price, lot-size and notional filters, with market-order behavior depending on the relevant filter settings. Those are venue-specific rules to retrieve and apply for the actual instrument, rather than constants to ask AI to remember. Binance Spot filter documentation. The exchange-order minimums guide examines cases where rounding cannot produce an acceptable order.
Third, the proposal is generated five seconds ago but references an observation recorded 70 seconds ago. An illustrative 60-second evidence-age policy rejects it. A recent answer is not fresh market data. Resolve the snapshot against a trusted record rather than accepting a model-written timestamp; see the market-data freshness guide for the separate clocks.
Test the rejection path with fixed fixtures
Use a mocked execution endpoint that records calls without placing orders. Keep the valid baseline, then change one field or condition at a time. This worksheet separates structural failures from state-dependent failures.
| Fixture | Expected outcome |
|---|---|
Unexpected approved field in a closed schema | Schema rejection; zero execution calls |
| Missing price for the buy-limit branch | Schema or branch-rule rejection; zero calls |
| Valid-looking identifier for a disallowed market | Instrument-policy rejection; zero calls |
| Correct structure, stale snapshot | Freshness rejection; zero calls |
| Valid proposal exceeding remaining commitment | Budget rejection; zero calls |
| Refused or incomplete model response | No executable proposal; zero calls |
Valid hold result | Recorded no-action decision; zero calls |
Never execute a partial streamed object just because its first fields look usable. For an invalid response, record the failure and follow a bounded repair policy if one exists. A repaired candidate must pass every check again; repair cannot waive policy or invent missing market evidence.
Record the original proposal, schema and policy versions, resolved snapshot, calculations, rejection reasons and execution-call count. Keep credentials out of that record. The paper-trading validation guide helps distinguish evidence about decisions from evidence about live execution.
Compare rejection and no-action patterns against a frozen baseline through model-drift monitoring, preserving pending outcomes and version changes.
Validation ends before the exchange outcome
Passing validation means the candidate satisfied defined checks at a particular state and time. Apply claim-by-claim hallucination checks to its factual premises separately; even a verified proposal does not guarantee profit or a fill. Recheck state at execution because balances, reservations and market rules can change after analysis or approval.
Submission then introduces separate uncertainties. If a request times out, do not generate a replacement proposal and assume the first order never existed. Establish the actual order state before retrying; the order-timeout reconciliation guide covers that boundary.
Prepared with AI assistance under the editorial policy, this worksheet provides reproducible checks rather than a certification of any trading system. Its useful result is a traceable decision: which contract passed, which independent rules passed, and why execution was permitted or stopped.
