Why I Filter Out 90 Percent of Trades (And Why That Is a Good Thing)
TL;DR / Key Takeaways
- The bot rejects most markets because volume is not the same as edge.
- Four primary filters protect expected value: ensemble spread, confidence, model-market gap, and fee efficiency.
- Aggressive filtering reduces fee drag, overfitting risk, and low-quality signals.
- The system is designed to wait for high-confidence setups and execute without emotional pressure.
Most people who hear that my bot skips 90 percent of available trades assume something is broken. It is not. The filters are the whole point.
Here is the thing about automated trading in prediction markets: the number of trades you take is not a measure of how hard the system is working. Volume is not performance. The bot that trades the most is usually the one losing the most, just faster.
My Kalshi weather trading bot runs 24/7 and evaluates every temperature contract for roughly 14 US cities every time the GFS ensemble updates. That is a lot of markets. And it passes on most of them. Deliberately.
What the Bot Is Actually Looking For
| Filter | Measures | Rejects when | Why it protects edge | | --- | --- | --- | --- | | Ensemble spread | Member disagreement | Forecasts are scattered | Avoids uncertain model states | | Ensemble confidence | Distance from 50/50 | Signal is too close to coin flip | Avoids weak probabilities | | Model vs market gap | Probability mispricing | Market already agrees with model | Avoids no-edge trades | | Fee efficiency | Net value after Kalshi fees | Fees consume too much gross edge | Avoids profitable-looking losers |
The bot scores each potential trade on four factors before it even considers placing an order.
Ensemble spread. The GFS ensemble I use runs 62 members, a hybrid combining 31 traditional GFS physics runs and 31 AI-based AIGEFS members. When those 62 members disagree a lot, spread is high, uncertainty is high, and I am not interested. I want convergence, not chaos. Divergence is risk.
Ensemble confidence. Even if the ensemble agrees directionally, how far is the mean probability from 50/50? A signal that says 52% chance of exceeding the temperature threshold is not a signal worth betting on. The minimum confidence threshold is 0.30, meaning the ensemble needs to be at least 30 percentage points away from a coin flip before I pay attention.
Model vs market gap. The most important number. What is the difference between what the ensemble says the probability is and what the Kalshi market is pricing it at? If the market already agrees with the model, there is no edge. I need the market to be wrong by a meaningful amount, which the ensemble detects routinely because weather data updates faster than market participants reprice.
Fee efficiency. Kalshi takes a fee on every trade. The formula is 0.07 x C x P x (1-P) where C is the number of contracts and P is the contract price. This fee peaks right at the 50-cent contracts that most people trade. If the fee consumes too large a share of the expected edge, the trade does not pass. Period.
All four of those factors have minimum thresholds. If any one of them fails, the trade is skipped. And most trades fail at least one.
Why Filtering This Hard Actually Works
Think about it this way. Imagine you are a poker player who only bets when you have a statistically significant advantage. You fold most hands. Your opponents think you are timid. But when you do bet, you win more often than not because you only played hands where the math was in your favor.
That is the entire strategy here.
The Kalshi weather markets are not perfectly efficient. Weather data is public, free, and updated frequently. But most market participants are either casual bettors or people who read a weather app and make a gut call. The ensemble model is systematically better than a weather app over thousands of forecasts. The edge is real but it is thin.
Thin edges disappear fast if you do not protect them. Overtrading is the fastest way to turn a positive expected value system into a losing one.
By filtering aggressively, the trades that do get placed have a much cleaner signal. The win rate goes up. The average edge per trade is higher. And the fee drag per dollar of expected profit is lower.
The Three Filters That Matter Most
If I had to pick the three filters that do the most work, it is these.
Minimum ensemble edge of 0.10. The model-to-market gap has to be at least 10 percentage points. Not 3. Not 5. Ten. This cuts out all the marginal trades where the model says 54% and the market says 50%. Those trades look tempting but they are noise.
Minimum contract price of 0.20. Contracts priced below 20 cents are nearly impossible to trade profitably after fees. The fee formula punishes extreme contracts less in theory but in practice the liquidity is terrible and the spreads are wide. Skip them.
Ensemble direction must not contradict the trade. This one is subtle but important. If the ensemble mean says 65% chance of exceeding the threshold but the spread is so wide that 40% of individual members disagree, the trade is flagged. A signal that half the ensemble contradicts is not a signal. It is a guess wearing signal clothing.
What Happens When I Loosen the Filters
I tested this. Early in development I ran the bot with looser thresholds to see more volume. The results were predictable: more trades, lower win rate, more fee drag, worse P&L.
It is not surprising in retrospect. Every filter exists for a reason. When you remove a filter, you are saying "I am willing to take trades where this specific condition is not met." Sometimes that works fine. Over a large sample it does not.
The tight filters also protect against model overfitting. Weather forecasts have good days and bad days. GFS is not perfect. The filters add a margin of safety so that when the model has a rough week, the bot is not buried.
This Is Not Caution, It Is Discipline
I want to be clear about something. This is not timid trading. Filtering 90 percent of trades does not mean the bot is sitting there doing nothing.
It means the bot is doing exactly what it is supposed to do: waiting for the right setup and then executing. The trades it does take are placed automatically, sized consistently, and logged in PostgreSQL for full P&L tracking. When the edge is there, the bot acts. When it is not there, the bot waits.
That discipline is hard for humans to maintain manually. It is trivial for a bot. That is one of the real advantages of automation. Not speed. Discipline.
If you want to see the full system including the filter logic, scoring engine, and Kalshi API integration, the source code is available for $67 at predictandprofit.gumroad.com. Everything is in Python, documented, and ready to run.
Frequently Asked Questions
Q: Why does the bot reject most available trades?
A: Most markets fail at least one requirement: ensemble confidence, spread, model-market gap, fee efficiency, liquidity, or minimum price. Rejecting them protects expected value.
Q: What is the most important filter?
A: The model-market gap is central because it measures whether the forecast probability differs from the market price. It still must be confirmed by spread, confidence, and fee checks.
Q: Can strict filters miss winning trades?
A: Yes. The system intentionally misses some winners to avoid many low-quality losers. The goal is not maximum activity; it is positive expected value after costs.