# Draw Square where One side of that square is Trendline

3rd screenshot mentioned in the post above, please.

No it is not. However, it is appearing so. As previously mentioned by @PanoS, It is happening because of anisotropic property of charts.

Anyways, below is a code, where it is mathematically proven that ABCD is a square and hence by default it implies that the quadrilateral PQRS formed out of the mid-points of its sides is also a square.

``````function RadToDeg( x ) {
pi = atan( 1 ) * 4;
return x * ( 180 / pi ); //Angle is calculated in radians, thus converting it to degrees
}

_SECTION_BEGIN( "Square off a Trendline" );
SetChartOptions( 1, chartShowDates );

bi = BarIndex();
ChartId = Name() + GetChartId();

//////////////////////////////////////////////////////////////
///////////// Capturing co-ordinates of A and B //////////////
//////////////////////////////////////////////////////////////
LeftMsBtnJustClkd = GetCursorMouseButtons() & 8;
LeftMsBtnDownRlsd = GetCursorMouseButtons() & 9;
MsMiddleBtnClkd = GetCursorMouseButtons() & 4;

x = GetCursorXPosition( 0 );
y = GetCursorYPosition( 0 );

CtrlPressed = GetAsyncKeyState( 17 ) < 0;
if( CtrlPressed ) {
if( LeftMsBtnJustClkd ) {
StaticVarSet( "Ax" + ChartId, x, 0 );
StaticVarSet( "Ay" + ChartId, y, 0 );
}
if( LeftMsBtnDownRlsd ) {
StaticVarSet( "Bx" + ChartId, x, 0 );
StaticVarSet( "By" + ChartId, y, 0 );
}
if( MsMiddleBtnClkd ) {
StaticVarRemove( "Ax" + ChartId );
StaticVarRemove( "Ay" + ChartId );
StaticVarRemove( "Bx" + ChartId );
StaticVarRemove( "By" + ChartId );
}
RequestMouseMoveRefresh();
}
//////////////////////////////////////////////////////////////

GfxSetZOrder( 0 );
GfxSetCoordsMode( 1 );

GfxSetBkMode( 1 );
GfxSelectFont( "Arial", 8, 400 );
GfxSetTextColor( colorLavender );
GfxSelectPen( colorBlueGrey, 1, 0 );

_Ax = Lookup( bi, StaticVarGet( "Ax" + ChartId ) );
_Ay = StaticVarGet( "Ay" + ChartId );
_Bx = Lookup( bi, StaticVarGet( "Bx" + ChartId ) );
_By = StaticVarGet( "By" + ChartId );

