autotrader/backtesting_test.go
2023-05-13 09:09:11 -05:00

129 lines
3.6 KiB
Go

package autotrader
import (
"strings"
"testing"
"time"
df "github.com/rocketlaunchr/dataframe-go"
)
const testDataCSV = `date,open,high,low,close,volume
2022-01-01,1.1,1.2,1.0,1.15,100
2022-01-02,1.15,1.2,1.1,1.2,110
2022-01-03,1.2,1.3,1.15,1.25,120
2022-01-04,1.25,1.3,1.2,1.1,130
2022-01-05,1.1,1.2,1.0,1.15,110
2022-01-06,1.15,1.2,1.1,1.2,120
2022-01-07,1.2,1.3,1.15,1.25,140
2022-01-08,1.25,1.3,1.2,1.1,150
2022-01-09,1.1,1.4,1.0,1.3,220`
func newTestingDataframe() *df.DataFrame {
data, err := ReadDataCSVFromReader(strings.NewReader(testDataCSV), DataCSVLayout{
LatestFirst: false,
DateFormat: "2006-01-02",
Date: "date",
Open: "open",
High: "high",
Low: "low",
Close: "close",
Volume: "volume",
})
if err != nil {
panic(err)
}
return data
}
func TestBacktestingBrokerCandles(t *testing.T) {
data := newTestingDataframe()
broker := NewTestBroker(nil, data, 0, 0, 0, 0)
candles, err := broker.Candles("EUR_USD", "D", 3)
if err != nil {
t.Fatal(err)
}
if candles.NRows() != 1 {
t.Errorf("Expected 1 candle, got %d", candles.NRows())
}
if candles.Series[0].Value(0).(time.Time) != time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC) {
t.Errorf("Expected first candle to be 2022-01-01, got %s", candles.Series[0].Value(0))
}
candles, err = broker.Candles("EUR_USD", "D", 3)
if err != nil {
t.Fatal(err)
}
if candles.NRows() != 2 {
t.Errorf("Expected 2 candles, got %d", candles.NRows())
}
if candles.Series[0].Value(1).(time.Time) != time.Date(2022, 1, 2, 0, 0, 0, 0, time.UTC) {
t.Errorf("Expected second candle to be 2022-01-02, got %s", candles.Series[0].Value(1))
}
for i := 0; i < 7; i++ { // 7 because we want to call broker.Candles 9 times total
candles, err = broker.Candles("EUR_USD", "D", 5)
if err != nil {
t.Fatalf("Got an error on iteration %d: %v", i, err)
}
if candles == nil {
t.Errorf("Candles is nil on iteration %d", i+1)
}
}
if candles.NRows() != 5 {
t.Errorf("Expected 5 candles, got %d", candles.NRows())
}
if candles.Series[4].Value(4).(float64) != 1.3 {
t.Errorf("Expected the last closing price to be 1.3, got %f", candles.Series[4].Value(4))
}
}
func TestBacktestingBrokerFunctions(t *testing.T) {
broker := NewTestBroker(nil, nil, 100_000, 20, 0, 0)
if broker.NAV() != 100_000 {
t.Errorf("Expected NAV to be 100_000, got %f", broker.NAV())
}
}
func TestBacktestingBrokerOrders(t *testing.T) {
broker := NewTestBroker(nil, newTestingDataframe(), 100_000, 50, 0, 0)
timeBeforeOrder := time.Now()
order, err := broker.MarketOrder("EUR_USD", 50_000, 0, 0) // Buy 50,000 USD for 1000 EUR with no stop loss or take profit
if err != nil {
t.Fatal(err)
}
if order == nil {
t.Fatal("Order is nil")
}
if order.Symbol() != "EUR_USD" {
t.Errorf("Expected symbol to be EUR_USD, got %s", order.Symbol())
}
if order.Units() != 50_000 {
t.Errorf("Expected units to be 50_000, got %f", order.Units())
}
if order.Price() != 1.15 {
t.Errorf("Expected order price to be 1.15 (first close), got %f", order.Price())
}
if order.Fulfilled() != true {
t.Error("Expected order to be fulfilled")
}
if order.Time().Before(timeBeforeOrder) {
t.Error("Expected order time to be after timeBeforeOrder")
}
if order.Leverage() != 50 {
t.Errorf("Expected leverage to be 50, got %f", order.Leverage())
}
if order.StopLoss() != 0 {
t.Errorf("Expected stop loss to be 0, got %f", order.StopLoss())
}
if order.TakeProfit() != 0 {
t.Errorf("Expected take profit to be 0, got %f", order.TakeProfit())
}
if order.Type() != MarketOrder {
t.Errorf("Expected order type to be MarketOrder, got %s", order.Type())
}
}