Sync charts for zoom and scroll

Here is the code that can be used to Synchronize charts and zoom.

/*<Usage>
Put this AFL in the Include Folder.
Add below 2 lines into your AFL
  UseZoomer = ParamToggle("Use Zoomer?", "No|Yes", 0);
  #include_once <iZoomer.afl>
  Sourcecode downloaded from: http://zaqimon.blogspot.co.uk/2012/09/synchronous-scrolling-in-amibroker.html
*/

function ZqZoomSync( force )
{
    // All variables are made local to guarantee naming collisions or side effects
    local LastBarIndex, FirstBarIndex, prevLastBarIndex, prevFirstBarIndex, prevFirstDateTime, DT, BI, LastDateTime, FirstDateTime, LastDateTimestr, FirstDateTimestr;
    local OAB, OAD, dcount, i, OADoc, OAW, OADocWin, res;
    // Get a count of the number of documents
    OAB = CreateObject( "Broker.Application" );
    OAD = OAB.Documents;
    dcount = OAD.Count;
    // Process multiple windows (documents)
    res = False;
    if ( dcount > 1 )
    {
        // Get current and last start and end DateTimes's
        LastBarIndex = Status( "LastVisibleBarIndex" );
        FirstBarIndex = Status( "FirstVisibleBarIndex" );
        //Nblankbar = Status( "LastVisibleBarIndex" ) - BarCount; // [zq] not used !!
        
        // [zq] BarIndex may always be the same due to QuickAFL, check prevFirstDateTime in addition
        prevLastBarIndex = Nz( StaticVarGet( "_prevLastVisibleBarIndex" ) );
        prevFirstBarIndex = Nz( StaticVarGet( "_prevFirstVisibleBarIndex" ) );
        prevFirstDateTime = Nz( StaticVarGet( "_prevFirstDateTime" ) );
        
        // [zq] move outside if() statement for checking prevFirstDateTime
        DT = DateTime();
        BI = BarIndex();
        LastDateTime = LastValue( ValueWhen( LastBarIndex == BI, DT ) ); // [zq] LastDateTime could be empty
        FirstDateTime = LastValue( ValueWhen( FirstBarIndex == BI, DT ) );
        
        // Check for a new date/time range
//        _TRACE(""+FirstBarIndex+", "+LastBarIndex);
        if ( LastBarIndex != prevLastBarIndex OR FirstBarIndex != prevFirstBarIndex OR FirstDateTime != prevFirstDateTime OR force )
        {
            // Set the new last values
            StaticVarSet( "_prevLastVisibleBarIndex", LastBarIndex );
            StaticVarSet( "_prevFirstVisibleBarIndex", FirstBarIndex );
            StaticVarSet( "_prevFirstDateTime", FirstDateTime );
            
            LastDateTimestr = DateTimeToStr( LastDateTime );
            FirstDateTimestr = DateTimeToStr( FirstDateTime );
//            _TRACE(""+FirstDateTimestr+", "+LastDateTimestr);
            // Loop through the document collection
            for ( i = 0; i < dcount; i++ )
            {
                // If it is not the active document -
                OADoc = OAD.Item( i );
                // NOTE - it doesn't hurt to sync the current window and it makes all
                // windows have no blank bars on the right so they look the same
                // [zq] I think it's reasonable for not syncing ActiveDocument.
                // [zq] Something not belong to the ActiveDocument was shown when not syncing ActiveDocument with multi-threaded charts options disabled.
                if ( OADoc != OAB.ActiveDocument )
                {
                    // Get the document window and zoom to range
                    //_TRACE( " Zoom to range document - " + i + " , " + Curststr + " - " + Curendstr );
                    OADW = OADoc.Windows;
                    // Document window count assumed to be 1
                    OADocWin = OADW.Item( 0 );
                    OADocWin.ZoomToRange( FirstDateTimestr, LastDateTimestr ); // [zq] this function failed to update chart at the right most margin with empty LastDateTimestr. Just minor issue, don't care.
                }
            }
            res = True;
        }
    }
    return res;
}

//  Call for synchronization
If (UseZoomer)
     ZqZoomSync( False ); // [zq] set True will enter infinite loop if we also update ActiveDocument
7 Likes