if( _Ax != 0 AND _Bx != 0 ) {
// Using GFX, drawing a line between A and B
GfxMoveTo( _Ax, _Ay );
GfxLineTo( _Bx, _By );

// Finding co-ordinates of C and D (ABCD being a square)
dX = _Bx - _Ax;	 dY = _By - _Ay;
_Cx = _Bx + dY ;	_Cy = _By - dx ;
_Dx = _Ax + dY ;	_Dy = _Ay - dx ;

// Drawing a line between B and C
GfxMoveTo( _Bx, _By );
GfxLineTo( _Cx, _Cy );

// Drawing a line between A and D
GfxMoveTo( _Ax, _Ay );
GfxLineTo( _Dx, _Dy );

// Drawing a line between C and D
GfxMoveTo( _Cx, _Cy );
GfxLineTo( _Dx, _Dy );

// Drawing diagonals of the square ABCD
GfxMoveTo( _Ax, _Ay );
GfxLineTo( _Cx, _Cy );
GfxMoveTo( _Bx, _By );
GfxLineTo( _Dx, _Dy );

// Finding mid-points of the sides of ABCD
Px = ( _Ax + _Bx ) / 2;	Py = ( _Ay + _By ) / 2;
Qx = ( _Bx + _Cx ) / 2;	Qy = ( _By + _Cy ) / 2;
Rx = ( _Cx + _Dx ) / 2;	Ry = ( _Cy + _Dy ) / 2;
Sx = ( _Ax + _Dx ) / 2;	Sy = ( _Ay + _Dy ) / 2;

// Drawing a square PQRS
GfxMoveTo( Px, Py );	GfxLineTo( Qx, Qy );
GfxMoveTo( Qx, Qy );	GfxLineTo( Rx, Ry );
GfxMoveTo( Rx, Ry );	GfxLineTo( Sx, Sy );
GfxMoveTo( Sx, Sy );	GfxLineTo( Px, Py );

// Text for co-ordinates
GfxTextOut( "A", _Ax, _Ay );
GfxTextOut( "B", _Bx, _By );
GfxTextOut( "C", _Cx, _Cy );
GfxTextOut( "D", _Dx, _Dy );
GfxTextOut( "P", Px, Py );
GfxTextOut( "Q", Qx, Qy );
GfxTextOut( "R", Rx, Ry );
GfxTextOut( "S", Sx, Sy );

//////////////////////////////////////////////////////////////
/////////////// Proving that ABCD is a square ////////////////
//////////////////////////////////////////////////////////////
// Measuring length of the sides using Distance formula
AB = sqrt( dX ^ 2 + dY ^ 2 );
BC = sqrt( ( _Cx - _Bx ) ^ 2 + ( _Cy - _By ) ^ 2 );
CD = sqrt( ( _Dx - _Cx ) ^ 2 + ( _Dy - _Cy ) ^ 2 );
DA = sqrt( ( _Dx - _Ax ) ^ 2 + ( _Dy - _Ay ) ^ 2 );

// Finding angle of the vertices of ABCD
CAD = atan( CD / DA );		CAB = atan( BC / AB );		/*Hence,*/	DAB = RadToDeg( CAD + CAB );
DBA = atan( DA / AB );		DBC = atan( CD / BC );		/*Hence,*/	ABC = RadToDeg( DBA + DBC );
ACB = atan( AB / BC );		ACD = atan( DA / CD );		/*Hence,*/	BCD = RadToDeg( ACB + ACD );
BDC = atan( BC / CD );		BDA = atan( AB / DA );		/*Hence,*/	CDA = RadToDeg( BDC + BDA );

Title =
"Proof 1: All sides of ABCD are equal" +
StrFormat( "\nAB = %1.2f, BC = %1.2f, CD = %1.2f, DA = %1.2f", AB, BC, CD, DA ) +
"\nAB = BC = CD = DA = " + WriteIf( AB == BC && BC == CD && CD == DA, "True", "False" ) +
"\n\nProof 2: All vertices of ABCD are of 90°" +
StrFormat( "\nDAB = %1.0f°, ABC = %1.0f°, BCD = %1.0f°, CDA = %1.0f°", DAB, ABC, BCD, CDA ) +
"\nAngle A = B = C = D = " + WriteIf( DAB == ABC && ABC == BCD && BCD == CDA, "True", "False" )
;
//////////////////////////////////////////////////////////////
}

Plot( C, "Price", colorDefault, styleCandle );
_SECTION_END();
``````

4 Likes

Hello Cougar,
Thank you for your help. I understood that part now. By using zoom - shorter bars & taller bars options, I am able to see the square shape on the chart.
Though, somehow I am not able to see Proof related text on the chart which I see on your screenshot on upper left part. If possible, let me know how to get it displayed on chart, please.

When selected point A has lower price & selected point B has higher price, it draws downward facing square on the right side of the selected points, which is awesome.

If possible, I would like to have square drawn to upward & right side of a trend line when a selected point A has higher price, selected point B has lower price & selected point B is located on (lower) right side from selected point A as shown in my screenshot below with this post, please. In other words, point A has occurred earlier (date/time) then point B (date/time)

In the GIF screenshot that you have displayed in your last reply, has point A has higher price & point B has lower price but Point B is located on (lower) left side from point A.

I am ok to use 2 separate indicators (one for each case) if its not possible to draw square using single indicator, please.

Thank you.

Use the latter code and draw a new trendline using CTRL & Mouse Left Button down. The moment you draw, the Title text will appear.

DIY please... You have all the cues in place!

Hint:

``````// Finding co-ordinates of C and D (ABCD being a square)
dX = _Bx - _Ax;	 dY = _By - _Ay;
_Cx = _Bx + dY ;	_Cy = _By - dx ;
_Dx = _Ax + dY ;	_Dy = _Ay - dx ;
``````
3 Likes

Hello Cougar,
I will try to DIM (Do it myself) & apply those changes.

Thank you.

Would be happy to help... It's just that one does not learn, if everything is showcased.

