# Persons Market Catcher (PMC) Indicator For ThinkOrSwim

#### Jtru94

##### New member
Here it is. To avoid any doubts that I did not pirate or copy the code but rather discovered the logic of the indicator, let me walk you through my process: From https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/O-Q/PMC:

"The Persons Market Catcher (PMC) is a variation on Relative Strength Comparative Analysis of one market versus the S&P 500 on a percentage change basis. The study uses a moving average component to help identify if there is a trend developing in performance over time."

The phrases "percentage change basis" and "moving average component" were the keys.

I started by examining the built-in PercentChg indicator on TOS. It has built within a lookback. I decided to see if the lookback feature has anything to do with the "moving average component". So I took the number 20 (a standard number in the industry) and applied to the lookback. I then just plotted a difference in calculations between the 20-period percentage change of the symbol and the 20-period percentage change of the SPY.

It turned out to match the numbers EXACTLY. I then decided to take a gander at what the moving average on the pmc indicated. I knew it was critical to understanding the color logic, so I took an educated guess that a type of 7period average (like slow average of the PPS indicator) might be a good place to start. A 7ema of the pmc turned out to be the correct answer. I coded the coloring of the pmc accordingly, added a symbol input (for the comparison) and an aggregation input for kicks, and voila:

Code:
``````### Person's Market Catcher Replica
### by Jtru1594
#
# Version 1.0 3/11/2022
#
# Version 2.0 3/13/2022 Added Optional Aggregation Input
#
###

input CorrelationWithSecurity = "SPY";
input alternateTimeFrame = no;
input agg = AggregationPeriod.HOUR;
def AP = GetAggregationPeriod();
def timeframe = if !alternateTimeFrame then AP else agg;
def close2 = close(CorrelationWithSecurity,period = timeframe);
declare lower;
def pctchg = 100 * (close(period = timeframe) / close(period = timeframe)[20] - 1);
def pctchgspy = 100 * (close2 / close2[20] - 1);
plot pmc = pctchg - pctchgspy;
pmc.setPaintingStrategy(paintingStrategy.HISTOGRAM);
plot pmcma = expaverage(pmc, 7);
pmc.assignValueColor(if pmc>=0 and pmc>=pmcma then color.cyan else if pmc>=0 and pmc<=pmcma then color.blue else if pmc<=0 and pmc<=pmcma then color.red else color.magenta);
pmcma.assignValueColor(if pmcma[0]>pmcma[1] then color.yellow else color.blue);
pmcma.setlineweight(2);``````

Nicely done, @Jtru94 Unfortunately this indicator does not appear to work with Futures/Extended Hours, but it looks great on Stock charts...

Here's a link to a brief overview of Persons Market Catcher, presented by John Person:

nice job jtru94, a quick question, on the video above on person charts is a BUY and SELL indicator, the someone have it here? thanks, i think the system call it PBS BUY an PBS SELL

There is a thread about the pps indicator. It features the 7sma and the 4sma(hlc3) as the slow and fast averages respectively, but to date, no one has completely nailed down the signals. The closest I have come is that many signals are similar to the gann Hilo activator (4,4,exponential) but it only matches about 90% of the signals. Personally, I have shied away from the pps signals; I have not found them to give a trend change signal early enough, but I LOVE the PMC.

Nicely done, @Jtru94 Unfortunately this indicator does not appear to work with Futures/Extended Hours, but it looks great on Stock charts...

Here's a link to a brief overview of Persons Market Catcher, presented by John Person:
It would only work with stocks anyhow because the indicator’s linking symbol is the SPY. You have the option to input a security symbol that may best match some sort of market standard to the futures, though.

If you change the lengths , it shows the change from bullishness to bearishness, but it still is not as clear as other indicators

Market Catcher is the lower indicator

Code:
``````input CorrelationWithSecurity = "SPY";
input alternateTimeFrame = no;
input agg = AggregationPeriod.HOUR;
def AP = GetAggregationPeriod();
def timeframe = if !alternateTimeFrame then AP else agg;
def close2 = close(CorrelationWithSecurity,period = timeframe);
declare lower;
input Period1 = 3;
input Period2 = 5;
input Period3 = 8;
input Period4 = 10;
input Period5 = 12;
input Period6 = 15;
input Period7 = 30;
input Period8 = 35;
input Period9 = 40;
input Period10 = 45;
input Period11 = 50;
input Period12 = 60;
input Dotsize = 3;
input Paintbars =0;

def pctchgA = 100 * (close(period = timeframe) / close(period = timeframe)[period1] - 1);
def pctchgspyA = 100 * (close2 / close2[period1] - 1);
def pmcA = pctchgA - pctchgspyA;
def pmcmaA = expaverage(pmcA, 3);
def pctchgB = 100 * (close(period = timeframe) / close(period = timeframe)[period2] - 1);
def pctchgspyB = 100 * (close2 / close2[period2] - 1);
def pmcB = pctchgB - pctchgspyB;
def pmcmaB = expaverage(pmcB, 3);
def pctchgC = 100 * (close(period = timeframe) / close(period = timeframe)[period3] - 1);
def pctchgspyC = 100 * (close2 / close2[period3] - 1);
def pmcC = pctchgC - pctchgspyC;
def pmcmaC = expaverage(pmcC, 3);
def pctchgD = 100 * (close(period = timeframe) / close(period = timeframe)[period4] - 1);
def pctchgspyD = 100 * (close2 / close2[period4] - 1);
def pmcD = pctchgD - pctchgspyD;
def pctchgE = 100 * (close(period = timeframe) / close(period = timeframe)[period5] - 1);
def pctchgspyE = 100 * (close2 / close2[period5] - 1);
def pmcE = pctchgE - pctchgspyE;
def pmcmaE = expaverage(pmcE, 3);
def pctchgF = 100 * (close(period = timeframe) / close(period = timeframe)[period6] - 1);
def pctchgspyF = 100 * (close2 / close2[period6] - 1);
def pmcF = pctchgF - pctchgspyF;
def pmcmaF = expaverage(pmcF, 3);
def pctchgG = 100 * (close(period = timeframe) / close(period = timeframe)[period7] - 1);
def pctchgspyG = 100 * (close2 / close2[period7] - 1);
def pmcG = pctchgG - pctchgspyG;
def pmcmaG = expaverage(pmcG, 7);
def pctchgH = 100 * (close(period = timeframe) / close(period = timeframe)[period8] - 1);
def pctchgspyH = 100 * (close2 / close2[period8] - 1);
def pmcH = pctchgH - pctchgspyH;
def pmcmaH = expaverage(pmcH, 7);
def pctchgI = 100 * (close(period = timeframe) / close(period = timeframe)[period9] - 1);
def pctchgspyI = 100 * (close2 / close2[period9] - 1);
def pmcI = pctchgI - pctchgspyI;
def pmcmaI = expaverage(pmcI, 7);

def pctchgJ = 100 * (close(period = timeframe) / close(period = timeframe)[period10] - 1);
def pctchgspyJ = 100 * (close2 / close2[period10] - 1);
def pmcJ = pctchgJ - pctchgspyJ;
def pmcmaJ = expaverage(pmcJ, 7);
def pctchgK = 100 * (close(period = timeframe) / close(period = timeframe)[period11] - 1);
def pctchgspyK = 100 * (close2 / close2[period11] - 1);
def pmcK = pctchgK - pctchgspyK;
def pmcmaK = expaverage(pmcK, 7);
def pctchgL = 100 * (close(period = timeframe) / close(period = timeframe)[period12] - 1);
def pctchgspyL = 100 * (close2 / close2[period12] - 1);
def pmcL = pctchgL - pctchgspyL;
def pmcmaL = expaverage(pmcL, 7);

plot A1_Dot = if IsNaN(Close) then Double.NaN else 1;
A1_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A1_Dot.SetLineWeight(DotSize);
A1_Dot.AssignValueColor(if pmcA>=0 and pmcA>=pmcmaA then color.cyan else if pmcA>=0 and pmcA<=pmcmaA then color.blue else if pmcA<=0 and pmcA<=pmcmaA then color.red else color.magenta);

plot A2_Dot = if IsNaN(Close) then Double.NaN else 2;
A2_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A2_Dot.SetLineWeight(DotSize);
A2_Dot.AssignValueColor(if pmcB>=0 and pmcB>=pmcmaB then color.cyan else if pmcB>=0 and pmcB<=pmcmaB then color.blue else if pmcB<=0 and pmcB<=pmcmaB then color.red else color.magenta);
plot A3_Dot = if IsNaN(Close) then Double.NaN else 3;
A3_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A3_Dot.SetLineWeight(DotSize);
A3_Dot.AssignValueColor(if pmcC>=0 and pmcC>=pmcmaC then color.cyan else if pmcC>=0 and pmcC<=pmcmaC then color.blue else if pmcC<=0 and pmcC<=pmcmaC then color.red else color.magenta);
plot A4_Dot = if IsNaN(Close) then Double.NaN else 4;
A4_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A4_Dot.SetLineWeight(DotSize);
A4_Dot.AssignValueColor(if pmcD>=0 and pmcD>=pmcmaD then color.cyan else if pmcD>=0 and pmcD<=pmcmaD then color.blue else if pmcD<=0 and pmcD<=pmcmaD then color.red else color.magenta);
plot A5_Dot = if IsNaN(Close) then Double.NaN else 5;
A5_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A5_Dot.SetLineWeight(DotSize);
A5_Dot.AssignValueColor(if pmcE>=0 and pmcE>=pmcmaE then color.cyan else if pmcE>=0 and pmcE<=pmcmaE then color.blue else if pmcE<=0 and pmcE<=pmcmaE then color.red else color.magenta);
plot A6_Dot = if IsNaN(Close) then Double.NaN else 6;
A6_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A6_Dot.SetLineWeight(DotSize);
A6_Dot.AssignValueColor(if pmcF>=0 and pmcF>=pmcmaF then color.cyan else if pmcF>=0 and pmcF<=pmcmaF then color.blue else if pmcF<=0 and pmcF<=pmcmaF then color.red else color.magenta);
plot B7_Dot = if IsNaN(Close) then Double.NaN else 7;
B7_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B7_Dot.SetLineWeight(DotSize);
B7_Dot.AssignValueColor(if pmcG>=0 and pmcG>=pmcmaG then color.cyan else if pmcG>=0 and pmcG<=pmcmaG then color.blue else if pmcG<=0 and pmcG<=pmcmaG then color.red else color.magenta);
plot B8_Dot = if IsNaN(Close) then Double.NaN else 8;
B8_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B8_Dot.SetLineWeight(DotSize);
B8_Dot.AssignValueColor(if pmcH>=0 and pmcH>=pmcmaH then color.cyan else if pmcH>=0 and pmcH<=pmcmaH then color.blue else if pmcH<=0 and pmcH<=pmcmaH then color.red else color.magenta);
plot B9_Dot = if IsNaN(Close) then Double.NaN else 9;
B9_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B9_Dot.SetLineWeight(DotSize);
B9_Dot.AssignValueColor(if pmcI>=0 and pmcI>=pmcmaI then color.cyan else if pmcI>=0 and pmcI<=pmcmaI then color.blue else if pmcI<=0 and pmcI<=pmcmaI then color.red else color.magenta);
plot B10_Dot = if IsNaN(Close) then Double.NaN else 10;
B10_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B10_Dot.SetLineWeight(DotSize);
B10_Dot.AssignValueColor(if pmcJ>=0 and pmcJ>=pmcmaJ then color.cyan else if pmcJ>=0 and pmcJ<=pmcmaJ then color.blue else if pmcJ<=0 and pmcJ<=pmcmaJ then color.red else color.magenta);
plot B11_Dot = if IsNaN(Close) then Double.NaN else 11;
B11_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B11_Dot.SetLineWeight(DotSize);
B11_Dot.AssignValueColor(if pmcK>=0 and pmcK>=pmcmaK then color.cyan else if pmcK>=0 and pmcK<=pmcmaK then color.blue else if pmcK<=0 and pmcK<=pmcmaK then color.red else color.magenta);
plot B12_Dot = if IsNaN(Close) then Double.NaN else 12;
B12_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B12_Dot.SetLineWeight(DotSize);
B12_Dot.AssignValueColor(if pmcL>=0 and pmcL>=pmcmaL then color.cyan else if pmcL>=0 and pmcL<=pmcmaL then color.blue else if pmcL<=0 and pmcL<=pmcmaL Then color.red else color.magenta);``````

Last edited by a moderator:
If you change the lengths , it shows the change from bullishness to bearishness, but it still is not as clear as other indicators

Market Catcher is the lower indicator

Code:
``````input CorrelationWithSecurity = "SPY";
input alternateTimeFrame = no;
input agg = AggregationPeriod.HOUR;
def AP = GetAggregationPeriod();
def timeframe = if !alternateTimeFrame then AP else agg;
def close2 = close(CorrelationWithSecurity,period = timeframe);
declare lower;
input Period1 = 3;
input Period2 = 5;
input Period3 = 8;
input Period4 = 10;
input Period5 = 12;
input Period6 = 15;
input Period7 = 30;
input Period8 = 35;
input Period9 = 40;
input Period10 = 45;
input Period11 = 50;
input Period12 = 60;
input Dotsize = 3;
input Paintbars =0;

