NYCJUG/2009-03-10/pfchart.ijs

From J Wiki
Jump to navigation Jump to search

An example of some small steps to converting code that is very untypical of J to code that is a little more J-like.

NB.* pfchart.ijs: point-and-figure (candlestick) charter based on work by "packrat":
NB. http://www.jsoftware.com/pipermail/programming/2009-February/013734.html

require 'files dates tables/csv grid'

Note 'example'
  pfgrid pfchartrgs ''
)

pfgrid=: (2 2$'GRIDMARGIN';0 0 0 0;'GRIDZOOM';0.5) grid <"0

pfchartrgs=: 3 : 0
NB. constants (should be input by user instead):
nBox=. 150    NB. size of charting box (related to nMaxRows below))
nRev=. 3    NB. number of boxes needed for reversal
nMaxCols=. 125
nMaxRows=. 50    NB. this can affect value of "nBox" if calculated by formula
nShowDate=. 1    NB. flag to display dates or not
sFname=. jpath '~temp\DJIA20072008.csv'

NB. initialize variables:
nCurrCol=. 0
sSymb=. 'OX'
nLastMonthPlotted=. 0
nLastYearPlotted=. 0
nRowOffset=. 0

NB. 4 extra rows needed for 4 vertical digits of year
if. nShowDate do. nRowOffset=. 4 end.
nMaxRows=. nMaxRows + nRowOffset
sChart=. (nMaxRows,nMaxCols) $ ' '    NB. chart array

NB. read in (Yahoo) market data file and pull out date/high/low/close values:
'bHdr bMktData'=. split readcsv sFname
nDate=.  getdate"1 > (bHdr i. <'Date') {"1 bMktData   NB. column 0 is date (format: yyyy-mm-dd)
NB. if newest data always at top could just |. bMktData
nOrder=. /: nDate  NB. sort order
nDate=. nDate /: nOrder
nHighLow=. nOrder /:~ makenum (bHdr i. 'High';'Low') {"1 bMktData
nClose=. nOrder /:~ makenum (bHdr i. <'Close') {"1 bMktData  NB. only used for working out start direction
NB. could now erase bMktData to save space

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. #nDate do.
  'nYr nMn nDy'=.  i { nDate
  sMonth=. (<:nMn) { '123456789ABC'

  nLowHigh=.  |. i { nHighLow NB. reverse order so low is index 0

  assert. (nLowHigh < nChartHigh) *. nLowHigh > nChartLow
  NB.  smoutput 'Data for ',(": i { bDate),' exceeded chart range'
  nLowHigh=. nLowHigh - nChartLow

  NB. (initialize starting point of chart in the first column)
  if. i = 0 do.   NB. is this the first entry?
    nClose=. (i { nClose) - nChartLow
    nColType=. nClose >: -: --/ nLowHigh
    nLHBox=. <. nLowHigh % nBox

    b=. i. >: --/ nLHBox
    sChart=. (nColType{sSymb) (< (nRowOffset + b + {.nLHBox);nCurrCol) } sChart

    nOldVal=. nColType { nLHBox

    if. nShowDate do.
      sChart=. (":nYr) (< (i.-nRowOffset);nCurrCol) } sChart
      nLastYearPlotted=. nYr
    end.

  else.    NB. the following is the normal (i.e., non-first) procedure:

    NB. convert prices to boxes:
    nLHBox=. <. nLowHigh % nBox
    nNewDiffs=. (-`+@.nColType) nLHBox - nOldVal

    NB. new high or low?
    if. nChg=. 1 <: ({.`{:@.nColType) nNewDiffs do.
      nNewVal=. nColType { nLHBox

    NB. no new high or low, so test for reversal:
    elseif. nChg=. nRev <: ({:`{.@.nColType) -nNewDiffs do.
      nCurrCol=. >: nCurrCol
      nColType=. -.nColType
      nNewVal=. nColType { nLHBox
    end.

    if. nChg do. NB. Does sChart need updating?
      NB. update Os & Xs
      b=. (* * >:@i.) nNewVal - nOldVal
      sChart=. (nColType{sSymb) (< (nRowOffset + nOldVal + b);nCurrCol) } sChart

      NB. update Dates if necessary
      if. nShowDate *. nMn ~: nLastMonthPlotted do.
        b=. nColType { _1 1
        sChart=. sMonth (< (nRowOffset + nOldVal + b);nCurrCol) } sChart
        nLastMonthPlotted=. nMn
        if. (nMn = 1) *. nYr ~: nLastYearPlotted do.
          sChart=. (":nYr) (< (i.-nRowOffset);nCurrCol) } sChart
          nLastYearPlotted=. nYr
        end.
      end.

      nOldVal=. nNewVal
      nChg=.0
    end.

  end. NB. "first/rest" loop
end.  NB. "for" loop

NB. flip chart array so that smallest coords are at lower left
NB. rather than at upper left:
sChart=. |. sChart
)