Thank you

Hello Cougar,

I agree. I will try to update. Once I get the desired result, I will share that code over here.
Thank you.

Very nice clean afl code with details, good job @Cougar

We can insert to your code (after line 40) the below code that is just for editing the point A or point B of the main line

I think now the @trader123 he have to hit the hart image button or solution on your post Cougar, as you spent at least one day just to help him.

``````	  //////////////////////////////////////////////////////////////
// For Editing TRENDLINE POINTS A OR B, (by holding keyboard button A OR B and just a Click Mouse Left Button )
//////////////////////////////////////////////////////////////
AlfaPressed = GetAsyncKeyState( 65 ) < 0;
BetaPressed = GetAsyncKeyState( 66 ) < 0;
if( AlfaPressed ) {
if( LeftMsBtnJustClkd ) {
StaticVarSet( "Ax" + ChartId, x, 0 );
StaticVarSet( "Ay" + ChartId, y, 0 );
}  RequestMouseMoveRefresh();
}
if( BetaPressed) {
if( LeftMsBtnJustClkd ) {
StaticVarSet( "Bx" + ChartId, x, 0 );
StaticVarSet( "By" + ChartId, y, 0 );
}	RequestMouseMoveRefresh();
}
//////////////////////////////////////////////////////////////
``````
4 Likes

Thank you

Nah!... About an hour (occasionally distracted by other things)... I was not doing anything either, would have anyways wasted that time... Productive utilization of free time so to speak...

BTW, there is a simpler way to flip the squares just by toggling the sign of delta of axis coordinates (line 61 - 63).

``````// Finding co-ordinates of C and D (ABCD being a square)
dX = _Bx - _Ax;	 dY = _By - _Ay;
_Cx = _Bx + dY ;	_Cy = _By - dx ;
_Dx = _Ax + dY ;	_Dy = _Ay - dx ;
``````

Flipping the squares by changing sign:

`````` dX = _Bx - _Ax;	 dY = _By - _Ay;
_Cx = _Bx - dY ;	_Cy = _By + dx ;
_Dx = _Ax - dY ;	_Dy = _Ay + dx ;
``````
3 Likes

Thank you Cougar & PanoS for your help.

2 Likes

Hello Cougar & PanoS,
I have got solution to draw the square on the chart. Various points of the chart can be used as support & resistance. Various side of the square can also be used as support & resistance. That's the usage of it, which you helped me with.

I had purchased Amibroker Professional Edition since early 2017 but was not using as much till now. Since, I got this interesting setup available on chart, I am planning to use it more often now. In that regards, I have one more query which I have posted it at following location in this forum, please.

If possible, I would like to request you to review it & let me know your input, please.
Thank you.

Hello Cougar,
When I draw square on S&P500 M5 & H1 charts. It works good. But when I draw square on S&P500 D1 (Daily) chart, side AD and BC stretch out a lot & square does not get completed within screen limit. As discussed earlier in the post, I think its due to difference in the unit of X-axis & Y-axis.

Similarly, when I try to draw square on EURUSD M5 chart & select point A & B then side AD & BC tend to extend to infinity. If you get chance, let me know if anything can be done for these situation, please.

You can re-solve that easily by converting Bar (on X-axis) and Price (on Y-axis) to pixel co-ordinates and then use `GfxSetCoordsMode` set to `0` (instead of `1` as previously used). Try this:

``````// To convert from Bar (on X-axis) and Price (on Y-axis) to pixel co-ordinates
Miny = Status( "axisminy" );
Maxy = Status( "axismaxy" );
lvb = Status( "lastvisiblebar" );
fvb = Status( "firstvisiblebar" );
pxchartleft = Status( "pxchartleft" );
pxchartwidth = Status( "pxchartwidth" );
pxchartbottom = Status( "pxchartbottom" );
pxchartheight = Status( "pxchartheight" );
function XtoPxX( bar ) { return pxchartleft + ( bar - fvb ) * pxchartwidth / ( lvb - fvb + 1 ); }
function YtoPxY( value ) { return pxchartbottom - floor( 0.5 + ( value - Miny ) * pxchartheight / ( Maxy - Miny + 1e-9 ) ); }

pi = atan( 1 ) * 4;
return x * ( 180 / pi ); //Angle is calculated in radians, thus converting it to degrees
}

