Using Z-order with VAP. Cursor/selector line synchronization between different charts

To be able to correlate price action on different Charts in different timeframes I want to add a Global Cursor which highlights a selected bar with a yellow circle on multiple charts at the same DateTime.

This highlight-circle should appear on top of the VAP but below the candle price chart.

No matter how I try I cannot succeed plotting the Highlight-Circle in between the price plot and the VAP. At some settings, the VAP covers the Highlight-Circle completely, even if it is in a different area. Yes, I have read all there is to read in the Help.

Can anyone tell me where I went wrong?

Thanks!

image

ZOrderPrice = Param( "Z-Order Price     .", 0, -10, 10, 1 );
Plot( C, "C", colorblack, styleCandle, Null, Null, 0, ZOrderPrice );

ZOrderCircle = Param( "ZOrder Circle", -1, -10, 10, 1 );
RequestMouseMoveRefresh();
x = GetCursorXPosition( 1 );
y = GetCursorYPosition( 1 );
GfxSetZOrder( ZOrderCircle );
GfxSelectSolidBrush( ColorYellow );
GfxSelectPen( colorYellow, 1 );
GfxCircle( x, y - 30, 30 );

ZorderVAP = Param( "ZOrder VAP", -2, -10, 10, 1 );
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
mx = PriceVolDistribution( H, L, V, 100, False, fvb, lvb );
bins = MxGetSize( mx, 0 );

GfxSetZOrder( ZorderVAP );
GfxSetCoordsMode( 1 );
GfxSelectPen( colorGold, 5 );
for( i = 0; i < bins; i++ )
{
    price = mx[ i ][ 0 ]; // price level
    relvolume = mx[ i ][ 1 ]; // relative volume 0..1
    relbar = relvolume * ( lvb - fvb + 1 );
    GfxMoveTo( fvb, price );
    GfxLineTo( fvb + relbar, price );
}
2 Likes

@Beaver, the Z-order seem to work here (if I correctly understood your request).

immagine

But to get the mouse cursor (circle) move in a right way I inverted these 2 lines:

GfxSetCoordsMode( 1 );
GfxSetZOrder( ZorderVAP );

Which version of AB are you using? I tested 6.28.0 - 64-bit.

3 Likes

Thank you beppe, but it still doesn't work. Also, the Coordinate's mode shouldn't affect the Z-Order, would it?

The thing is that when I set the VAP Z-Order behind the Circle:

Price = 0

Circle = -1 (Between price and VAP)

VAP = -2

The circle disappears completely no matter where on the chart is. It appears that the VAP affects the Z-Order differently from other objects but perhaps I am missing something obvious...

@SpinTrader(@Beaver let's try this:

ZOrderPrice = Param( "Z-Order Price     .", 0, -10, 10, 1 );
ZOrderCircle = Param( "ZOrder Circle", -1, -10, 10, 1 );
ZorderVAP = Param( "ZOrder VAP", -2, -10, 10, 1 );

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

GfxSetZOrder( ZorderVAP );
mx = PriceVolDistribution( H, L, V, 100, False, fvb, lvb );
GfxSetCoordsMode( 1 );
bins = MxGetSize( mx, 0 );
GfxSelectPen( colorGold, 5 );
for( i = 0; i < bins; i++ )
{
    price = mx[ i ][ 0 ]; // price level
    relvolume = mx[ i ][ 1 ]; // relative volume 0..1
    relbar = relvolume * ( lvb - fvb + 1 );
    GfxMoveTo( fvb, price );
    GfxLineTo( fvb + relbar, price );
}

GfxSetZOrder( ZOrderCircle );
RequestMouseMoveRefresh();
GfxSetCoordsMode( 0 );
x = GetCursorXPosition( 1 );
y = GetCursorYPosition( 1 );
GfxSelectSolidBrush( colorBlue );
GfxSelectPen( colorWhite, 1 );
GfxCircle( x, y - 30, 30 );

Plot( C, "C", colorblack, styleCandle, Null, Null, 0, ZOrderPrice );

I'm using the default Z order params and this works properly on my machine (6.28.0 64-bits)

From SPY daily chart:
immagine

1 Like

i agree with @Beppe. It has to do with pixel mode and bar/price mode. This also seems to work:

//GfxSetZOrder( -128 ); // set to lowest possible z-order initially
GfxSetBkMode( 1 ); // set transparent mode
RequestMouseMoveRefresh();

// Price /////////////////////////////////////////////////////
ZOrderPrice = Param( "Z-Order Price", 0, -10, 10, 1 );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, ZOrderPrice, 1 );
// Price /////////////////////////////////////////////////////



