Log Scaling Based Point & Figure AFL Charting

Hi @empottasch

  1. I am using your most updated code, not sure why there are multiple trendlines for all values in Param "ZigZag change amount".

I observe similar issues in Fractal Approach as well.

  1. Even for a Percent Scaling should " zz = log( zz ); " not be without log()? As without log() the Trendlines are much cleaner (tested in earlier version of your code and even @awilson has similar observation)

I add the Box ZigZag to your last code , what do you think ?

control it by changing

Boxzz = Param( "ZigZag Box Amount for Trendlines", 15, 0, 100, 1 );

_SECTION_BEGIN( "Point & Figure" );
RequestMouseMoveRefresh();
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

scaling = ParamList( "Scaling Method", "Traditional|Percentage", 1 );
hclmode = ParamList( "Price Mode", "HL|C", 0 );
displaymode = ParamList( "Display Mode", "Standard Chart|GFX|GFX 1 Box Reversal", 0 );
ft = ParamList( "Font Type", "Tahoma Bold|Arial Black|Verdana Bold|Courier New Bold|Comic Sans MS Bold|Arial Bold|Candara Bold|Calibri Bold|Constantia Bold|Georgia Bold|Gadugi Bold|Segoe UI Bold", 0 );
sz = Param( "Font Size", 11, 6, 50, 1 );
Box = Param( "Box", 50, 1, 2000, 1 );
nRev = Param( "Reverse Number of Boxes", 3, 1, 10, 1 );
nquot = Param( "Number of Quotes Shown on Axis", 10, 5, 50 );
PlotGridLines = ParamToggle( "PlotdGrid", "No|Yes", 1 ) ;
trendlinetype = ParamList( "Trendline Type", "BoxZigZag|ZigZag|Fractal|No Trendlines", 0 );
zz = Param( "ZigZag Change Amount for Trendlines (%)", 2, 0.1, 100, 0.1 );
Boxzz = Param( "ZigZag Box Amount for Trendlines", 15, 0, 100, 1 );
rightStrength = Param( "Fractal Pivot Right side Strength (bars)", 5, 2, 50, 1 );
leftStrength = Param( "Fractal Pivot Left side Strength (bars)", 10, 2, 50, 1 );
fact = Param( "Fractal Factor", 1, 1, 20, 1 );

// color definitions
xcolor = ParamColor( "X_Color", colorBrightGreen );
ocolor = ParamColor( "O_Color", colorRed );
bcolor = ParamColor( "Background Color", colorBlack );
yaxcolor = ParamColor( "Y Axis Color", colorWhite );
titleColor = ParamColor( "Title Color", colorGold );
titleHighlightColor = ParamColor( "Title Highlight Color", colorAqua );

rndbox = 30;
Lx = LastValue( bi );

SetChartBkColor( bcolor );
GfxSetZOrder( -5 );
GfxSetCoordsMode( 1 );

BarDateTime = DateTime();
BarTurn = 0;
BarEnd = 0;

mny = Status( "axisminy" );
mxy = Status( "axismaxy" );
pxb = Status( "pxchartbottom" );
pxh = Status( "pxchartheight" );
Buy = Sell = Short = Cover = BuyPrice = SellPrice = ShortPrice = CoverPrice = 0;

if( displaymode == "GFX 1 Box Reversal" AND nRev > 1 )
{
    displaymode = "GFX";
}

// set your TickSize here or put it in the information Window
// example for NQ and ES futures ---> TickSize = 0.25;
// if ticksize is not set in code or information window use 0.01
// Ticksize = 0.25   // I commented it out because I put it in the information window
if( TickSize == 0 )
{
    TickSize = 0.01;
}

// calculate format for display purposes
fmt = "" + TickSize;
fmt = StrReplace( fmt, ".", "," );
fmt = StrExtract( fmt, 1 );
fmt = "1" + "." + StrLen( fmt );
fmt = StrToNum( fmt );

switch( hclmode )
{
case "HL":
    prch = H;
    prcl = L;
    cmode = "High / Low Price";
    break;

case "C":
    prch = C;
    prcl = C;
    cmode = "Close Price";
    break;
}

switch( scaling )
{
case "Traditional":
    Box =  Box * TickSize;
    ctype = "Tradional (Boxsize in Points, Box x TickSize)";
    tbox = "True Box Value in Points: " + EncodeColor( titleHighlightColor ) +  NumToStr( Box, fmt ) + " Points" + EncodeColor( titleColor );
    break;

case "Percentage":
    Box = Box / 100;
    ctype = "Percentage (Boxsize in Percent)";
    tbox = "True Box Value in Percent: " + EncodeColor( titleHighlightColor ) + Box + " %" + EncodeColor( titleColor );
    break;
}

function GfxConvertValueToPixelY( Value )
{
    return Value * SafeDivide( pxh, mxy - mny );
}

PFL = PFH = 0;
Box_px = j = 0;

if( scaling == "Percentage" )
{
    Box = log( 1 + Box / 100 );
    prch = log( prch );
    prcl = log( prcl );
    PFL[0] = Box * ceil( prcl[0] / Box ) + Box;
    PFH[0] = Box * floor( prch[0] / Box );
    zz = log( zz );

    // box size in pixels
    Box_px = GfxConvertValueToPixelY( Box );
}
else
{
    PFL[0] = Box * ceil( prcl[0] / Box ) + Box;
    PFH[0] = Box * floor( prch[0] / Box );

    // box size in pixels
    Box_px = GfxConvertValueToPixelY( Box );
}

direction = -1;
notifyArray = 0;

ZigDirection = -1;
CurBox = 0;
BoxTr = BoxPk = 0;

iLastPk = 0;
iLastTr = 0;
IsPk = 0; IsPk[0] = 1;
IsTr = 0; IsTr[0] = 1;
LastPk = 0;
LastTr = 1000000;

for( i = 0; i < BarCount; i++ )
{
    if( direction[j] == ( -1 ) )
    {
        if( prcl[i] <= PFL[j] - Box )
        {
            PFL[j] = Box * ceil( prcl[i] / Box );
            BarEnd[j] = BarDateTime[i];
            notifyArray[i] = 1;
        }
        else
        {
            if( prch[i] >= PFL[j] + nRev * Box )
            {
                j++;
                direction[j] = 1;
                PFH[j] = Box * floor( prch[i] / Box );
                PFL[j] = PFL[j - 1] + Box;
                BarTurn[j] = BarDateTime[i];
                BarEnd[j] = BarDateTime[i];
                notifyArray[i] = 2;
            }
        }
    }
    else
    {
        if( prch[i] >= PFH[j] + Box )
        {
            PFH[j] = Box * floor( prch[i] / Box );
            BarEnd[j] = BarDateTime[i];
            notifyArray[i] = 3;
        }
        else
        {
            if( prcl[i] <= PFH[j] - nRev * Box )
            {
                j++;
                direction[j] = -1;
                PFH[j] = PFH[j - 1] - Box;
                PFL[j] = Box * ceil( prcl[i] / Box );
                BarTurn[j] = BarDateTime[i];
                BarEnd[j] = BarDateTime[i];
                notifyArray[i] = 4;
            }
        }
    }
    if( ZigDirection == (-1) )
    {
		if( PFL[j] <= LastTr )
		{
			IsTr[j] = 1;
			iLastTr = j;
			LastTr = PFL[j];
		} 
		//else if( ((PFH[j] / LastTr - 1) * 100) > zz)
		else if( (PFH[j] - LastTr)/Box > Boxzz)
		{
			ZigDirection = 1;
			LastPk = PFH[j];
			iLastPk = j;
			IsPk[j] = 1;

			IsTr[iLastTr] = 2;
		}
	}
	else 
	{
		if( PFH[j] >= LastPk )
		{
			iLastPk = j;
			LastPk = PFH[j];
			IsPk[j] = 1;
		}
		else if( (LastPk - PFL[j])/Box > Boxzz)
		{
			ZigDirection = -1;
			LastTr = PFL[j];
			iLastTr = j;
			IsTr[j] = 1;
			
			IsPk[iLastPk] = 2;
		}
	}
}

delta = BarCount - j - 1;
direction = Ref( direction, -delta );
BarTurn = Ref( BarTurn, -delta );
BarEnd = Ref( BarEnd, -delta );
Hi = Ref( PFH, -delta ) + Box / 2;
Lo = Ref( PFL, -delta ) - Box / 2;
Cl = IIf( direction == 1, Hi, Lo );
Op = IIf( direction == 1, Cl - Box, Cl + Box );
Graphcolor = IIf( direction == 1, xcolor, ocolor );

IsTr = Ref( IsTr, -delta );
IsPk = Ref( IsPk, -delta );

// this code is used for the 1-box reversal mode
if( scaling == "Percentage" )
{
    uu = IIf( AlmostEqual( exp( Hi - Lo ), exp( Box ), 1e3 ), 1, 0 );
}
else
{
    uu = IIf( AlmostEqual( Hi - Lo, Box, 1e5 ), 1, 0 );
}

//----------------------------------------------------------
// STANDARD CHART
//----------------------------------------------------------
if( displaymode == "Standard Chart" )
{
    Graphcolor = IIf( direction == 1, xcolor, ocolor );
    PlotOHLC( Op, Hi, Lo, Cl, "", GraphColor, stylePointAndFigure | styleNoLabel, Null, Null, 0, 0, 1 );
}

//----------------------------------------------------------
// GFX CHART
//----------------------------------------------------------
if( displaymode == "GFX" )
{
    x1 = x2 = y1 = y2 = x3 = y3 = 0;
    PlotOHLC( Op, Hi, Lo, Cl, "", colorWhite, styleNoLine | styleNoLabel, Null, Null, 0, 0, 1 );

    cols = j;
    cols = Min( BarCount - fvb, cols ); // adjust cols to visible for speed

    GfxSetZOrder( -1 );
    GfxSelectFont( ft, Box / 2 );

    for( i = 0; i <= cols; i++ )
    {
        hh = Hi[BarCount - 1 + i - cols];
        ll = Lo[BarCount - 1 + i - cols];
        nn = round( SafeDivide( hh - ll, Box ) );
        dd = direction[BarCount - 1 + i - cols];

        if( dd == 1 )
            GfxSelectSolidBrush( xcolor );

        if( dd == ( -1 ) )
            GfxSelectSolidBrush( ocolor );

        for( k = 0; k < nn - 0; k++ )
        {
            x1 = BarCount - cols + i - 1 - 0.5;
            x2 = BarCount - cols + i - 1 + 0.5;
            y1 = ll + Box * ( k + 1 ); // Hi
            y2 = ll + Box * k; // Lo

            if( dd == 1 )
            {
                x3 = 0;
                y3 = 0;
                GfxRoundRect( x1, y1, x2, y2, x3, y3 );
            }

            if( dd == ( -1 ) )
            {
                x3 = rndbox;
                y3 = rndbox;
                GfxRoundRect( x1, y1, x2, y2, x3, y3 );
            }
        }
    }
}

