Parablic SAR signal not firing in TOS Strategy


Category:
0
1

I am unsure why this is happening. Anyone have a fix or is this just a data feed issue?  See image for details. The code is below.

 

input tradeSize = 1;

input accelerationFactor = 0.1;
input accelerationLimit = 0.06;

Assert(accelerationFactor > 0, “‘acceleration factor’ must be positive: ” + accelerationFactor);
Assert(accelerationLimit >= accelerationFactor, “‘acceleration limit’ (” + accelerationLimit + “) must be greater than or equal to ‘acceleration factor’ (” + accelerationFactor + “)”);

def state = {default init, long, short};
def extreme;
def SAR;
def acc;

switch (state[1]) {
case init:
state = state.long;
acc = accelerationFactor;
extreme = high;
SAR = low;
case short:
if (SAR[1] < high)
then {
state = state.long;
acc = accelerationFactor;
extreme = high;
SAR = extreme[1];
} else {
state = state.short;
if (low < extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = low;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Max(Max(high, high[1]), SAR[1] + acc * (extreme – SAR[1]));
}
case long:
if (SAR[1] > low)
then {
state = state.short;
acc = accelerationFactor;
extreme = low;
SAR = extreme[1];
} else {
state = state.long;
if (high > extreme[1])
then {
acc = Min(acc[1] + accelerationFactor, accelerationLimit);
extreme = high;
} else {
acc = acc[1];
extreme = extreme[1];
}
SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme – SAR[1]));
}
}

plot parSAR = Floor(SAR / TickSize()) * TickSize();
parSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
parSAR.SetDefaultColor(GetColor(3));
def longExit = low < parSAR[1];
def shortExit = high > parSAR[1];

AddOrder(OrderType.BUY_AUTO, low > parSAR and open[-1] > parSAR, open[-1], tradeSize, Color.BLUE, Color.LIGHT_GREEN, ” Long @ ” +open()[-1]); #and open[-1] > parSAR

AddOrder(OrderType.SELL_TO_CLOSE, longExit[-1], Min(open, parSAR[0]), tradeSize, Color.PINK, Color.PINK,”PSAR @ ” + min(open, parSAR[0]));

AddOrder(OrderType.SELL_AUTO, high < parSAR[0], open[-1], tradeSize, Color.PINK, Color.PINK, “Short @ ” + open[-1]);

AddOrder(OrderType.BUY_TO_CLOSE, shortExit[-1], Max(open, parSAR[0]), tradeSize, Color.BLUE, Color.LIGHT_GREEN, “PSAR @ ” + max(open, parSAR[0]));

Attachments:
RESOLVED
Marked as spam
Posted by (Questions: 3, Answers: 2)
Asked on February 10, 2017 11:39 am
1204 views
0
Private answer

We’ll need a bit more detail as to exactly what specifications you are trying to use for your strategy entries and exits. I don’t want to assume to know this just from looking at your code.

In the mean time I will offer a suggestion. Based on what I saw in your AddOrder() statements, I see some alignment issues. Correcting the alignment may do the trick. So what do I mean by alignment? Well according to the Thinkorswim reference on strategies the condition we select triggers the order on the following bar.

http://tlc.thinkorswim.com/center/howToTos/tutorials/Basic/Chapter-7---Creating-Strategies.html

It can get very confusing when trying to line up what we expect to happen with what actually happens. In order to explain, I built a simple strategy that buys and sells based on a day of the week. I believe this is a great exercise for anyone wanting to learn what makes these things tick. The goal is to build a strategy that buys at the open on Monday and sells the open on Friday. So we start with this:

def buySignal = GetDayOfWeek(GetYYYYMMDD()) == 1;
def sellSignal = GetDayOfWeek(GetYYYYMMDD()) == 5;
def buyPrice = open;
def sellPrice = open;
AddOrder(OrderType.BUY_AUTO, buySignal, buyPrice, 1, Color.GREEN, Color.GREEN, "Buy @ $" + buyPrice );
AddOrder(OrderType.SELL_AUTO, sellSignal, sellPrice, 1, Color.RED, Color.RED, "Sell @ $" + sellPrice);

Reference the first screenshot below for the result. On the bottom of the chart I plot the day of week. In Thinkorswim, Monday = 1 and Sunday = 7. You can see that the code creates a buy signal on day 1, but the order is placed on day 2. This is exactly what we should expect, but how do we get it to place the orders on Monday and Friday? And hold on a minute, the prices are not matching at all. The entry prices are picked up from the previous bar, the bar that produced the signal. Let see if we can get that corrected in the next step, before we move forward to the final solution.

