Hello,
Quantopian Open will start soon but sometimes I wonder if such contest won't destroy the community spirit of Quantopian (I'm not saying that because I'm pretty sure I won't win this contest ;-) ).
In order to stay in the share spirit of this community (and more generally the open source community) I'm giving a "framework" to manage bracket orders also named here "BO" (with SL, TP) and additional features.
This is still something very experimental... it's not a "strategy" just a way to manage several orders differently.
A bracket order is composed of 3 orders:
- A master order
- A limit order (take profit)
- A stop order (stop loss)
How does it works ?
I created (on top of Zipline blotter) a special blotter named "bo_blotter" (class BOBlotter).
This bo_blotter is created at initialize:
def initialize(context):
context.bo_blotter = BOBlotter(context)
and updated at handle_data
def handle_data(context, data):
bo_blotter = context.bo_blotter
bo_blotter.update(context, data)
This object have several methods which looks like Metatrader 4 API.
tkt = bo_blotter.order_send(symb, LimitOrder(80), volume, context.price_stop_loss, context.price_take_profit, comment, context.magic, features)
for example will create a BracketOrder with a limit order with price of 80 (a buy order if volume>0). 2 others orders are around this order (a sell limit order at price_take_profit and a sell stop order at price_stop_loss).
Every bracket order can have a collection of "features" attached (BOFeatures is a collection of BOFeature).
For now there is 3 features for BO: Expiration, TrailingStop and BreakEven.
An Expiration feature can be attach to a (pending) BO.
If BO was never triggered before expiration reached, bracket order will be canceled (so master order, limit order and stop order will be canceled). Expiration can be set either using a datetime or a timedelta.
We can also attach a TrailingStop to a given bracket order (either using order_send and passing a TrailingStop object as feature or after order_send, when a ticket for BO is given, using bo_blotter.add_bo_feature(tkt, feature)
We can also attach a BreakEven to a given bracket order.
I also add some code from https://github.com/Numergy/signalslot/ a signal slot library.
So you can attach a slot to an "event" (signal).
So for example when expiration is reached you can do something. When take profit is reached you can also do something else. Same for stop loss. This event oriented approach can be very convenient.
An other approach for this could be the use of a pub/sub (publish / subscribe) library.
http://en.wikipedia.org/wiki/Signals_and_slots
http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
BO_Blotter also have statistics for each bracket order, for example Maximum Adverse Excursion (MAE) is compute, same for MFE (Maximum Favorable Excursion).
BracketOrders are stored inside an OrderedDict (attribute of bo_blotter) : with 3 keys: 'trades' (for opened bracket orders), 'history' (for closed bracket orders), 'canceled' (for canceled bracket orders)
All this work is still very experimental and probably still need many improvements. I'm aware of this.
There is also many items in the ToDo list:
for example there is no support for partial close of bracket orders.
MAE, MFE statistics should probably also be defined outside of blotter (maybe a BOBlotterFeature should be created).
Bracket order should also be send according a given risk, a given leverage, ....
Bracket order blotter should also be "secured" in order to ensure that there is no difference between this blotter and the original blotter (but maybe a cleaner approach could be to have this kind of order (bracket orders) directly managed by Zipline blotter.
see https://github.com/quantopian/zipline/issues/366
and https://github.com/quantopian/zipline/issues/189
what happens if master order is only partially filled ?
I hope this can help.
Here:
open BO buy limit AAPL @ 80 with SL=66.9 and TP=96.17
BO is closed because TP is reached