Keep existing event CSVs when a download carries no events of that kind

Yahoo stopped returning capitalGain events for some funds (2026); a blind
os.Create + write of an empty event set overwrote the only copy of that
history. When the new download has zero rows of an event kind and the
existing CSV has data rows, keep the existing file. (gmp/f data.py also
falls back to overrides/event-backup/ as a second line of defense.)
This commit is contained in:
Greg Pomerantz 2026-08-31 21:29:29 -04:00
parent 584ec8753c
commit 62d11abb9d

78
main.go
View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"sort" "sort"
"strings"
"time" "time"
) )
@ -219,47 +220,52 @@ func Conv(name string) {
adjclose[k], vol)) adjclose[k], vol))
} }
if dividends != nil { if dividends != nil {
out, err = os.Create(name + "-dividend.csv") writeEvents(name, name+"-dividend.csv", "Date,Dividends",
if err != nil { eventRows(name, "dividend", dividends, loc),
fmt.Printf("%s: %s\n", name, err) func(r eventRow) string { return fmt.Sprintf("%s,%f", r.date, r.amount) })
os.Exit(-1)
}
defer out.Close()
out.WriteString("Date,Dividends\n")
for _, r := range eventRows(name, "dividend", dividends, loc) {
out.WriteString(fmt.Sprintf("%s,%f\n", r.date, r.amount))
}
} }
if capgains != nil { if capgains != nil {
out, err = os.Create(name + "-capitalGain.csv") writeEvents(name, name+"-capitalGain.csv", "Date,Capital Gains",
if err != nil { eventRows(name, "capital gain", capgains, loc),
fmt.Printf("%s: %s\n", name, err) func(r eventRow) string { return fmt.Sprintf("%s,%f", r.date, r.amount) })
os.Exit(-1)
}
defer out.Close()
out.WriteString("Date,Capital Gains\n")
for _, r := range eventRows(name, "capital gain", capgains, loc) {
out.WriteString(fmt.Sprintf("%s,%f\n", r.date, r.amount))
}
} }
if splits != nil { if splits != nil {
out, err = os.Create(name + "-split.csv") writeEvents(name, name+"-split.csv", "Date,Stock Splits",
if err != nil { eventRows(name, "split", splits, loc),
fmt.Printf("%s: %s\n", name, err) func(r eventRow) string { return fmt.Sprintf("%s,%s", r.date, r.ratio) })
os.Exit(-1) }
} }
defer out.Close() // fileHasDataRows reports whether path exists and has a row beyond the header.
func fileHasDataRows(path string) bool {
out.WriteString("Date,Stock Splits\n") b, err := os.ReadFile(path)
for _, r := range eventRows(name, "split", splits, loc) { if err != nil {
out.WriteString(fmt.Sprintf("%s,%s\n", r.date, r.ratio)) return false
} }
lines := strings.Split(strings.TrimSpace(string(b)), "\n")
return len(lines) > 1 && strings.TrimSpace(lines[1]) != ""
}
// writeEvents writes the event rows to path, unless the download carries no
// rows of this kind while an existing populated file is present: Yahoo has
// stopped returning capitalGain events for some funds (2026), and a blind
// overwrite would wipe the only copy of that history. (The consumer side,
// gmp/f data.py, additionally falls back to a backup directory.)
func writeEvents(name, path, header string, rows []eventRow, format func(eventRow) string) {
if len(rows) == 0 && fileHasDataRows(path) {
fmt.Printf("%s: no %s events in download; keeping existing %s\n", name, header, path)
return
}
out, err := os.Create(path)
if err != nil {
fmt.Printf("%s: %s\n", name, err)
os.Exit(-1)
}
defer out.Close()
out.WriteString(header + "\n")
for _, r := range rows {
out.WriteString(format(r) + "\n")
} }
} }