Looking for Parabolic SAR MTF (Multi Time Frame)

flyer01

New member
Would anyone be willing to share code for a MTF PSAR script. For example, on a 1 hour chart I would like to see the Parabolic SAR plotted from a 4 hour aggregation. Is this possible?
 
Solution
@flyer01 Here is 4 hour agg. Can input agg of your choice to display PSAR at a different agg than chart.

Code:
#
# TD Ameritrade IP Company, Inc. (c) 2008-2019 ParabolicSAR
# Changed to 4 hour aggregation by Horserider 12/13/2019

input accelerationFactor = 0.02;
input accelerationLimit = 0.2;

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;
input agg = AggregationPeriod.FOUR_HOURS;
def high = high (period = agg);
def low = low...
@flyer01 Here is 4 hour agg. Can input agg of your choice to display PSAR at a different agg than chart.

Code:
#
# TD Ameritrade IP Company, Inc. (c) 2008-2019 ParabolicSAR
# Changed to 4 hour aggregation by Horserider 12/13/2019

input accelerationFactor = 0.02;
input accelerationLimit = 0.2;

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;
input agg = AggregationPeriod.FOUR_HOURS;
def high = high (period = agg);
def low = low (period = agg);
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 = SAR;
parSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
parSAR.SetDefaultColor(GetColor(5));
 
Solution
Nice study. Im using, is so useful. Do you know any study with a Parabolic SAR but crossover MTF? Im looking an arrow to see the trend within parabolicSAR. For example, in lower timeframe I would like to know when the price crossover parabolic in higher timeframe.
 
It would be nice, Parabolic SAR is one of the best trend directions than I ever see. Im seeing if can help to see the trend using swingarms (crossover represented in a arrow).
 
I am using "Multi time-frame Parabolic SAR indicator by tradegeek" and I'm wanting to make a scanner that lists stocks that have had their totalAssetTurnover cross below 3 (turn green) in the last like 12 minutes (I use 1 day 2 min charts so that would be 6 bars). I'm wanting to do this because the indicator would give much better results if I buy a stock right after MTF_PSAR turns green, instead of when it has been green for a while.

Though this does not work because the scanner doesn't allow you to use multiple aggregation periods in one filter. If I split each TimeFrame into different filters, then I can't check that the sum of them is less than 3.
I'm using this code:
Code:
declare lower;

input TimeFrame1 = AggregationPeriod.MIN;
input TimeFrame2 = AggregationPeriod.TWO_MIN;
input TimeFrame3 = AggregationPeriod.FIVE_MIN;
input TimeFrame4 = AggregationPeriod.TEN_MIN;
input TimeFrame5 = AggregationPeriod.FIFTEEN_MIN;
input PaintBars = {default "yes", "no"};

def close1 = Close(Period = TimeFrame1);
def close2 = Close(Period = TimeFrame2);
def close3 = Close(Period = TimeFrame3);
def close4 = Close(Period = TimeFrame4);
def close5 = Close(Period = TimeFrame5);

def low1 = Low(Period = TimeFrame1);
def low2 = Low(Period = TimeFrame2);
def low3 = Low(Period = TimeFrame3);
def low4 = Low(Period = TimeFrame4);
def low5 = Low(Period = TimeFrame5);

def high1 = High(Period = TimeFrame1);
def high2 = High(Period = TimeFrame2);
def high3 = High(Period = TimeFrame3);
def high4 = High(Period = TimeFrame4);
def high5 = High(Period = TimeFrame5);

input accelerationFactor = 0.02;
input accelerationLimit = 0.2;

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 + ")");

##### Chart Time-frame (Time-frame 1)
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]));
    }
}

##### Time-frame 2
def state2 = {default init, long, short};
def extreme2;
def SAR2;
def acc2;

