LangAlpha — a research agent that writes down why you are buying and where it would admit it was wrong

LangAlpha's trade-pitch skill produced, for one name, an investment case carrying entry, target and invalidation prices on the same page. That invalidation pric

LangAlpha — a research agent that writes down "why buy" and "where I would admit I was wrong" together

Done when: you get, for a single name, an investment case that states why you are buying and where you would admit the idea is wrong, in the same document.

What it does For one name it writes down what the market believes, what you see differently, and why that gap exists — and puts entry condition, target, invalidation price, time exit and size on one page
Who it fits People who want the structure of the argument more than the verdict. Anyone who has had to ask "so when am I wrong?" as a separate question after getting a buy case
Who it doesn't fit Anyone looking for something that buys and sells on its own once switched on. Anyone not using Docker (section 2). Anyone trading crypto — this looks at US equities only
What you end up with A one-page trade pitch with invalidation: below $221.56 printed in the body, and a record of that price carried straight over into an order condition
What you need · cost Code free (Apache-2.0) · model $0.26–0.42 per run (this article used gpt-6-astra; a cheaper model costs far less) · market data free (Yahoo, no key) · weltiq separately
Time · difficulty 20 minutes to install · 10 minutes to the first pitch · difficulty medium-high (easier if you have handled PostgreSQL, Redis and Docker before)
Relationship to weltiq It connects — but only halfway this time. The invalidation price this tool produced went into a weltiq order condition unchanged. The US market was closed on the day of the test, so the fill was never confirmed (section 5)
Test environment · date 2026-09-22 (KST) · macOS · Python 3.13 · repository ginlix-ai/LangAlpha, 2026-09-21 build (commit d95c4ce)
Disclosure I am a partner contributor for weltiq. The tool in this article is third-party open source with no connection to weltiq, and every number below comes from runs I did myself.

1. What this is

LangAlpha starts from a refusal — the refusal to be financial AI that ends at "one question, one answer". The people who built it call it vibe investing: research should accumulate the way a code repository accumulates commits. You create one workspace per research purpose, the agent leaves files, notes and earlier conclusions in it, and when you come back tomorrow they are still there.

The feature list is long: an execution model that processes data with Python inside a sandbox, parallel sub-agents, a web workbench with live charts, Slack and Discord integrations, scheduled automation. What this article measures is one item on that list: the trade-pitch skill.

Everything this tool decides lives under plugins/ as skill documents. Not code — nineteen markdown files. Among them trade-pitch handles the last step, "turn a name you have finished analyzing into a position", and it spells out fields that other tools tend to leave empty.

Exits come in three layers. The stop is a price rule, and its distance is written in units of that name's own volatility. The review level is a thesis rule, taken from the disconfirmation field. The time stop is the date at which the catalyst failing to arrive is itself the answer.

And it nails down that size is written not as a share count but as a fraction of the loss budget. The reasoning is in the document too: the agent does not know the other party's positions, assets or delegated limits, so the moment it writes "x percent of the book" that number is invented.

Repository github.com/ginlix-ai/LangAlpha · Apache-2.0 · 1,765 stars
Latest commit 2026-09-21 (actively worked on)
Stack Python backend (FastAPI) + React web + PostgreSQL + Redis + sandbox
Markets US equities, cash. There is no futures or crypto path in the code
Market data Yahoo, free (no key). FMP and web-search keys are optional
Models Several providers supported. The default is the Claude family

2. Installing

The one path I verified

This is the path that stands the thing up directly on the host. PostgreSQL and Redis can be whichever ones you already run.

git clone https://github.com/ginlix-ai/LangAlpha
cd LangAlpha
uv sync --extra test          # uv fetches Python 3.13 for you
cp .env.example .env          # filling in the five lines below is enough to boot
uv run alembic upgrade head   # create the tables (48 steps)
uv run python server.py --port 8000

Only five lines of .env are actually needed.

