Skip to content

Scope SL/TP exit checks to the tick's symbol #33

@mccaffers

Description

@mccaffers

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions