Event Callbacks in Blueshift

Blueshift is an event-driven engine. The core engine implements the event loop. The user strategy implements a set of callback functions ( i.e. event handlers) that are called by the event loop at defined events. The whole strategy logic is structured by responding to events as and when they occur. Blueshift strategies can respond to three types of events during its run.

  • Lifetime Events

    These are events generated by the Blueshift event loop based on the lifetime epochs of the strategy. They are summarised under the Main Callback Functions below.

  • Trade and Data Events

    These are events that are triggered once an order is (potentially partially) filled or on arrival of new data points. They work differently in backtest or real-time trading. See Trade and Data Callbacks below.

  • Time-based Events

    These are events scheduled by the user (using one of the scheduling functions). These are summarised under the Scheduled Callback Functions section.

Main Callback Functions

Lifetime event handlers are based on the epoch of the strategy run. This includes the following:

Initialize

initialize(context)

This is the first entry point function. initialize is called when at the beginning of an algorithm run, only once. For backtest, the call time is at midnight of the start date of the backtest run. For live trading, this is called at the start of the execution as soon as possible.

Parameters:

context (context object.) – The algorithm context.

User program should utilise this function to set up the algorithm initialization (parameters, trading universe, function scheduling, risk limits etc).

Warning

A valid strategy script/ module must have this function defined.

Before Trading Start

before_trading_start(context, data)

This function is called at the beginning of every trading session (day). For backtest, this is called 30 minutes before the regular market open hour everyday. For live trading, this is called 30 minutes before the market opens each day, or just after (around a minute) of the initialize call at the start on the execution start day (in case it is already trading hours or less than 30 minutes remaining from the opening hour).

Parameters:
  • context (context object.) – The algorithm context.

  • data (data object.) – The algorithm data object.

User program should utilise this function to set up daily initialization ( e.g. profit and loss, model re-evaluation etc.)

Warning

User strategy should not depend on the exact time of invocation of this handler function. The only thing that is guaranteed is that it will be called only once per session and will be called before any handle data or scheduled functions.

Handle Data

handle_data(context, data)

This function is called at every clock beat, i.e. every iteration of the event loop (usually at every minute bar).

Parameters:
  • context (context object.) – The algorithm context.

  • data (data object.) – The algorithm data object.

User program should utilise this function to run their core algo logic if the algorithm needs to respond to every trading bar (every minute). For algorithms (or functions) that need to respond at a lower scheduled frequency, it is more efficient to use the scheduling API function to handle such cases.

Note

If the clock frequency is one minute (which is the case at present on Blueshift), this function is equivalent to a scheduled function with time_rule as every_nth_minute(1).

After Trading Hours

after_trading_hours(context, data)

This function is called at the end of every session (every day) around 5 minutes after the last trading minute (market close).

Parameters:
  • context (context object.) – The algorithm context.

  • data (data object.) – The algorithm data object.

User program should utilise this function to do their end-of-day activities (e.g. update profit and loss, reconcile, set up for next day).

Warning

User strategy should not depend on the exact time of invocation of this handler function. The only thing that is guaranteed is that it will be called only once per session and will be called after the end of the regular market hours.

Analyze

analyze(context, performance)

This function is called only once, at the end of an algorithm run, as soon as possible.

Parameters:
  • context (context object.) – The algorithm context.

  • performance (pandas.DataFrame) – The algorithm performance.

Note

The performance object is a DataFrame with algo performance captured at daily intervals. The dataframe timestamps are the timestamps for after_trading_hours calls. The columns include some of the algo account fields as well the profit and loss (pnls) metrics.

See also

on_error for exit with a fatal error. on_cancel for exit after a cancellation of algo run. on_exit for exit in any cases.

User program can implement this method to add custom analysis of backtest results or after a live run completion. The analyze callback will be called only when the strategy exits normally (reaches end of the algo run without any fatal error).

Trade and Data Callbacks

Attention

only available for live trading, for brokers supporting streaming for data and trade updates.

