% Percentage Change for ThinkorSwim

Branch

Member
Can someone create a label that will tell me how much the current product (symbol) is up or down? TOS has it in the Symbol Menu but I would like to have it on the chart as a label also.

Code:
# =============================================================================
#Hint: <b>PM Percent Change</b>\nCalculates the percent change in value from now and N periods ago where<li>value: any data type enumerated by FundamentalData such as CLOSE, IV, etc.</li><li>N: user specified look back length</li><li>period: user or chart selected aggregation period such as FIVE_MIN, DAY, WEEK, etc.</li>
#
# PM Percent Change
#
# @author: Patrick Menard, @dranem05, [email protected]
#
# This script calculates the percent change in value from now and N periods ago
# where:
#
#     value: data type enumerated by FundamentalData := CLOSE, IV, VOLUME, etc.
#         N: user specified look back length
#    period: user or chart selected aggregation period := MIN, DAY, WEEK, etc.
#
# This script can be used as a plot and as a label. If displayed on a lower
# subgraph, the % chg and its hi and lo alert triggered instances will be
# shown as it occurred over time. If 'show_label' is enabled, the most recent
# % chg will be displayed on the chart. To use this script purely as a label
# on the main price chart, set 'label_only' to YES in the script settings window
#
# This script utilized ThinkOrSwim's built-in PercentChg script and the
# customizability provided in the PM_Rank script as inspiration.
#
# LICENSE ---------------------------------------------------------------------
#
# This PM_PercentChg script is free software distributed under the terms of the
# MIT license reproduced here:
#
# The MIT License (MIT)
#
# Copyright (c) 2013 Patrick Menard, http://www.dranem05.com, http://dranem05.blogspot.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# =============================================================================


input label_only       = YES; #Hint label_only: use this script only as a label (supercedes 'show_label')
input show_label       = YES; #Hint show_label: Toggle display of a label to display the % chg value (superceded by 'label_only')
input data_type        = FundamentalType.CLOSE; #Hint data_type: Data on which to compute a % chg
input length           = 10; #Hint length: 252 ~= 12 mth<br>189 ~= 9 mth<br>126 ~= 6 mth<br>63 ~= 3 mth
input period           = AggregationPeriod.DAY; #Hint period: Must be DAY or greater for IV computations
input use_chart_ap     = NO; #Hint use_chart_ap: Set to YES to utilize the chart's aggregation period
input high_alert       =  5.0; #Hint high_alert: Percent equal to or above which to change % chg display color
input low_alert        = -5.0; #Hint low_alert: Percent equal to or below which to change % chg display color
input multiplier       = 100; #Hint multiplier: 100 turns the % chg into a percentage, 1 leaves it as a decimal
input rounding         = 2; #Hint rounding: Number of decimal digits to which % chg value shall round
input no_nans          = YES; #Hint no_nans: If YES, return the previous % chg if current data is NaN

# -------------------------------------------------------------------------
# Ensure Aggregation Period is supported per the Fundamental Type specified
# -------------------------------------------------------------------------
#
# IMP_VOLATILITY does not support Aggregration periods less than 1 day.
# So, display at least the daily IV value

def ap_choice = if use_chart_ap then GetAggregationPeriod() else period;
def ap        = If( ap_choice < AggregationPeriod.DAY && FundamentalType.IMP_VOLATILITY == data_type, AggregationPeriod.DAY, ap_choice );

# -------------------------------------------------------------------------
# Adjust high and low alert thresholds to account for % chg multiplier
# -------------------------------------------------------------------------

plot pct_chg; # declare here so it appears first in strategy settings box on TOS
plot hi_alert = high_alert * multiplier / 100.0;
plot lo_alert = low_alert  * multiplier / 100.0;

# -------------------------------------------------------------------------
# Compute the percent change
# -------------------------------------------------------------------------

# If 'no_nans' is enabled, the previously computed % chg is returned when
# the fundamental data is NaN. If there is no previously computed % chg,
# the value returned will be what TOS uses to initialize variables:
#
#    0 as of 11/4/2013.
#
# Otherwise, NaN will be returned when a gap is encountered.
#
# TODO: may need to distinguish between gap meaning no data period vs. a temporary hole in the data (like a halt)