// Circle /////////////////////////////////////////////////////
ZOrderCircle = Param( "Z-Order Circle", -1, -10, 10, 1 );
GfxSetZOrder( ZOrderCircle );
GfxSetCoordsMode( 0 ); // pixel mode
x = GetCursorXPosition( 1 );
y = GetCursorYPosition( 1 );
GfxSelectSolidBrush( ColorRGB( 128, 255, 255 ) );
GfxSelectPen( ColorRGB( 0, 255, 255 ), 1 );
GfxCircle( x, y, 30 );
// Circle /////////////////////////////////////////////////////



// VWAP /////////////////////////////////////////////////////
ZorderVAP = Param( "Z-Order VAP", -2, -10, 10, 1 );
GfxSetZOrder( ZorderVAP );
GfxSetCoordsMode( 1 ); // bar/price mode
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
mx = PriceVolDistribution( H, L, V, 100, False, fvb, lvb );
bins = MxGetSize( mx, 0 );
GfxSelectPen( ColorRGB( 255, 128, 255 ), 1 );
for( i = 0; i < bins; i++ )
{
    price = mx[ i ][ 0 ]; // price level
    relvolume = mx[ i ][ 1 ]; // relative volume 0..1
    relbar = relvolume * ( lvb - fvb + 1 );
    GfxMoveTo( fvb, price );
    GfxLineTo( fvb + relbar, price );
}
// VWAP /////////////////////////////////////////////////////
2 Likes

Thank you beppe, yes indeed it works beautifully now. Thank you very much for spending time on this!! That really helped me along.

Now I can finish my code, I'll post it when I have it all finished.

Have a super day!

Herman

1 Like

Thank you Ed, you guys are good :grin: This problem stumped me for days!

Happy trading, or should I say happy programming?

Herman

No, that is wrong. It has got to do with how z order function operates (it creates sorted display lists). That is the reason.

I am not referring to any thread code.

oh ok. So how would the correct code look like? Thanks

just got to say. If you remove my GfxSetCoordsMode from the code I posted it will not work. So ZOrder might work like you say it does but you need to juggle with the GfxSetCoordsMode else it will not work.

But of course I like to be proven wrong :slight_smile:

Yes, it works that way. You just need to understand what is meant by that.

It would still work without first coords mode. So yes you could remove first coords mode (just done by me to prove it) and under certain circumstances it will still show the circle. So it is mainly about z ordering and precedence. I have not moved anything and no other code or functions have been added to very first code. There is only one coords mode call at the bottom.

200920

2 Likes

Below is a beta version of what I wanted. Thanks everyone for all your help! I still don't understand why it didn't work by merit of Z-Orders alone but I am a happy beaver and I am moving on.

The idea is to place the code in an include file and include it in any charting system you may have. Depending on your setup the code may require a few modifications. I toggle the Global Cursor on/off with a single click in the top 10% of the Chart area. The Global Cursor in de-selected tracks the cursor DateTime and Price of the cursor in the selected chart - you can just move from chart to chart and the others will track. This makes it easier to correlate peaks and valleys across different timeframes - if you use a multi-chart setup.

Happy trading!
Herman

_SECTION_BEGIN( "GLOBAl CURSOR" );

function GfxConvertBarToPixelX( bar )
{
    lvb = Status( "lastvisiblebar" );
    fvb = Status( "firstvisiblebar" );
    pxchartleft = Status( "pxchartleft" );
    pxchartwidth = Status( "pxchartwidth" );

    return pxchartleft + bar  * pxchartwidth / ( Lvb - fvb + 1 );
}

function GfxConvertValueToPixelY( 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 ) * pxchartheight / ( Maxy - Miny + 10 ^ -10 ) );
}

