PMAX Indicator in Amibroker

Has anybody implemented this trading view indicator (PMAX Profit Maximiser) in Amibroker?

pmax1

PMax is a brand new indicator developed by KivancOzbilgic in earlier 2020.

It's a combination of two trailing stop loss indicators;
One is Anıl Özekşi's MOST (Moving Stop Loss) Indicator

(MOST by Anıl ÖZEKŞİ — KivancOzbilgic tarafından gösterge — TradingView)

and the other one is well known ATR based SuperTrend.

(SuperTrend — KivancOzbilgic tarafından gösterge — TradingView)

Both MOST and SuperTrend Indicators are very good at trend following systems but conversely their performance is not in sideways market conditions like most of the other indicators.

Profit Maximizer - PMax tries to solve this problem. PMax combines the powerful sides of MOST (Moving Average Trend Changer) and SuperTrend (ATR price detection) in one indicator.

Backtest and optimization results of PMax are far better when compared to its ancestors MOST and SuperTrend. It reduces the number of false signals in sideways and give more reliable trade signals.

What have you done so far?
What's the issue?

I just have supertrend plotted. I could not integrate the moving average and crossover signals. Could you please share your AFL, it will be helpful for me to learn.

1 Like

Hello

Here my first attempt to translate the pinescript of this indicator to AFL

But it doesn't look like as expected :frowning:

I don't know where is my mistake(s), may be someone could help me

Thanks in advance

Best regards

src = (High + Low)/2;
Periods = Param("ATR Length",10,1,100,1);
Multiplier = Param("ATR Multiplier",3,0.1,100,0.1);
mav = ParamList("Moving Average Type","SMA|EMA|WMA|TMA|VAR|WWMA|ZLEMA|TSF",1);
length = Param("Moving Average Length",10,1,100,1);
changeATR = ParamToggle("Change ATR Calculation Method ?","No|Yes",1);
Normalize = ParamToggle("Normalize ATR ?","No|Yes",0);

atr1 = IIF(changeATR,ATR(Periods),MA(ATR(1),Periods));
MAvg=0;
switch (mav)
{
case "SMA" :   // Simple Moving Average
    MAvg = MA(src,length);
break;
case "WMA" :   // Weighted Moving Average
    MAvg = WMA(src,length);
break;
case "TMA" :  // Triangular Moving Average
    MAvg = MA(MA(src,Ceil(length/2)),Floor(length/2)+1);
break;
case "VAR" :   // Variable Index Dynamic Moving Average
    valpha = 2/(length+1);
    vud1 = IIF(src>Ref(src,-1),src-Ref(src,-1),0);
    vdd1 = IIF(src<Ref(src,-1),Ref(src,-1)-src,0);
    vUD = Sum(vud1,9);
    vDD = Sum(vdd1,9);
    vCMO = Nz((vUD-vDD)/(vUD+vDD));
    VAR = 0;
    VAR = Nz(valpha*Abs(vCMO)*src)+(1-valpha*Abs(vCMO))*Nz(Ref(VAR,-1));
    MAvg = VAR;
break;
case "WWMA" :   //  Welles Wilder's Moving Average
    wwalpha = 1/length;
    WWMA = 0;
    WWMA = wwalpha*src+(1-wwalpha)*Nz(Ref(WWMA,-1));
    MAvg = WWMA;
break;
case "ZLEMA" :  // Zero Lag Exponential Moving Average
    zxLag = IIF(length/2==Round(length/2),length/2,(length-1)/2);
    zxEMAData = (src+(src-src[zxLag]));
    MAvg = EMA(zxEMAData,length);
break;
case "TSF" :    // True Strength Force
    lrc = LinearReg(src,length);
    lrc1 = Ref(lrc,-1);
    MAvg = 2*lrc-lrc1;
break;
default : MAvg = EMA(src,length);  // Exponential Moving Average
break;
}
longStop = IIF(Normalize,MAvg-Multiplier*atr1/Close,MAvg-Multiplier*atr1);
longStopPrev = Ref(longStop,-1);
longStop = IIF(MAvg>longStopPrev,Max(longStop,longStopPrev),longStop);
shortStop = IIF(Normalize,MAvg+Multiplier*atr1/Close,MAvg+Multiplier*atr1);
shortStopPrev = Ref(shortStop,-1);
shortStop = IIF(MAvg<shortStopPrev,Min(shortStop,shortStopPrev),shortStop);
dir = 1;
dir = IIF(dir==-1 and MAvg>shortStopPrev,1,IIF(dir==1 and MAvg<longStopPrev,-1,dir));
PMax = IIF(dir==1,longStop,shortStop);
Plot(PMax,"PMax",colorGreen,styleLine|styleThick);

