Difficulties having OrderContext recognized with onBarUpdate

MattSeb

Member
Joined
Sep 17, 2020
Posts
6
Likes
0
Question for anybody more familiar with the MW SDK then myself. I have built a strategy that works as expected with all of the trade management using OrderContext taking place within onBarClose. However, I was looking to enhance my stop management between bar closes and I cannot seem to get OrderContext to be recognized within onBarUpdate. Any thoughts would be greatly appreciated as I'm stumped! ( i should add i have requiresBarUpdates set to true)
 
Last edited:
This is how I usually do it.

Java:
//Require Bar Updates in @StudyHeader.
@StudyHeader(
        namespace="com.mycompany",
        id="test1",
        rb="com.motivewave.platform.study.nls.strings",
        name="test1",
        label="test1",
        desc="test1",
        menu="MyStrategies",
        overlay = true,
        signals = true,
        strategy = true,
        autoEntry = true,
        manualEntry = false,
        supportsUnrealizedPL = true,
        supportsRealizedPL = true,
        supportsTotalPL = true,
        supportsRiskRatio = true,
        showTradeOptions = true,
        supportsBarUpdates = true,
        supportsPositionType = true,
        supportsTargetPL = true,
        underlayByDefault = true,
        barUpdatesByDefault = true,
        requiresBarUpdates = true)

//Declare global variables
private Order LongEntryOrder = null;
float SLprice = 0f;

//Then, perform all calculations inside calculate. 
@Override
protected void calculate(int index, DataContext ctx) {

    //For example, assume the price crosses above a moving average. This condition must be evaluated only after the bar is complete,
    //even when Bar Updates is enabled in the Strategy Settings.
    boolean crossover = crossedAbove(series, index, Values.CLOSE, Value.EMA) && series.isBarComplete(index);

    //Calculate your stop-loss level dynamically
    double low = series.lowest(index, 3, Enums.BarInput.LOW);
    float  SLprice = instr.round((float) (low - (tickSize*3)));  // Dynamic stop loss: 3 ticks below the lowest low of the last 3 candles.

    //Then, trigger the signal
    if (crossover){
        series.setBoolean(index, Signals.BuySignal, true);
        //This will trigger even we don't enable "Signal" in the "Signals" tab
        ctx.signal(index, Signals.BuySignal, buyMessage, "Current price: " + round(Close, 2));"
    }
}

//Enter a long position
@Override
public void onSignal(OrderContext ctx, Object signal) {
    if (signal == Signals.BuySignal){
        // submit a market buy or limit buy entry
           LongEntryOrder = ctx.createLimitOrder(...);
           ctx.submitOrders(LongEntryOrder);
    }
}


//After the long entry order is filled, close the position if the dynamic stop-loss level is hit
@Override
public void onOrderFilled(OrderContext ctx, Order order) {
    if (order == LongEntryOrder){
        if (close < SLprice){
        ctx.closeAtMarket() //close the position
        }
    }
}
 
@MattSeb That, and make sure if you have checked Bar updates in the strategy settings (in options tab).
View attachment 3300
Really appreciate your time John for answering. Quick follow up ~ what MW version are you running? I have the last version of MW6 (top feature version) and I don't have the Options (just Trading Options) tabs on my strategy GUI. I check the headers list in the SDK and not seeing anything that I have missed. I do have requiresBarUpdates and suppotsBarUpdates in my header as true.
 
This is how I usually do it.

Java:
//Require Bar Updates in @StudyHeader.
@StudyHeader(
        namespace="com.mycompany",
        id="test1",
        rb="com.motivewave.platform.study.nls.strings",
        name="test1",
        label="test1",
        desc="test1",
        menu="MyStrategies",
        overlay = true,
        signals = true,
        strategy = true,
        autoEntry = true,
        manualEntry = false,
        supportsUnrealizedPL = true,
        supportsRealizedPL = true,
        supportsTotalPL = true,
        supportsRiskRatio = true,
        showTradeOptions = true,
        supportsBarUpdates = true,
        supportsPositionType = true,
        supportsTargetPL = true,
        underlayByDefault = true,
        barUpdatesByDefault = true,
        requiresBarUpdates = true)

