Is jev-trader a live trading system?
It includes a live-order path as well as simulation. The ability to submit orders does not establish strategy validity or profitability.
jev-trader connects bounded model decisions to the Monad/Kuru order book. Jev selects a direction; code determines permission to quote, price, size and receipt handling. It is useful for studying an event-driven decision layer, not evidence of predictive advantage or trading returns.
We reviewed a pinned commit and tested selected behavior with network, market and filesystem doubles. We did not run the complete upstream application, call live Jev, connect a wallet, broadcast transactions or measure profit. These isolated tests are not a full project reproduction.
From a block to an order
- Receive a block
onBlock starts receipt checks for previous orders. If the previous iteration is busy, it records late/hold rather than starting another decision.
- Prepare evidence
Read the book, retain mid-price history and build TradeState. Trade logs update outside the hot path.
- Ask for direction
A single Choice selects buy or sell. Jev neither generates order code nor calculates the quote.
- Apply execution policy
allowed checks inventory, resting and in-flight orders; live mode also checks margin. If the selected side is disallowed, code tries the opposite side. If neither is allowed, no new quote is submitted.
- Submission is not a fill
market builds a batchUpdate to cancel prior orders and post a new post-only limit order. sent is submission intent, placed comes from a receipt, and actual fills come from Trade logs. Dry-run approximates fills from subsequent prints crossing the quote.
trader.ts: onBlock / allowed / harvest · market.ts: send / encode / pollPending
The actual Jev request and answer
This synthetic teaching input follows TradeState. It is not a chain sample, API log or recommended trading configuration. Use it to understand the role of each field group.
{
"market": "MON-USDC",
"block": 100,
"horizonBlocks": 100,
"blockMs": 300,
"mid": 1.01,
"spreadBps": 198.02,
"bookImbalance": 0,
"depth": {
"10bps": {
"bid": 0,
"ask": 0
}
},
"book": {
"bids": [
"1.000000 x 200"
],
"asks": [
"1.020000 x 200"
]
},
"returnsBps": {
"last1": 0,
"last5": 0,
"last20": 0,
"last100": 0
},
"recentMids": "1.010000",
"trades": {
"count": 0,
"buyMon": 0,
"sellMon": 0,
"cvdMon": 0,
"vwap": null,
"lastPrice": null,
"lastSide": null
},
"recentTrades": [],
"allowed": {
"buy": true,
"sell": true
}
} mid / spreadBps- Mid-price and spread calculated by code, not model arithmetic.
book / depth / bookImbalance- Top-five levels, depth bands, and nearby bid/ask imbalance.
returnsBps / recentMids- Computed returns and a sampled price path, not news or external research.
trades / recentTrades- Trade flow and recent prints, refreshed asynchronously; do not assume an atomic snapshot with the book.
horizonBlocks / allowed- Prediction horizon and code-computed direction constraints. The default horizon is 100 blocks; the upIn10 name does not mean a ten-block forecast.
JevModel uses evaluationModel from @ai-sdk/typesafe-ai with experimental_evaluate, a direction Choice and maxRetries=0. The question compares the future price over the horizon with the current mid. Its criteria contain only buy and sell, with no abstention option. This is not a three-way buy/sell/hold classifier.
Distinguish a.choice, a.probabilities and the execution-adjusted decision.action. upIn10 is just an alias for buy probability, not another Noul or confidence in profit. model.ts ↗
Six findings in the reviewed source
1. The prompt and execution use different order semantics
The pinned prompt assumes crossing the spread and an IOC market order in the next block. market.encode instead sets postOnly to true, while quotePrice avoids crossing the opposite quote. Resting orders have different execution assumptions. The mismatch is visible in source; its effect on results is unmeasured. Align the prompt with execution before comparing outcomes in your own fork.
model.ts: QUESTIONS · market.ts: quotePrice / encode
2. A probability of one can be a missing-data fallback
When probabilities are absent, the adapter fills the selected side with one and the other side with zero. Our isolated test reproduces this branch. These values are not calibrated model probabilities. A safer downstream design would label their provenance and represent missing probabilities as unknown; that is a recommendation, not existing upstream behavior.
3. Execution direction and displayed probabilities can disagree
When a cap rejects buy but permits sell, code changes action to sell and sets capped=true while retaining the original probabilities. In our synthetic test, buy probability 0.8 coexists with a sell quote. This is a policy override, not a contradictory model answer; inspect capped, quote.side and the original probabilities together.
model.ts: decide · trader.ts: onBlock
4. late/hold is neither a deadline nor a cancellation policy
The busy branch skips a new block without cancelling the previous request. Our test suspends a decision, sends another block and observes hold; releasing the earlier decision still leads to submission. The local loop has no explicit stale-result rejection. On provider failure, catch logs and finally releases busy; this branch does not cancel all resting orders. “Once per block” is not a hard 300ms deadline or a fail-closed guarantee.
5. Mock latency is not Jev latency
MockModel combines returns, book imbalance, flow and deterministic noise, then explicitly calls Bun.sleep(80). Our test checks the requested delay, not real latency. README timings for a dry-run/mock setup are not an independent Jev benchmark. Compare mock, live model calls and end-to-end loop timing separately, with sample counts and failure rates.
model.ts: MockModel · README: latency context
6. Displayed P&L is not all-in net profit
emit computes pnlUsd from realized plus unrealized P&L minus gasUsd; separately accumulated jevUsd is not deducted there. A synthetic test with realized 10, gas 2 and model cost 3 yields pnlUsd=8, not 5. Dry-run fills infer execution from prints crossing a quote; this does not establish real queue priority or fill opportunity. Account for costs, execution assumptions and model contribution separately.
Run without live orders
You need Git, Bun and a reachable Monad RPC. These steps follow the pinned source; we have not executed the full networked startup. Use an isolated environment without wallet keys. The server has permissive CORS and should not be exposed publicly. Inspect dependencies and scripts before installing.
git clone https://github.com/jarrodwatts/jev-trader.git
cd jev-trader
git checkout --detach b587759e459ea049590102e54a0b07800864cdc3
bun --version
bun install --frozen-lockfile
# No wallet, no model key, no live orders. RPC reads still use the network.
DRY_RUN=true MODEL=mock PRIVATE_KEY= TYPESAFE_AI_API_KEY= PORT=3000 bun run start Check status in another terminal. / returns a JSON snapshot, not a trading dashboard. latest can be null before the first event; inspect quotes and decisions after blocks arrive.
curl --fail http://127.0.0.1:3000/
curl --fail http://127.0.0.1:3000/history
curl --max-time 5 -N http://127.0.0.1:3000/events - Require model="mock", dryRun=true and wallet=null. Stop on a mismatch; do not add a real private key.
- A quote, when present, should have status="sim". No new quote may reflect constraints on both sides; late=true calls for checking the previous iteration.
- The SSE curl intentionally stops after five seconds; that timeout alone is not a server failure. Stop the local process with Ctrl+C.
A Jev-backed dry-run is a separate stage: retain DRY_RUN=true and an empty PRIVATE_KEY before selecting MODEL=jev and setting TYPESAFE_AI_API_KEY as shown in this repository’s .env.example. Note the extra AI in that variable name. This makes real model requests and may incur charges. We have not performed it and do not provide live-trading startup steps here.
What we verified
We retain the MIT license and pinned config.ts, model.ts and trader.ts. Tests transpile the original TypeScript, replacing market, model transport, file writes and Bun sleep in an isolated context rather than rewriting the algorithms.
- Mock and dry-run are independent; supplying a key changes the default simulation state.
- Missing probabilities become one-hot; request options are only buy/sell.
- MockModel explicitly requests an 80ms wait.
- The original probabilities survive an execution-side override.
- Busy emits hold while the earlier request can still complete.
- A model error sends no new order and releases busy.
- Displayed P&L does not deduct the separately tracked model cost.
# In the Jev Tutorial repository, not the upstream trader repository:
npm ci --prefix examples --ignore-scripts
cd examples
node --test jev-trader-contract.test.mjs These seven offline behavior tests pass. They do not validate order encoding, on-chain execution, live provider compatibility or strategy safety. The evidence level remains source review, not complete reproduction.
How to evaluate it further
To evaluate Jev’s contribution, do not rely on a single run and a profit screenshot. First align prompt and execution assumptions, then compare mock, a simple deterministic baseline and Jev on the same records, with time-separated development and untouched evaluation periods. This is a proposed protocol, not completed research.
- Decision layer: retain raw choices, probability provenance, model ID, horizon and independent labels; score directional outcomes under one definition.
- Execution layer: distinguish model and final sides, override reasons, sent/placed/reverted/lost, fills and cancellations.
- Reliability: report model and loop p50/p95, late rate, failures and stale results. Do not count artificial mock sleep as Jev performance.
- Costs and outcomes: disclose model charges, gas, other applicable costs, inventory effects and fill assumptions. Do not label partial-cost pnlUsd as net profit.
The transferable lesson is to keep judgment separate from execution and record when policy overrides the model. The useful pattern is auditable ownership, not a claim that adding Jev makes trading profitable.
Next: bounded retries and failure policies · Next: calibrating decision thresholds
Source reading map
All links pin the same commit. Recheck newer versions rather than assuming these findings still apply. Stars and forks come from the directory snapshot, not these tests.
- src/config.ts ↗
- Defaults, dryRun condition, position cap and horizon
- src/model.ts ↗
- Choice prompt, probability fallback, mock 80ms sleep
- src/trader.ts ↗
- Busy branch, side override, simulated fills and P&L
- src/market.ts ↗
- Quote pricing, post-only encoding, receipts and startup funding
- src/server.ts ↗
- Snapshot, history and SSE output
- README.md ↗
- Author run instructions and mock latency context