Files
Harwinder Sekhon 01baef48ff Initial import: XAUUSD news sentiment models, evals, and data tooling
TF-IDF baseline (news_sentiment.py, models/xauusd_sentiment.joblib) and the
two-head DeBERTa-v3-small transformer (transformer/, news_transformer.py)
with its Google News crawler and DeepSeek labeller (data_collect/), the
golden-set and archive evals (eval/), and the 2026-09-22 and 2026-09-27
results and progress notes.

Transformer weights (model.pt, model.onnx) and the crawl database are not
tracked; rebuild with transformer/train.py and transformer/export_onnx.py.
The DeepSeek label cache in data/ is tracked.
2026-09-27 19:22:30 -04:00

137 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# XAUUSD News Sentiment Model
See [`WORKFLOW_AND_USAGE.md`](WORKFLOW_AND_USAGE.md) for the complete
integration, LLM fallback, deployment, and retraining workflow.
This project trains a scikit-learn model to answer one specific question:
> Does this news imply bullish, neutral, or bearish sentiment for XAUUSD?
- `bullish`: supportive for gold versus the US dollar, so XAUUSD tends upward
- `bearish`: negative for gold versus the US dollar, so XAUUSD tends downward
- `neutral`: no clear directional implication or conflicting signals
Neutral is retained because forcing ambiguous news into a bullish or bearish
class creates false signals.
The model uses headline and description word/character TF-IDF features with
logistic regression. It also derives transparent domain features for explicit
gold movement, US dollar direction, Treasury-yield direction, and
hawkish/dovish policy language. Its numeric score is in `[-1, 1]`:
```text
P(XAUUSD bullish) - P(XAUUSD bearish)
```
## Training Labels
Labels are DeepSeek's (`deepseek-v4-flash`) XAU score for each headline, not
human or trader labels. The general article `score` is never used. For each
row the trainer takes the first of:
1. the `xau_score` column (stored for every LLM-scored headline since
2026-09-18),
2. `score_by_currency_json["XAU"]` (older rows that mention gold),
3. `--extra-labels` JSONL keyed by headline hash (for example
`eval/results/backfill_labels.jsonl`, DeepSeek labels for older macro
headlines).
By default only `score_source = 'llm'` rows are used, and test-feed rows
(`feed.example`, `good.example`) are skipped. `--scope gold` limits training to
rows with a JSON `XAU` key, which was the behaviour before 2026-09-22. The
included model (trained 2026-09-22, `--scope all`) used 2,620 deduplicated
headlines from Sep 8–22 (1,064 `xau_score`, 640 JSON, 933 backfill):
- 909 bearish
- 893 neutral
- 818 bullish
## Setup
```bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txt
```
## Train
```bash
python news_sentiment.py train --db newsdata.db \
--extra-labels eval/results/backfill_labels.jsonl
```
This creates:
- `models/xauusd_sentiment.joblib`: fitted model and metadata
- `models/xauusd_sentiment.metrics.json`: training and evaluation report
## Evaluation
The included model's built-in holdouts:
- Stratified random holdout: 69.3% accuracy and 0.689 macro-F1
- Newest chronological holdout (Sep 21–22): 66.6% accuracy and 0.659 macro-F1
These are lower than the 2026-09-17 model's 73.0% / 69.7%. That is because the
test sets now include macro headlines (Fed, dollar, yields), which are harder.
The fair comparison is on the same unseen rows: on Sep 18–22 the 09-17 model
agreed with DeepSeek on 45.9% of headlines (36.2% on macro). This recipe,
retrained daily, reached 62.8% (58.8% on macro). On the independent 78-headline
golden set it scores 47/78; the 09-17 model scored 39/78 and DeepSeek 78/78. See
`eval/RESULTS_2026-09-22.md`.
The data still covers only 15 days of a single market regime. More labelled
history across different regimes is the most valuable next improvement.
## Score News
```bash
python news_sentiment.py score \
--headline "Gold gains as the dollar weakens"
```
Example output from the included model:
```json
{
"target": "XAUUSD",
"label": "bullish",
"score": 0.94748,
"confidence": 0.971834,
"probabilities": {
"bearish": 0.024354,
"neutral": 0.003812,
"bullish": 0.971834
}
}
```
For batch scoring, pass newline-delimited JSON. Each object can contain
`headline` (or `title`/`text`) and an optional `description`:
```bash
python news_sentiment.py score --input articles.jsonl
python news_sentiment.py score --input - < articles.jsonl
```
The command writes JSONL to standard output and adds a `sentiment` object to
each input record.
## Python API
```python
from news_sentiment import load_model, score_news
model = load_model("models/xauusd_sentiment.joblib")
result = score_news(
model,
"Gold slides as Treasury yields rise",
"A stronger US dollar adds pressure to bullion.",
)
print(result)
```
This model estimates XAUUSD sentiment expressed by news. It does not predict
the size or timing of a future price move and is not trading advice.