Not sure, but looks like ":=" pinescript operand indicates recursion and maybe you need to use a loop to do the calculation

longStop = Normalize ? MAvg - Multiplier*atr/close : MAvg - Multiplier*atr
longStopPrev = nz(longStop[1], longStop)
longStop := MAvg > longStopPrev ? max(longStop, longStopPrev) : longStop
shortStop = Normalize ? MAvg + Multiplier*atr/close : MAvg + Multiplier*atr
shortStopPrev = nz(shortStop[1], shortStop)
shortStop := MAvg < shortStopPrev ? min(shortStop, shortStopPrev) : shortStop

Hello @awilson

According the manual, = is used to declare and initialize variables, := is used to assign values to variables after initialization and not for recursion

Expressions, declarations and statements — Pine Script User Manual 4 documentation (tradingview.com)

You may use looping here.


This is not correct.

It is AMA/AMA2.


Not correct. It is AMA/AMA2.


TSF() function exists in AmiBroker already!
https://www.amibroker.com/guide/afl/tsf.html


:= reassignement operator

The := is used to reassign a value to an existing variable. It says use this variable that was declared earlier in my script, and give it a new value.

2 Likes

Ok, is not recursion, but it is a reassign that considers the change of a previous value, and as @fxshrat already pointed out, you will need to do a loop.

Corrections done, everything seems working as expected, thanks a lot @fxshrat for your precious help
Don't hesitate if you see others mistakes
Regards

// https://in.tradingview.com/script/sU9molfV/
src = (High + Low)/2;
Periods = Param("ATR Length",10,1,100,1);
Multiplier = Param("ATR Multiplier",3,0.1,100,0.1);
mav = ParamList("Moving Average Type","SMA|EMA|WMA|TMA|VAR|WWMA|ZLEMA|TSF",1);
length = Param("Moving Average Length",10,1,100,1);
changeATR = ParamToggle("Change ATR Calculation Method ?","No|Yes",1);
Normalize = ParamToggle("Normalize ATR ?","No|Yes",0);

atr1 = IIF(changeATR,ATR(Periods),MA(ATR(1),Periods));
MAvg=0;
switch (mav)
{
case "SMA" :   // Simple Moving Average
    MAvg = MA(src,length);
break;
case "WMA" :   // Weighted Moving Average
    MAvg = WMA(src,length);
break;
case "TMA" :  // Triangular Moving Average
    MAvg = MA(MA(src,Ceil(length/2)),Floor(length/2)+1);
break;
case "VAR" :   // Variable Index Dynamic Moving Average
    valpha = 2/(length+1);
    vud1 = IIF(src>Ref(src,-1),src-Ref(src,-1),0);
    vdd1 = IIF(src<Ref(src,-1),Ref(src,-1)-src,0);
    vUD = Sum(vud1,9);
    vDD = Sum(vdd1,9);
    vCMO = Nz((vUD-vDD)/(vUD+vDD));
    MAvg = AMA(src,valpha*Abs(vCMO));
break;
case "WWMA" :   //  Welles Wilder's Moving Average
    MAvg = AMA(src,1/length);
break;
case "ZLEMA" :  // Zero Lag Exponential Moving Average
    zxLag = IIF(length/2==Round(length/2),length/2,(length-1)/2);
    zxEMAData = (src+(src-Ref(src,-zxLag)));
    MAvg = EMA(zxEMAData,length);
break;
case "TSF" :    // True Strength Force
    MAvg = TSF(src,length);
break;
default : MAvg = EMA(src,length);  // Exponential Moving Average
break;
}
longStop[0]=0;
shortStop[0]=0;
dir=1;
PMax[0]=0;
longStop = IIF(Normalize,MAvg-Multiplier*atr1/Close,MAvg-Multiplier*atr1);
shortStop = IIF(Normalize,MAvg+Multiplier*atr1/Close,MAvg+Multiplier*atr1);
for (i=1; i<BarCount; i++)
{
    longStopPrev[i]=longStop[i-1];
    if (MAvg[i]>longStopPrev[i]) longStop[i]=Max(longStop[i],longStopPrev[i]);
    shortStopPrev[i]=shortStop[i-1];
    if (MAvg[i]<shortStopPrev[i]) shortStop[i]=Min(shortStop[i],shortStopPrev[i]);
    dir[i]=dir[i-1];
    if (dir[i]==-1 and MAvg[i]>shortStopPrev[i]) dir[i]=1;
    else if (dir[i]==1 and MAvg[i]<longStopPrev[i]) dir[i]=-1;
    if (dir[i]==1) PMax[i]=longStop[i];
    else PMax[i]=shortStop[i];
}
Plot(PMax,"PMax",colorGreen,styleLine|styleThick);

