Back

Trailing Orders

Hi folks,
I'm thinking in develop a class to manage trailing orders. The draft idea is to instantiate a the class at every entry, the object will manage the stop loss price, the exit price and execute the orders.
But first I'd like to know; Is a good implementation? Am I doing some kind of shotgun surgeon?
Thanks in advance. JJ
Update Backtest






The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.



it should be dynamic , trail distance be decided by the volatility on the fly. instantiate once. and use it for the rest of the day or favorite period.
1

Hey @tubesarkilar,
Thanks for you reply, after reading it I downvote my own question! :D
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Dynamic would be cool but its definitely a common request @Juan, I'm sure a lot of people would appreciate a Trailing order type.

You could use a Stop Market Order, and adjust its stop price as the market moves higher -- e.g resetting the price to the lower bollinger band?

If you're feeling bold you could write a FuncStopOrder type which accepts a function! Then people could create their own functions to decide the stop price.
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks Jared for the tip!
I'll code some draft today and I'll share it as soon I have something.
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


I started working on managed orders that will include bracket orders and trailing stop. Managed orders will be separate classes that create and manipulate base Order objects through requests to the engine. Once we have the new order processing in place, I'll finish them up.
2

Hey @Dimitri, very interesting, seems we are in the same boat.
This is my first draft, still need a lot of work but I think the basic idea is clear, is basically a conveyor for a StopMarketOrder. Hope it helps.
@Jared, I definetively don't feel bold :P In this first draft, I tried to incorporate two ways to determining the stop price and implemented just one.
Now some questions:
- How can the class be automatically updated with new prices like indicators?
- Is a destructor call needed once the stop order is filled? How can be implemented?
Cheers, JJ
using System;
using System.Collections;
using System.Collections.Generic;

using QuantConnect.Orders;
using QuantConnect.Indicators;


namespace QuantConnect
{
///
/// Method used to trailing the stop loss price.
///

public enum TrailingMethod
{
FixedPercentage,
StandardDeviationStop,
// More comming soon!
}

///
/// Stop Market Order Type Definition
///

public class TrailingStopOrder
{
///
/// The fixed percentage to determine the trailing stop price.
///

private decimal _stopPricePercentage;

///
/// The window lookback to estimate the standar deviations stop prices
///

private int _windowLookback;

///
/// The StopMarket order to be used.
///

private StopMarketOrder _stopOrder;

///
/// The series history used to estimate the
///

private RollingWindow _seriesHistory;

///
/// Stop price for this stop market order.
///

public decimal StopPrice;

///
/// Signal showing the "StopLimitOrder" has been converted into a Limit Order
///

public bool StopTriggered = false;

///
/// Is the stop price allowed to move backwards?
///

public bool AllowStopPriceRetreat;

///
/// The trailing method used to determine the stop price.
///

public TrailingMethod trailingMethod;

///
/// Gets or sets the stop price percentage, adjusting if is needed.
///

///
/// The stop price percentage.
///

public decimal StopPricePercentage
{
get { return _stopPricePercentage; }
set
{
if (_stopOrder.Direction == OrderDirection.Buy && value > 1m) _stopPricePercentage = value - 1m;
if (_stopOrder.Direction == OrderDirection.Sell && value < 1m) _stopPricePercentage = value + 1m;
}
}

///
/// Maximum value of the order at is the stop limit price
///

public override decimal Value
{
get { return _stopOrder.Quantity * StopPrice; }
}

///
/// Initializes a new instance of the class.
///

/// The stop order.
private TrailingStopOrder(StopMarketOrder stopOrder);

///
/// Fixeds the trailing stop order.
///

/// Symbol asset we're seeking to trade
/// Quantity of the asset we're seeking to trade
/// The actual symbol's price.
/// The price fixed percentage used to estiamte the stop price.
/// Time the order was placed
/// A trailing stop order
public TrailingStopOrder FixedTrailingStopOrder(string symbol, int quantity, decimal price, decimal pricePercentage, DateTime time)
{
StopPricePercentage = pricePercentage;
trailingMethod = TrailingMethod.FixedPercentage;
StopPrice = price * _stopPricePercentage;
_stopOrder = new StopMarketOrder(symbol, quantity, StopPrice, time);
return new TrailingStopOrder(_stopOrder);
}

public TrailingStopOrder SDTrailingStopOrder(string symbol, int quantity, List series, int lookBackWindow, DateTime time)
{
_windowLookback = lookBackWindow;
_seriesHistory = new RollingWindow(_windowLookback);
foreach (decimal seriesValue in series)
{
_seriesHistory.Add(seriesValue);
}

decimal SDBand = EstimateSDBand(_seriesHistory);
StopPrice = (quantity > 0) ? series[series.Count] - SDBand : series[series.Count] + SDBand;
_stopOrder = new StopMarketOrder(symbol, quantity, StopPrice, time);

return new TrailingStopOrder(_stopOrder);
}

///
///
///

/// The last price.
///
private void ActualizeStopPrice(decimal lastPrice)
{
decimal newStopPrice;
bool priceChanged = false;

switch (trailingMethod)
{
case TrailingMethod.StandardDeviationStop:
_seriesHistory.Add(lastPrice);
decimal SDBand = EstimateSDBand(_seriesHistory);
decimal direction = (_stopOrder.Direction == OrderDirection.Buy) ? new decimal(-1) : new decimal(1);
StopPrice = lastPrice + SDBand * direction;
priceChanged = true;
break;

case TrailingMethod.FixedPercentage:
newStopPrice = lastPrice * _stopPricePercentage;
if ((_stopOrder.Direction == OrderDirection.Buy && newStopPrice > StopPrice) ||
(_stopOrder.Direction == OrderDirection.Sell && newStopPrice < StopPrice))
{
StopPrice = newStopPrice;
priceChanged = true;
}
break;
}
if (priceChanged) ActualizeOrder(StopPrice);
}

private decimal EstimateSDBand(RollingWindow _seriesHistory)
{
throw new NotImplementedException();
}

private void ActualizeOrder(decimal StopPrice)
{
_stopOrder.StopPrice = StopPrice;
}
}
}
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hey @Juan!