These callback APIs on Blueshift allows the user strategy to respond to the markets events as it happens (in real-time for live mode).

On Data

on_data(context, data)

This event handler is invoked at arrival of new data points. This function is called at every clock tick, i.e. every iteration of the event loop (usually at every minute bar) in backtest mode. In realtime mode, this is invoked only if the broker supports real-time data streaming and a new data point has been made available. In the case of the latter, only instruments that the algo has subscribed to can trigger a call to this function.

Parameters:
  • context (context object.) – The algorithm context.

  • data (data object.) – The algorithm data object.

Important

The on_data event handler is called only when triggered by the underlying broker. For that to happen, the broker must support streaming data (market data websockets or socketIO API), as well as the strategy must have subscribed to at least one instrument for streaming data. There is no explicit API to subscribe to streaming data, but curret or history will automatically trigger data subscriptions for the queried assets. If you are using this handler, make sure you have triggered a call to one of these methods to enable subscription. Without it, the handler will never be called.

Warning

The callback function must be short and quick to avoid creating a backlog. Adding long running funtions may lead to the algo crashing. Also, a temporary network disconnection will cause this event handler to stop triggering (till the connection is restored). To make sure your strategy logic is robust, you can also put the same logic inside handle_data to make sure the strategy logic is triggered at least once every minute, even if there is a disconnection. Of course, this depends on the specific need of a given strategy.

See also

See available callback types blueshift.protocol.AlgoCallBack.

On Trade

on_trade(context, data)

This event handler is invoked when an order placed by the strategy is filled. This function is called when the simulator fills an order in backtest mode or paper trading mode. In realtime mode, this is invoked only if the broker supports real-time order update streaming and an order has been filled.

Parameters:
  • context (context object.) – The algorithm context.

  • data (data object.) – The algorithm data object.

See also

See available callback types blueshift.protocol.AlgoCallBack.

Warning

The callback function must be short and quick to avoid creating a backlog. Adding long running funtions, may lead to the algo crashing.

On Stoploss

on_stoploss(context, asset)

This event handler is invoked when a (previously set) stoploss target is hit. The parameter asset is the asset object for which the position hit the target. If the stoploss is strategy-level, asset will be None.

Note

If a specific callback is supplied while setting up the stoploss, This function will not be called, instead the one supplied will be invoked.

Parameters:
  • context (context object.) – The algorithm context.

  • data (asset object.) – The asset object for the trigger, or None for strategy.

On Takeprofit

on_takeprofit(context, asset)

This event handler is invoked when a (previously set) takeprofit target is hit. The parameter asset is the asset object for which the position hit the target. If the takeprofit is strategy-level, asset will be None.

Note

If a specific callback is supplied while setting up the takeproft, This function will not be called, instead the one supplied will be invoked.

Parameters:
  • context (context object.) – The algorithm context.

  • data (asset object.) – The asset object for the trigger, or None for strategy.

Scheduled Callback Functions

The scheduled event callbacks provide a way to schedule a callback function (with signature func(context, data)) based on a date and time based rule. There is no limit on how many callbacks can be scheduled in such a manner. But only one callback can be scheduled at each call of the schedule_function.

Schedule Soon

TradingAlgorithm.schedule_soon(callback)

Add a callback to be called as soon as possible. The callback must have the standard call signature of f(context, data). The handler will be called for live modes as soon as possible, if in trading hours, else will be called in the next trading bar for the day. For backtest, it will always be next trading bar (exactly same behaviour as schedule_once).

Parameters:

callback (callable) – Callback function to run.

Note

  • This schedules the callback to run one time only. For repetitive callbacks, use schedule_function below

  • The callback can use this function to schedule itself recursively, if needed.

Schedule Once

TradingAlgorithm.schedule_once(callback)

Add a callback to be called once at the next event processing cycle. The callback must have the standard call signature of f(context, data). The handler will be called in the next trading bar - for both backtest and live modes.

Parameters:

callback (callable) – Callback function to run.

