static OrderStatus ExecOrd(int bar, Order order, double price, BacktestEval testEval)
{
Position position = session[bar].Summary;
PosDirection posDir = position.PosDir;
OrderDirection ordDir = order.OrdDir;
WayPointType wayPointType = WayPointType.None;
// Orders modification on a fly
// Checks whether we are on the market
if (posDir == PosDirection.Long || posDir == PosDirection.Short)
{ // We are on the market
if (order.OrdSender == OrderSender.Open)
{ // Entry orders
if (ordDir == OrderDirection.Buy && posDir == PosDirection.Long ||
ordDir == OrderDirection.Sell && posDir == PosDirection.Short)
{ // In case of a Same Dir Signal
switch (Strategy.SameSignalAction)
{
case SameDirSignalAction.Add:
order.OrdLots = TradingSize(Strategy.AddingLots, bar);
if (position.PosLots + TradingSize(Strategy.AddingLots, bar) <= maximumLots)
{ // Adding
wayPointType = WayPointType.Add;
}
else
{ // Cancel the Adding
order.OrdStatus = OrderStatus.Cancelled;
wayPointType = WayPointType.Cancel;
FindCancelExitOrder(bar, order); // Canceling of its exit order
}
break;
case SameDirSignalAction.Winner:
order.OrdLots = TradingSize(Strategy.AddingLots, bar);
if (position.PosLots + TradingSize(Strategy.AddingLots, bar) <= maximumLots &&
(position.PosDir == PosDirection.Long && position.PosPrice < order.OrdPrice ||
position.PosDir == PosDirection.Short && position.PosPrice > order.OrdPrice))
{ // Adding
wayPointType = WayPointType.Add;
}
else
{ // Cancel the Adding
order.OrdStatus = OrderStatus.Cancelled;
wayPointType = WayPointType.Cancel;
FindCancelExitOrder(bar, order); // Canceling of its exit order
}
break;
case SameDirSignalAction.Nothing:
order.OrdLots = TradingSize(Strategy.AddingLots, bar);
order.OrdStatus = OrderStatus.Cancelled;
wayPointType = WayPointType.Cancel;
FindCancelExitOrder(bar, order); // Canceling of its exit order
break;
default:
break;
}
}
else if (ordDir == OrderDirection.Buy && posDir == PosDirection.Short ||
ordDir == OrderDirection.Sell && posDir == PosDirection.Long)
{ // In case of an Opposite Dir Signal
switch (Strategy.OppSignalAction)
{
case OppositeDirSignalAction.Reduce:
if (position.PosLots > TradingSize(Strategy.ReducingLots, bar))
{ // Reducing
order.OrdLots = TradingSize(Strategy.ReducingLots, bar);
wayPointType = WayPointType.Reduce;
}
else
{ // Closing
order.OrdLots = position.PosLots;
wayPointType = WayPointType.Exit;
}
break;
case OppositeDirSignalAction.Close:
order.OrdLots = position.PosLots;
wayPointType = WayPointType.Exit;
break;
case OppositeDirSignalAction.Reverse:
order.OrdLots = position.PosLots + TradingSize(Strategy.EntryLots, bar);
wayPointType = WayPointType.Reverse;
break;
case OppositeDirSignalAction.Nothing:
order.OrdStatus = OrderStatus.Cancelled;
wayPointType = WayPointType.Cancel;
FindCancelExitOrder(bar, order); // Canceling of its exit order
break;
default:
break;
}
}
}
else
{ // Exit orders
if (ordDir == OrderDirection.Buy && posDir == PosDirection.Short ||
ordDir == OrderDirection.Sell && posDir == PosDirection.Long)
{ // The Close strategy can only close the position
order.OrdLots = position.PosLots;
wayPointType = WayPointType.Exit;
}
else
{ // If the direction of the exit order is same as the position's direction
// the order have to be cancelled
order.OrdStatus = OrderStatus.Cancelled;
wayPointType = WayPointType.Cancel;
}
}
}
else
{ // We are out of the market
if (order.OrdSender == OrderSender.Open)
{ // Open a new position
order.OrdLots = Math.Min(TradingSize(Strategy.EntryLots, bar), maximumLots);
wayPointType = WayPointType.Entry;
}
else// if (order.OrdSender == OrderSender.Close)
{ // The Close strategy cannot do anything
order.OrdStatus = OrderStatus.Cancelled;
wayPointType = WayPointType.Cancel;
}
}
// Enter Once can cancel an entry order
if (order.OrdSender == OrderSender.Open && order.OrdStatus == OrderStatus.Confirmed)
{
foreach (IndicatorSlot slot in Strategy.Slot)
if (slot.IndicatorName == "Enter Once")
{
bool toCancel = false;
switch (slot.IndParam.ListParam[0].Text)
{
case "Enter no more than once a bar":
toCancel = Time[bar] == lastEntryTime;
break;
case "Enter no more than once a day":
toCancel = Time[bar].DayOfYear == lastEntryTime.DayOfYear;
break;
case "Enter no more than once a week":
toCancel = (Time[bar].DayOfWeek >= lastEntryTime.DayOfWeek && Time[bar] < lastEntryTime.AddDays(7));
break;
case "Enter no more than once a month":
toCancel = Time[bar].Month == lastEntryTime.Month;
break;
default:
break;
}
if (toCancel)
{ // Cancel the entry order
order.OrdStatus = OrderStatus.Cancelled;
wayPointType = WayPointType.Cancel;
FindCancelExitOrder(bar, order); // Canceling of its exit order
break;
}
else
lastEntryTime = Time[bar];
}
}
// Do not trade after Margin Call or after -1000000 Loss
if (order.OrdSender == OrderSender.Open && order.OrdStatus == OrderStatus.Confirmed)
{
if (position.FreeMargin < -1000000 ||
Configs.TradeUntilMarginCall && RequiredMargin(order.OrdLots, bar) > position.FreeMargin)
{ // Cancel the entry order
order.OrdStatus = OrderStatus.Cancelled;
wayPointType = WayPointType.Cancel;
FindCancelExitOrder(bar, order); // Canceling of its exit order
}
}
// Executing the order
if (order.OrdStatus == OrderStatus.Confirmed)
{ // Executes the order
SetPosition(bar, ordDir, order.OrdLots, price, order.OrdNumb);
order.OrdStatus = OrderStatus.Executed;
// Set the evaluation
switch (testEval)
{
case BacktestEval.Error:
session[bar].BacktestEval = BacktestEval.Error;
break;
case BacktestEval.None:
break;
case BacktestEval.Ambiguous:
session[bar].BacktestEval = BacktestEval.Ambiguous;
break;
case BacktestEval.Unknown:
if (session[bar].BacktestEval != BacktestEval.Ambiguous)
session[bar].BacktestEval = BacktestEval.Unknown;
break;
case BacktestEval.Correct:
if (session[bar].BacktestEval == BacktestEval.None)
session[bar].BacktestEval = BacktestEval.Correct;
break;
default:
break;
}
// If entry order closes or reverses the position the exit orders of the
// initial position have to be cancelled
if (order.OrdSender == OrderSender.Open &&
(session[bar].Summary.Transaction == Transaction.Close ||
session[bar].Summary.Transaction == Transaction.Reverse))
{
int initialNumber = session[bar].Position[session[bar].Positions - 2].FormOrdNumb;
// If the position was opened during the current bar, we can find its exit order
bool isFound = false;
for (int ord = 0; ord < session[bar].Orders; ord++)
{
if (session[bar].Order[ord].OrdIF == initialNumber &&
session[bar].Order[ord].OrdSender == OrderSender.Close)
{
session[bar].Order[ord].OrdStatus = OrderStatus.Cancelled;
isFound = true;
break;
}
}
// In case when the order is not found, this means that the position is transferred
// so its exit order is not conditional
if (!isFound)
{
for (int ord = 0; ord < session[bar].Orders; ord++)
{
if (session[bar].Order[ord].OrdSender == OrderSender.Close &&
session[bar].Order[ord].OrdIF == 0)
{
session[bar].Order[ord].OrdStatus = OrderStatus.Cancelled;
break;
}
}
}
// Setting the exit order of the current position
if (session[bar].Summary.Transaction == Transaction.Close)
{ // In case of closing we have to cancel the exit order
int number = session[bar].Summary.FormOrdNumb;
for (int ord = 0; ord < session[bar].Orders; ord++)
{
if (session[bar].Order[ord].OrdIF == number)
{
session[bar].Order[ord].OrdStatus = OrderStatus.Cancelled;
break;
}
}
}
else if (session[bar].Summary.Transaction == Transaction.Reduce)
{ // In case of reducing we have to change the direction of the exit order
int number = session[bar].Summary.FormOrdNumb;
for (int ord = 0; ord < session[bar].Orders; ord++)
{
if (session[bar].Order[ord].OrdIF == number)
{
if (session[bar].Summary.PosDir == PosDirection.Long)
session[bar].Order[ord].OrdDir = OrderDirection.Sell;
else
session[bar].Order[ord].OrdDir = OrderDirection.Buy;
break;
}
}
}
}
}
session[bar].SetWayPoint(price, wayPointType);
if (order.OrdStatus == OrderStatus.Cancelled)
{
session[bar].WayPoint[session[bar].WayPoints - 1].OrdNumb = order.OrdNumb;
}
return order.OrdStatus;
}