def pctchgA = 100 * (close(period = timeframe) / close(period = timeframe)[period1] - 1);
def pctchgspyA = 100 * (close2 / close2[period1] - 1);
def pmcA = pctchgA - pctchgspyA;
def pmcmaA = expaverage(pmcA, 3);
def pctchgB = 100 * (close(period = timeframe) / close(period = timeframe)[period2] - 1);
def pctchgspyB = 100 * (close2 / close2[period2] - 1);
def pmcB = pctchgB - pctchgspyB;
def pmcmaB = expaverage(pmcB, 3);
def pctchgC = 100 * (close(period = timeframe) / close(period = timeframe)[period3] - 1);
def pctchgspyC = 100 * (close2 / close2[period3] - 1);
def pmcC = pctchgC - pctchgspyC;
def pmcmaC = expaverage(pmcC, 3);
def pctchgD = 100 * (close(period = timeframe) / close(period = timeframe)[period4] - 1);
def pctchgspyD = 100 * (close2 / close2[period4] - 1);
def pmcD = pctchgD - pctchgspyD;
def pctchgE = 100 * (close(period = timeframe) / close(period = timeframe)[period5] - 1);
def pctchgspyE = 100 * (close2 / close2[period5] - 1);
def pmcE = pctchgE - pctchgspyE;
def pmcmaE = expaverage(pmcE, 3);
def pctchgF = 100 * (close(period = timeframe) / close(period = timeframe)[period6] - 1);
def pctchgspyF = 100 * (close2 / close2[period6] - 1);
def pmcF = pctchgF - pctchgspyF;
def pmcmaF = expaverage(pmcF, 3);
def pctchgG = 100 * (close(period = timeframe) / close(period = timeframe)[period7] - 1);
def pctchgspyG = 100 * (close2 / close2[period7] - 1);
def pmcG = pctchgG - pctchgspyG;
def pmcmaG = expaverage(pmcG, 7);
def pctchgH = 100 * (close(period = timeframe) / close(period = timeframe)[period8] - 1);
def pctchgspyH = 100 * (close2 / close2[period8] - 1);
def pmcH = pctchgH - pctchgspyH;
def pmcmaH = expaverage(pmcH, 7);
def pctchgI = 100 * (close(period = timeframe) / close(period = timeframe)[period9] - 1);
def pctchgspyI = 100 * (close2 / close2[period9] - 1);
def pmcI = pctchgI - pctchgspyI;
def pmcmaI = expaverage(pmcI, 7);

def pctchgJ = 100 * (close(period = timeframe) / close(period = timeframe)[period10] - 1);
def pctchgspyJ = 100 * (close2 / close2[period10] - 1);
def pmcJ = pctchgJ - pctchgspyJ;
def pmcmaJ = expaverage(pmcJ, 7);
def pctchgK = 100 * (close(period = timeframe) / close(period = timeframe)[period11] - 1);
def pctchgspyK = 100 * (close2 / close2[period11] - 1);
def pmcK = pctchgK - pctchgspyK;
def pmcmaK = expaverage(pmcK, 7);
def pctchgL = 100 * (close(period = timeframe) / close(period = timeframe)[period12] - 1);
def pctchgspyL = 100 * (close2 / close2[period12] - 1);
def pmcL = pctchgL - pctchgspyL;
def pmcmaL = expaverage(pmcL, 7);

plot A1_Dot = if IsNaN(Close) then Double.NaN else 1;
A1_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A1_Dot.SetLineWeight(DotSize);
A1_Dot.AssignValueColor(if pmcA>=0 and pmcA>=pmcmaA then color.cyan else if pmcA>=0 and pmcA<=pmcmaA then color.blue else if pmcA<=0 and pmcA<=pmcmaA then color.red else color.magenta);

