Has anyone done some thing like one in red circles?

earningMarker

2 Likes

@mmqp I do not understand what is the purpose of the posted chart, but you can add images and extra text to your charts using the low-level graphics functions. For example:

GfxSetBkMode(1); // transparent
GfxSetTextColor(colorYellow);
GfxSelectFont("Arial", 9);
GfxDrawText("23.01", 235, 486, 265, 500, 5);
GfxDrawImage("C:\\downloads\\phone.bmp", 238, 500);

gfx

Probably, depending on what you want to achieve, you will have to calculate the text, x-y coordinates, and visibility dynamically.

I suggest studying the documentation for the function GfxSetCoordsMode() that could be useful in mode 3 to directly use bar references for the x coordinates and pixels for the y ones.

Please, see also this other thread to learn why it is better to use .bmp instead of .png images.

4 Likes

Thanks @beppe, that is exactly what I am looking for thank you.

FWIW, you do not need any external picture file to get telephone sign and other ones on chart but just single plottext* line to write unicode.

e.g.

unicode for telephone is

phone = "\u260E";

so,

PlotTextSetFont( "\u260E", "Symbola", size = 16, x = BarCount-2, y = Status("axisminy"), colorRed );

results in:

12

19 Likes

Hi fxshrat,

Innovative use of PlotTextSetFont() !

Can PlotTextSetFont() be used to replace PlotShape() if the developer runs out of shapes to use? The new "shape" needs to be positioned near the price bar, not at the bottom.

Sure you can.
You just need to iterate signals.
Here is example using Unicode star.

period = 20; 
m = MA( Close, period );
Buy = Cross( Close, m );
Sell = Cross( m, Close ); 

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

bi = Barindex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

shape1 = "\u260E";
shape2 = "\u2764";
dist1 = 15;
dist2 = 0;

PlotTextSetFont("", "Symbola", size = 16, lvb, 0, -1 );
for ( i = fvb; i <= lvb; i++ ) {
	if ( Buy[i] )	PlotText( shape1, i, L[i], colorGreen, -1, -dist1 );
	if ( Sell[i] )	PlotText( shape2, i, H[i], colorRed, -1, dist2 );
}

12


BTW, as for innovative... Unicode support has been implemented by @Tomasz but not by me. So he is the one sending thanks to.

9 Likes

The stuff I learn everyday. Next we need Emoji’s. :monkey_face:

I’m not really familiar with unicode besides the basics. Bit of research seems theirs many different versions and new ones get added to new editions. Not sure what edition is used by Amibroker, guessing something default to OS?

Nothing innovative here. Its documented and should be well known.

It is enough to just read the manual and release notes, everything is there. Just read it
Open "Release Notes" document (installed in AmIBroker directory) and read.

CHANGES FOR VERSION 5.94.0 (as compared to 5.93.0)

AFL: support for UCN (universal character numbers) \uXXXX where XXXX is hexadecimal character code. UCN output works in PlotText/PlotTextSetFont, GfxDrawText, GfxTextOut, Chart titles, Interpretation and Commentary windows. Requires Windows 2000 or higher

For example
heart "\u2764"
sun "\u2600"
star "\u2605"
EURO currency: "\u20ac"
Sigma (greek): "\u03a3"
alpha (greek): "\u03b1"
beta (greek): "\u03b2"
umbrella: "\u2602"
telephone: "\u260e"
hand pointing up "\u261D"

Tables of all UCN/Unicode characters
http://www.unicode.org


http://www.unicodemap.org

Various arrows:

Enclosed alphanumerics:

(note: NOT all glyphs (graphical representations of characters) are actually present in current font. This depends on your operating system. For example Segoe UI in Windows 7 has lots of characters, but Windows 8 has more,
if a glyph is missing usually an empty rectangle is drawn). DejaVu free font has lots of glyphs, Symbola free font has lots of weird shapes.

Plot( C, "", colorDefault );
PlotTextSetFont( "\u2665\u2126\u2191\u21d1\u24ee\u261D", "Segoe UI", 30, 20, HighestVisibleValue( C )/2 + LowestVisibleValue( C )/2 , colorRed );
Title = "A demo of UCN: "+EncodeColor(colorRed)+"\u2665\u2126\u2191\u20ac\u03a3\u03b2\u2602\u260E";
11 Likes

this is not really an important question but I was wondering if there is a way to center unicode symbols or any other symbol using PlotTextSetFont

