Skip to content
MrJev

jev_stock

Experiment in forecasting Hong Kong stock direction: it builds a past-only state from market data, asks for an up, flat or down call, and renders a standalone report.

View on GitHub →

Hands-on review

Forecasts Hong Kong share direction from a past-only state. We planted future prices in the series and none of them reached the request.

Good for

  • Reading a careful past-only state builder for a market forecast
  • A deliberately small reference set: the stock, HSI and HSTECH, nothing else
  • `--dry-run`, which prints the request without calling the API

Watch out for

  • No licence file, so nobody can legally reuse it
  • One request is 18 KB of price history, and it grows with the window
  • It is an experiment, and the author says so; do not trade on it

Tested Sep 21, 2026 at 81fa91979508 · python:3.12 in Docker with no network for the leakage probe; its 11 unit tests, and a synthetic price series with a marker after the cutoff

How we reviewed this: we ran its unit tests in Docker, then built a synthetic price series with a marker value in every bar after the cutoff and drove build_state and build_request directly with no network, to see whether anything from the future reaches the model. We made no Jev calls, and this review contains no accuracy figures for anything.

What it does

You give it a Hong Kong stock code. It downloads daily bars through AKShare, assembles a state out of the last 30 trading sessions, and asks Jev for a up / flat / down choice for each of the next N sessions plus one for the next 30 calendar days. There is a backtest mode over non-overlapping past samples and an HTML report.

Two framing decisions are better than the genre usually manages. The reference market is deliberately small — the target stock, the Hang Seng Index and the Hang Seng TECH Index — and the README says so: “The project does not silently add a basket of unrelated stocks.” And the README’s first sentence calls it an experiment.

The leakage check

For anything that backtests a forecast, the question that matters is whether the state ever contains information from after the cutoff. We built a 60-bar series in which every bar after the cutoff had a price of 999999, then asked for a state at that cutoff:

window size: 30 | cutoff bar: 2026-02-27 | last bar in the series: 2026-03-27
state as_of: 2026-02-27
post-cutoff marker present anywhere in the state?   False
latest date in the state: 2026-02-27
post-cutoff marker present anywhere in the request? False

Nothing from the future got through — not in the target window, not in the two index windows, not in the monthly or weekly context blocks, which are all built from market.target[:cutoff + 1].

The financial-data path is handled the same way, and the code says why in the state itself:

"financial_context": {"available": false,
  "reason": "历史回测不使用缺少公告发布日期的财报数据,以避免未来信息泄漏。"}

(“Backtests do not use financial statements that lack a publication date, to avoid look-ahead leakage.”) Excluding fundamentals because you cannot prove when they became public is the distinction most amateur backtests miss, and it is written into the artifact rather than a README.

What a request looks like

One request per forecast, carrying the whole state: 30 bars for the stock and for each index with computed indicators, monthly and weekly context, thresholds, and one choice question per horizon —direction_day_1 … direction_day_3 plus direction_next_30_calendar_days. Ours came to 18 KB. That is the cost model to keep in mind: the state is priced per call and grows with the window and the number of reference series.

--dry-run prints that request without calling anything, which is the right first command for a tool that spends money per forecast.

Tests and maintenance

11 unit tests pass, covering symbol normalisation, CSV loading, the state builder and the backtest’s labelling. The CSV loader is stricter than it needs to be in a good way: duplicate column names, rows with more fields than the header, and missing required columns are all rejected with a specific message rather than producing a silently wrong series.

There is no .github directory, so nothing runs those tests, and no licence file — GitHub reports none — which for a repository this readable is the one thing to fix.

Two smaller things. The endpoint is a constant with no override, so this one is Jev-only; and the key is read from the environment or a local .env, never written anywhere.

Verdict

As a piece of engineering it is careful where it counts: a past-only state, an explicit refusal to use undated fundamentals, a tiny reference set, strict input validation and a dry run. As a trading tool it is what its author calls it — an experiment — and three days of one person’s work.

If you are building anything that backtests a model against market data, the state builder here is worth reading before you write your own. Ask for a licence first.

For a Jev-in-the-market project with a live-trading loop, see jev-trader; for the sentiment-shaped version, Jev-X.

See how it compares with other tools in Best Jev tools, tested hands-on.

Review updated Sep 21, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.

More in Finance

jev-trader

★ 3.1k▲ 31

jarrodwatts/jev-trader

Asks Jev buy or sell on every Monad block and places real post-only limit orders on the Kuru MON-USDC book. Not financial advice.

TypeScriptReviewed

beebots

★ 334▲ 6

imikerussell/beebots

Three trading bots race on OKX perpetual futures with every decision typed and a risk layer in plain code; paper trading is the default. Not financial advice.

TypeScript

brainstormity/Jev-X-Sentiment-Analysis

Crypto terminal that reads up to 1,000 posts about a ticker alongside market and funding data and turns them into a buy, sell, hold, or take-profit call. No license file at the time of writing. Not financial advice.

PythonReviewed

Get new Jev projects every week

New Jev releases, pricing changes, and the best new projects, once a week. No spam; unsubscribe anytime.

Powered by Buttondown. See our privacy policy.