Simulate QuoteTracker API

intraday
Tags: #<Tag:0x00007f2d7b3b52b8>

#1

I am writing a program to feed real time data into QT.DLL plugin.
Using AmiBroker version 6.00.2
The data display error on Real time quote window.
It displays data correctly when RT data received but change back to today first data record immediately.
I read the QT source code in ADK 2.10a

I guess the below variables are give wrong information to AmiBroker

ri->nDateChange
ri->nTimeChange
ri->nDateUpdate 
ri->nTimeUpdate
ri->nBitmap
ri->nStatus

in module of

Please help me to make it right!!!
Below is correspond module code from QT.dll

//////////////////////////////
// Timer Callback procedure
// It is called periodically to retrieve
// current quotes from QuoteTracker.
// It just issues request getLastQuote(ACTIVE)
// to QT HTTP server, reads the response
// and updates corresponding fields of recent info table
/////////////////////////////
 
VOID CALLBACK OnTimerProc(
  HWND hwnd,         // handle to window
  UINT uMsg,         // WM_TIMER message
  UINT_PTR idEvent,  // timer identifier
  DWORD dwTime       // current system time
  )
{
	struct RecentInfo *ri;

	if( idEvent == 199 || idEvent == 198 )
	{
		if( ! IsQuoteTrackerRunning() )
		{
			KillTimer( g_hAmiBrokerWnd, idEvent );
			SetupRetry();
			return;
		}
		
		try
		{
			CInternetSession oSession( AGENT_NAME, 1, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_DONT_CACHE );
			
			CString oURL;

			oURL.Format("http://%s:%d/req?getLastQuote(ACTIVE)", g_oServer, g_nPortNumber );

			CStdioFile *poFile = oSession.OpenURL( oURL,1, INTERNET_FLAG_TRANSFER_ASCII | INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE );

			if( poFile )
			{
				CString oLine;

				int iSymbol = 0;

				if( poFile->ReadString( oLine ) )
				{
					if( oLine == "OK" )
					{
						while( poFile->ReadString( oLine ) )
						{
							TRACE( oLine + "\n" );
							
							if( oLine.GetLength() < 20 ) continue;//AfxMessageBox("test");

							GrowRecentInfoIfNecessary( iSymbol );

							ri = &g_aInfos[ iSymbol ];
									
							char *line = oLine.LockBuffer();


							ri->nStructSize = sizeof( struct RecentInfo );
							strcpy( ri->Name, strtok( line, "," ) );

							int month = safe_atoi( strtok( NULL, "/-." ) );
							int day = safe_atoi( strtok( NULL, "/-." ) );
							int year = safe_atoi( strtok( NULL, "," ) );

							int hour = safe_atoi( strtok( NULL, ":." ) );
							int minute = safe_atoi( strtok( NULL, ":." ) );
							int second = safe_atoi( strtok( NULL, "," ) );

							float fOldLast, fOldBid, fOldAsk;

							fOldLast = ri->fLast;
							fOldBid = ri->fBid;
							fOldAsk = ri->fAsk;

							//->nTimeUpdate = ri->nTimeUpdate & ~0x07 + time(NULL) & 0x7;


							ri->fLast = (float) safe_atof( strtok( NULL, "," ) );
							ri->fBid = (float) safe_atof( strtok( NULL, "," ) );
							ri->fAsk = (float) safe_atof( strtok( NULL, "," ) );
							ri->fChange = (float) safe_atof( strtok( NULL, "," ) );

							// tick
							strtok( NULL, "," );

							double dTemp = safe_atof( strtok( NULL, "," ) ); 
							ri->iTotalVol = (int) dTemp;
							ri->fTotalVol = (float) dTemp;
 							ri->fHigh = (float) safe_atof( strtok( NULL, "," ) );
							ri->fLow = (float) safe_atof( strtok( NULL, "," ) );
							ri->iBidSize = safe_atoi( strtok( NULL, "," ) );
							ri->iAskSize = safe_atoi( strtok( NULL, "," ) );

							dTemp = safe_atof( strtok( NULL, "," ) ); 
							ri->iTradeVol = (int) dTemp;
							ri->fTradeVol = (float) dTemp;

							strtok( NULL, "," );
							strtok( NULL, "," );
							ri->fOpen = (float) safe_atof( strtok( NULL, "," ) );
							ri->f52WeekLow = (float) safe_atof( strtok( NULL, "," ) );
							ri->f52WeekHigh = (float) safe_atof( strtok( NULL, "," ) );


							ri->nDateChange = 10000 * year + 100 * month + day; 
							ri->nTimeChange = 10000 * hour + 100 * minute + second;

							if( ri->fLast != fOldLast || ri->fAsk != fOldAsk || ri->fBid != fOldBid )
							{
								ri->nDateUpdate = ri->nDateChange;
								ri->nTimeUpdate = ri->nTimeChange;
							}

							ri->nBitmap = RI_LAST | ( ri->fOpen ? RI_OPEN : 0 ) | ( ri->fHigh ? RI_HIGHLOW : 0 ) | RI_TRADEVOL | RI_52WEEK | 
								RI_TOTALVOL | RI_PREVCHANGE | RI_BID | RI_ASK | RI_DATEUPDATE | RI_DATECHANGE;	

							ri->nStatus = RI_STATUS_UPDATE | RI_STATUS_BIDASK | RI_STATUS_TRADE | RI_STATUS_BARSREADY;


							oLine.UnlockBuffer();

							iSymbol++;
						}
					}
				}

				::SendMessage( g_hAmiBrokerWnd, WM_USER_STREAMING_UPDATE, 0, 0 );

				poFile->Close();
				delete poFile;
		
			
				g_nStatus = STATUS_CONNECTED;
				g_nRetryCount = RETRY_COUNT;
			}

			oSession.Close();
		}
		catch( CInternetException *e )
		{
			e->Delete();
			KillTimer( g_hAmiBrokerWnd, idEvent );
			SetupRetry();
			return;
		} 

	}

	if( idEvent == 198 )
	{
		KillTimer( g_hAmiBrokerWnd, 198 );
		SetTimer( g_hAmiBrokerWnd, 199, g_nRefreshInterval * 1000, (TIMERPROC)OnTimerProc );
	}
}

