< Back to Blog

The Honest Post-Mortem: Why We're Publishing Our Failures Publicly

TL;DR / Key Takeaways

  • We published a complete post-mortem of a bot that lost money because hiding it would have been worse for everyone, including us
  • Honest failure documentation is a competitive advantage in a market flooded with unverifiable success claims
  • "Build in public" means sharing the blood, not just the revenue screenshots
  • The people who buy because of an honest failure story are exactly the people you want as customers

The Part Where I Admit It Publicly

I ran a weather trading bot for four months. It lost money. Not a lot, roughly $23 total, but that's almost beside the point. The real problem was what I found when I audited the trade database: the model had no predictive skill. Zero. It was statistically worse than guessing the historical base rate.

Brier score 0.2858. Base rate guessing: 0.2439. Lower is better. My custom ensemble model, built with 164 forecast members across 4 weather data sources, performed worse than doing nothing.

I had two options. Quietly fix it and move on. Or publish the full autopsy.

I published it.

This post is about why.


What "Build in Public" Actually Means

There's a version of "build in public" that's become a performance. Revenue screenshots on Twitter. "We just crossed $10k MRR!" posts. Milestone threads with rocket emojis. It's marketing dressed up as transparency.

Real transparency is less comfortable. It's posting the month your revenue dropped 40% and explaining why. It's admitting your algorithm failed. It's showing the bug that cost you trades and the six hours you spent finding it.

I'm not saying the revenue milestone posts are dishonest. Sometimes things go well and you should say so. But if you only post wins, you're curating a highlight reel, not building in public. And your audience knows it, even if they don't say it.

The indie hacker community has a phrase I keep coming back to: "show your work." It sounds simple. It's actually hard. Showing your work means showing the dead ends, the wrong turns, the things you tried that didn't work. Most people don't do it because it feels like handing your critics a weapon.

I think it's the opposite. I think hiding the failures is what makes people distrust you.


The Risk I Was Thinking About

Before I published the post-mortem, I sat with the obvious concern for a while.

If I tell people my bot lost money and scored worse than guessing, why would anyone buy it?

That's the real question. And it's a reasonable one. I'm selling a $75 source code package. The last thing I need is the first thing potential customers read being "the bot failed."

Here's where I landed.

The people who would be scared off by an honest failure story are not my customers. They want a bot that prints money. They want the success story with the green dashboard and the passive income claim. That product does not exist here. If they read one paragraph of honest engineering and decide to leave, that's fine. Better for both of us.

The people who read the post-mortem and lean in? Those are my customers. They're the ones who have worked in data long enough to know that a model audit takes real effort. They're the ones who recognize a Brier score and understand what it means when yours is worse than random. They're the ones who appreciate finding and documenting seven distinct technical defects instead of sweeping them under the rug.

Those people don't just buy. They trust you. And in a market where everyone is claiming edge, trust is the actual scarce resource.


The Competitive Landscape Is Full of Silence

Spend any time in trading bot forums or subreddits and you'll notice something. People share their wins constantly. Losses are rare. Detailed failure analysis is almost nonexistent.

This is not because everyone's bots are profitable. It's because failure feels like weakness, and weakness feels like it will cost you customers, followers, or credibility.

The result is an information environment where almost nothing published is useful. If every post-mortem is hidden, the only signal available is success stories, and success stories from people with something to sell are not data. They're marketing.

When I published 112 trades worth of failure, it stood out immediately, not because it was unique in the history of the world, but because it was unique in the current publishing environment. The field had set the bar at "don't talk about losses." I cleared it by doing the opposite.

This is what I mean when I say honesty is a competitive advantage. I'm not being honest because I'm a noble person. I'm being honest because the market for honesty is undersupplied and I can differentiate there.


What the Actual Post-Mortem Looked Like

Here's a condensed version of the audit pipeline I built to analyze the 112 trades. The actual analysis ran against a PostgreSQL database of every trade the bot made.

import pandas as pd
import numpy as np
from sqlalchemy import create_engine

engine = create_engine("postgresql://user:pass@localhost/kalshi_trading")

# Pull completed trades with our probability estimate and actual outcome
query = """
    SELECT
        trade_id,
        market_ticker,
        our_probability,
        kalshi_price,
        outcome,        -- 1 = won, 0 = lost
        settled_at
    FROM trades
    WHERE status = 'settled'
    ORDER BY settled_at ASC
"""

df = pd.read_sql(query, engine)

# Brier score: mean squared error between probability estimate and outcome
# Lower is better. Perfect = 0.0. Coin flip = 0.25.
df['brier_component'] = (df['our_probability'] - df['outcome']) ** 2
our_brier = df['brier_component'].mean()

# Baseline: what if we just predicted the base rate every time?
base_rate = df['outcome'].mean()
df['baseline_brier_component'] = (base_rate - df['outcome']) ** 2
baseline_brier = df['baseline_brier_component'].mean()

print(f"Our model Brier score:    {our_brier:.4f}")
print(f"Base rate Brier score:    {baseline_brier:.4f}")
print(f"Difference:               {our_brier - baseline_brier:+.4f}")

if our_brier > baseline_brier:
    print("RESULT: Our model is worse than guessing the base rate.")

Output when I ran this:

Our model Brier score:    0.2858
Base rate Brier score:    0.2439
Difference:               +0.0419
RESULT: Our model is worse than guessing the base rate.

