← Back to portfolio
Case 05Case study

Irrational Signals: intraday trading signals as an API

Statistical signals on US equities, delivered via REST API and Python SDK. Free tier through Pro Max — live subscriptions on Stripe.

Founder·2025 — present
FintechAPI-firstPython SDK
  • Live
    subscription product
  • ~100/hr
    signals across 3 sectors
  • Free → $249
    tiered pricing on Stripe
§ Context

Built solo. The thesis: traders consume signal feeds programmatically. Anyone delivering signals through a dashboard is fighting user behaviour. Build API-first, let traders integrate into their own systems, monetise with tiers that map to actual consumption.

End-to-end ownership of every layer: market-data ingestion, signal generation, the REST API, the Python SDK, subscription billing, customer self-service, support, marketing site, and docs. No infrastructure-team escape hatch.

§ Approach

API-first product with deliberate technical transparency. Every signal carries provenance for its win rate; higher tiers expose live preflight checks against current market conditions; the SDK and raw REST surface are interchangeable.

  • Market-hours signal generation, 6 batches per trading day at :47 past each hour from 10 AM to 3 PM ET. Each batch analyses the prior mid-hour bar across hundreds of US equities in three sectors (Technology, Consumer Cyclical, Communication Services). Volumes are roughly 100–130 signals/hour in calm markets, ~105/hour in volatile ones.
  • Single endpoint — GET /v1/signals — authenticated via X-API-Key. Query params for sector filtering; same-day historical lookback via the hour parameter (Pro Max only). RFC 7807 problem-details errors. Rate-limit headers on every response. Versioned (/v1/) so a future change doesn't break integrations.
  • Win-rate provenance is a first-class field. Every signal carries win_rate_type: per_symbol (validated against ≥10 samples for this exact symbol + pattern — highest confidence), all_symbol (symbol-specific but below threshold), or pooled (signal-level average across symbols — treat as lower confidence). A 78% win rate from 10 samples is not the same as one from 1000, and the API is honest about which it is.
  • Execution guidance on every signal: entry_price, exit_target, primary_horizon (2 hours), and expected_return_pct — derived from the per-signal empirical 2.5-hour paper-forward return over the trailing 90 days, clipped to 0.3–1.5%, refreshed weekly. Pro Max adds a horizon_end timestamp and live preflight checks (price drift vs. entry, intraday range position, relative volume) fetched at request time.
  • Python SDK with typed wrappers, idiomatic error classes (AuthError, RateLimitError with retry_after, APIError with status_code + detail), and the same get_signals / sector / hour surface. pip install irrationalsignals.
  • Three subscription tiers billed on Stripe: Free ($0, 1 signal/day, 25 requests/day), Pro ($99/month, up to 8 signals/hour, 100 requests/day), Pro Max ($249/month, all ~100–130 signals/hour, 500 requests/day, preflight checks + same-day lookback). Field-level tier gating — fields not in your tier are simply absent from the response, never shown blanked out.
API-FIRST SIGNAL DELIVERYMarket dataUS equities · intraday barsStatistical models6 batches per market dayAPI SURFACEGET /v1/signals · X-API-Key · RFC 7807REST APIversioned · rate-limitedPython SDKpip install irrationalsignalsTrader codeautomation · screening · reviewFree · Pro ($99) · Pro Max ($249) — Stripe subscriptions · X-RateLimit headers

Market data → statistical models → versioned REST API + Python SDK → trader code. Live tiered subscriptions on Stripe.

§ Outcomes

Live subscription product with real users on automated billing. Closed loop from product idea to revenue, owning every layer of the stack and every layer of the business.

The discipline that came from being solo is the part I'd export to a team setting. Standardised error format (RFC 7807) from day one; versioned endpoints (/v1/...) so today's signal contract doesn't pin tomorrow's; explicit response-field transparency (win_rate_type, primary_horizon vs. horizon_end, tier echoed in every response). Nothing ships that I can't defend on a Monday-morning support call.

§ Reflection

Solo building forces ruthless scope discipline. The instinct to add 'just one more model' before launch is the single biggest threat — shipping a smaller, narrower product on time beats shipping a wider one late. The win_rate_type provenance field was a late addition and one of the most important: trading customers will assume the best about your numbers unless you tell them what to assume. Saying 'this one is per-symbol with ≥10 samples, that one is pooled' is more credible than a single shiny percentage.