Skip to content

onTick

onTick(ctx)

At a glance — optional hook fired on every price update within a bar. Receives a TickContext — a BarContext plus live bid and ask. Use for spread checks or intrabar exits; it runs far more often than onBar, so keep it light.

Signature

onTick?(ctx: TickContext): void

Example

hooks/lifecycle
import { defineStrategy } from '@nexpips/sdk-trading';
/**
* Cycle de vie complet : tous les hooks optionnels et les contextes qu'ils
* reçoivent — `InitContext` (init), `BarContext` (onBar), `TickContext`
* (onTick), `EventContext` + `Fill` / `Rejection` / `ClosedPosition` (events).
*/
export default defineStrategy({
symbol: 'EURUSD',
timeframe: 'M5',
risk: {
maxRiskPercentPerTrade: 0.5,
maxOpenPositions: 1,
maxDailyLossPercent: 3,
maxConsecutiveRejects: 5,
},
setup: () => ({
init(ctx) {
ctx.log.info('strategy started', { balance: ctx.account.balance, at: ctx.clock.now });
},
onBar(ctx) {
if (ctx.position.isFlat && !ctx.position.hasPendingOrder) {
ctx.order.marketBuy({
riskPercent: 0.5,
stopLoss: { type: 'pips', value: 20 },
takeProfit: { type: 'rr', value: 2 },
});
}
},
onTick(ctx) {
const spread = ctx.ask - ctx.bid;
if (spread > 0.0005) ctx.log.debug('wide spread', { spread });
},
onOrderFilled(ctx, fill) {
ctx.log.info('filled', { side: fill.side, price: fill.price, size: fill.size });
},
onOrderRejected(ctx, rejection) {
// rejection.reason est un RejectReason (union fermée).
ctx.log.warn('order rejected', { reason: rejection.reason, message: rejection.message });
},
onPositionClosed(ctx, closed) {
ctx.log.info('position closed', { pnl: closed.realizedPnl });
},
}),
});

onTick watches the live spread.

See also