Note

  • This schedules the callback to run one time only. For repetitive callbacks, use schedule_function below

  • The callback can use this function to schedule itself recursively, if needed.

Schedule Later

TradingAlgorithm.schedule_later(callback, delay)

Add a callback to be called once after a specified delay (in minutes). The callback must have the signature f(context, data). The callback will be triggered during the market hour only.

Parameters:
  • callback (callable) – Callback function to run.

  • delay (number) – Delay in minutes (can be fractional).

Note

  • This schedules the callback to run one time only. For repetitive callbacks, use schedule_function below

  • The callback can use this function to schedule itself recursively, if needed.

  • You cannot use this method from the initialize or the before_trading_start methods. This function must be called during trading hours.

  • You can use a fractional number to run a function at higher frequency resolution than minute. For example specifying delay=0.1 will run the callback after 6 seconds. This is only applicable for live runs. For backtests, it will fall back to one minute minimum. The minimum delay that can be specified is 1 second.

Warning

There is no guarantee the function will be called at the exact delay, but if it is called, it will be called at least after the specified delay amount. Also, scheduling are not carried forward over the end-of-day.

Schedule At

TradingAlgorithm.schedule_at(callback, at)

Add a callback to be called once at a specified time (in hh:mm format or as a hour,minute tuple). The callback must have the signature f(context, data). The callback will be triggered during the market hour only.

Parameters:
  • callback (callable) – Callback function to run.

  • at (number) – Time as hh:mm or as hour,minute tuple.

Note

  • This schedules the callback to run one time only. For repetitive callbacks, use schedule_function below

  • The callback can use this function to schedule itself recursively, if needed.

  • You cannot use this method from the initialize or the before_trading_start methods. This function must be called during trading hours.

Warning

There is no guarantee the function will be called at the exact time, but if it is called, it will be called at least at or after the scheduled time. Also, scheduling will not be carried forward over the end-of-day.

Schedule Function

TradingAlgorithm.schedule_function(callback, date_rule=None, time_rule=None)

Schedule a callable to be executed repeatedly by a set of date and time based rules. Schedule function can only be triggered during trading hours. The callable in the schedule function will be run before handle_data for that trading bar. The callback must accept two arguments - context and data.

Parameters:

Warning

  • This method can only be used within the initialize function. Attempting to set a scheduled callback anywhere else will raise error and crash the algo.

  • The offset should be meaningful and always non-negative. For e.g. although the hours offset can be maximum 23, using such an offset is not meaningful for shorter trading hours (unless it is a 24x7 market).

  • In live trading, there is no guarantee that the scheduled function will be called at exactly at the scheduled date and time. It may be delayed if the algorithm is busy with some other function. The function is guaranteed to be called no sooner than the scheduled date and time, and as soon as possible after that.

Date Rules

class blueshift.api.date_rules

Date rules define the date part of the rules for a scheduled function call. The supported functions are as below (further subjected to time rule). The days_offset parameter below (if applicable) must be int (positive), and it must not be greater than 3 for week_start/week_end and must not be greater than 15 for month_start and month_end. The weekday parameter can be either an integer between 0 (Monday) to 6 (Sunday), or a string representing the day of week (e.g. “Fri”, or “Friday”).

  • every_day(): called every day.

  • week_start(days_offset=0): days_offet days after the first trading day of the week.

  • week_end(days_offset=0): days_offet days before the last trading day of the week.

  • week_day(weekday=0): Run on given weekday - can be either an integer or weekday name or list of the same.

  • month_start(days_offset=0): days_offet days after the first trading day of the month.

  • month_end(days_offset=0): days_offet days before the last trading day of the month.

  • on(dts): called every day in the list dts (must be list of pandas Timestamps or DatetimeIndex).

Time Rules

class blueshift.api.time_rules

time rules defines the time part of the rules for a scheduled function call. The supported functions are as below (further subjected to date rule).

