mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-16 15:09:57 +00:00
* begins defining run management options * fleshes out concept * completes fund manager and RPC commands * coverage and improvements * adds coverage, and bad log concept * simplifies output at expense of races * removes run logging for now. tightens races. adds cov * Lints thine splints * Fixes stopping and clearing bugs * some niteroos * fix races
1213 lines
33 KiB
Go
1213 lines
33 KiB
Go
package engine
|
|
|
|
import (
|
|
"errors"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gofrs/uuid"
|
|
"github.com/shopspring/decimal"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/config"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/data"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/data/kline"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/eventholder"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/exchange"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/portfolio"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/portfolio/risk"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/portfolio/size"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/statistics"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/dollarcostaverage"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/event"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/fill"
|
|
evkline "github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/kline"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/order"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/signal"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/report"
|
|
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
|
"github.com/thrasher-corp/gocryptotrader/engine"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/ftx"
|
|
gctkline "github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
|
gctorder "github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
|
)
|
|
|
|
const testExchange = "ftx"
|
|
|
|
var leet = decimal.NewFromInt(1337)
|
|
|
|
type portfolioOverride struct {
|
|
Err error
|
|
portfolio.Portfolio
|
|
}
|
|
|
|
func (p portfolioOverride) CreateLiquidationOrdersForExchange(ev common.DataEventHandler, _ funding.IFundingManager) ([]order.Event, error) {
|
|
if p.Err != nil {
|
|
return nil, p.Err
|
|
}
|
|
return []order.Event{
|
|
&order.Order{
|
|
Base: ev.GetBase(),
|
|
ID: "1",
|
|
Direction: gctorder.Short,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func TestReset(t *testing.T) {
|
|
t.Parallel()
|
|
f, err := funding.SetupFundingManager(&engine.ExchangeManager{}, true, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
bt := BackTest{
|
|
shutdown: make(chan struct{}),
|
|
Datas: &data.HandlerPerCurrency{},
|
|
Strategy: &dollarcostaverage.Strategy{},
|
|
Portfolio: &portfolio.Portfolio{},
|
|
Exchange: &exchange.Exchange{},
|
|
Statistic: &statistics.Statistic{},
|
|
EventQueue: &eventholder.Holder{},
|
|
Reports: &report.Data{},
|
|
Funding: f,
|
|
}
|
|
bt.Reset()
|
|
if bt.Funding.IsUsingExchangeLevelFunding() {
|
|
t.Error("expected false")
|
|
}
|
|
}
|
|
|
|
func TestFullCycle(t *testing.T) {
|
|
t.Parallel()
|
|
ex := testExchange
|
|
cp := currency.NewPair(currency.BTC, currency.USD)
|
|
a := asset.Spot
|
|
tt := time.Now()
|
|
|
|
stats := &statistics.Statistic{}
|
|
stats.ExchangeAssetPairStatistics = make(map[string]map[asset.Item]map[currency.Pair]*statistics.CurrencyPairStatistic)
|
|
stats.ExchangeAssetPairStatistics[ex] = make(map[asset.Item]map[currency.Pair]*statistics.CurrencyPairStatistic)
|
|
stats.ExchangeAssetPairStatistics[ex][a] = make(map[currency.Pair]*statistics.CurrencyPairStatistic)
|
|
|
|
port, err := portfolio.Setup(&size.Size{
|
|
BuySide: exchange.MinMax{},
|
|
SellSide: exchange.MinMax{},
|
|
}, &risk.Risk{}, decimal.Zero)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
fx := &ftx.FTX{}
|
|
fx.Name = testExchange
|
|
err = port.SetupCurrencySettingsMap(&exchange.Settings{Exchange: fx, Asset: a, Pair: cp})
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
f, err := funding.SetupFundingManager(&engine.ExchangeManager{}, false, true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
b, err := funding.CreateItem(ex, a, cp.Base, decimal.Zero, decimal.Zero)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
quote, err := funding.CreateItem(ex, a, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
pair, err := funding.CreatePair(b, quote)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
err = f.AddPair(pair)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
bt := BackTest{
|
|
shutdown: nil,
|
|
Datas: &data.HandlerPerCurrency{},
|
|
Strategy: &dollarcostaverage.Strategy{},
|
|
Portfolio: port,
|
|
Exchange: &exchange.Exchange{},
|
|
Statistic: stats,
|
|
EventQueue: &eventholder.Holder{},
|
|
Reports: &report.Data{},
|
|
Funding: f,
|
|
}
|
|
|
|
bt.Datas.Setup()
|
|
k := kline.DataFromKline{
|
|
Item: gctkline.Item{
|
|
Exchange: ex,
|
|
Pair: cp,
|
|
Asset: a,
|
|
Interval: gctkline.FifteenMin,
|
|
Candles: []gctkline.Candle{{
|
|
Time: tt,
|
|
Open: 1337,
|
|
High: 1337,
|
|
Low: 1337,
|
|
Close: 1337,
|
|
Volume: 1337,
|
|
}},
|
|
},
|
|
Base: data.Base{},
|
|
RangeHolder: &gctkline.IntervalRangeHolder{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Ranges: []gctkline.IntervalRange{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Intervals: []gctkline.IntervalData{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
HasData: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = k.Load()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
bt.Datas.SetDataForCurrency(ex, a, cp, &k)
|
|
|
|
bt.Run()
|
|
}
|
|
|
|
func TestStop(t *testing.T) {
|
|
t.Parallel()
|
|
bt := &BackTest{
|
|
shutdown: make(chan struct{}),
|
|
Statistic: &statistics.Statistic{},
|
|
}
|
|
bt.Stop()
|
|
tt := bt.MetaData.DateEnded
|
|
|
|
bt.Stop()
|
|
if !tt.Equal(bt.MetaData.DateEnded) {
|
|
t.Errorf("received '%v' expected '%v'", bt.MetaData.DateEnded, tt)
|
|
}
|
|
|
|
bt = nil
|
|
bt.Stop()
|
|
}
|
|
|
|
func TestFullCycleMulti(t *testing.T) {
|
|
t.Parallel()
|
|
ex := testExchange
|
|
cp := currency.NewPair(currency.BTC, currency.USD)
|
|
a := asset.Spot
|
|
tt := time.Now()
|
|
|
|
stats := &statistics.Statistic{}
|
|
stats.ExchangeAssetPairStatistics = make(map[string]map[asset.Item]map[currency.Pair]*statistics.CurrencyPairStatistic)
|
|
stats.ExchangeAssetPairStatistics[ex] = make(map[asset.Item]map[currency.Pair]*statistics.CurrencyPairStatistic)
|
|
stats.ExchangeAssetPairStatistics[ex][a] = make(map[currency.Pair]*statistics.CurrencyPairStatistic)
|
|
|
|
port, err := portfolio.Setup(&size.Size{
|
|
BuySide: exchange.MinMax{},
|
|
SellSide: exchange.MinMax{},
|
|
}, &risk.Risk{}, decimal.Zero)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
err = port.SetupCurrencySettingsMap(&exchange.Settings{Exchange: &ftx.FTX{}, Asset: a, Pair: cp})
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
f, err := funding.SetupFundingManager(&engine.ExchangeManager{}, false, true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
b, err := funding.CreateItem(ex, a, cp.Base, decimal.Zero, decimal.Zero)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
quote, err := funding.CreateItem(ex, a, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
pair, err := funding.CreatePair(b, quote)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
err = f.AddPair(pair)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
bt := BackTest{
|
|
shutdown: nil,
|
|
Datas: &data.HandlerPerCurrency{},
|
|
Portfolio: port,
|
|
Exchange: &exchange.Exchange{},
|
|
Statistic: stats,
|
|
EventQueue: &eventholder.Holder{},
|
|
Reports: &report.Data{},
|
|
Funding: f,
|
|
}
|
|
|
|
bt.Strategy, err = strategies.LoadStrategyByName(dollarcostaverage.Name, true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
bt.Datas.Setup()
|
|
k := kline.DataFromKline{
|
|
Item: gctkline.Item{
|
|
Exchange: ex,
|
|
Pair: cp,
|
|
Asset: a,
|
|
Interval: gctkline.FifteenMin,
|
|
Candles: []gctkline.Candle{{
|
|
Time: tt,
|
|
Open: 1337,
|
|
High: 1337,
|
|
Low: 1337,
|
|
Close: 1337,
|
|
Volume: 1337,
|
|
}},
|
|
},
|
|
Base: data.Base{},
|
|
RangeHolder: &gctkline.IntervalRangeHolder{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Ranges: []gctkline.IntervalRange{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Intervals: []gctkline.IntervalData{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
HasData: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = k.Load()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
bt.Datas.SetDataForCurrency(ex, a, cp, &k)
|
|
|
|
bt.Run()
|
|
}
|
|
|
|
func TestTriggerLiquidationsForExchange(t *testing.T) {
|
|
t.Parallel()
|
|
bt := BackTest{}
|
|
expectedError := common.ErrNilEvent
|
|
err := bt.triggerLiquidationsForExchange(nil, nil)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
cp := currency.NewPair(currency.BTC, currency.USDT)
|
|
a := asset.Futures
|
|
expectedError = common.ErrNilArguments
|
|
ev := &evkline.Kline{
|
|
Base: &event.Base{Exchange: testExchange,
|
|
AssetType: a,
|
|
CurrencyPair: cp},
|
|
}
|
|
err = bt.triggerLiquidationsForExchange(ev, nil)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
bt.Portfolio = &portfolioOverride{}
|
|
pnl := &portfolio.PNLSummary{}
|
|
bt.Datas = &data.HandlerPerCurrency{}
|
|
d := data.Base{}
|
|
d.SetStream([]common.DataEventHandler{&evkline.Kline{
|
|
Base: &event.Base{
|
|
Exchange: testExchange,
|
|
Time: time.Now(),
|
|
Interval: gctkline.OneDay,
|
|
CurrencyPair: cp,
|
|
AssetType: a,
|
|
},
|
|
Open: leet,
|
|
Close: leet,
|
|
Low: leet,
|
|
High: leet,
|
|
Volume: leet,
|
|
}})
|
|
d.Next()
|
|
da := &kline.DataFromKline{
|
|
Item: gctkline.Item{
|
|
Exchange: testExchange,
|
|
Asset: a,
|
|
Pair: cp,
|
|
},
|
|
Base: d,
|
|
RangeHolder: &gctkline.IntervalRangeHolder{},
|
|
}
|
|
bt.Statistic = &statistics.Statistic{}
|
|
expectedError = nil
|
|
|
|
bt.EventQueue = &eventholder.Holder{}
|
|
bt.Funding = &funding.FundManager{}
|
|
bt.Datas.SetDataForCurrency(testExchange, a, cp, da)
|
|
err = bt.Statistic.SetupEventForTime(ev)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
pnl.Exchange = ev.Exchange
|
|
pnl.Item = ev.AssetType
|
|
pnl.Pair = ev.CurrencyPair
|
|
err = bt.triggerLiquidationsForExchange(ev, pnl)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
ev2 := bt.EventQueue.NextEvent()
|
|
ev2o, ok := ev2.(order.Event)
|
|
if !ok {
|
|
t.Fatal("expected order event")
|
|
}
|
|
if ev2o.GetDirection() != gctorder.Short {
|
|
t.Error("expected liquidation order")
|
|
}
|
|
}
|
|
|
|
func TestUpdateStatsForDataEvent(t *testing.T) {
|
|
t.Parallel()
|
|
pt := &portfolio.Portfolio{}
|
|
bt := &BackTest{
|
|
Statistic: &statistics.Statistic{},
|
|
Funding: &funding.FundManager{},
|
|
Portfolio: pt,
|
|
}
|
|
expectedError := common.ErrNilEvent
|
|
err := bt.updateStatsForDataEvent(nil, nil)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
cp := currency.NewPair(currency.BTC, currency.USDT)
|
|
a := asset.Futures
|
|
ev := &evkline.Kline{
|
|
Base: &event.Base{Exchange: testExchange,
|
|
AssetType: a,
|
|
CurrencyPair: cp},
|
|
}
|
|
|
|
expectedError = common.ErrNilArguments
|
|
err = bt.updateStatsForDataEvent(ev, nil)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
expectedError = nil
|
|
f, err := funding.SetupFundingManager(&engine.ExchangeManager{}, false, true)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
b, err := funding.CreateItem(testExchange, a, cp.Base, decimal.Zero, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
quote, err := funding.CreateItem(testExchange, a, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
pair, err := funding.CreateCollateral(b, quote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
bt.Funding = f
|
|
exch := &ftx.FTX{}
|
|
exch.Name = testExchange
|
|
err = pt.SetupCurrencySettingsMap(&exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
ev.Time = time.Now()
|
|
fl := &fill.Fill{
|
|
Base: ev.Base,
|
|
Direction: gctorder.Short,
|
|
Amount: decimal.NewFromInt(1),
|
|
ClosePrice: decimal.NewFromInt(1),
|
|
VolumeAdjustedPrice: decimal.NewFromInt(1),
|
|
PurchasePrice: decimal.NewFromInt(1),
|
|
Total: decimal.NewFromInt(1),
|
|
Slippage: decimal.NewFromInt(1),
|
|
Order: &gctorder.Detail{
|
|
Exchange: testExchange,
|
|
AssetType: ev.AssetType,
|
|
Pair: cp,
|
|
Amount: 1,
|
|
Price: 1,
|
|
Side: gctorder.Short,
|
|
OrderID: "1",
|
|
Date: time.Now(),
|
|
},
|
|
}
|
|
_, err = pt.TrackFuturesOrder(fl, pair)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
err = bt.updateStatsForDataEvent(ev, pair)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
}
|
|
|
|
func TestProcessSignalEvent(t *testing.T) {
|
|
t.Parallel()
|
|
var expectedError error
|
|
pt, err := portfolio.Setup(&size.Size{}, &risk.Risk{}, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
bt := &BackTest{
|
|
Statistic: &statistics.Statistic{},
|
|
Funding: &funding.FundManager{},
|
|
Portfolio: pt,
|
|
Exchange: &exchange.Exchange{},
|
|
EventQueue: &eventholder.Holder{},
|
|
}
|
|
cp := currency.NewPair(currency.BTC, currency.USDT)
|
|
a := asset.Futures
|
|
de := &evkline.Kline{
|
|
Base: &event.Base{Exchange: testExchange,
|
|
AssetType: a,
|
|
CurrencyPair: cp},
|
|
}
|
|
err = bt.Statistic.SetupEventForTime(de)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
ev := &signal.Signal{
|
|
Base: de.Base,
|
|
}
|
|
|
|
f, err := funding.SetupFundingManager(&engine.ExchangeManager{}, false, true)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
b, err := funding.CreateItem(testExchange, a, cp.Base, decimal.Zero, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
quote, err := funding.CreateItem(testExchange, a, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
pair, err := funding.CreateCollateral(b, quote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
bt.Funding = f
|
|
exch := &ftx.FTX{}
|
|
exch.Name = testExchange
|
|
err = pt.SetupCurrencySettingsMap(&exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
bt.Exchange.SetExchangeAssetCurrencySettings(a, cp, &exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
ev.Direction = gctorder.Short
|
|
err = bt.Statistic.SetEventForOffset(ev)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
err = bt.processSignalEvent(ev, pair)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
}
|
|
|
|
func TestProcessOrderEvent(t *testing.T) {
|
|
t.Parallel()
|
|
var expectedError error
|
|
pt, err := portfolio.Setup(&size.Size{}, &risk.Risk{}, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
bt := &BackTest{
|
|
Statistic: &statistics.Statistic{},
|
|
Funding: &funding.FundManager{},
|
|
Portfolio: pt,
|
|
Exchange: &exchange.Exchange{},
|
|
EventQueue: &eventholder.Holder{},
|
|
Datas: &data.HandlerPerCurrency{},
|
|
}
|
|
cp := currency.NewPair(currency.BTC, currency.USDT)
|
|
a := asset.Futures
|
|
de := &evkline.Kline{
|
|
Base: &event.Base{Exchange: testExchange,
|
|
AssetType: a,
|
|
CurrencyPair: cp},
|
|
}
|
|
err = bt.Statistic.SetupEventForTime(de)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
ev := &order.Order{
|
|
Base: de.Base,
|
|
}
|
|
|
|
f, err := funding.SetupFundingManager(&engine.ExchangeManager{}, false, true)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
b, err := funding.CreateItem(testExchange, a, cp.Base, decimal.Zero, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
quote, err := funding.CreateItem(testExchange, a, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
pair, err := funding.CreateCollateral(b, quote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
bt.Funding = f
|
|
exch := &ftx.FTX{}
|
|
exch.Name = testExchange
|
|
err = pt.SetupCurrencySettingsMap(&exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
bt.Exchange.SetExchangeAssetCurrencySettings(a, cp, &exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
ev.Direction = gctorder.Short
|
|
err = bt.Statistic.SetEventForOffset(ev)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
tt := time.Now()
|
|
bt.Datas.Setup()
|
|
k := kline.DataFromKline{
|
|
Item: gctkline.Item{
|
|
Exchange: testExchange,
|
|
Pair: cp,
|
|
Asset: a,
|
|
Interval: gctkline.FifteenMin,
|
|
Candles: []gctkline.Candle{{
|
|
Time: tt,
|
|
Open: 1337,
|
|
High: 1337,
|
|
Low: 1337,
|
|
Close: 1337,
|
|
Volume: 1337,
|
|
}},
|
|
},
|
|
Base: data.Base{},
|
|
RangeHolder: &gctkline.IntervalRangeHolder{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Ranges: []gctkline.IntervalRange{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Intervals: []gctkline.IntervalData{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
HasData: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = k.Load()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
bt.Datas.SetDataForCurrency(testExchange, a, cp, &k)
|
|
err = bt.processOrderEvent(ev, pair)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
ev2 := bt.EventQueue.NextEvent()
|
|
if _, ok := ev2.(fill.Event); !ok {
|
|
t.Fatal("expected fill event")
|
|
}
|
|
}
|
|
|
|
func TestProcessFillEvent(t *testing.T) {
|
|
t.Parallel()
|
|
var expectedError error
|
|
pt, err := portfolio.Setup(&size.Size{}, &risk.Risk{}, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
bt := &BackTest{
|
|
Statistic: &statistics.Statistic{},
|
|
Funding: &funding.FundManager{},
|
|
Portfolio: pt,
|
|
Exchange: &exchange.Exchange{},
|
|
EventQueue: &eventholder.Holder{},
|
|
Datas: &data.HandlerPerCurrency{},
|
|
}
|
|
cp := currency.NewPair(currency.BTC, currency.USD)
|
|
a := asset.Futures
|
|
de := &evkline.Kline{
|
|
Base: &event.Base{Exchange: testExchange,
|
|
AssetType: a,
|
|
CurrencyPair: cp},
|
|
}
|
|
err = bt.Statistic.SetupEventForTime(de)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
ev := &fill.Fill{
|
|
Base: de.Base,
|
|
}
|
|
em := engine.SetupExchangeManager()
|
|
exch, err := em.NewExchangeByName(testExchange)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
exch.SetDefaults()
|
|
cfg, err := exch.GetDefaultConfig()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = exch.Setup(cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
em.Add(exch)
|
|
f, err := funding.SetupFundingManager(em, false, true)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
b, err := funding.CreateItem(testExchange, a, cp.Base, decimal.Zero, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
quote, err := funding.CreateItem(testExchange, a, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
pair, err := funding.CreateCollateral(b, quote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
err = f.AddItem(b)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
err = f.AddItem(quote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
spotBase, err := funding.CreateItem(testExchange, asset.Spot, cp.Base, decimal.Zero, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
spotQuote, err := funding.CreateItem(testExchange, asset.Spot, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
spotPair, err := funding.CreatePair(spotBase, spotQuote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
err = f.AddPair(spotPair)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
bt.Funding = f
|
|
err = pt.SetupCurrencySettingsMap(&exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
bt.Exchange.SetExchangeAssetCurrencySettings(a, cp, &exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
ev.Direction = gctorder.Short
|
|
err = bt.Statistic.SetEventForOffset(ev)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
tt := time.Now()
|
|
bt.Datas.Setup()
|
|
k := kline.DataFromKline{
|
|
Item: gctkline.Item{
|
|
Exchange: testExchange,
|
|
Pair: cp,
|
|
Asset: a,
|
|
Interval: gctkline.FifteenMin,
|
|
Candles: []gctkline.Candle{{
|
|
Time: tt,
|
|
Open: 1337,
|
|
High: 1337,
|
|
Low: 1337,
|
|
Close: 1337,
|
|
Volume: 1337,
|
|
}},
|
|
},
|
|
Base: data.Base{},
|
|
RangeHolder: &gctkline.IntervalRangeHolder{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Ranges: []gctkline.IntervalRange{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Intervals: []gctkline.IntervalData{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
HasData: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = k.Load()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
bt.Datas.SetDataForCurrency(testExchange, a, cp, &k)
|
|
err = bt.processFillEvent(ev, pair)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
}
|
|
|
|
func TestProcessFuturesFillEvent(t *testing.T) {
|
|
t.Parallel()
|
|
var expectedError error
|
|
pt, err := portfolio.Setup(&size.Size{}, &risk.Risk{}, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
bt := &BackTest{
|
|
Statistic: &statistics.Statistic{},
|
|
Funding: &funding.FundManager{},
|
|
Portfolio: pt,
|
|
Exchange: &exchange.Exchange{},
|
|
EventQueue: &eventholder.Holder{},
|
|
Datas: &data.HandlerPerCurrency{},
|
|
}
|
|
cp := currency.NewPair(currency.BTC, currency.USD)
|
|
a := asset.Futures
|
|
de := &evkline.Kline{
|
|
Base: &event.Base{Exchange: testExchange,
|
|
AssetType: a,
|
|
CurrencyPair: cp},
|
|
}
|
|
err = bt.Statistic.SetupEventForTime(de)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
ev := &fill.Fill{
|
|
Base: de.Base,
|
|
}
|
|
em := engine.SetupExchangeManager()
|
|
exch, err := em.NewExchangeByName(testExchange)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
exch.SetDefaults()
|
|
cfg, err := exch.GetDefaultConfig()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = exch.Setup(cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
em.Add(exch)
|
|
f, err := funding.SetupFundingManager(em, false, true)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
b, err := funding.CreateItem(testExchange, a, cp.Base, decimal.Zero, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
quote, err := funding.CreateItem(testExchange, a, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
pair, err := funding.CreateCollateral(b, quote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
err = f.AddItem(b)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
err = f.AddItem(quote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
spotBase, err := funding.CreateItem(testExchange, asset.Spot, cp.Base, decimal.Zero, decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
spotQuote, err := funding.CreateItem(testExchange, asset.Spot, cp.Quote, decimal.NewFromInt(1337), decimal.Zero)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
spotPair, err := funding.CreatePair(spotBase, spotQuote)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
err = f.AddPair(spotPair)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
bt.exchangeManager = em
|
|
bt.Funding = f
|
|
|
|
err = pt.SetupCurrencySettingsMap(&exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
|
|
bt.Exchange.SetExchangeAssetCurrencySettings(a, cp, &exchange.Settings{
|
|
Exchange: exch,
|
|
Pair: cp,
|
|
Asset: a,
|
|
})
|
|
ev.Direction = gctorder.Short
|
|
err = bt.Statistic.SetEventForOffset(ev)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
tt := time.Now()
|
|
bt.Datas.Setup()
|
|
k := kline.DataFromKline{
|
|
Item: gctkline.Item{
|
|
Exchange: testExchange,
|
|
Pair: cp,
|
|
Asset: a,
|
|
Interval: gctkline.FifteenMin,
|
|
Candles: []gctkline.Candle{{
|
|
Time: tt,
|
|
Open: 1337,
|
|
High: 1337,
|
|
Low: 1337,
|
|
Close: 1337,
|
|
Volume: 1337,
|
|
}},
|
|
},
|
|
Base: data.Base{},
|
|
RangeHolder: &gctkline.IntervalRangeHolder{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Ranges: []gctkline.IntervalRange{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
Intervals: []gctkline.IntervalData{
|
|
{
|
|
Start: gctkline.CreateIntervalTime(tt),
|
|
End: gctkline.CreateIntervalTime(tt.Add(gctkline.FifteenMin.Duration())),
|
|
HasData: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = k.Load()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
ev.Order = &gctorder.Detail{
|
|
Exchange: testExchange,
|
|
AssetType: ev.AssetType,
|
|
Pair: cp,
|
|
Amount: 1,
|
|
Price: 1,
|
|
Side: gctorder.Short,
|
|
OrderID: "1",
|
|
Date: time.Now(),
|
|
}
|
|
bt.Datas.SetDataForCurrency(testExchange, a, cp, &k)
|
|
err = bt.processFuturesFillEvent(ev, pair)
|
|
if !errors.Is(err, expectedError) {
|
|
t.Errorf("received '%v' expected '%v'", err, expectedError)
|
|
}
|
|
}
|
|
|
|
func TestGenerateSummary(t *testing.T) {
|
|
t.Parallel()
|
|
bt := &BackTest{}
|
|
sum, err := bt.GenerateSummary()
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
if !sum.MetaData.ID.IsNil() {
|
|
t.Errorf("received '%v' expected '%v'", sum.MetaData.ID, "")
|
|
}
|
|
id, err := uuid.NewV4()
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
bt.MetaData.ID = id
|
|
sum, err = bt.GenerateSummary()
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
if sum.MetaData.ID != id {
|
|
t.Errorf("received '%v' expected '%v'", sum.MetaData.ID, id)
|
|
}
|
|
|
|
bt = nil
|
|
_, err = bt.GenerateSummary()
|
|
if !errors.Is(err, gctcommon.ErrNilPointer) {
|
|
t.Errorf("received '%v' expected '%v'", err, gctcommon.ErrNilPointer)
|
|
}
|
|
}
|
|
|
|
func TestSetupMetaData(t *testing.T) {
|
|
t.Parallel()
|
|
bt := &BackTest{}
|
|
err := bt.SetupMetaData()
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
if bt.MetaData.ID.IsNil() {
|
|
t.Errorf("received '%v' expected '%v'", bt.MetaData.ID, "an ID")
|
|
}
|
|
firstID := bt.MetaData.ID
|
|
err = bt.SetupMetaData()
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
if bt.MetaData.ID != firstID {
|
|
t.Errorf("received '%v' expected '%v'", bt.MetaData.ID, firstID)
|
|
}
|
|
|
|
bt = nil
|
|
err = bt.SetupMetaData()
|
|
if !errors.Is(err, gctcommon.ErrNilPointer) {
|
|
t.Errorf("received '%v' expected '%v'", err, gctcommon.ErrNilPointer)
|
|
}
|
|
}
|
|
|
|
func TestIsRunning(t *testing.T) {
|
|
t.Parallel()
|
|
bt := &BackTest{}
|
|
if bt.IsRunning() {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
bt.MetaData.DateStarted = time.Now()
|
|
if !bt.IsRunning() {
|
|
t.Errorf("received '%v' expected '%v'", false, true)
|
|
}
|
|
|
|
bt.MetaData.Closed = true
|
|
if bt.IsRunning() {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
bt = nil
|
|
if bt.IsRunning() {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
}
|
|
|
|
func TestHasRan(t *testing.T) {
|
|
t.Parallel()
|
|
bt := &BackTest{}
|
|
if bt.HasRan() {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
bt.MetaData.DateStarted = time.Now()
|
|
if bt.HasRan() {
|
|
t.Errorf("received '%v' expected '%v'", false, true)
|
|
}
|
|
|
|
bt.MetaData.Closed = true
|
|
if !bt.HasRan() {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
bt = nil
|
|
if bt.HasRan() {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
}
|
|
|
|
func TestEqual(t *testing.T) {
|
|
t.Parallel()
|
|
bt := &BackTest{}
|
|
bt2 := &BackTest{}
|
|
bt3 := &BackTest{}
|
|
if !bt.Equal(bt2) {
|
|
t.Errorf("received '%v' expected '%v'", false, true)
|
|
}
|
|
|
|
err := bt.SetupMetaData()
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
bt2.MetaData = bt.MetaData
|
|
if !bt.Equal(bt2) {
|
|
t.Errorf("received '%v' expected '%v'", false, true)
|
|
}
|
|
|
|
if bt.Equal(nil) {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
err = bt3.SetupMetaData()
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
if bt.Equal(bt3) {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
bt = nil
|
|
if bt.Equal(bt2) {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
}
|
|
|
|
func TestMatchesID(t *testing.T) {
|
|
t.Parallel()
|
|
bt := &BackTest{}
|
|
if bt.MatchesID(uuid.Nil) {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
err := bt.SetupMetaData()
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
|
|
if bt.MatchesID(uuid.Nil) {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
if !bt.MatchesID(bt.MetaData.ID) {
|
|
t.Errorf("received '%v' expected '%v'", false, true)
|
|
}
|
|
|
|
id := bt.MetaData.ID
|
|
bt.MetaData.ID = uuid.Nil
|
|
if bt.MatchesID(id) {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
|
|
bt = nil
|
|
if bt.MatchesID(id) {
|
|
t.Errorf("received '%v' expected '%v'", true, false)
|
|
}
|
|
}
|
|
|
|
func TestExecuteStrategy(t *testing.T) {
|
|
t.Parallel()
|
|
bt := &BackTest{}
|
|
err := bt.ExecuteStrategy(false)
|
|
if !errors.Is(err, errNotSetup) {
|
|
t.Errorf("received '%v' expected '%v'", err, errNotSetup)
|
|
}
|
|
bt.MetaData.DateLoaded = time.Now()
|
|
bt.MetaData.DateStarted = time.Now()
|
|
err = bt.ExecuteStrategy(false)
|
|
if !errors.Is(err, errRunIsRunning) {
|
|
t.Errorf("received '%v' expected '%v'", err, errRunIsRunning)
|
|
}
|
|
|
|
strat1 := filepath.Join("..", "config", "strategyexamples", "dca-api-candles.strat")
|
|
cfg, err := config.ReadStrategyConfigFromFile(strat1)
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
|
|
bt, err = NewFromConfig(cfg, "", "", false)
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
bt.Stop()
|
|
|
|
err = bt.ExecuteStrategy(true)
|
|
if !errors.Is(err, errAlreadyRan) {
|
|
t.Errorf("received '%v' expected '%v'", err, errAlreadyRan)
|
|
}
|
|
|
|
strat2 := filepath.Join("..", "config", "strategyexamples", "dca-candles-live.strat")
|
|
cfg, err = config.ReadStrategyConfigFromFile(strat2)
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
bt, err = NewFromConfig(cfg, "", "", false)
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
err = bt.ExecuteStrategy(true)
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
|
|
bt.MetaData.DateStarted = time.Time{}
|
|
err = bt.ExecuteStrategy(false)
|
|
if !errors.Is(err, nil) {
|
|
t.Errorf("received '%v' expected '%v'", err, nil)
|
|
}
|
|
bt.Stop()
|
|
|
|
bt = nil
|
|
err = bt.ExecuteStrategy(false)
|
|
if !errors.Is(err, gctcommon.ErrNilPointer) {
|
|
t.Errorf("received '%v' expected '%v'", err, gctcommon.ErrNilPointer)
|
|
}
|
|
}
|