All Articles
Feature10 min readBy Pro Trading Journal

Community Signals & the PTJ Algo Radar: How We Verify Every Call

How Pro Trading Journal separates algo setups, engine-checked community calls and self-reported outcomes, with locked entries and risk details.

πŸ“‘

One Page, Two Different Kinds of Trust

/dashboard/signals looks like a single feature. It's actually two systems sharing a page, and they earn trust in opposite ways.

The Algo Radar is machine-only: three fixed backtest engines scan a crypto watchlist and publish a live trade idea from each one, with a win-rate and expectancy badge that only appears once there's enough sample to mean something. The Community Signals hub is human-only: any Pro trader with a profile can post a directional call β€” market, entry, stop, up to three targets, a thesis β€” and it gets timestamped, locked, and eventually graded by a daily job that replays it against real candles.

Different inputs, same discipline: nothing on this page gets to grade itself. The radar hides its own numbers until the sample is real. The community hub doesn't let a trader's self-report stand unchallenged if the engine can check it. That's the actual product here β€” not signals, but verified signals, machine and human, side by side, with the verification method disclosed for both.

One thing worth saying up front: this page is Pro-gated, requires sign-in, and both it and the trader-profile route are explicitly marked noindex, nofollow. There's no separate marketing page for this feature. This post is the closest thing to public documentation it has.


The Algo Radar Runs Three Strategies, Not Five

Open the strategy source (features/algos/lib/pro/signal-feed.ts) and the current engine list is short on purpose: EMA 20/50 Cross, SMC, and PTJ S&O. Three, not five.

Three used to be five. RSI(2) mean reversion, RSI Divergence, and Pro Fib were pulled off the radar on 2026-07-11, and the file's own header comment records the historical results: RSI(2)'s full-sample expectancy came out to +0.003R, with a negative training split. Divergence was negative in the tested configurations. Pro Fib produced six trades at -0.39R. These results explain the product decision; they do not establish the strategies' future performance.

None of those three strategies disappeared from the product β€” they're still available as chart overlays, and RSI(2) and EMA both have a validated, walk-forward-tested edge documented on the chart side. What changed is narrower: they no longer get a seat on the radar, which only exists to surface strategies with a demonstrated, sample-backed edge across a live watchlist. A strategy that's marginal or negative doesn't belong on a dashboard whose entire pitch is "we only show you numbers we trust."

