trading-bot-agent — what breaks when a stock trading framework is ported to crypto

A zero-star TradingAgents derivative, installed and run nine times, measured the same way as the original to see whether it inherited the original's refusal to

Part 28. trading-bot-agent — what breaks when a stock framework is ported to crypto

Done when: you know what changes when a multi-agent framework built for stocks is pointed at crypto.


The tool on one card

What it does Eleven agents debate and produce a Bitcoin rating (Buy–Sell) plus an allocation instruction. It is a derivative of Part 12's TradingAgents, moved onto Binance spot
Who it fits Anyone who read Part 12 and wondered what happens when you port it to crypto. Anyone who wants to see where an open-source port actually breaks
Who it doesn't fit Anyone looking for a crypto analysis tool to use right now. Use the original — it supports crypto too, and it has had four more months of fixes
What you end up with One BTCUSDT verdict (rating + allocation instruction + written reasoning)
What you need · cost Code free (Apache-2.0) / 1 model key, $0.03 per run / market data from Binance's public API, no key needed / a weltiq account (section 5 only)
Time · difficulty 5 minutes to install, 3 minutes per run. Medium — you need to be comfortable with virtual environments and environment variables
Relationship to weltiq It gets compared. This tool places no orders, and most of the verdicts it produces say "reduce", which makes them awkward to move into a weltiq slot (section 5 is an integration experiment)
Test environment · date 2026-09-22 · macOS 26.6.2 / arm64 / Python 3.12 · pinned to commit e478951 · model openai/gpt-5.6-luna
Disclosure I am a paid contributor for weltiq. Every command and output in this article came from real runs in the environment above, and the numbers are untouched. All orders are simulated

1. What this is

ardhanurfan/trading-bot-agent is TradingAgents moved onto Binance spot. Analysts read the material, a bull and a bear debate, a trader writes an execution plan, three risk people argue again, and a portfolio manager issues the final rating — exactly the structure of Part 12. What changed is where the material comes from and where the orders go.

First, the relationship, stated precisely. On the GitHub API this repository carries no fork marker (fork: false, no parent repository). But the top of the README says this:

"This project is a heavily modified and upgraded version of the original TauricResearch/TradingAgents."

The README's star-history graph also points at the original (TauricResearch/TradingAgents), the assets/ folder still holds the original's logo, and the command-line screen prints "Built by Tauric Research". The source was re-uploaded into a new repository; in substance it is a derivative. The license (Apache-2.0) was honored.

Item Value
URL github.com/ardhanurfan/trading-bot-agent
Stars / forks / open issues 0 / 0 / 0
Created → last push 2026-05-12 → 2026-05-24 · 156 commits · not archived
License Apache-2.0
Package version 0.2.4 — the original's 2026-04-25 release

That last line is the most important one in this article. The original is now at 0.5.0. So this derivative split off from the original's April release and never followed it afterwards. That means any difference you find between the two is really two kinds of difference mixed together — what the derivative added (the crypto port) and what the original added later. Fail to separate them and your conclusion is wrong from top to bottom.

What the derivative added: a Binance spot client with candle and indicator functions, on-chain and funding-rate tools, a scanner that picks symbols by turnover on its own, a 24-hour resident daemon, a validator that turns verdicts into orders, and a spot order placer.

What the original added afterwards and this derivative does not have: a fifth analyst, macro indicator tools, a numeric verification layer, a hand-off point for the book, and a guard that filters analysts by asset class. The last one causes an accident immediately, in section 2.


2. Installing

This is the one path I verified.

git clone --depth 1 https://github.com/ardhanurfan/trading-bot-agent.git
cd trading-bot-agent
uv venv -p 3.12 /anywhere/.venv-tba
uv pip install --python /anywhere/.venv-tba/bin/python -r requirements.txt

The install itself does not get stuck. Keys go in as environment variables. This article used OpenRouter.

export OPENROUTER_API_KEY=...
export BINANCE_TESTNET=false        # ← the single most important line here. Section 3 explains why

If the command-line screen comes up, the install worked.

PYTHONPATH=. python -m cli.main

The screen after a successful install — the command line on first launch