def buySignal = GetDayOfWeek(GetYYYYMMDD()) == 1;
def sellSignal = GetDayOfWeek(GetYYYYMMDD()) == 5;
def buyPrice = open;
def sellPrice = open;
AddOrder(OrderType.BUY_AUTO, buySignal, buyPrice[-1], 1, Color.GREEN, Color.GREEN, "Buy @ $" + buyPrice[-1] );
AddOrder(OrderType.SELL_AUTO, sellSignal, sellPrice[-1], 1, Color.RED, Color.RED, "Sell @ $" + sellPrice[-1]);

Reference the second screenshot to see the result.

Ok, good. We now have the entry prices matching the opening price of each bar. We did this by adding brackets and a minus 1 “[-1]” after each buyPrice and sellPrice in the AddOrder() statements. This is what I mean by “alignment”. We have properly aligned the entries and exits with the prices. So let’s see if we can finish up our project and get the buy and sell signals to occur on Monday and Friday like we have specified.

def buySignal = GetDayOfWeek(GetYYYYMMDD()) == 1;
def sellSignal = GetDayOfWeek(GetYYYYMMDD()) == 5;
def buyPrice = open;
def sellPrice = open;
AddOrder(OrderType.BUY_AUTO, buySignal[-1], buyPrice[-1], 1, Color.GREEN, Color.GREEN, "Buy @ $" + buyPrice[-1] );
AddOrder(OrderType.SELL_AUTO, sellSignal[-1], sellPrice[-1], 1, Color.RED, Color.RED, "Sell @ $" + sellPrice[-1]);

Reference the third screenshot to see the result.

Well, everything looks good. We have orders taking place at Monday’s open and Friday’s open. And the prices are properly aligned. But how did we do this? We added a [-1] to the entry and exit signal within the AddOrder() statements. And we left the [-1] on the entry and exit prices. That doesn’t really make sense, does it? That’s the real challenge when working on strategies. In order to properly align your signals and the prices takes a bit of practice. Things get even more complicated when we want our entry and exit signals to be triggered based on a value from a previous bar, such as a trailing stop.

So once we understand the specification, we should be able to offer some guidance on the code posted by the author of this question.

Attachments:
Marked as spam
Posted by (Questions: 37, Answers: 4084)
Answered on February 10, 2017 1:46 pm
0
Private answer

Following your example…here’s what I came up with.  Those entries and exits did fix themselves. Thank you!!!!

 

def longExit = low < parSAR[1];
def shortExit = high > parSAR[1];
def buySignal = low > parSAR and open > parSAR;
def sellSignal = high < parSAR and open < parSAR;
AddOrder(OrderType.BUY_AUTO, buySignal[-1], open[-1], tradeSize, Color.BLUE, Color.LIGHT_GREEN, ” Long @ ” +open[-1]);

AddOrder(OrderType.SELL_TO_CLOSE, longExit[-1], Min(open, parSAR[-1]), tradeSize, Color.PINK, Color.PINK,”PSAR @ ” + min(open, parSAR[-1]));

AddOrder(OrderType.SELL_AUTO, sellSignal[-1], open[-1], tradeSize, Color.PINK, Color.PINK, “Short @ ” + open[-1]);

AddOrder(OrderType.BUY_TO_CLOSE, shortExit[-1], Max(open, parSAR[-1]), tradeSize, Color.BLUE, Color.LIGHT_GREEN, “PSAR @ ” + max(open, parSAR[-1]));

Attachments:
Marked as spam
Posted by (Questions: 3, Answers: 2)
Answered on February 10, 2017 2:52 pm
0

Got a little ahead of myself here. The shift fixed itself but the entry and exit are either happening on the open or close, not on the cross are what I need.

( at February 10, 2017 3:15 pm)
1

I received your email requesting professional assistance. Looking forward to helping you get the rest of this dialed for you. This has been a great post and I hope it helps many other viewers who are learning to build advanced Strategies.

( at February 10, 2017 6:14 pm)
0
So what is the end result or best code for this scenario? The shift is fixed but why would there be an order on the open or close? Is it because of the Min or Max condition? Thanks for the answer in advance.
( at October 8, 2020 1:53 pm)
0
In this particular case, the signal is only valid once the bar that triggers the signal has closed and the next bar has opened. So the only valid entry prices for this example require the use of the close of the signal bar or the open of the bar that follows. If using intraday data, set the order to use the open of the bar that follows the signal. For daily and higher time frames, set the order to use the close of the bar that triggers the signal.
( at October 8, 2020 3:18 pm)