Here is how I've modified the code:
protected override void OnBarUpdate()
{
if (State == State.Historical)
return;
if (BarsInProgress != 0)
return;
// Submit OCO entry limit orders if we currently don't have an entry order open
if (longEntry == null && shortEntry == null
&& Position.MarketPosition == MarketPosition.Flat)
{
/* The entry orders objects will take on a unique ID from our SubmitOrderUnmanaged() that we can use
later for order identification purposes in the OnOrderUpdate() and OnExecution() methods. */
if (State == State.Historical)
oco = DateTime.Now.ToString() + CurrentBar + "entry";
else
oco = GetAtmStrategyUniqueId() + "entry";
if (shortEntry == null && ShortOverUnder10() == true) {
//SubmitOrderUnmanaged(0, OrderAction.SellShort, OrderType.StopMarket, 1, 0, mktShortStop, oco, "Short limit entry");
SubmitOrderUnmanaged(0, OrderAction.SellShort, OrderType.StopMarket, 1, 0, mktShortStop, "Short limit entry");
Print(" --- In SHORT? if so set initial stop here? ---");
}
if (longEntry == null && LongUnderOver10() == true) {
//SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.StopMarket, 1, 0, mktLongStop, oco, "Long limit entry");
SubmitOrderUnmanaged(0, OrderAction.Buy, OrderType.StopMarket, 1, 0, mktLongStop, "Long limit entry");
Print(" --- In LONG? if so set initial stop here? ---");
}
}
}
protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
{
/* We advise monitoring OnExecution to trigger submission of stop/target orders instead of OnOrderUpdate()
since OnExecution() is called after OnOrderUpdate() which ensures your strategy has received the execution
which is used for internal signal tracking. */
Print("---------------- On execution Upate ------------------");
if (longEntry != null && longEntry == execution.Order)
{
if (execution.Order.OrderState == OrderState.Filled
|| execution.Order.OrderState == OrderState.PartFilled
|| (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
{
// We sum the quantities of each execution making up the entry order
sumFilledLong += execution.Quantity;
if (State == State.Historical)
oco = DateTime.Now.ToString() + CurrentBar + "LongExits";
else
oco = GetAtmStrategyUniqueId() + "LongExits";
if (stopLossLong == null)
{
Print("---------------- Sstting Long Stoploss ------------------");
SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.StopMarket, execution.Order.Filled, 0, execution.Order.AverageFillPrice - StopDistance * TickSize, oco, "StopLossLong");
}
if (targetLong == null)
{
Print("---------------- Setting Long Target ------------------");
SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Limit, execution.Order.Filled, execution.Order.AverageFillPrice + ProfitDistance * TickSize, 0, oco, "TargetLong");
}
else
{
// Submit exit orders for partial fills
if (execution.Order.OrderState == OrderState.PartFilled)
{
ChangeOrder(stopLossLong, execution.Order.Filled, 0, execution.Order.AverageFillPrice - StopDistance * TickSize);
ChangeOrder(targetLong, execution.Order.Filled, execution.Order.AverageFillPrice + ProfitDistance * TickSize, 0);
}
// Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities
else if (execution.Order.OrderState == OrderState.Filled && sumFilledLong == execution.Order.Filled)
{
// Stop-Loss order for OrderState.Filled
ChangeOrder(stopLossLong, execution.Order.Filled, 0, execution.Order.AverageFillPrice - StopDistance * TickSize);
ChangeOrder(targetLong, execution.Order.Filled, execution.Order.AverageFillPrice + ProfitDistance * TickSize, 0);
}
}
// Resets the entryOrder object and the sumFilled counter to null / 0 after the order has been filled
if (execution.Order.OrderState != OrderState.PartFilled && sumFilledLong == execution.Order.Filled)
{
longEntry = null;
sumFilledLong = 0;
}
}
}
if (shortEntry != null && shortEntry == execution.Order)
{
if (execution.Order.OrderState == OrderState.Filled
|| execution.Order.OrderState == OrderState.PartFilled
|| (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0))
{
// We sum the quantities of each execution making up the entry order
sumFilledShort += execution.Quantity;
if (State == State.Historical)
oco = DateTime.Now.ToString() + CurrentBar + "ShortExits";
else
oco = GetAtmStrategyUniqueId() + "ShortExits";
if (stopLossShort == null)
{
Print("---------------- Setting SHORT Stoploss ------------------");
SubmitOrderUnmanaged(1, OrderAction.BuyToCover, OrderType.StopMarket, execution.Order.Filled, 0, LongStopLoss, oco, "StopLossShort");
}
if (targetShort == null)
{
Print("---------------- Sstting SHORT Target ------------------");
SubmitOrderUnmanaged(1, OrderAction.BuyToCover, OrderType.Limit, execution.Order.Filled, execution.Order.AverageFillPrice - ProfitDistance * TickSize, 0, oco, "TargetShort");
}
else
{
// Submit exit orders for partial fills
if (execution.Order.OrderState == OrderState.PartFilled)
{
ChangeOrder(stopLossShort, execution.Order.Filled, 0, execution.Order.AverageFillPrice + StopDistance * TickSize);
ChangeOrder(targetShort, execution.Order.Filled, execution.Order.AverageFillPrice - ProfitDistance * TickSize, 0);
}
// Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities
else if (execution.Order.OrderState == OrderState.Filled && sumFilledShort == execution.Order.Filled)
{
// Stop-Loss order for OrderState.Filled
ChangeOrder(stopLossShort, execution.Order.Filled, 0, execution.Order.AverageFillPrice + StopDistance * TickSize);
ChangeOrder(targetShort, execution.Order.Filled, execution.Order.AverageFillPrice - ProfitDistance * TickSize, 0);
}
}
// Resets the entryOrder object and the sumFilled counter to null / 0 after the order has been filled
if (execution.Order.OrderState != OrderState.PartFilled && sumFilledShort == execution.Order.Filled)
{
shortEntry = null;
sumFilledShort = 0;
}
}
}
// Reset our stop order and target orders' Order objects after our position is closed.
if ((stopLossLong != null && stopLossLong == execution.Order) || (targetLong != null && targetLong == execution.Order))
{
if (execution.Order.OrderState == OrderState.Filled
|| execution.Order.OrderState == OrderState.PartFilled)
{
stopLossLong = null;
targetLong = null;
}
}
if ((stopLossShort != null && stopLossShort == execution.Order) || (targetShort != null && targetShort == execution.Order))
{
if (execution.Order.OrderState == OrderState.Filled
|| execution.Order.OrderState == OrderState.PartFilled)
{
stopLossShort = null;
targetShort = null;
}
}
}
1. I occasionally get an OCO error indicating the reuse of the OCO number. Do I need the OCO when I'm not placing both Long and Short trades at the same time? I have removed the oco from the SubmitOrderUnmanaged() but now I don't get the stop and take profit orders. I separated the Stop and Take profit orders as eventually want to change this independently with ChangeOrder.
2. My 2nd question is how do I cancel a pending order when the Stop Market order does not fill on the candle the order was placed on? With a managed approach it would cancel automatically. I would like it to function like that.
Thanks!

Comment