A green box with five stages under it (Analyst Team → Research Team → Trader → Risk Management → Portfolio Management) means the install is good. But look at this screen closely. At the bottom, Step 1: Ticker Symbol defaults to SPY, and the examples are SPY, CNC.TO, 7203.T, 0700.HK — all equities. Not one crypto example. The signature inside the box still reads "Built by Tauric Research" (the original team). It calls itself a crypto edition, but the door a human walks in through is exactly the one from its stock days.**

There is no dashboard. No web UI, no address to visit. The command-line screen above and Python calls are all of it. And to use crypto you have to go in through Python, not the command line — the command line has no crypto path prepared.

from tradingagents.default_config import DEFAULT_CONFIG
from tradingagents.graph.trading_graph import TradingAgentsGraph

cfg = dict(DEFAULT_CONFIG)
cfg.update({"llm_provider": "openrouter",
            "backend_url": "https://openrouter.ai/api/v1",
            "deep_think_llm": "openai/gpt-5.6-luna",
            "quick_think_llm": "openai/gpt-5.6-luna",
            "memory_log_path": "/anywhere/this-run.md"})     # explained in section 3

graph = TradingAgentsGraph(debug=False, config=cfg,
                           selected_analysts=["market", "social", "news"])
state, rating = graph.propagate("BTCUSDT", "2026-09-22")
print(rating)      # Buy / Overweight / Hold / Underweight / Sell

Where it gets stuck

