PDA

View Full Version : Newbie Code Help --- ATR Multiple for Stop


kcsystemtrader
12-18-2008, 03:36 PM
I'm new to NT, and fairly new to programming and have never used C#. Once a buy/sell condition has been met, I'm trying to write the code to set my stop and profit target correctly based on a multiple of the most recent ATR. It doesn't have to adjust the stops (i.e. dynamically modify the stop levels as each subsequent bar comes in) after the original buy/sell order has been filled. Rather, right when the buy/sell order is generated it needs to look back at the last 'x' amount of bars (25 in the code below) to calculate the most recent ATR, multiply it, and then set both the stop and profit limit orders accordingly.

My feeble attempt at this is below (only the main sections of the code included), and I'm getting the CS0102 error saying for the properties section saying that Variable0 and 1 are already defined. If I comment out the 'properties' code, I get CS0019 saying I can't apply an operand '*' to type 'int' and 'Ninjatrader.Indicator.ATR'.

Guidance here would be appreciated...Thanks,

KCSystemTrader


#region Variables section...

private int period1 = 25; // Default setting for Period1
private double Variable0 = 0.500; // Default ATR for stop loss
private double Variable1 = 1.000; // Default ATR for take profit

protected override void Initialize() Section...

//Custom code to calculate latest ATR reading and set stop and profit target levels
Add(ATR(Period1)); //This adds the ATR to the chart (I think)
Variable0 = 3 * ATR(Period1);
Variable1 = 6 * ATR(Period1);

//Plug Variable0 and Variable1 calculations into stop and profit target
SetStopLoss("Buy", CalculationMode.Ticks, Variable0, true);
SetStopLoss("Sell", CalculationMode.Ticks, Variable0, true);
SetProfitTarget("Buy", CalculationMode.Ticks, Variable1);
SetProfitTarget("Sell", CalculationMode.Ticks, Variable1);

#region Properties Section...

//Custom Code to define minimum allowable values for Variable0 and Variable1
[Description("ATR For Stop Loss")]
[Category("Parameters")]
public double Variable0
{
get { return Variable0; }
set { Variable0 = Math.Max(0.200, value); }
}

[Description("ATR For Take Profit")]
[Category("Parameters")]
public double Variable1
{
get { return Variable1; }
set { Variable1 = Math.Max(0.400, value); }
}

NinjaTrader_Josh
12-18-2008, 03:50 PM
You cannot do any calculation logic in Initialize(). Everything you want to do needs to be done in OnBarUpdate(). You need to calculate out your ATR value before you submit your entry order.

kcsystemtrader
12-19-2008, 06:50 AM
You cannot do any calculation logic in Initialize(). Everything you want to do needs to be done in OnBarUpdate(). You need to calculate out your ATR value before you submit your entry order.

Thanks. That makes sense. So I moved the calc logic into the OnBarUpdate section and am now trying to use a boolean 'defined' to only set it once. I got this from another related post. Here's the logic...


//Set Trailing Stop based on ATR Multiple
if (Defined == false)
{
TrailStop = ((ATR(Period1)[1] * ATRMultiple));
if (TrailStop < MinimumTrailStop)
{
TrailStop = MinimumTrailStop;
}
SetTrailStop("Buy", CalculationMode.Price, TrailStop, true);
SetTrailStop("Sell", CalculationMode.Price, TrailStop, true);
Defined = true;
}

Period1 is a defined int and MinimumTrailStop is a defined double. The code compiles but when I run the strategy a trailstop isn't getting set at all. It just buys/sells and then eventually closes itself out when another buy/sell condition is met. In the variables, I have

bool Defined = false;

Do I need to reset this to false if I have a flat position or something? How do I do that? Thanks,

kcsystemtrader

NinjaTrader_Bertrand
12-19-2008, 06:59 AM
Hi kcsystemtrader, yes you want it to reset, otherwise it will not make it through the trailstop section again...please also take a look at this reference sample - http://www.ninjatrader-support2.com/vb/showthread.php?t=3222

kcsystemtrader
12-19-2008, 10:19 PM
Hi kcsystemtrader, yes you want it to reset, otherwise it will not make it through the trailstop section again...please also take a look at this reference sample - http://www.ninjatrader-support2.com/vb/showthread.php?t=3222


So how do I do that? Do I set a reset based on my position being back to flat or something? I don't really know how to code that. Been programming for about 4 days now. Thanks,

NinjaTrader_Ray
12-20-2008, 09:36 AM
Bert will follow up on Monday.

kcsystemtrader
12-20-2008, 03:47 PM
Bert will follow up on Monday.

Okay, thanks. I guess what I need help with is the following:

If a position that was opened by the strategy is closed, then reset the bool "defined" back to false. Or, stated another way, upon any new position being opened by the strategy, reset the bool back to false so that it will run the trail stop code again.

So that could either be based on a "if market position = flat", or "if trail stop order = filled", or there are probably quite a few other ways you could code it too. Thanks again,

kcsystemtrader

NinjaTrader_Bertrand
12-22-2008, 04:27 AM
Hi kcsystemtrader,
To reset your bool variable when the strategy is flat you could use -


if (Position.MarketPosition == MarketPosition.Flat)
Defined = false;

kcsystemtrader
01-02-2009, 01:10 PM
I'm still having trouble here. I still haven't figured out how to run a calculation on an indicator that is dynamically updating. See below. I can see the "ATRvalue" updating in the output window, but I see nothing in the output window for "TrailStop".


ATRvalue = ATR(120)[0];
Print("The current ATR value is " + ATRvalue.ToString());

TrailStop = ATRvalue * 2;
Print("The current TrailStop value is " + TrailStop.ToString());

SetTrailStop("", CalculationMode.Price, TrailStop, false);

Once I can at least be sure I'm getting a value for TrailStop, I'll move on to making sure it is getting reset properly with the "Defined" boolean as discussed below based on position being flat. Thanks

kcsystemtrader
01-02-2009, 01:34 PM
I'm still having trouble here. I still haven't figured out how to run a calculation on an indicator that is dynamically updating. See below. I can see the "ATRvalue" updating in the output window, but I see nothing in the output window for "TrailStop".


ATRvalue = ATR(120)[0];
Print("The current ATR value is " + ATRvalue.ToString());

TrailStop = ATRvalue * 2;
Print("The current TrailStop value is " + TrailStop.ToString());

SetTrailStop("", CalculationMode.Price, TrailStop, false);

Once I can at least be sure I'm getting a value for TrailStop, I'll move on to making sure it is getting reset properly with the "Defined" boolean as discussed below based on position being flat. Thanks


Figured out what was wrong --- I didn't have an Add(ATR(120)); up in the intialize method. Didn't know that was required in order to reference an indicator in OnBarUpdate(). Thanks,

NinjaTrader_Ray
01-02-2009, 02:50 PM
Figured out what was wrong --- I didn't have an Add(ATR(120)); up in the intialize method. Didn't know that was required in order to reference an indicator in OnBarUpdate(). Thanks,

It's not however, if this has resolved your issue then just leave as is.

kcsystemtrader
01-02-2009, 03:22 PM
It's not however, if this has resolved your issue then just leave as is.

Ha - okay...I was making a lot of changes at the time so I probably changed something else that fixed it without realizing it. Either way, it's working now as far as I can tell from testing in real-time (at least I can see the 'TrailStop' continuously calculating along with 'ATRvalue'. However, in backtesting it still doesn't appear trailstop orders are getting simulated.

I don't think it is a reset problem because it just looks like it is never getting set.

NinjaTrader_Bertrand
01-03-2009, 09:34 AM
Hi kcsystemtrader, great it works now - are you using SetTrailStop together with SetStopLoss and reference the same position? This cannot be done, please see this help guide link - http://www.ninjatrader-support.com/HelpGuideV6/SetTrailStop.html

