Groups | Search | Server Info | Login | Register


Groups > comp.lang.awk > #10011

AWK + S&P 500 + Buying The Dip

From Mike Sanders <porkchop@invalid.foo>
Newsgroups comp.lang.awk
Subject AWK + S&P 500 + Buying The Dip
Date 2025-09-25 14:25 +0000
Organization A noiseless patient Spider
Message-ID <10b3jcg$b96c$1@dont-email.me> (permalink)

Show all headers | View raw


Hi folks, hope everyone is doing well.

Another experiment to mull over (notes below).
Very useful script for me at least. Hope it
posts without wordwrap (trying out 'Pan'
newsreader for the 1st time).

Must run, lots of irons in the fire these days...
Hope to check in with you guys down the road,
learn some new things.

Work hard & make your mother proud!

#!/bin/sh

:<<'ABOUT'

Michael Sanders - 2025

'Buying the dip' is an investment strategy where an investor purchases assets
after their  price has dropped, with   the  expectation  that the  value will
rebound.  The tactic is an application of the basic principle, 'buy low, sell
high'.

This script  fetches historical data within  the  specified range for the S&P
500 & determines if the price is down slightly within a broader upward trend.
The result is that you'll save a nickel  or two  on the  price. The rationale
here is that, while its great to have cash on the side ready to invest,  if a
strong pullback in the  market doesn't happen very frequently, then your cash
misses out on potential gains...

Some popular ETFs that track the SPX index include:

VOO:  Vanguard S&P 500
SPY:  SPDR S&P 500
SPLG: SPDR Portfolio S&P 500
IVV:  iShares Core S&P 500

FORMULA:

BUF IF SPX < SMA10 AND SPX > SMA30 AND RSI14 > 39 AND RSI14 < 51 ELSE WAIT

Condition                  Meaning

SPX < SMA10                Short-term pullback from recent highs
SPX > SMA30                Still trending upwards overall
RSI14 > 39 AND RSI14 < 51  Momentum is mild indicating healthy consolidation
BUY / WAIT                 Buy if all conditions are true, otherwise wait

GLOSSARY:

SPX:   S&P 500 index, representing the overall U.S. large-cap market.

SMA10: 10-day Simple Moving Average, average closing price over the last
       10 trading days.

SMA30  30-day Simple Moving Average, average closing price over the last
       30 trading days.

RSI14: 14-day Relative Strength Index, momentum indicator measuring
       overbought/oversold conditions.

ABOUT

S=$(date -d "45 days ago" +%Y-%m-%d) # start date
E=$(date +%Y-%m-%d) # end date

URL="https://fred.stlouisfed.org/graph/fredgraph.csv?id=SP500&cosd=$S&coed=$E"

curl -Ls "$URL" | awk -v mini=0 '

BEGIN { OFS = FS = "," }

# round to n decimals: 2.344 = 2.34, 2.345 = 2.35
function round(x, dec) {
    factor = 10^dec
    return int(x * factor + 0.5) / factor
}

# simple moving average
function SMA(len,   i,sum) {
    if (n < len) return ""
    sum = 0
    for(i = n - len + 1; i <= n; i++) sum += closes[i]
    return sum / len
}

# relative strength index
function RSI(len,   i,gain,loss,diff,rs) {
    if (n <= len) return ""
    gain = loss = 0
    for(i = n - len + 1; i <= n; i++) {
        diff = closes[i] - closes[i-1]
        if (diff > 0) gain += diff
        else loss -= diff
    }
    if (loss == 0) return 100
    rs = gain / loss
    return 100 - (100 / (1 + rs))
}

NR==1 { next }  # skip CSV header

{
   gsub(/"/,"",$2)  # remove quotes from the CLOSE field

    if ($2 ~ /^[0-9.]+$/) {
        n++
        closes[n] = $2 * 1 # convert string to number
        dates[n]  = $1     # store corresponding date
    }

}

END {
    if (n < 1) { print "No valid data"; exit }
    last = closes[n]

    sma10 = (n >= 10 ? SMA(10) : "")
    sma30 = (n >= 30 ? SMA(30) : "")
    rsi14 = (n >= 15 ? RSI(14) : "")

    # buy/wait signal (no rounding here use full precision)
    signal = "WAIT"
    if (sma10 != "" && sma30 != "" && rsi14 != "") {
        if (last < sma10 && last > sma30 && rsi14 > 39 && rsi14 < 51) signal="BUY"
    }

    # check if any computed field is missing or non-numeric
    invalid = (sma10 == "" || sma30 == "" || rsi14 == "" || last == "")

    # minimal output only...
    if (mini) {
        print dates[n] " SPX " (invalid ? "ERROR" : signal)
        exit
    }

    # print header
    print "DATE,INDEX,CLOSE,SMA10,SMA30,RSI14,SIGNAL"

    # print last row (current day) directly with rounding expressions
    if (invalid) {
        print dates[n], "SPX", "", "", "", "", "", "ERROR"
    } else {
        print dates[n], "SPX",
              round(last,  2),
              round(sma10, 2),
              round(sma30, 2),
              round(rsi14, 1),
              signal
    }
}'

# eof

Back to comp.lang.awk | Previous | Next | Find similar


Thread

AWK + S&P 500 + Buying The Dip Mike Sanders <porkchop@invalid.foo> - 2025-09-25 14:25 +0000

csiph-web