| 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>();
}
}