For modifying your stoploss orders, you may want to review this reference sample here - http://www.ninjatrader-support2.com/vb/showthread.php?t=3222

Have a good weekend!

kcsystemtrader
01-05-2009, 11:58 AM
Hi kcsystemtrader, great it works now - are you using SetTrailStop together with SetStopLoss and reference the same position? This cannot be done, please see this help guide link - http://www.ninjatrader-support.com/HelpGuideV6/SetTrailStop.html

For modifying your stoploss orders, you may want to review this reference sample here - http://www.ninjatrader-support2.com/vb/showthread.php?t=3222

Have a good weekend!

No, there is only a SetTrailStop, there isn't a SetStopLoss in the code.

The problem now is that I have the reset working and the calculation logic working right, but trail stop orders are not being generated. Nothing on the orders tab or in the log. With TraceOrders on, I am seeing the following in the output window:

The current ATR value is 0.292274060645679
The current TrailStop value is 0.876822181937038
1/5/2009 9:03:58 AM Entered internal SetStopTarget() method: Type=TrailStop FromEntrySignal='Buy' Mode=Price Value=0.876822181937038 Currency=0 Simulated=False
1/5/2009 9:03:58 AM Entered internal SetStopTarget() method: Type=TrailStop FromEntrySignal='Sell' Mode=Price Value=0.876822181937038 Currency=0 Simulated=False
The current value for BarsSinceExit is 337

What does "Entered internal SetStopTarget" mean, and why wouldn't it be an "external" trailing stop order that is sent immediately to the market? As you can see in the trace, I do have Simulated = False.

Here is the latest code:
//Reset upon going flat
if (Position.MarketPosition == MarketPosition.Flat)
definedTrailStop = false;

// Calculations For Stop Loss
if (definedTrailStop == false)
{
// Prints the current value of an 'x' period ATR using default price type
ATRvalue = ATR(ATRPeriod)[0];
Print("The current ATR value is " + ATRvalue.ToString());
// Multiply ATRvalue by ATRMultiple and Set TrailStop
TrailStop = ATRvalue * ATRMultiple;
if (TrailStop < MinimumTrailStop)
{
TrailStop = MinimumTrailStop;
}
Print("The current TrailStop value is " + TrailStop.ToString());
definedTrailStop = true;
}

//Send trailing stop order to market with last calculated TrailStop
SetTrailStop("Buy", CalculationMode.Price, TrailStop, false);
SetTrailStop("Sell", CalculationMode.Price, TrailStop, false);

//Buy and Sell Conditions here

I originally had the SetTrailStop up in the brackets in the ATR calculation logic section, but figured since this logic stops running once a position is entered that maybe the SetTrailStop command would not be seen. So, now it outside of that section of the logic and it is running the SetTrailStop code every update while in a position (and not updating the trailstop price), but still there are no trailing stop orders actually being placed. I've tested real time and it blows right through the stops. Thanks,

kcsystemtrader

NinjaTrader_Josh
01-05-2009, 12:04 PM
You need to call SetTrailStop before you place your order. After that you should not call it again. It will trail on its own tick by tick. From your code it looks like you are trying to use your own trailing logic and in that case you should not be using SetTrailStop. You should be using ExitLongStop() and just modify that order constantly.

kcsystemtrader
01-05-2009, 12:26 PM
You need to call SetTrailStop before you place your order. After that you should not call it again. It will trail on its own tick by tick. From your code it looks like you are trying to use your own trailing logic and in that case you should not be using SetTrailStop. You should be using ExitLongStop() and just modify that order constantly.

The SetTrailStop call is before the entry conditions. Currrently, the call does keep running after entry, but previously it did not and it still didn't work (when SetTrailStop was in the calculation logic section of the code that is programmed to stop running once position is no longer flat).

