Analyzing stock price time series with modern Fortran, Part 2

Dec 3, 2018 · 16 min read

Allocating, indexing, and slicing arrays for stock price analysis

Allocating arrays of certain size or range

`real, allocatable :: a(:) ! declare a dynamic array ainteger :: im = 5allocate(a(im)) ! allocate memory for array a with im elements`
`integer :: is = -5, ie = 10allocate(a(is:ie)) ! Allocate a with range from is to ie inclusive `

Allocating an array from another array

`real, allocatable :: a(:), b(:)allocate(b(10:20))allocate(a, mold=b) ! allocate a with same range and size as ba = 0 `
`real, allocatable :: a(:), b(:)b = [1.0, 2.0, 3.0]allocate(a, source=b) ! allocate and initialize a from b`

Automatic allocation on assignment

`integer, allocatable :: a(:)a = [integer ::] ! create an empty array []a = [a, 1] ! append 1 to a, now [1]a = [a, 2] ! append 2 to a, now [1, 2]a = [a, 2 * a] ! [1, 2, 2, 4]`

Cleaning up after use

`deallocate(a) ! clear a from memory`

Checking for allocation status

`real, allocatable :: a(:)print *, allocated(a) ! will print “F”allocate(a(10))print *, allocated(a) ! will print “T”deallocate(a)print *, allocated(a) ! will print “F” `

Catching allocation and deallocation errors

`allocate(u(im), stat=stat, errmsg=err)`
`call alloc(a, 5) ! do work with acall free(a)`
`subroutine alloc(a, n)  real, allocatable, intent(in out) :: a(:)  integer, intent(in) :: n  integer :: stat  character(len=100) :: errmsg  if (allocated(a)) call free(a)  allocate(a(n), stat=stat, errmsg=errmsg)  if (stat > 0) error stop errmsgend subroutine alloc`
`subroutine free(a)  real, allocatable, intent(in out) :: a(:)  integer :: stat  character(len=100) :: errmsg  if (.not. allocated(a)) return  deallocate(a, stat=stat, errmsg=errmsg)  if (stat > 0) error stop errmsgend subroutine free`

`subroutine read_stock(filename, time, open, high,&  low, close, adjclose, volume)  ...  integer :: fileunit  integer :: n, nm   nm = num_records(filename) — 1   if (allocated(time)) deallocate(time)  allocate(character(len=10) :: time(nm))  call alloc(open, nm)  call alloc(high, nm)  call alloc(low, nm)  call alloc(close, nm)  call alloc(adjclose, nm)  call alloc(volume, nm)   open(newunit=fileunit, file=filename) ! open the file  read(fileunit, fmt=*, end=1) ! use read() to skip the CSV header  do n = 1, nm ! loop over records and store into array elements    read(fileunit, fmt=*, end=1) time(n), open(n),&      high(n), low(n), close(n), adjclose(n), volume(n)  end do  1 close(fileunit) ! close file when done end subroutine read_stock`

Indexing and slicing arrays

`adjclose = reverse(adjclose) `
`real, allocatable :: subset(:)  ...subset = adjclose(5:10)`
`a(start:end:stride)`

Intermezzo: Reversing an array

`pure function reverse(x)  real, intent(in) :: x(:) ! assumed-size input array  real :: reverse(size(x)) ! declare reverse with same size as x  reverse = x(size(x):1:-1) ! use negative stride to copy backwardsend function reverse`
`print *, all(a == reverse(reverse(a))) ! should always print “T”`
`adjclose = reverse(adjclose)gain = (adjclose(size(adjclose)) — adjclose(1))`
`2000–01–03 through 2018–05–14Symbol, Gain (USD), Relative gain (%)---------------------------------AAPL   184.594589            5192AMZN   1512.16003            1692CRAY   9.60000038              56CSCO   1.71649933               4HPQ    1.55270004               7IBM    60.9193039              73INTC   25.8368015              89MSFT   59.4120979             154NVDA   251.745300            6964ORCL   20.3501987              77`
`make./stock_gain`

Written by

Written by