Draw Square where One side of that square is Trendline

3rd screenshot mentioned in the post above, please.

Square%20to%20be%20drawn%20on%20chart1%20updated

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();

1

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.
Square%20to%20be%20drawn%20on%20chart1%20updated1

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,
Thank you for your comments & Hint.
I will try to DIM (Do it myself) & apply those changes.

Thank you.

Do share your efforts!

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... :slight_smile:

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.
Capture%60
Capture1

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
// Link: http://www.amibroker.com/kb/2009/03/30/how-to-convert-from-bar-value-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 ) ); }

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, 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.

Hello Trader123,

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);

Screenshot 2020-07-17 at 9.53.57 PM

Made some progress, still unable to calculate proper radius. Image didn't got uploaded.Screenshot 2020-07-18 at 9.40.34 PM

         	 Cen1 = (_Ax + _Cx)/2 ; Cen2 = (_Ay + _Cy)/2 ; 
		 rad = sqrt( (_Ax+_Cx) + (_Ay+_Cy))  +sqrt((_Bx+_Dx) +(_By+_DY))  ;
		 GfxSelectStockObject( 5 ); 
		 GfxCircle(Cen1,Cen2,rad);pe or paste code here

Looks like found solution.
Screenshot 2020-07-18 at 9.58.36 PM

		 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,rad);
		 GfxCircle(Cen1, Cen2,r);
2 Likes

if someone wants Circle from trendline....Screenshot 2020-07-19 at 1.16.13 PM

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

AMI 1
AMI 2