I'm new to Go, and looking to create my own algo trading strategy backtesting library, an area I'm well experienced in with Python, to help learn the language.
I have a 5 minute OHLCV SPY5min.csv dataset, the head of which looks like this:
I use this code to read in the dataset from the file, converting everything to a list of lists of values:
package main
import (
"encoding/csv"
"log"
"os"
"fmt"
)
func ReadCsvFile(filePath string) [][]string {
f, err := os.Open(filePath)
if err != nil {
log.Fatal("Unable to read input file " filePath, err)
}
defer f.Close()
csvReader := csv.NewReader(f)
records, err := csvReader.ReadAll()
if err != nil {
log.Fatal("Unable to parse file as CSV for " filePath, err)
}
return records
}
func main() {
records := ReadCsvFile("./SPY5min.csv")
fmt.Println(records)
}
This returns a list of lists of string values. Cool. Now what I want to do is replicate a Pandas Dataframe like object, or perhaps separate each "column" into their own separate arrays/slices if that's easier, not sure yet.
Once that's done, I need a way to convert the strings of datetimes to actual datetime objects that I can run comparisons and loc's on. Can someone point me in the right direction?
My naive approach (pseudo) would be to:
- Declare 6 array variables (datetime, open, high, low, close, volume) of
len(records)in size - Iterate over the
recordslist of lists - Insert each value into the current
iof their respective arrays - Once iteration is done, mass convert the values in the
datetimearray to values of datetime objects?
Wondering if this is really the best way of doing this, or if there's a faster way than O(n) iteration?
CodePudding user response:
You asked, "Once that's done, I need a way to convert the strings of datetimes to actual datetime objects ...". I recently answered a similar question here: https://stackoverflow.com/a/74491722/5739452
Your timestamp looks like this: "2022-11-08 4:00". The time package contains parsing and other manipulation functions. The key detail is knowing the conventions for the layout parser format. Each element of a time is recognized as a specific number. The year is 2006, the month is 11 etc.
So, for your purpose something like this should work:
package main
import (
"fmt"
"time"
)
func main() {
t := "2022-11-08 4:00"
const layout = "2006-01-02 15:04"
x, err := time.Parse(layout, t)
fmt.Println(x, err)
}
CodePudding user response:
You could use a method based approach, like this:
package trading
import (
"encoding/csv"
"io"
"strconv"
"time"
)
type record []string
func records(r io.Reader) ([]record, error) {
var recs []record
raw := csv.NewReader(r)
for {
rec, err := raw.Read()
if err == io.EOF {
return recs, nil
} else if err != nil {
return nil, err
}
recs = append(recs, rec)
}
}
func (r record) time() (time.Time, error) {
return time.Parse("2006-01-02 15:04", r[0])
}
func (r record) open() (float64, error) {
return strconv.ParseFloat(r[1], 64)
}