#def data      = Fundamental(data_type, period=ap); #TODO: creates an array or maps 'data' to this fundamental array?
#def data      = close(period=ap); #TODO: creates an array or maps 'data' to this fundamental array?
#def pct_chg_v = if   no_nans && (IsNaN(data) or IsNaN(data[length]))
#                then pct_chg_v[1]
#                else Round(multiplier * (data / data[length] - 1), rounding);

# Using 'data', whether def or plot, to reference Fundamental() does not
# work as one would assume. During market hours (OnDemand or Live), the
# result returned for data[N] is the same as data[0]. Whereas explicitly
# doing Fundamental(dt,pd)[N] returns the actual value for N periods ago.
# The same is true if we reference directly 'close', 'open', etc.
#
# So, we have to be explicit in code until this ThinkScript error is fixed.

def pct_chg_v = if   no_nans && (IsNaN(Fundamental(data_type, period=ap)) or IsNaN(Fundamental(data_type, period=ap)[length]))
                then pct_chg_v[1]
                else Round(multiplier * (Fundamental(data_type, period=ap) / Fundamental(data_type, period=ap)[length] - 1), rounding);
pct_chg       = pct_chg_v;

# DEBUGGING TOOLS
#AddLabel(1, Concat("d[0]: ", data[0]), Color.CYAN);
#AddLabel(1, Concat("d[" + length + "]: ", data[length]), Color.CYAN);
#AddLabel(1, Concat("c[0]: ", close(period=ap)[0]), Color.CYAN);
#AddLabel(1, Concat("c[" + length + "]: ", close(period=ap)[length]), Color.CYAN);
#AddLabel(1, Concat("f[0]: ", Fundamental(data_type, period=ap)[0]), Color.CYAN);
#AddLabel(1, Concat("f[" + length + "]: ", Fundamental(data_type, period=ap)[length]), Color.CYAN);

# -------------------------------------------------------------------------
# Create visual effects, display label if requested
# -------------------------------------------------------------------------

# set colors based on hi and lo alert thresholds --------------------------

pct_chg.DefineColor("HiAlert", Color.UPTICK);
pct_chg.DefineColor("Normal" , Color.GRAY);
pct_chg.DefineColor("LoAlert", Color.DOWNTICK);
pct_chg.AssignValueColor( if pct_chg >= hi_alert then pct_chg.Color("HiAlert") else if pct_chg <= lo_alert then pct_chg.Color("LoAlert") else pct_chg.Color("Normal") );
hi_alert.SetDefaultColor( Color.YELLOW );
lo_alert.SetDefaultColor( Color.YELLOW );

# select the label's prefix based on the fundamental type -----------------

# cannot use switch/case as ThinkScript's fundamental types are not enums

AddLabel(show_label or label_only,
              Concat( if data_type == FundamentalType.IMP_VOLATILITY then "IV "
         else if data_type == FundamentalType.OPEN           then "$O "
         else if data_type == FundamentalType.HIGH           then "$H "
         else if data_type == FundamentalType.LOW            then "$L "
         else if data_type == FundamentalType.CLOSE          then "PRICE "
         else if data_type == FundamentalType.HL2            then "$HL2 "
         else if data_type == FundamentalType.HLC3           then "$HLC3 "
         else if data_type == FundamentalType.OHLC4          then "$OHLC4 "
         else if data_type == FundamentalType.VWAP           then "VWAP "
         else if data_type == FundamentalType.VOLUME         then "VOLUME "
         else if data_type == FundamentalType.OPEN_INTEREST  then "OI "
         else                                                     "",
         "%CHG("+length+") " + pct_chg),
         pct_chg.TakeValueColor() );

# hide plots if user wants labels only ------------------------------------

hi_alert.SetHiding( label_only );
lo_alert.SetHiding( label_only );
pct_chg.SetHiding( label_only );
 