function PlaceGlobalCursor( Trigger, Color, GlobalCursorZOrder )
{
    // External trigger toggles the Global cursor oen/off
    GlobalCursorOn = Nz( StaticVarGet( "GlobalCursorOn" ) );

    if( Trigger AND NOT GlobalCursorOn )
    {
        // Save parameters set on currently selected chart
        StaticVarSet( "GlobalCursorOn", True );
        StaticVarSet( "GlobalCursorZOrder", GlobalCursorZOrder, true );
        StaticVarSet( "GlobalCursorColor", Color, true );
    }
    else
        if( Trigger AND GlobalCursorOn )
            StaticVarSet( "GlobalCursorOn", false );

    GlobalCursorOn = Nz( StaticVarGet( "GlobalCursorOn" ) );

    if( GlobalCursorOn )
    {
        GlobalCursorZOrder 	= Nz( StaticVarGet( "GlobalCursorZOrder" ) );
        Color 				= Nz( StaticVarGet( "GlobalCursorColor" ) );

        // Use coordinates of currently selected chart
        CursorDT 		= GetCursorXPosition( 0 );
        CursorPrice 	= GetCursorYPosition( 0 );
        CursorOnChart 	= CursorDT > 0 AND CursorPrice > 0;

        if( CursorOnChart )
        {
            StaticVarSet( "CursorDT", CursorDT );
            StaticVarSet( "CursorPrice", CursorPrice );
        }

        CursorDT 	= StaticVarGet( "CursorDT" );
        CursorPrice = StaticVarGet( "CursorPrice" );

        // Convert selected DT and Price to pixels on other charts
        BI 				= BarIndex();
        fvb 			= Status( "firstvisiblebar" );
        lvb				= Status( "lastvisiblebar" );
        CursorBI 		= Lookup( BI, CursorDT ) - fvb;
        pxXcursor 		= GfxConvertBarToPixelX( CursorBI );
        ESCursorPrice 	= int( CursorPrice / ticksize ) * TickSize; // Trading ES
        pxCursorPrice 	= GfxConvertValueToPixelY( ESCursorPrice );

        GfxSetZOrder( GlobalCursorZOrder );
        pxchartBottom 	= Status( "pxchartbottom" );
        pxchartwidth  	= Status( "pxchartwidth" );
        GfxSetCoordsMode( 0 );
        GfxSelectSolidBrush( Color );
        GfxSelectPen( color, 1 );
        GfxMoveTo( pxXcursor, 0 );
        GfxLineTo( pxXcursor, pxchartBottom );
        GfxMoveTo( 0, pxCursorPrice );
        GfxLineTo( pxchartwidth, pxCursorPrice );
        GfxCircle( pxXcursor, pxCursorPrice, 30 );
    }
}


RequestMouseMoveRefresh();
Plot(C,"C",colorblack,styleCandle);

// Toggle Global Cursor on/off by clicking in the top 10% area of the Chart
pxchartBottom 	= Status( "pxchartbottom" );
LMBClick 		= GetCursorMouseButtons() == 9;
CursorYpixels 	= GetCursorYPosition( 1 );
Trigger 		= LMBClick AND CursorYpixels <= pxchartBottom*0.1;
GlobalCursorZOrder = -1; 
PlaceGlobalCursor( Trigger, Coloryellow, GlobalCursorZOrder );
_SECTION_END();

_SECTION_BEGIN("Volume At Price");
PlotVAPOverlay( Param("Lines", 300, 100, 1000, 1 ), Param("Width", 50, 1, 100, 1 ), ParamColor("Color", colorCycle ), ParamToggle("Side", "Left|Right" ) | 4*ParamToggle("Z-order", "On top|Behind", 0 ) );
_SECTION_END();


2 Likes

i am not seeing any cursor with that code, Herman.

Maybe someone can explain the following. First example: I stay in pixel mode. Since GfxSetCoordsMode( 0 ); is the default I will not call it at all. I just play with the ZOrder. In this case I place the cursor behind the price. This works as I would expect it would work.

GfxSetBkMode( 1 ); // set transparent mode
RequestMouseMoveRefresh();

// Price /////////////////////////////////////////////////////
ZOrderPrice = Param( "Z-Order Price", 0, -10, 10, 1 );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, ZOrderPrice, 1 );
// Price /////////////////////////////////////////////////////



