View Full Version : Make trail stop value update intra bar without indicator update.
dendy
10-17-2007, 11:56 AM
Can I have my trail stop update on a tick by tick basis without making the indicators change on a tick by tick basis?
If so what would be the way to effect this with strategy builder or the code?
Thanks to anyone who can help...
dendy.
NinjaTrader_Ray
10-17-2007, 12:30 PM
Yes you can by running with CalculateOnBarClose = false.
http://www.ninjatrader-support.com/HelpGuideV6/CalculateOnBarClose1.html
dendy
10-17-2007, 03:37 PM
Thanks Ray,
I honestly tried that but I had to shut down the connection and reload the Ninjascripts before it worked.
Is there any way to allow the trail stop to update intra bar and allow entries to happen only when a bar closes (and conditions are met).
Thanks again....
dendy.
woodside
10-17-2007, 05:20 PM
Not exactly what you are looking for, but I add a 15 minute timeframe into my chart that runs on a 1 minute timeframe. The trailing stops adjust every minute but I take all my order entry signals off the 15 minute.
dendy
10-17-2007, 07:23 PM
Woodside,
If you don't mind me asking, what is the script for doing this. I am testing a 5 min strategy on my IB connection and would like it to update the trailstop every 30 seconds to 1 min if possible. I originally wanted every tick but your solution also sounds very good!
Thanks for responding...
dendy.
NinjaTrader_Josh
10-17-2007, 10:41 PM
Hi dendy,
The way SetTrailStop() is designed is it will work tick-by-tick and no other way. It does not care what you set CalculateOnBarClose to, it will run tick-by-tick. When you set CalculateOnBarClose to true it means your OnBarUpdate() method will only be executed once at the end of every bar. This means if you have your SetTrailStop() set inside the OnBarUpdate() method then you end up having its value set only when the once per bar at the end. This generally shouldn't be a problem if you call SetTrailStop() immediately after you call EnterLong() or EnterShort(). This caveat also does not mean your Trail Stop order is not working tick-by-tick. Once the order is submitted it will work tick-by-tick until you get stopped out.
Hope that clarifies your concerns about SetTrailStop().
For further information please review the documentation here: http://www.ninjatrader-support.com/HelpGuideV6/SetTrailStop.html
There is also a reference sample that may be of value to you here: http://www.ninjatrader-support.com/vb/showthread.php?t=3222
In regards to adding a second time frame to your NinjaScript strategy you can review how to do it here: http://www.ninjatrader-support.com/HelpGuideV6/MultiTimeFrameInstruments.html
woodside
10-18-2007, 09:18 AM
Dendy,
I use a modified version of the sample multi timeframe strategy. My strategy runs in a 1 minute timeframe, then I add a 15 minute to the strategy, the use BarsArray[1] in all my indicators to determine entrys.
I found that when backtesting, the results are much more accurate with the trailing stops as the get updated every minute.
Josh, In my experience the trailing stops only get updated when the bar closes. Is this just because I'm running in simulation? When I run my strategy live with my broker account will it send an actual "trail stop" order to my broker which will then update it tick by tick? Broker is MB Trading which does support trailing stops natively.
dendy
10-18-2007, 12:20 PM
Thanks Woodside and Josh,
I've been investigating the multi-time frame strategy and this is great stuff. I know it's old news to you. But I'll be trying to use this for the first time.
As you mentioned Josh, the trail stop is checked on a tick by tick but the value is not updated until the bar closes.
I will work on this.
Thanks to all.
dendy.
woodside
10-18-2007, 01:25 PM
I'm still new at this also but I have a fair amount of programming experience.
I could never figure out why I couldn't get better performance using trailing stops then just fixed stops. When looking at past bars, ninja has no idea if a high came before or after a low so trailing stops never get updated on the same bar, and your target and/or your stop could get hit on the same bar. Using 1 minute bars seems to help as at least the stop gets updated once every minute.
If as Josh says they will get updated tick by tick when trading for real that this isn't an issue, but it sure helps when backtesting. My experience with trailing stops is they update at the close of a bar, and they are adjusted based on the high/low of the previous bar depending on if you are long/short.
-Erik
NinjaTrader_Ray
10-18-2007, 02:40 PM
For clarification.
SetTrailStop() will submit a stop loss order immediately on the opening of a position based on internal incoming fill events on an order. The adjustment of the stop loss price (the trailing stop) is adjusted on OnBarUpdate() events which either trigger on the close of a bar or on each tick depending on what your CalculateOnBarClose property is set to.
dendy
10-19-2007, 07:54 AM
I have an issue with trying to use a multi-time strategy to update my trail stop more often than my entry order.
I have a multi time frame and not a multi instrument strategy. According to the help file and confirmed by errors, you may only execute orders against the primary time frame. I cannot make the primary time frame 1 minute because I don't want to execute that many entries. Let's say I make the primary time frame 5 minutes, then my entries will run only on 5 min intervals (good). But the trail stop will also update only every 5 minutes unless I find a workable way to command the trail stop to update based on the bars that I add with the Add command. (As woodside said earlier, 1 min bars or so.)
Can anyone help with this?
Thanks again...
NinjaTrader_Ray
10-19-2007, 08:42 AM
NT 6.5 will allow you to place orders against all time frames which will solve your road block. We are within weeks of releasing public beta of this.
dendy
10-19-2007, 08:48 AM
NT 6.5 sounds like it's going to be a huge update...
Can't wait to see it.
Thanks for clearing that up for us,
dendy.
woodside
10-19-2007, 10:18 AM
You could use a counter to do this I think. Load your script on a 1 minute bar, add a 15 minute bar, initialize a counter at 0, then every bar increment it by one, when it hits 15 run your order entry conditions and reset the counter to 0. That way your stops would run every bar but the orders would only trigger every 15th bar.
-Erik
dendy
10-19-2007, 12:04 PM
Woodside,
I'm trying to use the count command but all the help guide has to say about it is below. The Countif does not work on multi time frame strategies. I'm still trying to make the Count work. I'm slow because I don't know anything about programming.
Thanks...
Definition
The total number of bars or data points.
Property Value
An integer value representing the the total number of bars.
Syntax
Count
Property Of
Custom Indicator, Custom Strategy
woodside
10-19-2007, 12:20 PM
I"m not talking about using the count function of ninja. Just define a varable in the variable section like
private int myBars = 0;
Then inside your onbarupdate,
do something like
myBars = myBars + 1;
then
if (myBars == 15) {
do your order enty stuff and then
myBars = 0;
}
Haven't tested this but it should work.
dendy
10-19-2007, 01:41 PM
Woodside,
This is what I got but it won't compile. Any ideas:
#region Variables
// Wizard generated variables
private int sMAFast = 6; // Default setting for SMAFast
private int trailStop = 4; // Default setting for TrailStop
private int myBars = 0; // Woodside says to use this to count bars
// User defined variables (add any user defined variables below)
#endregion
/// <summary>
/// This method is used to configure the strategy and is called once before any strategy method is called.
/// </summary>
protected override void Initialize()
{
///Add 1 Minute Bars to the strategy.
Add(PeriodType.Minute, 15);
// if (BarsInProgress == 1)
SetTrailStop("", CalculationMode.Ticks, TrailStop, true);
CalculateOnBarClose = true;
}
/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate()
{
// Woodside says use this code to count bars.
myBars = myBars +1;
then
if(myBars == 15);
//Call bars so that orders are made
{
if (BarsInProgress == 0)
// Condition set 1
if (ToTime(Time[0]) > ToTime(10, 0, 0)
&& ToTime(Time[0]) <= ToTime(16, 10, 0)
&& SMA(SMAFast)[0] > SMA(SMAFast)[1])
{
EnterLong(DefaultQuantity, "");
// Woodside says use this code to reset the count to zero after entry is made.
myBars = 0;
}
}
}
NinjaTrader_Josh
10-19-2007, 01:43 PM
Hi dendy,
You don't need the line "then". Also if you don't feel like giving a signal name on your EnterLong() you can simply do EnterLong(DefaultQuantity). In fact since you are just using default quantity I believe you could even just go EnterLong().
dendy
10-19-2007, 02:43 PM
Thanks Josh,
When I cut out the "then", the code compiles and the strategy runs. It's not happening right though. Either the code is not counting the bars or the reset is not occurring. I think the count is not restarting because the entries are happening every minute or so.
Do you have any advice?
dendy.
woodside
10-19-2007, 02:47 PM
Right after the onbarupdate put:
Print("myBar = " + myBars.ToString());
then open an output window and see what you are getting.
dendy
10-19-2007, 03:16 PM
Woodside,
The output window shows the myBar count going high (at times into the hundreds). Afterward, the count will go to zero (sometimes for 3 to 5 zeros in a row). At times the count goes up to 2 or 3 and then back down to zero.
An example is at the bottom of this post.
Thanks again. I'm learning lots about Ninjascript with your help...
myBar = 26
myBar = 27
myBar = 28
myBar = 0
myBar = 1
myBar = 0
myBar = 0
myBar = 0
myBar = 1
myBar = 0
myBar = 1
myBar = 2
myBar = 3
myBar = 4
myBar = 0
myBar = 1
myBar = 0
myBar = 1
myBar = 2
myBar = 3
myBar = 4
myBar = 5
myBar = 6
myBar = 7
myBar = 0
myBar = 0
myBar = 0
myBar = 1
myBar = 2
myBar = 3
myBar = 4
myBar = 5
myBar = 6
myBar = 0
myBar = 1
myBar = 0
myBar = 0
myBar = 1
myBar = 2
myBar = 3
myBar = 4
myBar = 5
myBar = 6
myBar = 7
myBar = 8
myBar = 0
myBar = 0
myBar = 0
myBar = 0
myBar = 0
myBar = 1
myBar = 0
myBar = 0
myBar = 0
myBar = 1
myBar = 2
myBar = 3
myBar = 4
myBar = 5
myBar = 0
myBar = 0
myBar = 0
myBar = 0
myBar = 1
myBar = 2
myBar = 3
myBar = 4
myBar = 5
myBar = 0
myBar = 1
myBar = 0
myBar = 0
myBar = 0
myBar = 1
myBar = 2
myBar = 3
myBar = 4
myBar = 5
woodside
10-19-2007, 03:22 PM
move the myBars = 0 to right below
if(myBars == 15);
myBars = 0;
right now you have it inside your if conditions so it doesn't get reset unless your conditions are all true.
NinjaTrader_Josh
10-19-2007, 03:24 PM
Hi dendy,
There are several errors in your current code.
if(myBars == 15); There shouldn't be a ; at the end of the if statement.
Your myBar reset only happens if you entered long also. I'm not sure if this is intentional, but I would assume you would want it to reset every time it hits 15 regardless if you entered a trade or not. The way you have it currently, when your myBars becomes 15 and if, by chance, you don't enter the trade your myBars would never be reset and would just keep incrementing forever after that.
You also need curly brackets for the BarsInProgress if statement.
if(myBars == 15)
//Call bars so that orders are made
{
if (BarsInProgress == 0)
{
// Condition set 1
if (ToTime(Time[0]) > ToTime(10, 0, 0)
&& ToTime(Time[0]) <= ToTime(16, 10, 0)
&& SMA(SMAFast)[0] > SMA(SMAFast)[1])
{
EnterLong(DefaultQuantity, "");
}
}
// Woodside says use this code to reset the count to zero after entry is made.
myBars = 0;
}
dendy
10-19-2007, 04:38 PM
I made all the suggested changes. The count goes from zero to 14 and then resets every time. To make the orders obey, I added: "&&myBars = 14" to the entry conditions. The code is below.
Again thanks for all the help...
I believe it is working now......................
protected override void OnBarUpdate()
{
// Woodside says, "Use this code to print the bar count to the output window.
Print("myBar = " + myBars.ToString());
{
// Woodside says use this code to count bars.
myBars = myBars +1;
if(myBars == 15)
myBars = 0;
//Call bars so that orders are made
{
if (BarsInProgress == 0)
{
// Condition set 1
if (ToTime(Time[0]) > ToTime(10, 0, 0)
&& ToTime(Time[0]) <= ToTime(16, 10, 0)
&& SMA(SMAFast)[0] > SMA(SMAFast)[1]
&& myBars == 14)
{
EnterLong(DefaultQuantity, "");
}
}
}
}
}
woodside
10-19-2007, 09:00 PM
I don't think that is going to work properly.
You aren't going to see it hit 15 because when it's on 14, 1 gets added to it.
When the "if myBarrs ==15" condition is true and it gets reset back to 0.
For the same reason the && myBars == 14 will never be true because it's inside the if statement that only executes when myBars = 15 which then gets reset to 0. I'd remove the && myBars ==14 from your if and put another print statement near you "EnterLong" statement to see if if fires.
It doesn't appear to me that it will at this point.
When I'm developing/debugging I use lots of print statements to help me see what is going on.
-Erik
Why don't you try something like this...
private bool wait_for_primary = false; // If set, remember to do logic on next primary time-frame bar.
protected override void Initialize()
{
Add(PeriodType.Minute, 15); // Use a 15-Min bar object (for BarsInProgress==1).
CalculateOnBarClose = true; // If set to 'false' then OnBarUpdate will be called for every tick.
}
protected override void OnBarUpdate()
{
// Secondary time frame -- Since trades must be issued from the primary instrument,
// just set a flag on the secondary time frame.
//
if (BarsInProgress == 1) // This happens once every 15-min...
{
wait_for_primary = true; // Check for time to trade on next primary bar.
return;
}
// Primary time frame -- Since trades must be issued from the primary instrument,
// we do that here if the flag was set on the secondary time frame.
//
if (BarsInProgress == 0) // This happens once every 1-min...
{
if (wait_for_primary)
{
if (ToTime(Time[0]) > ToTime(10, 0, 0)
&& ToTime(Time[0]) <= ToTime(16, 10, 0)
&& SMA(SMAFast)[0] > SMA(SMAFast)[1])
{
EnterLong(DefaultQuantity, "");
}
wait_for_primary = false; // Only do this once; wait for another 15-min.
}
}
}
dendy
10-21-2007, 09:14 AM
Woodside and KBJ,
The count code works. I have not used the print on the EnterLong but I have looked at the backtest output to confirm that the EnterLong fires and only does so every 14 mins.
I also used KBJ's code and it works too. The only thing is that when I'm adding a second condition to exit the position at 4:15 PM this new condition was difficult for me to implement. I had to slide it in up top as such...
Thanks again guys!
protected override void OnBarUpdate()
{
// Condition set 2 (Exit all at 4:14 PM)
if (ToTime(Time[0]) == ToTime(16, 14, 0))
{
ExitLong("", "");
ExitShort("", "");
}
// Secondary time frame -- Since trades must be issued from the primary instrument,
// just set a flag on the secondary time frame.
//
if (BarsInProgress == 1) // This happens once every 15-min...
{
wait_for_primary = true; // Check for time to trade on next primary bar.
return;
}
// Primary time frame -- Since trades must be issued from the primary instrument,
// we do that here if the flag was set on the secondary time frame.
//
if (BarsInProgress == 0) // This happens once every 1-min...
{
if (wait_for_primary)
{
if (ToTime(Time[0]) > ToTime(13, 0, 0)
&& ToTime(Time[0]) <= ToTime(16, 00, 0)
&& SMA(SMAFast)[0] > SMA(SMAFast)[1])
{
EnterLong(DefaultQuantity, "");
}
wait_for_primary = false; // Only do this once; wait for another 15-min.
}
}
}