#! /usr/bin/gawk -f # Last edited on 2014-04-06 17:21:47 by stolfilocal # User must define variables {tstep}, {bestsale} and {refprice}, and may define variables # {refdate}, {reftime} with "-v {VAR}={VALUE}" # Reads from {stdin} a file with summarized trade data for consecutive # time intervals. Assumes that each interval is {tstep} time units # long and there are no missing intervals (although there may be intervals with "zero" prices). # # For each input data line up to but not including a certain reference line, ignoring comments # and table headers, writes to {stdout} a line # # "{DATE[i]} {TIME[i]} {DELTA[i]} {PR[i]} {APLC[i]} {ARPC[i]}" # # where # # {DATE[i]}, {TIME[i]} is the timestamp of an input data line. # {DELTA[i]} is the (negative) time difference between that timestamp and a reference timestamp. # {PR[i]} is the weighted mean price from that line divided by that of the reference line. # {APLC[i]} is the average change per unit time in {log10} of price in that interval. # {ARPC[i]} is the average relative change in price per unit time in that interval. # # Namely, let {P[i]} be the weighted mean price of data line with index {i}, # and {r} be the index of the data line with timestamp "{refdate} {reftime}" # (or the last line, if {refdate} and {reftime} are blank or not found). # Then, for all {i} less than {r}, # # {DELTA[i] = (i - r)*tstep}, # {PR[i] = P[i]/REFPR} # {APLC[i] = (Z[i] - Z[r])/DELTA[i]} where {Z[i] = log10(P[i])}; # {ARPC[i] = (10^APLC[i]) - 1)}. # # wehre {REFPR} is the reference price. # # If {bestsale} is zero, then {r} is the line with # {DATE[r] == refdate} and {TIME[i]== reftime}, and {REFPR} is {refprice}. # If {bestsale} is 1, then {r} is the line after time {i} that maximizes # {APLC[i]} when {REFPR} is {P[r]}. # # In the output, a blank line is written where line {r} should be, and also in place # of any line with zero mean price. BEGIN \ { if (tstep == "") { arg_error(("must define {tstep}")); } if (bestsale == "") { arg_error(("must define {bestsale}")); } if (refprice == "") { arg_error(("must define {refprice}")); } if (refprice + 0 <= 0) { arg_error(("reference price = \"" refprice "\" is missing or invalid")); } n = 0; # Number of data lines. split("", Ptb); # Prices of of data lines are {Ptb[0..n-1]}. split("", Dtb); # Dates of of data lines are {Dtb[0..n-1]}. split("", Ttb); # Times of of data lines are {Ttb[0..n-1]}. refi = -1; # Index of reference record. LOG10 = log(10); } /(^[ ]*([#]|$))|[!]/ { next; } /^20[0-9][0-9][-]/ \ { dt = $1; # Date "%Y-%m-%d". tm = $2; # Time of day "%H:%M:%S". P = $(16) + 0; # Weighted mean price. Dtb[n] = dt; Ttb[n] = tm; Ptb[n] = P; # Is it the reference line? if ((dt == refdate) && (tm == reftime)) { refi = n; } n++; next; } // \ { data_error("invalid line format"); } END \ { printf "read %d data lines\n", n > "/dev/stderr"; if (refi < 0) { # The reference record was not found or was not specified: if ((refdate != "") || (reftime != "")) { arg_error(("timestamp \"" refdate " " reftime "\" not found in input file")); } # Use the last entry as reference: refi = n - 1; } printf "assuming line %d = %s %s as reference/limit\n", refi, Dtb[refi], Ttb[refi] > "/dev/stderr"; # Write the output file: for (i = 0; i < refi; i++) { if (Ptb[i] <= 0) { # Output a blank line: printf "\n"; } else { # Get the reference price {Pr} and its log {Zr}: if (bestsale != 0) { Fbest = -1.0e100; r = -1; for (s = i+1; s <= refi; s++) { if (Ptb[s] > 0) { Fis = log(Ptb[i]/Ptb[s])/(i - s); if (Fis > Fbest) { r = s; Fbest = Fis; } } } Pr = ( r >= 0 ? Ptb[r] : -1 ); printf " buy on %5d @ %8.2f - sell on %5d @ %8.2f\n", i, Ptb[i], r, Ptb[r] > "/dev/stderr"; } else { r = refi; Pr = refprice + 0; } if ((r < 0) || (Pr <= 0)) { # Output a blank line: printf "\n"; } else { # Compute the appreciation from {i} to {r}: DELTAi = (i - r)*tstep; PRi = Ptb[i]/Pr; ZZi = log(PRi)/LOG10; # Average change in {log10} of price per time unit. ALPCi = ZZi/DELTAi; # Average relative change factor in price per time unit. ARPCi = (ALPCi > 15.0 ? 1.0e15 : (ALPCi < -15.0 ? 1.0e-15 : exp(LOG10*ALPCi))); printf "%s %s %+11.8f %26.12f %+11.8f %11.8f\n", Dtb[i], Ttb[i], DELTAi, PRi, ALPCi, ARPCi; } } } } function data_error(msg) { printf "%s:%s: ** %s\n", FILENAME, FNR, msg > "/dev/stderr"; printf " «%s»\n", $0 > "/dev/stderr"; abort = 1; exit(abort); } function arg_error(msg) { printf "** %s\n", msg > "/dev/stderr"; abort = 1; exit(abort); }