I've downloaded and applied the ProfitChaseStopTrailUnmanagedExample Strategy but for the love of god I somehow can't get it to work for both long and short trades respectively.
Can anyone help? If you're curious or haven't seen the Example Script, here it is:
protected override void OnBarUpdate()
{
if (CurrentBars[0] < BarsRequiredToTrade || CurrentBars[1] < BarsRequiredToTrade)
return;
if (BarsInProgress == 0)
sessionIterator.GetNextSession(Time[0], true);
// if after the exit on close, prevent new orders until the new session
if (Times[1][0] >= sessionIterator.ActualSessionEnd.AddSeconds(-ExitOnSessionCloseSeconds) && Times[1][0] <= sessionIterator.ActualSessionEnd)
{
exitOnCloseWait = true;
}
// an exit on close occurred in the previous session, reset for a new entry on the first bar of a new session
if (exitOnCloseWait && Bars.IsFirstBarOfSession)
{
entryOrder = null;
profitTarget = null;
stopLoss = null;
exitFlat = null;
exitSession = null;
exitOnCloseWait = false;
suppressCancelExit = false;
}
// the entry logic can be done when the primary series is processing
if (BarsInProgress == 0)
{
// because this is a demonstration, this code will cause any historical position
// to be exited on the last historical bar so the strategy will always start flat in real-time
if (State == State.Historical && CurrentBar == BarsArray[0].Count - 2)
{
if (entryOrder != null)
{
if (profitTarget != null && (profitTarget.OrderState == OrderState.Accepted || profitTarget.OrderState == OrderState.Working))
CancelOrder(profitTarget);
else if (stopLoss != null && (stopLoss.OrderState == OrderState.Accepted || stopLoss.OrderState == OrderState.Working))
CancelOrder(stopLoss);
ordersCancelled = false;
suppressCancelExit = true;
exitName = "exit to start flat";
exitFlat = placeHolderOrder;
SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Market, 1, 0, 0, string.Empty, exitName);
}
}
// if this is not the last historical bar, and entryOrder is null, then place an entry order
else if (!exitOnCloseWait && entryOrder == null && profitTarget == null && stopLoss == null)
{
entryName = "entry";
entryOrder = placeHolderOrder;
SubmitOrderUnmanaged(1, OrderAction.Buy, OrderType.Market, 1, 0, 0, string.Empty, entryName);
}
}
// all code below this point takes places during BarsInProgress 1 when the secondary series is processing
if (BarsInProgress != 1)
return;
if (ordersCancelled)
{
message = string.Format("{0} stop and/or target cancelled or rejected", Times[1][0]);
if (entryOrder == null || entryOrder.OrderState != OrderState.Filled && PrintDetails)
Print(string.Format("{0} | OBU | entry not filled or is null", Times[1][0]));
// if the orders were cancelled due to the exit on close, do not submit an order to flatten
if (!exitOnCloseWait && !suppressCancelExit && entryOrder != null && entryOrder.OrderState == OrderState.Filled)
{
message += "; exiting and resetting";
if (PrintDetails)
Print(message);
exitName = "exit for cancel";
exitFlat = placeHolderOrder;
SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Market, entryOrder.Filled, 0, 0, string.Empty, exitName);
}
ordersCancelled = false;
return;
}
// the profitTarget/stopLoss is first created when the entry order fills. If it exists then move it.
// trigger the chase action when the current price is further than the set distance to the profit target
if (ChaseProfitTarget &&
profitTarget != null && (profitTarget.OrderState == OrderState.Accepted || profitTarget.OrderState == OrderState.Working) &&
Close[0] < currentPtPrice - ProfitTargetDistance * tickSizeSecondary)
{
currentPtPrice = Close[0] + ProfitTargetDistance * tickSizeSecondary;
ChangeOrder(profitTarget, entryOrder.Filled, currentPtPrice, 0);
}
// trigger the trail action when the current price is further than the set distance to the stop loss
if (TrailStopLoss &&
stopLoss != null && (stopLoss.OrderState == OrderState.Accepted || stopLoss.OrderState == OrderState.Working) &&
Close[0] > currentSlPrice + StopLossDistance * tickSizeSecondary)
{
currentSlPrice = Close[0] - ProfitTargetDistance * tickSizeSecondary;
ChangeOrder(stopLoss, entryOrder.Filled, 0, currentSlPrice);
}
}
protected override void OnExecutionUpdate(Cbi.Execution execution, string executionId, double price, int quantity,
Cbi.MarketPosition marketPosition, string orderId, DateTime time)
{
if (PrintDetails)
Print(string.Format("{0} | OEU | execution | {1} | {2}", Times[1][0], time, execution.ToString()));
if (execution.Order.OrderState != OrderState.Filled)
return;
// when the entry order fully fills, place the profit target and stop loss
if (entryOrder != null && execution.Order == entryOrder)
{
ocoString = Guid.NewGuid().ToString();
if (UseProfitTarget)
{
if (PrintDetails)
Print(string.Format("{0} | OEU | placing profit target", execution.Time));
// calculate a price for the profit target using the secondary series ticksize
currentPtPrice = execution.Order.AverageFillPrice + ProfitTargetDistance * tickSizeSecondary;
profitTarget = placeHolderOrder;
SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Limit, execution.Order.Filled, currentPtPrice, 0, ocoString, "profit target");
}
if (UseStopLoss)
{
if (PrintDetails)
Print(string.Format("{0} | OEU | placing stop loss", execution.Time));
currentSlPrice = execution.Order.AverageFillPrice - StopLossDistance * tickSizeSecondary;
stopLoss = placeHolderOrder;
SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.StopMarket, execution.Order.Filled, 0, currentSlPrice, ocoString, "stop loss");
}
}
}
protected override void OnOrderUpdate(Cbi.Order order, double limitPrice, double stopPrice,
int quantity, int filled, double averageFillPrice,
Cbi.OrderState orderState, DateTime time, Cbi.ErrorCode error, string comment)
{
if (PrintDetails)
Print(string.Format("{0} | OOU | order | {1} | {2}", Times[1][0], time, order.ToString()));
AssignOrderToVariable(ref order);
// if either the profit target or stop loss is cancelled or rejected, then reset for a new entry
if ( !suppressCancelExit && entryOrder != null && order != entryOrder &&
(!UseProfitTarget || (profitTarget != null &&
(profitTarget.OrderState == OrderState.Cancelled ||
profitTarget.OrderState == OrderState.Rejected))) &&
(!UseStopLoss || (stopLoss != null &&
(stopLoss.OrderState == OrderState.Cancelled ||
stopLoss.OrderState == OrderState.Rejected)) )
)
{
// if either the stop or target is cancelled, wait 1 tick in OBU to check
// to see if this was because of the Exit on close occurring or if manually cancelled
ordersCancelled = true;
if (PrintDetails)
Print(string.Format("{0} stop or target cancelled or rejected", Times[1][0]));
}
// once the stop loss or profit target (or exit for flat / exit for manual cancel) fills, reset for a new entry
if ( (profitTarget != null && profitTarget.OrderState == OrderState.Filled && (stopLoss == null || stopLoss.OrderState == OrderState.Cancelled)) ||
(stopLoss != null && stopLoss.OrderState == OrderState.Filled && (profitTarget == null || profitTarget.OrderState == OrderState.Cancelled)) ||
(exitFlat != null && exitFlat.OrderState == OrderState.Filled && (profitTarget == null || profitTarget.OrderState == OrderState.Cancelled) && (stopLoss == null || stopLoss.OrderState == OrderState.Cancelled)) )
{
if (PrintDetails)
Print(string.Format( "{0} | OOU | resetting", Times[1][0] ));
entryOrder = null;
profitTarget = null;
stopLoss = null;
exitFlat = null;
suppressCancelExit = false;
}
// when the Exit on close fills, wait for the new session to start the next entry
// (so no orders are submitted between the exit on close and the end of the session)
if (exitSession != null && exitSession.OrderState == OrderState.Filled)
{
if (PrintDetails)
Print(string.Format("{0} | OOU | exit on close filled waiting for next session for reset\r\n{1}", Times[1][0], order.ToString()));
exitOnCloseWait = true;
}
}
}
}
PS: I had to delete the public class and and all parameters and OnStateChange for it to fit in a post.
Cheers

Comment