In LEAN anything can receive automatic updates through the usage of consolidators. Take a peak at how we register the indicators for these updates. In short, we create a consolidator that will give us the data we want, for your case, you just want regular, unaltered, price data, so the IdentityDataConsolidator will do just that, it will forward all input data as it is received to any listeners.

Now that we've created our consolidator, we can then register it using SubscriptionManager.AddConsolidator. This will cause the engine to pump new data for the specified symbol into the consolidator. The IdentityDataConsolidator will forward all price data to any listeners, so the next step is to register an event handler on the DataConsolidated event.

Next we'll attach a listener to the consolidator as is done in RegisterIndicator. What this code is doing is attaching an event handler (MSDN) that will be called each time the consolidator outputs new data!consolidator.DataConsolidated += (sender, consolidated) =>
{
// do something with our 'consolidated' data, such as update stop prices
};


Let me know if there are other LEAN gems I can share :)
1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks @Michael, that was fast! :D
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Here a more serious attempt; don't work, but at least compile and run... well not too serious, there are some guesses. I tried to incorporate the consolidator (RegisterTrailingOrder method in TrailingStopOrder.cs) and a destructor. Both features are deactivated in the shared code.
I know that the StopMarketOrder object is updated because I run in debug mode in VS and the stop price changes acording to the price. But seems the StopMarketOrder doesn't execute when the price hits the stop price.
@MichaelH and @Jared I know how busy you both are, but can someone please check if at least the implementation makes any sense? I feel really swamped, and I'd like to know if it worth to continue with this implementation.
Thanks in advance. JJ
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Juan, I updated your project to send the orders for update to transaction manager. But they still don't seem to be updating. Well, that's something.
1


Sorry about spam, but now I got your orders to submit and update. You get some fills and errors. That's progress!
1


@Juan/@Dmitri

I've made a few updates and I get stop market orders executing. It seems we weren't ever submitting the actual stop market order to the transaction manager (algorithm.Transactions). Also, it looks like there was some added confusion by making the TrailingStopOrder derive from QCAlgorithm, this gave the appearance that functions like logging and such would work, but really they only work on the main algorithm object.

So I've modified your custom order helper class to accept a QCAlgorithm instance so we can do logging and call Transactions.UpdateOrder

EDIT:: @Dmitri, you beat me to the punchline!!
1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Dimitri and @Michael Thank you both so much for your help! Every time I share something here I end up learning a lot.
After incorporate the changes, the code runs better. The class is updated automatically and the stop price moves only in the desired direction (the shared code runs a short position).
However (nothing can be perfect isn’t?) seem that the StopMarketOrder object is filled immediately, any ideas why? Once solved that I think the class will work properly.
Here the log's first lines:
2013-01-02 09:31:00 01/02/2013 09:31:00 - Market - Submitted:: OrderID: 1 Symbol: IBM Status: Submitted
2013-01-02 09:31:00 01/02/2013 09:31:00 - Market - Filled:: OrderID: 1 Symbol: IBM Status: Filled Quantity: 136 FillPrice: 183.377433816
2013-01-02 09:31:00 01/02/2013 09:31:00 - StopMarket - Submitted:: OrderID: 2 Symbol: IBM Status: Submitted
2013-01-02 09:31:00 01/02/2013 09:31:00 - StopMarket - Filled:: OrderID: 2 Symbol: IBM Status: Filled Quantity: 136 FillPrice: 183.377433816

