Overall Statistics |
Total Trades 3 Average Win 0% Average Loss -1.82% Compounding Annual Return -5.366% Drawdown 33.800% Expectancy -1 Net Profit -5.361% Sharpe Ratio 0.019 Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.382 Beta 1.364 Annual Standard Deviation 0.346 Annual Variance 0.12 Information Ratio -0.887 Tracking Error 0.314 Treynor Ratio 0.005 Total Fees $5.10 |
namespace QuantConnect { public partial class TestingTrailingOrders : QCAlgorithm { string symbol = "IBM"; TrailingStopOrder trailingOrder; public override void Initialize() { SetStartDate(2013, 1, 1); SetEndDate(2013, 12, 31); SetCash(25000); AddSecurity(SecurityType.Equity, symbol, Resolution.Minute); } public void OnData(TradeBars data) { if (!Portfolio.HoldStock) { int quantity = (int)Math.Floor(Portfolio.Cash / data[symbol].Close); Order(symbol, quantity); trailingOrder = FixedTrailingStopOrder(symbol, quantity, data[symbol].Price, 0.95m, Time); } trailingOrder.ActualizeStopPrice(data[symbol].Price); if(trailingOrder.StopOrder != null && trailingOrder.StopOrder.Status == OrderStatus.Update) { int returnCode = 0; if(trailingOrder.StopOrder.Id == 0) { Log(String.Format("Submitting {0}", trailingOrder.StopOrder)); returnCode = Transactions.AddOrder(trailingOrder.StopOrder); } else { Log(String.Format("Updating {0}", trailingOrder.StopOrder)); returnCode = Transactions.UpdateOrder(trailingOrder.StopOrder); } if(returnCode < 1) Log(String.Format("Error: {0}", returnCode)); } } public override void OnOrderEvent(OrderEvent fill) { var order = Transactions.GetOrderById(fill.OrderId); Console.WriteLine(Time + " - " + order.Type + " - " + fill.Status + ":: " + fill); } } }
namespace QuantConnect { /// <summary> /// Method used to trailing the stop loss price. /// </summary> public enum TrailingMethod { FixedPercentage, StandardDeviationStop, // not fully implemented yet // WIP } /// <summary> /// Stop Market Order Type Definition /// </summary> public class TrailingStopOrder : QCAlgorithm, IDisposable { #region Fields and properties /// <summary> /// The symbol wich this order will track. /// </summary> private string _symbol; /// <summary> /// The fixed percentage to determine the trailing stop price. /// </summary> private decimal _stopPricePercentage; /// <summary> /// The window lookback to estimate the standar deviations stop prices. /// </summary> private int _windowLookback; /// <summary> /// The StopMarketOrder object to be used. /// </summary> public StopMarketOrder StopOrder; /// <summary> /// The series history used to estimate the standar deviations stop prices. /// </summary> private RollingWindow<decimal> _seriesHistory; /// <summary> /// Stop price for this stop market order. /// </summary> public decimal StopPrice; /// <summary> /// Is the stop price allowed to move backwards? /// </summary> public bool AllowStopPriceRetreat; // not implemented yet /// <summary> /// The trailing method used to determine the stop price. /// </summary> public TrailingMethod trailingMethod; /// <summary> /// Maximum value of the order at is the stop limit price /// </summary> public decimal Value { get { return StopOrder.Quantity * StopOrder.StopPrice; } } #endregion #region Constructor and destructor /// <summary> /// Initializes a new instance of the <see cref="TrailingStopOrder"/> class. /// </summary> /// <param name="stopOrder">The stop order.</param> public TrailingStopOrder(string symbol, int quantity, decimal price, decimal pricePercentage, DateTime time) { _symbol = symbol; _stopPricePercentage = CheckPercentage(quantity, pricePercentage); trailingMethod = TrailingMethod.FixedPercentage; StopPrice = price * _stopPricePercentage; StopOrder = new StopMarketOrder(symbol, quantity, StopPrice, time); //RegisterTrailingOrder(_symbol); Log("Trailing Stop Order ID " + StopOrder.Id + " set for " + _symbol + " at stop price " + StopOrder.StopPrice); } public TrailingStopOrder(string symbol, int quantity, List<decimal> series, int lookBackWindow, DateTime time) { _symbol = symbol; _windowLookback = lookBackWindow; _seriesHistory = new RollingWindow<decimal>(_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); RegisterTrailingOrder(_symbol); } /// <summary> /// Finalizes an instance of the <see cref="TrailingStopOrder"/> class. /// </summary> ~TrailingStopOrder() { Dispose(); } #endregion #region Methods /// <summary> /// Registers the trailing order to recieve automatic prices updates. /// </summary> /// <param name="symbol">Symbol asset prices to be updated.</param> private void RegisterTrailingOrder(string symbol) { IdentityDataConsolidator<Data.BaseData> trailingOrderConsolidator = new IdentityDataConsolidator<Data.BaseData>(); SubscriptionManager.AddConsolidator(symbol, trailingOrderConsolidator); trailingOrderConsolidator.DataConsolidated += (sender, consolidated) => { this.ActualizeOrder(consolidated.Price); }; } /// <summary> /// Check the order status and dispose the object if is filled. /// If not, estimates the new stop price and update the order if needed. /// </summary> /// <param name="lastPrice">The last price observation.</param> public void ActualizeStopPrice(decimal lastPrice) { decimal newStopPrice; bool priceChanged = false; // If the order is filled, dispose the instance. if (StopOrder.Status == OrderStatus.Filled) { //this.Dispose(); return; } switch (trailingMethod) { case TrailingMethod.FixedPercentage: newStopPrice = lastPrice * _stopPricePercentage; if ((StopOrder.Direction == OrderDirection.Buy && newStopPrice > StopPrice) || (StopOrder.Direction == OrderDirection.Sell && newStopPrice < StopPrice)) { StopPrice = newStopPrice; priceChanged = true; } break; 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; } if (priceChanged) ActualizeOrder(StopPrice); } /// <summary> /// Actualizes the order. /// </summary> /// <param name="StopPrice">The updated stop price.</param> private void ActualizeOrder(decimal StopPrice) { StopOrder.Status = OrderStatus.Update; StopOrder.StopPrice = StopPrice; Log("Trailing Stop Order ID " + StopOrder.Id + " for " + _symbol + " update stop price to " + StopOrder.StopPrice); } /// <summary> /// Gets or sets the stop price percentage, adjusting the value if needed. /// </summary> /// <value> /// The stop price percentage. /// </value> private decimal CheckPercentage(int quantity, decimal pricePercentage) { if (quantity > 0 && pricePercentage > 1m) return pricePercentage - 1m; else if (quantity < 0 && pricePercentage < 1m) return pricePercentage + 1m; else return pricePercentage; } /// <summary> /// Estimates the standar deviation of the historical prices. /// </summary> /// <param name="seriesHistory">The price series history.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> private decimal EstimateSDBand(RollingWindow<decimal> seriesHistory) { throw new NotImplementedException(); } /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { Dispose(); GC.SuppressFinalize(this); } #endregion } }
namespace QuantConnect { public partial class TestingTrailingOrders : QCAlgorithm { #region Wrapper methods /// <summary> /// Instantiate a stop trailing order with stop price estiamted as a price fixed percentage /// </summary> /// <param name="symbol">Symbol asset we're seeking to trade.</param> /// <param name="quantity">Quantity of the asset we're seeking to trade.</param> /// <param name="price">The actual symbol's price.</param> /// <param name="pricePercentage">The price fixed percentage used to estiamte the stop price.</param> /// <param name="time">Time the order was placed.</param> /// <returns>A trailing stop order</returns> public TrailingStopOrder FixedTrailingStopOrder(string symbol, int quantity, decimal price, decimal pricePercentage, DateTime time) { return new TrailingStopOrder(symbol, quantity, price, pricePercentage, time); } /// <summary> /// Instantiate a stop trailing order with stop price estiamted as price +/- a standar deviation. /// </summary> /// <param name="symbol">Symbol asset we're seeking to trade</param> /// <param name="quantity">Quantity of the asset we're seeking to trade.</param> /// <param name="series">Historical prices used to estimate the standar deviation</param> /// <param name="lookBackWindow">The look back window used to estimate the standar deviation.</param> /// <param name="time">Time the order was placed.</param> /// <returns></returns> public TrailingStopOrder SDTrailingStopOrder(string symbol, int quantity, List<decimal> series, int lookBackWindow, DateTime time) { return new TrailingStopOrder(symbol, quantity, series, lookBackWindow, time); } #endregion } }