below some code where I would like the arrow to be centered below the bar. I can use GfxTextOut for that but that is also not exactly centered. I tried to adjust the position when using PlotTextSetFont to be exactly centered below the bar but I didn't manage so far.

thanks

bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
Lx = LastValue( bi );

rightstrength = 5;//Param( "Right Strength", 5, 2, 50, 1 );
leftstrength = 10;//Param( "Left Strength", 10, 2, 50, 1 );

pk = H == HHV( H, leftstrength ) AND Ref( HHV( H, rightstrength ), rightstrength ) < H;
pk = pk AND Lx - ValueWhen( pk, bi ) > rightStrength;
tr = L == LLV( L, leftstrength ) AND Ref( LLV( L, rightstrength ), rightstrength ) > L;
tr = tr AND Lx - ValueWhen( tr, bi ) > rightStrength;

GraphXSpace = 5;
SetChartBkColor( colorBlack );
SetChartOptions( 1, chartShowDates );
Plot( C, "", colorWhite, styleCandle, Null, Null, 0, 0, 1 );

PlotShapes( shapeSmallCircle * tr, ColorRGB( 0, 0, 255 ), 0, L, -5 );
PlotShapes( shapeSmallCircle * pk, ColorRGB( 255, 0, 0 ), 0, H, 5 );

GfxSetZOrder( -1 );
GfxSetCoordsMode( 1 );

sz = Param( "Font Size", 20, 0, 50, 1 );
ft = "Segoe UI";
//ft = "Symbola";
//ft = "DejaVu";

GfxSelectFont( ft, sz ); // method 1
GfxSetTextColor( colorBrightGreen ); // method 1
GfxSetTextAlign( 6 );// method 1

for( i = fvb + 1; i <= lvb; i++ )
{
    if( tr[i] )
    {
        str =  "\u2191";

        // method 1
        GfxTextOut( str, i, L[i] ); // uses GfxSetTextAlign

        // method 2
        PlotTextSetFont( str, ft, sz, i, L[i], colorYellow, colorDefault, -sz * 3 );
    }
}


Shifting unicode text in x-direction one can simply add or subtract a fractional part to 2nd argument of PlotText function or to 4th argument of PlotTextFont function.

So using the telephone/heart example of this post

I added this one to it

slvb = Status("LastVisibleBar");
num_bars = slvb-fvb+1;
shift_value = 0.003;
x_shift = shift_value*num_bars;

-> So,

/// 1. Plotting unicode text per TRUE signal
/// 2. Shifting unicode text in x-direction
///    x_shift either has to be added or substracted from i depending on the unicode. 
///    shift_value may be modified depending on unicode too.

/// @link https://forum.amibroker.com/t/has-anyone-done-some-thing-like-one-in-red-circles/18268/10
m = MA( Close, 20 );
Buy = Cross( Close, m );
Sell = Cross( m, Close ); 

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

bi = Barindex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

shape1 = "\u260E";
shape2 = "\u2764";
dist1 = 20;
dist2 = 5;
size = 16;

slvb = Status("LastVisibleBar");
num_bars = slvb-fvb+1;
shift_value = 0.003;
x_shift = shift_value*num_bars;

PlotTextSetFont("", "Symbola", size, lvb, 0, -1 );
for ( i = fvb; i <= lvb; i++ ) {
	if ( Buy[i] )	PlotText( shape1, i-x_shift, L[i], colorGreen, -1, -dist1 );
	if ( Sell[i] )	PlotText( shape2, i-x_shift, H[i], colorRed, -1, dist2 );
}

Again, x_shift either has to be added or substracted from i depending on the unicode. shift_value may be modified depending on unicode too.

BTW for num_bars calculation I use slvb = Status("LastVisibleBar"); instead of lvb = LastVisibleValue( bi ); because there may be blank right margin which is included in visual chart area too.

Before:

24

After:

23

It also works acceptably for different zoom levels

8

4 Likes

thanks, yes I also tried to add a shift but I do not find that works very good. Maybe indeed for a certain symbol and certain fontsize. But I did not manage to find a general method to shift the symbol to a precise centered position below the bar when you for instance zoom in/out or change the fontsize or the symbol.

I used a shift based on the chart settings using this

nbars = visible_bars = Min( lvb - fvb, BarCount - fvb );

pxh = Status( "pxchartheight" );
pxw = Status( "pxchartwidth" );

miny = Status( "axisminy" );
maxy = Status( "axismaxy" );
dy = maxy - miny;

