Problem possibly linked to separating a variable definition from its value assignment

italnsd

New member
TLDR: I am trying to write a study that uses a state variable to transfer information from one bar to the next, but can't manage to understand why it fails, returning N/A values for the state variable (and obviously an empty plot). I suspect the issue is related to separating the variable definition from its value assignment.

While the implementation of a state variable is a trivial construction in many programming languages, it is challenging in ThinkScript due the constraint that forbids intrabar variable updates. This led me to the implementation shown in the pseudocode below

Code:
#Begin of the study
def nextState;
def state = CompoundValue(1, nextState[1], 0);
..........................................
# series of computations of quantities and conditions based on the value of state
.............................
plot statePlot = state;
#last instruction computes the state variable for next bar
nextState = function(state);

On bar 1 state is set equal to zero. Despite nextState not being used by the CompoundValue function on bar 1, the thinkScript editor requires it to be defined, which is the reason why I had to add the def nextState statement on top, that is well before the value of nextState gets assigned on the last instruction of the routine.
According to the reference manual this is a legal construct in ThinkScript, if the value is assigned before the variable gets used. This is indeed the case as the routine goes on computing quantities and conditions based on the value of state and finally ends up the execution for bar 1 by assigning to nextState its computed value. This value will then be used for the first time at the beginning of bar 2 when the CompoundValue function assigns it to state.

As mentioned earlier, the study fails returning N/A values for both state and nextState, resulting in empty plots. The suspicion that the failure is related to the separate definition and value assignment of nextState is heightened by the fact that when I eliminate it from the arguments of CompoundValue, writing for example something like
def state = CompoundValue(1, state[1]+1, 0);
then state gets plotted without any problem.
I cannot see in which way my code might violate the syntax described in the ThinkScript manual, and I would appreciate if someone could point that out or maybe let me know whether I am running into some known issue.

To fully illustrate the issue, I attached below a simplified study that reproduces it. This study is meant to run concurrently to a strategy that can either open a long or a short position, under the constraint that at any time there cannot be more than one open position, which, hence, needs to be closed before any other trade can take place. While in the strategy this constraint is handled automatically by using the appropriate OrderType (BUY_TO_OPEN, SELL_AUTO, SELL_TO_CLOSE, SELL_TO_OPEN), in a study a state variable is needed to greenlight only those trade that are allowed in a given state.

Code:
# ==========================================
# ThinkScript study that monitors 4 boolean variables that signal the conditions to enter/exit a long or a short position .
# Constraint: At all times there cannot be more than one open position
# Entry into a long (short) position is triggered by the boolean longEntry (shortEntry), which is true when the fast MA crosses above (below) the slow MA AND the latter is increasing decreasing)
# Exit from a long (short) position is triggered by longExit (shortExit) which is true when either the fast MA is below (above) the slow MA OR the latter is decreasing (increasing) for as many consecutive bars as specified by exitBars.
# The variable state represents the current open position and determines what trades are feasible in that situatio: if there is no open position (state = 0), both longEntry and shortEntry are valid trade triggers, if there is an open long position (state = 1), only exitLong is a valid trade trigger, if there is an open short position (state = -1) only exitShort is a valid trade trigger
# ==========================================
declare lower;

input fastLen = 3;
input slowLen = 60;
input exitBars = 6;
input price = open;

def fastMA = Average(price, 3);
def slowMA = Average(price, 60);
def slowSlope = slowMA - slowMA[1];
def slowGrowing = slowSlope > 0;
def slowFalling = slowSlope < 0;

def crossUp   = fastMA crosses above slowMA;
def crossDown = fastMA crosses below slowMA;

#############################################################
# ----------------------------
# state variable (stable this bar)
# ----------------------------
def nextState;
def state = CompoundValue(1, nextState[1], 0);  # State is x(n), nextState is x(n+1)
def isFlat  = state == 0;
def inLong  = state == 1;
def inShort = state == -1;

# To compute valid Entries/exits use state x(n)
#Long Entry points
def longEntry = isFlat and crossUp and slowGrowing;

#Short Entry points
def shortEntry = isFlat and crossDown and slowFalling;

# Exit points
def longFail  = inLong  and (fastMA < slowMA or slowFalling);
def shortFail = inShort and (fastMA > slowMA or slowGrowing);

# Counts must also be CompoundValue (safer) and must reset when not in that position
def longFailCount = CompoundValue(
    1,
    if !inLong then 0 else if longFail then longFailCount[1] + 1 else 0,
    0
);

def shortFailCount = CompoundValue(
    1,
    if !inShort then 0 else if shortFail then shortFailCount[1] + 1 else 0,
    0
);

#Long Exit points
def longExit = longFailCount >= exitBars;

#Short Exit points
def shortExit = shortFailCount >= exitBars;

# ----------------------------
# Computation of nextState
# ----------------------------
nextState =
    if longExit then 0
    else if shortExit then 0
    else if longEntry then 1
    else if shortEntry then -1
    else state;

# The value on nextState in bar n becomesthe value of state in bar n+1

#Plot the state with the transition shown in the bar and entry/exit happened
plot statePlot = state;
statePlot.SetDefaultColor(Color.BLUE);

plot nextStatePlot = nextState;
nextStatePlot.SetDefaultColor(Color.RED);
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
1270 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top