Real-Time Charting for Nasdaq

Table of Contents
 1. Problem
 2. Solution
 3. Sample Output
 4. Sample Code
 5. WWW Page

1. Problem Top

Nasdaq was working on their first public web site and wanted to present near real-time graphs for their various indexes.

They had been working with their in-house group reponsible for the design and appearance of all Nasdaq products. The group had designed the web site and expected the appearance to be exactly as they had defined.

After working with various Microsoft and COTS graphing/charting packages for several months the engineering group was unable to create graphs/charts acceptable to the design group.

2. Solution Top

I had previously created similar appearing charts, in PostScript, for another hard copy product, the Corporate Record, produced by Nasdaq.

The design group remembered the graphs and ended up referring the engineering group to me.

The code needed to run in a Microsoft Windows NT environment. The needed to finalize size and placment of the graphs so the code needed to be flexible. It also needed to be done quickly as it was March and they wanted to roll out their web site in July.

It was written in C and developed on a HPUX system. The code was then tested on a Sun Solaris server and then the code was imported into a Microsoft Visual C environment under Windows NT and a DLL was created.

The DLL was used during the first three generations of the Nasdaq web site

3. Sample Output Top

The following are representative samples of the appearance of the graphs on the Nasdaq web site from 1996. You can find a sample page on the Internet Archive WayBackMachine although they don't seem to have captured the charts.


The Nasdaq Composite for March 1, 1996


The Nasdaq Composite for March 7, 1996

The Daily Nasdaq Composite Index Value and Volume as of Mar 1, 96