The hours parameter below (if applicable) must be int, (positive) and it must not be greater than 23. The minutes parameter below (if applicable) must be int (positive) and must not be greater than 59.

  • market_open(minutes=0, hours=0): called after hours and minutes offset from market open.

  • on_open(minutes=0, hours=0): Alias for market_open.

  • market_close(minutes=0, hours=0): called after hours and minutes offset before market close.

  • on_close(minutes=0, hours=0): Alias for market_close.

  • every_nth_minute(minutes=1): called every n-th minute during the trading hours.

  • every_nth_hour(cls, hours=1): called every n-th hour during the trading hours.

  • every_hour(): called every hours during the trading day.

  • at(dt): Called at the given time dt (must be a datetime.time object).

Scheduling Examples

Repetitive Logic with Scheduling

The below code shows examples of setting up a monthly callback function, to be called on the first business day of each month, 30 minutes before the market close.

from blueshift.api import schedule_function, date_rules, time_rules
from blueshift.api import get_datetime

def initialize(context):
    schedule_function(myfunc,
                      date_rule=date_rules.month_start(),
                      time_rule=time_rules.market_open(minutes=30))

def myfunc(context, data):
    print(f'scheduled function called at {get_datetime()}')

Responsive Strategy with Scheduling

The below code shows examples of placing a limit order and then updating the order to optimize time to fill and fill price. The algo terminates once the order is executed.

from blueshift.api import schedule_later, schedule_once, symbol, terminate
from blueshift.api import terminate, order, update_order, get_order

def initialize(context):
    context.asset = symbol('AAPL')
    context.order_id = None
    schedule_once(myfunc) # call as soon as ready

def myfunc(context, data):
    if context.order_id is None:
        context.order_id = order(context.asset, 1)
        if not context.order_id:
            raise ValueError(f'something went wrong.')

        schedule_later(myfunc, 1) # call again after one minute
        return

    o = get_order(context.order_id)
    if o.is_open():
        px = data.current(context.asset, 'close')
        update_order(context.order_id, price=px)
        schedule_later(myfunc, 1) # call again after one minute
    else:
        # we are done
        terminate(f'order executed, terminate now.')

If you are using schedule_once or schedule_later recursively, carefully follow your logic and make sure the recursion ends where it needs to.

User Order Confirmation Callback

Attention

only available for live trading, when running in oneclick execution mode.

On Oneclick

blueshift.api.on_oneclick(notifications)

This callback function is invoked when notifications (raised when a order notification is generated in oneclick mode) are either confirmed by the user or expired or some error occured. The input parameter notifications is a dictionary with notification ID (returnd from the ordering functions in oneclick mode) as key and the final state of that notification as value. This is a global handler, i.e. it is called only in the parent algo context, and not any sub-contexts.

See also

See available status types blueshift.protocol.OneClickState. See execution mode blueshift.api.ExecutionMode.

Algo Error and Cancel Callbacks

User strategy can define an error or cancel handler if desired. Only one of them will be triggered - depending on if the algo exits by a user cancel or with an error. If the algo finishes the run normally, none of these will be invoked (and the analyze callback will be called instead). These callbacks are for any reporting purposes and should not be used to place orders or trigger square-offs/ order cancellations. To handle square-off/ cancellation behaviour on exit, see set_exit_policy under risk management.

On Cancel

blueshift.api.on_cancel(context)
Parameters:

context (context object.) – The algorithm context.

This callback function is invoked once if the strategy exits following a user cancel. The only argument to this function is the context object.

On Error

blueshift.api.on_error(context, error)
Parameters:
  • context (context object.) – The algorithm context.

  • error (str) – The error message.

This callback function is invoked once if the strategy exits with an error. The first argument is the context object. The second argument can be either a string (in which case it is the error message), or an exception object.

On Exit

blueshift.api.on_exit(context)
Parameters:
  • context (context object.) – The algorithm context.

  • error (str) – The error message.

This callback function is invoked once on strategy exit. This will always be invoked (after any one of analyze, on_error or on_cancel as the case maybe) before the final strategy exit.