Signals

What a forex signal is in this addon, the one write path that assigns one to an account, where customers read them, and the limits of the feature before you build a service on top of it.

5 min readUpdated 3 August 2026signals, accounts, admin

Signals are the addon's way of publishing trade ideas to selected customers. Set expectations before you build anything on them: a signal in this product is a title, an image and a status. There is no pair, no direction, no entry, no stop, no target and no expiry — nothing structured that a screen could render as a trade instruction, and nothing a customer's account could act on.

That is not a limitation to work around. It is the shape of the feature: you publish a chart image with a headline, and the customers you assign it to see it.

Creating a signal

Admin → Forex → Signals (/admin/forex/signal).

Field Required Notes
title Yes The headline. Cannot be empty
image Yes The chart or illustration. Cannot be empty
status No Defaults to off. Only active signals are ever returned to a customer

Put the analysis in the image. Since the title is the only text the model carries, everything else you want to say — pair, direction, levels, reasoning — has to be rendered into the picture.

status defaults to false, and both customer-facing read paths filter on status: true. A signal you have created and assigned but not enabled is invisible to everyone. Bulk activation from the table works correctly — an earlier build's bulk-activate switched signals off.

The table supports create, edit, delete, a per-row status toggle and bulk status changes, gated on view.forex.signal, create.forex.signal, edit.forex.signal and delete.forex.signal.

Assigning a signal to an account

A signal reaches a customer through their forex account, not through their user record. The link lives in forex_account_signal, and it is a full many-to-many: one signal can go to many accounts, one account can carry many signals.

The write path is a single endpoint:

Replaces the complete set of signals assigned to one forex account

It takes the whole list, not a delta:

{ "signalIds": ["…", "…", "…"] }

Whatever is not in the list is unassigned. Sending an empty array clears every signal from the account.

The admin account form has four groups — owner, broker and platform, trading settings, account settings — and none of them carries a signal picker. The endpoint above is the only way to write a forex_account_signal row, and you call it directly or from your own tooling.

Note this is still an improvement on where the feature started: it shipped with an admin screen for signals, two ways to read them and a landing-page widget, and nothing anywhere that could assign a signal to an account. Every account's signal list was empty by construction and every subscriber count was permanently zero, so the whole feature could never produce a single result.

The endpoint validates before it writes. Every ID in the list must exist, and an unknown one fails the whole request naming the offenders rather than silently assigning the ones it recognised.

Where customers read them

Two paths, both scoped to the caller:

The caller's signals across every account they hold, paginated
The signals assigned to one specific account the caller owns

Both return active signals only. The first returns an empty result — not an error — for a customer with no forex accounts at all.

Both reads join through the account subscription with an inner join. With an outer join the subscription filter sits in the ON clause and every active signal on the platform comes back regardless of who is assigned to it, which is exactly what used to happen. If you are extending these routes, keep the join required.

The landing page at /forex also carries a signals widget. That one is public and shows the platform's active signals as marketing, independent of assignment.

Operating the feature

A workable pattern, given the model:

  1. Decide what a signal means on your desk — a daily market note, a chart idea, a weekly outlook. Whatever it is, it has to fit in one image and one line of text.

  2. Publish it inactive. Create the signal with status off so it is not visible while you are still assigning it.

  3. Assign it. Call the assignment endpoint for each account that should receive it, sending that account's complete signal list — including the signals it already had, or they will be removed.

  4. Enable it. Toggle status on from the signals table. It becomes visible to every assigned account at once.

  5. Retire it. Toggle status off. The assignment rows stay, so the signal can be brought back without reassigning anything.

Because the assignment call replaces the whole set, read the account's current signals first if you are adding one to an account that already has some.

What signals do not do

Say all of this plainly to your customers, because the interface does not:

  • A signal does not affect an investment. Settlement reads the plan's profit percentage and result. Signals are not an input to any calculation anywhere in the addon.
  • A signal is not sent anywhere. There is no email, push or in-app notification when one is published or assigned. A customer sees it the next time they load a screen that reads signals.
  • A signal has no performance record. Nothing tracks whether a signal was right, and no win rate is computed from them. Any accuracy figure you publish is a claim your install cannot substantiate — which is why the landing page's hard-coded "99.7% Signal Accuracy" was removed.
  • A signal has no expiry. It stays visible until you switch it off.

If you need structured, actionable trade instructions with entry, stop and target — and a record of how they performed — that is a different product. Look at Forex & Multi-Asset Trading or Copy Trading.