# Draw Square where One side of that square is Trendline

Hello Everyone,
I would like to draw a square as shown in the picture where one side of the square is trendline.
In other word, when someone draw a trendline, the aft program should draw a square using 2 points of the trendline. For example, trendline with point A & B , it will draw square where length of AB = BC = CD = DA and angles DAC = ABC = BCD = CDA = 90 degrees.!
Please, let me know how I can do that.Square%20to%20be%20drawn%20on%20chart1%20updated|689x454

Hi, and welcome to the forum.

What I recommend first of all is to read carefully until you understand about the maths that @Tomasz explained here about anisotropic charts.

# Need Help Gann Line

After reading the above links and if you agree to continue, then if you are good in afl coding you can achieve that by spending max two hours coding. So have a look of a readymade AFL codes that you can use to achieve your tool dream.

1 Like

Below is one (easy) way to solve your query. Hope it helps!

``````_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 );
}

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

As previously explained by Milosz, on a chart, 'Ctrl' held down and 'Mouse left button' down sets the co-ordinates of A. While in this state of Ctrl and Mouse left button down, drag the mouse for point B. Upon releasing either Ctrl or Mouse left button, locks the co-ordinates of B. To remove the lines drawn, hold down 'Ctrl' and click 'Mouse middle button'.

3 Likes

Thank you codejunkie, PanoS & Cougar for the help.
Cougar, I have copied the code & pasted it in formula editor, saved it in custom folder as Draw Square.afl I click on Chart -- custom -- Draw Square & then on chart , I did --- 'Ctrl' held down and 'Mouse left button' down sets the co-ordinates of A. While in this state of Ctrl and Mouse left button down, drag the mouse for point B. Upon releasing either Ctrl or Mouse left button, it should lock the co-ordinates of B. Though, I have observed that nothing is happening. it does not draw square on the chart upon doing it as mentioned above.

Also, after that Draw Square.afl was open in formula editor & I clicked on apply indicator. it gave an error as follows ---

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

Error 30. Syntax error, identifier 'requestmousemoverefresh' is undefined.
}

If possible, I need help on how to draw square, please.

Thank you.

The function `RequestMouseMoveRefresh()` is available from v6.21.0. Which version you are on?

I just tested the code again. And it is working! You need to upgrade your AmiBroker license.

1 Like

Hello Cougar,
Thank you very much for the help. I have upgraded Amibroker from 6.002 to 6.30.5 now & Draw Square.afl is working.
I have observed that when I choose point A & B, it is drawing rectangle as shown in the picture. (1st screenshot)
Also, when we draw the square, angle between CB and BA which is angle CBA or simply angle B should be 90 degree. similarly, angle between BA and AD which is angle BAD or simply angle A should be 90 degree. (2nd screenshot)
Also, when someone draw upward facing trendline which selecting point A as higher price point and selecting point B as lower price point, then draw square may be drawn on right side facing upward, please. (3rd screenshot)
If possible, can you look into above mentioned details, please.
Thank you once again for your help.

2nd screenshot

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.