Listing 1.
channel.pl - Simulating channel-based futures trading
M. Edward Borasky
Futures Trading with Perl
The Perl Journal, Spring 1997
  channel.pl - Simulating channel-based futures trading

# Simulate basic channel system

# M. Edward Borasky, 26-DEC-96

# usage: perl channel.pl <contract> <days>

# where <contract> is the contract name and <days> is the

# number of days in the channel.



$start = time();                     # starting time stamp



# open hardcoded input file

$contract = $ARGV[0];                # contract name

$infile = “a:\\pinnacle\\clc\\temp\\${contract}_clc.asc";

open(INPUT, $infile);

print "Input from $infile\n";



$days = $ARGV[1]+0;                  # number of days in channel

print "Days in channel = $days\n";



# open output file

$outfile = "${contract}.prn";

open(OUTPUT, ">> $outfile");

print "Output to $outfile\n";



@high = @low = ();                   # allocate saved data arrays empty

$position = 0;                       # start neutral

$rollflag = 0;                       # first day is regular record



# main loop over data file

while (<INPUT>) {                    # read a line

    @F = split(’ ’, $_);             # split into fields

    $date = $F[0]+0;                 # date

    if ($date == 0) {                # rollover record

        $rollflag = 1;               # set rollover flag

        $offset = $F[4] - $F[1];     # compute offset

    } else {                         # regular data record

        $open = $F[1]+0;             # opening price

        $high = $F[2]+0;             # day’s high

        $low = $F[3]+0;              # day’s low

        $close = $F[4]+0;            # closing price

        $trdays++ if $position != 0; # days in trade

        if ($rollflag) {             # this is a rollover day

            &backadjust;             # back adjust data

            &rolltrade;              # do rollover trade

            &newdata;                # update data buffer/stops

            $rollflag = 0;           # reset flag

            printf("%s %d Rollover %6g %12.9g\n", $contract, $days, $date, $offset);

        } else {                     # regular day

            &trades;                 # simulate any trades

            &newdata;                # update data buffer/stops

        }

    }

}



$stop = time(); $minutes = ($stop - $start)/60; # elapsed time

printf ("%s %d Elapsed minutes=%6g\n", $contract, $days, $minutes);

printf OUTPUT ("%s %d Elapsed minutes=%6g\n", $contract, $days, $minutes);

close(INPUT); 

close(OUTPUT); 



sub rolltrade {                      # trades on rollover day

    return if $#high < ($days - 1);  # not enough data



    if ($open >= $buystop && $position != 1) {

        &closeshort($open - $offset);# close short

        &openlong  ($open);          # open new long

    } elsif ($open <= $sellstop && $position != -1) {

        &closelong($open - $offset); # close long

        &openshort($open);           # open new short

    } elsif ($high >= $buystop && $position != 1) {

        &closeshort($buystop - $offset);

        &openlong  ($buystop); 

    } elsif ($low <= $sellstop && $position != -1) {

        &closelong($sellstop - $offset);

        &openshort($sellstop);

    } elsif ($position == -1) {      # holding short

        &closeshort($close - $offset); # close

        &openshort ($close);         # open new

    } elsif ($position == 1) {       # holding long

        &closelong($close - $offset);# close

        &openlong ($close);          # open new

    }

}



sub backadjust { # adjust past price data on rollover day

    for ($ix = 0; $ix <= $#high; $ix++) { # adjust back data

        $high[$ix] += $offset;

        $low[$ix] += $offset;

    }

    $buystop += $offset;             # and stops

    $sellstop += $offset; 

}

sub trades {                         # simulate any trades for this day

    return if $#high < ($days - 1);  # not enough data

    if ($open >= $buystop && $position != 1) {

        &closeshort($open);          # close any open short

        &openlong  ($open);          # open new long

    } elsif ($open <= $sellstop && $position != -1) {

        &closelong($open);           # close any open long

        &openshort($open);           # open new short

    } elsif ($high >= $buystop && $position != 1) {

        &closeshort($buystop);

        &openlong  ($buystop);

    } elsif ($low <= $sellstop && $position != -1) {

        &closelong($sellstop);

        &openshort($sellstop);

    }

}



sub newdata {                         # add today’s data, drop oldest point

    push(@high, $high);              # today’s high

    push(@low, $low);                # today’s low

    if ($#high >= $days) {           # buffer full

        shift(@high); shift(@low);   # drop oldest

    }



    # search for stops

    $buystop = $high[0]; 

    $sellstop = $low[0];             # init 

    for ($ix = 1; $ix <= $#high; $ix++) { # search

        $buystop = $high[$ix] if $high[$ix] > $buystop;

        $sellstop = $low[$ix] if $low[$ix] < $sellstop;

    }

}



sub closeshort {                     # close out any short position

    return if $position != -1;       # not short -- go away

    $price = $_[0];                  # argument is price



    # print to trade log

    print OUTPUT "$contract $days -1 ";

    printf OUTPUT ("%6g %12.9g %6g %12.9g %d\n",

                    $opendate, $paid, $date, $price ,$trdays);

    $position = 0;                   # we’re neutral

}



sub closelong {                      # close out any long position

    return if $position != 1;        # not long -- go away

    $price = $_[0];                  # argument is price



    # print to trade log

    print OUTPUT "$contract $days  1 ";

    printf OUTPUT ("%6g %12.9g %6g %12.9g %d\n",

                   $opendate, $paid, $date, $price ,$trdays);

    $position = 0;                   # we’re neutral

}



sub openlong {

    return if $position == 1;        # already long -- go away

    $paid = $_[0];                   # argument is price

    $trdays = 0;                     # days in trade

    $position = 1;                   # we’re now long

    $opendate = $date;               # remember when we opened trade

}

sub openshort {

    return if $position == -1;       # already short -- go away

    $paid = $_[0];                   # argument is price

    $trdays = 0;                     # days in trade

    $position = -1;                  # we’re now short

    $opendate = $date;               # remember when we opened trade

}