Overall Statistics |
Total Trades 2 Average Win 1.72% Average Loss 0% Compounding Annual Return 21.317% Drawdown 0.300% Expectancy 0 Net Profit 1.720% Sharpe Ratio 6.985 Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.225 Beta -0.07 Annual Standard Deviation 0.027 Annual Variance 0.001 Information Ratio -3.371 Tracking Error 0.106 Treynor Ratio -2.688 Total Fees $2.00 |
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using QuantConnect.Algorithm; using QuantConnect.Data.Market; using QuantConnect.Orders; namespace QuantConnect { public class OneCancelsAllAlgorithm : QCAlgorithm { public const string Symbol = "SPY"; // we need a concurrent data structure since we're using it in both OnData and OnOrderEvent which run on separate t public readonly ConcurrentBag<OneCancelsAll> orderGroups = new ConcurrentBag<OneCancelsAll>(); //Initialize the data and resolution you require for your strategy: public override void Initialize() { //Start and End Date range for the backtest: SetStartDate(2013, 01, 1); SetEndDate(2013, 02, 01); //Cash allocation SetCash(25000); //Add as many securities as you like. All the data will be passed into the event handler: AddSecurity(SecurityType.Equity, Symbol, Resolution.Daily); } //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { if (Transactions.OrdersCount == 0) { // open an initial position MarketOrder(Symbol, 100); var oca = new OneCancelsAll(); // set profit taking order var limitPrice = data[Symbol].Close * 1.05m; var profitTakingTicket = LimitOrder(Symbol, -100, limitPrice, tag: "TakeProfit: " + limitPrice); // set stop loss order var stopPrice = data[Symbol].Low * .99m; var stopLossTicket = StopMarketOrder(Symbol, -100, stopPrice, tag: "StopLoss: " + stopPrice); // add tickets to our oca group oca.Tickets.Add(profitTakingTicket); oca.Tickets.Add(stopLossTicket); orderGroups.Add(oca); } } public override void OnOrderEvent(OrderEvent fill) { Console.WriteLine(Time + ": " + Transactions.GetOrderById(fill.OrderId).Type + ": " + fill); if (fill.Status.IsClosed()) { // find the oca grouping from this fill foreach (var oca in orderGroups) { // check if this oca matches the fill we received if (oca.Tickets.Any(x => x.OrderId == fill.OrderId)) { // cancel all orders that aren't this order id foreach (var ticket in oca.Tickets) { // cancel each other ticket in our OCA group if (ticket.OrderId != fill.OrderId && ticket.Status.IsOpen()) { ticket.Cancel(); Log("Cancelled OCA: " + ticket.OrderId + " tag: " + ticket.Tag); } } } } } } } // class to hold ticks in an OCA group public class OneCancelsAll { public List<OrderTicket> Tickets = new List<OrderTicket>(); } }