1 Like

This may help you get started.

image

Title = "PMax";

Src = ( H + L ) / 2;
AtrPeriods = 9;
AtrMultiplier = 3;
MovAvgPeriod = 9;

BandWidth = ATR( AtrPeriods ) * AtrMultiplier;
UpperBand = Nz( Src + BandWidth );
LowerBand = Nz( Src - BandWidth );
MovAvg = EMA( src, MovAvgPeriod );

PMax = Null;
UpTrend = 0;

for( i = Max( AtrPeriods, MovAvgPeriod ); i < BarCount; i++ )
{
    if( MovAvg[i] > UpperBand[i - 1] ) UpTrend = 1;
    else
        if( MovAvg[i] < LowerBand[i - 1] ) UpTrend = 0;

    if( UpTrend )
    {
        PMax[i] = LowerBand[i] = Max( LowerBand[i], LowerBand[i - 1] );
    }
    else
        if( NOT UpTrend )
        {
            PMax[i]  = UpperBand[i] = Min( UpperBand[i], UpperBand[i - 1] );
        }
        else
        {
            PMax[i] = PMax[i - 1];
        }
}

Plot( C, "", colorDefault, styleCandle );
Plot( PMax, "", colorRed, styleLine, Null, Null, 0, 0, 2 );
Plot( MovAvG, "", colorBlue, styleLine, Null, Null, 0, 0, 2 );

PlotShapes( shapeUpArrow * Cross( MovAvg, Pmax ), colorGreen, 0, PMax, -20 );
PlotShapes( shapeDownArrow * Cross( Pmax, MovAvg ), colorRed, 0, PMax, -20 );
1 Like

With the Buy and Sell signals

buySignalk = Cross(MAvg, PMax);
sellSignallk = Cross(PMax, MAvg);
if (showsignalsk)
{
   shape = buySignalk * shapeUpArrow + sellSignallk * shapeDownArrow;
   PlotShapes( shape, IIf( buySignalk, colorGreen, colorRed ), 0, IIf( buySignalk, PMax*0.995, PMax*1.005 ) );
}
buySignalc = Cross(src, PMax);
sellSignallc = Cross(PMax, src);
if (showsignalsc)
{
   shape = buySignalc * shapeUpArrow + sellSignallc * shapeDownArrow;
   PlotShapes( shape, IIf( buySignalc, colorGreen, colorRed ), 0, IIf( buySignalc, PMax*0.995, PMax*1.005 ) );
}
2 Likes

Here is version of picture of post #2

// @version=4
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © KivancOzbilgic
// developer: @KivancOzbilgic
// author: @KivancOzbilgic
// https://in.tradingview.com/script/sU9molfV/
// AFL conversion by fxshrat@gmail.com
// https://forum.amibroker.com/t/pmax-indicator-in-amibroker/30028/12
function getMA(src, length) {
    global mav, VAR, WWMA, ZLEMA;
    result = 0;
    if (mav == "SMA") result = MA(src, length);
    if (mav == "EMA") result = EMA(src, length);
    if (mav == "WMA") result = WMA(src, length);
    if (mav == "TMA") result = MA(MA(src, ceil(length / 2)), floor(length / 2) + 1);
    if (mav == "VAR") result = VAR;
    if (mav == "WWMA") result = WWMA;
    if (mav == "ZLEMA") result = ZLEMA;
    if (mav == "TSF") result = TSF(src,length);
	return result;
}