4. Sample Code Top

  if ( (ent->time[0]%100) < 10 ) {
    gdImageLine( summary_gif,
          x_line_offset+1+(long)(x_interval*0.0),
          graph_height+TOP_MARGIN,
          x_line_offset+1+(long)(x_interval*0.0),
          graph_height + 2+TOP_MARGIN,
          label_color );

    gdImageString( summary_gif, gdFontSmall,
          x_line_offset+1+(long)(x_interval*0.0) + 1,
          graph_height + 3+TOP_MARGIN,
          months[last_month], label_color );
  }

  for ( indx = 1; indx < ent->data1_indx; indx++ ) {
    
    if ( ! (flags[indx-1] & ND_NULL)
      && ! (flags[indx] & ND_NULL) ) {
      int      x = x_line_offset+1+(x_interval*indx);
      int      y;

      if ( indx == ent->data1_indx - 1 ) {
        points[0].x = x_line_offset+1+graph_width-2;
        points[0].y = Y_VOLUME_CALC( volume[indx] );
        points[1].x = x_line_offset+1+(long)(x_interval*(double)(indx-1));
        points[1].y = Y_VOLUME_CALC( volume[indx-1] );
        points[2].x = x_line_offset+1+(long)(x_interval*(double)(indx-1));
        points[2].y = graph_height-1+TOP_MARGIN;
        points[3].x = x_line_offset+1+graph_width-2;
        points[3].y = graph_height-1+TOP_MARGIN;
        gdImageFilledPolygon( summary_gif, points, 4, volume_color );
      } else {
        points[0].x = x_line_offset+1+(long)(x_interval*(double)indx);
        points[0].y = Y_VOLUME_CALC( volume[indx] );
        points[1].x = x_line_offset+1+(long)(x_interval*(double)(indx-1));
        points[1].y = Y_VOLUME_CALC( volume[indx-1] );
        points[2].x = x_line_offset+1+(long)(x_interval*(double)(indx-1));
        points[2].y = graph_height-1+TOP_MARGIN;
        points[3].x = x_line_offset+1+(long)(x_interval*(double)indx);
        points[3].y = graph_height-1+TOP_MARGIN;
        gdImageFilledPolygon( summary_gif, points, 4, volume_color );
      }
      gdImageLine( summary_gif,
            x_line_offset+1+(long)(x_interval*(double)indx),
            Y_VOLUME_CALC( volume[indx] ),
            x_line_offset+1+(long)(x_interval*(double)(indx-1)),
            Y_VOLUME_CALC( volume[indx-1] ),
            volume_outline_color );

      gdImageLine( summary_gif,
            x_line_offset+1+(long)(x_interval*(double)indx),
            Y_VALUE_CALC( data[indx] ),
            x_line_offset+1+(long)(x_interval*(double)(indx-1)),
            Y_VALUE_CALC( data[indx-1] ),
            value_color );

      gdImageLine( summary_gif,
            x_line_offset+1+(long)(x_interval*(double)indx),
            Y_VALUE_CALC( data[indx] ) + 1,
            x_line_offset+1+(long)(x_interval*(double)(indx-1)),
            Y_VALUE_CALC( data[indx-1] ) + 1,
            value_color );

      gdImageLine( summary_gif,
            x_line_offset+1+(long)(x_interval*(double)indx),
            Y_VALUE_CALC( data[indx] ) - 1,
            x_line_offset+1+(long)(x_interval*(double)(indx-1)),
            Y_VALUE_CALC( data[indx-1] ) - 1,
            value_color );

      gdImageLine( summary_gif,
            x_line_offset+1+(long)(x_interval*(double)indx),
            Y_VALUE_CALC( data[indx] ) + 2,
            x_line_offset+1+(long)(x_interval*(double)(indx-1)),
            Y_VALUE_CALC( data[indx-1] ) + 2,
            value_outline_color );

      gdImageLine( summary_gif,
            x_line_offset+1+(long)(x_interval*(double)indx),
            Y_VALUE_CALC( data[indx] ) - 2,
            x_line_offset+1+(long)(x_interval*(double)(indx-1)),
            Y_VALUE_CALC( data[indx-1] ) - 2,
            value_outline_color );

      if ( ((ent->time[indx]/100)%100) != last_month ) {
        int      day = (ent->time[indx]%100);

        last_month = ((ent->time[indx]/100)%100);

        gdImageLine( summary_gif,
            x_line_offset+1+(long)(x_interval*(double)indx)-day,
            graph_height+TOP_MARGIN,
            x_line_offset+1+(long)(x_interval*(double)indx)-day,
            graph_height + 2+TOP_MARGIN,
            label_color );

        if ( (long)(x_line_offset+1+(long)(x_interval*(double)ent->data1_indx)) - (long)(x_line_offset+1+(long)(x_interval*(double)indx)+1-day) > 19 ) {
          gdImageString( summary_gif, gdFontSmall,
              x_line_offset+1+(long)(x_interval*(double)indx)+1-day,
              graph_height + 3+TOP_MARGIN,
              months[last_month], label_color );
        }

        if ( ctl->x_grid_on ) {
          gdImageLine( summary_gif,
            x_line_offset+1+(long)(x_interval*(double)indx)-day,
            0+TOP_MARGIN,
            x_line_offset+1+(long)(x_interval*(double)indx)-day,
            graph_height - 1+TOP_MARGIN,
            grid_color );
        }
      }
    }
  }

5. WWW Page Top

Click here for a non-tabled version of this site.
Composite Index Total Share Volume
1242.48 +0.52 545,801,275
Nasdaq-100 Index Market Data as of
756.83 +1.06 Oct. 18, 96 Mkt Clsd
Button Bar

Oct. 18, 96 - The Nasdaq Stock Market Closed Up .52

Advanced - 1,898 Declined - 1,902 Unchanged - 1,874 New Highs - 158 New Lows - 78

Nasdaq Composite +0.52 Nasdaq-100 Index +1.06

Daily Nasdaq Composite Index Value and Volume as of Oct. 17, 96
Button Bar

Please give us feedback on our web site.

Neither Nasdaq, nor any of its affiliates or any of their officers, employees, directors, or agents: (1) has passed on the merit of any of these companies; or (2) has endorsed or sponsored any of these companies. ADVICE FROM A SECURITIES PROFESSIONAL IS STRONGLY ADVISED.
Click here for important information for investors

The Nasdaq Web Site uses technology from the following Nasdaq listed companies:

Microsoft BackOffice and Internet Information Server Cisco System's 7000 series high-speed Internet Routers
MCI's high speed InternetMCI service Intel architecture-based Pentium processor servers

© Copyright 1996, The Nasdaq Stock Market, Inc. All Rights Reserved.
Please read our Disclaimer.



For more information contact:
Steve Monroe
Phone: 540-822-3946
Internet: steve@pcthree.com