// Circle /////////////////////////////////////////////////////
ZOrderCircle = Param( "Z-Order Circle", -1, -10, 10, 1 );
GfxSetZOrder( ZOrderCircle );
x = GetCursorXPosition( 1 );
y = GetCursorYPosition( 1 );
GfxSelectSolidBrush( ColorRGB( 128, 255, 255 ) );
GfxSelectPen( ColorRGB( 0, 255, 255 ), 1 );
GfxCircle( x, y, 30 );
// Circle /////////////////////////////////////////////////////

Now I add the VWAP. For the VWAP I need to use the "bar/price" mode. But since I call this at the bottom of the code I can leave the code I posted above unchanged (in my mind at least). So then I would get:

GfxSetBkMode( 1 ); // set transparent mode
RequestMouseMoveRefresh();

// Price /////////////////////////////////////////////////////
ZOrderPrice = Param( "Z-Order Price", 0, -10, 10, 1 );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, ZOrderPrice, 1 );
// Price /////////////////////////////////////////////////////



// Circle /////////////////////////////////////////////////////
ZOrderCircle = Param( "Z-Order Circle", -1, -10, 10, 1 );
GfxSetZOrder( ZOrderCircle );
x = GetCursorXPosition( 1 );
y = GetCursorYPosition( 1 );
GfxSelectSolidBrush( ColorRGB( 128, 255, 255 ) );
GfxSelectPen( ColorRGB( 0, 255, 255 ), 1 );
GfxCircle( x, y, 30 );
// Circle /////////////////////////////////////////////////////



// VWAP /////////////////////////////////////////////////////
ZorderVAP = Param( "Z-Order VAP", -2, -10, 10, 1 );
GfxSetZOrder( ZorderVAP );
GfxSetCoordsMode( 1 ); // bar/price mode
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
mx = PriceVolDistribution( H, L, V, 100, False, fvb, lvb );
bins = MxGetSize( mx, 0 );
GfxSelectPen( ColorRGB( 255, 128, 255 ), 1 );
for( i = 0; i < bins; i++ )
{
    price = mx[ i ][ 0 ]; // price level
    relvolume = mx[ i ][ 1 ]; // relative volume 0..1
    relbar = relvolume * ( lvb - fvb + 1 );
    GfxMoveTo( fvb, price );
    GfxLineTo( fvb + relbar, price );
}
// VWAP /////////////////////////////////////////////////////

However, now the cursor will not be visible. To make it visible I need to add GfxSetCoordsMode( 0 ); as follows:

GfxSetBkMode( 1 ); // set transparent mode
RequestMouseMoveRefresh();

// Price /////////////////////////////////////////////////////
ZOrderPrice = Param( "Z-Order Price", 0, -10, 10, 1 );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, ZOrderPrice, 1 );
// Price /////////////////////////////////////////////////////



// Circle /////////////////////////////////////////////////////
ZOrderCircle = Param( "Z-Order Circle", -1, -10, 10, 1 );
GfxSetZOrder( ZOrderCircle );
GfxSetCoordsMode( 0 ); // pixel mode
x = GetCursorXPosition( 1 );
y = GetCursorYPosition( 1 );
GfxSelectSolidBrush( ColorRGB( 128, 255, 255 ) );
GfxSelectPen( ColorRGB( 0, 255, 255 ), 1 );
GfxCircle( x, y, 30 );
// Circle /////////////////////////////////////////////////////



// VWAP /////////////////////////////////////////////////////
ZorderVAP = Param( "Z-Order VAP", -2, -10, 10, 1 );
GfxSetZOrder( ZorderVAP );
GfxSetCoordsMode( 1 ); // bar/price mode
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
mx = PriceVolDistribution( H, L, V, 100, False, fvb, lvb );
bins = MxGetSize( mx, 0 );
GfxSelectPen( ColorRGB( 255, 128, 255 ), 1 );
for( i = 0; i < bins; i++ )
{
    price = mx[ i ][ 0 ]; // price level
    relvolume = mx[ i ][ 1 ]; // relative volume 0..1
    relbar = relvolume * ( lvb - fvb + 1 );
    GfxMoveTo( fvb, price );
    GfxLineTo( fvb + relbar, price );
}
// VWAP /////////////////////////////////////////////////////

So how does this work? Is the code interpreted from the bottom up? Since it seems it now sets it to GfxSetCoordsMode( 1 ); before the cursor is plotted.

3 Likes