_SECTION_BEGIN( "Square off a Trendline" );
SetChartOptions( 1, chartShowDates );

bi = BarIndex();
ChartId = Name() + GetChartId();

//////////////////////////////////////////////////////////////
///////////// Capturing co-ordinates of A and B //////////////
//////////////////////////////////////////////////////////////
LeftMsBtnJustClkd = GetCursorMouseButtons() & 8;
LeftMsBtnDownRlsd = GetCursorMouseButtons() & 9;
MsMiddleBtnClkd = GetCursorMouseButtons() & 4;

x = GetCursorXPosition( 0 );
y = GetCursorYPosition( 0 );

CtrlPressed = GetAsyncKeyState( 17 ) < 0;
if( CtrlPressed ) {
if( LeftMsBtnJustClkd ) {
StaticVarSet( "Ax" + ChartId, x, 0, False );
StaticVarSet( "Ay" + ChartId, y, 0, False );
}
if( LeftMsBtnDownRlsd ) {
StaticVarSet( "Bx" + ChartId, x, 0, False );
StaticVarSet( "By" + ChartId, y, 0, False );
}
if( MsMiddleBtnClkd ) {
StaticVarRemove( "Ax" + ChartId );
StaticVarRemove( "Ay" + ChartId );
StaticVarRemove( "Bx" + ChartId );
StaticVarRemove( "By" + ChartId );
}
}
//////////////////////////////////////////////////////////////

GfxSetZOrder( 0 );
GfxSetCoordsMode( 0 );
GfxSetBkMode( 1 );
GfxSelectFont( "Arial", 8, 400 );
GfxSetTextColor( colorLavender );
GfxSelectPen( colorBlueGrey, 1, 0 );

_Ax = XtoPxX( Lookup( bi, StaticVarGet( "Ax" + ChartId ) ) );
_Ay = YtoPxY( StaticVarGet( "Ay" + ChartId ) );
_Bx = XtoPxX( Lookup( bi, StaticVarGet( "Bx" + ChartId ) ) );
_By = YtoPxY( StaticVarGet( "By" + ChartId ) );

if( _Ax > 0 && _Bx > 0 ) {
// Finding co-ordinates of C and D (ABCD being a square)
dX = _Bx - _Ax;	 		 dY = _By - _Ay;
_Cx = _Bx - dY;			_Cy = _By + dx;
_Dx = _Ax - dY;			_Dy = _Ay + dx;

// Drawing square ABCD
GfxMoveTo( _Ax, _Ay );		GfxLineTo( _Bx, _By );
GfxMoveTo( _Bx, _By );		GfxLineTo( _Cx, _Cy );
GfxMoveTo( _Ax, _Ay );		GfxLineTo( _Dx, _Dy );
GfxMoveTo( _Cx, _Cy );		GfxLineTo( _Dx, _Dy );

// Drawing diagonals of the square ABCD
GfxMoveTo( _Ax, _Ay );		GfxLineTo( _Cx, _Cy );
GfxMoveTo( _Bx, _By );		GfxLineTo( _Dx, _Dy );

// Finding mid-points of the sides of ABCD
Px = ( _Ax + _Bx ) / 2;	Py = ( _Ay + _By ) / 2;
Qx = ( _Bx + _Cx ) / 2;	Qy = ( _By + _Cy ) / 2;
Rx = ( _Cx + _Dx ) / 2;	Ry = ( _Cy + _Dy ) / 2;
Sx = ( _Ax + _Dx ) / 2;	Sy = ( _Ay + _Dy ) / 2;

// Drawing a square PQRS
GfxMoveTo( Px, Py );		GfxLineTo( Qx, Qy );
GfxMoveTo( Qx, Qy );		GfxLineTo( Rx, Ry );
GfxMoveTo( Rx, Ry );		GfxLineTo( Sx, Sy );
GfxMoveTo( Sx, Sy );		GfxLineTo( Px, Py );

// Text for co-ordinates
GfxTextOut( "A", _Ax, _Ay ); 	GfxTextOut( "B", _Bx, _By );	GfxTextOut( "C", _Cx, _Cy ); 	GfxTextOut( "D", _Dx, _Dy );
GfxTextOut( "P", Px, Py ); 	GfxTextOut( "Q", Qx, Qy ); 		GfxTextOut( "R", Rx, Ry ); 		GfxTextOut( "S", Sx, Sy );

//////////////////////////////////////////////////////////////
/////////////// Proving that ABCD is a square ////////////////
//////////////////////////////////////////////////////////////
// Measuring length of the sides using Distance formula (in pixels)
AB = sqrt( dX ^ 2 + dY ^ 2 );
BC = sqrt( ( _Cx - _Bx ) ^ 2 + ( _Cy - _By ) ^ 2 );
CD = sqrt( ( _Dx - _Cx ) ^ 2 + ( _Dy - _Cy ) ^ 2 );
DA = sqrt( ( _Dx - _Ax ) ^ 2 + ( _Dy - _Ay ) ^ 2 );

// Finding angle of the vertices of ABCD
CAD = atan( CD / DA );		CAB = atan( BC / AB );		/*Hence,*/ DAB = RadToDeg( CAD + CAB );
DBA = atan( DA / AB );		DBC = atan( CD / BC );		/*Hence,*/ ABC = RadToDeg( DBA + DBC );
ACB = atan( AB / BC );		ACD = atan( DA / CD );		/*Hence,*/ BCD = RadToDeg( ACB + ACD );
BDC = atan( BC / CD );		BDA = atan( AB / DA );		/*Hence,*/ CDA = RadToDeg( BDC + BDA );

Title =
"Proof 1: All sides of ABCD are equal (in pixels)" +
StrFormat( "\nAB = %1.2f, BC = %1.2f, CD = %1.2f, DA = %1.2f", AB, BC, CD, DA ) +
"\nAB = BC = CD = DA = " + WriteIf( AB == BC && BC == CD && CD == DA, "True", "False" ) +
"\n\nProof 2: All vertices of ABCD are of 90°" +
StrFormat( "\nDAB = %1.0f°, ABC = %1.0f°, BCD = %1.0f°, CDA = %1.0f°", DAB, ABC, BCD, CDA ) +
"\nAngle A = B = C = D = " + WriteIf( DAB == ABC && ABC == BCD && BCD == CDA, "True", "False" )
;
//////////////////////////////////////////////////////////////
}

