mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
* Adds lovely initial concept for historical data doer
* Adds ability to save tasks. Adds config. Adds startStop to engine
* Has a database microservice without use of globals! Further infrastructure design. Adds readme
* Commentary to help design
* Adds migrations for database
* readme and adds database models
* Some modelling that doesn't work end of day
* Completes datahistoryjob sql.Begins datahistoryjobresult
* Adds datahistoryjob functions to retreive job results. Adapts subsystem
* Adds process for upserting jobs and job results to the database
* Broken end of day weird sqlboiler crap
* Fixes issue with SQL generation.
* RPC generation and addition of basic upsert command
* Renames types
* Adds rpc functions
* quick commit before context swithc. Exchanges aren't being populated
* Begin the tests!
* complete sql tests. stop failed jobs. CLI command creation
* Defines rpc commands
* Fleshes out RPC implementation
* Expands testing
* Expands testing, removes double remove
* Adds coverage of data history subsystem, expands errors and nil checks
* Minor logic improvement
* streamlines datahistory test setup
* End of day minor linting
* Lint, convert simplify, rpc expansion, type expansion, readme expansion
* Documentation update
* Renames for consistency
* Completes RPC server commands
* Fixes tests
* Speeds up testing by reducing unnecessary actions. Adds maxjobspercycle config
* Comments for everything
* Adds missing result string. checks interval supported. default start end cli
* Fixes ID problem. Improves binance trade fetch. job ranges are processed
* adds dbservice coverage. adds rpcserver coverage
* docs regen, uses dbcon interface, reverts binance, fixes races, toggle manager
* Speed up tests, remove bad global usage, fix uuid check
* Adds verbose. Updates docs. Fixes postgres
* Minor changes to logging and start stop
* Fixes postgres db tests, fixes postgres column typo
* Fixes old string typo,removes constraint,error parsing for nonreaders
* prevents dhm running when table doesn't exist. Adds prereq documentation
* Adds parallel, rmlines, err fix, comment fix, minor param fixes
* doc regen, common time range check and test updating
* Fixes job validation issues. Updates candle range checker.
* Ensures test cannot fail due to time.Now() shenanigans
* Fixes oopsie, adds documentation and a warn
* Fixes another time test, adjusts copy
* Drastically speeds up data history manager tests via function overrides
* Fixes summary bug and better logs
* Fixes local time test, fixes websocket tests
* removes defaults and comment,updates error messages,sets cli command args
* Fixes FTX trade processing
* Fixes issue where jobs got stuck if data wasn't returned but retrieval was successful
* Improves test speed. Simplifies trade verification SQL. Adds command help
* Fixes the oopsies
* Fixes use of query within transaction. Fixes trade err
* oopsie, not needed
* Adds missing data status. Properly ends job even when data is missing
* errors are more verbose and so have more words to describe them
* Doc regen for new status
* tiny test tinkering
* str := string("Removes .String()").String()
* Merge fixups
* Fixes a data race discovered during github actions
* Allows websocket test to pass consistently
* Fixes merge issue preventing datahistorymanager from starting via config
* Niterinos cmd defaults and explanations
* fixes default oopsie
* Fixes lack of nil protection
* Additional oopsie
* More detailed error for validating job exchange
561 lines
16 KiB
Go
561 lines
16 KiB
Go
package backtest
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"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/statistics/currencystatistics"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/base"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/dollarcostaverage"
|
|
"github.com/thrasher-corp/gocryptotrader/backtester/report"
|
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
|
"github.com/thrasher-corp/gocryptotrader/engine"
|
|
gctexchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
|
gctkline "github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
|
)
|
|
|
|
const testExchange = "Bitstamp"
|
|
|
|
func newBotWithExchange() (*engine.Engine, gctexchange.IBotExchange) {
|
|
bot, err := engine.NewFromSettings(&engine.Settings{
|
|
ConfigFile: filepath.Join("..", "..", "testdata", "configtest.json"),
|
|
EnableDryRun: true,
|
|
}, nil)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
bot.ExchangeManager = engine.SetupExchangeManager()
|
|
err = bot.LoadExchange(testExchange, false, nil)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
exch := bot.GetExchangeByName(testExchange)
|
|
if exch == nil {
|
|
log.Fatal("expected not nil")
|
|
}
|
|
return bot, exch
|
|
}
|
|
|
|
func TestNewFromConfig(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := NewFromConfig(nil, "", "", nil)
|
|
if err == nil {
|
|
t.Error("expected error for nil config")
|
|
}
|
|
|
|
cfg := &config.Config{
|
|
GoCryptoTraderConfigPath: filepath.Join("..", "..", "testdata", "configtest.json"),
|
|
}
|
|
_, err = NewFromConfig(cfg, "", "", nil)
|
|
if !errors.Is(err, errNilBot) {
|
|
t.Errorf("expected: %v, received %v", errNilBot, err)
|
|
}
|
|
|
|
bot, _ := newBotWithExchange()
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if !errors.Is(err, config.ErrNoCurrencySettings) {
|
|
t.Errorf("expected: %v, received %v", config.ErrNoCurrencySettings, err)
|
|
}
|
|
|
|
cfg.CurrencySettings = []config.CurrencySettings{
|
|
{
|
|
ExchangeName: "test",
|
|
Base: "test",
|
|
Quote: "test",
|
|
},
|
|
}
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if !errors.Is(err, config.ErrBadInitialFunds) {
|
|
t.Errorf("expected: %v, received %v", config.ErrBadInitialFunds, err)
|
|
}
|
|
|
|
cfg.CurrencySettings[0].InitialFunds = 1337
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if !errors.Is(err, config.ErrUnsetAsset) {
|
|
t.Errorf("expected: %v, received %v", config.ErrUnsetAsset, err)
|
|
}
|
|
|
|
cfg.CurrencySettings[0].Asset = asset.Spot.String()
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if !errors.Is(err, engine.ErrExchangeNotFound) {
|
|
t.Errorf("expected: %v, received %v", engine.ErrExchangeNotFound, err)
|
|
}
|
|
|
|
cfg.CurrencySettings[0].ExchangeName = testExchange
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if !errors.Is(err, errNoDataSource) {
|
|
t.Errorf("expected: %v, received %v", errNoDataSource, err)
|
|
}
|
|
|
|
cfg.CurrencySettings[0].Base = "BTC"
|
|
cfg.CurrencySettings[0].Quote = "USD"
|
|
|
|
cfg.DataSettings.APIData = &config.APIData{
|
|
StartDate: time.Time{},
|
|
EndDate: time.Time{},
|
|
}
|
|
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if err != nil && !strings.Contains(err.Error(), "unrecognised dataType") {
|
|
t.Error(err)
|
|
}
|
|
cfg.DataSettings.DataType = common.CandleStr
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if !errors.Is(err, config.ErrStartEndUnset) {
|
|
t.Errorf("expected: %v, received %v", config.ErrStartEndUnset, err)
|
|
}
|
|
|
|
cfg.DataSettings.APIData.StartDate = time.Now().Add(-time.Hour)
|
|
cfg.DataSettings.APIData.EndDate = time.Now()
|
|
cfg.DataSettings.APIData.InclusiveEndDate = true
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if !errors.Is(err, errIntervalUnset) {
|
|
t.Errorf("expected: %v, received %v", errIntervalUnset, err)
|
|
}
|
|
|
|
cfg.DataSettings.Interval = gctkline.FifteenMin.Duration()
|
|
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if !errors.Is(err, base.ErrStrategyNotFound) {
|
|
t.Errorf("expected: %v, received %v", base.ErrStrategyNotFound, err)
|
|
}
|
|
|
|
cfg.StrategySettings = config.StrategySettings{
|
|
Name: dollarcostaverage.Name,
|
|
CustomSettings: map[string]interface{}{
|
|
"hello": "moto",
|
|
},
|
|
}
|
|
cfg.CurrencySettings[0].MakerFee = 1337
|
|
cfg.CurrencySettings[0].TakerFee = 1337
|
|
_, err = NewFromConfig(cfg, "", "", bot)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestLoadData(t *testing.T) {
|
|
t.Parallel()
|
|
cfg := &config.Config{
|
|
GoCryptoTraderConfigPath: filepath.Join("..", "..", "testdata", "configtest.json"),
|
|
}
|
|
cfg.CurrencySettings = []config.CurrencySettings{
|
|
{
|
|
ExchangeName: "test",
|
|
Asset: "test",
|
|
Base: "test",
|
|
Quote: "test",
|
|
},
|
|
}
|
|
cfg.CurrencySettings[0].ExchangeName = "binance"
|
|
cfg.CurrencySettings[0].Asset = asset.Spot.String()
|
|
cfg.CurrencySettings[0].Base = "BTC"
|
|
cfg.CurrencySettings[0].Quote = "USDT"
|
|
cfg.CurrencySettings[0].InitialFunds = 1337
|
|
cfg.DataSettings.APIData = &config.APIData{
|
|
StartDate: time.Time{},
|
|
EndDate: time.Time{},
|
|
}
|
|
cfg.DataSettings.APIData.StartDate = time.Now().Add(-time.Hour)
|
|
cfg.DataSettings.APIData.EndDate = time.Now()
|
|
cfg.DataSettings.Interval = gctkline.FifteenMin.Duration()
|
|
cfg.DataSettings.DataType = common.CandleStr
|
|
cfg.StrategySettings = config.StrategySettings{
|
|
Name: dollarcostaverage.Name,
|
|
CustomSettings: map[string]interface{}{
|
|
"hello": "moto",
|
|
},
|
|
}
|
|
cfg.CurrencySettings[0].MakerFee = 1337
|
|
cfg.CurrencySettings[0].TakerFee = 1337
|
|
bot, exch := newBotWithExchange()
|
|
|
|
_, err := NewFromConfig(cfg, "", "", bot)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
bt := BackTest{
|
|
Reports: &report.Data{},
|
|
}
|
|
|
|
cp := currency.NewPair(currency.BTC, currency.USD)
|
|
_, err = bt.loadData(cfg, exch, cp, asset.Spot)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
cfg.DataSettings.APIData = nil
|
|
cfg.DataSettings.DatabaseData = &config.DatabaseData{
|
|
StartDate: time.Now().Add(-time.Hour),
|
|
EndDate: time.Now(),
|
|
ConfigOverride: nil,
|
|
InclusiveEndDate: true,
|
|
}
|
|
cfg.DataSettings.DataType = common.CandleStr
|
|
cfg.DataSettings.Interval = gctkline.FifteenMin.Duration()
|
|
|
|
bt.Bot = bot
|
|
_, err = bt.loadData(cfg, exch, cp, asset.Spot)
|
|
if err != nil && !strings.Contains(err.Error(), "unable to retrieve data from GoCryptoTrader database") {
|
|
t.Error(err)
|
|
}
|
|
|
|
cfg.DataSettings.DatabaseData = nil
|
|
cfg.DataSettings.CSVData = &config.CSVData{
|
|
FullPath: "test",
|
|
}
|
|
_, err = bt.loadData(cfg, exch, cp, asset.Spot)
|
|
if err != nil &&
|
|
!strings.Contains(err.Error(), "The system cannot find the file specified.") &&
|
|
!strings.Contains(err.Error(), "no such file or directory") {
|
|
t.Error(err)
|
|
}
|
|
cfg.DataSettings.CSVData = nil
|
|
cfg.DataSettings.LiveData = &config.LiveData{
|
|
APIKeyOverride: "test",
|
|
APISecretOverride: "test",
|
|
APIClientIDOverride: "test",
|
|
API2FAOverride: "test",
|
|
APISubaccountOverride: "test",
|
|
RealOrders: true,
|
|
}
|
|
_, err = bt.loadData(cfg, exch, cp, asset.Spot)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestLoadDatabaseData(t *testing.T) {
|
|
t.Parallel()
|
|
cp := currency.NewPair(currency.BTC, currency.USD)
|
|
_, err := loadDatabaseData(nil, "", cp, "", -1)
|
|
if err != nil && !strings.Contains(err.Error(), "nil config data received") {
|
|
t.Error(err)
|
|
}
|
|
cfg := &config.Config{
|
|
DataSettings: config.DataSettings{
|
|
DatabaseData: &config.DatabaseData{
|
|
StartDate: time.Time{},
|
|
EndDate: time.Time{},
|
|
ConfigOverride: nil,
|
|
},
|
|
},
|
|
GoCryptoTraderConfigPath: filepath.Join("..", "..", "testdata", "configtest.json"),
|
|
}
|
|
_, err = loadDatabaseData(cfg, "", cp, "", -1)
|
|
if !errors.Is(err, config.ErrStartEndUnset) {
|
|
t.Errorf("expected %v, received %v", config.ErrStartEndUnset, err)
|
|
}
|
|
cfg.DataSettings.DatabaseData.StartDate = time.Now().Add(-time.Hour)
|
|
cfg.DataSettings.DatabaseData.EndDate = time.Now()
|
|
_, err = loadDatabaseData(cfg, "", cp, "", -1)
|
|
if !errors.Is(err, errIntervalUnset) {
|
|
t.Errorf("expected %v, received %v", errIntervalUnset, err)
|
|
}
|
|
|
|
cfg.DataSettings.Interval = gctkline.OneDay.Duration()
|
|
_, err = loadDatabaseData(cfg, "", cp, "", -1)
|
|
if err != nil && !strings.Contains(err.Error(), "could not retrieve database data") {
|
|
t.Error(err)
|
|
}
|
|
|
|
cfg.DataSettings.DataType = common.CandleStr
|
|
_, err = loadDatabaseData(cfg, "", cp, "", common.DataCandle)
|
|
if err != nil && !strings.Contains(err.Error(), "exchange, base, quote, asset, interval, start & end cannot be empty") {
|
|
t.Error(err)
|
|
}
|
|
_, err = loadDatabaseData(cfg, testExchange, cp, asset.Spot, common.DataCandle)
|
|
if err != nil && !strings.Contains(err.Error(), "database support is disabled") {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestLoadLiveData(t *testing.T) {
|
|
t.Parallel()
|
|
err := loadLiveData(nil, nil)
|
|
if !errors.Is(err, common.ErrNilArguments) {
|
|
t.Error(err)
|
|
}
|
|
cfg := &config.Config{
|
|
GoCryptoTraderConfigPath: filepath.Join("..", "..", "testdata", "configtest.json"),
|
|
}
|
|
err = loadLiveData(cfg, nil)
|
|
if !errors.Is(err, common.ErrNilArguments) {
|
|
t.Error(err)
|
|
}
|
|
b := &gctexchange.Base{
|
|
Name: testExchange,
|
|
API: gctexchange.API{
|
|
AuthenticatedSupport: false,
|
|
AuthenticatedWebsocketSupport: false,
|
|
PEMKeySupport: false,
|
|
Credentials: struct {
|
|
Key string
|
|
Secret string
|
|
ClientID string
|
|
PEMKey string
|
|
Subaccount string
|
|
}{},
|
|
CredentialsValidator: struct {
|
|
RequiresPEM bool
|
|
RequiresKey bool
|
|
RequiresSecret bool
|
|
RequiresClientID bool
|
|
RequiresBase64DecodeSecret bool
|
|
}{
|
|
RequiresPEM: true,
|
|
RequiresKey: true,
|
|
RequiresSecret: true,
|
|
RequiresClientID: true,
|
|
RequiresBase64DecodeSecret: true,
|
|
},
|
|
},
|
|
}
|
|
err = loadLiveData(cfg, b)
|
|
if !errors.Is(err, common.ErrNilArguments) {
|
|
t.Error(err)
|
|
}
|
|
cfg.DataSettings.LiveData = &config.LiveData{
|
|
|
|
RealOrders: true,
|
|
}
|
|
cfg.DataSettings.Interval = gctkline.OneDay.Duration()
|
|
cfg.DataSettings.DataType = common.CandleStr
|
|
err = loadLiveData(cfg, b)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
cfg.DataSettings.LiveData.APIKeyOverride = "1234"
|
|
cfg.DataSettings.LiveData.APISecretOverride = "1234"
|
|
cfg.DataSettings.LiveData.APIClientIDOverride = "1234"
|
|
cfg.DataSettings.LiveData.API2FAOverride = "1234"
|
|
cfg.DataSettings.LiveData.APISubaccountOverride = "1234"
|
|
err = loadLiveData(cfg, b)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestReset(t *testing.T) {
|
|
t.Parallel()
|
|
bt := BackTest{
|
|
Bot: &engine.Engine{},
|
|
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{},
|
|
}
|
|
bt.Reset()
|
|
if bt.Bot != nil {
|
|
t.Error("expected nil")
|
|
}
|
|
}
|
|
|
|
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]*currencystatistics.CurrencyStatistic)
|
|
stats.ExchangeAssetPairStatistics[ex] = make(map[asset.Item]map[currency.Pair]*currencystatistics.CurrencyStatistic)
|
|
stats.ExchangeAssetPairStatistics[ex][a] = make(map[currency.Pair]*currencystatistics.CurrencyStatistic)
|
|
|
|
port, err := portfolio.Setup(&size.Size{
|
|
BuySide: config.MinMax{},
|
|
SellSide: config.MinMax{},
|
|
}, &risk.Risk{}, 0)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
_, err = port.SetupCurrencySettingsMap(ex, a, cp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
err = port.SetInitialFunds(ex, a, cp, 1333337)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
bot, _ := newBotWithExchange()
|
|
|
|
bt := BackTest{
|
|
Bot: bot,
|
|
shutdown: nil,
|
|
Datas: &data.HandlerPerCurrency{},
|
|
Strategy: &dollarcostaverage.Strategy{},
|
|
Portfolio: port,
|
|
Exchange: &exchange.Exchange{},
|
|
Statistic: stats,
|
|
EventQueue: &eventholder.Holder{},
|
|
Reports: &report.Data{},
|
|
}
|
|
|
|
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{},
|
|
Range: &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)
|
|
|
|
err = bt.Run()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestStop(t *testing.T) {
|
|
t.Parallel()
|
|
bt := BackTest{shutdown: make(chan struct{})}
|
|
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]*currencystatistics.CurrencyStatistic)
|
|
stats.ExchangeAssetPairStatistics[ex] = make(map[asset.Item]map[currency.Pair]*currencystatistics.CurrencyStatistic)
|
|
stats.ExchangeAssetPairStatistics[ex][a] = make(map[currency.Pair]*currencystatistics.CurrencyStatistic)
|
|
|
|
port, err := portfolio.Setup(&size.Size{
|
|
BuySide: config.MinMax{},
|
|
SellSide: config.MinMax{},
|
|
}, &risk.Risk{}, 0)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
_, err = port.SetupCurrencySettingsMap(ex, a, cp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
err = port.SetInitialFunds(ex, a, cp, 1333337)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
bot, _ := newBotWithExchange()
|
|
|
|
bt := BackTest{
|
|
Bot: bot,
|
|
shutdown: nil,
|
|
Datas: &data.HandlerPerCurrency{},
|
|
Portfolio: port,
|
|
Exchange: &exchange.Exchange{},
|
|
Statistic: stats,
|
|
EventQueue: &eventholder.Holder{},
|
|
Reports: &report.Data{},
|
|
}
|
|
|
|
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{},
|
|
Range: &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)
|
|
|
|
err = bt.Run()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|