pxwPerBarUnit = SafeDivide( pxw, nbars );
pxhPerPriceUnit = SafeDivide( pxh, dy );

barsPerpxw = SafeDivide( nbars, pxw );
pricePerpxh = SafeDivide( dy, pxh );

Then I think GfxTextOut in combination with GfxTextAlign works better. Using this method the symbol stays at the same "centered" position if you for instance change the fontsize or zoom in and out. Also the position is stable from 1 symbol to the next. But it is not centered precisely.

No big deal. Maybe adding such a "centered" keyword to PlotTextSetFont is not possible.

So this method below works best imo. Maybe GfxDrawText could also work but I didn't manage yet

bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
Lx = LastValue( bi );

rightstrength = 5;//Param( "Right Strength", 5, 2, 50, 1 );
leftstrength = 10;//Param( "Left Strength", 10, 2, 50, 1 );

pk = H == HHV( H, leftstrength ) AND Ref( HHV( H, rightstrength ), rightstrength ) < H;
pk = pk AND Lx - ValueWhen( pk, bi ) > rightStrength;
tr = L == LLV( L, leftstrength ) AND Ref( LLV( L, rightstrength ), rightstrength ) > L;
tr = tr AND Lx - ValueWhen( tr, bi ) > rightStrength;

GraphXSpace = 5;
SetChartBkColor( colorBlack );
SetChartOptions( 1, chartShowDates );
Plot( C, "", colorWhite, styleCandle, Null, Null, 0, 0, 1 );

PlotShapes( shapeSmallCircle * tr, ColorRGB( 0, 0, 255 ), 0, L, -5 );
PlotShapes( shapeSmallCircle * pk, ColorRGB( 255, 0, 0 ), 0, H, 5 );

GfxSetZOrder( -1 );
GfxSetCoordsMode( 1 );

sz = Param( "Font Size", 20, 0, 50, 1 );
ft = "Segoe UI";
//ft = "Symbola";
//ft = "DejaVu";

GfxSelectFont( ft, sz ); // method 1
GfxSetTextColor( colorBrightGreen ); // method 1
GfxSetTextAlign( 6 );// method 1

for( i = fvb + 1; i <= lvb; i++ )
{
    if( tr[i] )
    {
        //str = "\u2191";
        str = "\u21C8";

        // method 1
        GfxTextOut( str, i, L[i] ); // uses GfxSetTextAlign
    }
}

2 Likes

Thank you very much @fxshrat for the elegent code. Many years ago I had also used "PlotTextSetFont" to plot exotic graphics on my chart; and as usual was delighted by the features of the Software (Big Results with minimum resources).

I had experienced a bit of unexpected behaviour also; and just to review recency of my understanding I plotted your code also. And AGAIN I was delighted to observe the elegence of your code.

I find that you are using "PlotTextSetFont" to JUST set the Font & for actual plotting the Text you are using the legacy "PlotText" Function. (I was simply using "PlotTextSetFont" for the complete job.)

Actually, this was the unexpected behaviour; I had faced at that time:
"PlotTextSetFont" seems to set the Font for all subsequent calls of Legacy "PlotText" also - You have turned the Unexpected behaviour into a Feature. At that time I had thought of requesting @Tomasz to please have a function "PlotTextRestoreFont" also (Just like RestorePriceArrays). Since the context is fresh here - may I request @Tomasz to please consider to provide the "PlotTextRestoreFont" without the necessity of FeedBack Centre? :slightly_smiling_face:

Thank you @fxshrat and @Tomasz for delighting again & again.

With Regards

Sanjiv Bansal

I have a screen resolution of 3840 x 2160 and usually have about 1 year of daily bars (~260) on my screen, so PlotShapes and other icons are too small for my old eyes to see. Thanks to efforts by fxshrat, beppe, empottasch, mmqp, and Tomasz, it's easier for me to visualize trading signals. Ed Pottasch mentioned that scaling and alignment was a problem with unicode shapes, so I offer what I use to help alleviate those problems. It's not a cure, but it helps.

//------------------------------- Simple Entry Example --------------------------------------------------------

BuyMAPeriods = Param( "BuyMAPer", 15, 3, 50, 1 ); 
SellMAPeriods = Param( "SellMAPer", 46, 3, 50, 1 );

ShortMAPeriods = Param( "ShortMAPer", 44, 3, 50, 1 ); 
CoverMAPeriods = Param( "CoverMAPer", 8, 3, 50, 1 );

