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
Tubesarkilar
JayJayD
Jared Broad
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.
JayJayD
Dmitri Pavlenkov
JayJayD
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;
}
}
}
Michael Handschuh
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 :)JayJayD
JayJayD
Dmitri Pavlenkov
Dmitri Pavlenkov
Michael Handschuh
JayJayD
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 theTransactions.AddOrder(order.StopOrder)
in the wrappers methods? Well, thanks folks, I truly appreciate your time and effort. Cheers, JJDmitri Pavlenkov
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 toStopOrder = 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.JayJayD
Dmitri Pavlenkov
JayJayD
JayJayD
Michael Handschuh
Levitikon
This doesn't seem to work any more. Are there any updates with this? Been integrated into core perhaps?
Build Error: File: /TrailingOrdersWrappers.cs Line:15 Column:34 - Argument 1: cannot convert from 'QuantConnect.Orders.StopMarketOrder' to 'QuantConnect.Orders.SubmitOrderRequest'
JayJayD
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.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!