LowestAll & HighestAll causing error in ThinkorSwim

E

eddielee394

Member
Working on a custom P&L study that's used in conjunction with a strategy (see full script here). I'm attempting to get the lowest and highest P&L for each round trip triggered by the strategy (not the Total P&L value, but the return for each individual trade - i.e. $1.50[exitPrice] - $1.00[entryPrice] = .50). The code as is working fine to determine the difference between the exitPrice and entryPrice. The problem is when I store the return value in a temp variable and then try to use either HighestAll() or LowestAll() to find the highest and lowest trade returns, it breaks all of my win/loss ratios.
Code:
def highestReturn = HighestAll(entryReturnWin);
def lowestReturn = LowestAll(entryReturnLoss);
After some debugging it seems when using either HighestAll() or LowestAll() on any of the variables declared using the isExitBar condition, it breaks all the win/loss logic due to a divide by zero error and instead of returning the highest/lowest returns it just returns 0 for either. The odd thing is that if I use Highest or Lowest everything works fine with the caveat that I can only check for the highest/lowest return for a maximum of 2000 bars in the past (which will potentially return the incorrect lowest value if the chart is greater than 2k bars).
Code:
#Breaks all the win/loss calculations and returns 0
def highestReturn = HighestAll(entryReturnWin);
def lowestReturn = LowestAll(entryReturnLoss);

#Does not break the win/loss calculations but will not return lowest value if it's older than 2k bars
def highestReturn = Highest(entryReturnWin, 1999); 
def lowestReturn = Lowest(entryReturnLoss, 1999);

I'm thinking there may be a problem deeper in my code, but I can't seem to figure out where. Here's the logic that handles the w/l ratios, counts & trade return calculations. If anyone needs to dig deeper than the snippet below, the entire script can be found in this post. Any suggestions on how to resolve this using the current logic or possibly another different approach to calculating the difference between the entry and exit price of a strategy order?


Python:
#Win/Loss ratios
def entryBarsTemp = if hasEntry
                    then bn
                    else nan;

def entryBarNum = if hasEntry and IsNaN(entryBarsTemp[1])
                  then bn
                  else entryBarNum[1];

def isEntryBar = entryBarNum != entryBarNum[1];


def entryBarPL = if isEntryBar
                 then FPL
                 else entryBarPL[1];

def exitBarsTemp = if !hasEntry
                   and bn > entryBarsTemp[1]
                   then bn
                   else nan;

def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
                 then bn
                 else exitBarNum[1];

def isExitBar = exitBarNum != exitBarNum[1];

def exitBarPL = if isExitBar
                then FPL
                else exitBarPL[1];

def isWin = if isExitBar and exitBarPL > entryBarPL then 1 else 0;
def isLoss = if isExitBar and exitBarPL < entryBarPL then 1 else 0;
def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else 0;
def entryReturnWin = if entryReturn > 0 then entryReturn else 0;
def entryReturnLoss = if entryReturn < 0 then entryReturn else 0;
def entryFPLWins = if isWin then FPL else entryFPLWins[1];
def entryFPLLosses = if isLoss then FPL else entryFPLLosses[1];
def entryFPLAll = if isLoss or isWin then FPL else entryFPLAll[1];

def winCount = CompoundValue(1,
                 if isWin
                 then winCount[1] + 1
                 else winCount[1], 0);

def lossCount = CompoundValue(1,
                 if isLoss
                 then lossCount[1] + 1
                 else lossCount[1], 0);

def winRate = winCount / lossCount;
def winLossRatio = winCount / entryCount;

#Breaks all the win/loss calculations and returns 0
def highestReturn = HighestAll(entryReturnWin);
def lowestReturn = LowestAll(entryReturnLoss);

def avgReturn = TotalSum(entryReturn)/entryCount;
def avgWin = TotalSum(entryReturnWin)/winCount;
def avgLoss = TotalSum(entryReturnLoss)/lossCount;
 
Last edited:
E

eddielee394

Member
After spending a couple weeks stuck on this I've come to the conclusion, unless someone with more TS experience than I have can explain otherwise, that the issue lies with using HighestAll() or LowestAll() on the EntryPrice() function or on any variables that are initialized using the EntryPrice() function. Not sure why specifically, but it must be some kind of internal quirk that when used with either of the *All functions, they somehow prevent some object that the EntryPrice() function maybe is referencing internally from instantiating when the thinkscript compiler runs. This ends up causing the function to always fail silently, breaking any other references using it throughout the script.

So I implemented the following workaround to get the highest/lowest value within an entire chart without using either of the *All functions. It's basically a recursive variable that continuously checks whether the value of a preceding bar is greater/less than the recursive variable's preceding value.

Code:
def highestReturn = if entryReturnWin[1] > highestReturn[1]
                    then entryReturnWin[1]
                    else highestReturn[1];

def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
                   then entryReturnLoss[1]
                   else lowestReturn[1];
 
Top