I built a tool to track my own CS2 (Counter-Strike 2) skin inventory — what it's worth, what I actually made after the Steam Market's 15% fee. Once the data was flowing, an obvious question showed up: do any of the "signals" people chase in this market — momentum, retired cases, cheap vs. expensive — actually predict anything? Or is it noise with a narrative attached?
So I backtested them. Here's what held up, what didn't, and the two bugs the backtest caught in its own scoring model before I caught them.
The setup
I used the price-history cache my tool (SkinVault) already builds — three years of data across 373 price series, about 50,000 samples. For each candidate factor (momentum, price level, case-retirement status, and a few others), I measured its information coefficient (IC): the rank correlation, across items on the same date, between the factor's value and the item's return over some later horizon (7, 30, 90, 365 days).
The "same date" part matters more than it sounds. If you just correlate a factor with returns across your whole dataset without controlling for date, a market-wide rally makes every factor look predictive — everything went up together, so everything "worked." Comparing items cross-sectionally on the same date strips that out: you're asking whether the factor ranked items correctly relative to each other, not whether the whole market moved.
Finding 1: momentum is inverted
The standard momentum trade — buy what's been going up — did the opposite of what you'd expect here. Items that had just risen went on to perform worse than items that hadn't, at every horizon I tested from 7 days out to a year. This market mean-reverts; it doesn't trend.
Flipping the sign of the momentum factors (treating "recently up" as a bearish signal instead of bullish) raised the 90-day IC from 0.035 to 0.160 — a meaningful jump in a space where most individual factors hover near zero.
Finding 2: retired cases are the one edge that survives the fee
This is the strongest result, and the only one that actually clears Steam's 15% cut.
Across 41 cases over the same three-year window, cases that had been pulled from the active drop pool returned a median +48% per year (+25.8% after the fee — and 35 of 35 were positive). Cases still in rotation returned +18.9% gross, which is just +1.0% after the fee. The effect is strongest right after a case retires and fades with age (Spearman correlation of −0.76 between a retired case's age and its subsequent return).
The intuition isn't exotic — supply stops growing, demand doesn't — but seeing the actual spread, and that it's one of the only things that beats the fee at all, was the most useful single number to come out of this.
Finding 3: price is a ceiling
Cheap items appreciate more. Items under R$1 returned a median +73% over a year; items above R$500 returned +8.7%. The correlation holds across the whole dataset (IC −0.26) and within cases specifically (−0.30). Unsurprising in hindsight — more room to move, lower absolute floor — but it's a clean, monotonic effect, not a weak one.
Finding 4: nothing short-term clears the fee
I also checked whether the scanner's composite score (which blends several of these factors) could be used to trade short-term. It can rank items — the top quintile by score gained +13.6% gross over 90 days, clearly ahead of the rest of the distribution — but that's −1.2% after the fee. The score is useful for finding items with better odds; it is not a basis for flipping things in three months. Nothing I tested was.
The backtest caught two bugs in itself
This is the part I think is actually worth sharing beyond the CS2-specific findings.
Future leakage. An early version of a "case vintage" factor computed a case's age using today's date rather than the date being simulated. That meant the backtest was — without anyone intending it — telling the model how old a case would eventually be, which is information it couldn't have had at the time. The factor's apparent one-year IC was +0.22, a great-looking number. Once the bug was fixed and the factor computed age relative to the simulated date instead, that signal vanished entirely. It wasn't predictive; it was a time machine.
A fee miscalculation. The portfolio fee model treated Steam's cut as a percentage of the buy price rather than the sell price. That's a small-sounding error with real consequences: it put the effective break-even at 17.65% instead of the actual 15%, meaning every "is this trade worth it after fees" calculation in the tool was off by 2.65 points, in the pessimistic direction, for as long as the bug existed.
Neither of these would have surfaced from manual review — they only showed up because the backtest was rerun and compared against itself after each change, treating the scoring logic as something to verify rather than something to trust by default.
Limits worth being honest about
Survivorship bias. The dataset only covers items that still trade. Items that effectively died (stopped having a liquid market) aren't well represented, which likely overstates how good the surviving universe looks.
Median-to-median, no spread. Returns compare median sell prices, not actual fill prices, so the buy/sell spread — real cost for anyone actually trading — isn't in these numbers.
Small active sample. Only 5 cases are currently in rotation, so "active case" as a category is thin going forward even though the historical comparison (41 cases) is reasonably sized.
Past data, not a forecast. This describes what happened in this window, not what will happen next. None of it is investment advice.
The tool
I built SkinVault to track this — a free, local, open-source desktop/web app for CS2 inventories and the Steam Market. It never asks for your Steam login (only reads public data), has no account system, and the scanner's score is explainable: every point is traceable to one of the factors above, including the ones that turned out not to help. Full methodology, the AGENTS.md notes on data quirks, and the code are in the repo if you want to check my work or run your own version of this.
Happy to go deeper on the methodology, the IC calculation, or the fee model in the comments if anyone wants specifics I glossed over here.