Y = ParamField( "Input Prices", 3 );

BuySig = MA(Y,BuyMAPeriods);
SellSig = MA(Y,SellMAPeriods);
ShortSig = MA(Y,ShortMAPeriods);
CoverSig = MA(Y,CoverMAPeriods);

Buy = Cross( Y, BuySig );

Sell = Cross( Sellsig, Y );

Short = Cross(ShortSig, Y);

Cover = Cross(Y,CoverSig);

//-------------------------------------- TRADE SIGNALS ---------------------------------------
// https://forum.amibroker.com/t/has-anyone-done-some-thing-like-one-in-red-circles/18268/10
// Code by fxshrat, beppe, empottasch, mmqp, and Tomasz
// Tweaks by CE

if( Status( "action" ) == actionIndicator )
{

//Buy = ExRem( Buy, Sell );
//Sell = ExRem( Sell, Buy );

//Short = ExRem( Short, Cover );
//Cover = ExRem( Cover, Short );

bi = Barindex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
Z1 = LVB-FVB;// Number of visible bars
BIR = Status("barinrange");

Plot( C, "C", colorgrey50, styleline , Null, Null, 0, 0, 2 );

PlotSpec = ParamList("Specific Plots", "Buy|Short",0 ); 

if( PlotSpec == "Buy" ) 
{
Plot( BuySig, "BuySig", colorgreen,1, Null, Null, 0, 0,2);
Plot( SellSig, "SellSig", colorred,1, Null, Null, 0, 0, 2 );

buyshape = "\u25B2";// solid triangle
sellshape = "\u25BC";
dist1 = Param("Buy-Sell Shapes Distance",60,20,200,1);

size = Max(int(1157/Z1),10);

PL = Y;// Select line to plot the shapes on

Bx_shift = Remap(Z1,80,261,0.27,0.5);
Sx_shift = Remap(Z1,80,261,0.27,0.5);

PlotTextSetFont( "", "Symbola", size, lvb, 0, -1 );

for( i = fvb; i <= lvb; i++ )
{
    if( Buy[i] AND BIR[i] ) PlotText( buyshape, i - Bx_shift, PL[i], colorGreen, -1, -dist1 );

    if( Sell[i] AND BIR[i] ) PlotText( sellshape, i - Sx_shift, PL[i], colorRed, -1, dist1 );
}

}

if( PlotSpec == "Short" ) 
{

Plot( ShortSig, "ShortSig", colorGreen,1, Null, Null, 0, 0,2 );
Plot( CoverSig, "CoverSig", colorRed,1, Null, Null, 0, 0, 2 );

shortshape = "\u25BD";// hollow triangle
covershape = "\u25B3";
dist2 = Param("Short-Cover Shapes Distance",60,20,200,1);
size = Max(int(1157/Z1),10);

PL = Y;// Line to plot the shapes on

Sx_shift = Remap(Z1,72,261,0.15,0.3);
Cx_shift = Remap(Z1,72,261,0.15,0.35);

PlotTextSetFont( "", "Symbola", size, lvb, 0, -1 );

for( i = fvb; i <= lvb; i++ )
{
    if( Cover[i] AND BIR[i] ) PlotText( covershape, i - Cx_shift, PL[i], colorRed, -1, -dist2);

    if( Short[i] AND BIR[i] )	PlotText( shortshape, i - Sx_shift, PL[i], colorGreen, -1, dist2);
}

}

GraphXSpace = 15;

}

//

In the code above, I use Z1 to adjust the size variable to keep the font size consistent through zoom changes. I also use the Remap function to adjust the x-axis shift which also changes with various zoom levels.
I found more useful shapes at https://www.unicode.org/charts/PDF/U2B00.pdf

Really unexpected? When you guys will do yourself a favor and start READING THE MANUAL ?????

If you did: AFL Function Reference - PLOTTEXTSETFONT

you would see this sentence:

The function also sets font for all subsequent calls to PlotText().

Is it rocket science to read the manual????

And no, there is no need for any "restore". Just can just set the "old" font yourself ("Arial")

And no, PlotText is NOT "legacy" function. I don't know from where people get such "ideas". PlotText is as "modern" as any other function.

3 Likes

Nice thread. I use a lot PlotText and PlotTextSetFont and a feature I miss is to be able of plotting also with data set on styleLeftAxisScale. It will be nice to have this feature avalaible in upcoming Ami Versions.
Best Regards

Rob.

1 Like