When I run it, it seems to want to launch trades on historical bars. Obviously I don't want that. If it wants to show me the trades that would have occurred, that's fine, but I sure don't want it to try to send actual orders based on historical bars!
One of the first messages I get in the Output window is this:
Strategy 'SimpleTestStrategy/207949029': An order has been ignored since the stop price ‘11479.5’ near the bar stamped ‘10/5/2020 3:12:30 PM’ is invalid based on the price range of the bar. This is an invalid order and subsequent orders may also be ignored.
Then it executes all my Print statements in OnExecutionUpdate and OnPositionUpdate so it seems to be trying to open actual orders. I don't want this!
Am i misunderstanding what it is doing? How can I see past trades that would have occurred without it trying to send actual live orders?
namespace NinjaTrader.NinjaScript.Strategies
{
public class SimpleTestStrategy : Strategy
{
SOME PRIVATE VARS HERE
protected override void OnExecutionUpdate(Cbi.Execution execution, string executionId, double price, int quantity,
Cbi.MarketPosition marketPosition, string orderId, DateTime time)
{
Print("Inside OnExecutionUpdate");
Print(" price is " + price+", quantity is "+quantity);
Print(" marketPosition is "+marketPosStr(marketPosition));
Print(" execution market position is "+marketPosStr(execution.MarketPosition));
Print(" Order name is "+execution.Order.Name);
}
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)
{
// Assign Order objects here
// This is more reliable than assigning Order objects in OnBarUpdate, as the assignment is not guaranteed to be complete if it is referenced immediately after submitting
if (order.Name == SHORT_ENTRY_NAME)
shortEntry = order;
else if (order.Name == LONG_ENTRY_NAME)
longEntry = order;
if (longEntry != null && longEntry == order)
{
// Reset the longEntry object to null if order was cancelled without any fill
if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
{
longEntry = null;
}
}
if (shortEntry != null && shortEntry == order)
{
// Reset the shortTop object to null if order was cancelled without any fill
if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
{
shortEntry = null;
}
}
}
protected override void OnPositionUpdate(Cbi.Position position, double averagePrice,
int quantity, Cbi.MarketPosition marketPosition)
{
//
// If we just opened a position, reset the setup so we can be computing new setups, even while the position is open
//
Print("Inside OnPositionUpdate");
this.priorMarketPosition = this.currentMarketPosition;
this.currentMarketPosition = position.MarketPosition;
if (this.currentMarketPosition != MarketPosition.Flat && this.priorMarketPosition == MarketPosition.Flat) {
Print(" Just opened new position");
} else if (this.currentMarketPosition == MarketPosition.Flat && this.priorMarketPosition != MarketPosition.Flat) {
Print(" Just closed position, now Flat");
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < BarsRequiredToTrade)
return;
computeTradability();
if (this.canEnterNewTrade) {
if (Close[0] > Open[0]) {
double entryPriceLong = High[0] + 4*TickSize;
enterBuyStop(1, entryPriceLong, 5, 10);
} else {
double entryPriceShort = Low[0] - 4*TickSize;
enterSellStop(1, entryPriceShort, 5, 10);
}
}
}
// ************************************
// Order entry and adjustment methods
// ************************************
private void enterBuyStop(int quantity, double entryPrice, int stopTicks, int takeProfitTicks) {
SetStopLoss(LONG_ENTRY_NAME, CalculationMode.Ticks, (double)stopTicks, false);
SetProfitTarget(LONG_ENTRY_NAME, CalculationMode.Ticks, (double)takeProfitTicks);
Print("Inside enterBuyStop: current price: "+Close[0]+", entry price: "+entryPrice);
Print(" : stopTicks: "+stopTicks+", takeProfitTicks: "+takeProfitTicks);
EnterLongStopMarket(quantity, entryPrice, LONG_ENTRY_NAME);
}
private void enterSellStop(int quantity, double entryPrice, int stopTicks, int takeProfitTicks) {
SetStopLoss(SHORT_ENTRY_NAME, CalculationMode.Ticks, (double)stopTicks, false);
SetProfitTarget(SHORT_ENTRY_NAME, CalculationMode.Ticks, (double)takeProfitTicks);
Print("Inside enterSellStop: current price: "+Close[0]+", entry price: "+entryPrice);
Print(" : stopTicks: "+stopTicks+", takeProfitTicks: "+takeProfitTicks);
EnterShortStopMarket(quantity, entryPrice, SHORT_ENTRY_NAME);
}
//
// This method is called at the start of OnBarUpdate. It sets three member variables in OnBarUpdate:
// canEnterNewTrade: This is true if we are currently Flat
// longFilledAndClosed: This is true if we are currently Flat AND if we detect that a prior long position was filled and is now closed
// shortFilledAndClosed: This is true if we are currently Flat AND if we detect that a prior short position was filled and is now closed
//
private void computeTradability() {
this.canEnterNewTrade = false;
this.longFilledAndClosed=false;
this.shortFilledAndClosed=false;
if (this.currentMarketPosition == MarketPosition.Flat) {
//
// If we are flat then we can enter a new trade if we get a new signal
//
this.canEnterNewTrade = true;
if (this.longEntry != null && this.longEntry.OrderState == OrderState.Filled) {
this.longFilledAndClosed=true; // prior long entry order was filled but we are now flat, so it was filled and exited
this.longEntry=null;
} else {
this.longFilledAndClosed=false;
}
if (this.shortEntry != null && this.shortEntry.OrderState == OrderState.Filled) {
this.shortFilledAndClosed=true; // prior short entry order was filled but we are now flat, so it was filled and exited
this.shortEntry=null;
} else {
this.shortFilledAndClosed=false;
}
}
}
}
}
Comment