Inspect a strategy¶
Record a value or label to help understand why your rules fired. These records are separate from confirmed orders and fills.
def on_tick():
if len(close) < 20:
return
average = mean(close, 20)
plot("average", average)
if position.is_flat and close[0] > average:
label("entry signal", price=close[0])
alert("Entry condition matched", level="info")
long(10)
| Function | Purpose |
|---|---|
plot(name, value) |
Record a named numeric value. |
label(text, price=None) |
Record an annotation. |
alert(message, level="info") |
Record a diagnostic message. |
They use bar time. A recorded alert is not a promise of an email, push notification or a visible chart in every application. Rendering and delivery depend on the consuming platform. See plot and alert reference.
Record the decision, then inspect execution¶
Keep plot names stable across bars so a renderer can treat them as one series. Record numeric current values, such as plot("RSI", rsi(close, 14)[0]), rather than an indicator object. Provider-dependent values still require that provider.
Use a label or alert on the branch you want to inspect. A label before long(10) marks a matched condition; it does not confirm submission or a fill. Compare the diagnostic timestamp to actual order/fill records in the backtest or execution report.
Choose useful detail¶
| Question | Record |
|---|---|
| Why did the threshold match? | The indicator value and threshold. |
| Why did a crossover differ from a state rule? | Current and previous relationship. |
| Why was there no entry? | Position state, schedule eligibility and sizing/admission outcome. |
| Why did the trade close? | The matched signal or reported protection exit reason. |
alert accepts info, warn and error; another level raises ValueError. label accepts an optional numeric price. Omitting it leaves price placement to the consuming renderer. Repeating a diagnostic on every bar can create noise; put it at a meaningful state change or condition branch.