(If you've seen in-app upsell copy anywhere still promising "5 tuned strategies" β€” that line predates the pruning. Three is the accurate, currently shipped count.)


What Each Strategy Is Actually Scored On

EMA 20/50 Cross β€” the trend rider

Radar settings: target 3R, stop at 2x ATR. The tuning script that produced these settings logged train expectancy of +0.204R and out-of-sample expectancy of +0.168R. It's the same crossover-and-ride logic covered in the Pro engine walkthrough β€” small, frequent losses, occasional trades that run.

SMC β€” the structure read

Radar settings: minimum confidence 5, target 1.5R, adaptive R:R switched off. The tuning script logged train expectancy of +0.290R and out-of-sample expectancy of +0.299R over 280 trades β€” one of the rare cases where the out-of-sample number came in higher than training, which is at least a sign the walk-forward split wasn't flattering it. Full mechanics of what SMC actually detects β€” order blocks, FVGs, liquidity grabs β€” are in PTJ Smart Money Concepts, decoded.

A caveat that applies to both of the numbers above: they live as code comments next to the tuning parameters, documenting what a specific historical run produced β€” not as figures rendered anywhere in the live UI. The dashboard always computes and shows a live win-rate and expectancy from the current watchlist scan, so the exact percentage you see today will drift from these tuning-run figures over time, even though the underlying strategy parameters haven't changed.

PTJ S&O β€” the one we walked back

This is the strategy with a story worth telling in full, because we shipped the wrong version of it first.

On 2026-07-03, a tuning pass (commit 8a16172) set the radar's S&O target to 3R instead of the chart's own default of 2R, because the numbers were marginally better: train expectancy +0.024R versus +0.021R, out-of-sample +0.238R versus +0.218R, at an identical win rate. A real, if small, edge from loosening the target. We shipped it.

Sixteen days later, on 2026-07-19, we reverted it (commit 34ac265). Not because the numbers were wrong β€” because the decision was wrong. Once you retune S&O just for the radar, the radar stops describing the same system a trader can actually inspect and configure on their own chart. It becomes a second, better-tuned S&O that only exists on a dashboard, next to a first, slightly worse S&O that's the one you're actually trading. That gap is exactly the kind of thing this whole page exists to prevent.

PTJ S&O deliberately uses the exact chart defaults. A radar-only target or filter would make the dashboard score a different system from the one traders can inspect and configure on the chart.

So today, S&O's radar settings β€” grade threshold 3, stop at 2x ATR, target 2R β€” are just DEFAULT_SO_SIGNAL, unchanged from what loads on a fresh chart. There's no current headline expectancy number cited for it in the source, on purpose: its stats are computed live from the same aggregation path as EMA and SMC, not pre-baked from a tuning run.


The 100-Trade Gate

A strategy doesn't get a badge just for existing. MIN_SAMPLE_SIZE is 100 β€” a strategy's win-rate and expectancy only render once it has at least 100 closed trades pooled across the whole watchlist. Below that, it's hidden entirely rather than shown with a number too noisy to mean anything.

The watchlist itself is 16 major Binance USDT pairs β€” BTC, ETH, SOL, BNB, XRP, ADA, AVAX, LINK, DOGE, DOT, LTC, BCH, ATOM, TRX, ETC, XLM β€” on the daily timeframe only. Recent-results history is capped at the last 50 resolved trades per strategy; the monthly tuning buckets underneath aren't capped and fold in every trade the strategy has ever closed.

Daily candles (16 pairs) -> 3 causal backtests (EMA, SMC, S&O) -> latest trade per strategy -> radar card
                                                                -> every closed trade -> recent results (last 50)

Refresh is a shared 5-minute server cache backing both the initial page load and the manual Scan button, so two traders loading the page in the same five minutes see identical numbers rather than each triggering their own recompute. The client also auto-rescans once an hour on its own β€” which sounds infrequent until you remember every engine on the radar trades the daily timeframe, so there's genuinely nothing new to compute more than once a day anyway.


Community Signals: A Call You Can't Quietly Edit

The human half works differently. Any Pro trader with a signals profile can publish a call: market, symbol, timeframe, entry type, entry price, stop, up to three targets, and a thesis. The moment it posts, it's locked β€” entry, stop, targets, and timestamp don't move afterward β€” and it fires a notification to every follower.

Following is a plain relationship: a Follow button upserts or deletes a row keyed to the trader's handle, you can't follow yourself, and a new post batches out community_signal.posted notifications 20 recipients at a time, respecting each follower's own notification preferences rather than blasting everyone unconditionally.

Community calls cover four markets β€” crypto, forex, stocks, and indices. Publishing is deliberately limited to instruments the verification engine can replay, so the composer and the server schema both refuse anything else. There's no separate PSX market key in the community-signals type list.


Verified vs. Self-Reported

This is the part that separates a signal feed from a leaderboard of people grading their own homework.

Every still-open community call gets replayed daily against real market data by a cron job (/api/cron/signals, scheduled 0 7 * β€” 07:00 UTC) before it runs the notification scan. The replay function, resolveSignalAgainstBars(), walks hourly OHLC bars with rules deliberately biased toward conservatism: the signal's own posting candle is skipped so it can't "resolve" against the exact bar it was called on; the entry has to actually trade before a target or stop can count against it; if a stop and a target both touch on the same bar, the stop wins the tie; and an entry that never fills within 30 days auto-cancels rather than sitting open forever. A limit call now also carries its fill state: until the engine sees a bar actually trade the entry, the call reads Pending entry rather than Live, the fill instant is written back to the row when it happens, and the only outcome its author may record by hand is a cancellation. On the fill bar itself a stop can resolve the call but a target cannot β€” price reaching the stop proves it passed the entry first, while a target run may have happened before the fill. It's pure and unit-tested β€” 17 tests covering exactly these edge cases.

Signal posted (locked) -> daily 07:00 UTC cron -> replay against real OHLC bars -> target hit / stopped / cancelled -> badge

The payoff for surviving that replay is a badge, and the app is explicit about what each one means. A call the engine resolved shows a cyan Verified pill with a tooltip that reads "Outcome verified by the engine against exchange candles β€” not self-reported." A call the trader closed out manually shows a muted Self-reported pill instead: "Outcome recorded by the trader β€” not yet engine-verified." The resolve modal itself nudges toward the better path before you even click: "Manual outcomes are marked self-reported β€” the engine verifies target and stop touches against exchange candles daily, so letting it resolve earns the verified badge."

Candle sourcing decides what may be published at all: crypto is verified against Binance hourly klines, forex/stocks/indices against Yahoo hourly bars. Commodities have no verifiable feed, so rather than accept a call that could never earn the badge, we stopped offering them. Publishing also resolves the symbol against a live snapshot before the row is written, so an unsupported ticker is refused at post time instead of sitting unverifiable forever β€” and a market-entry call is stamped with the verified price rather than whatever the composer was showing when you hit publish.


The PTJ Community Score

One naming note before the formula, because we now have two scores that sound alike and rank two different things. This is the PTJ Community Score β€” it grades the track record of a trader's published calls. It's a separate system from the PTJ Score on the exchange-synced leaderboard, which grades a trader's actual executed trades by percentile against the rest of the cohort. Similar name, similar spirit β€” score based on what you can prove, discount what you can't β€” but different inputs and a different formula. Nothing here reads from, or feeds into, the leaderboard.

Once a trader has at least 20 engine-resolved signals, they get ranked. Below that, no score β€” the sample is too thin to say anything, so the app says nothing instead of guessing. The qualifier matters as much as the number: a call the trader closed by hand still shows on their profile, but it cannot count toward the threshold or the score. Only outcomes the engine read off exchange candles do, so a trader cannot self-report their way onto the board.

The formula leans on shrinkage rather than raw averages, so that clearing the threshold on a hot run still doesn't outrank someone with a longer record:

shrunkExpectancy = averageR Γ— (n / (n + 12))
bayesianWinRate  = (wins + 2) / (n + 4)
confidence       = min(1, log2(n + 1) / log2(31))
score = clamp(50 + clamp(shrunkExpectancy, -1.5, 2) Γ— 20
                + (bayesianWinRate - 0.5) Γ— 25
                + confidence Γ— 5
                βˆ’ cancellationRate Γ— 15, 0, 100)

A few things fall out of that on purpose. n + 12 in the expectancy term means a trader's raw average R gets pulled toward zero until they've built up real volume β€” three great trades barely move the score, thirty great trades do. The win-rate term adds two phantom wins and four phantom trades before computing a percentage, so a 2-for-2 record doesn't read as a mechanically perfect 100%. And cancellationRate Γ— 15 means cancelled or unfilled calls actively cost points rather than just vanishing from the sample β€” publishing entries you never let trigger, or calls you walk back, has a real cost to your score, not just an absence of credit.

Worth saying plainly: 20 engine-resolved signals is still a lighter bar than the radar's 100-trade gate. The shrinkage math exists specifically to compensate for that, and the app's scoring formula keeps discounting a thin record rather than hiding the trader from the board β€” but twenty verified outcomes is a track record, where three was a weekend.


Trader Profiles and Following

Every ranked trader gets a profile page at /dashboard/signals/traders/[handle] β€” PTJ Community Score, rank (a Top-trader badge for the top 3), win rate, average R, profit factor, count of resolved calls, the full timestamped signal history, and a track-record health panel breaking down published / resolved / wins–losses / cancelled. It's the same gating as the main page: signed in, Pro, noindex.


What This Page Doesn't Try to Be

A few limits, stated plainly rather than buried:

  • Nothing here is public marketing. Both routes are noindex/nofollow and sit behind sign-in plus an active Pro subscription. This page doesn't try to rank in search; it exists for traders already inside the product.
  • Historical tuning numbers aren't live numbers. EMA's +0.168R and SMC's +0.299R are what a specific backtest run produced, preserved as source comments. The badge you see today is computed fresh from the current watchlist and will differ, even though the strategy logic hasn't changed.
  • A 24-hour worst case exists by design. Because auto-resolution runs once a day, a signal that only closes right after the 07:00 UTC run waits until the next day's run to get its badge. That's the tradeoff of a scheduled job instead of constant polling.
  • Commodities can't be engine-verified, full stop, because there's no candle feed to check them against.

Try It

Community Signals and the Algo Radar both live at /dashboard/signals for Pro subscribers β€” see plans if you're not on Pro yet. Once you're in: watch the radar's three strategies until one clears the 100-trade bar on a pair you actually trade, or post your own call and let the daily cron earn you a verified badge instead of a self-reported one.

Compare engine-generated setups with the SMC chart concepts, and check the Pro feature boundaries before using the radar. Verified resolution checks the recorded call against candles; it does not guarantee a profitable next signal.

Recommended reading

Ready to review your trades with a crypto trading journal?

Turn this guide into a repeatable review habit with Pro Trading Journal, a crypto trading journal app for trade records and manual review tags. Starter includes 50 new trades every calendar month with no expiry; Pro adds deeper equity analytics and psychology tools.

Start Your Free Journal