Symptom Cause What to do
The first run dies with ALPHA_VANTAGE_API_KEY ... is not set The fundamentals analyst is asking for Bitcoin's financial statements. The original's "skip this analyst for crypto" guard is missing here Drop fundamentals from selected_analysts. The code above is that configuration
The 200-day moving average comes back identical to the 50-day BINANCE_TESTNET defaults to true export BINANCE_TESTNET=false (section 3)
You flipped the switch and it is still wrong The cached candle files do not distinguish live market from test market rm ~/.tradingagents/cache/*Binance*.csv
Same question, but the answer quotes the previous run Verdicts pile up in a file and the next run reads it Point memory_log_path at a fresh file per run
CoinGecko news fetch failed ... 404 / 429 Blocked on their side, or rate limited Only the news column goes thin. The run still completes
BTCUSDT typed at the command line is not recognized as crypto The command line is the stock-era build Call it from Python instead

3. First result — and this is where beginners get confused

The default points at a test exchange

This tool's Binance client defaults to the testnet (testnet.binance.vision). Touch nothing and that is what it reads.

The problem is that the testnet does not raise an error. The public market-data endpoints are open, so values come back looking fine. The prices are close to the live market too. So there is no signal that you are using it wrong. Measure it and here is what you get.

Same request, different exchange — how many daily candles come back

I threw the same request at both addresses. Look at the numbers on the left — the live market returns 1,000 daily candles (from 2023-12-28), the testnet returns 14 (from 2026-09-09). This tool's market analyst computes a 10-day EMA, a 50-day SMA, a 200-day SMA, MACD, RSI, Bollinger and ATR. A 200-day moving average does not exist inside 14 days of data.**

This is not a hidden trap. The tool notices it itself. Here is the market report, verbatim, from a run on the testnet.

The reported close_200_sma was not emphasized in the signal interpretation
because it is identical to the 50 SMA in the supplied output, indicating that
the data window is insufficient or the vendor has substituted the available average.

"The 200-day is identical to the 50-day, which means the data window is insufficient." That sentence sits in the middle of the report, and the rating comes out anyway. If you don't read it, you never know.

Switching to public live-market data — two lines.

bash export BINANCE_TESTNET=false rm ~/.tradingagents/cache/*Binance*.csv

Do the second line as well. The cached candle filenames do not distinguish live from test. The filename can say five years while the contents are 14 days of testnet data, and then flipping the switch keeps reading the old material. I threw away three runs before I understood this.

And if you are only reading public market data, you do not need a Binance key. A key is only needed for the built-in order placer, which this article did not use.

This is what it looks like when it works

After about three minutes it ends like this.

A finished run — the rating and the execution plan

Between the bold rules, PORTFOLIO MANAGER RATING : Underweight is the final rating, and below it is the trader's execution plan. The two lines Action: Hold and Position Sizing: Reduce existing BTCUSDT exposure by approximately 20%–30% are what this tool actually hands you. In the middle of Reasoning you can see resistance near $87,400 and a confirmed daily breakout above $87,400 — those are the levels that get moved into a rule in section 5. At the very bottom, [tokens] calls=15 in=90459 out=16619 is what this single run spent, and it took 179 seconds. This screen means success.

Read it in this order. The rating (Underweight) is one of five steps, Action is one of three (Buy/Hold/Sell), and Position Sizing is the actual instruction. Reasoning carries the why in prose, and the run above even gives levels: add after a confirmed daily close above 87,400, or after a pullback into 81,000–82,000.


4. Getting the most out of it — ask the same question nine times

The best way to use this tool is to not trust a single run. In Part 12 I asked the original the same question thirteen times, and it became obvious that you cannot characterize a tool from one verdict. I reproduced that experiment on the derivative.

Held fixed: model openai/gpt-5.6-luna (same as Part 12), 3 analysts, 1 debate round, 1 risk-discussion round, commit e478951. Changed: only the date, and whether verdict memory was shared.

Run Date Data Memory Rating Action
1 2026-09-22 testnet shared Underweight Sell
2 2026-09-22 live shared Hold Hold
3 2026-09-22 live shared Underweight Sell
4 2026-09-22 live shared Underweight Sell
5 2026-06-30 live shared Underweight Sell
6 2026-09-22 live isolated Underweight Hold
7 2026-09-22 live isolated Sell Sell
8 2026-09-22 live isolated Underweight Sell
9 2026-09-22 live isolated Underweight Hold

Buy (Buy or Overweight) came up 0 times out of 9. The original was 0 out of 13. Run 5 used the same date Part 12 asked about — the day Bitcoin sat 53% below its high with RSI at 30. The original refused to buy that day, saying it was oversold but the bottom was not confirmed, and the derivative refused too.

The data source was swapped from Yahoo Finance to Binance, the sentiment source was replaced wholesale, and the prompts are a generation behind — and the sign does not flip. Of everything that survived the port, this bias is the most certain.

What did change is decisiveness. The original never returned Hold once across thirteen runs. The derivative returned it three times across nine, measured by Action. Open the source and the direction makes sense — the original's portfolio-manager prompt contains this sentence.

The risk debate always contains conflicting stances; deciding which is stronger
is the job, so conflict alone is not a reason to Hold.

"Disagreement alone is not a reason to Hold." The same place in the derivative reads "Be decisive..." and nothing more. The original added that sentence after April; the derivative stopped before it.

There is one more spot like that. The original's trader prompt instructs it to nail entry and stop down as absolute prices, and hands it the raw market report so it can. The derivative has no such instruction. The result follows.

What this tool hands you each run Out of nine runs
Allocation instruction ("cut to 75–85% of normal allocation") 9 / 9
An entry-price field 1 / 9
A stop field 2 / 9

This tool's verdict is "direction plus size". The levels are not structured fields — they are in the prose. The single run that produced an entry price gave entry 86,625 / stop 87,383, which is a sell verdict with a stop above the entry. It looks more like the two numbers cited in the body as a resistance zone being split across two fields. Do not trust the numbers in those fields; read the prose.

One reason the answers differ run to run — memory piles up in a file

That is what the "Memory" column is. Every time this tool finishes a verdict it writes to ~/.tradingagents/memory/trading_memory.md, and the next run on the same symbol reads it. Here is the reasoning from run 2, the only Hold:

Prior BTCUSDT outcomes reinforce this balance: the recent Underweight calls
correctly warned against chasing extended momentum, while the earlier
Overweight and Hold calls underperformed

"The recent Underweight calls were right" — it is using verdicts it wrote minutes earlier as evidence. That is a feature if you want feedback, but if you are measuring how much the answer wobbles across N runs of the same question, this is not N independent runs. So runs 6–9 were done with a fresh memory file each time. If you plan to experiment with this tool, change memory_log_path.

Spot or futures

This is a must-check for any crypto tool. This one is almost entirely spot. Candles, prices and orders all go through Binance spot paths (/api/v3/...). The futures address (fapi) appears in only two places, and both are reading funding rate and premium index as reference indicators. So the verdict applies to spot as-is.

One thing does catch on spot, though. Eight of the nine runs say "reduce." A spot account that started in cash has nothing to reduce. And this tool's built-in order placer does not check the balance before placing an order. It will queue a sell with no holding. This article did not turn the built-in order placer on.


5. Moving it into weltiq — an integration experiment

Saying it up front: this tool is a poor fit for weltiq. It gives you information, and that information is mostly "reduce your holding", which leaves nothing to move into a slot that starts in cash. It is the same wall Part 12 hit with the original, and it is unchanged in the derivative. That article's section 5 is worth reading first.

Even so, there was one field I could move. Run 2's verdict text contained a conditional buy branch, written in prose.

consider incremental additions only after a controlled pullback toward
83,500–84,500 or a confirmed close above 87,400, and reassess defensively
below 81,270

To be clear: this run's final action was Hold. What I moved is the branch the verdict spells out — "add on a confirmed break above 87,400" — and the direction (long) and the two levels (87,400 / 81,270) are the tool's own words. The quantity is mine — a Hold verdict does not state a size for a new entry.

The path that worked had four steps.

  1. Write it as a rule — if close > 87400 and the holding is 0, enter long. The stop falls out of the two numbers the tool gave: (87,400 − 81,270) ÷ 87,400 = 7.0%
  2. Write the reasoning in your own words — the case and the invalidation (a close below 81,270 breaks this logic) go in together. Without it weltiq refuses to create the slot
  3. Set stop conditions — a maximum loss and a time limit are mandatory
  4. Start the slot — it watches 1-minute candles and enforces the rule whether or not you, or this tool, are running

What I observed (checked directly): the slot took live 1-minute candles and kept evaluating the condition. At the last check the close was 85,548 against a threshold of 87,400 — the condition never held, so there was no entry. The breakout line the tool picked was 2.2% above the price at the time, and it was never reached inside the observation window. After checking, I stopped and deleted the slot.

What did not move over

What Why
Allocation instructions like "75–85% of normal allocation" Allocation is not a rule. It is a property of the tool, and Part 12 has the same line
A complete order (sell 0.05 BTC, limit 87,400, stop 92,000) A spot slot that starts in cash cannot sell what it does not hold
The confidence value See below

One line on confidence. This tool's order validator has a confidence field and rejects orders below 0.60. But that value does not come out of the eleven-agent debate. A separate model re-reads the verdict text and extracts it, under instructions to "estimate a reasonable value if none is mentioned." In my runs it produced 0.82–0.86, and no agent ever said any such number. The quantity (0.05 BTC) works the same way. Do not use numbers that are not in the verdict text as evidence.


6. After using it

What was good

What fell short

Cost

Item Value
Code Free (Apache-2.0)
Model $0.0323 per run, measured (openai/gpt-5.6-luna, roughly 75,000 input and 14,000 output tokens)
Market data (Binance) Free, no key
News (CoinGecko) Free. It was often empty with 404/429 while I wrote this
Nine runs, total $0.29

7. What to do next

If you are thinking of using this tool today, use the original. It supports crypto too, it has had four more months of fixes, and it works out the asset class by itself. Part 12 is the install guide for it.

What is worth taking away is the method, not the tool. When you meet an open-source project ported to a different market, check three things first. ① Which release of the original is the package version — anything the original fixed after the split is not in there. ② Where do the defaults point — a testnet running quietly tells you nothing. ③ Does the door a human walks in through know about the new market — if the port were finished, the examples on the first screen would have changed.

And for any tool that issues judgments, do not characterize it from a single run. That is why there were nine, and those nine said the same thing as the original's thirteen.

The next part revisits the same family on US equities — putting it side by side with a tool that structures levels and invalidation conditions from the start.

weltiq setup

If you want to move this tool's verdict into a rule and run it 24 hours a day:

  1. Sign up for weltiq
  2. My → Connections → issue a key
  3. claude mcp add weltiq --transport http https://weltiq.ai/mcp --header "Authorization: Bearer <your key>"

All orders are simulated.


The full verification record for this article — the raw verdicts from all twelve runs, the source comparison against the original, the defect list and every workaround — is in reports/a/28-trading-bot-agent/.