switch (state2[1]) {
case init:
    state2 = state2.long;
    acc2 = accelerationFactor;
    extreme2 = high2;
    SAR2 = low2;
case short:
    if (SAR2[1] < high2)
    then {
        state2 = state2.long;
        acc2 = accelerationFactor;
        extreme2 = high2;
        SAR2 = extreme2[1];
    } else {
        state2 = state2.short;
        if (low2 < extreme2[1])
        then {
            acc2 = min(acc2[1] + accelerationFactor, accelerationLimit);
            extreme2 = low2;
        } else {
            acc2 = acc2[1];
            extreme2 = extreme2[1];
        }
        SAR2 = max(max(high2, high2[1]), SAR2[1] + acc2 * (extreme2 - SAR2[1]));
    }
case long:
    if (SAR2[1] > low2)
    then {
        state2 = state2.short;
        acc2 = accelerationFactor;
        extreme2 = low2;
        SAR2 = extreme2[1];
    } else {
        state2 = state2.long;
        if (high2 > extreme2[1])
        then {
            acc2 = min(acc2[1] + accelerationFactor, accelerationLimit);
            extreme2 = high2;
        } else {
            acc2 = acc2[1];
            extreme2 = extreme2[1];
        }
        SAR2 = min(min(low2, low2[1]), SAR2[1] + acc2 * (extreme2 - SAR2[1]));
    }
}

##### Time-frame 3
def state3 = {default init, long, short};
def extreme3;
def SAR3;
def acc3;

switch (state3[1]) {
case init:
    state3 = state3.long;
    acc3 = accelerationFactor;
    extreme3 = high3;
    SAR3 = low3;
case short:
    if (SAR3[1] < high3)
    then {
        state3 = state3.long;
        acc3 = accelerationFactor;
        extreme3 = high3;
        SAR3 = extreme3[1];
    } else {
        state3 = state3.short;
        if (low3 < extreme3[1])
        then {
            acc3 = min(acc3[1] + accelerationFactor, accelerationLimit);
            extreme3 = low3;
        } else {
            acc3 = acc3[1];
            extreme3 = extreme3[1];
        }
        SAR3 = max(max(high3, high3[1]), SAR3[1] + acc3 * (extreme3 - SAR3[1]));
    }
case long:
    if (SAR3[1] > low3)
    then {
        state3 = state3.short;
        acc3 = accelerationFactor;
        extreme3 = low3;
        SAR3 = extreme3[1];
    } else {
        state3 = state3.long;
        if (high3 > extreme3[1])
        then {
            acc3 = min(acc3[1] + accelerationFactor, accelerationLimit);
            extreme3 = high3;
        } else {
            acc3 = acc3[1];
            extreme3 = extreme3[1];
        }
        SAR3 = min(min(low3, low3[1]), SAR3[1] + acc3 * (extreme3 - SAR3[1]));
    }
}

##### Time-frame 4
def state4 = {default init, long, short};
def extreme4;
def SAR4;
def acc4;

switch (state4[1]) {
case init:
    state4 = state4.long;
    acc4 = accelerationFactor;
    extreme4 = high4;
    SAR4 = low4;
case short:
    if (SAR4[1] < high4)
    then {
        state4 = state4.long;
        acc4 = accelerationFactor;
        extreme4 = high4;
        SAR4 = extreme4[1];
    } else {
        state4 = state4.short;
        if (low4 < extreme4[1])
        then {
            acc4 = min(acc4[1] + accelerationFactor, accelerationLimit);
            extreme4 = low4;
        } else {
            acc4 = acc4[1];
            extreme4 = extreme4[1];
        }
        SAR4 = max(max(high4, high4[1]), SAR4[1] + acc4 * (extreme4 - SAR4[1]));
    }
case long:
    if (SAR4[1] > low4)
    then {
        state4 = state4.short;
        acc4 = accelerationFactor;
        extreme4 = low4;
        SAR4 = extreme4[1];
    } else {
        state4 = state4.long;
        if (high4 > extreme4[1])
        then {
            acc4 = min(acc4[1] + accelerationFactor, accelerationLimit);
            extreme4 = high4;
        } else {
            acc4 = acc4[1];
            extreme4 = extreme4[1];
        }
        SAR4 = min(min(low4, low4[1]), SAR4[1] + acc4 * (extreme4 - SAR4[1]));
    }
}

