The strategy

A 5-step rulebook

  1. On the daily chart, draw three exponential moving averages: EMA 5, EMA 8, and EMA 13.
  2. Wait until the close prints under all three EMAs for at least 3 consecutive bars. This is the "compression" — price is stretched below its short-term moving averages.
  3. Take the trade on the bar where the close jumps back above all three EMAs in a single candle — i.e., the close is above max(EMA5, EMA8, EMA13).
  4. Enter at 17:30 TR — 30 minutes before the BIST close. (We use 17:30 instead of 17:55 so the operator has time to confirm the setup before the bell.)
  5. Manage next session: with high probability the morning open prints +0.45–0.50% above entry. Take profit there or trail the stop. Hard stop is −1.0% below entry.

Two win rates · which one is real?

We report both. They answer different questions.

  • Touch rate — of all next-day bars after a signal, what fraction had a high reaching +0.45% at any point? This is what an operator watching the morning session can capture by exiting the moment the level prints. It's the "85–90%" claim.
  • Strict win rate — of resolved signals, what fraction reached +0.45% TP before −1% SL on the next bar? Daily OHLC hides intraday path. When both are reachable inside a single bar, we conservatively assume SL fired first. This is the worst-case backtest for an inattentive trader who lets the stop do its job.

The truth lives in the gap between these two. Be honest about which one applies to you.

Data

  • Source: isyatirim.com.tr public HisseTekil endpoint (split/dividend-adjusted daily OHLC). No auth, no key.
  • Latency: end-of-day, ~15 minutes after BIST close. Acceptable for a daily-timeframe strategy.
  • Universe: BIST 30 + a curated set of liquid BIST 100 names. Thinly-traded stocks gap past TP/SL on volume spikes.
  • We do not get an explicit "open" price (the endpoint exposes close, high, low, and adjusted weighted-average price). The TP/SL evaluation only needs high and low — both are real. The "open" stand-in is purely cosmetic for the gap-up badge.

What we built

Next.js 15 app. SQLite-backed daily candle store + signal ledger. The strategy engine is lib/strategy.ts — pure functions over candle arrays. Refresh pipeline pulls universe candles, runs the backtest from full stored history, and upserts signal outcomes idempotently. Charts are lightweight-charts (TradingView's open library).

Operating it

  • Refresh fires on demand via POST /api/refresh (or schedule a curl from cron).
  • Want to track different tickers? Edit lib/universe.ts and refresh.
  • Want to tune TP/SL or streak length? Edit DEFAULT_PARAMS in lib/types.ts, refresh, and watch the win rates move.

Honest disclaimer

Educational. Not financial advice. Backtests describe the past, not the future. The strategy was supplied as a rulebook — we do not endorse it, we just measure it honestly.