src = (H+L)/2;
Periods = Param("ATR Length", 10);
Multiplier = Param("ATR Multiplier", 3, 1, 5, 0.1);
mav = ParamList("MovingAverageType","EMA,SMA,EMA,WMA,TMA,VAR,WWMA,ZLEMA", 4);
length = Param("Moving Average Length", 10, 1, 100, 1);
changeATR = ParamToggle("Change ATR Calculation Method ?", "ON|OFF", true);
Normalize = ParamToggle("Normalize ATR ?", "ON|OFF",false);
showsupport = ParamToggle("Show Moving Average?", "ON|OFF",true);
showsignalsk = ParamToggle("Show Crossing Signals?", "ON|OFF",true);
showsignalsc = ParamToggle("Show Price/Pmax Crossing Signals?", "ON|OFF",false);
highlighting = ParamToggle("Highlighter On/Off ?", "ON|OFF",true);

tr = ATR(1);
my_atr = IIf(changeATR, ATR(Periods), MA(tr, Periods));

vud1 = Max(0,src-Ref(src,-1));
vdd1 = Max(0,Ref(src,-1)-src);
vUD = Sum(vud1,9);
vDD = Sum(vdd1,9);
vCMO = Nz((vUD-vDD)/(vUD+vDD));

valpha = 2/(length+1);
VAR = AMA(src,valpha*Abs(vCMO));

wwalpha = 1/ length;
WWMA = AMA(src, wwalpha);

zxLag = IIf(length/2==round(length/2), length/2, (length - 1) / 2);
zxEMAData = 2*src - Ref(src,-zxLag);
ZLEMA = EMA(zxEMAData, length);

MAvg = getMA( src, length );

div = IIf(Normalize, C, 1);
longStop = MAvg - Multiplier*my_atr/div;
shortStop = MAvg + Multiplier*my_atr/div;

dir = dir_arr = 1;
longStop_arr = longStop;
shortStop_arr = shortStop;
for( i = 1; i < BarCount; i++ ) {
	longStopPrev = longStop_arr[i-1];
	longStop_arr[i] = IIf(MAvg[i] > longStopPrev, Max(longStop_arr[i], longStopPrev), longStop_arr[i]);	
	
	shortStopPrev = shortStop_arr[i-1];
	shortStop_arr[i] = IIf(MAvg[i] < shortStopPrev, Min(shortStop_arr[i], shortStopPrev), shortStop_arr[i]);
	
	dir = IIf(dir == -1 AND MAvg[i] > shortStopPrev, 1, IIf(dir == 1 and MAvg[i] < longStopPrev, -1, dir)); 
	dir_arr[i] = dir;	
}

PMax = IIf(dir_arr == 1, longStop_arr, shortStop_arr);

Plot( C, "Price", colorDefault, styleCandle );
Plot(IIf(showsupport, MAvg, Null), "Moving Avg Line", ColorRGB(5,133,225), styleLine, Null, Null, 0, 0, 2);
Plot(PMax, "PMax", colorred, styleLine, Null, Null, 0, 0, 2);

if ( showsignalsk ) {
	buySignalk = Cross(MAvg, PMax);
	sellSignallk = Cross(PMax, MAvg);
	PlotShapes(buySignalk*shapeUpArrow, colorGreen, 0, PMax*0.995 );	
	PlotShapes(sellSignallk *shapedownArrow, colorRed, 0, PMax*1.005 );
}
if ( showsignalsc ) {
	buySignalc = Cross(src, PMax);
	sellSignallc = Cross(PMax, src);
	PlotShapes(buySignalc*shapeUpArrow, colorBlue, 0, PMax*0.995);	
	PlotShapes(sellSignallc *shapedownArrow, colorBlue, 0, PMax*1.005);
}
11 Likes

Thank you so much for your help!!!! @fxshrat @didrip @bysoaa

1 Like

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.