Herman, don't get me wrong - if your solution suits you, that's good, but in my opinion it is very inefficient, because:

  1. I think it can be coded without any "manual' conversion between bars/price and pixels (which you do). Probably it can be coded using only GfxSetCoordsMode(1) - bar / price mode where X is expressed in bar index and Y is expressed in price. If you really need using also pixel mode, other modes of GfxSetCoordsMode() should be enough. That would save a lot of unnecessary calculations.

  2. You use RequestMouseMoveRefresh() unconditionally - even if the solution is off.

  3. To work properly and be able to see the virtual cursor moving on the other charts, you need to force regular refreshes in all those charts (at least when you work offline).

... but the most important thing is, that a very similar result can be achieved in AmiBroker without any coding at all!

If you link some charts using Symbol link Icon --> Link you get selector line synchronization for free, and you can easily use SelectedValue() in all those charts to draw anything you want (for example your circle), without any regular/additional refreshes :wink:

Sync%202

https://www.amibroker.com/guide/h_sheets.html

Regards

3 Likes

... for example:

_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} - {{DATE}}"));
Plot(C, "C", colorDefault, styleCandle);

Bi = BarIndex();
GfxSetZOrder(-1);
GfxSetCoordsMode(1);
GfxSelectSolidBrush( colorYellow );
GfxSelectPen( colorOrange, 2 );
GfxCircle(SelectedValue(Bi), SelectedValue(C), -25);

Note: when using GfxSetCoordsMode(1) add minus (-) before radius, to be able to provide it's size in pixels.

Sync%20Circle%201

No regular or additional refreshes are required. All linked charts are refreshed when you click just one of them! - That's very convinient!

4 Likes

@Milosz
while your solution is probably the best one for many users, anyway, the @Beaver formula may be useful if someone prefers to work with "unlinked" symbols, for instance, to compare different but correlated instruments (like stocks to an ETF that includes them).

To improve it a bit, as you noted, it is possible to activate the "refreshes" using conditional code. In the included formula as:

if (Nz( StaticVarGet( "GlobalCursorOn" ) ))
	RequestMouseMoveRefresh();
Plot(C,"C",colorDefault,styleNoDraw|styleNoLabel|styleNoTitle);

(I also changed the "close" Plot line in order to use other styles/colors in my charts).

The same use of a conditional applies to other charts using the include file (to enable refreshes offline).

if (Nz( StaticVarGet( "GlobalCursorOn" ) ))
	RequestTimedRefresh(0.1);
1 Like

Yes, I agree @beppe, quite frankly I forgot that author's intention might be using different instruments, because I concentrated on this line:

... but in this situation:

  1. You can still use my simple solution (at least in some cases), using PlotForeign() in linked charts instead of Plot()

  2. In my opinion there is still much room for further improvements in Herman's code to make it lighter. As I wrote - I would get rid of any "manual' conversion between bars/price and pixels and try not to use any additional regular refreshes - especially RequestTimedRefresh(0.1). I would try another approach - similar to the one I proposed in this post:

I would try implementing "sync on click" solution (without using RequestMouseMoveRefresh() ) in which selected charts would be refreshed on demand (when mouse button is clicked) using OLE. But that might not be needed if the author will be using the code on the live market when all charts are regularly refreshed anyway.

... and that is just my point of view :wink: Some could say I pay too much attention to optimizing code, because the code is written to earn money and it can be executed on a very powerful machine - that's true - I understand that, but I just like to write my codes to be as light and effective as possible. That's my hobby :slight_smile:

2 Likes

I didn't have much time, but as an example I have prepared a much simpler (and lighter) example of a code with "Global cursor" This code can work with different Symbols and Intervals:

The main chart's code:

/// @link https://forum.amibroker.com/t/using-z-order-with-vap-cursor-selector-line-synchronization-between-different-charts/5979/18
// ----------------     Miłosz Mazurkiewicz    ---------------------------------------------

_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} - {{DATE}}" ) );
Plot( C, "C", colorDefault, styleCandle );

GlobalCursorON = ParamToggle( "GlobalCursorON", "No|Yes", 0 );
GlobalCursorColor = ParamColor( "GlobalCursorColor", colorBlue );
StaticVarSet( "GlobalCursorOn", GlobalCursorON );
StaticVarSet( "GlobalCursorColor", GlobalCursorColor);