//Declare global variables
private Order LongEntryOrder = null;
float SLprice = 0f;

//Then, perform all calculations inside calculate.
@Override
protected void calculate(int index, DataContext ctx) {

    //For example, assume the price crosses above a moving average. This condition must be evaluated only after the bar is complete,
    //even when Bar Updates is enabled in the Strategy Settings.
    boolean crossover = crossedAbove(series, index, Values.CLOSE, Value.EMA) && series.isBarComplete(index);

    //Calculate your stop-loss level dynamically
    double low = series.lowest(index, 3, Enums.BarInput.LOW);
    float  SLprice = instr.round((float) (low - (tickSize*3)));  // Dynamic stop loss: 3 ticks below the lowest low of the last 3 candles.

    //Then, trigger the signal
    if (crossover){
        series.setBoolean(index, Signals.BuySignal, true);
        //This will trigger even we don't enable "Signal" in the "Signals" tab
        ctx.signal(index, Signals.BuySignal, buyMessage, "Current price: " + round(Close, 2));"
    }
}

//Enter a long position
@Override
public void onSignal(OrderContext ctx, Object signal) {
    if (signal == Signals.BuySignal){
        // submit a market buy or limit buy entry
           LongEntryOrder = ctx.createLimitOrder(...);
           ctx.submitOrders(LongEntryOrder);
    }
}


//After the long entry order is filled, close the position if the dynamic stop-loss level is hit
@Override
public void onOrderFilled(OrderContext ctx, Order order) {
    if (order == LongEntryOrder){
        if (close < SLprice){
        ctx.closeAtMarket() //close the position
        }
    }
}
Appreciate you sharing the code HalTrader - have you every tried order management within onBarUpdate as that's where I'm having difficulty. All my execution and managment is done in Calculate or onBarClose but I want to move my stop managment to onBarUpdate so I can step my stops in a more timely fashion.
 
So far, I have never tried doing this within onBarUpdate, but if you create a global variable and calculate your dynamic SL level in onBarUpdate, it should be possible to call it in onOrderFilled.

In brief, I do all of my trade management within onOrderFilled since it guarantees that, for example, once my long entry is filled, I can trail my SL or move it to breakeven if my TP1 is hit, etc. To do this, I use flags/global variables such as LongEntryOrder, which becomes null once the entry order is filled.

By the way, I am using MW7, but the same code was also working in MW6.
 
So far, I have never tried doing this within onBarUpdate, but if you create a global variable and calculate your dynamic SL level in onBarUpdate, it should be possible to call it in onOrderFilled.

In brief, I do all of my trade management within onOrderFilled since it guarantees that, for example, once my long entry is filled, I can trail my SL or move it to breakeven if my TP1 is hit, etc. To do this, I use flags/global variables such as LongEntryOrder, which becomes null once the entry order is filled.

By the way, I am using MW7, but the same code was also working in MW6.
some good ideas there. Thank you!
 
Really appreciate your time John for answering. Quick follow up ~ what MW version are you running? I have the last version of MW6 (top feature version) and I don't have the Options (just Trading Options) tabs on my strategy GUI. I check the headers list in the SDK and not seeing anything that I have missed. I do have requiresBarUpdates and suppotsBarUpdates in my header as true.

I am using motivewave 7. and here is the header I am using

@StudyHeader(namespace = "com.company",
id = "TEST_TRADING_STRTEGY",
name = "STRATEGY_NAME",
desc = "STRATEGY_DESCRIPTION",
rb = "com.packagename.strings",
menu = "MENU_MY_STRATEGY",
overlay = true,
signals = true,
strategy = true,
autoEntry = true,
manualEntry = false,
supportsUnrealizedPL = true,
supportsRealizedPL = true,
supportsTotalPL = true,
supportsSessions = true,
barUpdatesByDefault = true)
 
@MattSeb I hope you are accessing ordercontext by implementing this bar update method:
public void onBarUpdate(OrderContext orderContext) {)

There is one more onBarUpdate method with DataContext as parameter. You wont be able to access ordercontext inside of that.
 
Top