here is a version with a "variable percentage". In this case I based it on the ATR. So basically what you get are ATR pivots expressed in percentages. I like this better because you get a similar ZigZag profile when you switch between timeframes
period = Param( "Period", 100, 5, 100, 1 );
uppercentageFactor = Param( "Upward Zig Factor", 2, 0.1, 10, 0.1 );
downpercentageFactor = Param( "Downward Zig Factor", 2, 0.1, 10, 0.1 );
priceswitch = ParamToggle( "Use Close or High and Low price", "Use Close|Use High and Low", 0 );
showUpDnSwing = 1;//ParamToggle( "Show Up/Down Swing", "Off|On", 0 );
labelsswitchswing = ParamToggle( "Show Labels", "Off|On", 1 );
showTrailline = ParamToggle( "Show Trail Line", "Off|On", 1 );
// build variable percentage array
//variablePercentage = StDev( 100 * ( H - L ) / ( ( H + L ) / 2 ), period );
variablePercentage = ATR( period ) / MA( C, period ) * 100;
uppercentage = uppercentageFactor * Ref( variablePercentage, -1 );
downpercentage = downpercentageFactor * Ref( variablePercentage, -1 );
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
pk = tr = Buy = Sell = BuyPrice = SellPrice = 0;
ZigZag = line1 = line2 = Null;
trailarrayup = Null;
trailarraydn = Null;
mode = "";
SetBarsRequired( ( lvb - fvb ) * 2 );
if( priceswitch )
{
prch = H;
prcl = L;
mode = "High/Low price";
}
else
{
prch = C;
prcl = C;
mode = "Close price";
}
// if ticksize is not set in code or information window 0.01 is used
if( TickSize == 0 )
{
TickSize = 0.01;
}
function percfluc( prc, perc )
{
retprice = round( ( prc * perc / 100 ) / TickSize ) * TickSize;
return retprice;
}
function calculatePivots()
{
// initial condition trend is up (but -1 works also)
trend = 1;
topprc = prch[0];
topidx = 0;
botprc = prcl[0];
botidx = 0;
trailarrayup[period] = topprc - percfluc( topprc, downpercentage[period] );
trailarraydn[period] = botprc + percfluc( botprc, uppercentage[period] );
for( i = period + 1; i < BarCount; i++ )
{
if( trend > 0 )
{
// trend turning down, avoid same bar as the peak
if( prcl[i] <= trailarrayup[i - 1] AND prch[i] < topprc )
{
pk[topidx] = 1;
botprc = prcl[i];
botidx = i;
trend = -1;
Sell[i] = 1;
trailarraydn[i] = botprc + percfluc( botprc, uppercentage[i] );
trailarrayup[i] = trailarrayup[i - 1];
if( priceswitch )
SellPrice[i] = Min( O[i], trailarrayup[i] );
else
SellPrice[i] = C[i];
}
else
// still in uptrend and new top reached
if( prch[i] >= topprc )
{
topprc = prch[i];
topidx = i;
trailarrayup[i] = Max( trailarrayup[i - 1], prch[i] - percfluc( topprc, downpercentage[i] ) );
}
// continuation inside uptrend
else
{
trailarrayup[i] = Max( trailarrayup[i - 1], prch[i] - percfluc( prch[i], downpercentage[i] ) );
}
}
else
if( trend < 0 )
{
// trend turning up, avoid same bar as the trough
if( prch[i] >= trailarraydn[i - 1] AND prcl[i] > botprc )
{
tr[botidx] = 1;
topprc = prch[i];
topidx = i;
trend = 1;
Buy[i] = 1;
trailarrayup[i] = topprc - percfluc( topprc, downpercentage[i] );
trailarraydn[i] = trailarraydn[i - 1];
if( priceswitch )
BuyPrice[i] = Max( O[i], trailarraydn[i] );
else
BuyPrice[i] = C[i];
}
else
// still in downtrend and new trough reached
if( prcl[i] <= botprc )
{
botprc = prcl[i];
botidx = i;
trailarraydn[i] = Min( trailarraydn[i - 1], prcl[i] + percfluc( botprc, uppercentage[i] ) );
}
// continuation inside downtrend
else
{
trailarraydn[i] = Min( trailarraydn[i - 1], prcl[i] + percfluc( prcl[i], uppercentage[i] ) );
}
}
}
}
function calculateZigZag()
{
// create ZIGZAG array line
zigup = Flip( tr, pk );
zigupLow = ValueWhen( tr, prcl, 1 );
zigupHigh = ValueWhen( pk, prch, 0 );
zigupLowIndex = ValueWhen( tr, bi, 1 );
zigupHighIndex = ValueWhen( pk, bi, 0 );
slopeup = IIf( zigup, ( zigupHigh - zigupLow ) / ( zigupHighIndex - zigupLowIndex ) , Null );
zigupLine = IIf( zigup, zigupLow + slopeup * BarsSince( tr ), Null );
zigdn = Flip( pk, tr );
zigdnLow = ValueWhen( tr, prcl, 0 );
zigdnHigh = ValueWhen( pk, prch, 1 );
zigdnLowIndex = ValueWhen( tr, bi, 0 );
zigdnHighIndex = ValueWhen( pk, bi, 1 );
slopedn = IIf( zigdn, ( zigdnLow - zigdnHigh ) / ( zigdnLowIndex - zigdnHighIndex ) , Null );
zigdnLine = IIf( zigdn, zigdnHigh + slopedn * BarsSince( pk ), Null );
ZigZag = IIf( zigup, zigupLine, IIf( zigdn, zigdnLine, Null ) );
ZigZag = IIf( bi > Max( LastValue( ValueWhen( tr, bi ) ), LastValue( ValueWhen( pk, bi ) ) ), Null, ZigZag );
}
function calculateLastSegments( )
{
line1 = line2 = Null;
lastidxpk = LastValue( ValueWhen( pk, bi ) );
lastidxtr = LastValue( ValueWhen( tr, bi ) );
lastvalpk = LastValue( ValueWhen( pk, prch ) );
lastvaltr = LastValue( ValueWhen( tr, prcl ) );
lastidxbuy = LastValue( ValueWhen( Buy, bi ) );
lastidxsell = LastValue( ValueWhen( Sell, bi ) );
valpk = LastValue( HighestSince( Ref( tr, -1 ), prch , 1 ) );
idxpk = LastValue( ValueWhen( prch == valpk, bi ) );
valtr = LastValue( LowestSince( Ref( pk, -1 ), prcl, 1 ) );
idxtr = LastValue( ValueWhen( prcl == valtr, bi ) );
if( lastidxsell > lastidxbuy AND lastidxsell > lastidxpk AND lastidxpk > lastidxtr )
{
x0 = lastidxpk;
y0 = lastvalpk;
x1 = idxtr;
y1 = valtr;
line1 = linedn = LineArray( x0, y0, x1, y1 );
tr[idxtr] = 1;
valpk = LastValue( HighestSince( Ref( tr, -1 ), prch, 1 ) );
idxpk = LastValue( ValueWhen( prch == valpk, bi ) );
}
if( lastidxsell < lastidxbuy AND lastidxbuy > lastidxtr AND lastidxpk < lastidxtr )
{
x0 = lastidxtr;
y0 = lastvaltr;
x1 = idxpk;
y1 = valpk;
line1 = lineup = LineArray( x0, y0, x1, y1 );
pk[idxpk] = 1;
valtr = LastValue( LowestSince( Ref( pk, -1 ), prcl, 1 ) );
idxtr = LastValue( ValueWhen( prcl == valtr, bi ) );
}
ZigZag = IIf( !IsEmpty( line1 ), line1, ZigZag );
}
SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "Price", colorWhite, styleCandle, Null, Null, 0, 0, 0 );
calculatePivots();
calculateZigZag();
calculateLastSegments();
Plot( zigzag, "ZigZag", colorGold, styleLine | styleNoLabel | styleNoRescale, Null, Null, 0, 1, 1 );
PlotShapes( shapeSmallCircle * tr, colorGreen, 0, L, -10 );
PlotShapes( shapeSmallCircle * pk, colorRed, 0, H, 10 );
if( showUpDnSwing )
{
sz = 8;
ft = "Arial Black";
PlotShapes( shapeSmallUpTriangle * Buy, colorAqua, 0, L, -20 );
PlotShapes( shapeSmallDownTriangle * Sell, colorGold, 0, H, -20 );
PlotShapes( shapeSmallCircle * Buy, colorAqua, 0, BuyPrice, 0 );
PlotShapes( shapeSmallCircle * Sell, colorGold, 0, SellPrice, 0 );
Short = Sell;
ShortPrice = SellPrice;
Cover = Buy;
CoverPrice = BuyPrice;
BuyPrice = ValueWhen( Buy, BuyPrice );
ShortPrice = ValueWhen( Short, ShortPrice );
CoverPrice = ValueWhen( Cover, CoverPrice );
SellPrice = ValueWhen( Sell, SellPrice );
longResult = Nz( Prec( IIf( Sell, SellPrice - ValueWhen( Buy, BuyPrice ), 0 ), 2 ) );
shortResult = Nz( Prec( IIf( Cover, ValueWhen( Short, ShortPrice ) - CoverPrice, 0 ), 2 ) );
totalResult = LastValue( Cum( longResult ) + Cum( shortResult ) );
clr = colorDefault;
GfxSetZOrder( 0 );
GfxSetCoordsMode( 1 );
shiftLabels = 10;//Param( "Shift Labels", 10, -20, 100, 1 );
upColor = colorAqua;
dnColor = colorGold;
if( labelsswitchSwing )
{
for( i = fvb; i <= lvb; i++ )
{
if( Buy[i] && Cover[i] )
{
str = "Buy: " + BuyPrice[i] + " (" + shortResult[i] + ")";
PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -35 - shiftLabels );
//str = "Cover: " + CoverPrice[i] + " (" + shortResult[i] + ")";
//PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -50 - shiftLabels );
}
if( !Buy[i] && Cover[i] )
{
str = "Cover: " + CoverPrice[i] + " (" + shortResult[i] + ")";
PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -35 - shiftLabels );
}
if( Buy[i] && !Cover[i] )
{
str = "Buy: " + BuyPrice[i];
PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -35 - shiftLabels );
}
if( Short[i] && Sell[i] )
{
str = "Short: " + ShortPrice[i] + " (" + longResult[i] + ")";
PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 25 + shiftLabels );
//str = "Sell: " + SellPrice[i] + " (" + longResult[i] + ")";
//PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 40 + shiftLabels );
}
if( !Short[i] && Sell[i] )
{
str = "Sell: " + SellPrice[i] + " (" + longResult[i] + ")";
PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 25 + shiftLabels );
}
if( Short[i] && !Sell[i] )
{
str = "Short: " + ShortPrice[i];
PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 25 + shiftLabels );
}
}
}
if( showTrailline )
{
Plot( trailarrayup, "trail up", colorLightBlue, styleDots | styleStaircase | styleNoRescale | styleNoLabel, Null, Null, 0, 1, 1 );
if( !IsEmpty( trailarrayup[BarCount - 1] ) )
{
PlotTextSetFont( "" + trailarrayup[BarCount - 1 ], ft, sz, BarCount + 1, trailarrayup[BarCount - 1], colorLightBlue, clr, 0 );
}
Plot( trailarraydn, "trail dn", colorOrange, styleDots | styleStaircase | styleNoRescale | styleNoLabel, Null, Null, 0, 1, 1 );
if( !IsEmpty( trailarraydn[BarCount - 1] ) )
{
PlotTextSetFont( "" + trailarraydn[BarCount - 1], ft, sz, BarCount + 1, trailarraydn[BarCount - 1], colorOrange, clr, 0 );
}
}
}
Title =
"Price: " + C
+ EncodeColor( colorGold ) + " | ZigZag: " + ZigZag
+ EncodeColor( colorBrightGreen ) + " | Up Percentage (%): " + Prec( uppercentage, 2 )
+ EncodeColor( colorRed ) + " | Down Percentage (%): " + Prec( downpercentage, 2 )
+ EncodeColor( colorLightBlue ) + " | Trail Array Up: " + trailarrayup
+ EncodeColor( colorOrange ) + " | Trail Array Down: " + trailarraydn;