if( GlobalCursorON )
{	
	BI = BarIndex();
    MouseButtonPressed = GetCursorMouseButtons();

    if( MouseButtonPressed )
    {
        CursorDT = SelectedValue( DateTime() );
        CursorBI = SelectedValue( BI );
        CursorPoint = BI == SelectedValue( BI );
        StaticVarSet( "GlobalCursorDT", CursorDT, true );
    }
    else
    {
        CursorDT = Nz( StaticVarGet( "GlobalCursorDT" ) );
        CursorBI = Nz(Lookup( BI, CursorDT, 1 ));
        CursorPoint = BI == CursorBI;
    }

    Plot( CursorPoint, "", GlobalCursorColor, styleHistogram | styleOwnScale | styleNoLabel, 0, 1, 0, 0, -80 );

    GfxSetZOrder( -1 );
    GfxSetCoordsMode( 1 );
    GfxSelectSolidBrush( colorYellow );
    GfxSelectPen( colorOrange, 2 );
    //GfxCircle( CursorBI, SelectedValue( C ), -25 );
    GfxCircle( CursorBI, C[CursorBI], -25 );
}

RequestTimedRefresh( 0.5 );  // Just for demonstration

... and all other charts' code:

/// @link https://forum.amibroker.com/t/using-z-order-with-vap-cursor-selector-line-synchronization-between-different-charts/5979/18
// ----------------     Miłosz Mazurkiewicz    ---------------------------------------------

_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} - {{DATE}}" ) );
Plot( C, "C", colorDefault, styleCandle );

GlobalCursorON = Nz( StaticVarGet( "GlobalCursorON" ) );
GlobalCursorColor = Nz( StaticVarGet( "GlobalCursorColor" ) );

if( GlobalCursorON )
{
    BI = BarIndex();
    MouseButtonPressed = GetCursorMouseButtons();

    if( MouseButtonPressed )
    {
        CursorDT = SelectedValue( DateTime() );
        CursorBI = SelectedValue( BI );
        CursorPoint = BI == SelectedValue( BI );
        StaticVarSet( "GlobalCursorDT", CursorDT, true );
    }
    else
    {
        CursorDT = Nz( StaticVarGet( "GlobalCursorDT" ) );
        CursorBI = Nz(Lookup( BI, CursorDT, 1 ));
        CursorPoint = BI == CursorBI;
    }

    Plot( CursorPoint, "", GlobalCursorColor, styleHistogram | styleOwnScale | styleNoLabel, 0, 1, 0, 0, -80 );

    GfxSetZOrder( -1 );
    GfxSetCoordsMode( 1 );
    GfxSelectSolidBrush( colorYellow );
    GfxSelectPen( colorOrange, 2 );
    GfxCircle( CursorBI, C[CursorBI], -25 );
}

RequestTimedRefresh( 0.5 ); // Just for demonstration

.. gives results similar to this one:

Sync%20Charts%203

In this code I haven't implemented the "refresh on demand" solution... but it can also be done.

Regards.

4 Likes

Thank you Miloz, I appreciate your comments!

Yes, it is rather bloated!! The code is basically a proof of concept and may be cleaned up later. My layout uses lots of gfx and mouse operations. I trade RT and date refreshed are always there. For me, it works smoothly over four charts and I usually don't spend too much time optimizing code unless there is a need for it. Otherwise, I'd rather move on to other topics.

Have a great day Miloz!

1 Like

Nice Miloz,

I will definitely look at the doing it without the pixel conversions - I expect that will work. I cut and pasted from other codes to create this routine. Some other features I added are freezing/unfreezing the Global cursor with a click on the chart and adding a DateTimeStr label to it. BTW, this Global Cursor is not always active, it is mostly for chart inspections and when you want to see resistance and support levels over multiple timeframes.

Another feature I might create is to place multiple shapeDigit (the small circles with a number in it) at click locations. These would remain on the chart as global reference points. I like that even better than the Global cursor :grin: and it would make it easier to document trades.

Yours, Milosz, works slightly different as you assigned a Master. In my case, whichever chart the cursor is over becomes the Master where I can turn the Global Cursor on/off, and the others charts would follow - you could say that all my charts are masters. For example, I can place orders from any timeframe/chart.

1 Like