Now, as always, my bothering questions:
1.- The using of a QCAlgorithm in the class, instead inherit it. Is only for the log? I ask because in the register the subscription manager is a method of the QCAlgorithm. Is this the best way to doing it?
2.- I understand now that trying to dispose the class from inside class itself will create a loop. Is there any way to dispose a class after some event (in this case, the order is filled) from the same class?
3.- In this particular case: Is really needed to dispose the instantiated object? I think so because even when I use the same name to point to a new instance, the former instance will be pointed by the SubscriptionManager, so the garbage collector will not clean it. Am I right?
4.- What is the function of the Transactions.AddOrder(order.StopOrder) in the wrappers methods?

Well, thanks folks, I truly appreciate your time and effort.
Cheers, JJ
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Juan, I also noticed that your StopMarket orders seem to fill immediately, but haven't looked at this closely yet, but let me try to respond to your questions

1. it's perfectly fine and correct to pass your QCAlgorithm instance to your classes so they can interact with the engine. In Quantconnect terminal, on the left side you can find Help button, there you can see Quantconnect API with descriptions of classes and their members. Main point is QCAlgorithm is meant to be the gateway for all information and interactions with the engine.

2. Usually it is sufficient to set the reference to null, say if you are done with current order, then StopOrder = null;

3. Let's look at StopOrder field. If you are done with this order and want to assign an new one, then it's sufficient to StopOrder = new ... ;. This makes sure you no longer reference the old object and it can be disposed by garbage collector if possible. However, orders will not be disposed because they are stored by transaction manager. And that's ok. I think you have a 10000 order limit at the moment, and I believe eventually we'll have an ability to clear the cache on demand.

4. Simply creating an order will not submit it. You need Transactions.AddOrder to submit it. Same deal with updating order fields. After you update them, you still need Transactions.UpdateOrder to submit your updated order to broker.
2

@Dmitri thank you so much for your clear answers!
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Jose, you can look at my clone and check the log, I hope I made things more clear. I edited your SetEndDate to reduce log spam.

1. You initiate a short position (negative quantity), therefore your stop order should be positive quantity, so I fixed that in Main.cs.

2. You need to check you stop price calculation viz direction. Your CheckPercentage is confusing. End result is, your algorithm sets stop price on the other side of current price of what it should. Currently, positive stop order has a price below current price, so naturally it is filled immediately.
2


Hey @Dmitri thanks again for your help!

I already tried using the different quantity sign in the market order and in the stop order and didn't worked. Then I guessed that the StopMarketOrders automatically interpret the sing as contrary (my mistake, I must stop guessing and try every conjecture). But your main point is correct! And fixing that, everything seems to works fine!

Respect to the CheckPercentage method, the idea is to avoid a misusage. But I agree, is totally confusing and superfluous, so I deleted it.

Tomorrow I’ll share a (hopefully working) version with all the changes.

Best, JJ
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hi gang,
Seems this time the trailing stop order is working properly!

I made some changes, mainly using the information in the instantiated QCAlgorithm to retrieve some information. So now the wrapper method for a fixed percentage trailing order only needs two inputs, the symbol and the percentage. The quantity is estimated as the negative of the actual positions.

I worked in the implementation of the standard deviation trailing order. In this case the user must input a RollingWindow with the prices to estimate the first band value. I’m using a StandardDeviation indicator, but when I try to fill the indicator with previous values, throws a “This is a forward only indicator” error (InitializeSDBand method).

The shared code runs just for a week to make the log manageable. If you want to try more time, comment the log in the OnOrderEvent method.

I think that maybe a next step is to implement the @Jared idea:
...write a FuncStopOrder type which accepts a function! Then people could create their own functions to decide the stop price.

But I don't have any clue from where to start :D

Well, thanks you all so much! Especially @Dmitri and @MichaelH, I couldn't have done without you help.

Best, JJ

P.S.: I’ll be traveling until the Thursday, so probably I will not be able to respond until then.
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Great news @Jose! Glad to see it working. Eventually we'll want this kind of functionality in he core product.

Just a heads up:

we're in the middle of working in some order update per @Dmitri's pull request. So some of this code may need to change in the near future. I can help with the migration when the new order system comes gets deployed.
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


0

@Levi; Now orders are disconnected from order tickets. The algorithm "requests" and order, and you get a ticket for the request which you can cancel or update directly. This didn't affect 99% of people but you're right it does break this algorithm.

We split it up because the transactions handler who processes the orders and the algorithm are on different threads. If you were to modify the order directly it can cause cross threading issues and kill an algorithm.

As such; the actual order isn't really used in the same sense anymore. Its a system of order tickets and order requests. You can submit a create-request, update-request and cancel-request. The order is tracked with its ticket.

You could tweak this to get it working I think? Theres no reason why you can't have a order ticket being updated to implement the trailing stop. See here for how to do it.  

 

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Levi,

@Jared already gave you a great answer. Just in case, here is a strategy with an implementation of a trailing stop loss; however I'm not sure that strategy still works.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed