PPO_MMA Indicator for ThinkorSwim

tomsk

Well-known member
VIP
@HighBredCloud @netarchitech if you are interested I have revamped your PPO code so that the moving average of interest are now properly calculated within the code. Please note that I have removed the Ehler's Forward Reverse EMA as that appears to be very EMA specific. Hope this helps you

Code:
# PPO Multiple Moving Averages
# Based on earlier PPO FREMAS code from netarchitect
# Revamped by tomsk
# 11.11.2019

declare lower;

input fastPeriod   = 12;
input slowPeriod   = 26;
input signalPeriod = 9;
input price        = close;
input showBreakoutSignals = yes;
input ma_length = 21; #Length(180-200 for floating S/R , 55 for swing entry
input movingAverageType = {"Simple MA", default "Exponential MA", "Wilders Smoothing", "Weighted MA", "Hull MA", "Adaptive MA", "Triangular MA", "Variable MA", "Dema MA", "Tema MA", "EHMA", "THMA"};

def fast;
def slow;

switch (movingAverageType) {
case "Simple MA":
    fast = Average(price, fastPeriod);
    slow = Average(price, slowPeriod);

case "Exponential MA":
    fast = ExpAverage(price, fastPeriod);
    slow = ExpAverage(price, slowPeriod);

case "Wilders Smoothing":
    fast = WildersAverage(price, fastPeriod);
    slow = WildersAverage(price, slowPeriod);

case "Weighted MA":
    fast = wma(price, fastPeriod);
    slow = wma(price, slowPeriod);

case "Hull MA":
    fast = HullMovingAvg(price, fastPeriod);
    slow = HullMovingAvg(price, slowPeriod);

case "Adaptive MA":
    fast = MovAvgAdaptive(price, fastPeriod);
    slow = MovAvgAdaptive(price, slowPeriod);

case "Triangular MA":
    fast = MovAvgTriangular(price, fastPeriod);
    slow = MovAvgTriangular(price, slowPeriod);

case "Variable MA":
    fast = variableMA(price, fastPeriod);
    slow = variableMA(price, slowPeriod);

case "Dema MA":
    fast = DEMA(price, fastPeriod);
    slow = DEMA(price, slowPeriod);

case "Tema MA":
    fast = TEMA(price, fastPeriod);
    slow = TEMA(price, slowPeriod);

case EHMA:
    fast = ExpAverage(2 * ExpAverage(price, fastPeriod / 2) - ExpAverage(price, fastPeriod), Round(Sqrt(fastPeriod)));
    slow = ExpAverage(2 * ExpAverage(price, slowPeriod / 2) - ExpAverage(price, slowPeriod), Round(Sqrt(slowPeriod)));

case THMA:
    fast = WMA(WMA(price, (fastPeriod / 2) / 3) * 3 - WMA(price, (fastPeriod / 2) / 2) - WMA(price, (fastPeriod / 2)), (fastPeriod / 2));
    slow = WMA(WMA(price, (slowPeriod / 2) / 3) * 3 - WMA(price, (slowPeriod / 2) / 2) - WMA(price, (slowPeriod / 2)), (slowPeriod / 2));
}

def periodOK  = fastPeriod < slowPeriod;
AddLabel(!periodOK, "ERROR: fastPeriod MUST be less than slowPeriod");
def _ppo      = if periodOK then ((fast - slow) / slow) * 100 else 0;
def _signal;

switch (movingAverageType) {
case "Simple MA":
    _signal = Average(_ppo, signalPeriod);

case "Exponential MA":
    _signal = ExpAverage(_ppo, signalPeriod);

case "Wilders Smoothing":
    _signal = WildersAverage(_ppo, signalPeriod);

case "Weighted MA":
    _signal = wma(_ppo, signalPeriod);

case "Hull MA":
    _signal = HullMovingAvg(_ppo, signalPeriod);

case "Adaptive MA":
    _signal = MovAvgAdaptive(_ppo, signalPeriod);

case "Triangular MA":
    _signal = MovAvgTriangular(_ppo, signalPeriod);

case "Variable MA":
    _signal = variableMA(_ppo, signalPeriod);

case "Dema MA":
    _signal = DEMA(_ppo, signalPeriod);

case "Tema MA":
    _signal = TEMA(_ppo, signalPeriod);

case EHMA:
    _signal = ExpAverage(2 * ExpAverage(_ppo, signalPeriod / 2) - ExpAverage(_ppo, signalPeriod), Round(Sqrt(signalPeriod)));

case THMA:
    _signal = WMA(WMA(_ppo, (signalPeriod / 2) / 3) * 3 - WMA(_ppo, (signalPeriod / 2) / 2) - WMA(_ppo, (signalPeriod / 2)), (signalPeriod / 2));
}

plot Ppo      = _ppo;
Ppo.SetDefaultColor(GetColor(1));
Ppo.SetLineWeight(2);

plot PpoEma   = _signal;
PpoEma.SetDefaultColor(GetColor(8));
PpoEma.SetLineWeight(2);

plot zeroLine = 0;
zeroLine.HideBubble();
zeroLine.SetDefaultColor(GetColor(4));

plot PPOdiff  = 2 * (_ppo - _signal);
PPOdiff.SetDefaultColor(GetColor(5));
PPOdiff.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
PPOdiff.DefineColor("Positive and Up", Color.GREEN);
PPOdiff.DefineColor("Positive and Down", Color.DARK_GREEN);
PPOdiff.DefineColor("Negative and Down", Color.RED);
PPOdiff.DefineColor("Negative and Up", Color.DARK_RED);
PPOdiff.AssignValueColor(if PPOdiff >= 0
                         then if PPOdiff > PPOdiff[1]
                              then PPOdiff.Color("Positive and Up")
                              else PPOdiff.Color("Positive and Down")
                         else if PPOdiff < PPOdiff[1]
                              then PPOdiff.Color("Negative and Down")
                              else PPOdiff.Color("Negative and Up"));
PPOdiff.SetLineWeight(3);

plot UpSignal = if PPOdiff crosses above ZeroLine then ZeroLine else Double.NaN;
plot DownSignal = if PPOdiff crosses below ZeroLine then ZeroLine else Double.NaN;

UpSignal.SetHiding(!showBreakoutSignals);
DownSignal.SetHiding(!showBreakoutSignals);

UpSignal.SetDefaultColor(Color.DOWNTICK);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
UpSignal.SetLineWeight(2);
DownSignal.SetDefaultColor(Color.UPTICK);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
DownSignal.SetLineWeight(2);
# END CODE
 
Last edited:
@HighBredCloud @netarchitech Here's version 2 of my PPO Multiple Moving Averages study.
This is a revision from an earlier posted version that had two separate switch structures.
I moved some of the definitions around, and collapsed all of this into a single switch statement
Makes future code maintenance easier. Hope this helps

Code:
# PPO Multiple Moving Averages
# Based on earlier PPO FREMAS code from netarchitect
# Revamped by tomsk
# 11.13.2019

# V11.11.2019 - tomsk - revamped netarchitect's base PPO code
# V11.13.2019 - tomsk - enhanced code structure, collapsed computation into a single switch

declare lower;

input fastPeriod = 12;
input slowPeriod = 26;
input signalPeriod = 9;
input price = close;
input showBreakoutSignals = yes;
input ma_length = 21; #Length(180-200 for floating S/R , 55 for swing entry
input movingAverageType = {"Simple MA", default "Exponential MA", "Wilders Smoothing", "Weighted MA",
    "Hull MA", "Adaptive MA", "Triangular MA", "Variable MA", "Dema MA", "Tema MA", "EHMA", "THMA"};

def periodOK  = fastPeriod < slowPeriod;
AddLabel(!periodOK, "ERROR: fastPeriod MUST be less than slowPeriod");

def fast;
def slow;
def _ppo;
def _signal;

