Entry, Risk, and Sizing Design
Strategy design guidance for entries as explicit intent, risk and exits as signal-stage logic, and choosing one sizing model per strategy.
Design Entries as Explicit Intent#
Do not let entries emerge accidentally from downstream mapping. Decide the entry direction, timing, and price basis in the signal stage, then emit only the trade-frame fields that represent that decision.
Risk and Exits Are Part of Strategy Logic#
Stops, targets, and trailing offsets are not formatting steps. They reflect how the strategy thinks about risk.
Compute them in build_signal_frame(...) from ATR, structure, or fixed rules and keep the trade frame thin.
Choose One Sizing Story per Strategy#
Most confusion around strategy sizing comes from mixing unit-based and percent-based thinking. Pick one primary sizing model, emit the corresponding field clearly, and keep the other field neutral unless the runtime requires both to be present.
Bracket Risk Fields: sl and tp#
These fields express protective intent. They belong in build_signal_frame(...) because they depend on the
same strategic context as the entry itself: structure, ATR, volatility regime, or bracket policy.
frame["sl"] = np.where(
frame["entry_side"] == "BUY",
frame["entry_price"] - (frame["atr"] * sl_mult),
np.where(frame["entry_side"] == "SELL", frame["entry_price"] + (frame["atr"] * sl_mult), 0.0),
)
frame["tp"] = np.where(
frame["entry_side"] == "BUY",
frame["entry_price"] + (frame["atr"] * tp_mult),
np.where(frame["entry_side"] == "SELL", frame["entry_price"] - (frame["atr"] * tp_mult), 0.0),
)