DB_HOST=localhost
DB_NAME=langalpha
REDIS_URL=redis://localhost:6379/0
BYOK_ENCRYPTION_KEY=<openssl rand -hex 32>
OPENROUTER_API_KEY=<model key>

When curl localhost:8000/health returns {"status":"healthy"}, the backend is done. The web interface comes up separately with cd web && pnpm install && pnpm dev.

The first screen after installation — picking a model provider. If the keys are already in the environment, it shows up at the top as "2 providers connected".

Where it gets stuck

Where Symptom How to get past it
Sandbox Send a message and it ends with Starting workspace… followed by a single line, "An error occurred" You need Docker. See below
Models The default configuration goes looking for an Anthropic key and dies with ANTHROPIC_API_KEY ... is not set Add the key, or pick the provider you actually use in the web settings
Boot log ZAI_API_KEY and DEEPSEEK_API_KEY exceptions keep printing These are used by the fallback model and the background market summary; they do not affect conversations
No pnpm command not found npm i -g pnpm

About Docker — this tool's biggest barrier to entry

This tool's agent will not run a single turn without a sandbox. There are exactly two sandbox providers: Daytona (cloud, account required) and Docker (local). My machine had no Docker, so it ended like this.

What you get when you send a mission on a machine without Docker. Market data, news and the dashboard all come up; only the agent refuses to run.

The data paths are fine. Indices, news, ticker search, daily bars and analyst targets all come through without Docker.

The dashboard. Everything up to this point comes up without Docker.

If you can use Docker the official path is far shorter — make config && make up brings up PostgreSQL, Redis, backend and frontend in one go. I was not able to confirm that path on this machine.

If you cannot use Docker, use the method in section 3 of this article. Everything this tool decides is a skill document, so you can put the same documents in front of a model and run them without the harness.


3. First result

Because I had no Docker, I took the values from the free market-data path of the backend I had just stood up, put the eight trade-pitch skill documents (about 60,000 characters) on top of them as they are, and threw that at a model. The script is under 100 lines (reports/a/18-langalpha/mission.py).

What I sent was exactly one line.

Trade NVDA and make me a profit. And explain why you did what you did.

I sent it three times under the same conditions, and all three started the same way.

Recommendation: wait for proof on a potential long position until the earnings basis and cash conversion are verified and a live price, valuation anchor, catalyst, and loss budget are available. Entry / target / price exit: withheld rather than invented.

"I will leave it blank rather than invent it." That is the first result, and it is the first thing to know about this tool.

It did not only hand back blanks. All three runs also produced these.

So the invalidation condition did come out all three times. Just in the form of a claim, not a price. That difference is what separates sections 4 and 5.


4. Getting the most out of it — hand it a one-page mandate

This tool leaves the prices blank not out of laziness. The first step of the skill requires five fields to be settled first — horizon, vehicle, benchmark, loss budget and the analysis the pitch rests on — and if they are empty, readiness drops to blocked and the usable verbs shrink to three: wait, wait for proof, review.

So fill those fields in and the same skill gives you prices. Here is what I sent alongside the mission (the full text is in mandate-24h.txt).

- Vehicle: a cash account, long only, US common stock only. No leverage,
  no options, no shorting
- Benchmark: none. Absolute return
- Loss budget = 150 basis points of the book, read as an absolute cap that
  must hold in any state
- Horizon = ONE US regular session (09:30-16:00 ET). Opened at the next open
  and closed inside 24 hours. A multi-quarter horizon must not be
  substituted for it
- The analysis this rests on: none. Deliver it screen-grade, but do not
  withhold the expression
- Execution: a paper broker that will not accept anything at all without
  a reason, an invalidation price and a quantity

The last two lines are the crux. Writing only "24 hours" is not enough — the skill's default horizon is "2 to 8 quarters", and unless you nail it down it reverts to the long view. Without "deliver it, do not withhold" you get section 3 again: every field blank.

With that one page attached to the same mission, the first line changed to this.

Recommendation: wait for proof at the next open; conditional long NVDA common stock. Entry condition: opening price above $221.56 and at or below $222.94; target $228.50–$230.40; invalidation below $221.56; time exit September 22, 2026, by 16:00 ET.

The expression table filled in all six of its fields as well.

Field What came out
Vehicle Common stock, fully cash, no leverage and no hedge
Entry Only if the next open is above $221.56 and at or below $222.94. Otherwise the day is a non-event. Do not chase it intraday
Target $228.50–$230.40. Only the lower end is supported by the argument; the upper end is illustrative
Stop Below $221.56 the support hypothesis is negated. This is an intended exit price, not a guaranteed fill price
Review If the prior session's low breaks, the input that supports the pullback case collapses with it
Time exit 16:00 ET the same day
Size As much as keeps purchase amount plus cost within the 150bp budget. No share count is assigned
Binding constraint An absolute loss cap. Not a reward-to-risk ratio

There is one more thing worth looking at. It splits size into two readings and shows the arithmetic for both. Read as an absolute cap, common stock can go to zero, so the purchase amount itself has to sit inside the budget; read as a scenario limit, the size is the budget divided by the 0.62% distance to the stop. "If the mandate does not say which, show both" is the skill's rule, and it did show both.

And the verb is still wait for proof. It never says "buy now." It gives you a hypothesis with conditions attached, and a human checks whether the conditions are met.

A caution — where these prices come from. $221.56 and $222.94 are the prior session's low and open. The tool says so itself: "levels picked from past bars, with no evidence that these levels predict the next session's return path." This is not a valuation; it is a pullback hypothesis.


5. Moving it into weltiq — the integration experiment

weltiq will not accept an entry order without a reason and an invalidation price. That is exactly why this tool is unusual — the field other tools leave empty, this one fills when told to.

Step 0 — setup. Sign up → My → Connections and issue a key → claude mcp add weltiq … (see the CTA in section 7). A per-symbol order-limit approval has to be created once in the browser (a key alone will not do it).

Step 1 — send it without an invalidation price. The fastest way to see which door is locked is to walk into it.

curl -X POST https://weltiq.ai/v1/orders/oneoff -H "Authorization: Bearer <key>" \
 -d '{"venue":"us-equity","symbol":"NVDA","side":"buy","type":"limit",
      "qty":"3","price":"222.94","thesis":{"why":"전날 시가 부근 되돌림에서 전날 고가까지의 회복을 시험한다"}}'

The why field above is Korean, and it says: "test a recovery to the prior day's high from a pullback around the prior day's open". The reply — its detail is Korean for "an exit condition (px_below/px_above) is required" — is this:

422  {"code":"invalidation_required","detail":"청산 조건(px_below/px_above)이 필요합니다"}

Step 2 — put in the price the tool produced. It is one line.

"invalidation": {"px_below": "221.56"}
200  {"status":"accepted","est_notional":"668.82","qty":"3"}

Step 3 — carry it into a rule document as well. To have it watched all day you need a rule, not an order. The US equity engine does not know price-condition blocks, so it is written in the internal rule format. The three numbers the tool produced go in unchanged.

entry: (low ≤ 222.94) AND (low > 221.56) AND (no position) → long
exit:  stop 221.56 · target 228.50
protective stop: 0.62%        ← the $1.38 ÷ $222.94 the tool calculated

Here is what weltiq read back (Korean: "entry … → enter long L · price-condition exit L … → exit: protective stop 0.62%").

진입: (((low ≤ 222.94) AND (low > 221.56)) AND (position.size = 0)) → 진입 long L · 가격 조건 청산 L (stop=221.56, limit=228.50) → 청산: 보호 손절 0.62%

