autotrader/backtesting.go
2023-05-12 19:36:03 -05:00

70 lines
1.6 KiB
Go

package autotrader
import (
"errors"
df "github.com/rocketlaunchr/dataframe-go"
)
var ErrNoData = errors.New("no data")
func Backtest(trader *Trader) {
trader.Tick()
}
type TestBroker struct {
DataBroker Broker
Data *df.DataFrame
Cash float64
Leverage float64
StartCandles int
candles int
}
func (b *TestBroker) Candles(symbol string, frequency string, count int) (*df.DataFrame, error) {
if b.DataBroker != nil && b.Data == nil {
// Fetch a lot of candles from the broker so we don't keep asking.
candles, err := b.DataBroker.Candles(symbol, frequency, Max(count, 1000))
if err != nil {
return nil, err
}
b.Data = candles
} else if b.Data == nil { // Both b.DataBroker and b.Data are nil.
return nil, ErrNoData
}
// Check if we reached the end of the existing data.
if b.candles >= b.Data.NRows() {
return nil, nil
}
// Catch up to the start candles.
if b.candles < b.StartCandles {
b.candles = b.StartCandles
} else {
b.candles++
}
end := b.candles - 1
start := Max(b.candles-count, 0)
return b.Data.Copy(df.Range{Start: &start, End: &end}), nil
}
func (b *TestBroker) MarketOrder(symbol string, units float64, stopLoss, takeProfit float64) (Order, error) {
return nil, nil
}
func (b *TestBroker) NAV() float64 {
return b.Cash
}
func NewTestBroker(dataBroker Broker, data *df.DataFrame, cash, leverage float64, startCandles int) *TestBroker {
return &TestBroker{
DataBroker: dataBroker,
Data: data,
Cash: cash,
Leverage: Max(leverage, 1),
StartCandles: Max(startCandles-1, 0),
}
}