Getting stock quotes over the internet

Here's a simple Tcl script which will fire up a window to track a small portfolio of stocks. Nothing too fancy. I've included an example portfolio of three stocks, and a cash holding. To see your own portfolio, simply edit the 'shares' array, and the 'cash' variable.

 # Portfolio tracking by Vince Darley
 # This file may be freely modified, sold, changed, etc.  
 # If you do make useful changes, I would like a copy, 
 # although you aren't obligated to send me anything.
 # Ideas for future improvements: auto-update every N minutes, 
 # graphs of total portfolio value over time, 
 # ability to record changes in portfolio over time...
 exec wish "$0"

 package require http

 namespace eval portfolio {}

 set shares(AAPL) 550
 set shares(ORCL) 100
 set shares(INKT) 100
 set cash 3285.74

  # -------------------------------------------------------------------------
  # "portfolio::getInformation" --
  #  Takes a list of symbols, from Nasdaq, NYSE or even mutual funds etc.,
  #  and returns a list of results, one for each symbol given.  
  #  Each returned result is a string containing comma separated values, 
  #  in the order:
  #  symbol, price, date, ...
  #  We use a quote server from yahoo.
  # -------------------------------------------------------------------------
 proc portfolio::getInformation {symbols} {
     set query ""
     append query "/d/quotes.csv?s=[join $symbols +]&f=sl1d1t1c1ohgv&e=.csv"
     set token [http::geturl $query]
     set actual {}
     foreach res [split [string trim [http::data $token]] "\r\n"] {
         if {$res != ""} {
             set res [split $res ,]
             lappend actual [lreplace $res 0 0 [string trim [lindex $res 0] {{}""}]]
     return $actual

 proc portfolio::dumpData {data} {
     foreach result $data {
         set items [split $result ","]
         puts stdout $items

 proc portfolio::createWindow {portfolio} {
     foreach {s q} $portfolio {
         set w [symbolToWin $s]
         label ${w}symb     -text $s
         label ${w}price    -text ""
         label ${w}change   -text ""
         label ${w}quantity -text $q
         label ${w}value    -text ""
         grid ${w}symb ${w}price ${w}change ${w}quantity ${w}value
     button .update -text "Update" -command portfolio::updateAll
     label .total -text ""
     grid  .update .total
     wm title . "Portfolio"
     wm withdraw .
     wm deiconify .

 proc portfolio::symbolToWin {symbol} {
     return ".[join [string tolower $symbol]]"

 proc portfolio::updateWindow {data} {
     global cash
     if {[info exists cash]} {
         set total $cash
     } else {
         set total 0.0
     foreach items $data {
         set w      [symbolToWin [lindex $items 0]]
         set price  [lindex $items 1]
         set change [lindex $items 4]
         ${w}price  configure -text $price
         ${w}change configure -text $change
         set val [expr {[${w}quantity cget -text] * $price}]
         ${w}value configure -text $val
         set total [expr {$total + $val}]
     .total configure -text $total

 proc portfolio::updateAll {} {
     global shares
     updateWindow [getInformation [array names shares]]

 portfolio::createWindow [array get shares]

Also see