| 1 | #! /usr/local/bin/python |
|---|
| 2 | ################################################## |
|---|
| 3 | # Name: barchart - Python BarCharts in SVG |
|---|
| 4 | # Author: Philip J Cooper <Philip.Cooper@openvest.org> |
|---|
| 5 | # Start date: 18 July 2003 |
|---|
| 6 | # Current Date:20 Feb 2006 |
|---|
| 7 | # Purpose: Get prices from ovpyq and produce an SVG Chart |
|---|
| 8 | # version Note:This uses ovpyq and is thus dynamic in how it |
|---|
| 9 | # updates as it queries. |
|---|
| 10 | ############################################################## |
|---|
| 11 | |
|---|
| 12 | __version__ = "0.4.0" |
|---|
| 13 | |
|---|
| 14 | import sys,cgi |
|---|
| 15 | import ovpyq, mx.DateTime |
|---|
| 16 | |
|---|
| 17 | if len(sys.argv)>1: |
|---|
| 18 | ticker=sys.argv[1] |
|---|
| 19 | else: |
|---|
| 20 | try: |
|---|
| 21 | query = cgi.FieldStorage() |
|---|
| 22 | if query.has_key("tick"): |
|---|
| 23 | ticker= query["tick"].value |
|---|
| 24 | else: |
|---|
| 25 | ticker= query["field_ticker"].value |
|---|
| 26 | except KeyError: |
|---|
| 27 | ticker = "RHT" |
|---|
| 28 | |
|---|
| 29 | |
|---|
| 30 | ## get the Name for the Ticker |
|---|
| 31 | name=ovpyq.getName(ticker) |
|---|
| 32 | |
|---|
| 33 | ## Get the History for the Ticker |
|---|
| 34 | ndays=365 |
|---|
| 35 | enddt=mx.DateTime.today() |
|---|
| 36 | begdt=enddt-ndays |
|---|
| 37 | hist=ovpyq.getCachedTicker(enddt-ndays,enddt,ticker) |
|---|
| 38 | |
|---|
| 39 | ################################################################ |
|---|
| 40 | |
|---|
| 41 | color="blue" |
|---|
| 42 | w=800.0 #this should be a float not an int |
|---|
| 43 | h=600.0 #this should be a float not an int |
|---|
| 44 | cw=w-100 |
|---|
| 45 | ch=h-100 |
|---|
| 46 | |
|---|
| 47 | ################################################################################ |
|---|
| 48 | ## begin the header |
|---|
| 49 | print "Content-type: image/svg+xml" |
|---|
| 50 | print "" |
|---|
| 51 | |
|---|
| 52 | print """<?xml version="1.0"?> |
|---|
| 53 | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" |
|---|
| 54 | "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> |
|---|
| 55 | """ |
|---|
| 56 | |
|---|
| 57 | ################################################################################ |
|---|
| 58 | ## set the coordinates/size |
|---|
| 59 | print '<svg xmlns="http://www.w3.org/2000/svg"' |
|---|
| 60 | print ' xmlns:xlink="http://www.w3.org/1999/xlink"' |
|---|
| 61 | print ' viewBox="0 0 %i %i">'%(w,h) |
|---|
| 62 | |
|---|
| 63 | ################################################################################ |
|---|
| 64 | ## add static filters and defs |
|---|
| 65 | print """ |
|---|
| 66 | <title>barchart.svg</title> |
|---|
| 67 | <desc>line graph</desc> |
|---|
| 68 | <defs> |
|---|
| 69 | <filter id="DropShadowFilter" filterUnits="objectBoundingBox" x="-10%" y="-10%" width="120%" height="120%"> |
|---|
| 70 | <feGaussianBlur in="SourceAlpha" stdDeviation="2" result="BlurAlpha"/> |
|---|
| 71 | <feOffset in="BlurAlpha" dx="4" dy="4" result="OffsetBlurAlpha"/> |
|---|
| 72 | <feMerge> |
|---|
| 73 | <feMergeNode in="OffsetBlurAlpha"/> |
|---|
| 74 | <feMergeNode in="SourceGraphic"/> |
|---|
| 75 | </feMerge> |
|---|
| 76 | </filter> |
|---|
| 77 | </defs> |
|---|
| 78 | """ |
|---|
| 79 | ################################################################################ |
|---|
| 80 | ## start the chart |
|---|
| 81 | print '<g id="chart" transform="translate(%i, %i)" style="filter:url(#DropShadowFilter)">'%(50,50+ch) |
|---|
| 82 | |
|---|
| 83 | ################################################################################ |
|---|
| 84 | ## add the company name |
|---|
| 85 | print '<text id="Company" x="50" y="-%i" font-size="30" style=";font-weight:Normal;text-anchor:left;stroke:%s;fill:%s" >%s</text>'%(ch+10,color,color,name) |
|---|
| 86 | |
|---|
| 87 | |
|---|
| 88 | ################################################################################ |
|---|
| 89 | ## add the x and y axis |
|---|
| 90 | print '<path d="M0,0H-5 0 V 5 -%i h -5 10 -5 V 0 H%i V 5 -5 0 H 0" style="fill:none;stroke:black"/>'%(ch,cw) |
|---|
| 91 | |
|---|
| 92 | ################################################################################ |
|---|
| 93 | ## lets do the x ticks labels and grid |
|---|
| 94 | mth=['','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] |
|---|
| 95 | stepx=1.0*cw/len(hist) |
|---|
| 96 | x=stepx/2 |
|---|
| 97 | months=[a[0].month for a in hist] #months=map(lambda x:x[1].month,hist) |
|---|
| 98 | begx=x; begm=months[0] |
|---|
| 99 | for m in months: |
|---|
| 100 | x=x+stepx |
|---|
| 101 | if m <> begm: |
|---|
| 102 | print '<path style="fill:none;stroke:grey" d="M %i 0 v-%i"/>'%(x,ch) |
|---|
| 103 | print '<text x="%i" y="15" style="font-size:15;text-anchor:middle">%s</text>'%((begx+x)/2,mth[begm]) |
|---|
| 104 | begx=x; begm=m |
|---|
| 105 | #begx+x/2,mth |
|---|
| 106 | print '<text x="%i" y="15" style="font-size:15;text-anchor:middle">%s</text>'%((begx+x)/2,mth[begm]) |
|---|
| 107 | |
|---|
| 108 | ################################################################################ |
|---|
| 109 | ## lets do the y ticks labels and grid |
|---|
| 110 | maxgrid=5 |
|---|
| 111 | intervals=(.1,.25,.5,1,2,5,10,25,50,100) #.5 was here but didn't work in arg3 to range |
|---|
| 112 | hi=max([x[2] for x in hist]) |
|---|
| 113 | lo=min([x[3] for x in hist]) |
|---|
| 114 | for ystep in intervals: |
|---|
| 115 | y=(hi-lo)/ystep |
|---|
| 116 | if ( y <= maxgrid): |
|---|
| 117 | break; #we've found one that works so stop iterating |
|---|
| 118 | # This is to get the tick marks |
|---|
| 119 | # a lot of rounding and stuff |
|---|
| 120 | # I'm sure there's a simpler better way to do this |
|---|
| 121 | # but my head hurts so I'll stop now |
|---|
| 122 | lotic=int((lo+ystep)/ystep)*ystep |
|---|
| 123 | hitic=int((hi+ystep)/ystep)*ystep |
|---|
| 124 | y=[i*ystep+lotic for i in range((hitic-lotic)/ystep)] |
|---|
| 125 | |
|---|
| 126 | # draw the lines |
|---|
| 127 | print ' <path id="ygrid" style="fill:none;stroke:grey" d=" ' |
|---|
| 128 | for g in y: |
|---|
| 129 | print 'M0,-%i h%i '%((g-lo)*ch/(hi-lo),cw), |
|---|
| 130 | print '"/>' |
|---|
| 131 | # add the labels |
|---|
| 132 | for g in y: |
|---|
| 133 | print '<text x="-20" y="-%i" style="font-size:15;text-anchor:middle">%0.2f</text>'%((g-lo)*ch/(hi-lo),g) |
|---|
| 134 | |
|---|
| 135 | ################################################################################ |
|---|
| 136 | ## now lets do the actual bars |
|---|
| 137 | xstep=1.0*cw/len(hist) |
|---|
| 138 | x=0.0 |
|---|
| 139 | print '<path id="chartbars" style="fill:none;stroke:%s" d="'%color |
|---|
| 140 | for b in hist: |
|---|
| 141 | x=x+xstep |
|---|
| 142 | b=map(lambda yy:(float(yy)-lo)*ch/(hi-lo),b[1:5]) |
|---|
| 143 | print 'M %s,-%i h%s V-%i -%i -%i h%s '%(x,b[0],xstep/2,b[1],b[2],b[3],xstep/2), |
|---|
| 144 | print '"/>' |
|---|
| 145 | ################################################################################ |
|---|
| 146 | print "</g></svg>" |
|---|
| 147 | |
|---|
| 148 | |
|---|
| 149 | |
|---|