Sync symbol charted between two running AB instances

Hi Gents,

Curious if someone knows of an elegant hack for this. So when I double click a row in exploration results, the chart switches to that symbol, but I would also like another running instance of AB, that is open at the same time, that has a different loaded database, to also switch to that symbol? To make it more simple, just one chart is open in each instance. So, in effect having two instances of AB running and syncing current symbol in the chart?

Not a big deal, but I was just thinking about it and if it can easily be done.

With OLE, code embedded in AFL would default to that running instance.
So one way to work around this, would be to call an external script from the 2nd instance which would be triggered in the chart code.

The external script can then use AB.ActiveDocument.Name to set symbol for the first running instance.
Keeping the script, window hidden property, this would be most elegant imo.

A follow up question,
Are the instances open on multiple monitors?
You could use Autoit. It also has OLE support.

Then there are ways like using a file. I used a windows pipe, but the pipe server was in python.
And there is overhead of continuously checking if file is changed etc

Hi nsm51,
Same computer, probably a different monitor, but could be on the same monitor? How does which monitor matter?

that was for autoit, because in same monitor it would switch to the other instance and be a bit complicated etc. if 2 instances are on different monitors, then it is easier to identify.
Anyway, i'd still stick with OLE and work in the 2nd instance.

Meaning I run the OLE from the 2nd instance to get the charted symbol in the first instance? That gets messy and why I thought someone might have a clever more elegant way around doing that etc. Thanks for the input.

Read my post, OLE calls embedded inside AFL will default to that instance. You have to call a script from chart as it changes, while you click a symbol from Exploration.
the tiny script ( batch, JScript or JScript inside batch etc) will use OLE to change the symbol in the first instance.

What do you mean by messy?

Elegant way is only one, if Tomasz implemented it :smiley: the rest are all hacks

1 Like

LOL seriously. What I meant by "Messy" is OLE and instances, which instance A or B is opened first. I was under the impression OLE will only control or reference the first opened AB instance? You're saying OLE embedded in AFL in Instance "B", opened last (2nd) will control itself?

I think a good answer might lay in this forum post thread...

and here...

I'll delve deeper into it.

I reckon a straightforward hack would be to have AFL write the ticker name to file every couple of seconds, and have the client instance read the same file every few seconds.
If you get a corrupt file, it’s only going to be a few seconds before a new version is written anyway.

OK, this works but a hack, so I'm a bit embarrassed. If anyone has a better solution, then have at it. The issue as it were, is this chart button has to be run on the 2nd AB instance to be opened, because the OLE in the AFL targets the first running AB instance. You'll need to make a small graphic button and change the path to it....



// Sean O'Neill
// Enhances from Milosz original button click contribution.
//
// If you drag this onto chart in the SECOND TO OPEN instance of AB and
// assuming both have same symbol in their respective databases, then by 
// holding the ctrl keyboard button down and left mouse clicking, it will open the same
// symbol in first opened instance of AB.  The clipboard was used because initially
// this would work in reverse, with ClipboardSet on first instance and ClipboardGet
// on second instance, however OLE seems to just operate on the first opened
// instance of AB, rather than its own instance.


_SECTION_BEGIN( "Open Symbol in First Opened ABInstance" );
// "NOT NEEDED"
CurrentSymbol = Name();
PreviousSymbol = StaticVarGetText("PreviousSymbol");

GuiSetFont( "Segoe UI", 10.5 );
UseSymToOtherAB = ParamToggle( "Open Symbol in Another AB Graphic", "OFF|ON", 1 );
database = ParamStr("D:\\AB DataBases\\IEX_1Min","D:\\AB DataBases\\IEX_1Min");
Xshift = Param("Button Horiz Shift",60,0.00,600.00,5.00,1.00);
Yshift = Param("Button Vertical Shift",175,0.00,600.00,5.00,1.00);

graphicABIconPath = "C:\\Users\\Sean\\Pictures\\AB Icons\\Launch Extra AB Instance\\ABPlus.bmp";
graphicABPixelHeight = 49;
graphicABPixelWidth = 68;

// Record a change to charted symbol to clipboard and static var, "NOT NEEDED" 
if(CurrentSymbol != PreviousSymbol)
{
  // Code to execute when a new symbol is detected
  //Say("New symbol: " + CurrentSymbol, 1); // Example: Display a message
  ClipboardSet(Name());
  StaticVarRemove("MyVariable" + Name() + "*"); // Example: Remove previous symbol-specific variables
}
// "Also NOT NEEDED" 
StaticVarSetText("PreviousSymbol", Name()); // Update the Previous Symbol static variable


if(UseSymToOtherAB)
{
	sym = Name();
	GfxDrawImage(graphicABIconPath, 5 + Xshift , 5 + Yshift);
	MouseButtonPressed = GetCursorMouseButtons();
	CtrlABPressed =  GetAsyncKeyState( 17 ) < 0 ;
	x = GetCursorXPosition( 1 );  
	y = GetCursorYPosition( 1 );
	LogoABClicked = (x >=(5 + Xshift)  AND x<= (5 + Xshift + graphicABPixelWidth) ) AND (y >=(5 + Yshift) AND y<= (5 + Yshift + graphicABPixelHeight));

	if (CtrlABPressed AND LogoABClicked)
	{
		// Need to remove index prefix, i.e., $ from symbols like $SPX
		if ( StrCount(sym, "$") == 1)
		{
		
		}
		else
		{
			sym2 = ClipboardGet();	// Not needed can just use Name();
			ABa = CreateObject( "Broker.Application" );
			doca = ABa.ActiveDocument();
			doca.Name = sym2;
		}
	}
}
else
{
	GuiButton( "UseSymToOtherAB", 10, 5 + Xshift, 5 + Yshift, 100, 30, 255 );
	id = GuiGetEvent( 0, 0 ); event = GuiGetEvent( 0, 1 );
	sym = Name();

	// FYI  ":" = %3A  "&" = %26  etc.
	if( id == 10 AND event == 1 )
	{
		// Need to remove index prefix, i.e., $ from symbols like $SPX
		if ( StrCount(sym, "$") == 1)
		{
			
		}
		else
		{
			sym2 = ClipboardGet();	// Not needed can just use Name();
			ABb = CreateObject( "Broker.Application" );
			docb = ABb.ActiveDocument();
			docb.Name = sym2;
		}
	}
}
_SECTION_END();

While working with the data plugin, that is what I observed. It is a bit logical. Every AB instance will run its own OLE Server. So, within an instance, if I instantiate COleDispatchDriver -> it would find it within the process and not go out to ask windows.

In bold font, it is a Windows limitation that OLE points to the first running instance. If you close the 1st one, the 2nd becomes first. That is why ABs server is still loaded for each instance.

Maybe for AFL, it is like a guard. Ideally, OLE calls should originate from outside of AB otherwise it "will" create deadlocks.
Tomasz has written a lot of guard code to prevent this and that is why the user experience is so good.