diff --git a/main.go b/main.go index 8881201..e211cb2 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "sort" + "strings" "time" ) @@ -219,47 +220,52 @@ func Conv(name string) { adjclose[k], vol)) } if dividends != nil { - out, err = os.Create(name + "-dividend.csv") - if err != nil { - fmt.Printf("%s: %s\n", name, err) - 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)) - } + writeEvents(name, name+"-dividend.csv", "Date,Dividends", + eventRows(name, "dividend", dividends, loc), + func(r eventRow) string { return fmt.Sprintf("%s,%f", r.date, r.amount) }) } if capgains != nil { - out, err = os.Create(name + "-capitalGain.csv") - if err != nil { - fmt.Printf("%s: %s\n", name, err) - 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)) - } + writeEvents(name, name+"-capitalGain.csv", "Date,Capital Gains", + eventRows(name, "capital gain", capgains, loc), + func(r eventRow) string { return fmt.Sprintf("%s,%f", r.date, r.amount) }) } if splits != nil { - out, err = os.Create(name + "-split.csv") - if err != nil { - fmt.Printf("%s: %s\n", name, err) - os.Exit(-1) - } - - defer out.Close() - - out.WriteString("Date,Stock Splits\n") - for _, r := range eventRows(name, "split", splits, loc) { - out.WriteString(fmt.Sprintf("%s,%s\n", r.date, r.ratio)) - } + writeEvents(name, name+"-split.csv", "Date,Stock Splits", + eventRows(name, "split", splits, loc), + func(r eventRow) string { return fmt.Sprintf("%s,%s", r.date, r.ratio) }) + } +} + +// fileHasDataRows reports whether path exists and has a row beyond the header. +func fileHasDataRows(path string) bool { + b, err := os.ReadFile(path) + if err != nil { + 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") } }