##### time-frame 5
def state5 = {default init, long, short};
def extreme5;
def SAR5;
def acc5;

switch (state5[1]) {
case init:
    state5 = state5.long;
    acc5 = accelerationFactor;
    extreme5 = high5;
    SAR5 = low5;
case short:
    if (SAR5[1] < high5)
    then {
        state5 = state5.long;
        acc5 = accelerationFactor;
        extreme5 = high5;
        SAR5 = extreme5[1];
    } else {
        state5 = state5.short;
        if (low5 < extreme5[1])
        then {
            acc5 = min(acc5[1] + accelerationFactor, accelerationLimit);
            extreme5 = low5;
        } else {
            acc5 = acc5[1];
            extreme5 = extreme5[1];
        }
        SAR5 = max(max(high5, high5[1]), SAR5[1] + acc5 * (extreme5 - SAR5[1]));
    }
case long:
    if (SAR5[1] > low5)
    then {
        state5 = state5.short;
        acc5 = accelerationFactor;
        extreme5 = low5;
        SAR5 = extreme5[1];
    } else {
        state5 = state5.long;
        if (high5 > extreme5[1])
        then {
            acc5 = min(acc5[1] + accelerationFactor, accelerationLimit);
            extreme5 = high5;
        } else {
            acc5 = acc5[1];
            extreme5 = extreme5[1];
        }
        SAR5 = min(min(low5, low5[1]), SAR5[1] + acc5 * (extreme5 - SAR5[1]));
    }
}

##### Plots
def PSAR = if IsNaN(SAR) then Double.NaN else 1;

def PSAR2 = if IsNaN(SAR2) then Double.NaN else 2;

def PSAR3 = if IsNaN(SAR3) then Double.NaN else 3;

def PSAR4 = if IsNaN(SAR4) then Double.NaN else 4;

def PSAR5 = if IsNaN(SAR5) then Double.NaN else 5;

def PSAR_TF1 = if state == state.long then 0 else 1;
def PSAR_TF2 = if state2 == state2.long then 0 else 1;
def PSAR_TF3 = if state3 == state3.long then 0 else 1;
def PSAR_TF4 = if state4 == state4.long then 0 else 1;
def PSAR_TF5 = if state5 == state5.long then 0 else 1;


plot MTF_PSAR = 6;
MTF_PSAR.SetPaintingStrategy(PaintingStrategy.SQUARES);
MTF_PSAR.SetLineWeight(lineWeight = 3);
MTF_PSAR.DefineColor("Buy", GetColor(5));
MTF_PSAR.DefineColor("Sell", GetColor(6));
MTF_PSAR.AssignValueColor ( if (PSAR_TF1 + PSAR_TF2 + PSAR_TF3 + PSAR_TF4 + PSAR_TF5) >= 3 then MTF_PSAR.Color("Buy") else MTF_PSAR.Color("Sell"));

plot totalAssetTurnover = (PSAR_TF1 + PSAR_TF2 + PSAR_TF3 + PSAR_TF4 + PSAR_TF5);
plot line = 3;
 
Howdy @horserider, sorry to necropost but I noticed the PSAR MTF code you posted will plot different values when viewed in lower aggregations.

Example for AAPL: "WEEK" PSAR level when viewing on a 1Month : Day chart is $149.12, but when viewing on a 1Year : Day chart is $165.16. "YEAR" PSAR level on 1Year : Day is $116.21 versus 66.10 on 5Year : Week.

The value can also change when looking at the same "time frame" (5 years for example) but when using a different candle length (4 Hour, Day, Week, Month...).

