Add a symbol filter inside reviewStopAndLimit in source/operations.cpp:30-44 so SL/TP checks only run on trades whose trade.symbol matches the incoming tick.symbol. Today the loop iterates every open trade and calls trading::exit_rules::checkExit(trade, tick) regardless of symbol. checkExit (defined inline in include/trading/exitRules.hpp:31-56) compares tick.bid/tick.ask directly against trade.exitReferencePrice ± offset, with no symbol awareness — so an AUSIDXAUD tick at price ~1 fed against a LONG EURUSD trade with exitReferencePrice ~1.1 trivially satisfies tick.bid <= stopPrice and the trade is closed at the wrong price.
The codebase already carries the data needed for the fix: Trade::symbol is populated from tick.symbol at open in source/trading/tradeManager.cpp:28 (Trade trade(price, size, direction, tick.symbol);), and PriceData::symbol is set by the SQL stream loader in source/databaseConnection.cpp:70-77. Multi-symbol streaming is already wired up: SqlManager::streamPriceData (source/sqlManager.cpp:12-22) takes a vector of symbols parsed from config in source/main.cpp:49-56, so the latent bug becomes a real one as soon as a config lists more than one symbol. The author's "smallest viable change" framing is correct — no struct changes, no signature changes, just a guard at the top of the existing range-for body.
Existing XCTest cases in tests/tradeManager.mm (lines 32-201) all construct ticks and trades with "EURUSD", so they exercise the matching-symbol path only and will continue to pass unchanged. There are no existing tests that drive reviewStopAndLimit itself (it lives in an anonymous namespace inside source/operations.cpp) — exit-rule coverage today is via the inlined checkExit directly. The acceptance criterion of "EURUSD trades only exit on EURUSD ticks" therefore needs a new regression test, which is most naturally added at the checkExit callsite level by exposing the behavior through a small test against TradeManager + a cross-symbol tick, or by lifting reviewStopAndLimit out of the anonymous namespace for testability; the simplest option is the former, since checkExit itself is symbol-agnostic by design and the guard belongs at the caller.
Add a symbol filter inside
reviewStopAndLimitinsource/operations.cpp:30-44so SL/TP checks only run on trades whosetrade.symbolmatches the incomingtick.symbol. Today the loop iterates every open trade and callstrading::exit_rules::checkExit(trade, tick)regardless of symbol.checkExit(defined inline ininclude/trading/exitRules.hpp:31-56) comparestick.bid/tick.askdirectly againsttrade.exitReferencePrice± offset, with no symbol awareness — so anAUSIDXAUDtick at price ~1 fed against aLONGEURUSDtrade withexitReferencePrice~1.1 trivially satisfiestick.bid <= stopPriceand the trade is closed at the wrong price.The codebase already carries the data needed for the fix:
Trade::symbolis populated fromtick.symbolat open insource/trading/tradeManager.cpp:28(Trade trade(price, size, direction, tick.symbol);), andPriceData::symbolis set by the SQL stream loader insource/databaseConnection.cpp:70-77. Multi-symbol streaming is already wired up:SqlManager::streamPriceData(source/sqlManager.cpp:12-22) takes avectorof symbols parsed from config insource/main.cpp:49-56, so the latent bug becomes a real one as soon as a config lists more than one symbol. The author's "smallest viable change" framing is correct — no struct changes, no signature changes, just a guard at the top of the existing range-for body.Existing
XCTestcases intests/tradeManager.mm(lines 32-201) all construct ticks and trades with"EURUSD", so they exercise the matching-symbol path only and will continue to pass unchanged. There are no existing tests that drivereviewStopAndLimititself (it lives in an anonymous namespace insidesource/operations.cpp) — exit-rule coverage today is via the inlinedcheckExitdirectly. The acceptance criterion of "EURUSD trades only exit on EURUSD ticks" therefore needs a new regression test, which is most naturally added at thecheckExitcallsite level by exposing the behavior through a small test againstTradeManager+ a cross-symbol tick, or by liftingreviewStopAndLimitout of the anonymous namespace for testability; the simplest option is the former, sincecheckExititself is symbol-agnostic by design and the guard belongs at the caller.