switch (movingAverageType) {
case "Simple MA":
    fast = Average(price, fastPeriod);
    slow = Average(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = Average(_ppo, signalPeriod);

case "Exponential MA":
    fast = ExpAverage(price, fastPeriod);
    slow = ExpAverage(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = ExpAverage(_ppo, signalPeriod);

case "Wilders Smoothing":
    fast = WildersAverage(price, fastPeriod);
    slow = WildersAverage(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = WildersAverage(_ppo, signalPeriod);

case "Weighted MA":
    fast = wma(price, fastPeriod);
    slow = wma(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = wma(_ppo, signalPeriod);

case "Hull MA":
    fast = HullMovingAvg(price, fastPeriod);
    slow = HullMovingAvg(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = HullMovingAvg(_ppo, signalPeriod);

case "Adaptive MA":
    fast = MovAvgAdaptive(price, fastPeriod);
    slow = MovAvgAdaptive(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = MovAvgAdaptive(_ppo, signalPeriod);

case "Triangular MA":
    fast = MovAvgTriangular(price, fastPeriod);
    slow = MovAvgTriangular(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = MovAvgTriangular(_ppo, signalPeriod);

case "Variable MA":
    fast = variableMA(price, fastPeriod);
    slow = variableMA(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = variableMA(_ppo, signalPeriod);

case "Dema MA":
    fast = DEMA(price, fastPeriod);
    slow = DEMA(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = DEMA(_ppo, signalPeriod);

case "Tema MA":
    fast = TEMA(price, fastPeriod);
    slow = TEMA(price, slowPeriod);
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = TEMA(_ppo, signalPeriod);

case EHMA:
    fast = ExpAverage(2 * ExpAverage(price, fastPeriod / 2) - ExpAverage(price, fastPeriod), Round(Sqrt(fastPeriod)));
    slow = ExpAverage(2 * ExpAverage(price, slowPeriod / 2) - ExpAverage(price, slowPeriod), Round(Sqrt(slowPeriod)));
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = ExpAverage(2 * ExpAverage(_ppo, signalPeriod / 2) - ExpAverage(_ppo, signalPeriod), Round(Sqrt(signalPeriod)));

case THMA:
    fast = WMA(WMA(price, (fastPeriod / 2) / 3) * 3 - WMA(price, (fastPeriod / 2) / 2) - WMA(price, (fastPeriod / 2)), (fastPeriod / 2));
    slow = WMA(WMA(price, (slowPeriod / 2) / 3) * 3 - WMA(price, (slowPeriod / 2) / 2) - WMA(price, (slowPeriod / 2)), (slowPeriod / 2));
    _ppo = if periodOK then ((fast - slow) / slow) * 100 else 0;
    _signal = WMA(WMA(_ppo, (signalPeriod / 2) / 3) * 3 - WMA(_ppo, (signalPeriod / 2) / 2) - WMA(_ppo, (signalPeriod / 2)), (signalPeriod / 2));
}

plot Ppo = _ppo;
Ppo.SetDefaultColor(GetColor(1));
Ppo.SetLineWeight(2);

plot PpoEma = _signal;
PpoEma.SetDefaultColor(GetColor(8));
PpoEma.SetLineWeight(2);

plot zeroLine = 0;
zeroLine.HideBubble();
zeroLine.SetDefaultColor(GetColor(4));

plot PPOdiff = 2 * (_ppo - _signal);
PPOdiff.SetDefaultColor(GetColor(5));
PPOdiff.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
PPOdiff.DefineColor("Positive and Up", Color.GREEN);
PPOdiff.DefineColor("Positive and Down", Color.DARK_GREEN);
PPOdiff.DefineColor("Negative and Down", Color.RED);
PPOdiff.DefineColor("Negative and Up", Color.DARK_RED);
PPOdiff.AssignValueColor(if PPOdiff >= 0
                         then if PPOdiff > PPOdiff[1]
                              then PPOdiff.Color("Positive and Up")
                              else PPOdiff.Color("Positive and Down")
                         else if PPOdiff < PPOdiff[1]
                              then PPOdiff.Color("Negative and Down")
                              else PPOdiff.Color("Negative and Up"));
PPOdiff.SetLineWeight(3);

plot UpSignal = if PPOdiff crosses above ZeroLine then ZeroLine else Double.NaN;
plot DownSignal = if PPOdiff crosses below ZeroLine then ZeroLine else Double.NaN;

UpSignal.SetHiding(!showBreakoutSignals);
DownSignal.SetHiding(!showBreakoutSignals);

UpSignal.SetDefaultColor(Color.DOWNTICK);
UpSignal.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
UpSignal.SetLineWeight(2);
DownSignal.SetDefaultColor(Color.UPTICK);
DownSignal.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
DownSignal.SetLineWeight(2);
# END CODE
 
@tomsk OK...I just looked at it now...Since I am not a coder...In layman's terms from what I am seeing...It looks and acts the same as version 1 you posted above except you cleaned up the code so its easier to work with for further uses? Am I getting that right?
 
@HighBredCloud Yes indeed - I streamlined the code, makes it much easier to follow. Functionality same as before, less code statements to deal with so less chance of errors down the road. Regarding the project, let me read through the thread, not real sure what is being requested here. It might help if you could summarize the gist of what you're planning to achieve
 
@netarchitech OK I read through the thread of your latest project. My interpretation is that you'd like the dots to reflect the four states:

Positive and Up
Positive and Down
Negative and Down
Negative and Up

If so you'd need to represent this with 4 different colors and if you look at this visually, some of the colors may not be easily distinguishable.
Hence my input is that you may want it to remain at 2 colors so that at one glance you'll be able to determine the general trend
Not real sure if a 4 color granularity helps with interpretation though. Just my $0.02

My apologies if I have misunderstood your intent
 
@tomsk Thanks for taking a look and swiftly responding...

Yes...preferably 4 states...as we are dealing with 2 histograms (MACD and PPO)...With that said, you make a good point about the color issue...

Would you consider working with us on this project?

My apologies if I have misunderstood your intent
No problem, @tomsk speak freely...you are amongst compatriots :)
 

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