Add drawdown

This commit is contained in:
Luke I. Wilson 2023-05-16 20:49:44 -05:00
parent 1110144cea
commit a9df8cd8e3
2 changed files with 30 additions and 3 deletions

View File

@ -33,11 +33,12 @@ func Backtest(trader *Trader) {
chart := charts.NewLine() chart := charts.NewLine()
chart.SetGlobalOptions(charts.WithTitleOpts(opts.Title{ chart.SetGlobalOptions(charts.WithTitleOpts(opts.Title{
Title: "Backtest", Title: fmt.Sprintf("Backtest (%s)", time.Now().Format(time.DateTime)),
Subtitle: fmt.Sprintf("%s %s %T", trader.Symbol, trader.Frequency, trader.Strategy), Subtitle: fmt.Sprintf("%s %s %T", trader.Symbol, trader.Frequency, trader.Strategy),
})) }))
chart.SetXAxis(seriesStringArray(trader.Stats().Dates())). chart.SetXAxis(seriesStringArray(trader.Stats().Dates())).
AddSeries("Equity", lineDataFromSeries(trader.Stats().Series("Equity"))) AddSeries("Equity", lineDataFromSeries(trader.Stats().Series("Equity"))).
AddSeries("Drawdown", lineDataFromSeries(trader.Stats().Series("Drawdown")))
// Draw the chart to a file. // Draw the chart to a file.
f, err := os.Create("backtest.html") f, err := os.Create("backtest.html")
@ -65,11 +66,27 @@ func lineDataFromSeries(s Series) []opts.LineData {
} }
func seriesStringArray(s Series) []string { func seriesStringArray(s Series) []string {
if s == nil || s.Len() == 0 {
return []string{}
}
first := true
data := make([]string, s.Len()) data := make([]string, s.Len())
var dateLayout string
for i := 0; i < s.Len(); i++ { for i := 0; i < s.Len(); i++ {
switch val := s.Value(i).(type) { switch val := s.Value(i).(type) {
case time.Time: case time.Time:
data[i] = val.Format(time.DateTime) if first {
first = false
dateHead := s.Value(0).(time.Time)
dateTail := s.Value(-1).(time.Time)
diff := dateTail.Sub(dateHead)
if diff.Hours() > 24*365 {
dateLayout = time.DateOnly
} else {
dateLayout = time.DateTime
}
}
data[i] = val.Format(dateLayout)
case string: case string:
data[i] = fmt.Sprintf("%q", val) data[i] = fmt.Sprintf("%q", val)
default: default:

View File

@ -82,6 +82,7 @@ func (t *Trader) Init() {
t.stats = NewDataFrame( t.stats = NewDataFrame(
NewDataSeries(dataframe.NewSeriesTime("Date", nil)), NewDataSeries(dataframe.NewSeriesTime("Date", nil)),
NewDataSeries(dataframe.NewSeriesFloat64("Equity", nil)), NewDataSeries(dataframe.NewSeriesFloat64("Equity", nil)),
NewDataSeries(dataframe.NewSeriesFloat64("Drawdown", nil)),
) )
} }
@ -95,6 +96,15 @@ func (t *Trader) Tick() {
t.stats.PushValues(map[string]interface{}{ t.stats.PushValues(map[string]interface{}{
"Date": t.data.Date(-1), "Date": t.data.Date(-1),
"Equity": t.Broker.NAV(), "Equity": t.Broker.NAV(),
"Drawdown": func() float64 {
var bal float64
if t.stats.Len() > 0 {
bal = t.stats.Value("Equity", 0).(float64) // Take starting balance
} else {
bal = t.Broker.NAV()
}
return Max(bal-t.Broker.NAV(), 0)
}(),
}) })
} }