Most sentiment-driven trading demos collapse a news feed into a single number between −1 and +1 and treat that as a signal. The number is real; the meaning isn’t. A wave of bullish coverage means something very different on the first day of a story than on the fifteenth.
Argentum keeps the sentiment score but adds the thing that gives it context: where the narrative currently sits in its own lifecycle.
How it works
News items are scored with VADER, then grouped into narratives by keyword clustering, so “industrial demand” and “safe-haven flight” are tracked as separate stories rather than averaged into one mood. Each narrative is assigned a lifecycle phase from its volume and sentiment trajectory — emerging, saturating, or fading.
confidence 0.0 – 1.0
narrative contributing story
phase lifecycle stage
A rule-based agent turns that into a position call. Rules rather than a learned policy, deliberately: with a few hundred labelled days there isn’t enough data to train a policy that generalises, and a rule set has the property I actually wanted, which is that every call can be traced back to the specific narrative and phase that produced it. A confidence score rides along with each decision, so a weak signal is visibly a weak signal instead of an equally-formatted assertion.
The whole thing is exposed through agent_api.py, and there’s a backtest
harness with plots so decisions can be replayed against price history rather than
just inspected one at a time.
What I’d fix
Keyword clustering is the weak joint. It splits narratives that should be one and merges ones that shouldn’t, and the lifecycle phase inherits that error. Embedding based clustering would be the honest next step. The confidence score is also currently a function of rule agreement, not of any calibrated relationship to outcomes — it ranks decisions sensibly but a confidence of 0.8 does not mean the call is right 80% of the time, and it shouldn’t be read that way.
Built with Python, NLTK (VADER), pandas, NumPy, Matplotlib · Source