///////////////////////////////

Moderator comment: Please use [code] tags for code. I fixed your post, but please next time follow “how to use this site” docs.


#2

First of all, the subject of the topic should reflect its content.
If you are giving it subject “QT plugin error” you are making false statement because you claim errors in QT plugin while the error is in your own code that you wrote to simulate QT.

Better and easier than writing program that simulates QuoteTracker HTTP API is to write your own plugin or use ASCII data plugin project (included in the ADK). It contains very simple code that would be much easier to adopt for your custom feed.

Secondly I am not sure if we should help anyone who tries to reverse engineer other people’s software (i.e. reverse engineer QuoteTracker)

Besides it is not clear what you are actually doing, are you modifying QT plugin? What for?
QT plugin works and should not be modified. If you intend to simulate QT HTTP feed you should just implement “the other side”, i.e. not the plugin but HTTP API that mimicks QT.

Or better yet as I wrote, use ASCII data project that is simpler.


#3

No sir, I did not modify QT plugin, I wrote “the other side” code only, to simulate QT HTTP feed. The code I listed is from ADK without any modified. QT.dll did not rebuild.


#4

If so, you need to emulate getLastQuote QuoteTracker HTTP API properly, returning data EACH time it gets called. You may be returning empty (or just “OK”) and then data would disappear.

You need to emulate QT API fully as documented, not by reverse engineering the QT plugin sources.
http://www.medved.net/quotetracker/help/qtserver.shtml#GetLastQuote

Emulating QT feed is not really AmiBroker question.


#5

Thanks for your help,
I am following your instructions, try to figure out what data that I send to QT.dll.
Original, I work on Windows 10 x64 PC.
now I setup Windows 7 x64 on VMware.
Run AB and my program without any modified on it.
They are working fine. RT window working fine.
I am OK now. Thank you for the help.