Strategy Building Workflow¶
What is a trading strategy¶
A trading strategy is a set of rules that consumes market events (e.g. arrival of new data points, a order getting executed or rejected etc.) and responds by producing a series of trading orders. A trading strategy is, then , just a set of rules (or a program) that can tells us what to do under any market event. A trading engine can be thought of the sum of tools and infrastructure, that allows a trading strategy to run. A trading engine invokes and run the trading strategy, makes the market events available to the strategy to consume, and routes the orders generated from it to appropriate destinations.
A strategy can be memory-less
, i.e. while consuming market
events and producing orders, it does not have to remember past events or
actions. The rule(s) in this case depends only on the current event and
nothing else. An example of this: if last price greater than 10-period
moving average1, then buy 5 units of the stock. Trading engines that
are most suitable for such strategies are known as rule engines
. These
are stateless
trading engine.
More sophisticated strategies usually depend not only on the latest events
but also the past events, and actions. The strategies are no longer
memory-less
. They need access to past events and its own actions. Trading
engines suitable for such cases are known as complext event processing
engines or CEP
engines. CEP engines are stateful. Blueshift is a CEP
engine, capable of running strategies of any complexity.
Strategy Events for Bluesfhit¶
Strategies for CEP engines focus on defining how to handle market events. These events depends on the specific engine. On Blueshift, we follow the typical events a quant developer will care about. These includes:
-
Start of the strategy: This is an event the strategy will receive only once - at the very start of the run. This is useful for setting up all sorts of initialization that the strategy needs - for e.g. defining the trading universe, trade parameters, placeholder variables etc. On Blueshift, this event invokes the function
initialize
defined within the user strategy. A user strategy on blueshift without defining this function is not a legal strategy. -
Start of the day: This event is raised at the start of the every trading day while the strategy is running. The corresponding function on Blueshift is
before_trading_start
. This is a useful event to carry out start of the day stuff - like periodic model evaluation, book-keeping etc. It is optional to define this function in the strategy. -
Data event: This event is triggered at each incoming data candles. On Blueshift, data candles are generated at minute frequency. This means the corresponding function -
handle_data
- is called every minute. This usually the core of the strategy where data fetching and buying and selling logics go. This is optional as well.
Optionally, you can also define analyze
function, that corresponds to an
event which is raised on the strategy run completes. Apart from this events,
on Blueshift we can also generate time-based events through the
schedule_function function. This allows us to define a
rich set of date and time based rules. The Blueshift engine will trigger
events based on these rules and we can respond (take action, make a trade
etc.) by responding to it.
We have already seen a sample strategy in the quick start section. Now we can hopefully follow the logic more clearly.
Extra event handling for Live Trading
If the live trading broker supports, Blueshift allows to respond to
streaming events as well. For this, use the on_data
function (with
the signature as on_data(callback)
) to respond to streaming data
events in real-time. Or use the on_trade
function for responding to
order fills events. Note: not all brokers support both (or any) of
these, in which case, these callback
functions will be ignored and
never be invoked. The signature of the callback
functions are the
usual callback(context, data)
. The on_data
and on_trade
are API
function so must be imported from blueshift api
(from blueshift.api import on_data, on_trade
). Also both have a
corresponding function to remove the handler, off_data
and off_trade
.
-
Although last 10 period moving average sounds like it depends on past data, in a looser sense, this still can be classified as memory-less as most trading interface allows us to query for past 10 data points anytime. ↩