using System.Collections.Concurrent;
public class ConsolidatorDemoAlgorithm : QCAlgorithm
{
private const string Symbol = "AMD";
private SimpleMovingAverage sma50;
// 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>();
public override void Initialize()
{
SetStartDate(2018, 1, 1);
SetEndDate(2019, 1, 18);
SetCash(10000);
//AddEquity(Symbol, Resolution.Minute);
AddEquity(Symbol, Resolution.Minute, Market.USA, true, 1, true);
AddEquity("SPY", Resolution.Minute);
// Securities[Symbol].SetDataNormalizationMode(DataNormalizationMode.SplitAdjusted);
var minConsolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(5));
minConsolidator.DataConsolidated += OnDataConsolidated;
SubscriptionManager.AddConsolidator(Symbol, minConsolidator);
sma50 = new SimpleMovingAverage(Symbol, 50);
RegisterIndicator(Symbol, sma50, minConsolidator);
}
public void OnDataConsolidated(object sender, TradeBar bar) {
}
//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 (data[Symbol].Close > sma50 && !Portfolio[Symbol].Invested)
{
// 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].Close * .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>();
}
}