That's the number that forced the rebuild. Not the $23 loss. The $23 loss I could rationalize. Four months of data, small sample, bad luck, whatever. But a model that underperforms a naive baseline is not a model. It's noise with a UI.

Publishing that output, the actual code and the actual result, is what makes a post-mortem credible. Anyone can say "we found some issues and fixed them." The code is the proof.


The Seven Defects, Briefly

The audit found seven distinct bugs. I've written about each in detail elsewhere, but the list matters here because it shows what "honest post-mortem" actually looks like in practice.

  1. DST date-bucketing error. The bot was analyzing the wrong 24-hour window for eight months of the year because NWS defines weather days in Local Standard Time year-round. Every losing trade fell in this window.

  2. Wrong settlement airports. Chicago settles on Midway, not O'Hare. Houston on Hobby, not Bush Intercontinental. I was using the wrong stations.

  3. xarray truthiness error. Using Python's or operator on an xarray DataArray raises a ValueError. Should have been an explicit None check.

  4. Wrong dict key in kalshi_client.py. get_positions() was reading the wrong key from the API response. The bot could not see its own open positions. One line of code. Largest single impact of the entire project.

  5. Stale settlement status. settle_trade() was missing status = 'settled' in the UPDATE statement. Settled trades stayed open in the local database.

  6. Missing trade decision logging. The trade_decisions table only logged trades that fired. Every rejected candidate was silently dropped. Added 15 call sites to log skip reasons.

  7. Overconfident probability calibration. The ensemble produced 95%+ confidence readings that matched actual outcomes at roughly 60%. Fixed by switching to NOAA's professionally calibrated NBM forecasts.

I could have published "we fixed some bugs and rebuilt the model." Instead I published each defect with its root cause and fix. The difference matters. Vague "we improved things" claims are what every vendor publishes after a bad quarter. Specific defect documentation is what engineers write when they actually understand what went wrong.


What the Response Looked Like

I did not expect what happened next.

Engineers came out of the woodwork. Not to buy, at least not immediately. To share their own DST horror stories. To ask follow-up questions about the Brier score methodology. To send me their own war stories about wrong API keys and stale database rows.

One person told me the wrong-dict-key bug in get_positions() looked exactly like a bug they'd chased for three weeks in a different context. Another said the DST bucketing issue was "a category of error that kills a production data pipeline at least once per engineer."

These are not comments you get when you publish a success story. Success stories generate "congrats!" and "nice work!" Failure stories generate technical conversation. And technical conversation is where trust actually forms.

The buying happened later, and it came from people who mentioned the post-mortem specifically. Not "I saw your bot makes money." More like "I read the audit and I want to see the source for the NBM integration."

That's the customer I want. Someone who read the failure, understood what it meant, and decided the engineering approach was worth $75 regardless of whether the bot is currently validated.


The Argument I Keep Hearing Against This

"But you're giving people a reason not to buy."

Here's the counterargument.

I'm selling source code. Not a financial product. Not a promise of returns. Source code. The value proposition is that it's well-engineered, honestly tested, and built by someone who has demonstrated they'll find the problems and fix them rather than hide them.

If the post-mortem makes someone trust that story more, it's doing its job. If it makes someone distrust it, they were looking for something I don't sell.

There's also a second-order effect that I didn't anticipate. Honest failure stories filter your audience. The people who read a detailed technical post-mortem and decide to engage are serious. They're not looking for a get-rich scheme. They understand that prediction markets are speculative, that bots fail, that validation takes time. Those are the customers who set appropriate expectations, don't flood your inbox with "why isn't this printing money," and actually provide useful feedback.

The filtering effect alone would justify the transparency even if it cost sales.


The Principle Underneath All of This

I've spent 30 years in corporate software. I know what it looks like when an organization hides its failures. Postmortems get buried. Root cause analyses get softened. "We had some issues and we've addressed them" becomes the standard language for everything from a minor bug to a system that was broken for months.

The pattern is consistent: organizations hide failures because leadership fears accountability. And the longer the hiding goes on, the more credibility the organization loses with the people who actually know what's happening.

I'm one person selling source code. I don't have layers of management or a PR team. The only thing I have is what I actually say and whether it matches what I actually do.

Publishing failures is not heroic. It's just honest. And in a market where honesty is rare, rare things have value.


Where the Bot Is Now

The Weather Bot is rebuilt and in paper-trading mode. The NBM integration is running. Forecast quality assessment takes about two weeks once daily verification is running consistently. Whether the strategy has any edge against Kalshi pricing takes 100+ completed trades, which is four to six months at current trading rates.

I'm not claiming it works. I'm claiming I rebuilt it correctly and I'm measuring it honestly. Those are different claims and only one of them is something I can actually support right now.

The Econ Bot is a separate system targeting CPI and PCE markets. Different architecture, different signal stack, different status. That one has its own documentation.

Both are in the $75 source code package if you want to look at the internals yourself.


The Practical Takeaway

If you're building something and you hit a failure, document it before you fix it. Not for marketing purposes. For your own engineering clarity. The discipline of writing "here is exactly what went wrong and why" forces you to actually understand the failure instead of patching around it.

Then publish it. Not because it will definitely help your business. Because the alternative, a track record of only publishing successes, is a track record no one should believe.

Rigor is the edge. Being built to be proven wrong is the whole point.