The only thing I'm trying to do is to have the value for "price" calculated right at entry based on a recent ATR. Upon an order being filled, I want a trailing stop order to be submitted to the market and monitored by the broker (and function like any other trailing stop order you would place manually with your broker).

I want a trailing stop order to be placed with a static price calculated and set right at entry...not a stop order that is constantly updated by code.

NinjaTrader_Josh
01-05-2009, 12:29 PM
If you do not want it updating based on your code you should only call SetTrailStop once. In terms of if your order will be held at your brokerage this depends. Please see this article: http://www.ninjatrader-support2.com/vb/showthread.php?t=5349

kcsystemtrader
01-05-2009, 12:55 PM
If you do not want it updating based on your code you should only call SetTrailStop once. In terms of if your order will be held at your brokerage this depends. Please see this article: http://www.ninjatrader-support2.com/vb/showthread.php?t=5349

I understand but in my case it really doesn't matter. The value for TrailStop will not change once a position is entered, so even if it updates the trail stop order after entry, it would be with an identical value. Since that is apparently not the problem, I'll probably put the SetTrailStop call back in the Calc Logic section so that it will stop running upon entry. It will now only be running SetTrailStop call when the strategy is flat.

But that is not the problem: when an order gets filled, a trailing stop order is not being generated. All I get is the "Entered internal SetStopTarget() method" statement in the output window. Regardless of where the actual order is residing (whether it is simulated on my machine, held on my broker's servers, or held at the exchange) NT should still show a working trailstop order in the orders tab, shouldn't it? When I use SetStopLoss or SetProfitTarget in Initialize, I get live working orders that show up on the Orders tab. Nothing shows up over there. Again, trailing stop orders are not even getting placed. Regardless of if they are updated or not, or where they reside, the orders simply aren't being placed.

kcsystemtrader
01-05-2009, 12:57 PM
Do I need a SetStopLoss in the Intialize() section as well as in the OnBarUpdate section? Right now there is nothing in Initialize. Not sure why that would matter, but just a thought...

NinjaTrader_Josh
01-05-2009, 01:22 PM
That does not matter. Please try with an as-simple-as-possible strategy.

if (Position.MarketPosition == MarketPosition.Flat)
{
SetTrailStop(...);
EnterLong();
}and see what happens.

kcsystemtrader
01-05-2009, 03:29 PM
That does not matter. Please try with an as-simple-as-possible strategy.

if (Position.MarketPosition == MarketPosition.Flat)
{
SetTrailStop(...);
EnterLong();
}and see what happens.

Taking it down to that level helped my troubleshooting a lot. Thanks

It is working now. I think it was a combination of problems. For one, I had the calc mode set to price, not ticks. My ATR is calculating ticks away from entry to set a stop, not a price level to set the stop.

Another thing is that I had the SetTrailStop's outside of the brackets for the entry conditions. I now have them directly above each entry condition, both within the same bracket (like you've shown above). Before it was like this...

SetTrailStop("Buy",...)
SetTrailStop("Sell",...)

if(...)
{
EnterLong("Buy");
}

if(...)
{
EnterShort("Sell");
}

Now I have:

if(...)
{
SetTrailStop("Buy",...)
EnterLong("Buy");
}

if(...)
{
SetTrailStop("Sell",...)
EnterShort("Sell");
}

Would that have been all it was the whole time, just the placement of SetTrailStop has to be in the same "if" statement as the Enter commands?

NinjaTrader_Josh
01-05-2009, 03:38 PM
It shouldn't have mattered, but doesn't hurt to leave it as you have it. Most likely the calculation mode differences were what was causing issues. Perhaps it ended up trying to submit at an invalid price.

kcsystemtrader
01-05-2009, 04:03 PM
It shouldn't have mattered, but doesn't hurt to leave it as you have it. Most likely the calculation mode differences were what was causing issues. Perhaps it ended up trying to submit at an invalid price.

In the next day or so, I'll run a test with it the old way to see if it gives me problems again. Just curious. Thanks again for your help and quick responses.