I also noticed this happens when almost any higher aggregation plot is created outside the timeframe that's being displayed.

Do you know if there's a way for these plots to display the same value across all aggregations regardless of length or candle duration?

Thanks!
 
Last edited:
Howdy @horserider, sorry to necropost but I noticed the PSAR MTF code you posted will plot different values when viewed in lower aggregations.

Example for AAPL: "WEEK" PSAR level when viewing on a 1Month : Day chart is $149.12, but when viewing on a 1Year : Day chart is $165.16. "YEAR" PSAR level on 1Year : Day is $116.21 versus 66.10 on 5Year : Week.

The value can also change when looking at the same "time frame" (5 years for example) but when using a different candle length (4 Hour, Day, Week, Month...).

I also noticed this happens when almost any higher aggregation plot is created outside the timeframe that's being displayed.

Do you know if there's a way for these plots to display the same value across all aggregations regardless of length or candle duration?

Thanks!
MTF indicators will only reflect the correct value when the high timeframe closes.
For example if you have an hourly aggregation on a 2min chart. It will take 30 bars for those bars to reflect the correct value.
Read more about MTF repainting here:
https://usethinkscript.com/threads/answers-to-commonly-asked-questions.6006/#post-57833
 
Thanks for the reply @MerryDay ... I thought for sure my question would have been lost in the abyss by now. :)

Also, thanks for the clarification and the link! I went ahead and gave it a read and it's possible that I'm encountering some of what's in that post. It's also possible that what I'm experiencing is part of how PSAR plots overall.

I'm fairly familiar with MTF studies, specifically MTF StandardDev/Error Channels as well as MTF Moving averages (I've used and modified ThinkScript code for both). Generally, the values they plot are pretty consistent across all the lower aggregations and they only seem to vary slightly when looking an smaller and smaller aggregations (plotting a Weekly MTF MA level on a 10 minute chart for example).

What I'm running into is a bit different.

Essentially, what I think is happening, is that when the Stop-And-Reverse (switch from Long to Short) occurs outside the viewed time frame, it somehow changes the plot (not just the value but also changes from long to short).

Here's a couple screenshots of what I'm talking about:
I'm assuming it has something to do with how the indicator looks back when viewing smaller aggregations. So far, my solution has been to "max out" any aggregation I'm viewing (1D : Max, 4H : 360Day, etc) to make sure it doesn't mis-plot.

Any input or help is always greatly appreciated!
 
Thanks for the reply @MerryDay ... I thought for sure my question would have been lost in the abyss by now. :)

Also, thanks for the clarification and the link! I went ahead and gave it a read and it's possible that I'm encountering some of what's in that post. It's also possible that what I'm experiencing is part of how PSAR plots overall.

I'm fairly familiar with MTF studies, specifically MTF StandardDev/Error Channels as well as MTF Moving averages (I've used and modified ThinkScript code for both). Generally, the values they plot are pretty consistent across all the lower aggregations and they only seem to vary slightly when looking an smaller and smaller aggregations (plotting a Weekly MTF MA level on a 10 minute chart for example).

What I'm running into is a bit different.

Essentially, what I think is happening, is that when the Stop-And-Reverse (switch from Long to Short) occurs outside the viewed time frame, it somehow changes the plot (not just the value but also changes from long to short).

Here's a couple screenshots of what I'm talking about:
I'm assuming it has something to do with how the indicator looks back when viewing smaller aggregations. So far, my solution has been to "max out" any aggregation I'm viewing (1D : Max, 4H : 360Day, etc) to make sure it doesn't mis-plot.

Any input or help is always greatly appreciated!
Ahhhhh... Wow, as you have astuted; it uses extremes in its calculations:
Read more here and here for some workarounds:
https://usethinkscript.com/threads/tos-parabolic-sar-bug-is-there-a-working-alternative.10260/
https://usethinkscript.com/threads/psar-shifting-question.3709/
 

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
404 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