Loading...
[-]

AJAX Push – Comet

After reading what underdog discovered about Yahoo Finance’s streamerapi I decided to get try to the data directly into an HTML page in IE8.

Go to Yahoo finance and with IE8′s debugger set a breakpoint in the yfs_concat.js file on the loadUrl (214) with a watch on url to get the streamerapi call.

Usually this is minified, fortunately Yahoo must have been debugging when I grabbed this screenshot.

Open that URL in IE8 and the status bar starts filling so we can see something is happening. Right click and view source to see the stream of script commands.

View Source

Monitoring the feed with wireshark

GET /streamer/1.0?s=DX-Y.NYB,AUDUSD=X,EURUSD=X,USDJPY=X,GBPUSD=X,CLF10.NYM,GCZ09.CMX,USD=X,^GSPC,^IXIC,^DJI&
  k=c10,l10,p20,t10&callback=parent.yfs_u1f&mktmcb=parent.yfs_mktmcb&gencallback=parent.yfs_gencb HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap,
  application/x-shockwave-flash, */*
Accept-Language: en-AU,zh-TW;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727;
  .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
Accept-Encoding: gzip, deflate
Host: streamerapi.finance.yahoo.com
Connection: Keep-Alive
Cookie: B=dpcg5595g36bh&b=3&s=qb; adx=c83020@1259630968@1; YSC=0; Q=q1=AACAAAAAAAAAAA--&q2=SxeGOg--;
  PRF=&t=EURUSD=X+GCZ09.CMX+CLF10.NYM+DX-Y.NYB+EURUSD%3DX+AUDUSD%3DX+AUDUSD%3DX+AUDUSD&cp=interactive&
  cd=symbol%3Agcz09.cmx_@range%3A5d_@indicator%3Avolume_@charttype%3Aline_@crosshair%3Aon_@ohlcvalues%3A0_@
  logscale%3Aon_@source%3Aundefined; TT=tick1=0&tick2=0&tick3=1

HTTP/1.1 200 OK
Cache-Control: private
Connection: Keep-Alive
Server: Yahoo! Finance Push Server - v1.0.3
Content-Type: text/html

<html><head><script type='text/javascript'> document.domain='finance.yahoo.com';</script> </head><body></body>
<script>try{parent.yfs_u1f({"USD=X":{l10:"1.00",c10:"0.00",p20:"0.00"}});}catch(e){}</script>
<script>try{parent.yfs_u1f({"^IXIC":{l10:"2214.47",c10:"+13.42",p20:"+0.61"}});}catch(e){}</script>
<script>try{parent.yfs_u1f({"^DJI":{l10:"10497.42",c10:"+45.42",p20:"+0.43"}});}catch(e){}</script>
<script>try{parent.yfs_u1f({"GBPUSD=X":{l10:"1.6386",c10:"+0.0117",p20:"+0.72"}});}catch(e){}</script>
<script>try{parent.yfs_u1f({"AUDUSD=X":{l10:"0.9012",c10:"-0.0048",p20:"-0.52"}});}catch(e){}</script>

shows Yahoo opens an HTTP connection, sends a head and body tags and then slowly sends a series of script tags without ever sending a tag or closing the connection. However I have noted that I reliably lose the connection at GMT 1030 so I assume Yahoo is reseting their servers. The yfs_mktmcb (market time callback?) callback is called every 300s so it acts as a heartbeat, you could use setTimeout and if you don’t get a response within 300+x seconds then reconnect.

After seeing the stream running I moved to the next step. Initially I used an XMLHttpRequest from a local file (IE8 ignores cross domain issues when source HTML is local) but unfortunately since the streamer never completes readyState stays 3 forever and neither responseText nor responseBody ever become available.

I then tried a change of direction, using an html file with a hidden iframe containing the streamerapi call, which is how Yahoo does it, but cross domain scripting restrictions prevented that from working even from localhost. Searching turned up a similar problem on Experts Exchange but the answer didn’t appear on their website, looking on the Google cached version of the page (click cache then scroll to the bottom) instead I found that if you are creating a HTA or HTML Application then you can set your iframe up with “application=yes” and it will conveniently ignore cross domain issues.

Google's cached view of Experts Exchange

Armed with that information I was put together a small HTA debugging tool which consumes the stream, shows the scripted commands as they arrive and changes the window title to the most recent price of the “AUDUSD”. You can download it here (may need to unblock to get it running). Since HTAs are trusted applications which happen to be written in HTML you can do things like write to disk, this could be used to stream the data to a file or you could process the stream and build an HTA ticker application.

A similar technique might work to consume LightStreamer and other push technologies but I haven’t tried.

You might also be interested in: CheesyFinance.HTA which adds some graphing and logging to disk.

3 Comments

  1. Bobby
    Posted March 4, 2010 at 02:39 | Permalink

    Great post! Thanks for sharing this info.
    I’ve been looking something like this as I cannot find much info out there on the streamerapi .

    I want to ultimatly login to my yahoo finance account and download streaming quotes for my portfolio to a csv file or upload the data directly to a db, do you know if this would be possible using javascript?

  2. Posted March 5, 2010 at 09:57 | Permalink

    I’d say yes in theory, if Yahoo is using the same Comet mechanism then it should work fine but I don’t have a Yahoo finance account so I’ve never attempted it.

    If it does work then one thing you’ll need to watch for is server resets where you’ll need to reconnect. I haven’t done any real testing so I’m not sure how reliable the feeds are. I’d suggest running two streams simultaneously and when they fail fall back to requesting the prices using GET every few minutes until your streams can be restarted. In short what is in this post right now is a small, unreliable debugging tool which gives you a view into how Yahoo Finance delivers data, it is not anything production ready. Using it in the current form will result in randomly sized gaps in your data. Caveat emptor.

  3. B
    Posted December 20, 2010 at 04:18 | Permalink

    Great post ! Very interesting analysis.
    Does any of you have a C++ code that does it all, from connecting, maintaining the connection alive, and display/store quotes of multiple stocks simultaneously as they arive ?

    Thanks !

One Trackback

  1. By CheesyFinance.HTA – Cheesy Code on March 30, 2010 at 01:04

    [...] on from my earlier post on AJAX Push – Comet I decided to add some pure javascript graphing, a little logging to disk, some robustness to handle [...]

Post a Comment

Your email is never shared. Required fields are marked *

*
*