Step 4 — write the reasoning in your own words and put it up. To run a rule as a resident slot it asks for the reasoning one more time. And the third of its three questions is this — "specify the invalidation condition (a price level or a point in time) as a number." Use this tool and that answer is already in your hand.

Step 5 — the result. The slot came up, and there was no fill. The day I ran the test, the US market had already closed (11pm local time). With no closed bar, the entry condition never gets evaluated. I left the record, then stopped and deleted it, and cancelled the order too.

So what was actually confirmed.

What the tool produced Did it carry over
Invalidation price $221.56 Unchanged. As an order condition and as a rule stop
Entry condition above $221.56 and at or below $222.94 Into the rule document unchanged. Into the one-off order, only the upper bound
Target $228.50–$230.40 Lower end only. There is no field that takes a range
Time exit 16:00 ET There is no place for it
Size (a fraction of the budget) I converted it — 3 shares, assuming a $50,000 book. The tool does not produce share counts
Review condition ("if the earnings basis is overturned") There is no place for it. Only prices and times are accepted
An intraday fill Unconfirmed

One thing confirmed here for the first time. Most of the tools covered so far in this series could not fill in the "invalidation price" field, so that number had to be written by me. This time the number the tool wrote went into the order unchanged. It is the first case with nothing invented by the person doing the carrying. That said, you can only call it closed after seeing a fill, and that has not happened yet.


6. After using it

The good

  1. It does not invent what it does not have. When an input is missing it writes "missing", and then writes what would change if it were there. Where other tools emit a plausible-looking price target, this one stops. It is frustrating, and it is this tool's value.
  2. The invalidation condition is part of the judgment. Not "bought, here is why" but "bought, here is why, and here is what makes me wrong", all on one page.
  3. It catches data that disagrees with itself. When the previous close for the same name came back differently from two places, it split them into a table and wrote "we do not quietly pick one of the two." It caught it all three times.
  4. It is honest about size. It does not invent a share count; it gives a fraction of the budget. It even shows, with arithmetic, that the answer differs depending on whether the budget is an absolute cap or a scenario limit.
  5. It starts free. It runs on Yahoo with no market-data key.

The bad

  1. Docker is effectively mandatory. It is this tool's biggest barrier to entry, and even the documented "on the host, without Docker" path ends up using Docker for the databases.
  2. The default is long-horizon. Ask plainly and it answers on a 2-to-8-quarter view. To get a one-day call you have to nail it down as in section 4.
  3. It will not pick a direction by itself. It does not choose the name for you, and without a mandate it produces no prices at all. It is a poor fit for "just handle it".
  4. It gives no confidence score. It gives a readiness grade instead. For anyone comparing tools by a numeric confidence value, that field is missing.
  5. It is hard to call a run cheap. The skill documents alone are 20,000 tokens of input. For me a run came to $0.26–0.42 (on an expensive model; pick a cheap one and it drops sharply).

Cost

Item Measured
Model 20,039 input · 3,416 output tokens per run. Four runs totalled $1.22
Market data Free (Yahoo)
Code Free (Apache-2.0)
Infrastructure PostgreSQL, Redis, Docker — my own machine's resources

7. What to do next

Throw one question at it with no conditions attached, then attach the mandate from section 4 and throw it again. Watching the same tool produce a completely different shape of answer from the same data is the fastest way to understand it. If you have Docker, starting with make up is far easier.

DayTradingAgent is coming up in this series. That one produces intraday entries, exits and stop moves without being asked, so you can put "a tool that gives you prices when you ask" and "a tool that gives them without asking" side by side in the same US market.

weltiq setup — 3 steps 1. Sign up: {{CTA_URL}} 2. Issue a key under My → Connections 3. claude mcp add weltiq --transport http https://weltiq.ai/mcp --header "Authorization: Bearer <key>"

Paper only. You can follow section 5 of this article exactly as written.


The full verification transcripts, commands and responses are in reports/a/18-langalpha/.