All documentation

Trade Filters

Every per-relationship filter that can skip a copy before it's replicated, evaluated together by RiskCalculationService.checkTradeFilters (src/lib/copy-engine/risk-calculation-service.ts), short-circuiting on the first one that blocks. Symbol allow/deny (isSymbolAllowed) and the risk-profile-level filters (Max Open Trades, Time Filter, News Filter, Max Position Size) are evaluated separately — see docs/RISK_PROFILES.md — since they only ever apply to 'open' events, unlike the filters below which apply to every event type.

FilterColumn(s)Pure functionApplies to
Trade Directiondirection_filtercheckDirectionFilterBuy Only / Sell Only / Both
Trading Session/Daysrisk_profiles.time_filtercheckTimeFiltersee docs/RISK_PROFILES.md
Maximum Spreadmax_spread_pointscheckSpreadFilterskips if the follower's live spread exceeds this
Maximum Slippagemax_slippage_pointscheckSlippageFilterskips if price moved too far since the signal
Copy Pending Orderscopy_pending_orderscheckPendingOrderFilteropt-in; position events always eligible
Magic Numbermagic_numbers (integer[])checkMagicNumberFilteronly copy signals tagged with one of these
Comment Containscomment_filter (text)checkCommentFilteronly copy signals whose comment contains this substring

Magic Number / Comment — what's real and what isn't

StandardTrade.magicNumber/.comment (src/lib/connectors/sdk/trade.ts) are populated only by the MT5 connector today (src/lib/connectors/mt5/normalize.ts, reading Mt5Position/Mt5Order/ Mt5Deal's own magic/comment fields — confirmed real fields on the installed metaapi.cloud-sdk's own MetatraderPosition/ MetatraderOrder/MetatraderDeal types, not guessed). "Magic number" is MT4/MT5's own concept (identifies which Expert Advisor opened a position); no other broker this codebase connects to has an equivalent first-class field, so every other connector's StandardTrade output leaves both fields undefined.

A relationship whose master isn't MT5 can still configure a Magic Number or Comment filter — it will simply never match (every non-MT5 signal has no magic number/comment to compare against a configured filter, and checkMagicNumberFilter/checkCommentFilter both treat "the signal has none but the relationship requires one" as a block, not a pass). This is the correct, honest behavior: a filter that can't be evaluated shouldn't silently let everything through.

Configured per relationship in the Copy Relationship dialog (src/components/copier/copy-relationship-dialog.tsx) as a comma- separated magic-number list and a free-text comment substring, parsed by readTradeFilters in src/app/dashboard/copier/actions.ts.

Database

copy_relationships.magic_numbers integer[] and copy_relationships.comment_filter text (migration 20260808030000_magic_number_comment_filters.sql) — both nullable, additive, default to "no restriction" for every relationship that existed before this migration.