Plot( C, "Price", colorDefault, styleCandle );
RequestMouseMoveRefresh();
_SECTION_END();
``````

Yes!

And scaling as Tomasz wrote about it here. Quoting him:

4 Likes

Hello Cougar,
Thank you for taking time & providing updated code. I have tried it on different instruments & different time frames. I have tried drawing square on S&P500 - M5, H1 & D1 and EURUSD - M5, H1 & D1 charts. Its working good now.

Thank you.

Why the update code is a backward draw when I choose Peak and Vallery. Can you show for the updated code? It is useful.

Hi,
I tried to draw circle around the square, have read help file etc, still I am unable to draw it properly.

``````        	GfxSelectStockObject( 5 );
Cirstar = (( _Ax + _Ay ) + ( _Cx + _Cy ))/2 ;
yAxisM = ( _Ax + _Ay );
r = sqrt(( _Bx + _By )^2 + ( _Dx + _Dy )^2);
GfxMoveTo(_Ax,_Ay);
GfxCircle  ( Cirstar, yAxisM, r);
``````

``````         	 Cen1 = (_Ax + _Cx)/2 ; Cen2 = (_Ay + _Cy)/2 ;
rad = sqrt( (_Ax+_Cx) + (_Ay+_Cy))  +sqrt((_Bx+_Dx) +(_By+_DY))  ;
GfxSelectStockObject( 5 );
``````

Looks like found solution.

``````		 Cen1 = (_Ax + _Cx)/2 ; Cen2 = (_Ay + _Cy)/2 ;
rad = sqrt( dX ^ 2 + dY ^ 2 )/2;
r = (sqrt( ( _Cx - _Bx ) ^ 2 + ( _Cy - _By ) ^ 2 ))/1.41;
GfxSelectStockObject( 5 );
GfxCircle(Cen1, Cen2,r);
``````
2 Likes

if someone wants Circle from trendline....

``````GfxCircle(Px,Py,rad);
``````
2 Likes

Hi Cougar,

is there anyway can make the afl become explorable ;

• point A and B either top or valley for days range input in parameter
• filter exploring point C if valley is in A and Top is in B , vice versa for point D

i try to modif the code but not working at all.

Thank you