NYCJUG/2009-02-10/pf.ijs
< NYCJUG | 2009-02-10
Jump to navigation
Jump to search
Some code for creating a "point-and-figure" chart from Dow Jones price data for 2007 and 2008.
NB. pf.ijs - standard "Point & Figure" charting algorithm with optional dating added NB. by Harvey E. Hahn -- 23-25,29-31 Jan; 1,4,6-7 Feb 2009 NB. Initial datatype prefixes used to keep names straight: NB. "b" for boxed NB. "s" for string (literal) NB. "n" for numeric require 'files' pfchart=: 3 : 0 NB. constants (should be input by user instead?): nBox=. 150 NB. size of charting box (related to nMaxRows below)) nRevBoxes=. 3 NB. number of boxes needed for reversal nMaxColumns=. 125 nMaxRows=. 50 NB. this can affect value of "nBox" if calculated by formula nShowDate=. 1 NB. flag to display dates or not NB. initialize variables: nBoxHigh=. 0 nBoxLow=. 0 nHigh=. 0 nLow=. 0 nClose=. 0 nNewHigh=. 0 nNewLow=. 0 nCurrCol=. 0 nFirst=. 1 NB. flag is turned "off" (false) after first entry nXCol=. 1 nOCol=. 0 nColType=. nXCol sLastMonthPlotted=. '' sLastYearPlotted=. '' sYr=. '' sMn=. '' nMon=. 0 sMonth=. '' nRowOffset=. 0 if. (1 = nShowDate) do. nMaxRows=. nMaxRows + 4 NB. 4 extra rows needed for 4 vertical digits of year nRowOffset=. 4 end. sChart=. (nMaxRows,nMaxColumns) $ ' ' NB. chart array NB. read in (Yahoo) market data file and cull out date/high/low/close values: NB. bMktData=. readcsv (jpath '~user\data\DJI-r-pf.csv') bMktData=. readcsv 'DJI2007-2008.csv' bDate=. 0 {"1 bMktData NB. column 0 is date (format: yyyy-mm-dd) bHigh=. 2 {"1 bMktData NB. column 2 is high bLow=. 3 {"1 bMktData NB. column 3 is low bClose=. 4 {"1 bMktData NB. column 4 is close NB. two ways chart range might be done -- NB. (1) look for max and min of prices (nBox = (max-min)/boxsize), NB. or NB. (2) take first price and calculate range of 50% higher NB. and 50% lower NB. for testing purposes (DJIA 2007-2008): nChartLow=. 7000 nChartHigh=. 14500 NB. midpoint = 10750, nBox = 150 for_i. i.((#bMktData)-1) do. sYr=. 4 {. > i { bDate sMn=. 2 {. 5 }. > i { bDate nMon=. ". sMn if. (9 < nMon) do. sMonth=. (nMon-10) { 'abc' else. sMonth=. ": 1 } sMn end. nHigh=. (". > i { bHigh) - nChartLow nLow=. (". > i { bLow) - nChartLow nClose=. (". > i { bClose) - nChartLow if. (nChartHigh < (". > i { bHigh)) +. (nChartLow > (". > i { bLow)) do. sChart=. |. sChart smoutput 'Data for ',(> i { bDate),' exceeded chart range' return. end. NB. (initialize starting point of chart in the first column) NB. is this the first entry? if. (1 = nFirst) do. nFirst=. 0 NB. turn off flag to guarantee this is done only once: if. nClose >= ((nHigh - nLow) % 2) do. nColType=. nXCol nBoxHigh=. <. (nLow % nBox) nNewHigh=. <. (nHigh % nBox) for_b. i.((nNewHigh-nBoxHigh)+1) do. sChart=. 'X' (< (nBoxHigh+b+nRowOffset),nCurrCol) } sChart end. else. nColType=. nOCol nBoxLow=. <. (nHigh % nBox) nNewLow=. <. (nLow % nBox) for_b. i.((nBoxLow-nNewLow)+1) do. sChart=. 'O' (< ((nBoxLow-b)+nRowOffset),nCurrCol) } sChart end. end. if. 1 = nShowDate do. if. (0 = (sLastYearPlotted -: sYr)) do. for_c. i._4 do. sChart=. (c{sYr) (< (3-c),nCurrCol) } sChart end. sLastYearPlotted=. sYr end. end. else. NB. the following is the normal (i.e., non-first) procedure: NB. convert prices to boxes: nNewHigh=. <. (nHigh % nBox) nNewLow=. <. (nLow % nBox) NB. continue upward direction? if. (nXCol = nColType) do. if. (1 <: (nNewHigh-nBoxHigh)) do. for_b. (1+i.(nNewHigh-nBoxHigh)) do. sChart=. 'X' (< (nBoxHigh+b+nRowOffset),nCurrCol) } sChart end. if. 1 = nShowDate do. if. (0 = (sLastMonthPlotted -: sMonth)) do. sChart=. sMonth (< (nBoxHigh+1+nRowOffset),nCurrCol) }sChart sLastMonthPlotted=. sMonth if. 1 = ".sMonth do. if. (0 = (sLastYearPlotted -: sYr)) do. for_c. i._4 do. sChart=. (c{sYr) (< (3-c),nCurrCol) } sChart end. sLastYearPlotted=. sYr end. end. end. end. nBoxHigh=. nNewHigh nBoxLow=. nBoxHigh - 1 NB. for drawing purposes, 1 box below highest 'X' NB. no new high, so test for downside reversal: elseif. (nRevBoxes <: (nBoxHigh - nNewLow) ) do. if. (nCurrCol < nMaxColumns-1) do. nCurrCol=. nCurrCol + 1 else. sChart=. |. sChart return. end. nColType=. nOCol for_b. i.((nBoxLow-nNewLow)+1) do. sChart=. 'O' (< ((nBoxLow-b)+nRowOffset),nCurrCol) } sChart end. if. 1 = nShowDate do. if. (0 = (sLastMonthPlotted -: sMonth)) do. sChart=. sMonth (< ((nBoxLow-2)+nRowOffset),nCurrCol) } sChart sLastMonthPlotted=. sMonth if. 1 = ".sMonth do. if. (0 = (sLastYearPlotted -: sYr)) do. for_c. i._4 do. sChart=. (c{sYr) (< (3-c),nCurrCol) } sChart end. sLastYearPlotted=. sYr end. end. end. end. nBoxLow=. nNewLow nBoxHigh=. nBoxLow + 1 NB. for drawing purposes, 1 box above lowest 'O' end. NB. continue downward direction? elseif. (nOCol = nColType) do. if. (1 <: (nBoxLow-nNewLow)) do. for_b. (1+i.(nBoxLow-nNewLow)) do. sChart=. 'O' (< ((nBoxLow-b)+nRowOffset),nCurrCol) } sChart end. if. 1 = nShowDate do. if. (0 = (sLastMonthPlotted -: sMonth)) do. sChart=. sMonth (< ((nBoxLow-1)+nRowOffset),nCurrCol) } sChart sLastMonthPlotted=. sMonth if. 1 = ".sMonth do. if. (0 = (sLastYearPlotted -: sYr)) do. for_c. i._4 do. sChart=. (c{sYr) (< (3-c),nCurrCol) } sChart end. sLastYearPlotted=. sYr end. end. end. end. nBoxLow=. nNewLow nBoxHigh=. nBoxLow + 1 NB. for drawing purposes, 1 box above lowest 'O' NB. no new low, so test for upside reversal: elseif. (nRevBoxes <: (nNewHigh - nBoxLow) ) do. if. (nCurrCol < nMaxColumns-1) do. nCurrCol=. nCurrCol + 1 else. sChart=. |. sChart return. end. nColType=. nXCol for_b. i.((nNewHigh-nBoxHigh)+1) do. sChart=. 'X' (< (nBoxHigh+b+nRowOffset),nCurrCol) } sChart end. if. 1 = nShowDate do. if. (0 = (sLastMonthPlotted -: sMonth)) do. sChart=. sMonth (< (nBoxHigh+2+nRowOffset),nCurrCol) } sChart sLastMonthPlotted=. sMonth if. 1 = ".sMonth do. if. (0 = (sLastYearPlotted -: sYr)) do. for_c. i._4 do. sChart=. (c{sYr) (< (3-c),nCurrCol) } sChart end. sLastYearPlotted=. sYr end. end. end. end. nBoxHigh=. nNewHigh nBoxLow=. nBoxHigh - 1 NB. for drawing purposes, 1 box below highest 'X' end. end. end. end. NB. "for" loop NB. flip chart array so that smallest coords are at lower left NB. rather than at upper left: sChart=. |. sChart )