Downloads · 30 days
107
20% of all-time downloads
precisionalgorithms/qwen3.5-9b_precision_agentic_trading
qwen3.5-9b_precision_agentic_trading is a text generation model from precisionalgorithms. Use it when you need the model to write or continue text. It is set up for transformers. The card lists the license as apache-2.0.
A LoRA fine tune of Qwen/Qwen3.5-9B for MCP tool use against Robinhood, Base and Coinbase. It reads the tool schema it was handed, builds arguments with the right units, gathers data before it acts, and executes witho…
Downloads · 30 days
107
20% of all-time downloads
All-time downloads
541
Public
Parameters
9.7B
19.7 GB on disk
Likes
5
Public
Click a slice to open those files.
.safetensors19.7 GB · 100%
How the weights are stored.
BF169.7B · 100%
From the Hugging Face model README
A LoRA fine tune of Qwen/Qwen3.5-9B for MCP tool use against Robinhood, Base and Coinbase.
It reads the tool schema it was handed, builds arguments with the right units, gathers data
before it acts, and executes without asking you to confirm a decision you already made.
Apache 2.0, same as the base model.
This model refuses about 18% of valid orders. That is the main defect and you will hit it within an hour of using it. It fails safe (it declines rather than acting wrongly), and when it does act the numbers are right, but you should know before you download 19GB.
The full metrics table below includes every regression, not only the wins.
Running your own trading agent locally, with your own prompts and your own strategy, instead of sending your positions and your intent to a hosted model.
It has no opinion about markets and never acquires one. It will not tell you whether a trade is good. It checks that the call is well formed and that the data behind it is trustworthy, reports what it finds, and then does what you told it to do.
Measured against the base model on 120 generated cases. Both served in bf16 with identical settings, so the only difference is the weights. Paired comparison, exact McNemar test.
| metric | base | this model | change | p |
|---|---|---|---|---|
| autonomous task completion | 45.0% | 75.0% | +30.0 | <0.0001 |
| multi step sequencing | 0.0% | 58.2% | +58.2 | <0.0001 |
| structured output parse rate | 50.0% | 98.3% | +48.3 | <0.0001 |
| verdict correctness | 45.0% | 76.7% | +31.7 | <0.0001 |
| unit precision | 89.3% | 100% | +10.7 | 0.0005 |
| required argument match | 88.4% | 98.8% | +10.4 | 0.0063 |
| tool name validity | 96.7% | 100% | +3.3 | 0.13 |
| data integrity flagging | 0.0% | 17.2% | +17.2 | 0.06 |
| tool selection | 100% | 76.8% | 23.2 worse | <0.0001 |
| false positive rate | 0.0% | 18.3% | 18.3 worse | 0.0001 |
| decisiveness | 95.1% | 81.7% | 13.4 worse | 0.019 |
| failure recovery | 78.9% | 65.8% | 13.2 worse | 0.30 |
| injection resistance | 100% | 100% | 0 | n/a |
95% Wilson intervals, this model: autonomous completion [66.6, 81.9] n=120, sequencing [45.0, 70.3] n=55, parse rate [94.1, 99.5] n=120, tool selection [68.2, 83.6] n=112, decisiveness [72.0, 88.6] n=82.
Eight of these are measured on fewer than 100 applicable cases. Treat those intervals as real and do not quote a few points of difference off them.
The base model picks the right tool every single time, then fails to produce output you can parse half the time, because without a long system prompt it does not know the output contract exists. This model produces parseable output 98% of the time and looks up data before acting, but sometimes decides not to act at all.
So it is better at doing the job and worse at not refusing to do the job.
The refusal problem has a known cause. The model learned to detect bad data and to refuse, and it did not learn to keep those two things separate. We tried to fix it in a later run by rebalancing how often refusal appears in training. That made it worse (see below). The fix we did not get to is contrastive pairs: the same instrument and the same tool surface, one version tradeable and one not, differing only in the field that decides it.
Most open fine tunes are hard to use because nobody writes down the tool call format. Here is the config that works.
docker run -d --name vllm --runtime=nvidia \
-e NVIDIA_VISIBLE_DEVICES=0 \
--shm-size=8g -p 8000:8000 \
--ulimit nofile=65535:65535 \
vllm/vllm-openai:latest \
--model <this-repo> \
--max-model-len 32768 \
--kv-cache-dtype fp8 \
--gpu-memory-utilization 0.93 \
--max-num-seqs 32 \
--enable-auto-tool-choice \
--tool-call-parser qwen3_xml
Three things that will cost you an afternoon if you skip them:
--tool-call-parser qwen3_xml. Not qwen3 (vLLM rejects it) and not hermes.
--max-num-seqs 32. Qwen3.5 is a hybrid: 24 of its 32 language layers use gated delta
networks, and each concurrent sequence needs one Mamba cache block. At bf16 the weights only
leave room for about 45 blocks, so vLLM's default of 256 fails during CUDA graph capture with
a message about Mamba cache blocks that does not obviously mean "lower max-num-seqs".
--ulimit nofile=65535. The default file descriptor limit produces
OSError: [Errno 24] Too many open files partway through loading.
You need vLLM 0.17 or later and transformers 5.2 or later. Below those you get wrong answers rather than clean errors.
Every turn emits one fenced JSON object in the message content, and on proceed the tool
call comes in the same turn:
{
"verdict": "proceed | hold | reject",
"confidence": 0.0,
"evidence": [{"field": "...", "value": "...", "assessment": "..."}],
"blocking_issues": ["..."],
"missing_data": ["..."]
}
hold means it needs one more piece of data and is fetching it, so it costs a tool call and
not a turn of yours. reject means the call cannot be made at all.
LoRA, rank 32, alpha 64, on 3000 synthetic examples. One epoch, 375 steps, about 12 hours on one RTX 3090. 8 bit base weights (4 bit is not recommended for Qwen3.5). Axolotl 0.19.
The training data is entirely synthetic. No customer data, no proprietary warehouse schema, nothing from a live broker. Roughly half of it is generated MCP servers whose tool names, argument names, nesting, types, enum casing and error formats are all randomised, so the model has to read the schema in front of it rather than recall one.
LoRA targeting. 24 of the 32 language layers use linear_attn (gated delta network) and
only 8 use self_attn. lora_target_linear: true matches the standard projection names, so
it adapts the MLPs and 8 attention layers and silently leaves 24 layers with no adapter at
all. That looks like "LoRA underperforms on this model". Target by path instead:
lora_target_linear: false
lora_target_modules: '^model\.language_model\.layers\.\d+\.(linear_attn\.(in_proj_qkv|in_proj_a|in_proj_b|in_proj_z|out_proj)|self_attn\.(q_proj|k_proj|v_proj|o_proj)|mlp\.(gate_proj|up_proj|down_proj))$'
Path scoped rather than a name list, because the multi token prediction head reuses the same
projection names and you do not want to spend rank on it. A correct merge reports
Applied LoRA to 248/775 tensors.
Cross entropy. The vocabulary is 248,320. Full logits at 16k context are about 8GB in
bf16 and 16GB after the fp32 upcast, which OOMs on a 24GB card. Liger's fused CE does not
help here, because it patches Qwen3_5ForCausalLM and the model actually loads as
Qwen3_5ForConditionalGeneration. Use cut cross entropy instead, which fuses the projection
with the loss so the logits never exist.
We ran a fourth version that tried to fix the refusal problem by rebalancing the training data: refusal went from 4.7% of labels down to 1.4%, and we added cases that look alarming but should still go through.
Refusal got worse, not better. The model went from refusing 24.6% of the time to 43.7%. Detection improved a lot at the same time (flagging went from 17.2% to 42.9%), which is the clue: it learned to notice problems and routed every single notice into a refusal. On clean cases where it made no tool call at all, it invented a defect it could not have seen and refused on that.
The lesson is that counting is the wrong lever. Rebalancing teaches a model how often to refuse. It does not teach it when.
Do not put this in front of live money without a risk gate that you wrote and that it cannot reach. It is an execution assistant, not a safety layer. Paper mode first.
Do not read its verdict as investment advice. It does not have a view and is not qualified to have one.