plot A2_Dot = if IsNaN(Close) then Double.NaN else 2;
A2_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A2_Dot.SetLineWeight(DotSize);
A2_Dot.AssignValueColor(if pmcB>=0 and pmcB>=pmcmaB then color.cyan else if pmcB>=0 and pmcB<=pmcmaB then color.blue else if pmcB<=0 and pmcB<=pmcmaB then color.red else color.magenta);
plot A3_Dot = if IsNaN(Close) then Double.NaN else 3;
A3_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A3_Dot.SetLineWeight(DotSize);
A3_Dot.AssignValueColor(if pmcC>=0 and pmcC>=pmcmaC then color.cyan else if pmcC>=0 and pmcC<=pmcmaC then color.blue else if pmcC<=0 and pmcC<=pmcmaC then color.red else color.magenta);
plot A4_Dot = if IsNaN(Close) then Double.NaN else 4;
A4_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A4_Dot.SetLineWeight(DotSize);
A4_Dot.AssignValueColor(if pmcD>=0 and pmcD>=pmcmaD then color.cyan else if pmcD>=0 and pmcD<=pmcmaD then color.blue else if pmcD<=0 and pmcD<=pmcmaD then color.red else color.magenta);
plot A5_Dot = if IsNaN(Close) then Double.NaN else 5;
A5_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A5_Dot.SetLineWeight(DotSize);
A5_Dot.AssignValueColor(if pmcE>=0 and pmcE>=pmcmaE then color.cyan else if pmcE>=0 and pmcE<=pmcmaE then color.blue else if pmcE<=0 and pmcE<=pmcmaE then color.red else color.magenta);
plot A6_Dot = if IsNaN(Close) then Double.NaN else 6;
A6_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
A6_Dot.SetLineWeight(DotSize);
A6_Dot.AssignValueColor(if pmcF>=0 and pmcF>=pmcmaF then color.cyan else if pmcF>=0 and pmcF<=pmcmaF then color.blue else if pmcF<=0 and pmcF<=pmcmaF then color.red else color.magenta);
plot B7_Dot = if IsNaN(Close) then Double.NaN else 7;
B7_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B7_Dot.SetLineWeight(DotSize);
B7_Dot.AssignValueColor(if pmcG>=0 and pmcG>=pmcmaG then color.cyan else if pmcG>=0 and pmcG<=pmcmaG then color.blue else if pmcG<=0 and pmcG<=pmcmaG then color.red else color.magenta);
plot B8_Dot = if IsNaN(Close) then Double.NaN else 8;
B8_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B8_Dot.SetLineWeight(DotSize);
B8_Dot.AssignValueColor(if pmcH>=0 and pmcH>=pmcmaH then color.cyan else if pmcH>=0 and pmcH<=pmcmaH then color.blue else if pmcH<=0 and pmcH<=pmcmaH then color.red else color.magenta);
plot B9_Dot = if IsNaN(Close) then Double.NaN else 9;
B9_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B9_Dot.SetLineWeight(DotSize);
B9_Dot.AssignValueColor(if pmcI>=0 and pmcI>=pmcmaI then color.cyan else if pmcI>=0 and pmcI<=pmcmaI then color.blue else if pmcI<=0 and pmcI<=pmcmaI then color.red else color.magenta);
plot B10_Dot = if IsNaN(Close) then Double.NaN else 10;
B10_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B10_Dot.SetLineWeight(DotSize);
B10_Dot.AssignValueColor(if pmcJ>=0 and pmcJ>=pmcmaJ then color.cyan else if pmcJ>=0 and pmcJ<=pmcmaJ then color.blue else if pmcJ<=0 and pmcJ<=pmcmaJ then color.red else color.magenta);
plot B11_Dot = if IsNaN(Close) then Double.NaN else 11;
B11_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B11_Dot.SetLineWeight(DotSize);
B11_Dot.AssignValueColor(if pmcK>=0 and pmcK>=pmcmaK then color.cyan else if pmcK>=0 and pmcK<=pmcmaK then color.blue else if pmcK<=0 and pmcK<=pmcmaK then color.red else color.magenta);
plot B12_Dot = if IsNaN(Close) then Double.NaN else 12;
B12_Dot.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
B12_Dot.SetLineWeight(DotSize);
B12_Dot.AssignValueColor(if pmcL>=0 and pmcL>=pmcmaL then color.cyan else if pmcL>=0 and pmcL<=pmcmaL then color.blue else if pmcL<=0 and pmcL<=pmcmaL Then color.red else color.magenta);``````
Percentage changes aggregate over time similar to how price changes over time starting with the smallest timeframe, so trying to find statistical significance of trendingness (if you will) by overlapping a bunch of lookbacks becomes tricky. (That’s why is a RELATIVE strength indicator). I like what you did though to show various look backs. Perhaps it would be more fruitful to see if any one of those look backs fits the data in a more advantageous way.

Last edited by a moderator:

87k+ Posts
250 Online

## The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
• Exclusive indicators
• Proven strategies & setups
• Private Discord community
• Exclusive members-only content
• 1 full year of unlimited support

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?