Orders and callbacks

OnBar returns a slice of orders. Build them with the constructors:

algolang.MarketBuy(sym, qty)                    algolang.MarketSell(sym, qty)
algolang.LimitBuy(sym, qty, price)              algolang.LimitSell(sym, qty, price)
algolang.StopBuy(sym, qty, stop)                algolang.StopSell(sym, qty, stop)
algolang.StopLimitBuy(sym, qty, stop, limit)    algolang.StopLimitSell(sym, qty, stop, limit)
algolang.TrailingStopBuy(sym, qty, trail)       algolang.TrailingStopSell(sym, qty, trail)

Every constructor returns an Order struct you may adjust before returning it – most usefully ClientID (your handle for matching fills and cancels; make it deterministic, see below) and TIF (Day by default; also GTC, IOC, FOK).

algolang.Bracket(entry, takeProfit, stopLoss) wraps any entry order with a take-profit limit and a stop-loss stop. The two exits activate only when the entry fills, and they cancel each other (one-cancels-other); the fill simulator chapter has a worked example. Separately, orders that share a non-empty OCOGroup form a standalone one-cancels-other group: the first to fill cancels the rest. A group member may carry attached orders of its own, so two bracket entries around a bar can be OCO-joined, each with its protective stop: the winner’s attached orders activate at its fill and the losers’ are cancelled with them.

Reacting to fills and cancels

Implement the optional interfaces you care about; the SDK detects them by type assertion:

InterfaceMethod(s)Called when
InitializerOnInit(ctx, cfg)Once, after inputs are applied, before any bar. Validate inputs; read cfg.Instruments, the run range.
LookbackerLookback() intOnce at init; sizes the history buffer and the warmup pre-roll.
FillHandlerOnFill(ctx, fill)An order (or bracket child) filled. The SDK updates ctx.Position before calling you.
CancelHandlerOnCancel(ctx, cancel)An order was cancelled: OCO sibling filled, TIF expired, rejected, or shutdown.
CorporateActionObserverOnCorporateAction(ctx, notice)An equity capital action is announced or becomes effective. Informational.
RollObserverOnRoll(symbol, from, to, ...)A continuous future changes active contract. Informational.
AdoptHandlerOnAdoptedState(ctx, state)Live startup reconciliation seeds existing broker state; an error refuses startup.
ShutdownerOnShutdown(ctx)Once, at end of data. Print summaries here.
SessionHandlerOnSessionStart/EndReserved; no session events are generated in this build.
MultiSymbolIsMultiSymbol() boolDeclares the strategy must see all portfolio symbols in one instance.
DataRequirerDataRequirements() []DataRequirementOnce at init; declares extra data series and symbols beyond the run’s universe (above).
TradeableDeclarerTradeableSymbols() []stringOnce at init; admits declared symbols to the tradeable (venue) universe.
SeriesAlignerAlignedSeries() []AlignedSeriesOnce at init; declares views that carry one series’ latest value onto every bar of another (see Aligned series).
UniverseHandlerOnUniverseResolved(ctx)Once, after the engine resolves the (possibly expanded) universe, before the first bar; ctx.Instrument is populated. A non-nil return refuses the run.
CalendarRequirerNeedsCalendar() boolOnce, after OnInit; true sets InitAck.needs_calendar, asking the engine for the exchange calendar of each root (see Strategy SDK lookups).
CalendarObserverOnCalendar(ctx, cal)Once per pushed root, before the first warm-up bar and after the SDK has stored the calendar, so ctx.Calendar answers inside it; implementing it also sets needs_calendar. A non-nil return refuses the run. The engine pushes one calendar per root it was served (see Engine side).
CapabilityRequirerRequiredCapabilities() []stringOnce at init, after inputs are applied and before OnInit; declares the capabilities the run must put in effect, today only algolang.CapabilityLifetimeV2. A token the engine did not offer refuses the run before OnInit (see Capability negotiation).
OrderUpdateHandlerOnOrderUpdate(ctx, update)One attempt’s status transition (lifetime-v2 only). Under lifetime v2 the working view has already moved on it when the handler runs; on a v1 run no ctx state moves.
CancelResponseHandlerOnCancelResponse(ctx, response)The classified answer to one cancel request (lifetime-v2 only). Like OnOrderUpdate: the view first, then the handler.
TurnHandlerOnLifecycleTurn(ctx, turn)One lifecycle decision turn (lifetime-v2 only): the engine has delivered the outcomes of the strategy’s commands at the turn’s instant and grants a decision on them before the clock advances. Answered as OnBar is, with orders; no bar arrives and no series moves. See Lifecycle turns.

The last four are the SDK’s side of the order-lifetime programme’s v2 protocol (GLE-367 defined it, GLE-377 put it in effect; the wire is in the protocol reference). A strategy that implements the v2 order lifetime returns []string{algolang.CapabilityLifetimeV2} from RequiredCapabilities; the SDK matches it against the engine’s offer before OnInit and refuses the run, with Error code capability_unsupported and a non-nil Run error, when the engine did not offer it. A backtest or an emulated-live run under --lifetime v2 offers it (Lifecycle turns); the default profile offers nothing, so a strategy that requires nothing is unaffected and its InitAck is byte-identical. OrderUpdate carries the attempt (ClientID, Attempt, OrderRef), its Status (an OrderStatus, whose Terminal() is true for Filled, Cancelled, Rejected, Denied and Expired and whose String() renders pending_cancel and the like), the original, filled and remaining quantities, Reason and BrokerCode, ParentClientID and OwnerID; CancelResponse carries the attempt, the RequestID it answers, an Outcome (a CancelOutcome: Confirmed, Pending, Refused or Unknown) and the attempt’s Status and RemainingQuantity as evidence. Both timestamps are the zero time.Time when the wire carries none. The SDK delivers every OrderUpdate and CancelResponse envelope it receives, whatever was negotiated, and a strategy without the observer ignores it: keeping them off a v1 run is the host’s job, not the SDK’s. On a run that negotiated lifetime-v2 each of them moves the attempt-indexed working view before the observer sees it (I3, GLE-372; see The working view under lifetime v2); on a v1 run neither moves anything: ctx.WorkingOrders and ctx.Flat still move on OnFill and OnCancel alone, and a confirmed cancel reaches the view through its OrderCancel event. ctx.Position moves on OnFill alone under either view. On the same footing, Fill (Attempt, ExecID, OrderRef, RemainingQuantity), OrderCancel (Attempt, OrderRef, RequestID, RemainingQuantity), Order.Attempt, AdoptedState.OwnerID and the complete AdoptedOrder frame (TrailAmount, OCOGroup, AttachedOrders, Attempt, OrderRef, Status, FilledQuantity, RemainingQuantity, SubmittedAt, OwnerID) exist on the SDK types. Under lifetime v2 the SDK stamps Order.Attempt on every submission, ctx.Cancel carries the attempt it addresses and a request id, and OnAdoptedState restores the view from the full frame; on a v1 run all of them are zero, the SDK stamps nothing, a cancel request carries the label alone and the view is seeded from the nine v1 fields. The engine’s side of the exchange on the simulated path (attempts echoed on Fill and OrderCancel, the two events, the classified cancel responses and the turns) is --lifetime v2, the programme’s increment I4 unit 4a; the live path’s turns are unit 4b’s, and the full adoption frame belongs to persisted ownership (I7). The view is written to be exact with stamped events and right with the unstamped ones a v1 engine sends.