Analyzing stock price time series with modern Fortran, Part 2

Milan Curcic
Dec 3, 2018 · 16 min read
Image for post
Image for post
Wall Street. Photo by Rick Tap.

Allocating, indexing, and slicing arrays for stock price analysis

Allocating arrays of certain size or range

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

Allocating an array from another array

real, allocatable :: a(:), b(:)
allocate(a, mold=b) ! allocate a with same range and size as b
a = 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
Image for post
Image for post

Checking for allocation status

real, allocatable :: a(:)
print *, allocated(a) ! will print “F”
print *, allocated(a) ! will print “T”
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 a
call 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 errmsg
end 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 errmsg
end subroutine free

Implementing the CSV reader subroutine

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)

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 backwards
end 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–14
Symbol, Gain (USD), Relative gain (%)
AAPL 184.594589 5192
AMZN 1512.16003 1692
CRAY 9.60000038 56
CSCO 1.71649933 4
HPQ 1.55270004 7
IBM 60.9193039 73
INTC 25.8368015 89
MSFT 59.4120979 154
NVDA 251.745300 6964
ORCL 20.3501987 77


Modern Fortran

Modern Fortran: Building Efficient Parallel Applications

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store