//----------------------------------------------------------
// GFX CHART 2 - special case for a 1 Box Reversal
//----------------------------------------------------------
if( displaymode == "GFX 1 Box Reversal" )
{
    Hi_new = Lo_new = Op_new = Cl_new = direction_new = 0;
    BarTurn_new = 0;
    BarEnd_new = 0;
    cnt = 0;

    for( i = 0; i < BarCount; i++ )
    {
        if( Hi[i] > 0 OR Lo[i] > 0 )
        {
            if( uu[i] ) // 1 box column, next column needs to be shifted back
            {
                if( direction[i] == ( -1 ) AND i < BarCount - 1 )
                {
                    cnt++;
                    // shift next column above the "O"
                    Hi_new[cnt] = Hi[i + 1];
                    Lo_new[cnt] = Lo[i];
                    Cl_new[cnt] = Hi_new[cnt];
                    Op_new[cnt] = Lo_new[cnt];
                    direction_new[cnt] = 2; // 2 means up, therefor bottom box is red, the rest green
                    barturn_new[cnt] = barturn[i + 1];
                    // skip 1 bar
                    i++;
                }
                else
                    if( direction[i] == 1 AND i < BarCount - 1 )
                    {
                        cnt++;
                        // shift next column below the "X"
                        Hi_new[cnt] = Hi[i];
                        Lo_new[cnt] = Lo[i + 1];
                        Cl_new[cnt] = Lo_new[cnt];
                        Op_new[cnt] = Hi_new[cnt];
                        direction_new[cnt] = -2; // -2 mean down, therefor to box is green, the rest red
                        barturn_new[cnt] = barturn[i + 1];
                        // skip 1 bar
                        i++;
                    }
                    else
                        if( i == ( BarCount - 1 ) )
                        {
                            cnt++;
                            // normal column, no adjustment
                            Hi_new[cnt] = Hi[i];
                            Lo_new[cnt] = Lo[i];

                            if( direction[i] == ( -1 ) )
                            {
                                Cl_new[cnt] = Lo_new[cnt];
                                Op_new[cnt] = Cl_new[cnt] + box;
                            }

                            if( direction[i] == 1 )
                            {
                                Cl_new[cnt] = Hi_new[cnt];
                                Op_new[cnt] = Cl_new[cnt] - box;
                            }

                            direction_new[cnt] = direction[i];
                            barturn_new[cnt] = barturn[i];
                        }
            }
            else
            {
                cnt++;
                // normal column, no adjustment
                Hi_new[cnt] = Hi[i];
                Lo_new[cnt] = Lo[i];

                if( direction[i] == ( -1 ) )
                {
                    Cl_new[cnt] = Lo_new[cnt];
                    Op_new[cnt] = Cl_new[cnt] + box;
                }

                if( direction[i] == 1 )
                {
                    Cl_new[cnt] = Hi_new[cnt];
                    Op_new[cnt] = Cl_new[cnt] - box;
                }

                direction_new[cnt] = direction[i];
                barturn_new[cnt] = barturn[i];
            }
        }
    }

    cols = cnt;

    delta = BarCount - cols - 1;
    Hi_new = Ref( Hi_new, -delta );
    Lo_new = Ref( Lo_new, -delta );
    Op_new = Ref( Op_new, -delta );
    Cl_new = Ref( Cl_new, -delta );
    direction_new = Ref( direction_new, -delta );
    barturn_new = Ref( barturn_new, -delta );

    Hi_new = IIf( Hi_new == 0, Null, Hi_new );
    Lo_new = IIf( Lo_new == 0, Null, Lo_new );
    Cl_new = IIf( Cl_new == 0, Null, Cl_new );
    Op_new = IIf( Op_new == 0, Null, Op_new );
    direction_new = IIf( direction_new == 0, Null, direction_new );

    x1 = x2 = y1 = y2 = x3 = y3 = 0;

    PlotOHLC( Op_new, Hi_new, Lo_new, Cl_new, "", colorWhite, styleNoLine | styleNoLabel, Null, Null, 0, 0, 1 );

    cols = cnt;
    cols = Min( BarCount - fvb, cols ); // adjust cols to visible for speed

    GfxSetZOrder( -1 );
    GfxSelectFont( ft, Box / 2 );

    for( i = 0; i < cols; i++ )
    {
        shft = ( BarCount - cols + i );
        hh = Hi_new[shft];
        ll = Lo_new[shft];
        nn = round( SafeDivide( hh - ll, Box ) );
        dd = direction_new[shft];

        if( dd == 1 OR dd == ( -1 ) )
        {
            if( dd == 1 )
                GfxSelectSolidBrush( xcolor );

            if( dd == ( -1 ) )
                GfxSelectSolidBrush( ocolor );

            //_TRACE("nn: " + nn );
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = ll + Box * ( k + 1 ); // Hi
                y2 = ll + Box * k; // Lo

                if( dd == 1 )
                {
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }

                if( dd == ( -1 ) )
                {
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }

        // special case up
        if( dd == 2 )
        {
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = ll + Box * ( k + 1 );
                y2 = ll + Box * k;

                if( k == 0 )
                {
                    GfxSelectSolidBrush( ocolor );
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
                else
                {
                    GfxSelectSolidBrush( xcolor );
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }

        // special case down
        if( dd == ( -2 ) )
        {
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = hh - Box * k;
                y2 = hh - Box * ( k + 1 );

                if( k == 0 )
                {
                    GfxSelectSolidBrush( xcolor );
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
                else
                {
                    GfxSelectSolidBrush( ocolor );
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }
    }
}

if( scaling == "Percentage" )
{
    Last = Ref( LastValue( log( C ) ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots | styleNoLabel, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "<-----------------  " + NumToStr( exp( Last ), fmt ), ft, sz, BarCount + 1, LastValue( Last ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0, gridFlags = 1 ) ; //chartGridPercent
}
else
{
    // the last close
    Last = Ref( LastValue( C ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "<-----------------  " + NumToStr( Last, fmt ), ft, sz, BarCount + 1, LastValue( C ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0 ) ;
}


if( nRev == 1 AND displaymode != "GFX 1 Box Reversal" )
{
    PlotShapes( IIf( uu, shapeSmallCircle, shapeNone ), colorWhite, 0, Lo, Box_px / 2 );
    PlotShapes( IIf( uu, shapeHollowCircle, shapeNone ), colorBlack, 0, Lo, Box_px / 2 );
}

//----------------------------------------------------------
// GRID CONSTRUCTION
//----------------------------------------------------------
if( PlotGridLines == 1 )
{
    GfxSetBkColor( bcolor );
    GfxSetTextColor( yaxcolor );
    GfxSelectFont( ft, sz, 700 );

    if( displaymode == "GFX 1 Box Reversal" )
    {
        barturn = barturn_new;
        j = cnt;
        direction = direction_new;
        direction = IIf( direction == 2, 1, IIf( direction == ( -2 ), -1, direction ) );
        Hi = Hi_new;
        Lo = Lo_new;
    }

    // Y-AXIS
    nrows = ceil( ( LastValue( Highest( Hi ) ) - LastValue( Lowest( Lo ) ) ) / box ) + 1;

    bx = LastValue( Lowest( Lo ) );
    GfxSelectPen( ColorRGB( 50, 50, 50 ) );

    nrows_visible = ceil( ( mxy - mny ) / box ) + 1;
    mult = round( nrows_visible / Min( nquot, nrows_visible ) );

    for( i = 0; i < nrows; i++ )
    {
        lvbs = bx + box * i;

        if( lvbs > mny AND lvbs < mxy )
        {
            // for placement
            ev = i % mult == 0;

            GfxMoveTo( fvb, lvbs );
            GfxLineTo( lvb, lvbs );

            if( ev )
            {
                if( scaling == "Percentage" )
                {
                    nstr = " " + NumToStr( exp( lvbs ), fmt );
                }
                else
                {
                    lvbs = round( lvbs / TickSize ) * TickSize;
                    nstr = " " + NumToStr( lvbs, fmt );
                }

                GfxTextOut( nstr, lvb, lvbs );
            }
        }
    }

    for( i = fvb; i <= lvb; i++ )
    {
        GfxMoveTo( i - 0.5, mny );
        GfxLineTo( i - 0.5, mxy );
    }

    // DATE AXIS
    GfxSelectFont( ft, sz, 600, False, False, orientation = 360 );
    GfxSetBkMode( 1 );
    GfxSetTextColor( colorAqua );

    cols = Min( Min( lvb, BarCount ) - fvb, j ); // adjust cols to visible for speed

    for( i = 1; i <= j; i++ )
    {
        shft = ( lvb - j + i - 1 );
        //mult = round( j / nquot );
        mult = round( cols / Min( nquot, cols ) );
        ev = i % mult == 0;

        if( ev )
        {
            str = DateTimeFormat( "%Y/%m/%d", BarTurn[shft] );

            if( str != "Invalid DateTime" AND barturn[shft] != 0 )
            {
                if( direction[shft] == 1 )
                {
                    GfxSetTextColor( xcolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
                else
                {
                    GfxSetTextColor( ocolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
            }
        }
    }
}

//----------------------------------------------------------
// TRENDLINES
//----------------------------------------------------------
if( trendlinetype == "BoxZigZag" AND BoxZZ > 0)
{
	pk = IsPk == 2;
	tr = IsTr == 2;
	
	pkb = BarsSince(pk);
	trb = BarsSince(tr);

	for( i = 0; i < 3; i++ )
	{
		VarSet( "px" + i, ValueWhen( pk, bi, i ) );
		VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
		VarSet( "ph" + i, ValueWhen( pk, Hi, i ) );
		VarSet( "tl" + i, ValueWhen( tr, Lo, i ) );
	}

	ll = tr AND tl1 < tl2;
	hl = tr AND tl1 > tl2;
	hh = pk AND ph1 > ph2;
	lh = pk AND ph1 < ph2;
	dt = pk AND ph1 == ph2;
	db = tr AND tl1 == tl2;

	Hiprice = ValueWhen( pk, Hi );
	Hibar = BarsSince( pk );
	TLDn = Hiprice - ( Box * HiBar );// + box / 2;

	Loprice = ValueWhen( tr, Lo );
	Lobar = BarsSince( tr );
	TLUp = Loprice + ( Box * LoBar );// - box / 2;
	
	//TLDn = IIf( trb < pkb AND TLDn >= Hi, TLDn, Null );
	//TLUp = IIf( pkb < trb AND TLUp <= Lo, TLUp, Null );
	TLDn = IIf( TLDn >= Hi, TLDn, Null );
	TLUp = IIf( TLUp <= Lo, TLUp, Null );

	Plot( TLDn, "TLDn", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
	Plot( TLUp, "TLUp", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );

	PlotShapes( IIf( tr, shapeCircle, shapeNone ), colorGreen, 0, Lo, -10 );
	PlotShapes( IIf( pk, shapeCircle, shapeNone ), colorRed, 0, Hi, 10 );

	//PlotShapes( IIf( IsTr == 1, shapeCircle, shapeNone ), colorYellow, 0, Lo, -20 );
	//PlotShapes( IIf( IsPk == 1, shapeCircle, shapeNone ), colorYellow, 0, Hi, 20 );

	for( i = lvb; i > fvb; i-- )
	{
		{
			if( ll[i] )
				PlotTextSetFont( "LL", "Arial Black", 8, i, Lo[i], colorGreen, colorDefault, -45 );

			if( hl[i] )
				PlotTextSetFont( "HL", "Arial Black", 8, i, Lo[i], colorGreen, colorDefault, -45 );

			if( db[i] )
				PlotTextSetFont( "DB", "Arial Black", 8, i, Lo[i], colorLightBlue, colorDefault, -45 );

			if( hh[i] )
				PlotTextSetFont( "HH", "Arial Black", 8, i, Hi[i], colorRed, colorDefault, 35 );

			if( lh[i] )
				PlotTextSetFont( "LH", "Arial Black", 8, i, Hi[i], colorRed, colorDefault, 35 );

			if( dt[i] )
				PlotTextSetFont( "DT", "Arial Black", 8, i, Hi[i], colorOrange, colorDefault, 25 );
		}
	}
}

if( trendlinetype == "ZigZag" )
{
    if( zz > 0 )
    {
        pk = PeakBars( Hi, zz ) == 0;
        tr = TroughBars( Lo, zz ) == 0;

        for( i = 0; i < 3; i++ )
        {
            VarSet( "px" + i, ValueWhen( pk, bi, i ) );
            VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
            VarSet( "ph" + i, ValueWhen( pk, Hi, i ) );
            VarSet( "tl" + i, ValueWhen( tr, Lo, i ) );
        }

        ll = tr AND tl1 < tl2;
        hl = tr AND tl1 > tl2;
        hh = pk AND ph1 > ph2;
        lh = pk AND ph1 < ph2;
        dt = pk AND ph1 == ph2;
        db = tr AND tl1 == tl2;

        for( i = fvb; i <= lvb; i++ )
        {
            if( pk[i] )
            {
                Hiprice = ValueWhen( bi == i, Hi );
                Hibar = BarsSince( bi == i );
                TLDn = Hiprice - ( Box * HiBar );
                TLDn = IIf( TLDn >= Hi, TLDn, Null );
                VarSet( "TLDn" + i, IIf( IsEmpty( TLDn ) AND !IsEmpty( Ref( TLDn, -1 ) ), Ref( TLDn, -1 ) - Box, TLDn ) );
                Plot( VarGet( "TLDn" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
                Buy = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), 1, Buy );
                BuyPrice = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), VarGet( "TLDn" + i ), BuyPrice );
            }

            if( tr[i] )
            {
                Loprice = ValueWhen( bi == i, Lo );
                Lobar = BarsSince( bi == i );
                TLUp = Loprice + ( Box * LoBar );
                TLUp = IIf( TLUp <= Lo, TLUp, Null );
                VarSet( "TLUp" + i, IIf( IsEmpty( TLUp ) AND !IsEmpty( Ref( TLUp, -1 ) ), Ref( TLUp, -1 ) + Box, TLUp ) );
                Plot( VarGet( "TLUp" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
                Short = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), 1, Short );
                ShortPrice = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), VarGet( "TLUp" + i ), ShortPrice );
            }
        }

        PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ) , colorAqua, 0, BuyPrice, 0 );
        PlotShapes( IIf( Short, shapeDownArrow, shapeNone ) , colorOrange, 0, ShortPrice, 0 );
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), xcolor, 0, Lo, -Box_px / 2 );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), ocolor, 0, Hi, Box_px / 2 );

        for( i = lvb; i > fvb; i-- )
        {
            {
                if( ll[i] )
                    PlotTextSetFont( "LL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * 2 );

                if( hl[i] )
                    PlotTextSetFont( "HL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * 2 );

                if( db[i] )
                    PlotTextSetFont( "DB", "Arial Black", 8, i, Lo[i], colorLightBlue, colorDefault, -Box_px * 2 );

                if( hh[i] )
                    PlotTextSetFont( "HH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * 2 - sz );

                if( lh[i] )
                    PlotTextSetFont( "LH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * 2 - sz );

                if( dt[i] )
                    PlotTextSetFont( "DT", "Arial Black", 8, i, Hi[i], colorOrange, colorDefault, Box_px * 2 - sz );
            }
        }
    }
}

if( trendlinetype == "Fractal" )
{
    pk = Hi > Ref( HHV( Hi, leftStrength * fact ), -1 ) AND Ref( HHV( Hi, rightStrength * fact ), rightStrength * fact ) <= Hi;
    tr = Lo < Ref( LLV( Lo, leftStrength * fact ), -1 ) AND Ref( LLV( Lo, rightStrength * fact ), rightStrength * fact ) >= Lo;

    for( i = 0; i < 3; i++ )
    {
        VarSet( "px" + i, ValueWhen( pk, bi, i ) );
        VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
        VarSet( "ph" + i, ValueWhen( pk, Hi, i ) );
        VarSet( "tl" + i, ValueWhen( tr, Lo, i ) );
    }

    ll = tr AND tl1 < tl2;
    hl = tr AND tl1 > tl2;
    hh = pk AND ph1 > ph2;
    lh = pk AND ph1 < ph2;
    dt = pk AND ph1 == ph2;
    db = tr AND tl1 == tl2;

    for( i = fvb; i <= lvb; i++ )
    {
        if( pk[i] )
        {
            Hiprice = ValueWhen( bi == i, Hi );
            Hibar = BarsSince( bi == i );
            TLDn = Hiprice - ( Box * HiBar );
            TLDn = IIf( TLDn >= Hi, TLDn, Null );
            VarSet( "TLDn" + i, IIf( IsEmpty( TLDn ) AND !IsEmpty( Ref( TLDn, -1 ) ), Ref( TLDn, -1 ) - Box, TLDn ) );
            Plot( VarGet( "TLDn" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
            Buy = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), 1, Buy );
            BuyPrice = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), VarGet( "TLDn" + i ), BuyPrice );
        }

        if( tr[i] )
        {
            Loprice = ValueWhen( bi == i, Lo );
            Lobar = BarsSince( bi == i );
            TLUp = Loprice + ( Box * LoBar );
            TLUp = IIf( TLUp <= Lo, TLUp, Null );
            VarSet( "TLUp" + i, IIf( IsEmpty( TLUp ) AND !IsEmpty( Ref( TLUp, -1 ) ), Ref( TLUp, -1 ) + Box, TLUp ) );
            Plot( VarGet( "TLUp" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
            Short = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), 1, Short );
            ShortPrice = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), VarGet( "TLUp" + i ), ShortPrice );
        }
    }

    PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ) , colorAqua, 0, BuyPrice, 0 );
    PlotShapes( IIf( Short, shapeDownArrow, shapeNone ) , colorOrange, 0, ShortPrice, 0 );
    PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( tr, bi ) > rightStrength * fact, xcolor, colorWhite ), 0, Lo, -Box_px / 2 );
    PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( pk, bi ) > rightStrength * fact, ocolor, colorWhite ), 0, Hi, Box_px / 2 );

    for( i = lvb; i > fvb; i-- )
    {
        {
            if( ll[i] )
                PlotTextSetFont( "LL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * 2 );

            if( hl[i] )
                PlotTextSetFont( "HL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * 2 );

            if( db[i] )
                PlotTextSetFont( "DB", "Arial Black", 8, i, Lo[i], colorLightBlue, colorDefault, -Box_px * 2 );

            if( hh[i] )
                PlotTextSetFont( "HH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * 2 - sz );

            if( lh[i] )
                PlotTextSetFont( "LH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * 2 - sz );

            if( dt[i] )
                PlotTextSetFont( "DT", "Arial Black", 8, i, Hi[i], colorOrange, colorDefault, Box_px * 2 - sz );
        }
    }
}

//----------------------------------------------------------
// TITLE
//----------------------------------------------------------
if( scaling == "Percentage" )
{
    str1 =
        EncodeColor( titleColor ) +
        "High " + NumToStr( exp( Hi ) , fmt )   + "\n" +
        "Low " + NumToStr( exp( Lo ), fmt ) + "\n" +
        "Close " + NumToStr( exp( Cl ), fmt ) + "\n" +
        "Open " + NumToStr( exp( Op ), fmt );
}
else
{
    str1 =
        EncodeColor( colorWhite ) +
        "High " + NumToStr( Hi , fmt )   + "\n" +
        "Low " + NumToStr( Lo, fmt ) + "\n" +
        "Close " + NumToStr( Cl, fmt ) + "\n" +
        "Open " + NumToStr( Op, fmt );
}

Title = EncodeColor( titleColor ) + "Point & Figure" + "\n" +
        Name() + " | " + FullName() + "\n" +
        EncodeColor( titleColor ) + "Mode: " + EncodeColor( titleHighlightColor ) + cmode + "\n" +
        EncodeColor( titleColor ) + "Box Type: " + EncodeColor( titleHighlightColor ) + ctype + "\n" +
        EncodeColor( titleColor ) + tbox + "\n" +
        "Reverse (Boxes) : " + EncodeColor( titleHighlightColor ) + nRev + EncodeColor( titleColor ) + "\n" +
        "Chart Timeframe (sec): "  + EncodeColor( titleHighlightColor ) + Interval() + "\n" +
        EncodeColor( titleColor ) + "Date at Turn: " + EncodeColor( titleHighlightColor ) + DateTimeFormat( "%Y/%m/%d", BarTurn[LastValue( SelectedValue( bi ) )] ) + "\n" +
        EncodeColor( titleColor ) + "Trendline Type: " + EncodeColor( titleHighlightColor ) + trendlinetype + "\n" +
        str1 + "\n" +
        "notifyarray " + notifyarray;


//----------------------------------------------------------
// EXPLORATION
//----------------------------------------------------------
if( Status( "action" ) == actionExplore )
{
    snd = 1;

    if( snd )
    {
        AlertIf( LastValue( notifyarray ) OR LastValue( Buy ) OR LastValue( Short ), "SOUND C:\\Windows\\Media\\Alarm03.wav", "Audio alert", 1, 15, 1 );
    }

    Filter = notifyarray OR Buy OR Short;
    AddColumn( notifyarray == 1, "New Box Down", 1.2, colorBlack, IIf( notifyarray == 1, colorRed, colorWhite ) );
    AddColumn( notifyarray == 2, "Reversal Up", 1.2, colorBlack, IIf( notifyarray == 2, colorBrightGreen, colorWhite ) );
    AddColumn( notifyarray == 3, "New Box Up", 1.2, colorBlack, IIf( notifyarray == 3, colorBrightGreen, colorWhite ) );
    AddColumn( notifyarray == 4, "Reversal Down", 1.2, colorBlack, IIf( notifyarray == 4, colorRed, colorWhite ) );
    AddColumn( Buy, "Buy", 1.2, colorBlack, IIf( Buy, colorBrightGreen, colorWhite ) );
    AddColumn( Short, "Sell", 1.2, colorBlack, IIf( Short, colorRed, colorWhite ) );
}

_SECTION_END();

thnaks will respond tomorrow, trying to get YM below 42500 today, the money printers probably will win

1 Like

hi, I added your new pivots to the code (although I did not study it in detail yet). Also added a 4-th trendline type "HHVLLV". Then I added a toggle between your original type of display "Original" and my "Alternative". My "Alternative" display make signals possible and removes discontinuities but it can get crowded :smiley:

I guess for now maybe need to think a little what to do with it all :smiley:

_SECTION_BEGIN( "Point & Figure" );
RequestMouseMoveRefresh();
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

scaling = ParamList( "Scaling Method", "Traditional|Percentage", 1 );
hclmode = ParamList( "Price Mode", "HL|C", 0 );
displaymode = ParamList( "Display Mode", "Standard Chart|GFX|GFX 1 Box Reversal", 0 );
ft = ParamList( "Font Type", "Tahoma Bold|Arial Black|Verdana Bold|Courier New Bold|Comic Sans MS Bold|Arial Bold|Candara Bold|Calibri Bold|Constantia Bold|Georgia Bold|Gadugi Bold|Segoe UI Bold", 0 );
sz = Param( "Font Size", 11, 6, 50, 1 );
Box = Param( "Box", 50, 1, 2000, 1 );
nRev = Param( "Reverse Number of Boxes", 3, 1, 10, 1 );
nquot = Param( "Number of Quotes Shown on Axis", 10, 5, 50 );
PlotGridLines = ParamToggle( "PlotdGrid", "No|Yes", 1 );
trendlinetype = ParamList( "Trendline Type", "ZigZag|Fractal|BoxZigZag|HHVLLV|No Trendlines", 1 );
trendlineDisplayType = ParamList( "Trendline Display Type", "Original|Alternative", 1 );
// parameter for zigzag trendlines
zz = Param( "ZigZag Change Amount for Trendlines (%)", 2, 0.1, 100, 0.1 );
// parameters for fractal trendlines
rightStrength = Param( "Fractal Pivot Right side Strength (bars)", 5, 2, 50, 1 );
leftStrength = Param( "Fractal Pivot Left side Strength (bars)", 10, 2, 50, 1 );
fact = Param( "Fractal Factor", 2, 1, 20, 1 );
// parameters for ZigZag Box Trendlines
Boxzz = Param( "ZigZag Box Amount for Trendlines", 15, 0, 100, 1 );
// parameters for HHVLLV trendlines
nbar = Param( "Swing number of Bars", 10, 1, 50, 1 );
handleBothOutside = ParamToggle( "Long AND Short signal at the SAME bar", "Change Trend|Stay with current Trend", 0 );
// buy sell signals
showbuysell = ParamToggle( "Show Buy Sell Signals", "No|Yes", 0 ) ;

// color definitions
xcolor = ParamColor( "X_Color", colorBrightGreen );
ocolor = ParamColor( "O_Color", colorRed );
bcolor = ParamColor( "Background Color", colorBlack );
yaxcolor = ParamColor( "Y Axis Color", colorWhite );
titleColor = ParamColor( "Title Color", colorGold );
titleHighlightColor = ParamColor( "Title Highlight Color", colorAqua );

rndbox = 30;
Lx = LastValue( bi );

SetChartBkColor( bcolor );
GfxSetZOrder( -5 );
GfxSetCoordsMode( 1 );

BarDateTime = DateTime();
BarTurn = 0;
BarEnd = 0;

mny = Status( "axisminy" );
mxy = Status( "axismaxy" );
pxb = Status( "pxchartbottom" );
pxh = Status( "pxchartheight" );
Buy = Sell = Short = Cover = BuyPrice = SellPrice = ShortPrice = CoverPrice = 0;
pk = tr = 0;

if( displaymode == "GFX 1 Box Reversal" AND nRev > 1 )
{
    displaymode = "GFX";
}

// set your TickSize here or put it in the information Window
// example for NQ and ES futures ---> TickSize = 0.25;
// if ticksize is not set in code or information window use 0.01
// Ticksize = 0.25   // I commented it out because I put it in the information window
if( TickSize == 0 )
{
    TickSize = 0.01;
}

// calculate format for display purposes
fmt = "" + TickSize;
fmt = StrReplace( fmt, ".", "," );
fmt = StrExtract( fmt, 1 );
fmt = "1" + "." + StrLen( fmt );
fmt = StrToNum( fmt );

switch( hclmode )
{
case "HL":
    prch = H;
    prcl = L;
    cmode = "High / Low Price";
    break;

case "C":
    prch = C;
    prcl = C;
    cmode = "Close Price";
    break;
}

switch( scaling )
{
case "Traditional":
    Box =  Box * TickSize;
    ctype = "Tradional (Boxsize in Points, Box x TickSize)";
    tbox = "True Box Value in Points: " + EncodeColor( titleHighlightColor ) +  NumToStr( Box, fmt ) + " Points" + EncodeColor( titleColor );
    break;

case "Percentage":
    Box = Box / 100;
    ctype = "Percentage (Boxsize in Percent)";
    tbox = "True Box Value in Percent: " + EncodeColor( titleHighlightColor ) + Box + " %" + EncodeColor( titleColor );
    break;
}

function GfxConvertValueToPixelY( Value )
{
    return Value * SafeDivide( pxh, mxy - mny );
}

PFL = PFH = 0;
Box_px = j = 0;

if( scaling == "Percentage" )
{
    Box = log( 1 + Box / 100 );
    prch = log( prch );
    prcl = log( prcl );
    PFL[0] = Box * ceil( prcl[0] / Box ) + Box;
    PFH[0] = Box * floor( prch[0] / Box );
    zz = log( zz );

    // box size in pixels
    Box_px = GfxConvertValueToPixelY( Box );
}
else
{
    PFL[0] = Box * ceil( prcl[0] / Box ) + Box;
    PFH[0] = Box * floor( prch[0] / Box );

    // box size in pixels
    Box_px = GfxConvertValueToPixelY( Box );
}

direction = -1;
notifyArray = 0;

// parameters for ZigZag Box Trendlines
ZigDirection = -1;
CurBox = 0;
BoxTr = BoxPk = 0;
iLastPk = 0;
iLastTr = 0;
IsPk = 0;
IsPk[0] = 1;
IsTr = 0;
IsTr[0] = 1;
LastPk = 0;
LastTr = 1000000;

for( i = 0; i < BarCount; i++ )
{
    if( direction[j] == ( -1 ) )
    {
        if( prcl[i] <= PFL[j] - Box )
        {
            PFL[j] = Box * ceil( prcl[i] / Box );
            BarEnd[j] = BarDateTime[i];
            notifyArray[i] = 1;
        }
        else
        {
            if( prch[i] >= PFL[j] + nRev * Box )
            {
                j++;
                direction[j] = 1;
                PFH[j] = Box * floor( prch[i] / Box );
                PFL[j] = PFL[j - 1] + Box;
                BarTurn[j] = BarDateTime[i];
                BarEnd[j] = BarDateTime[i];
                notifyArray[i] = 2;
            }
        }
    }
    else
    {
        if( prch[i] >= PFH[j] + Box )
        {
            PFH[j] = Box * floor( prch[i] / Box );
            BarEnd[j] = BarDateTime[i];
            notifyArray[i] = 3;
        }
        else
        {
            if( prcl[i] <= PFH[j] - nRev * Box )
            {
                j++;
                direction[j] = -1;
                PFH[j] = PFH[j - 1] - Box;
                PFL[j] = Box * ceil( prcl[i] / Box );
                BarTurn[j] = BarDateTime[i];
                BarEnd[j] = BarDateTime[i];
                notifyArray[i] = 4;
            }
        }
    }

    if( ZigDirection == ( -1 ) )
    {
        if( PFL[j] <= LastTr )
        {
            IsTr[j] = 1;
            iLastTr = j;
            LastTr = PFL[j];
        }
        else
            if( ( PFH[j] - LastTr ) / Box > Boxzz )
            {
                ZigDirection = 1;
                LastPk = PFH[j];
                iLastPk = j;
                IsPk[j] = 1;
                IsTr[iLastTr] = 2;
            }
    }
    else
    {
        if( PFH[j] >= LastPk )
        {
            iLastPk = j;
            LastPk = PFH[j];
            IsPk[j] = 1;
        }
        else
            if( ( LastPk - PFL[j] ) / Box > Boxzz )
            {
                ZigDirection = -1;
                LastTr = PFL[j];
                iLastTr = j;
                IsTr[j] = 1;
                IsPk[iLastPk] = 2;
            }
    }
}

delta = BarCount - j - 1;
direction = Ref( direction, -delta );
BarTurn = Ref( BarTurn, -delta );
BarEnd = Ref( BarEnd, -delta );
Hi = Ref( PFH, -delta ) + Box / 2;
Lo = Ref( PFL, -delta ) - Box / 2;
Cl = IIf( direction == 1, Hi, Lo );
Op = IIf( direction == 1, Cl - Box, Cl + Box );
Graphcolor = IIf( direction == 1, xcolor, ocolor );
IsTr = Ref( IsTr, -delta );
IsPk = Ref( IsPk, -delta );

// this code is used for the 1-box reversal mode
if( scaling == "Percentage" )
{
    uu = IIf( AlmostEqual( exp( Hi - Lo ), exp( Box ), 1e3 ), 1, 0 );
}
else
{
    uu = IIf( AlmostEqual( Hi - Lo, Box, 1e5 ), 1, 0 );
}

//----------------------------------------------------------
// STANDARD CHART
//----------------------------------------------------------
if( displaymode == "Standard Chart" )
{
    Graphcolor = IIf( direction == 1, xcolor, ocolor );
    PlotOHLC( Op, Hi, Lo, Cl, "", GraphColor, stylePointAndFigure | styleNoLabel, Null, Null, 0, 0, 1 );
}

//----------------------------------------------------------
// GFX CHART
//----------------------------------------------------------
if( displaymode == "GFX" )
{
    x1 = x2 = y1 = y2 = x3 = y3 = 0;
    PlotOHLC( Op, Hi, Lo, Cl, "", colorWhite, styleNoLine | styleNoLabel, Null, Null, 0, 0, 1 );

    cols = j;
    cols = Min( BarCount - fvb, cols ); // adjust cols to visible for speed

    GfxSetZOrder( -1 );
    GfxSelectFont( ft, Box / 2 );

    for( i = 0; i <= cols; i++ )
    {
        hh = Hi[BarCount - 1 + i - cols];
        ll = Lo[BarCount - 1 + i - cols];
        nn = round( SafeDivide( hh - ll, Box ) );
        dd = direction[BarCount - 1 + i - cols];

        if( dd == 1 )
            GfxSelectSolidBrush( xcolor );

        if( dd == ( -1 ) )
            GfxSelectSolidBrush( ocolor );

        for( k = 0; k < nn - 0; k++ )
        {
            x1 = BarCount - cols + i - 1 - 0.5;
            x2 = BarCount - cols + i - 1 + 0.5;
            y1 = ll + Box * ( k + 1 ); // Hi
            y2 = ll + Box * k; // Lo

            if( dd == 1 )
            {
                x3 = 0;
                y3 = 0;
                GfxRoundRect( x1, y1, x2, y2, x3, y3 );
            }

            if( dd == ( -1 ) )
            {
                x3 = rndbox;
                y3 = rndbox;
                GfxRoundRect( x1, y1, x2, y2, x3, y3 );
            }
        }
    }
}

//----------------------------------------------------------
// GFX CHART 2 - special case for a 1 Box Reversal
//----------------------------------------------------------
if( displaymode == "GFX 1 Box Reversal" )
{
    Hi_new = Lo_new = Op_new = Cl_new = direction_new = 0;
    BarTurn_new = 0;
    BarEnd_new = 0;
    cnt = 0;

    for( i = 0; i < BarCount; i++ )
    {
        if( Hi[i] > 0 OR Lo[i] > 0 )
        {
            if( uu[i] ) // 1 box column, next column needs to be shifted back
            {
                if( direction[i] == ( -1 ) AND i < BarCount - 1 )
                {
                    cnt++;
                    // shift next column above the "O"
                    Hi_new[cnt] = Hi[i + 1];
                    Lo_new[cnt] = Lo[i];
                    Cl_new[cnt] = Hi_new[cnt];
                    Op_new[cnt] = Lo_new[cnt];
                    direction_new[cnt] = 2; // 2 means up, therefor bottom box is red, the rest green
                    barturn_new[cnt] = barturn[i + 1];
                    // skip 1 bar
                    i++;
                }
                else
                    if( direction[i] == 1 AND i < BarCount - 1 )
                    {
                        cnt++;
                        // shift next column below the "X"
                        Hi_new[cnt] = Hi[i];
                        Lo_new[cnt] = Lo[i + 1];
                        Cl_new[cnt] = Lo_new[cnt];
                        Op_new[cnt] = Hi_new[cnt];
                        direction_new[cnt] = -2; // -2 mean down, therefor to box is green, the rest red
                        barturn_new[cnt] = barturn[i + 1];
                        // skip 1 bar
                        i++;
                    }
                    else
                        if( i == ( BarCount - 1 ) )
                        {
                            cnt++;
                            // normal column, no adjustment
                            Hi_new[cnt] = Hi[i];
                            Lo_new[cnt] = Lo[i];

                            if( direction[i] == ( -1 ) )
                            {
                                Cl_new[cnt] = Lo_new[cnt];
                                Op_new[cnt] = Cl_new[cnt] + box;
                            }

                            if( direction[i] == 1 )
                            {
                                Cl_new[cnt] = Hi_new[cnt];
                                Op_new[cnt] = Cl_new[cnt] - box;
                            }

                            direction_new[cnt] = direction[i];
                            barturn_new[cnt] = barturn[i];
                        }
            }
            else
            {
                cnt++;
                // normal column, no adjustment
                Hi_new[cnt] = Hi[i];
                Lo_new[cnt] = Lo[i];

                if( direction[i] == ( -1 ) )
                {
                    Cl_new[cnt] = Lo_new[cnt];
                    Op_new[cnt] = Cl_new[cnt] + box;
                }

                if( direction[i] == 1 )
                {
                    Cl_new[cnt] = Hi_new[cnt];
                    Op_new[cnt] = Cl_new[cnt] - box;
                }

                direction_new[cnt] = direction[i];
                barturn_new[cnt] = barturn[i];
            }
        }
    }

    cols = cnt;

    delta = BarCount - cols - 1;
    Hi_new = Ref( Hi_new, -delta );
    Lo_new = Ref( Lo_new, -delta );
    Op_new = Ref( Op_new, -delta );
    Cl_new = Ref( Cl_new, -delta );
    direction_new = Ref( direction_new, -delta );
    barturn_new = Ref( barturn_new, -delta );

    Hi_new = IIf( Hi_new == 0, Null, Hi_new );
    Lo_new = IIf( Lo_new == 0, Null, Lo_new );
    Cl_new = IIf( Cl_new == 0, Null, Cl_new );
    Op_new = IIf( Op_new == 0, Null, Op_new );
    direction_new = IIf( direction_new == 0, Null, direction_new );

    x1 = x2 = y1 = y2 = x3 = y3 = 0;

    PlotOHLC( Op_new, Hi_new, Lo_new, Cl_new, "", colorWhite, styleNoLine | styleNoLabel, Null, Null, 0, 0, 1 );

    cols = cnt;
    cols = Min( BarCount - fvb, cols ); // adjust cols to visible for speed

    GfxSetZOrder( -1 );
    GfxSelectFont( ft, Box / 2 );

    for( i = 0; i < cols; i++ )
    {
        shft = ( BarCount - cols + i );
        hh = Hi_new[shft];
        ll = Lo_new[shft];
        nn = round( SafeDivide( hh - ll, Box ) );
        dd = direction_new[shft];

        if( dd == 1 OR dd == ( -1 ) )
        {
            if( dd == 1 )
                GfxSelectSolidBrush( xcolor );

            if( dd == ( -1 ) )
                GfxSelectSolidBrush( ocolor );

            //_TRACE("nn: " + nn );
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = ll + Box * ( k + 1 ); // Hi
                y2 = ll + Box * k; // Lo

                if( dd == 1 )
                {
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }

                if( dd == ( -1 ) )
                {
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }

        // special case up
        if( dd == 2 )
        {
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = ll + Box * ( k + 1 );
                y2 = ll + Box * k;

                if( k == 0 )
                {
                    GfxSelectSolidBrush( ocolor );
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
                else
                {
                    GfxSelectSolidBrush( xcolor );
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }

        // special case down
        if( dd == ( -2 ) )
        {
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = hh - Box * k;
                y2 = hh - Box * ( k + 1 );

                if( k == 0 )
                {
                    GfxSelectSolidBrush( xcolor );
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
                else
                {
                    GfxSelectSolidBrush( ocolor );
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }
    }
}

if( scaling == "Percentage" )
{
    Last = Ref( LastValue( log( C ) ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots | styleNoLabel, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "<-----------------  " + NumToStr( exp( Last ), fmt ), ft, sz, BarCount + 1, LastValue( Last ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0, gridFlags = 1 ) ; //chartGridPercent
}
else
{
    // the last close
    Last = Ref( LastValue( C ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "<-----------------  " + NumToStr( Last, fmt ), ft, sz, BarCount + 1, LastValue( C ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0 ) ;
}


if( nRev == 1 AND displaymode != "GFX 1 Box Reversal" )
{
    PlotShapes( IIf( uu, shapeSmallCircle, shapeNone ), colorWhite, 0, Lo, Box_px / 2 );
    PlotShapes( IIf( uu, shapeHollowCircle, shapeNone ), colorBlack, 0, Lo, Box_px / 2 );
}

//----------------------------------------------------------
// GRID CONSTRUCTION
//----------------------------------------------------------
if( PlotGridLines == 1 )
{
    GfxSetBkColor( bcolor );
    GfxSetTextColor( yaxcolor );
    GfxSelectFont( ft, sz, 700 );

    if( displaymode == "GFX 1 Box Reversal" )
    {
        barturn = barturn_new;
        j = cnt;
        direction = direction_new;
        direction = IIf( direction == 2, 1, IIf( direction == ( -2 ), -1, direction ) );
        Hi = Hi_new;
        Lo = Lo_new;
    }

    // Y-AXIS
    nrows = ceil( ( LastValue( Highest( Hi ) ) - LastValue( Lowest( Lo ) ) ) / box ) + 1;

    bx = LastValue( Lowest( Lo ) );
    GfxSelectPen( ColorRGB( 50, 50, 50 ) );

    nrows_visible = ceil( ( mxy - mny ) / box ) + 1;
    mult = round( nrows_visible / Min( nquot, nrows_visible ) );

    for( i = 0; i < nrows; i++ )
    {
        lvbs = bx + box * i;

        if( lvbs > mny AND lvbs < mxy )
        {
            // for placement
            ev = i % mult == 0;

            GfxMoveTo( fvb, lvbs );
            GfxLineTo( lvb, lvbs );

            if( ev )
            {
                if( scaling == "Percentage" )
                {
                    nstr = " " + NumToStr( exp( lvbs ), fmt );
                }
                else
                {
                    lvbs = round( lvbs / TickSize ) * TickSize;
                    nstr = " " + NumToStr( lvbs, fmt );
                }

                GfxTextOut( nstr, lvb, lvbs );
            }
        }
    }

    for( i = fvb; i <= lvb; i++ )
    {
        GfxMoveTo( i - 0.5, mny );
        GfxLineTo( i - 0.5, mxy );
    }

    // DATE AXIS
    GfxSelectFont( ft, sz, 600, False, False, orientation = 900 );
    GfxSetBkMode( 1 );
    GfxSetTextColor( colorAqua );

    cols = Min( Min( lvb, BarCount ) - fvb, j ); // adjust cols to visible for speed

    for( i = 1; i <= j; i++ )
    {
        shft = ( lvb - j + i - 1 );
        //mult = round( j / nquot );
        mult = round( cols / Min( nquot, cols ) );
        ev = i % mult == 0;

        if( ev )
        {
            str = DateTimeFormat( "%Y/%m/%d", BarTurn[shft] );

            if( str != "Invalid DateTime" AND barturn[shft] != 0 )
            {
                if( direction[shft] == 1 )
                {
                    GfxSetTextColor( xcolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
                else
                {
                    GfxSetTextColor( ocolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
            }
        }
    }
}

//----------------------------------------------------------
// TRENDLINES
//----------------------------------------------------------
if( trendlinetype == "ZigZag" )
{
    if( zz > 0 )
    {
        pk = PeakBars( Hi, zz ) == 0;
        tr = TroughBars( Lo, zz ) == 0;
    }
}

if( trendlinetype == "Fractal" )
{
    pk = Hi > Ref( HHV( Hi, leftStrength * fact ), -1 ) AND Ref( HHV( Hi, rightStrength * fact ), rightStrength * fact ) <= Hi;
    tr = Lo < Ref( LLV( Lo, leftStrength * fact ), -1 ) AND Ref( LLV( Lo, rightStrength * fact ), rightStrength * fact ) >= Lo;
}

if( trendlinetype == "BoxZigZag" AND BoxZZ > 0 )
{
    pk = IsPk == 2;
    tr = IsTr == 2;
}

if( trendlinetype == "HHVLLV" )
{
    // find trend
    res = HHV( Hi, nbar );
    sup = LLV( Lo, nbar );
    crossup = Hi > Ref( res, -1 );
    crossdn = Lo < Ref( sup, -1 );

    if( handleBothOutside )
    {
        // if in H/L mode both crossup and crossdn at the same bar may occur.
        // if handleBothOutside is true then it will stay in the current trend
        // if handleBothOutside is false it will change the trend.
        crossup = IIf( ( crossup AND crossdn ) AND( BarsSince( Ref( crossup, -1 ) ) > BarsSince( Ref( crossdn, -1 ) ) ), 0, crossup );
        crossdn = IIf( ( crossup AND crossdn ) AND( BarsSince( Ref( crossdn, -1 ) ) > BarsSince( Ref( crossup, -1 ) ) ), 0, crossdn );
    }

    crossup = ExRem( crossup, crossdn );
    crossdn = ExRem( crossdn, crossup );
    trendup = Flip( crossup, crossdn );
    trenddn = Flip( crossdn, crossup );

    // find pivots
    rtrenddn = Reverse( trenddn );
    rtrendup = Reverse( trendup );
    l1 = LowestSince( trenddn AND Ref( trendup, -1 ), Lo );
    rL = Reverse( Lo );
    l2 = LowestSince( rtrenddn AND Ref( rtrendup, -1 ), rL );
    rl2 = Reverse( l2 );
    h1 = HighestSince( trendup AND Ref( trenddn, -1 ), Hi );
    rH = Reverse( Hi );
    h2 = HighestSince( rtrendup AND Ref( rtrenddn, -1 ), rH );
    rh2 = Reverse( h2 );
    tr = l1 == rl2 AND trenddn;
    pk = h1 == rh2 AND trendup;
    rpk = Reverse( pk );
    rtr = Reverse( tr );
    rpk = ExRem( rpk, rtr );
    rtr = ExRem( rtr, rpk );
    pk = Reverse( rpk );
    tr = Reverse( rtr );
}

if( trendlinetype != "No trendLines" AND trendlineDisplayType == "Original" )
{
    for( i = 0; i < 3; i++ )
    {
        VarSet( "px" + i, ValueWhen( pk, bi, i ) );
        VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
        VarSet( "ph" + i, ValueWhen( pk, Hi, i ) );
        VarSet( "tl" + i, ValueWhen( tr, Lo, i ) );
    }

    ll = tr AND tl1 < tl2;
    hl = tr AND tl1 > tl2;
    hh = pk AND ph1 > ph2;
    lh = pk AND ph1 < ph2;
    dt = pk AND ph1 == ph2;
    db = tr AND tl1 == tl2;

    Hiprice = ValueWhen( pk, Hi );
    Hibar = BarsSince( pk );
    TLDn = Hiprice - ( Box * HiBar ) + box / 2;
    Loprice = ValueWhen( tr, Lo );
    Lobar = BarsSince( tr );
    TLUp = Loprice + ( Box * LoBar ) - box / 2;
    TLDn = IIf( TLDn >= Hi, TLDn, Null );
    TLUp = IIf( TLUp <= Lo, TLUp, Null );

    Plot( TLDn, "TLDn", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
    Plot( TLUp, "TLUp", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );

    if( trendlinetype == "Fractal" )
    {
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( tr, bi ) > rightStrength * fact, xcolor, colorWhite ), 0, Lo, -Box_px );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( pk, bi ) > rightStrength * fact, ocolor, colorWhite ), 0, Hi, Box_px );
    }
    else
    {
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), colorGreen, 0, Lo, -Box_px );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), colorRed, 0, Hi, Box_px );
    }

    dist = 2;

    for( i = lvb; i > fvb; i-- )
    {
        {
            if( ll[i] )
                PlotTextSetFont( "LL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * dist );

            if( hl[i] )
                PlotTextSetFont( "HL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * dist );

            if( db[i] )
                PlotTextSetFont( "DB", "Arial Black", 8, i, Lo[i], colorLightBlue, colorDefault, -Box_px * dist );

            if( hh[i] )
                PlotTextSetFont( "HH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * dist - sz );

            if( lh[i] )
                PlotTextSetFont( "LH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * dist - sz );

            if( dt[i] )
                PlotTextSetFont( "DT", "Arial Black", 8, i, Hi[i], colorOrange, colorDefault, Box_px * dist - sz );
        }
    }
}

if( trendlinetype != "No trendLines" AND trendlineDisplayType == "Alternative" )
{
    for( i = 0; i < 3; i++ )
    {
        VarSet( "px" + i, ValueWhen( pk, bi, i ) );
        VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
        VarSet( "ph" + i, ValueWhen( pk, Hi, i ) );
        VarSet( "tl" + i, ValueWhen( tr, Lo, i ) );
    }

    ll = tr AND tl1 < tl2;
    hl = tr AND tl1 > tl2;
    hh = pk AND ph1 > ph2;
    lh = pk AND ph1 < ph2;
    dt = pk AND ph1 == ph2;
    db = tr AND tl1 == tl2;

    for( i = fvb; i <= lvb; i++ )
    {
        if( pk[i] )
        {
            Hiprice = ValueWhen( bi == i, Hi );
            Hibar = BarsSince( bi == i );
            TLDn = Hiprice - ( Box * HiBar ) + box / 2;;
            TLDn = IIf( TLDn > Hi, TLDn, Null );
            VarSet( "TLDn" + i, IIf( IsEmpty( TLDn ) AND !IsEmpty( Ref( TLDn, -1 ) ), Ref( TLDn, -1 ) - Box, TLDn ) );
            Plot( VarGet( "TLDn" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
            Buy = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), 1, Buy );
            BuyPrice = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), VarGet( "TLDn" + i ), BuyPrice );

            if( showbuysell )
                PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ) , colorAqua, 0, BuyPrice, 0 );
        }

        if( tr[i] )
        {
            Loprice = ValueWhen( bi == i, Lo );
            Lobar = BarsSince( bi == i );
            TLUp = Loprice + ( Box * LoBar ) - box / 2;;
            TLUp = IIf( TLUp < Lo, TLUp, Null );
            VarSet( "TLUp" + i, IIf( IsEmpty( TLUp ) AND !IsEmpty( Ref( TLUp, -1 ) ), Ref( TLUp, -1 ) + Box, TLUp ) );
            Plot( VarGet( "TLUp" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
            Short = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), 1, Short );
            ShortPrice = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), VarGet( "TLUp" + i ), ShortPrice );

            if( showbuysell )
                PlotShapes( IIf( Short, shapeDownArrow, shapeNone ) , colorOrange, 0, ShortPrice, 0 );
        }
    }

    if( trendlinetype == "Fractal" )
    {
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( tr, bi ) > rightStrength * fact, xcolor, colorWhite ), 0, Lo, -Box_px );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( pk, bi ) > rightStrength * fact, ocolor, colorWhite ), 0, Hi, Box_px );
    }
    else
    {
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), colorGreen, 0, Lo, -Box_px );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), colorRed, 0, Hi, Box_px );
    }

    dist = 2;

    for( i = lvb; i > fvb; i-- )
    {
        {
            if( ll[i] )
                PlotTextSetFont( "LL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * dist );

            if( hl[i] )
                PlotTextSetFont( "HL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * dist );

            if( db[i] )
                PlotTextSetFont( "DB", "Arial Black", 8, i, Lo[i], colorLightBlue, colorDefault, -Box_px * dist );

            if( hh[i] )
                PlotTextSetFont( "HH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * dist - sz );

            if( lh[i] )
                PlotTextSetFont( "LH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * dist - sz );

            if( dt[i] )
                PlotTextSetFont( "DT", "Arial Black", 8, i, Hi[i], colorOrange, colorDefault, Box_px * dist - sz );
        }
    }
}

//----------------------------------------------------------
// TITLE
//----------------------------------------------------------
if( scaling == "Percentage" )
{
    str1 =
        EncodeColor( titleColor ) +
        "High " + NumToStr( exp( Hi ) , fmt )   + "\n" +
        "Low " + NumToStr( exp( Lo ), fmt ) + "\n" +
        "Close " + NumToStr( exp( Cl ), fmt ) + "\n" +
        "Open " + NumToStr( exp( Op ), fmt );
}
else
{
    str1 =
        EncodeColor( colorWhite ) +
        "High " + NumToStr( Hi , fmt )   + "\n" +
        "Low " + NumToStr( Lo, fmt ) + "\n" +
        "Close " + NumToStr( Cl, fmt ) + "\n" +
        "Open " + NumToStr( Op, fmt );
}

Title = EncodeColor( titleColor ) + "Point & Figure" + "\n" +
        Name() + " | " + FullName() + "\n" +
        EncodeColor( titleColor ) + "Mode: " + EncodeColor( titleHighlightColor ) + cmode + "\n" +
        EncodeColor( titleColor ) + "Box Type: " + EncodeColor( titleHighlightColor ) + ctype + "\n" +
        EncodeColor( titleColor ) + tbox + "\n" +
        "Reverse (Boxes) : " + EncodeColor( titleHighlightColor ) + nRev + EncodeColor( titleColor ) + "\n" +
        "Chart Timeframe (sec): "  + EncodeColor( titleHighlightColor ) + Interval() + "\n" +
        EncodeColor( titleColor ) + "Date at Turn: " + EncodeColor( titleHighlightColor ) + DateTimeFormat( "%Y/%m/%d", BarTurn[LastValue( SelectedValue( bi ) )] ) + "\n" +
        EncodeColor( titleColor ) + "Trendline Type: " + EncodeColor( titleHighlightColor ) + trendlinetype + "\n" +
        EncodeColor( titleColor ) + "Trendline Display Type: " + EncodeColor( titleHighlightColor ) + trendlineDisplaytype + "\n" +
        str1 + "\n" +
        "notifyarray " + notifyarray;


//----------------------------------------------------------
// EXPLORATION
//----------------------------------------------------------
if( Status( "action" ) == actionExplore )
{
    snd = 1;

    if( snd )
    {
        AlertIf( LastValue( notifyarray ) OR LastValue( Buy ) OR LastValue( Short ), "SOUND C:\\Windows\\Media\\Alarm03.wav", "Audio alert", 1, 15, 1 );
    }

    Filter = notifyarray OR Buy OR Short;
    AddColumn( notifyarray == 1, "New Box Down", 1.2, colorBlack, IIf( notifyarray == 1, colorRed, colorWhite ) );
    AddColumn( notifyarray == 2, "Reversal Up", 1.2, colorBlack, IIf( notifyarray == 2, colorBrightGreen, colorWhite ) );
    AddColumn( notifyarray == 3, "New Box Up", 1.2, colorBlack, IIf( notifyarray == 3, colorBrightGreen, colorWhite ) );
    AddColumn( notifyarray == 4, "Reversal Down", 1.2, colorBlack, IIf( notifyarray == 4, colorRed, colorWhite ) );
    AddColumn( Buy, "Buy", 1.2, colorBlack, IIf( Buy, colorBrightGreen, colorWhite ) );
    AddColumn( Short, "Sell", 1.2, colorBlack, IIf( Short, colorRed, colorWhite ) );
}

_SECTION_END();

1 Like

Hi @empottasch - If you SS I shared in previous post (against which I am replying this post), I am getting mutiple overlapping trednlines too crowded. I am using your latest updated code as per below link, Any idea what could be wrong in Param Settings?

I get similar Trendlines for all Tickers. While your earlier trendline code (before some of the enhancements you did, worked fine)

in the latest code I posted you can chose "Trendline Display Type" Original. This is what Wilson originally made. You get so many lines because you have too many pivots. You need to change the parameters to get less pivots.

Each trendline type has their own parameters, see code. ZizZag uses "ZigZag change amount" etc. When you change that number you change the number of pivots and therefore also the number of lines.

So here is the stock you showed. You can set the trendline Display type to original, see arrows

Thanks for adding.

ZigZag changes direction depending on a % change
BoxZigZag does the same but instead of % it counts number of boxes since last peak or last through

1 Like

Found some symbols that with default parameters with Traditional approach
may cause endless loop in GridLines

I suggest you add a limit to "for"

if( PlotGridLines == 1 )
{
    ------------
    ------------ lines of code
    ------------

    for( i = 0; i < nrows AND nrows < 1000; i++ )
    {

1 Like

@Tomasz as you can see in above screenshots of empottasch, 900 orientation for him has a diferent effect from mine. Just to report

Using 899 as orientation give me this

Using 900 as orientation give me this (but when empottasch post his screenshot looks like my 899)

used last code posted by empottasch

AB 6.93.0 64 bits

This is something that Windows implements, not AmiBroker. I am just passing the value unchanged to LOGFONT structure LOGFONTA (wingdi.h) - Win32 apps | Microsoft Learn

1 Like

i still had some ABCD code i adjusted as an overlay to drag over the base code. I adjusted the base code so that you can turn off grid, trendlines etc else it will be a mess visually. Will post the codes later

1 Like

ES 1% chart. data from 2010

1 Like



2 Likes

here is the code. I put it in 1 file but the ABCD code starts at line 900 and you can just remove the code from that ABCD section and put it in a separate file in the C:\Program Files\AmiBroker\Formulas\Custom folder and drag it on top of the code. I arranged the parameters a bit different so by default it shows the ABCD and no grid or trendlines.

_SECTION_BEGIN( "Point & Figure" );
RequestMouseMoveRefresh();
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

scaling = ParamList( "Scaling Method", "Traditional|Percentage", 1 );
hclmode = ParamList( "Price Mode", "HL|C", 0 );
displaymode = ParamList( "Display Mode", "Standard Chart|GFX|GFX 1 Box Reversal", 0 );
ft = ParamList( "Font Type", "Tahoma Bold|Arial Black|Verdana Bold|Courier New Bold|Comic Sans MS Bold|Arial Bold|Candara Bold|Calibri Bold|Constantia Bold|Georgia Bold|Gadugi Bold|Segoe UI Bold", 0 );
sz = Param( "Font Size", 11, 6, 50, 1 );
Box = Param( "Box", 20, 1, 2000, 1 );
nRev = Param( "Reverse Number of Boxes", 3, 1, 10, 1 );
nquot = Param( "Number of Quotes Shown on Axis", 10, 5, 50 );
ShowGrid = ParamToggle( "Show Grid", "No|Yes", 0 );
ShowAxis = ParamToggle( "Show Axis", "No|Yes", 1 );
showpivots = ParamToggle( "Show Pivots", "No|Yes", 1 );
showtrendlines = ParamToggle( "Show Trendlines", "No|Yes", 0 );
pivottype = ParamList( "Pivot Type", "ZigZag|Fractal|BoxZigZag|HHVLLV", 3 );
trendlineDisplayType = ParamList( "Trendline Display Type", "Original|Alternative", 0 );
// parameter for zigzag pivots
zz = Param( "ZigZag Change Amount for Trendlines (%)", 2, 0.1, 100, 0.1 );
// parameters for fractal pivots
rightStrength = Param( "Fractal Pivot Right side Strength (bars)", 5, 2, 50, 1 );
leftStrength = Param( "Fractal Pivot Left side Strength (bars)", 10, 2, 50, 1 );
fact = Param( "Fractal Factor", 2, 1, 20, 1 );
// parameters for ZigZag Box pivots
Boxzz = Param( "ZigZag Box Amount for Trendlines (BoxZigZag Pivots)", 50, 1, 150, 1 );
// parameters for HHVLLV trendlines
nbar = Param( "Swing number of Bars", 10, 1, 50, 1 );
handleBothOutside = ParamToggle( "Long AND Short signal at the SAME bar", "Change Trend|Stay with current Trend", 0 );
// buy sell signals
showbuysell = ParamToggle( "Show Buy Sell Signals", "No|Yes", 0 ) ;

// color definitions
xcolor = ParamColor( "X_Color", colorBrightGreen );
ocolor = ParamColor( "O_Color", colorRed );
bcolor = ParamColor( "Background Color", colorBlack );
yaxcolor = ParamColor( "Y Axis Color", colorWhite );
titleColor = ParamColor( "Title Color", colorGold );
titleHighlightColor = ParamColor( "Title Highlight Color", colorAqua );

rndbox = 30;
Lx = LastValue( bi );

SetChartBkColor( bcolor );
GfxSetZOrder( -5 );
GfxSetCoordsMode( 1 );

BarDateTime = DateTime();
BarTurn = 0;
BarEnd = 0;

mny = Status( "axisminy" );
mxy = Status( "axismaxy" );
pxb = Status( "pxchartbottom" );
pxh = Status( "pxchartheight" );
Buy = Sell = Short = Cover = BuyPrice = SellPrice = ShortPrice = CoverPrice = 0;
pk = tr = 0;

if( displaymode == "GFX 1 Box Reversal" AND nRev > 1 )
{
    displaymode = "GFX";
}

// set your TickSize here or put it in the information Window
// example for NQ and ES futures ---> TickSize = 0.25;
// if ticksize is not set in code or information window use 0.01
// Ticksize = 0.25   // I commented it out because I put it in the information window
if( TickSize == 0 )
{
    TickSize = 0.01;
}

// calculate format for display purposes
fmt = "" + TickSize;
fmt = StrReplace( fmt, ".", "," );
fmt = StrExtract( fmt, 1 );
fmt = "1" + "." + StrLen( fmt );
fmt = StrToNum( fmt );

switch( hclmode )
{
case "HL":
    prch = H;
    prcl = L;
    cmode = "High / Low Price";
    break;

case "C":
    prch = C;
    prcl = C;
    cmode = "Close Price";
    break;
}

switch( scaling )
{
case "Traditional":
    Box =  Box * TickSize;
    ctype = "Tradional (Boxsize in Points, Box x TickSize)";
    tbox = "True Box Value in Points: " + EncodeColor( titleHighlightColor ) +  NumToStr( Box, fmt ) + " Points" + EncodeColor( titleColor );
    break;

case "Percentage":
    Box = Box / 100;
    ctype = "Percentage (Boxsize in Percent)";
    tbox = "True Box Value in Percent: " + EncodeColor( titleHighlightColor ) + Box + " %" + EncodeColor( titleColor );
    break;
}

function GfxConvertValueToPixelY( Value )
{
    return Value * SafeDivide( pxh, mxy - mny );
}

PFL = PFH = 0;
Box_px = j = 0;

if( scaling == "Percentage" )
{
    Box = log( 1 + Box / 100 );
    prch = log( prch );
    prcl = log( prcl );
    PFL[0] = Box * ceil( prcl[0] / Box ) + Box;
    PFH[0] = Box * floor( prch[0] / Box );
    zz = log( zz );

    // box size in pixels
    Box_px = GfxConvertValueToPixelY( Box );
}
else
{
    PFL[0] = Box * ceil( prcl[0] / Box ) + Box;
    PFH[0] = Box * floor( prch[0] / Box );

    // box size in pixels
    Box_px = GfxConvertValueToPixelY( Box );
}

direction = -1;
notifyArray = 0;

// parameters for ZigZag Box Trendlines
ZigDirection = -1;
CurBox = 0;
BoxTr = BoxPk = 0;
iLastPk = 0;
iLastTr = 0;
IsPk = 0;
IsPk[0] = 1;
IsTr = 0;
IsTr[0] = 1;
LastPk = 0;
LastTr = 1000000;

for( i = 0; i < BarCount; i++ )
{
    if( direction[j] == ( -1 ) )
    {
        if( prcl[i] <= PFL[j] - Box )
        {
            PFL[j] = Box * ceil( prcl[i] / Box );
            BarEnd[j] = BarDateTime[i];
            notifyArray[i] = 1;
        }
        else
        {
            if( prch[i] >= PFL[j] + nRev * Box )
            {
                j++;
                direction[j] = 1;
                PFH[j] = Box * floor( prch[i] / Box );
                PFL[j] = PFL[j - 1] + Box;
                BarTurn[j] = BarDateTime[i];
                BarEnd[j] = BarDateTime[i];
                notifyArray[i] = 2;
            }
        }
    }
    else
    {
        if( prch[i] >= PFH[j] + Box )
        {
            PFH[j] = Box * floor( prch[i] / Box );
            BarEnd[j] = BarDateTime[i];
            notifyArray[i] = 3;
        }
        else
        {
            if( prcl[i] <= PFH[j] - nRev * Box )
            {
                j++;
                direction[j] = -1;
                PFH[j] = PFH[j - 1] - Box;
                PFL[j] = Box * ceil( prcl[i] / Box );
                BarTurn[j] = BarDateTime[i];
                BarEnd[j] = BarDateTime[i];
                notifyArray[i] = 4;
            }
        }
    }

    if( ZigDirection == ( -1 ) AND pivottype == "BoxZigZag" )
    {
        if( PFL[j] <= LastTr )
        {
            IsTr[j] = 1;
            iLastTr = j;
            LastTr = PFL[j];
        }
        else
            if( ( PFH[j] - LastTr ) / Box > Boxzz )
            {
                ZigDirection = 1;
                LastPk = PFH[j];
                iLastPk = j;
                IsPk[j] = 1;
                IsTr[iLastTr] = 2;
            }
    }
    else
    {
        if( PFH[j] >= LastPk )
        {
            iLastPk = j;
            LastPk = PFH[j];
            IsPk[j] = 1;
        }
        else
            if( ( LastPk - PFL[j] ) / Box > Boxzz )
            {
                ZigDirection = -1;
                LastTr = PFL[j];
                iLastTr = j;
                IsTr[j] = 1;
                IsPk[iLastPk] = 2;
            }
    }
}

delta = BarCount - j - 1;
direction = Ref( direction, -delta );
BarTurn = Ref( BarTurn, -delta );
BarEnd = Ref( BarEnd, -delta );
Hi = Ref( PFH, -delta ) + Box / 2;
Lo = Ref( PFL, -delta ) - Box / 2;
Cl = IIf( direction == 1, Hi, Lo );
Op = IIf( direction == 1, Cl - Box, Cl + Box );
Graphcolor = IIf( direction == 1, xcolor, ocolor );
IsTr = Ref( IsTr, -delta );
IsPk = Ref( IsPk, -delta );

// this code is used for the 1-box reversal mode
if( scaling == "Percentage" )
{
    uu = IIf( AlmostEqual( exp( Hi - Lo ), exp( Box ), 1e3 ), 1, 0 );
}
else
{
    uu = IIf( AlmostEqual( Hi - Lo, Box, 1e5 ), 1, 0 );
}

//----------------------------------------------------------
// STANDARD CHART
//----------------------------------------------------------
if( displaymode == "Standard Chart" )
{
    Graphcolor = IIf( direction == 1, xcolor, ocolor );
    PlotOHLC( Op, Hi, Lo, Cl, "", GraphColor, stylePointAndFigure | styleNoLabel, Null, Null, 0, 0, 1 );
}

//----------------------------------------------------------
// GFX CHART
//----------------------------------------------------------
if( displaymode == "GFX" )
{
    x1 = x2 = y1 = y2 = x3 = y3 = 0;
    PlotOHLC( Op, Hi, Lo, Cl, "", colorWhite, styleNoLine | styleNoLabel, Null, Null, 0, 0, 1 );

    cols = j;
    cols = Min( BarCount - fvb, cols ); // adjust cols to visible for speed

    GfxSetZOrder( -1 );
    GfxSelectFont( ft, Box / 2 );

    for( i = 0; i <= cols; i++ )
    {
        hh = Hi[BarCount - 1 + i - cols];
        ll = Lo[BarCount - 1 + i - cols];
        nn = round( SafeDivide( hh - ll, Box ) );
        dd = direction[BarCount - 1 + i - cols];

        if( dd == 1 )
            GfxSelectSolidBrush( xcolor );

        if( dd == ( -1 ) )
            GfxSelectSolidBrush( ocolor );

        for( k = 0; k < nn - 0; k++ )
        {
            x1 = BarCount - cols + i - 1 - 0.5;
            x2 = BarCount - cols + i - 1 + 0.5;
            y1 = ll + Box * ( k + 1 ); // Hi
            y2 = ll + Box * k; // Lo

            if( dd == 1 )
            {
                x3 = 0;
                y3 = 0;
                GfxRoundRect( x1, y1, x2, y2, x3, y3 );
            }

            if( dd == ( -1 ) )
            {
                x3 = rndbox;
                y3 = rndbox;
                GfxRoundRect( x1, y1, x2, y2, x3, y3 );
            }
        }
    }
}

//----------------------------------------------------------
// GFX CHART 2 - special case for a 1 Box Reversal
//----------------------------------------------------------
if( displaymode == "GFX 1 Box Reversal" )
{
    Hi_new = Lo_new = Op_new = Cl_new = direction_new = 0;
    BarTurn_new = 0;
    BarEnd_new = 0;
    cnt = 0;

    for( i = 0; i < BarCount; i++ )
    {
        if( Hi[i] > 0 OR Lo[i] > 0 )
        {
            if( uu[i] ) // 1 box column, next column needs to be shifted back
            {
                if( direction[i] == ( -1 ) AND i < BarCount - 1 )
                {
                    cnt++;
                    // shift next column above the "O"
                    Hi_new[cnt] = Hi[i + 1];
                    Lo_new[cnt] = Lo[i];
                    Cl_new[cnt] = Hi_new[cnt];
                    Op_new[cnt] = Lo_new[cnt];
                    direction_new[cnt] = 2; // 2 means up, therefor bottom box is red, the rest green
                    barturn_new[cnt] = barturn[i + 1];
                    // skip 1 bar
                    i++;
                }
                else
                    if( direction[i] == 1 AND i < BarCount - 1 )
                    {
                        cnt++;
                        // shift next column below the "X"
                        Hi_new[cnt] = Hi[i];
                        Lo_new[cnt] = Lo[i + 1];
                        Cl_new[cnt] = Lo_new[cnt];
                        Op_new[cnt] = Hi_new[cnt];
                        direction_new[cnt] = -2; // -2 mean down, therefor to box is green, the rest red
                        barturn_new[cnt] = barturn[i + 1];
                        // skip 1 bar
                        i++;
                    }
                    else
                        if( i == ( BarCount - 1 ) )
                        {
                            cnt++;
                            // normal column, no adjustment
                            Hi_new[cnt] = Hi[i];
                            Lo_new[cnt] = Lo[i];

                            if( direction[i] == ( -1 ) )
                            {
                                Cl_new[cnt] = Lo_new[cnt];
                                Op_new[cnt] = Cl_new[cnt] + box;
                            }

                            if( direction[i] == 1 )
                            {
                                Cl_new[cnt] = Hi_new[cnt];
                                Op_new[cnt] = Cl_new[cnt] - box;
                            }

                            direction_new[cnt] = direction[i];
                            barturn_new[cnt] = barturn[i];
                        }
            }
            else
            {
                cnt++;
                // normal column, no adjustment
                Hi_new[cnt] = Hi[i];
                Lo_new[cnt] = Lo[i];

                if( direction[i] == ( -1 ) )
                {
                    Cl_new[cnt] = Lo_new[cnt];
                    Op_new[cnt] = Cl_new[cnt] + box;
                }

                if( direction[i] == 1 )
                {
                    Cl_new[cnt] = Hi_new[cnt];
                    Op_new[cnt] = Cl_new[cnt] - box;
                }

                direction_new[cnt] = direction[i];
                barturn_new[cnt] = barturn[i];
            }
        }
    }

    cols = cnt;

    delta = BarCount - cols - 1;
    Hi_new = Ref( Hi_new, -delta );
    Lo_new = Ref( Lo_new, -delta );
    Op_new = Ref( Op_new, -delta );
    Cl_new = Ref( Cl_new, -delta );
    direction_new = Ref( direction_new, -delta );
    barturn_new = Ref( barturn_new, -delta );

    Hi_new = IIf( Hi_new == 0, Null, Hi_new );
    Lo_new = IIf( Lo_new == 0, Null, Lo_new );
    Cl_new = IIf( Cl_new == 0, Null, Cl_new );
    Op_new = IIf( Op_new == 0, Null, Op_new );
    direction_new = IIf( direction_new == 0, Null, direction_new );

    x1 = x2 = y1 = y2 = x3 = y3 = 0;

    PlotOHLC( Op_new, Hi_new, Lo_new, Cl_new, "", colorWhite, styleNoLine | styleNoLabel, Null, Null, 0, 0, 1 );

    cols = cnt;
    cols = Min( BarCount - fvb, cols ); // adjust cols to visible for speed

    GfxSetZOrder( -1 );
    GfxSelectFont( ft, Box / 2 );

    for( i = 0; i < cols; i++ )
    {
        shft = ( BarCount - cols + i );
        hh = Hi_new[shft];
        ll = Lo_new[shft];
        nn = round( SafeDivide( hh - ll, Box ) );
        dd = direction_new[shft];

        if( dd == 1 OR dd == ( -1 ) )
        {
            if( dd == 1 )
                GfxSelectSolidBrush( xcolor );

            if( dd == ( -1 ) )
                GfxSelectSolidBrush( ocolor );

            //_TRACE("nn: " + nn );
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = ll + Box * ( k + 1 ); // Hi
                y2 = ll + Box * k; // Lo

                if( dd == 1 )
                {
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }

                if( dd == ( -1 ) )
                {
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }

        // special case up
        if( dd == 2 )
        {
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = ll + Box * ( k + 1 );
                y2 = ll + Box * k;

                if( k == 0 )
                {
                    GfxSelectSolidBrush( ocolor );
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
                else
                {
                    GfxSelectSolidBrush( xcolor );
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }

        // special case down
        if( dd == ( -2 ) )
        {
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = hh - Box * k;
                y2 = hh - Box * ( k + 1 );

                if( k == 0 )
                {
                    GfxSelectSolidBrush( xcolor );
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
                else
                {
                    GfxSelectSolidBrush( ocolor );
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }
    }
}

if( scaling == "Percentage" )
{
    Last = Ref( LastValue( log( C ) ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots | styleNoLabel, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "<-----------------  " + NumToStr( exp( Last ), fmt ), ft, sz, BarCount + 1, LastValue( Last ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0, gridFlags = 1 ) ; //chartGridPercent
}
else
{
    // the last close
    Last = Ref( LastValue( C ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "<-----------------  " + NumToStr( Last, fmt ), ft, sz, BarCount + 1, LastValue( C ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0 ) ;
}


if( nRev == 1 AND displaymode != "GFX 1 Box Reversal" )
{
    PlotShapes( IIf( uu, shapeSmallCircle, shapeNone ), colorWhite, 0, Lo, Box_px / 2 );
    PlotShapes( IIf( uu, shapeHollowCircle, shapeNone ), colorBlack, 0, Lo, Box_px / 2 );
}

//----------------------------------------------------------
// GRID CONSTRUCTION
//----------------------------------------------------------
if( ShowAxis == 1 )
{
    GfxSetBkColor( bcolor );
    GfxSetTextColor( yaxcolor );
    GfxSelectFont( ft, sz, 700 );

    if( displaymode == "GFX 1 Box Reversal" )
    {
        barturn = barturn_new;
        j = cnt;
        direction = direction_new;
        direction = IIf( direction == 2, 1, IIf( direction == ( -2 ), -1, direction ) );
        Hi = Hi_new;
        Lo = Lo_new;
    }

    // Y-AXIS
    nrows = ceil( ( LastValue( Highest( Hi ) ) - LastValue( Lowest( Lo ) ) ) / box ) + 1;

    bx = LastValue( Lowest( Lo ) );
    GfxSelectPen( ColorRGB( 50, 50, 50 ) );

    nrows_visible = ceil( ( mxy - mny ) / box ) + 1;
    mult = round( nrows_visible / Min( nquot, nrows_visible ) );

    for( i = 0; i < nrows; i++ )
    {
        lvbs = bx + box * i;// + ( box );

        if( lvbs > mny AND lvbs < mxy )
        {
            // for placement
            ev = i % mult == 0;

            if( ShowGrid )
            {
                GfxMoveTo( fvb, lvbs );
                GfxLineTo( lvb, lvbs );
            }

            if( ev )
            {
                if( scaling == "Percentage" )
                {
                    nstr = " " + NumToStr( exp( lvbs ), fmt );
                }
                else
                {
                    lvbs = round( lvbs / TickSize ) * TickSize;
                    nstr = " " + NumToStr( lvbs, fmt );
                }

                GfxTextOut( nstr, lvb, lvbs );
            }
        }
    }

    if( ShowGrid )
    {
        for( i = fvb; i <= lvb; i++ )
        {
            GfxMoveTo( i - 0.5, mny );
            GfxLineTo( i - 0.5, mxy );
        }
    }

    // DATE AXIS
    GfxSelectFont( ft, sz, 600, False, False, orientation = 900 );
    GfxSetBkMode( 1 );
    GfxSetTextColor( colorAqua );

    cols = Min( Min( lvb, BarCount ) - fvb, j ); // adjust cols to visible for speed

    for( i = 1; i <= j; i++ )
    {
        shft = ( lvb - j + i - 1 );
        //mult = round( j / nquot );
        mult = round( cols / Min( nquot, cols ) );
        ev = i % mult == 0;

        if( ev )
        {
            str = DateTimeFormat( "%Y/%m/%d", BarTurn[shft] );

            if( str != "Invalid DateTime" AND barturn[shft] != 0 )
            {
                if( direction[shft] == 1 )
                {
                    GfxSetTextColor( xcolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
                else
                {
                    GfxSetTextColor( ocolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
            }
        }
    }
}

//----------------------------------------------------------
// PIVOTS
//----------------------------------------------------------
if( pivottype == "ZigZag" )
{
    if( zz > 0 )
    {
        pk = PeakBars( Hi, zz ) == 0;
        tr = TroughBars( Lo, zz ) == 0;
    }
}

if( pivottype == "Fractal" )
{
    pk = Hi > Ref( HHV( Hi, leftStrength * fact ), -1 ) AND Ref( HHV( Hi, rightStrength * fact ), rightStrength * fact ) <= Hi;
    tr = Lo < Ref( LLV( Lo, leftStrength * fact ), -1 ) AND Ref( LLV( Lo, rightStrength * fact ), rightStrength * fact ) >= Lo;
}

if( pivottype == "BoxZigZag" AND BoxZZ > 0 )
{
    pk = IsPk == 2;
    tr = IsTr == 2;
}

if( pivottype == "HHVLLV" )
{
    // find trend
    res = HHV( Hi, nbar );
    sup = LLV( Lo, nbar );
    crossup = Hi > Ref( res, -1 );
    crossdn = Lo < Ref( sup, -1 );

    if( handleBothOutside )
    {
        // if in H/L mode both crossup and crossdn at the same bar may occur.
        // if handleBothOutside is true then it will stay in the current trend
        // if handleBothOutside is false it will change the trend.
        crossup = IIf( ( crossup AND crossdn ) AND( BarsSince( Ref( crossup, -1 ) ) > BarsSince( Ref( crossdn, -1 ) ) ), 0, crossup );
        crossdn = IIf( ( crossup AND crossdn ) AND( BarsSince( Ref( crossdn, -1 ) ) > BarsSince( Ref( crossup, -1 ) ) ), 0, crossdn );
    }

    crossup = ExRem( crossup, crossdn );
    crossdn = ExRem( crossdn, crossup );
    trendup = Flip( crossup, crossdn );
    trenddn = Flip( crossdn, crossup );

    // find pivots
    rtrenddn = Reverse( trenddn );
    rtrendup = Reverse( trendup );
    l1 = LowestSince( trenddn AND Ref( trendup, -1 ), Lo );
    rL = Reverse( Lo );
    l2 = LowestSince( rtrenddn AND Ref( rtrendup, -1 ), rL );
    rl2 = Reverse( l2 );
    h1 = HighestSince( trendup AND Ref( trenddn, -1 ), Hi );
    rH = Reverse( Hi );
    h2 = HighestSince( rtrendup AND Ref( rtrenddn, -1 ), rH );
    rh2 = Reverse( h2 );
    tr = l1 == rl2 AND trenddn;
    pk = h1 == rh2 AND trendup;
    rpk = Reverse( pk );
    rtr = Reverse( tr );
    rpk = ExRem( rpk, rtr );
    rtr = ExRem( rtr, rpk );
    pk = Reverse( rpk );
    tr = Reverse( rtr );
}

for( i = 0; i < 3; i++ )
{
    VarSet( "px" + i, ValueWhen( pk, bi, i ) );
    VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
    VarSet( "ph" + i, ValueWhen( pk, Hi, i ) );
    VarSet( "tl" + i, ValueWhen( tr, Lo, i ) );
}

ll = tr AND tl1 < tl2;
hl = tr AND tl1 > tl2;
hh = pk AND ph1 > ph2;
lh = pk AND ph1 < ph2;
dt = pk AND ph1 == ph2;
db = tr AND tl1 == tl2;

if( showpivots )
{
    if( pivottype == "Fractal" )
    {
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( tr, bi ) > rightStrength * fact, xcolor, colorWhite ), 0, Lo, -Box_px );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( pk, bi ) > rightStrength * fact, ocolor, colorWhite ), 0, Hi, Box_px );
    }
    else
    {
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), colorGreen, 0, Lo, -Box_px );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), colorRed, 0, Hi, Box_px );
    }

    dist = 2;

    for( i = lvb; i > fvb; i-- )
    {
        {
            if( ll[i] )
                PlotTextSetFont( "LL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * dist );

            if( hl[i] )
                PlotTextSetFont( "HL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * dist );

            if( db[i] )
                PlotTextSetFont( "DB", "Arial Black", 8, i, Lo[i], colorLightBlue, colorDefault, -Box_px * dist );

            if( hh[i] )
                PlotTextSetFont( "HH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * dist - sz );

            if( lh[i] )
                PlotTextSetFont( "LH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * dist - sz );

            if( dt[i] )
                PlotTextSetFont( "DT", "Arial Black", 8, i, Hi[i], colorOrange, colorDefault, Box_px * dist - sz );
        }
    }
}


//----------------------------------------------------------
// TRENDLINES
//----------------------------------------------------------
if( showtrendlines AND trendlineDisplayType == "Original" )
{
    Hiprice = ValueWhen( pk, Hi );
    Hibar = BarsSince( pk );
    TLDn = Hiprice - ( Box * HiBar ) + box / 2;
    Loprice = ValueWhen( tr, Lo );
    Lobar = BarsSince( tr );
    TLUp = Loprice + ( Box * LoBar ) - box / 2;
    TLDn = IIf( TLDn >= Hi, TLDn, Null );
    TLUp = IIf( TLUp <= Lo, TLUp, Null );

    Plot( TLDn, "TLDn", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
    Plot( TLUp, "TLUp", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
}

if( showtrendlines AND trendlineDisplayType == "Alternative" )
{
    for( i = fvb; i <= lvb; i++ )
    {
        if( pk[i] )
        {
            Hiprice = ValueWhen( bi == i, Hi );
            Hibar = BarsSince( bi == i );
            TLDn = Hiprice - ( Box * HiBar ) + box / 2;;
            TLDn = IIf( TLDn > Hi, TLDn, Null );
            VarSet( "TLDn" + i, IIf( IsEmpty( TLDn ) AND !IsEmpty( Ref( TLDn, -1 ) ), Ref( TLDn, -1 ) - Box, TLDn ) );
            Plot( VarGet( "TLDn" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
            Buy = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), 1, Buy );
            BuyPrice = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), VarGet( "TLDn" + i ), BuyPrice );

            if( showbuysell )
                PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ) , colorAqua, 0, BuyPrice, 0 );
        }

        if( tr[i] )
        {
            Loprice = ValueWhen( bi == i, Lo );
            Lobar = BarsSince( bi == i );
            TLUp = Loprice + ( Box * LoBar ) - box / 2;;
            TLUp = IIf( TLUp < Lo, TLUp, Null );
            VarSet( "TLUp" + i, IIf( IsEmpty( TLUp ) AND !IsEmpty( Ref( TLUp, -1 ) ), Ref( TLUp, -1 ) + Box, TLUp ) );
            Plot( VarGet( "TLUp" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
            Short = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), 1, Short );
            ShortPrice = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), VarGet( "TLUp" + i ), ShortPrice );

            if( showbuysell )
                PlotShapes( IIf( Short, shapeDownArrow, shapeNone ) , colorOrange, 0, ShortPrice, 0 );
        }
    }
}

//----------------------------------------------------------
// TITLE
//----------------------------------------------------------
if( scaling == "Percentage" )
{
    str1 =
        EncodeColor( titleColor ) +
        "High " + NumToStr( exp( Hi ) , fmt )   + "\n" +
        "Low " + NumToStr( exp( Lo ), fmt ) + "\n" +
        "Close " + NumToStr( exp( Cl ), fmt ) + "\n" +
        "Open " + NumToStr( exp( Op ), fmt );
}
else
{
    str1 =
        EncodeColor( colorWhite ) +
        "High " + NumToStr( Hi , fmt )   + "\n" +
        "Low " + NumToStr( Lo, fmt ) + "\n" +
        "Close " + NumToStr( Cl, fmt ) + "\n" +
        "Open " + NumToStr( Op, fmt );
}

Title = EncodeColor( titleColor ) + "Point & Figure" + "\n" +
        Name() + " | " + FullName() + "\n" +
        EncodeColor( titleColor ) + "Mode: " + EncodeColor( titleHighlightColor ) + cmode + "\n" +
        EncodeColor( titleColor ) + "Box Type: " + EncodeColor( titleHighlightColor ) + ctype + "\n" +
        EncodeColor( titleColor ) + tbox + "\n" +
        "Reverse (Boxes) : " + EncodeColor( titleHighlightColor ) + nRev + EncodeColor( titleColor ) + "\n" +
        "Chart Timeframe (sec): "  + EncodeColor( titleHighlightColor ) + Interval() + "\n" +
        EncodeColor( titleColor ) + "Date at Turn: " + EncodeColor( titleHighlightColor ) + DateTimeFormat( "%Y/%m/%d", BarTurn[LastValue( SelectedValue( bi ) )] ) + "\n" +
        EncodeColor( titleColor ) + "Pivot Type: " + EncodeColor( titleHighlightColor ) + pivottype + "\n" +
        EncodeColor( titleColor ) + "Trendline Display Type: " + EncodeColor( titleHighlightColor ) + trendlineDisplaytype + "\n" +
        str1 + "\n" +
        "notifyarray " + notifyarray;


//----------------------------------------------------------
// EXPLORATION
//----------------------------------------------------------
if( Status( "action" ) == actionExplore )
{
    snd = 1;

    if( snd )
    {
        AlertIf( LastValue( notifyarray ) OR LastValue( Buy ) OR LastValue( Short ), "SOUND C:\\Windows\\Media\\Alarm03.wav", "Audio alert", 1, 15, 1 );
    }

    Filter = notifyarray OR Buy OR Short;
    AddColumn( notifyarray == 1, "New Box Down", 1.2, colorBlack, IIf( notifyarray == 1, colorRed, colorWhite ) );
    AddColumn( notifyarray == 2, "Reversal Up", 1.2, colorBlack, IIf( notifyarray == 2, colorBrightGreen, colorWhite ) );
    AddColumn( notifyarray == 3, "New Box Up", 1.2, colorBlack, IIf( notifyarray == 3, colorBrightGreen, colorWhite ) );
    AddColumn( notifyarray == 4, "Reversal Down", 1.2, colorBlack, IIf( notifyarray == 4, colorRed, colorWhite ) );
    AddColumn( Buy, "Buy", 1.2, colorBlack, IIf( Buy, colorBrightGreen, colorWhite ) );
    AddColumn( Short, "Sell", 1.2, colorBlack, IIf( Short, colorRed, colorWhite ) );
}

_SECTION_END();

_SECTION_BEGIN( "ABCD for PnF" );

/*
ratio labels
AB_AX means the ratio (A-B)/(A-X). It is the retracement of A to B over the price range A to X
BC_AB means the ratio (C-B)/(A-B)
CD_BC means the ratio (C-D)/(C-B)
AD_AX means the ratio (A-D)/(A-X)
*/

// PARAMETERS
showABCD = ParamToggle( "Show ABCD", "Off|On", 1 );
bu = ParamToggle( "Bullish Pattern", "Off|On", 1 );
be = ParamToggle( "Bearish Pattern", "Off|On", 1 );
showReciprocalABCD = ParamToggle( "Show Reciprocal ABCD", "Off|On", 0 );
st = Param( "Separation of Letters", 3, 1, 10, 1 );
dl = Param( "Dashed Line Number", 2, 1, 4, 1 );
showDotsAtD = ParamToggle( "Show Dots at D", "Off|On", 1 );
showPatternName = ParamToggle( "Show Pattern Name", "Off|On", 1 );
loc = Param( "Pattern Name Position", 6, 1, 10, 0.1 );
deviation = Param( "Deviation", 15, 0.1, 100, 0.1 );
fillPRZ = ParamToggle( "Fill PRZ area with color", "Off|On", 0 );

// ABCD
ABCD_MinAC = 0.382 - 0.382 * deviation / 100; // retrace from B to C over distance A to B
ABCD_MaxAC = 0.886 + 0.886 * deviation / 100;
ABCD_MinBD = 1.13 - 1.13 * deviation / 100; // retrace from C to D over distance B to C
ABCD_MaxBD = 2.618 + 2.618 * deviation / 100;

// Reciprocal ABCD
ReciprocalABCD_MinAC = 1.13 - 1.13 * deviation / 100; // retrace from B to C over distance A to B
ReciprocalABCD_MaxAC = 3.618 + 3.618 * deviation / 100;
ReciprocalABCD_MinBD = 0.382 - 0.382 * deviation / 100; // retrace from C to D over distance B to C
ReciprocalABCD_MaxBD = 0.886 + 0.886 * deviation / 100;

// DECLARE GLOBAL ARRAYS
Bull = Bull4 = Bear = Bear4 = 0;
AD_AX_min = AD_AX_max = 0;
CD_BC_min = CD_BC_max = 0;
BullABCD = BearABCD = 0;
topBox_bu = topBox_be = botBox_bu = botBox_be = 0;

// 'clean' the pivots function
// meaning make the pivots alternate like pk-tr-pk-tr-pk-tr-etc..
procedure alternate_proc( pk, tr )
{
    global pkg;
    global trg;

    // alternate pivots
    pkg = pk;
    trg = tr;
    pkHigh = 0;
    pkHighIndex = 0;
    trLow = 1e10;
    trLowIndex = 0;

    for( i = fvb; i <= lvb; i++ )
    {
        // peak and trough on same bar
        if( pk[i] AND tr[i] )
        {
            if( pkHighIndex > trLowIndex )
            {
                pkg[i] = 0;
                trg[i] = 1;

                if( Lo[i] <= trLow )
                {
                    pkHigh = 0;
                    pkHighIndex = 0;
                    trLow = Lo[i];
                    trLowIndex = i;
                }
                else
                {
                    pkHigh = 0;
                    pkHighIndex = 0;
                }
            }
            else
                if( pkHighIndex < trLowIndex )
                {
                    pkg[i] = 1;
                    trg[i] = 0;

                    if( Hi[i] >= pkHigh )
                    {
                        trLow = 1e10;
                        trLowIndex = 0;
                        pkHigh = Hi[i];
                        pkHighIndex = i;
                    }
                    else
                    {
                        trLow = 1e10;
                        trLowIndex = 0;
                    }
                }
                else
                {
                    pkg[i] = 0;
                    trg[i] = 0;
                }
        }
        else

            // consecutive higher peak found
            if( pk[i] AND Hi[i] >= pkHigh )
            {
                // disable the previous lower peak
                pkg[pkHighIndex] = 0;
                // update new peak variables
                pkHigh = Hi[i];
                pkHighIndex = i;
                // reset trough variables
                trLow = 1e10;
                trLowIndex = 0;
            }
            else

                // consecutive lower peak found
                if( pk[i] AND Hi[i] < pkHigh )
                {
                    // disable this peak
                    pkg[i] = 0;
                    // reset trough variables
                    trLow = 1e10;
                    trLowIndex = 0;
                }
                else

                    // consecutive lower trough found
                    if( tr[i] AND Lo[i] <= trLow )
                    {
                        // disable the previous higher trough
                        trg[trLowIndex] = 0;
                        // update trough variables
                        trLow = Lo[i];
                        trLowIndex = i;
                        // reset peak variables
                        pkHigh = 0;
                        pkHighIndex = 0;
                    }
                    else

                        // consecutive higher trough found
                        if( tr[i] AND Lo[i] > trLow )
                        {
                            // disable this trough
                            trg[i] = 0;
                            // reset peak variables
                            pkHigh = 0;
                            pkHighIndex = 0;
                        }
    }
}

if( pivottype == "Fractal" )
{
	// run clean pivots
	alternate_proc( pk, tr );
	pk = pkg;
	tr = trg;
}

// BULLISH AND BEARISH PATTERN PREPARATIONS
pkH1 = ValueWhen( pk, Hi );
pkBar1 = ValueWhen( pk, bi );
pkH2 = ValueWhen( pk, Hi, 2 );
pkBar2 = ValueWhen( pk, bi, 2 );
trL1 = ValueWhen( tr, Lo );
trBar1 = ValueWhen( tr, bi );
trL2 = ValueWhen( tr, Lo, 2 );
trBar2 = ValueWhen( tr, bi, 2 );

PTvalid_bu = ( pkBar1 > trBar1 AND trBar1 > pkBar2 AND pkbar2 > trBar2 ) AND pk;

AX_bu = pkH2 - trL2;
AB_bu = pkH2 - trL1;
BC_bu = pkH1 - trL1;

AB_AX_bu = SafeDivide( AB_bu, AX_bu );
BC_AB_bu = SafeDivide( BC_bu, AB_bu );

PTvalid_be = ( trBar1 > pkBar1 AND pkBar1 > trBar2 AND trBar2 > pkBar2 ) AND tr;

AX_be = pkH2 - trL2;
AB_be = pkH1 - trL2;
BC_be = pkH1 - trL1;

AB_AX_be = SafeDivide( AB_be, AX_be );
BC_AB_be = SafeDivide( BC_be, AB_be );

// PATTERN CALCULATION AND DISPLAY FUNCTIONS
function GfxConvertBarToPixelX( bar )
{
    local fvb1, lvb1;

    lvb1 = Status( "lastvisiblebar" );
    fvb1 = Status( "firstvisiblebar" );
    pxchartleft = Status( "pxchartleft" );
    pxchartwidth = Status( "pxchartwidth" );

    return pxchartleft + bar  * pxchartwidth / ( lvb1 - fvb1 + 1 );
}

function GfxConvertValueToPixelY2( Value )
{
    local Miny, Maxy, pxchartbottom, pxchartheight;

    Miny = Status( "axisminy" );
    Maxy = Status( "axismaxy" );

    pxchartbottom = Status( "pxchartbottom" );
    pxchartheight = Status( "pxchartheight" );

    return pxchartbottom - floor( 0.5 + ( Value - Miny ) * SafeDivide( pxchartheight, Maxy - Miny ) );
}

function CalculateAngle( x1, y1, x2, y2 )
{
    // calculate angle of text
    x1 = GfxConvertBarToPixelX( x1 );
    y1 = GfxConvertValueToPixelY2( y1 );
    x2 = GfxConvertBarToPixelX( x2 );
    y2 = GfxConvertValueToPixelY2( y2 );
    onerad = 57.2957795;
    angle = 10 * onerad * atan( SafeDivide( y2 - y1,  x2 - x1 ) ) * -1;
    return angle;
}

function drawABCDPattern( Abar, A, Bbar, B, C1bar, C1, Dbar, D, BCdAB, BCdCD, topBox, botBox, patternName, clr1, clr2, clr3, fac, dir )
{
    GfxSetZOrder( -1 );
    GfxSelectPen( clr1, 2, 0 );
    GfxMoveTo( Abar, A );
    GfxLineTo( Bbar, B );
    GfxLineTo( C1bar, C1 );
    GfxLineTo( Dbar, D );
    GfxSelectPen( clr1, 1, dl );
    GfxMoveTo( Abar, A );
    GfxLineTo( C1bar, C1 );
    GfxMoveTo( Bbar, B );
    GfxLineTo( Dbar, D );

    PlotTextSetFont( NumToStr( BCdAB, 1.2 ), ft, sz, ( C1bar + Abar ) / 2, ( C1 + A ) / 2, clr1, colorDefault, 0 );
    PlotTextSetFont( NumToStr( BCdCD, 1.2 ), ft, sz, ( Bbar + Dbar ) / 2, ( B + D ) / 2, clr1, colorDefault, 0 );
    PlotTextSetFont( "A", ft, sz, Abar - st, A, clr1, colorDefault, sz * dir );
    PlotTextSetFont( "B", ft, sz, Bbar - st, B, clr1, colorDefault, -sz * dir );
    PlotTextSetFont( "C", ft, sz, C1bar + st, C1, clr1, colorDefault, sz * dir );
    PlotTextSetFont( "D", ft, sz, Dbar + st, D, clr1, colorDefault, - sz * dir );

    if( showPatternName )
    {
        //PlotTextSetFont( "" + patternName, ft, sz, Abar, A, clr1, colorDefault, sz * fac );

        if( dir == 1 )
        {
            angle = calculateAngle( ABar, A, C1Bar, C1 );
            GfxSelectFont( ft, sz, 400, False, False, angle );
            GfxSetCoordsMode( 1 );
            GfxSetTextColor( clr1 );
            GfxTextOut( "" + patternName, Abar + ( C1bar - Abar ) / loc, A + ( C1 - A ) / loc );
        }

        if( dir == ( -1 ) )
        {
            angle = calculateAngle( BBar, B, DBar, D );
            GfxSelectFont( ft, sz, 400, False, False, angle );
            GfxSetCoordsMode( 1 );
            GfxSetTextColor( clr1 );
            GfxTextOut( "" + patternName, Bbar + ( Dbar - Bbar ) / loc, B + ( D - B ) / loc );
        }
    }

    // draw PRZ rectangle
    GfxSetZOrder( -4 );
    GfxSelectSolidBrush( clr3 );
    x0 = C1bar;
    y0 = topBox;
    x1 = Dbar;
    y1 = botBox;

    if( fillPRZ )
    {
        GfxSelectPen( clr2, 1, 0 );
        GfxRectangle( x0, y0, x1, y1 );
    }
    else
    {
        GfxSelectPen( clr2, 1, 0 );
        GfxMoveTo( x0, y0 );
        GfxLineTo( x0, y1 );
        GfxLineTo( x1, y1 );
        GfxLineTo( x1, y0 );
        GfxLineTo( x0, y0 );
    }
}

function calculateBullishABCDPattern( MinAC, MaxAC, MinBD, MaxBD, pattername )
{
    Bull4 = PTvalid_bu AND( BC_AB_bu > MinAC ) AND( BC_AB_bu < MaxAC );

    dHigh = HighestSince( Bull4, Hi );
    dLow = LowestSince( Bull4, Lo );

    pC = ValueWhen( Bull4, pkH1 );
    pB = ValueWhen( Bull4, trL1 );
    pA = ValueWhen( Bull4, pkH2 );
    CB = pC - pB;

    CD_BC_min = pC - CB * MinBD;
    CD_BC_max = pC - CB * MaxBD;

    Bull = IIf( ( dLow < CD_BC_min ) AND( dLow > CD_BC_max )
                AND( dHigh <= pC ) AND( dLow == Lo ),
                True, False );

    if( pattername == "ABCD" )
        Bull = Bull AND( dLow < pB );

    if( showDotsAtD )
        PlotShapes( IIf( Bull, shapeSmallCircle, Null ), ColorRGB( 64, 128, 64 ), 0, Lo, -20 );
}

function calculateBearishABCDPattern( MinAC, MaxAC, MinBD, MaxBD, patternname )
{
    Bear4 = PTvalid_be AND( BC_AB_be > MinAC ) AND( BC_AB_be < MaxAC );

    dHigh = HighestSince( Bear4, Hi );
    dLow = LowestSince( Bear4, Lo );

    pA = ValueWhen( Bear4, trL2 );
    pB = ValueWhen( Bear4, pkH1 );
    pC = ValueWhen( Bear4, trL1 );
    CB = pB - pC;

    CD_BC_min = pC + CB * MinBD;
    CD_BC_max = pC + CB * MaxBD;

    Bear = IIf( ( dHigh > CD_BC_min ) AND( dHigh < CD_BC_max )
                AND( dLow >= pC ) AND( dHigh == Hi ),
                True, False );

    if( patternname == "ABCD" )
        Bear = Bear AND( dHigh > pB );

    if( showDotsAtD )
        PlotShapes( IIf( Bear, shapeSmallCircle, Null ), ColorRGB( 128, 128, 64 ), 0, Hi, 20 );
}

function showBullishABCDPattern( patternName )
{
    BullHar4 = Bull4;
    BullHar = Bull;

    if( lvb > 0 )
    {
        rBullHar4 = Reverse( BullHar4, 0, lvb );
        rBullHar = Reverse( BullHar, 0, lvb );
        rBullHar = ExRem( rBullHar, rBullHar4 );
        BullHar = Reverse( rBullHar, 0, lvb );
    }

    A = ValueWhen( BullHar4, pkH2 );
    Abar = ValueWhen( BullHar4, pkbar2 );
    B = ValueWhen( BullHar4, trL1 );
    Bbar = ValueWhen( BullHar4, trbar1 );
    C1 = ValueWhen( BullHar4, pkH1 );
    C1bar = ValueWhen( BullHar4, pkbar1 );
    D = ValueWhen( BullHar, Lo );
    Dbar = ValueWhen( BullHar, bi );
    BCdAB = SafeDivide( C1 - B, A - B );
    BCdCD = SafeDivide( C1 - D, C1 - B );

    for( i = lvb; i > fvb; i-- )
    {
        bullcolor = xcolor;
        linethick = 1;

        if( BullHar[i] AND bu )
        {
            drawABCDPattern( Abar[i], A[i], Bbar[i], B[i], C1bar[i], C1[i], Dbar[i], D[i], BCdAB[i], BCdCD[i],
                             CD_BC_min[i], CD_BC_max[i], patternName, xcolor, ColorRGB( 0, 80, 0 ), ColorRGB( 0, 10, 0 ), 1, 1 );
        }
    }
}

function showBearishABCDPattern( patternName )
{
    BearHar4 = Bear4;
    BearHar = Bear;

    if( lvb > 0 )
    {
        rBearHar4 = Reverse( BearHar4, 0, lvb );
        rBearHar = Reverse( BearHar, 0, lvb );
        rBearHar = ExRem( rBearHar, rBearHar4 );
        BearHar = Reverse( rBearHar, 0, lvb );
    }

    A = ValueWhen( BearHar4, trL2 );
    Abar = ValueWhen( BearHar4, trbar2 );
    B = ValueWhen( BearHar4, pkH1 );
    Bbar = ValueWhen( BearHar4, pkbar1 );
    C1 = ValueWhen( BearHar4, trL1 );
    C1bar = ValueWhen( BearHar4, trbar1 );
    D = ValueWhen( BearHar, Hi );
    Dbar = ValueWhen( BearHar, bi );
    BCdAB = SafeDivide( B - C1, B - A );
    BCdCD = SafeDivide( D - C1, B - C1 );

    for( i = lvb; i > fvb; i-- )
    {
        bearcolor = ocolor;
        linethick = 1;

        if( BearHar[i] AND be )
        {
            drawABCDPattern( Abar[i], A[i], Bbar[i], B[i], C1bar[i], C1[i], Dbar[i], D[i], BCdAB[i], BCdCD[i],
                             CD_BC_min[i], CD_BC_max[i], patternName, ocolor, ColorRGB( 80, 0, 0 ), ColorRGB( 10, 0, 0 ), -2, -1 );
        }
    }
}

if( bu )
{
    if( showABCD )
    {
        // Bullish ABCD Pattern
        Bull = Bull4 = 0;
        CD_BC_min = CD_BC_max = 0;
        calculateBullishABCDPattern( ABCD_MinAC, ABCD_MaxAC, ABCD_MinBD, ABCD_MaxBD, "ABCD" );
        showBullishABCDPattern( "Bullish ABCD" );
        BullABCD = Bull;
    }

    if( showReciprocalABCD )
    {
        // Bullish Reciprocal ABCD Pattern
        Bull = Bull4 = 0;
        CD_BC_min = CD_BC_max = 0;
        calculateBullishABCDPattern( ReciprocalABCD_MinAC, ReciprocalABCD_MaxAC, ReciprocalABCD_MinBD, ReciprocalABCD_MaxBD, "ReciprocalABCD" );
        showBullishABCDPattern( "Bullish Reciprocal ABCD" );
        BullReciprocalABCD = Bull;
    }
}

if( be )
{
    if( showABCD )
    {
        // Bearish ABCD Pattern
        Bear = Bear4 = 0;
        CD_BC_min = CD_BC_max = 0;
        calculateBearishABCDPattern( ABCD_MinAC, ABCD_MaxAC, ABCD_MinBD, ABCD_MaxBD, "ABCD" );
        showBearishABCDPattern( "Bearish ABCD" );
        BearABCD = Bear;
    }

    if( showReciprocalABCD )
    {
        // Bearish Reciprocal ABCD Pattern
        Bear = Bear4 = 0;
        CD_BC_min = CD_BC_max = 0;
        calculateBearishABCDPattern( ReciprocalABCD_MinAC, ReciprocalABCD_MaxAC, ReciprocalABCD_MinBD, ReciprocalABCD_MaxBD, "ReciprocalABCD" );
        showBearishABCDPattern( "Bearish Reciprocal ABCD" );
        BearReciprocalABCD = Bear;
    }

}

_SECTION_END();

4 Likes

Thanks for sharing the code.

Only a minor sugestion on scale Y so it doesn't take too much space to show last price

Below only code changed.

if( scaling == "Percentage" )
{
    Last = Ref( LastValue( log( C ) ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots | styleNoLabel, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "" + NumToStr( exp( Last ), fmt ), ft, sz, BarCount + 1, YLastPrice = LastValue( Last ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0, gridFlags = 1 ) ; //chartGridPercent
}
else
{
    // the last close
    Last = Ref( LastValue( C ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "" + NumToStr( Last, fmt ), ft, sz, BarCount + 1, YLastPrice = LastValue( C ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0 ) ;
}


if( nRev == 1 AND displaymode != "GFX 1 Box Reversal" )
{
    PlotShapes( IIf( uu, shapeSmallCircle, shapeNone ), colorWhite, 0, Lo, Box_px / 2 );
    PlotShapes( IIf( uu, shapeHollowCircle, shapeNone ), colorBlack, 0, Lo, Box_px / 2 );
}

//----------------------------------------------------------
// GRID CONSTRUCTION
//----------------------------------------------------------
if( ShowAxis == 1 )
{
    GfxSetBkColor( bcolor );
    GfxSetTextColor( yaxcolor );
    GfxSelectFont( ft, sz, 700 );

    if( displaymode == "GFX 1 Box Reversal" )
    {
        barturn = barturn_new;
        j = cnt;
        direction = direction_new;
        direction = IIf( direction == 2, 1, IIf( direction == ( -2 ), -1, direction ) );
        Hi = Hi_new;
        Lo = Lo_new;
    }

    // Y-AXIS
    nrows = ceil( ( LastValue( Highest( Hi ) ) - LastValue( Lowest( Lo ) ) ) / box ) + 1;

    bx = LastValue( Lowest( Lo ) );
    GfxSelectPen( ColorRGB( 50, 50, 50 ) );

    nrows_visible = ceil( ( mxy - mny ) / box ) + 1;
    mult = round( nrows_visible / Min( nquot, nrows_visible ) );
	ii = 0;
    for( i = 0; i < nrows; i++ )
    {
        lvbs = bx + box * i;// + ( box );

        if( lvbs > mny AND lvbs < mxy )
        {
            // for placement
            ev = ii % mult == 0;

            if( ShowGrid )
            {
                GfxMoveTo( fvb, lvbs );
                GfxLineTo( lvb, lvbs );
            }

            if( ev )
            {
                if( scaling == "Percentage" )
                {
                    nstr = " " + NumToStr( exp( lvbs ), fmt );
					toonear = 0.0055;
                }
                else
                {
                    lvbs = round( lvbs / TickSize ) * TickSize;
                    nstr = " " + NumToStr( lvbs, fmt );
					toonear = 0.55;
                }
				if( lvb < BarCount - 2 OR lvbs - toonear > YLastPrice OR lvbs + toonear < YLastPrice )
					GfxTextOut( nstr, lvb, lvbs );
				else
					ii--;
            }
        }
		ii++;
    }

    if( ShowGrid )
    {
        for( i = fvb; i <= lvb; i++ )
        {
            GfxMoveTo( i - 0.5, mny );
            GfxLineTo( i - 0.5, mxy );
        }
    }

    // DATE AXIS
    GfxSelectFont( ft, sz, 600, False, False, orientation = 899 );
    GfxSetBkMode( 1 );
    GfxSetTextColor( colorAqua );

    cols = Min( Min( lvb, BarCount ) - fvb, j ); // adjust cols to visible for speed

    for( i = 1; i <= j; i++ )
    {
        shft = ( lvb - j + i - 1 );
        //mult = round( j / nquot );
        mult = round( cols / Min( nquot, cols ) );
        ev = i % mult == 0;

        if( ev )
        {
            str = DateTimeFormat( "%Y/%m/%d", BarTurn[shft] );

            if( str != "Invalid DateTime" AND barturn[shft] != 0 )
            {
                if( direction[shft] == 1 )
                {
                    GfxSetTextColor( xcolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
                else
                {
                    GfxSetTextColor( ocolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
            }
        }
    }
}


1 Like

thank you, I put it in.

1 Like

the Point&Figure is actually the same as a Renko chart (to my knowledge) it is just plotted differently. So since we have the P&F chart already we can derive the Renko from that. See chart below. Every box is plotted on a new bar. So the only thing that is tricky is that the number of boxes may exceed Barcount. That just means you need to start drawing not from the beginning of the P&F but you have to calculate the correct bar so the RENKO will fit within Barcount bars. I think I fixed this correctly.

Will have to adjust stuff with axis still. Will post in couple of days probably.

The chart shows P&F on the top and on the bottom the renko with the same settings. So the Renko shows about the last 6 bars of the P&F

2 Likes

code is below. So I added RENKO. In the Parameter window you chose it in display mode. Renko has no trendlines for now. But pivots can be calculated and therefore you can drag the ABCD code on top (second code posted below). Will wait for comments. It probably can be coded with arrays only but for now I used a loop.

_SECTION_BEGIN( "Point & Figure" );
RequestMouseMoveRefresh();
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

scaling = ParamList( "Scaling Method", "Traditional|Percentage", 1 );
hclmode = ParamList( "Price Mode", "HL|C", 0 );
displaymode = ParamList( "Display Mode", "Standard Chart|GFX|GFX 1 Box Reversal|RENKO", 0 );
ft = ParamList( "Font Type", "Tahoma Bold|Arial Black|Verdana Bold|Courier New Bold|Comic Sans MS Bold|Arial Bold|Candara Bold|Calibri Bold|Constantia Bold|Georgia Bold|Gadugi Bold|Segoe UI Bold", 0 );
sz = Param( "Font Size", 11, 6, 50, 1 );
Box = Param( "Box", 20, 1, 2000, 1 );
nRev = Param( "Reverse Number of Boxes", 3, 1, 10, 1 );
nquot = Param( "Number of Quotes Shown on Axis", 10, 5, 50 );
ShowGrid = ParamToggle( "Show Grid", "No|Yes", 1 );
ShowAxis = ParamToggle( "Show Axis", "No|Yes", 1 );
showpivots = ParamToggle( "Show Pivots", "No|Yes", 1 );
showtrendlines = ParamToggle( "Show Trendlines", "No|Yes", 1 );
pivottype = ParamList( "Pivot Type", "ZigZag|Fractal|HHVLLV", 2 );
trendlineDisplayType = ParamList( "Trendline Display Type", "Original|Alternative", 0 );
// parameter for zigzag pivots
zz = Param( "ZigZag Change Amount for Trendlines (%)", 2, 0.1, 100, 0.1 );
// parameters for fractal pivots
rightStrength = Param( "Fractal Pivot Right side Strength (bars)", 5, 2, 50, 1 );
leftStrength = Param( "Fractal Pivot Left side Strength (bars)", 10, 2, 50, 1 );
fact = Param( "Fractal Factor", 2, 1, 20, 1 );
// parameters for HHVLLV trendlines
nbar = Param( "Swing number of Bars", 10, 1, 50, 1 );
handleBothOutside = ParamToggle( "Long AND Short signal at the SAME bar", "Change Trend|Stay with current Trend", 0 );
// buy sell signals
showbuysell = ParamToggle( "Show Buy Sell Signals", "No|Yes", 0 ) ;

// color definitions
xcolor = ParamColor( "X_Color", colorBrightGreen );
ocolor = ParamColor( "O_Color", colorRed );
bcolor = ParamColor( "Background Color", colorBlack );
yaxcolor = ParamColor( "Y Axis Color", colorWhite );
titleColor = ParamColor( "Title Color", colorGold );
titleHighlightColor = ParamColor( "Title Highlight Color", colorAqua );

rndbox = 30;
Lx = LastValue( bi );

SetChartBkColor( bcolor );
GfxSetZOrder( -5 );
GfxSetCoordsMode( 1 );

BarDateTime = DateTime();
BarTurn = 0;
BarEnd = 0;

mny = Status( "axisminy" );
mxy = Status( "axismaxy" );
pxb = Status( "pxchartbottom" );
pxh = Status( "pxchartheight" );
Buy = Sell = Short = Cover = BuyPrice = SellPrice = ShortPrice = CoverPrice = 0;
pk = tr = 0;

if( displaymode == "GFX 1 Box Reversal" AND nRev > 1 )
{
    displaymode = "GFX";
}

// set your TickSize here or put it in the information Window
// example for NQ and ES futures ---> TickSize = 0.25;
// if ticksize is not set in code or information window use 0.01
// Ticksize = 0.25   // I commented it out because I put it in the information window
if( TickSize == 0 )
{
    TickSize = 0.01;
}

// calculate format for display purposes
fmt = "" + TickSize;
fmt = StrReplace( fmt, ".", "," );
fmt = StrExtract( fmt, 1 );
fmt = "1" + "." + StrLen( fmt );
fmt = StrToNum( fmt );

switch( hclmode )
{
case "HL":
    prch = H;
    prcl = L;
    cmode = "High / Low Price";
    break;

case "C":
    prch = C;
    prcl = C;
    cmode = "Close Price";
    break;
}

switch( scaling )
{
case "Traditional":
    Box =  Box * TickSize;
    ctype = "Tradional (Boxsize in Points, Box x TickSize)";
    tbox = "True Box Value in Points: " + EncodeColor( titleHighlightColor ) +  NumToStr( Box, fmt ) + " Points" + EncodeColor( titleColor );
    break;

case "Percentage":
    Box = Box / 100;
    ctype = "Percentage (Boxsize in Percent)";
    tbox = "True Box Value in Percent: " + EncodeColor( titleHighlightColor ) + Box + " %" + EncodeColor( titleColor );
    break;
}

function GfxConvertValueToPixelY( Value )
{
    return Value * SafeDivide( pxh, mxy - mny );
}

PFL = PFH = 0;
Box_px = cols = 0;

if( scaling == "Percentage" )
{
    Box = log( 1 + Box / 100 );
    prch = log( prch );
    prcl = log( prcl );
    PFL[0] = Box * ceil( prcl[0] / Box ) + Box;
    PFH[0] = Box * floor( prch[0] / Box );
    zz = log( zz );

    // box size in pixels
    Box_px = GfxConvertValueToPixelY( Box );
}
else
{
    PFL[0] = Box * ceil( prcl[0] / Box ) + Box;
    PFH[0] = Box * floor( prch[0] / Box );

    // box size in pixels
    Box_px = GfxConvertValueToPixelY( Box );
}

direction = -1;
notifyArray = 0;

for( i = 1; i < BarCount; i++ )
{
    if( direction[cols] == ( -1 ) )
    {
        if( prcl[i] <= PFL[cols] - Box )
        {
            PFL[cols] = Box * ceil( prcl[i] / Box );
            BarEnd[cols] = BarDateTime[i];
            notifyArray[i] = 1;
        }
        else
        {
            if( prch[i] >= PFL[cols] + nRev * Box )
            {
                cols++;
                direction[cols] = 1;
                PFH[cols] = Box * floor( prch[i] / Box );
                PFL[cols] = PFL[cols - 1] + Box;
                BarTurn[cols] = BarDateTime[i];
                BarEnd[cols] = BarDateTime[i];
                notifyArray[i] = 2;
            }
        }
    }
    else
    {
        if( prch[i] >= PFH[cols] + Box )
        {
            PFH[cols] = Box * floor( prch[i] / Box );
            BarEnd[cols] = BarDateTime[i];
            notifyArray[i] = 3;
        }
        else
        {
            if( prcl[i] <= PFH[cols] - nRev * Box )
            {
                cols++;
                direction[cols] = -1;
                PFH[cols] = PFH[cols - 1] - Box;
                PFL[cols] = Box * ceil( prcl[i] / Box );
                BarTurn[cols] = BarDateTime[i];
                BarEnd[cols] = BarDateTime[i];
                notifyArray[i] = 4;
            }
        }
    }
}

delta = BarCount - cols - 1;
directionr = direction;
BarTurnr = BarTurn;
direction = Ref( direction, -delta );
BarTurn = Ref( BarTurn, -delta );
BarEnd = Ref( BarEnd, -delta );
Hi = Ref( PFH, -delta ) + Box / 2;
Lo = Ref( PFL, -delta ) - Box / 2;
Cl = IIf( direction == 1, Hi, Lo );
Op = IIf( direction == 1, Cl - Box, Cl + Box );
Graphcolor = IIf( direction == 1, xcolor, ocolor );
direction_renko = 0;

// this code is used for the 1-box reversal mode
if( scaling == "Percentage" )
{
    uu = IIf( AlmostEqual( exp( Hi - Lo ), exp( Box ), 1e3 ), 1, 0 );
}
else
{
    uu = IIf( AlmostEqual( Hi - Lo, Box, 1e5 ), 1, 0 );
}

//----------------------------------------------------------
// STANDARD CHART
//----------------------------------------------------------
if( displaymode == "Standard Chart" )
{
    Graphcolor = IIf( direction == 1, xcolor, ocolor );
    PlotOHLC( Op, Hi, Lo, Cl, "", GraphColor, stylePointAndFigure | styleNoLabel, Null, Null, 0, 0, 1 );
}

//----------------------------------------------------------
// GFX CHART
//----------------------------------------------------------
if( displaymode == "GFX" )
{
    x1 = x2 = y1 = y2 = x3 = y3 = 0;
    PlotOHLC( Op, Hi, Lo, Cl, "", colorWhite, styleNoLine | styleNoLabel, Null, Null, 0, 0, 1 );

    //cols = j;
    cols = Min( BarCount - fvb, cols ); // adjust cols to visible for speed

    GfxSetZOrder( -1 );
    GfxSelectFont( ft, Box / 2 );

    for( i = 0; i <= cols; i++ )
    {
        hh = Hi[BarCount - 1 + i - cols];
        ll = Lo[BarCount - 1 + i - cols];
        nn = round( SafeDivide( hh - ll, Box ) );
        dd = direction[BarCount - 1 + i - cols];

        if( dd == 1 )
            GfxSelectSolidBrush( xcolor );

        if( dd == ( -1 ) )
            GfxSelectSolidBrush( ocolor );

        for( k = 0; k < nn - 0; k++ )
        {
            x1 = BarCount - cols + i - 1 - 0.5;
            x2 = BarCount - cols + i - 1 + 0.5;
            y1 = ll + Box * ( k + 1 ); // Hi
            y2 = ll + Box * k; // Lo

            if( dd == 1 )
            {
                x3 = 0;
                y3 = 0;
                GfxRoundRect( x1, y1, x2, y2, x3, y3 );
            }

            if( dd == ( -1 ) )
            {
                x3 = rndbox;
                y3 = rndbox;
                GfxRoundRect( x1, y1, x2, y2, x3, y3 );
            }
        }
    }
}

//----------------------------------------------------------
// GFX CHART 2 - special case for a 1 Box Reversal
//----------------------------------------------------------
if( displaymode == "GFX 1 Box Reversal" )
{
    Hi_new = Lo_new = Op_new = Cl_new = direction_new = 0;
    BarTurn_new = 0;
    BarEnd_new = 0;
    cnt = 0;

    for( i = 0; i < BarCount; i++ )
    {
        if( Hi[i] > 0 OR Lo[i] > 0 )
        {
            if( uu[i] ) // 1 box column, next column needs to be shifted back
            {
                if( direction[i] == ( -1 ) AND i < BarCount - 1 )
                {
                    cnt++;
                    // shift next column above the "O"
                    Hi_new[cnt] = Hi[i + 1];
                    Lo_new[cnt] = Lo[i];
                    Cl_new[cnt] = Hi_new[cnt];
                    Op_new[cnt] = Lo_new[cnt];
                    direction_new[cnt] = 2; // 2 means up, therefor bottom box is red, the rest green
                    barturn_new[cnt] = barturn[i + 1];
                    // skip 1 bar
                    i++;
                }
                else
                    if( direction[i] == 1 AND i < BarCount - 1 )
                    {
                        cnt++;
                        // shift next column below the "X"
                        Hi_new[cnt] = Hi[i];
                        Lo_new[cnt] = Lo[i + 1];
                        Cl_new[cnt] = Lo_new[cnt];
                        Op_new[cnt] = Hi_new[cnt];
                        direction_new[cnt] = -2; // -2 mean down, therefor to box is green, the rest red
                        barturn_new[cnt] = barturn[i + 1];
                        // skip 1 bar
                        i++;
                    }
                    else
                        if( i == ( BarCount - 1 ) )
                        {
                            cnt++;
                            // normal column, no adjustment
                            Hi_new[cnt] = Hi[i];
                            Lo_new[cnt] = Lo[i];

                            if( direction[i] == ( -1 ) )
                            {
                                Cl_new[cnt] = Lo_new[cnt];
                                Op_new[cnt] = Cl_new[cnt] + box;
                            }

                            if( direction[i] == 1 )
                            {
                                Cl_new[cnt] = Hi_new[cnt];
                                Op_new[cnt] = Cl_new[cnt] - box;
                            }

                            direction_new[cnt] = direction[i];
                            barturn_new[cnt] = barturn[i];
                        }
            }
            else
            {
                cnt++;
                // normal column, no adjustment
                Hi_new[cnt] = Hi[i];
                Lo_new[cnt] = Lo[i];

                if( direction[i] == ( -1 ) )
                {
                    Cl_new[cnt] = Lo_new[cnt];
                    Op_new[cnt] = Cl_new[cnt] + box;
                }

                if( direction[i] == 1 )
                {
                    Cl_new[cnt] = Hi_new[cnt];
                    Op_new[cnt] = Cl_new[cnt] - box;
                }

                direction_new[cnt] = direction[i];
                barturn_new[cnt] = barturn[i];
            }
        }
    }

    cols = cnt;

    delta = BarCount - cols - 1;
    Hi_new = Ref( Hi_new, -delta );
    Lo_new = Ref( Lo_new, -delta );
    Op_new = Ref( Op_new, -delta );
    Cl_new = Ref( Cl_new, -delta );
    direction_new = Ref( direction_new, -delta );
    barturn_new = Ref( barturn_new, -delta );

    Hi_new = IIf( Hi_new == 0, Null, Hi_new );
    Lo_new = IIf( Lo_new == 0, Null, Lo_new );
    Cl_new = IIf( Cl_new == 0, Null, Cl_new );
    Op_new = IIf( Op_new == 0, Null, Op_new );
    direction_new = IIf( direction_new == 0, Null, direction_new );

    x1 = x2 = y1 = y2 = x3 = y3 = 0;

    PlotOHLC( Op_new, Hi_new, Lo_new, Cl_new, "", colorWhite, styleNoLine | styleNoLabel, Null, Null, 0, 0, 1 );

    cols = cnt;
    cols = Min( BarCount - fvb, cols ); // adjust cols to visible for speed

    GfxSetZOrder( -1 );
    GfxSelectFont( ft, Box / 2 );

    for( i = 0; i < cols; i++ )
    {
        shft = ( BarCount - cols + i );
        hh = Hi_new[shft];
        ll = Lo_new[shft];
        nn = round( SafeDivide( hh - ll, Box ) );
        dd = direction_new[shft];

        if( dd == 1 OR dd == ( -1 ) )
        {
            if( dd == 1 )
                GfxSelectSolidBrush( xcolor );

            if( dd == ( -1 ) )
                GfxSelectSolidBrush( ocolor );

            //_TRACE("nn: " + nn );
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = ll + Box * ( k + 1 ); // Hi
                y2 = ll + Box * k; // Lo

                if( dd == 1 )
                {
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }

                if( dd == ( -1 ) )
                {
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }

        // special case up
        if( dd == 2 )
        {
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = ll + Box * ( k + 1 );
                y2 = ll + Box * k;

                if( k == 0 )
                {
                    GfxSelectSolidBrush( ocolor );
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
                else
                {
                    GfxSelectSolidBrush( xcolor );
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }

        // special case down
        if( dd == ( -2 ) )
        {
            for( k = 0; k < nn - 0; k++ )
            {
                x1 = BarCount - cols + i - 0.5;
                x2 = BarCount - cols + i + 0.5;
                y1 = hh - Box * k;
                y2 = hh - Box * ( k + 1 );

                if( k == 0 )
                {
                    GfxSelectSolidBrush( xcolor );
                    x3 = 0;
                    y3 = 0;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
                else
                {
                    GfxSelectSolidBrush( ocolor );
                    x3 = rndbox;
                    y3 = rndbox;
                    GfxRoundRect( x1, y1, x2, y2, x3, y3 );
                }
            }
        }
    }
}

//----------------------------------------------------------
// RENKO (derived from P&F)
//----------------------------------------------------------
if( displaymode == "RENKO" )
{
    BarTurnr1 = 0;
    PFHr = PFH + box / 2;
    PFLr = PFL - box / 2;

    NBox = round( SafeDivide( PFHr - PFLr, Box ) );
    NBox = IIf( PFH > 0, NBox, 0 );
    CumNBox = Cum( NBox );

	// if the box size is small the number of boxes may exceed Barcount
	// in these cases we need to start the loop not at 0 but at strt
    NBoxr = Reverse( Ref( NBox, -delta ) );
    CumNBoxr = Cum( NBoxr );
    CumNBoxr = IIf( CumNBoxr > 0, CumNBoxr, 0 );
    
    for( kk = 0; kk < BarCount; kk++ )
    {
        if( CumNBoxr[kk] >= BarCount )
            break;
    }

	if( kk < cols )
	{
		strt = cols - kk + 1;
	}
	else
	{
		strt = 0;
	}

    RRH = RRL = RRO = RRC = cnt = 0;

    for( i = strt; i <= cols; i++ )
    {
        if( nBox[i] > 0 )
        {
            if( cnt + nBox[i] >= BarCount )
                break;

            if( directionr[i] == 1 )
            {
                nn = nBox[i];

                for( ii = 0; ii < nn; ii++ )
                {
                    RRL[ ii + cnt ] = PFLr[i] + ii * Box;
                    RRH[ ii + cnt ] = PFLr[i] + ii * Box + Box;
                    RRO[ ii + cnt ] = RRL[ ii + cnt ];
                    RRC[ ii + cnt ] = RRH[ ii + cnt ];
                    BarTurnr1[ ii + cnt ] = BarTurnr[i];
                    direction_renko[ ii + cnt ] = 1;
                }

                cnt = cnt + nn;
            }
            else
                if( directionr[i] == ( -1 ) )
                {
                    nn = nBox[i];

                    for( ii = 0; ii < nn; ii++ )
                    {
                        RRH[ ii + cnt ] = PFHr[i] - ii * Box;
                        RRL[ ii + cnt ] = PFHr[i] - ii * Box - Box;
                        RRO[ ii + cnt ] = RRH[ ii + cnt ];
                        RRC[ ii + cnt ] = RRL[ ii + cnt ];
                        BarTurnr1[ ii + cnt ] = BarTurnr[i];
                        direction_renko[ ii + cnt ] = -1;
                    }

                    cnt = cnt + nn;
                }
        }
    }

    if( cnt < BarCount )
    {
        delta_r = BarCount - cnt;
        RRH = Ref( RRH, -delta_r );
        RRL = Ref( RRL, -delta_r );
        RRO = Ref( RRO, -delta_r );
        RRC = Ref( RRC, -delta_r );
        BarTurn = BarTurnr1;
        BarTurn = Ref( BarTurn, -delta_r );
        direction_renko = Ref( direction_renko, -delta_r );

        RRH = IIf( RRH, RRH, Null );
        RRL = IIf( RRL, RRL, Null );
        RRO = IIf( RRO, RRO, Null );
        RRC = IIf( RRC, RRC, Null );

        Plot( RRH, "", colorRed, styleLine | styleNoLabel, Null, Null, 0, 0, 1 );
        Plot( RRL, "", colorGreen, styleLine | styleNoLabel, Null, Null, 0, 0, 1 );
        PlotOHLC( RRO, RRH, RRL, RRC, "", IIf( RRC > RRO, xcolor, ocolor ), styleCandle | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
    }

	// put in arrays used for further calculations
    cols = cnt;
    Hi = RRH;
    Lo = RRL;
    Cl = RRC;
    Op = RRO;
    direction = direction_renko;
    Graphcolor = IIf( direction == 1, xcolor, ocolor );
}

if( scaling == "Percentage" )
{
    Last = Ref( LastValue( log( C ) ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots | styleNoLabel, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "" + NumToStr( exp( Last ), fmt ), ft, sz, BarCount + 1, YLastPrice = LastValue( Last ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0, gridFlags = 1 ) ; //chartGridPercent
}
else
{
    // the last close
    Last = Ref( LastValue( C ), -( BarCount - 1 ) );
    Plot( Last, "", LastValue( Graphcolor ), styleNoLine | styleDots, Null, Null, 1, 0, 1 );
    PlotTextSetFont( "" + NumToStr( Last, fmt ), ft, sz, BarCount + 1, YLastPrice = LastValue( C ), LastValue( Graphcolor ), colorDefault, -sz / 2 ); // label shows current price
    SetChartOptions( Mode = 1, Flags = 0 ) ;
}

if( displaymode != "RENKO" )
{
    if( nRev == 1 AND displaymode != "GFX 1 Box Reversal" )
    {
        PlotShapes( IIf( uu, shapeSmallCircle, shapeNone ), colorWhite, 0, Lo, Box_px / 2 );
        PlotShapes( IIf( uu, shapeHollowCircle, shapeNone ), colorBlack, 0, Lo, Box_px / 2 );
    }
}

//----------------------------------------------------------
// GRID CONSTRUCTION
//----------------------------------------------------------
if( ShowAxis == 1 )
{
    GfxSetBkColor( bcolor );
    GfxSetTextColor( yaxcolor );
    GfxSelectFont( ft, sz, 700 );

    if( displaymode == "GFX 1 Box Reversal" )
    {
        barturn = barturn_new;
        cols = cnt;
        direction = direction_new;
        direction = IIf( direction == 2, 1, IIf( direction == ( -2 ), -1, direction ) );
        Hi = Hi_new;
        Lo = Lo_new;
    }

    // Y-AXIS
    nrows = ceil( ( LastValue( Highest( Hi ) ) - LastValue( Lowest( Lo ) ) ) / box ) + 1;

    bx = LastValue( Lowest( Lo ) );
    GfxSelectPen( ColorRGB( 50, 50, 50 ) );

    nrows_visible = ceil( ( mxy - mny ) / box ) + 1;
    mult = round( nrows_visible / Min( nquot, nrows_visible ) );
    ii = 0;

    for( i = 0; i < nrows; i++ )
    {
        lvbs = bx + box * i;// + ( box );

        if( lvbs > mny AND lvbs < mxy )
        {
            // for placement
            ev = ii % mult == 0;

            if( ShowGrid )
            {
                GfxMoveTo( fvb, lvbs );
                GfxLineTo( lvb, lvbs );
            }

            if( ev )
            {
                if( scaling == "Percentage" )
                {
                    nstr = " " + NumToStr( exp( lvbs ), fmt );
                    toonear = 0.0055;
                }
                else
                {
                    lvbs = round( lvbs / TickSize ) * TickSize;
                    nstr = " " + NumToStr( lvbs, fmt );
                    toonear = 0.55;
                }

                if( lvb < BarCount - 2 OR lvbs - toonear > YLastPrice OR lvbs + toonear < YLastPrice )
                    GfxTextOut( nstr, lvb, lvbs );
                else
                    ii--;
            }
        }

        ii++;
    }

    if( ShowGrid )
    {
        for( i = fvb; i <= lvb; i++ )
        {
            GfxMoveTo( i - 0.5, mny );
            GfxLineTo( i - 0.5, mxy );
        }
    }

    // DATE AXIS
    GfxSelectFont( ft, sz, 600, False, False, orientation = 899 );
    GfxSetBkMode( 1 );
    GfxSetTextColor( colorAqua );

    if( displaymode == "RENKO" )
        cols = Min( lvb, cols );

    cols = Min( Min( lvb, BarCount ) - fvb, cols ); // adjust cols to visible for speed

    for( i = 1; i <= cols; i++ )
    {
        shft = ( lvb - cols + i - 1 );
        //mult = round( j / nquot );
        mult = round( cols / Min( nquot, cols ) );
        ev = i % mult == 0;

        if( ev )
        {
            str = DateTimeFormat( "%Y/%m/%d", BarTurn[shft] );

            if( str != "Invalid DateTime" AND barturn[shft] != 0 )
            {
                if( direction[shft] == 1 )
                {
                    GfxSetTextColor( xcolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
                else
                {
                    GfxSetTextColor( ocolor );
                    GfxTextOut( "<--- " + str, shft, mxy - ( mxy - mny ) / 10 );
                }
            }
        }
    }
}

//----------------------------------------------------------
// PIVOTS
//----------------------------------------------------------
if( pivottype == "ZigZag" )
{
    if( zz > 0 )
    {
        pk = PeakBars( Hi, zz ) == 0;
        tr = TroughBars( Lo, zz ) == 0;
    }
}

if( pivottype == "Fractal" )
{
    pk = Hi > Ref( HHV( Hi, leftStrength * fact ), -1 ) AND Ref( HHV( Hi, rightStrength * fact ), rightStrength * fact ) <= Hi;
    tr = Lo < Ref( LLV( Lo, leftStrength * fact ), -1 ) AND Ref( LLV( Lo, rightStrength * fact ), rightStrength * fact ) >= Lo;
}

if( pivottype == "BoxZigZag" AND BoxZZ > 0 )
{
    pk = IsPk == 2;
    tr = IsTr == 2;
}

if( pivottype == "HHVLLV" )
{
    // find trend
    res = HHV( Hi, nbar );
    sup = LLV( Lo, nbar );
    crossup = Hi > Ref( res, -1 );
    crossdn = Lo < Ref( sup, -1 );

    if( handleBothOutside )
    {
        // if in H/L mode both crossup and crossdn at the same bar may occur.
        // if handleBothOutside is true then it will stay in the current trend
        // if handleBothOutside is false it will change the trend.
        crossup = IIf( ( crossup AND crossdn ) AND( BarsSince( Ref( crossup, -1 ) ) > BarsSince( Ref( crossdn, -1 ) ) ), 0, crossup );
        crossdn = IIf( ( crossup AND crossdn ) AND( BarsSince( Ref( crossdn, -1 ) ) > BarsSince( Ref( crossup, -1 ) ) ), 0, crossdn );
    }

    crossup = ExRem( crossup, crossdn );
    crossdn = ExRem( crossdn, crossup );
    trendup = Flip( crossup, crossdn );
    trenddn = Flip( crossdn, crossup );

    // find pivots
    rtrenddn = Reverse( trenddn );
    rtrendup = Reverse( trendup );
    l1 = LowestSince( trenddn AND Ref( trendup, -1 ), Lo );
    rL = Reverse( Lo );
    l2 = LowestSince( rtrenddn AND Ref( rtrendup, -1 ), rL );
    rl2 = Reverse( l2 );
    h1 = HighestSince( trendup AND Ref( trenddn, -1 ), Hi );
    rH = Reverse( Hi );
    h2 = HighestSince( rtrendup AND Ref( rtrenddn, -1 ), rH );
    rh2 = Reverse( h2 );
    tr = l1 == rl2 AND trenddn;
    pk = h1 == rh2 AND trendup;
    rpk = Reverse( pk );
    rtr = Reverse( tr );
    rpk = ExRem( rpk, rtr );
    rtr = ExRem( rtr, rpk );
    pk = Reverse( rpk );
    tr = Reverse( rtr );
}

for( i = 0; i < 3; i++ )
{
    VarSet( "px" + i, ValueWhen( pk, bi, i ) );
    VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
    VarSet( "ph" + i, ValueWhen( pk, Hi, i ) );
    VarSet( "tl" + i, ValueWhen( tr, Lo, i ) );
}

ll = tr AND tl1 < tl2;
hl = tr AND tl1 > tl2;
hh = pk AND ph1 > ph2;
lh = pk AND ph1 < ph2;
dt = pk AND ph1 == ph2;
db = tr AND tl1 == tl2;

if( showpivots )
{
    if( pivottype == "Fractal" )
    {
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( tr, bi ) > rightStrength * fact, xcolor, colorWhite ), 0, Lo, -Box_px );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), IIf( Lx - ValueWhen( pk, bi ) > rightStrength * fact, ocolor, colorWhite ), 0, Hi, Box_px );
    }
    else
    {
        PlotShapes( IIf( tr, shapeSmallCircle, shapeNone ), colorGreen, 0, Lo, -Box_px );
        PlotShapes( IIf( pk, shapeSmallCircle, shapeNone ), colorRed, 0, Hi, Box_px );
    }

    dist = 2;

    for( i = lvb; i > fvb; i-- )
    {
        {
            if( ll[i] )
                PlotTextSetFont( "LL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * dist );

            if( hl[i] )
                PlotTextSetFont( "HL", "Arial Black", 8, i, Lo[i], xcolor, colorDefault, -Box_px * dist );

            if( db[i] )
                PlotTextSetFont( "DB", "Arial Black", 8, i, Lo[i], colorWhite, xcolor, -Box_px * dist );

            if( hh[i] )
                PlotTextSetFont( "HH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * dist - sz );

            if( lh[i] )
                PlotTextSetFont( "LH", "Arial Black", 8, i, Hi[i], ocolor, colorDefault, Box_px * dist - sz );

            if( dt[i] )
                PlotTextSetFont( "DT", "Arial Black", 8, i, Hi[i], colorWhite, ocolor, Box_px * dist - sz );
        }
    }
}


//----------------------------------------------------------
// TRENDLINES
//----------------------------------------------------------
if( showtrendlines AND trendlineDisplayType == "Original" AND displaymode != "RENKO" )
{
    Hiprice = ValueWhen( pk, Hi );
    Hibar = BarsSince( pk );
    TLDn = Hiprice - ( Box * HiBar ) + box / 2;
    Loprice = ValueWhen( tr, Lo );
    Lobar = BarsSince( tr );
    TLUp = Loprice + ( Box * LoBar ) - box / 2;
    TLDn = IIf( TLDn >= Hi, TLDn, Null );
    TLUp = IIf( TLUp <= Lo, TLUp, Null );

    Plot( TLDn, "TLDn", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
    Plot( TLUp, "TLUp", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
}

if( showtrendlines AND trendlineDisplayType == "Alternative" AND displaymode != "RENKO" )
{
    for( i = fvb; i <= lvb; i++ )
    {
        if( pk[i] )
        {
            Hiprice = ValueWhen( bi == i, Hi );
            Hibar = BarsSince( bi == i );
            TLDn = Hiprice - ( Box * HiBar ) + box / 2;;
            TLDn = IIf( TLDn > Hi, TLDn, Null );
            VarSet( "TLDn" + i, IIf( IsEmpty( TLDn ) AND !IsEmpty( Ref( TLDn, -1 ) ), Ref( TLDn, -1 ) - Box, TLDn ) );
            Plot( VarGet( "TLDn" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
            Buy = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), 1, Buy );
            BuyPrice = IIf( !IsEmpty( VarGet( "TLDn" + i ) ) AND Cross( hi, VarGet( "TLDn" + i ) ), VarGet( "TLDn" + i ), BuyPrice );

            if( showbuysell )
                PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ) , colorAqua, 0, BuyPrice, 0 );
        }

        if( tr[i] )
        {
            Loprice = ValueWhen( bi == i, Lo );
            Lobar = BarsSince( bi == i );
            TLUp = Loprice + ( Box * LoBar ) - box / 2;;
            TLUp = IIf( TLUp < Lo, TLUp, Null );
            VarSet( "TLUp" + i, IIf( IsEmpty( TLUp ) AND !IsEmpty( Ref( TLUp, -1 ) ), Ref( TLUp, -1 ) + Box, TLUp ) );
            Plot( VarGet( "TLUp" + i ), "", colorWhite, styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 1 );
            Short = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), 1, Short );
            ShortPrice = IIf( !IsEmpty( VarGet( "TLUp" + i ) ) AND Cross( VarGet( "TLUp" + i ), Lo ), VarGet( "TLUp" + i ), ShortPrice );

            if( showbuysell )
                PlotShapes( IIf( Short, shapeDownArrow, shapeNone ) , colorOrange, 0, ShortPrice, 0 );
        }
    }
}

//----------------------------------------------------------
// TITLE
//----------------------------------------------------------
if( scaling == "Percentage" )
{
    str1 =
        EncodeColor( titleColor ) +
        "High " + NumToStr( exp( Hi ) , fmt )   + "\n" +
        "Low " + NumToStr( exp( Lo ), fmt ) + "\n" +
        "Close " + NumToStr( exp( Cl ), fmt ) + "\n" +
        "Open " + NumToStr( exp( Op ), fmt );
}
else
{
    str1 =
        EncodeColor( colorWhite ) +
        "High " + NumToStr( Hi , fmt )   + "\n" +
        "Low " + NumToStr( Lo, fmt ) + "\n" +
        "Close " + NumToStr( Cl, fmt ) + "\n" +
        "Open " + NumToStr( Op, fmt );
}

Title = EncodeColor( titleColor ) + "Point & Figure" + "\n" +
        Name() + " | " + FullName() + "\n" +
        EncodeColor( titleColor ) + "Mode: " + EncodeColor( titleHighlightColor ) + cmode + "\n" +
        EncodeColor( titleColor ) + "Box Type: " + EncodeColor( titleHighlightColor ) + ctype + "\n" +
        EncodeColor( titleColor ) + tbox + "\n" +
        "Reverse (Boxes) : " + EncodeColor( titleHighlightColor ) + nRev + EncodeColor( titleColor ) + "\n" +
        "Chart Timeframe (sec): "  + EncodeColor( titleHighlightColor ) + Interval() + "\n" +
        EncodeColor( titleColor ) + "Date at Turn: " + EncodeColor( titleHighlightColor ) + DateTimeFormat( "%Y/%m/%d", SelectedValue( BarTurn ) ) + "\n" +
        EncodeColor( titleColor ) + "Pivot Type: " + EncodeColor( titleHighlightColor ) + pivottype + "\n" +
        EncodeColor( titleColor ) + "Trendline Display Type: " + EncodeColor( titleHighlightColor ) + trendlineDisplaytype + "\n" +
        EncodeColor( titleColor ) + "Display Mode: " + EncodeColor( titleHighlightColor ) + displaymode + "\n" +
        str1 + "\n";


//----------------------------------------------------------
// EXPLORATION
//----------------------------------------------------------
if( Status( "action" ) == actionExplore )
{
    snd = 1;

    if( snd )
    {
        AlertIf( LastValue( notifyarray ) OR LastValue( Buy ) OR LastValue( Short ), "SOUND C:\\Windows\\Media\\Alarm03.wav", "Audio alert", 1, 15, 1 );
    }

    Filter = notifyarray OR Buy OR Short;
    AddColumn( notifyarray == 1, "New Box Down", 1.2, colorBlack, IIf( notifyarray == 1, colorRed, colorWhite ) );
    AddColumn( notifyarray == 2, "Reversal Up", 1.2, colorBlack, IIf( notifyarray == 2, colorBrightGreen, colorWhite ) );
    AddColumn( notifyarray == 3, "New Box Up", 1.2, colorBlack, IIf( notifyarray == 3, colorBrightGreen, colorWhite ) );
    AddColumn( notifyarray == 4, "Reversal Down", 1.2, colorBlack, IIf( notifyarray == 4, colorRed, colorWhite ) );
    AddColumn( Buy, "Buy", 1.2, colorBlack, IIf( Buy, colorBrightGreen, colorWhite ) );
    AddColumn( Short, "Sell", 1.2, colorBlack, IIf( Short, colorRed, colorWhite ) );
}

_SECTION_END();

ABCD code you can put in the custom folder and drag it on top of the PnF code

_SECTION_BEGIN( "ABCD for PnF" );

/*
ratio labels
AB_AX means the ratio (A-B)/(A-X). It is the retracement of A to B over the price range A to X
BC_AB means the ratio (C-B)/(A-B)
CD_BC means the ratio (C-D)/(C-B)
AD_AX means the ratio (A-D)/(A-X)
*/

// PARAMETERS
showABCD = ParamToggle( "Show ABCD", "Off|On", 1 );
bu = ParamToggle( "Bullish Pattern", "Off|On", 1 );
be = ParamToggle( "Bearish Pattern", "Off|On", 1 );
showReciprocalABCD = ParamToggle( "Show Reciprocal ABCD", "Off|On", 0 );
st = Param( "Separation of Letters", 3, 1, 10, 1 );
dl = Param( "Dashed Line Number", 2, 1, 4, 1 );
showDotsAtD = ParamToggle( "Show Dots at D", "Off|On", 1 );
showPatternName = ParamToggle( "Show Pattern Name", "Off|On", 1 );
loc = Param( "Pattern Name Position", 6, 1, 10, 0.1 );
deviation = Param( "Deviation", 15, 0.1, 100, 0.1 );
fillPRZ = ParamToggle( "Fill PRZ area with color", "Off|On", 0 );

// ABCD
ABCD_MinAC = 0.382 - 0.382 * deviation / 100; // retrace from B to C over distance A to B
ABCD_MaxAC = 0.886 + 0.886 * deviation / 100;
ABCD_MinBD = 1.13 - 1.13 * deviation / 100; // retrace from C to D over distance B to C
ABCD_MaxBD = 2.618 + 2.618 * deviation / 100;

// Reciprocal ABCD
ReciprocalABCD_MinAC = 1.13 - 1.13 * deviation / 100; // retrace from B to C over distance A to B
ReciprocalABCD_MaxAC = 3.618 + 3.618 * deviation / 100;
ReciprocalABCD_MinBD = 0.382 - 0.382 * deviation / 100; // retrace from C to D over distance B to C
ReciprocalABCD_MaxBD = 0.886 + 0.886 * deviation / 100;

// DECLARE GLOBAL ARRAYS
Bull = Bull4 = Bear = Bear4 = 0;
AD_AX_min = AD_AX_max = 0;
CD_BC_min = CD_BC_max = 0;
BullABCD = BearABCD = 0;
topBox_bu = topBox_be = botBox_bu = botBox_be = 0;

// 'clean' the pivots function
// meaning make the pivots alternate like pk-tr-pk-tr-pk-tr-etc..
procedure alternate_proc( pk, tr )
{
    global pkg;
    global trg;

    // alternate pivots
    pkg = pk;
    trg = tr;
    pkHigh = 0;
    pkHighIndex = 0;
    trLow = 1e10;
    trLowIndex = 0;

    for( i = fvb; i <= lvb; i++ )
    {
        // peak and trough on same bar
        if( pk[i] AND tr[i] )
        {
            if( pkHighIndex > trLowIndex )
            {
                pkg[i] = 0;
                trg[i] = 1;

                if( Lo[i] <= trLow )
                {
                    pkHigh = 0;
                    pkHighIndex = 0;
                    trLow = Lo[i];
                    trLowIndex = i;
                }
                else
                {
                    pkHigh = 0;
                    pkHighIndex = 0;
                }
            }
            else
                if( pkHighIndex < trLowIndex )
                {
                    pkg[i] = 1;
                    trg[i] = 0;

                    if( Hi[i] >= pkHigh )
                    {
                        trLow = 1e10;
                        trLowIndex = 0;
                        pkHigh = Hi[i];
                        pkHighIndex = i;
                    }
                    else
                    {
                        trLow = 1e10;
                        trLowIndex = 0;
                    }
                }
                else
                {
                    pkg[i] = 0;
                    trg[i] = 0;
                }
        }
        else

            // consecutive higher peak found
            if( pk[i] AND Hi[i] >= pkHigh )
            {
                // disable the previous lower peak
                pkg[pkHighIndex] = 0;
                // update new peak variables
                pkHigh = Hi[i];
                pkHighIndex = i;
                // reset trough variables
                trLow = 1e10;
                trLowIndex = 0;
            }
            else

                // consecutive lower peak found
                if( pk[i] AND Hi[i] < pkHigh )
                {
                    // disable this peak
                    pkg[i] = 0;
                    // reset trough variables
                    trLow = 1e10;
                    trLowIndex = 0;
                }
                else

                    // consecutive lower trough found
                    if( tr[i] AND Lo[i] <= trLow )
                    {
                        // disable the previous higher trough
                        trg[trLowIndex] = 0;
                        // update trough variables
                        trLow = Lo[i];
                        trLowIndex = i;
                        // reset peak variables
                        pkHigh = 0;
                        pkHighIndex = 0;
                    }
                    else

                        // consecutive higher trough found
                        if( tr[i] AND Lo[i] > trLow )
                        {
                            // disable this trough
                            trg[i] = 0;
                            // reset peak variables
                            pkHigh = 0;
                            pkHighIndex = 0;
                        }
    }
}

if( pivottype == "Fractal" )
{
	// run clean pivots
	alternate_proc( pk, tr );
	pk = pkg;
	tr = trg;
}

// BULLISH AND BEARISH PATTERN PREPARATIONS
pkH1 = ValueWhen( pk, Hi );
pkBar1 = ValueWhen( pk, bi );
pkH2 = ValueWhen( pk, Hi, 2 );
pkBar2 = ValueWhen( pk, bi, 2 );
trL1 = ValueWhen( tr, Lo );
trBar1 = ValueWhen( tr, bi );
trL2 = ValueWhen( tr, Lo, 2 );
trBar2 = ValueWhen( tr, bi, 2 );

PTvalid_bu = ( pkBar1 > trBar1 AND trBar1 > pkBar2 AND pkbar2 > trBar2 ) AND pk;

AX_bu = pkH2 - trL2;
AB_bu = pkH2 - trL1;
BC_bu = pkH1 - trL1;

AB_AX_bu = SafeDivide( AB_bu, AX_bu );
BC_AB_bu = SafeDivide( BC_bu, AB_bu );

PTvalid_be = ( trBar1 > pkBar1 AND pkBar1 > trBar2 AND trBar2 > pkBar2 ) AND tr;

AX_be = pkH2 - trL2;
AB_be = pkH1 - trL2;
BC_be = pkH1 - trL1;

AB_AX_be = SafeDivide( AB_be, AX_be );
BC_AB_be = SafeDivide( BC_be, AB_be );

// PATTERN CALCULATION AND DISPLAY FUNCTIONS
function GfxConvertBarToPixelX( bar )
{
    local fvb1, lvb1;

    lvb1 = Status( "lastvisiblebar" );
    fvb1 = Status( "firstvisiblebar" );
    pxchartleft = Status( "pxchartleft" );
    pxchartwidth = Status( "pxchartwidth" );

    return pxchartleft + bar  * pxchartwidth / ( lvb1 - fvb1 + 1 );
}

function GfxConvertValueToPixelY2( Value )
{
    local Miny, Maxy, pxchartbottom, pxchartheight;

    Miny = Status( "axisminy" );
    Maxy = Status( "axismaxy" );

    pxchartbottom = Status( "pxchartbottom" );
    pxchartheight = Status( "pxchartheight" );

    return pxchartbottom - floor( 0.5 + ( Value - Miny ) * SafeDivide( pxchartheight, Maxy - Miny ) );
}

function CalculateAngle( x1, y1, x2, y2 )
{
    // calculate angle of text
    x1 = GfxConvertBarToPixelX( x1 );
    y1 = GfxConvertValueToPixelY2( y1 );
    x2 = GfxConvertBarToPixelX( x2 );
    y2 = GfxConvertValueToPixelY2( y2 );
    onerad = 57.2957795;
    angle = 10 * onerad * atan( SafeDivide( y2 - y1,  x2 - x1 ) ) * -1;
    return angle;
}

function drawABCDPattern( Abar, A, Bbar, B, C1bar, C1, Dbar, D, BCdAB, BCdCD, topBox, botBox, patternName, clr1, clr2, clr3, fac, dir )
{
    GfxSetZOrder( -1 );
    GfxSelectPen( clr1, 2, 0 );
    GfxMoveTo( Abar, A );
    GfxLineTo( Bbar, B );
    GfxLineTo( C1bar, C1 );
    GfxLineTo( Dbar, D );
    GfxSelectPen( clr1, 1, dl );
    GfxMoveTo( Abar, A );
    GfxLineTo( C1bar, C1 );
    GfxMoveTo( Bbar, B );
    GfxLineTo( Dbar, D );

    PlotTextSetFont( NumToStr( BCdAB, 1.2 ), ft, sz, ( C1bar + Abar ) / 2, ( C1 + A ) / 2, clr1, colorDefault, 0 );
    PlotTextSetFont( NumToStr( BCdCD, 1.2 ), ft, sz, ( Bbar + Dbar ) / 2, ( B + D ) / 2, clr1, colorDefault, 0 );
    PlotTextSetFont( "A", ft, sz, Abar - st, A, clr1, colorDefault, sz * dir );
    PlotTextSetFont( "B", ft, sz, Bbar - st, B, clr1, colorDefault, -sz * dir );
    PlotTextSetFont( "C", ft, sz, C1bar + st, C1, clr1, colorDefault, sz * dir );
    PlotTextSetFont( "D", ft, sz, Dbar + st, D, clr1, colorDefault, - sz * dir );

    if( showPatternName )
    {
        //PlotTextSetFont( "" + patternName, ft, sz, Abar, A, clr1, colorDefault, sz * fac );

        if( dir == 1 )
        {
            angle = calculateAngle( ABar, A, C1Bar, C1 );
            GfxSelectFont( ft, sz, 400, False, False, angle );
            GfxSetCoordsMode( 1 );
            GfxSetTextColor( clr1 );
            GfxTextOut( "" + patternName, Abar + ( C1bar - Abar ) / loc, A + ( C1 - A ) / loc );
        }

        if( dir == ( -1 ) )
        {
            angle = calculateAngle( BBar, B, DBar, D );
            GfxSelectFont( ft, sz, 400, False, False, angle );
            GfxSetCoordsMode( 1 );
            GfxSetTextColor( clr1 );
            GfxTextOut( "" + patternName, Bbar + ( Dbar - Bbar ) / loc, B + ( D - B ) / loc );
        }
    }

    // draw PRZ rectangle
    GfxSetZOrder( -4 );
    GfxSelectSolidBrush( clr3 );
    x0 = C1bar;
    y0 = topBox;
    x1 = Dbar;
    y1 = botBox;

    if( fillPRZ )
    {
        GfxSelectPen( clr2, 1, 0 );
        GfxRectangle( x0, y0, x1, y1 );
    }
    else
    {
        GfxSelectPen( clr2, 1, 0 );
        GfxMoveTo( x0, y0 );
        GfxLineTo( x0, y1 );
        GfxLineTo( x1, y1 );
        GfxLineTo( x1, y0 );
        GfxLineTo( x0, y0 );
    }
}

function calculateBullishABCDPattern( MinAC, MaxAC, MinBD, MaxBD, pattername )
{
    Bull4 = PTvalid_bu AND( BC_AB_bu > MinAC ) AND( BC_AB_bu < MaxAC );

    dHigh = HighestSince( Bull4, Hi );
    dLow = LowestSince( Bull4, Lo );

    pC = ValueWhen( Bull4, pkH1 );
    pB = ValueWhen( Bull4, trL1 );
    pA = ValueWhen( Bull4, pkH2 );
    CB = pC - pB;

    CD_BC_min = pC - CB * MinBD;
    CD_BC_max = pC - CB * MaxBD;

    Bull = IIf( ( dLow < CD_BC_min ) AND( dLow > CD_BC_max )
                AND( dHigh <= pC ) AND( dLow == Lo ),
                True, False );

    if( pattername == "ABCD" )
        Bull = Bull AND( dLow < pB );

    if( showDotsAtD )
        PlotShapes( IIf( Bull, shapeSmallCircle, Null ), ColorRGB( 64, 128, 64 ), 0, Lo, -20 );
}

function calculateBearishABCDPattern( MinAC, MaxAC, MinBD, MaxBD, patternname )
{
    Bear4 = PTvalid_be AND( BC_AB_be > MinAC ) AND( BC_AB_be < MaxAC );

    dHigh = HighestSince( Bear4, Hi );
    dLow = LowestSince( Bear4, Lo );

    pA = ValueWhen( Bear4, trL2 );
    pB = ValueWhen( Bear4, pkH1 );
    pC = ValueWhen( Bear4, trL1 );
    CB = pB - pC;

    CD_BC_min = pC + CB * MinBD;
    CD_BC_max = pC + CB * MaxBD;

    Bear = IIf( ( dHigh > CD_BC_min ) AND( dHigh < CD_BC_max )
                AND( dLow >= pC ) AND( dHigh == Hi ),
                True, False );

    if( patternname == "ABCD" )
        Bear = Bear AND( dHigh > pB );

    if( showDotsAtD )
        PlotShapes( IIf( Bear, shapeSmallCircle, Null ), ColorRGB( 128, 128, 64 ), 0, Hi, 20 );
}

function showBullishABCDPattern( patternName )
{
    BullHar4 = Bull4;
    BullHar = Bull;

    if( lvb > 0 )
    {
        rBullHar4 = Reverse( BullHar4, 0, lvb );
        rBullHar = Reverse( BullHar, 0, lvb );
        rBullHar = ExRem( rBullHar, rBullHar4 );
        BullHar = Reverse( rBullHar, 0, lvb );
    }

    A = ValueWhen( BullHar4, pkH2 );
    Abar = ValueWhen( BullHar4, pkbar2 );
    B = ValueWhen( BullHar4, trL1 );
    Bbar = ValueWhen( BullHar4, trbar1 );
    C1 = ValueWhen( BullHar4, pkH1 );
    C1bar = ValueWhen( BullHar4, pkbar1 );
    D = ValueWhen( BullHar, Lo );
    Dbar = ValueWhen( BullHar, bi );
    BCdAB = SafeDivide( C1 - B, A - B );
    BCdCD = SafeDivide( C1 - D, C1 - B );

    for( i = lvb; i > fvb; i-- )
    {
        bullcolor = xcolor;
        linethick = 1;

        if( BullHar[i] AND bu )
        {
            drawABCDPattern( Abar[i], A[i], Bbar[i], B[i], C1bar[i], C1[i], Dbar[i], D[i], BCdAB[i], BCdCD[i],
                             CD_BC_min[i], CD_BC_max[i], patternName, xcolor, ColorRGB( 0, 80, 0 ), ColorRGB( 0, 10, 0 ), 1, 1 );
        }
    }
}

function showBearishABCDPattern( patternName )
{
    BearHar4 = Bear4;
    BearHar = Bear;

    if( lvb > 0 )
    {
        rBearHar4 = Reverse( BearHar4, 0, lvb );
        rBearHar = Reverse( BearHar, 0, lvb );
        rBearHar = ExRem( rBearHar, rBearHar4 );
        BearHar = Reverse( rBearHar, 0, lvb );
    }

    A = ValueWhen( BearHar4, trL2 );
    Abar = ValueWhen( BearHar4, trbar2 );
    B = ValueWhen( BearHar4, pkH1 );
    Bbar = ValueWhen( BearHar4, pkbar1 );
    C1 = ValueWhen( BearHar4, trL1 );
    C1bar = ValueWhen( BearHar4, trbar1 );
    D = ValueWhen( BearHar, Hi );
    Dbar = ValueWhen( BearHar, bi );
    BCdAB = SafeDivide( B - C1, B - A );
    BCdCD = SafeDivide( D - C1, B - C1 );

    for( i = lvb; i > fvb; i-- )
    {
        bearcolor = ocolor;
        linethick = 1;

        if( BearHar[i] AND be )
        {
            drawABCDPattern( Abar[i], A[i], Bbar[i], B[i], C1bar[i], C1[i], Dbar[i], D[i], BCdAB[i], BCdCD[i],
                             CD_BC_min[i], CD_BC_max[i], patternName, ocolor, ColorRGB( 80, 0, 0 ), ColorRGB( 10, 0, 0 ), -2, -1 );
        }
    }
}

if( bu )
{
    if( showABCD )
    {
        // Bullish ABCD Pattern
        Bull = Bull4 = 0;
        CD_BC_min = CD_BC_max = 0;
        calculateBullishABCDPattern( ABCD_MinAC, ABCD_MaxAC, ABCD_MinBD, ABCD_MaxBD, "ABCD" );
        showBullishABCDPattern( "Bullish ABCD" );
        BullABCD = Bull;
    }

    if( showReciprocalABCD )
    {
        // Bullish Reciprocal ABCD Pattern
        Bull = Bull4 = 0;
        CD_BC_min = CD_BC_max = 0;
        calculateBullishABCDPattern( ReciprocalABCD_MinAC, ReciprocalABCD_MaxAC, ReciprocalABCD_MinBD, ReciprocalABCD_MaxBD, "ReciprocalABCD" );
        showBullishABCDPattern( "Bullish Reciprocal ABCD" );
        BullReciprocalABCD = Bull;
    }
}

if( be )
{
    if( showABCD )
    {
        // Bearish ABCD Pattern
        Bear = Bear4 = 0;
        CD_BC_min = CD_BC_max = 0;
        calculateBearishABCDPattern( ABCD_MinAC, ABCD_MaxAC, ABCD_MinBD, ABCD_MaxBD, "ABCD" );
        showBearishABCDPattern( "Bearish ABCD" );
        BearABCD = Bear;
    }

    if( showReciprocalABCD )
    {
        // Bearish Reciprocal ABCD Pattern
        Bear = Bear4 = 0;
        CD_BC_min = CD_BC_max = 0;
        calculateBearishABCDPattern( ReciprocalABCD_MinAC, ReciprocalABCD_MaxAC, ReciprocalABCD_MinBD, ReciprocalABCD_MaxBD, "ReciprocalABCD" );
        showBearishABCDPattern( "Bearish Reciprocal ABCD" );
        BearReciprocalABCD = Bear;
    }

}

_SECTION_END();

5 Likes

Thanks for sharing and thanks to keep the 899 orientation, :sunglasses:

In plot renko ,
you have this 3 Plot functions,
any reason why you need the first 2 ?
If you comment out both and
delete the stylenorescale from the third plot
the graphic looks cleaner

        //Plot( RRH, "", colorRed, styleLine | styleNoLabel, Null, Null, 0, 0, 1 );
        //Plot( RRL, "", colorGreen, styleLine | styleNoLabel, Null, Null, 0, 0, 1 );
        PlotOHLC( RRO, RRH, RRL, RRC, "", IIf( RRC > RRO, xcolor, ocolor ), styleCandle | styleNoLabel, Null, Null, 0, 0, 1 );
    }

1 Like

thanks, I didn't notice the 899. I think I copied some code that you posted. Yes you are right. The RRH and RRL can be commented out. I just left them in. Code is still under development. Just wanted to see if this Renko is correct since compared to other codes it is slightly different.

But as I mentioned I just took the result from the PnF and used that to create the Renko. So my Renko is just a derivative of the PnF. In my opinion it is correct. I used code by Graham before but if you take the box size too small it does not plot the real time bricks. I corrected for that. As explained if the boxsize is chosen to be small you end up with more bricks then bars (Barcount). And with Renko every brick uses 1 bar.

I took out the boxsize pivots just because it makes the code is a bit cleaner

2 Likes