--- base_model: mlx-community/Qwen2.5-1.5B-Instruct-4bit tags: - qlora - lora - mlx - trading - structured-output license: apache-2.0 --- # TradeParse-QLoRA QLoRA adapter for **Qwen2.5-1.5B-Instruct (4-bit, MLX)**, fine-tuned to convert natural language trade instructions into structured, schema-validated JSON. **Example** Input: `"Buy Reliance if it drops below 2800, sell above 3000, intraday"` Output: ```json { "symbol": "RELIANCE", "action_conditions": [ {"trigger": "price_below", "value": 2800, "action": "buy"}, {"trigger": "price_above", "value": 3000, "action": "sell"} ], "strategy_type": "intraday" } ``` ## Technique - **Base model**: `mlx-community/Qwen2.5-1.5B-Instruct-4bit` - **Method**: QLoRA (LoRA adapters trained on top of a 4-bit quantized base) via `mlx-lm`, chosen for feasible memory usage on Apple Silicon - **Training data**: synthetic instruction → JSON pairs, including normal trade parses and structured error cases for missing/ambiguous information ## Eval results V2 adapter eval on 240 generated validation examples: | Metric | Result | |---|---:| | Valid JSON | 100.00% | | Schema valid | 100.00% | | Success exact match | 92.08% | | Error exact match | 68.42% | | Overall exact match | 88.33% | The split matters: success exact match is measured over trade-parse cases only, while error exact match is measured over invalid/ambiguous instruction cases only. ## Three representative cases ### 1. Correct trade JSON Input: ```text Buy Infosys if it drops below 1500, sell above 1700, intraday ``` Expected/model output: ```json { "symbol": "INFY", "action_conditions": [ {"trigger": "price_below", "value": 1500, "action": "buy"}, {"trigger": "price_above", "value": 1700, "action": "sell"} ], "strategy_type": "intraday" } ``` This shows the normal target behavior: company-name normalization, two price conditions, and strategy extraction. ### 2. Correct structured error Input: ```text Buy ONGC when it's cheap, sell when it's expensive ``` Expected/model output: ```json { "error": "missing_price_condition", "symbol": "ONGC", "message": "No numeric price condition found." } ``` This should not be force-parsed. The instruction has a symbol and actions, but no concrete price levels. ### 3. Known wrong / limitation case Input: ```text buy this stock below 500, sell above 600, futures ``` model output: ```json { "symbol": "AAPL", "action_conditions": [ {"trigger": "price_below", "value": 500, "action": "buy"}, {"trigger": "price_above", "value": 600, "action": "sell"}], "strategy_type": "futures" } ``` Expected output: ```json { "error": "missing_symbol", "symbol": null, "message": "No symbol or company name found." } ``` This is a useful failure case to track. The model may produce valid-looking trade JSON even though the instruction never identifies which stock to trade. In a real trading workflow, this should be rejected or sent back for clarification. **Known failure modes:** - Vague price language like "cheap" or "expensive" requires a structured error unless another price-resolution system exists. - Missing-symbol instructions can still tempt the model to hallucinate a symbol. - Error-case accuracy is lower than normal trade parsing, so negative/error examples need more data and harder evaluation. ## Usage Requires the base model + this adapter loaded together via `mlx-lm`: ```python from mlx_lm import load, generate model, tokenizer = load( "mlx-community/Qwen2.5-1.5B-Instruct-4bit", adapter_path="path/to/downloaded/adapter" ) ``` Full code, training data generation script, and eval scripts: [GitHub repo](https://github.com/Misbah-Asif/trade-parse-qlora) ## Scope This is a translation layer (natural language → structured JSON), not a trading execution engine. Output is intended to be consumed by a downstream order/strategy system.