Solution
I have updated the Percent Change Label (from Previous Day's Close) that should work both on a daily as well as intraday aggregations. Since the equities market is currently closed I have tested this against /ES. It seems to work fine as far as I can tell.

Code:
# Percent Change Label (from Yesterday's Close)
# tomsk
# 1.9.2020

# V1.0 - 01.08.2020 - tomsk - Initial release of Percent Change Label, to be used for daily aggregation
# V1.1 - 01.09.2020 - tomsk - Updated to work on intraday aggregation as well as daily

def PC = close(period = AggregationPeriod.DAY)[1];
def PctChange = (close - PC) / PC;
AddLabel(1, "Percent Change = " + AsPercent(PctChange), if PctChange > 0 then Color.Green else if PctChange < 0 then Color.Red else...

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

If I have to see this in one minute daily chart for intraday trading and need to see price change back in 3 minutes candles how the script would be different?

I need to compare price 3 minutes ago in three minute daily chart. will it work?
 
Hello All ! I tried to look on the forum but did not find. Tried to build it myself but with no success.

I'm trying to add a column or a scan for %change since the market opens at 09:30...and not from the previous close price.

Thank you for your help !
 
Hello,

I'm a bit new to this, but the code below should do the trick!

Code:
# Get percent change from Open

input Agg = AggregationPeriod.DAY;

def currentPrice = ask;
def openPrice = open;

def priceDifference = ask - open;

plot percentChange = priceDifference / open;

AddLabel(yes, open + "  " + close + "   " +asPercent(round(percentChange,4)), if close < open then color.RED else color.Green);

#Edit - fixed the label
 
Last edited:
I got it. Thanks. If I have to use on 5 minutes chart then what value do I set “input bar ago”?

If I understand correctly, any time frame for intraday 1 min, 3 min or 15 min, “Input bars ago” will remain always 1 bar ago?
I am novice so apologize for this.
Thanks.
 
@Nervo,


The first input agg will set the currentPrice to day(I made sure I followed through with adding this as a parameter below).

currentPrice fetches the ask. Which should be a constant across all time periods..

I caught an error or two on the original code though now that you mention it..the fixed version is below. Thanks for helping me catch it!

Code:
# Get percent change from Open

input agg = AggregationPeriod.DAY;

def currentPrice = ask;
def openPrice = open(period = agg); # Fixed: I didn't set the agg as a parameter to the open price


def priceDifference = ask - open;

plot percentChange = priceDifference / open;

AddLabel(yes, asPercent(round(percentChange,4)), if ask < open then color.RED else color.Green); # changed close to ask

#Edit - fixed the label
 
Last edited:
Well if you just want the close of the last bar for the timeframe aggregation you choose for your watchlist column, then yes it will remain 1 bar ago. Keep in mind that means for a 15 minute bar, it will not be comparing the current price to 15 minutes ago. When the new bar starts, the current price will be compared to 1min ago, then 2 min ago, then 3...... until it hits 15 min ago, then the new bar starts.

The other way, if you want the price 15 minutes ago, but want it to update every minute, you want the aggregation to be 1 minute and make it 15 bars ago.
 
What's the difference between your column and the colume %CHANGE on TOS???
@Len20 @aharvard
I'd actually like to expand on this topic.
When I use this scan below, is the % change from yesterday to current price OR is the % change from the open of today to the current price???

edit: the TOS % change is from yesterday close to current price. But is it possible to scan criteria today %change from open to current price is a certain %????


last edit: figured it out
Code:
input price = close;
input percentchange = 1.0;
input Choice = {default less};

def fromopen = round(100*((close/open)-1),1);
plot scan;

switch (Choice){

case less:
    scan = fromopen <= -percentchange;

}

owKOgv8h.jpg
 
Last edited:
@jngy2k

I'm new to this. Does this indicate a 1 percent or greater change from open will show in the scan query? If so, can anyone advise as to why when entered I'm getting % change results (as indicated by the column % change and it's corresponding values) that are beyond that 1%? I'm trying to achieve a scan result that will only show stocks that have changed a certain percentage since open, whether it be negative or positive, so that I can set an alert for that query and react accordingly. Any help would be greatly appreciated.

Edit: Or, what about this? I'm still confused about the aggregator period and what that means, exactly. Running the below gives the same results as the default %change so I don't know if I have to wait until the market opens up to get an open value or what, tbh. Is it saying, for 1 days worth of time calculate the percentage change using the given (if aggregator is set to 1D). If that's the case, do you have to wait an entire day for it to update, or is it real-time? What is it saying if you set it to 1 hour? Percentage change from open for the most recent hour, excluding time previous to that, lol? I dunno.

Code:
input MinChangeFromOpen = 0.9; #Change from open, %
def ChangeFromOpen = AbsValue((close-open)/open*100);
plot Signal = ChangeFromOpen >= MinChangeFromOpen;
 
Last edited:

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
437 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