mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-02 07:26:53 +00:00
build/ci: Update Go to v1.24, golangci-lint to v1.64.6 and fix issues (#1804)
* build/ci: Update Go to v1.24, golangci-lint to v1.64.5 and fix issues * Address shazbert's nitters * linter/config: Fix new linter issue and use versionSize const * Address gk's nitters and fix additional linter issue after rebase * Address glorious nits * staticcheck: Fix additional linter issues after upgrading to Go 1.24.1 and golangci-lint v1.64.6 Also addresses nits * Improve testing, assertify usage and use common.ErrParsingWSField * TestCreateNewStrategy: Replace must > should wording
This commit is contained in:
@@ -1,15 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/btrpc"
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/urfave/cli/v2"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -49,10 +50,10 @@ var executeStrategyFromFileCommand = &cli.Command{
|
||||
Aliases: []string{"e"},
|
||||
Usage: fmt.Sprintf("override the strategy file's end time using your local time. eg '%v'", time.Now().Truncate(time.Hour).Format(time.DateTime)),
|
||||
},
|
||||
&cli.Uint64Flag{
|
||||
&cli.DurationFlag{
|
||||
Name: "intervaloverride",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "override the strategy file's candle interval, in seconds. eg 60 = 1 minute",
|
||||
Usage: "override the strategy file's candle interval in the format of a time duration. eg '1m' for 1 minute",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -118,16 +119,18 @@ func executeStrategyFromFile(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
var intervalOverride uint64
|
||||
var intervalOverride time.Duration
|
||||
if c.IsSet("intervaloverride") {
|
||||
intervalOverride = c.Uint64("intervaloverride")
|
||||
intervalOverride = c.Duration("intervaloverride")
|
||||
} else if c.Args().Get(5) != "" {
|
||||
intervalOverride, err = strconv.ParseUint(c.Args().Get(5), 10, 64)
|
||||
intervalOverride, err = time.ParseDuration(c.Args().Get(5))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
overrideDuration := time.Duration(intervalOverride) * time.Second
|
||||
if intervalOverride < 0 {
|
||||
return errors.New("interval override duration cannot be less than 0")
|
||||
}
|
||||
|
||||
client := btrpc.NewBacktesterServiceClient(conn)
|
||||
result, err := client.ExecuteStrategyFromFile(
|
||||
@@ -138,7 +141,7 @@ func executeStrategyFromFile(c *cli.Context) error {
|
||||
DoNotStore: dns,
|
||||
StartTimeOverride: timestamppb.New(s),
|
||||
EndTimeOverride: timestamppb.New(e),
|
||||
IntervalOverride: uint64(overrideDuration),
|
||||
IntervalOverride: durationpb.New(intervalOverride),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -503,7 +506,7 @@ func executeStrategyFromConfig(c *cli.Context) error {
|
||||
}
|
||||
|
||||
dataSettings := &btrpc.DataSettings{
|
||||
Interval: uint64(defaultConfig.DataSettings.Interval.Duration().Nanoseconds()),
|
||||
Interval: durationpb.New(defaultConfig.DataSettings.Interval.Duration()),
|
||||
Datatype: defaultConfig.DataSettings.DataType,
|
||||
}
|
||||
if defaultConfig.DataSettings.APIData != nil {
|
||||
@@ -546,7 +549,7 @@ func executeStrategyFromConfig(c *cli.Context) error {
|
||||
if defaultConfig.DataSettings.DatabaseData != nil {
|
||||
dbConnectionDetails := &btrpc.DatabaseConnectionDetails{
|
||||
Host: defaultConfig.DataSettings.DatabaseData.Config.Host,
|
||||
Port: uint32(defaultConfig.DataSettings.DatabaseData.Config.Port),
|
||||
Port: defaultConfig.DataSettings.DatabaseData.Config.Port,
|
||||
Password: defaultConfig.DataSettings.DatabaseData.Config.Password,
|
||||
Database: defaultConfig.DataSettings.DatabaseData.Config.Database,
|
||||
SslMode: defaultConfig.DataSettings.DatabaseData.Config.SSLMode,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ syntax = "proto3";
|
||||
package btrpc;
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/thrasher-corp/gocryptotrader/backtester/btrpc";
|
||||
@@ -151,7 +152,7 @@ message ExchangeCredentials {
|
||||
}
|
||||
|
||||
message DataSettings {
|
||||
uint64 interval = 1;
|
||||
google.protobuf.Duration interval = 1;
|
||||
string datatype = 2;
|
||||
ApiData api_data = 3;
|
||||
DatabaseData database_data = 4;
|
||||
@@ -205,7 +206,7 @@ message ExecuteStrategyFromFileRequest {
|
||||
bool do_not_store = 3;
|
||||
google.protobuf.Timestamp start_time_override = 4;
|
||||
google.protobuf.Timestamp end_time_override = 5;
|
||||
uint64 interval_override = 6;
|
||||
google.protobuf.Duration interval_override = 6;
|
||||
}
|
||||
|
||||
message ExecuteStrategyResponse {
|
||||
|
||||
@@ -138,8 +138,7 @@
|
||||
"name": "config.dataSettings.interval",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "config.dataSettings.datatype",
|
||||
@@ -426,8 +425,7 @@
|
||||
"name": "intervalOverride",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
@@ -723,8 +721,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"interval": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
"type": "string"
|
||||
},
|
||||
"datatype": {
|
||||
"type": "string"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc-gen-go-grpc v1.4.0
|
||||
// - protoc (unknown)
|
||||
// source: btrpc.proto
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
// Requires gRPC-Go v1.62.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion8
|
||||
|
||||
const (
|
||||
BacktesterService_ExecuteStrategyFromFile_FullMethodName = "/btrpc.BacktesterService/ExecuteStrategyFromFile"
|
||||
@@ -54,8 +54,9 @@ func NewBacktesterServiceClient(cc grpc.ClientConnInterface) BacktesterServiceCl
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) ExecuteStrategyFromFile(ctx context.Context, in *ExecuteStrategyFromFileRequest, opts ...grpc.CallOption) (*ExecuteStrategyResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ExecuteStrategyResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ExecuteStrategyFromFile_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ExecuteStrategyFromFile_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -63,8 +64,9 @@ func (c *backtesterServiceClient) ExecuteStrategyFromFile(ctx context.Context, i
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) ExecuteStrategyFromConfig(ctx context.Context, in *ExecuteStrategyFromConfigRequest, opts ...grpc.CallOption) (*ExecuteStrategyResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ExecuteStrategyResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ExecuteStrategyFromConfig_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ExecuteStrategyFromConfig_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -72,8 +74,9 @@ func (c *backtesterServiceClient) ExecuteStrategyFromConfig(ctx context.Context,
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) ListAllTasks(ctx context.Context, in *ListAllTasksRequest, opts ...grpc.CallOption) (*ListAllTasksResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListAllTasksResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ListAllTasks_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ListAllTasks_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -81,8 +84,9 @@ func (c *backtesterServiceClient) ListAllTasks(ctx context.Context, in *ListAllT
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) StartTask(ctx context.Context, in *StartTaskRequest, opts ...grpc.CallOption) (*StartTaskResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(StartTaskResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_StartTask_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_StartTask_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -90,8 +94,9 @@ func (c *backtesterServiceClient) StartTask(ctx context.Context, in *StartTaskRe
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) StartAllTasks(ctx context.Context, in *StartAllTasksRequest, opts ...grpc.CallOption) (*StartAllTasksResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(StartAllTasksResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_StartAllTasks_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_StartAllTasks_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -99,8 +104,9 @@ func (c *backtesterServiceClient) StartAllTasks(ctx context.Context, in *StartAl
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) StopTask(ctx context.Context, in *StopTaskRequest, opts ...grpc.CallOption) (*StopTaskResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(StopTaskResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_StopTask_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_StopTask_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -108,8 +114,9 @@ func (c *backtesterServiceClient) StopTask(ctx context.Context, in *StopTaskRequ
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) StopAllTasks(ctx context.Context, in *StopAllTasksRequest, opts ...grpc.CallOption) (*StopAllTasksResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(StopAllTasksResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_StopAllTasks_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_StopAllTasks_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -117,8 +124,9 @@ func (c *backtesterServiceClient) StopAllTasks(ctx context.Context, in *StopAllT
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) ClearTask(ctx context.Context, in *ClearTaskRequest, opts ...grpc.CallOption) (*ClearTaskResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ClearTaskResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ClearTask_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ClearTask_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -126,8 +134,9 @@ func (c *backtesterServiceClient) ClearTask(ctx context.Context, in *ClearTaskRe
|
||||
}
|
||||
|
||||
func (c *backtesterServiceClient) ClearAllTasks(ctx context.Context, in *ClearAllTasksRequest, opts ...grpc.CallOption) (*ClearAllTasksResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ClearAllTasksResponse)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ClearAllTasks_FullMethodName, in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, BacktesterService_ClearAllTasks_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -4,8 +4,15 @@ deps:
|
||||
- remote: buf.build
|
||||
owner: googleapis
|
||||
repository: googleapis
|
||||
commit: 62f35d8aed1149c291d606d958a7ce32
|
||||
commit: 546238c53f7340c6a2a6099fb863bc1b
|
||||
digest: shake256:8d75c12f391e392b24c076d05117b47aeddb090add99c70247a8f4389b906a65f61a933c68e54ed8b73a050b967b6b712ba194348b67c3ab3ee26cc2cb25852c
|
||||
- remote: buf.build
|
||||
owner: grpc-ecosystem
|
||||
repository: grpc-gateway
|
||||
commit: bc28b723cd774c32b6fbc77621518765
|
||||
commit: 4c5ba75caaf84e928b7137ae5c18c26a
|
||||
digest: shake256:e174ad9408f3e608f6157907153ffec8d310783ee354f821f57178ffbeeb8faa6bb70b41b61099c1783c82fe16210ebd1279bc9c9ee6da5cffba9f0e675b8b99
|
||||
- remote: buf.build
|
||||
owner: protocolbuffers
|
||||
repository: wellknowntypes
|
||||
commit: d4f14e5e0a9c40889c90d373c74e95eb
|
||||
digest: shake256:c9824714afd6cc432c2e1fafa20df47c87a8a0aca9e27192cd5732619453997af1721c2eac5c0fbbe7b29a741af5b8d7ba4ee89c85903e782d9c725d7b9436b5
|
||||
|
||||
@@ -14,4 +14,5 @@ breaking:
|
||||
- FILE
|
||||
deps:
|
||||
- buf.build/googleapis/googleapis
|
||||
- buf.build/protocolbuffers/wellknowntypes
|
||||
- buf.build/grpc-ecosystem/grpc-gateway
|
||||
|
||||
@@ -429,12 +429,12 @@ func parseDatabase(reader *bufio.Reader, cfg *config.Config) error {
|
||||
input = quickParse(reader)
|
||||
var port uint64
|
||||
if input != "" {
|
||||
port, err = strconv.ParseUint(input, 10, 16)
|
||||
port, err = strconv.ParseUint(input, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cfg.DataSettings.DatabaseData.Config.Port = uint16(port)
|
||||
cfg.DataSettings.DatabaseData.Config.Port = uint32(port) //nolint:gosec // No overflow risk
|
||||
err = database.DB.SetConfig(&cfg.DataSettings.DatabaseData.Config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("database failed to set config: %w", err)
|
||||
|
||||
@@ -130,7 +130,7 @@ candleLoop:
|
||||
d.Item.RemoveDuplicates()
|
||||
d.Item.SortCandlesByTimestamp(false)
|
||||
if d.RangeHolder != nil {
|
||||
d.RangeHolder, err = gctkline.CalculateCandleDateRanges(d.Item.Candles[0].Time, d.Item.Candles[len(d.Item.Candles)-1].Time.Add(d.Item.Interval.Duration()), d.Item.Interval, uint32(d.RangeHolder.Limit))
|
||||
d.RangeHolder, err = gctkline.CalculateCandleDateRanges(d.Item.Candles[0].Time, d.Item.Candles[len(d.Item.Candles)-1].Time.Add(d.Item.Interval.Duration()), d.Item.Interval, d.RangeHolder.Limit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -211,11 +211,11 @@ func (s *GRPCServer) ExecuteStrategyFromFile(_ context.Context, request *btrpc.E
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if io64 := int64(request.IntervalOverride); io64 > 0 {
|
||||
if io64 < gctkline.FifteenSecond.Duration().Nanoseconds() {
|
||||
return nil, fmt.Errorf("%w, interval must be >= 15 seconds, received '%v'", gctkline.ErrInvalidInterval, time.Duration(request.IntervalOverride))
|
||||
if io := request.IntervalOverride.AsDuration(); io > 0 {
|
||||
if io < gctkline.FifteenSecond.Duration() {
|
||||
return nil, fmt.Errorf("%w, interval must be >= 15 seconds, received '%v'", gctkline.ErrInvalidInterval, io)
|
||||
}
|
||||
cfg.DataSettings.Interval = gctkline.Interval(request.IntervalOverride)
|
||||
cfg.DataSettings.Interval = gctkline.Interval(io)
|
||||
}
|
||||
|
||||
if startTime := request.StartTimeOverride.AsTime(); startTime.Unix() != 0 && !startTime.IsZero() {
|
||||
@@ -528,7 +528,7 @@ func (s *GRPCServer) ExecuteStrategyFromConfig(_ context.Context, request *btrpc
|
||||
Driver: request.Config.DataSettings.DatabaseData.Config.Driver,
|
||||
ConnectionDetails: drivers.ConnectionDetails{
|
||||
Host: request.Config.DataSettings.DatabaseData.Config.Config.Host,
|
||||
Port: uint16(request.Config.DataSettings.DatabaseData.Config.Config.Port),
|
||||
Port: request.Config.DataSettings.DatabaseData.Config.Config.Port,
|
||||
Username: request.Config.DataSettings.DatabaseData.Config.Config.UserName,
|
||||
Password: request.Config.DataSettings.DatabaseData.Config.Config.Password,
|
||||
Database: request.Config.DataSettings.DatabaseData.Config.Config.Database,
|
||||
@@ -591,7 +591,7 @@ func (s *GRPCServer) ExecuteStrategyFromConfig(_ context.Context, request *btrpc
|
||||
},
|
||||
CurrencySettings: configSettings,
|
||||
DataSettings: config.DataSettings{
|
||||
Interval: gctkline.Interval(request.Config.DataSettings.Interval),
|
||||
Interval: gctkline.Interval(request.Config.DataSettings.Interval.AsDuration()),
|
||||
DataType: request.Config.DataSettings.Datatype,
|
||||
APIData: apiData,
|
||||
DatabaseData: dbData,
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/binancecashandcarry"
|
||||
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
||||
gctkline "github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@@ -80,7 +81,7 @@ func TestExecuteStrategyFromFile(t *testing.T) {
|
||||
StrategyFilePath: dcaConfigPath,
|
||||
StartTimeOverride: timestamppb.New(time.Now().Add(-time.Minute)),
|
||||
EndTimeOverride: timestamppb.New(time.Now()),
|
||||
IntervalOverride: 1,
|
||||
IntervalOverride: durationpb.New(time.Duration(1)),
|
||||
})
|
||||
if !errors.Is(err, gctkline.ErrInvalidInterval) {
|
||||
t.Errorf("received '%v' expecting '%v'", err, gctkline.ErrInvalidInterval)
|
||||
@@ -90,7 +91,7 @@ func TestExecuteStrategyFromFile(t *testing.T) {
|
||||
StrategyFilePath: dcaConfigPath,
|
||||
StartTimeOverride: timestamppb.New(time.Now().Add(-time.Hour * 6).Truncate(time.Hour)),
|
||||
EndTimeOverride: timestamppb.New(time.Now().Add(-time.Hour * 2).Truncate(time.Hour)),
|
||||
IntervalOverride: uint64(time.Hour.Nanoseconds()),
|
||||
IntervalOverride: durationpb.New(time.Hour),
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v' expecting '%v'", err, nil)
|
||||
@@ -218,7 +219,7 @@ func TestExecuteStrategyFromConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
dataSettings := &btrpc.DataSettings{
|
||||
Interval: uint64(defaultConfig.DataSettings.Interval.Duration().Nanoseconds()),
|
||||
Interval: durationpb.New(defaultConfig.DataSettings.Interval.Duration()),
|
||||
Datatype: defaultConfig.DataSettings.DataType,
|
||||
}
|
||||
if defaultConfig.DataSettings.APIData != nil {
|
||||
@@ -256,7 +257,7 @@ func TestExecuteStrategyFromConfig(t *testing.T) {
|
||||
if defaultConfig.DataSettings.DatabaseData != nil {
|
||||
dbConnectionDetails := &btrpc.DatabaseConnectionDetails{
|
||||
Host: defaultConfig.DataSettings.DatabaseData.Config.Host,
|
||||
Port: uint32(defaultConfig.DataSettings.DatabaseData.Config.Port),
|
||||
Port: defaultConfig.DataSettings.DatabaseData.Config.Port,
|
||||
Password: defaultConfig.DataSettings.DatabaseData.Config.Password,
|
||||
Database: defaultConfig.DataSettings.DatabaseData.Config.Database,
|
||||
SslMode: defaultConfig.DataSettings.DatabaseData.Config.SSLMode,
|
||||
|
||||
@@ -820,19 +820,12 @@ func (bt *BackTest) loadData(cfg *config.Config, exch gctexchange.IBotExchange,
|
||||
cfg.DataSettings.APIData.EndDate = cfg.DataSettings.APIData.EndDate.Add(cfg.DataSettings.Interval.Duration())
|
||||
}
|
||||
|
||||
var limit int64
|
||||
limit, err = b.Features.Enabled.Kline.GetIntervalResultLimit(cfg.DataSettings.Interval)
|
||||
limit, err := b.Features.Enabled.Kline.GetIntervalResultLimit(cfg.DataSettings.Interval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err = loadAPIData(
|
||||
cfg,
|
||||
exch,
|
||||
fPair,
|
||||
a,
|
||||
uint32(limit),
|
||||
dataType)
|
||||
resp, err = loadAPIData(cfg, exch, fPair, a, limit, dataType)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -894,7 +887,7 @@ func loadDatabaseData(cfg *config.Config, name string, fPair currency.Pair, a as
|
||||
isUSDTrackingPair)
|
||||
}
|
||||
|
||||
func loadAPIData(cfg *config.Config, exch gctexchange.IBotExchange, fPair currency.Pair, a asset.Item, resultLimit uint32, dataType int64) (*kline.DataFromKline, error) {
|
||||
func loadAPIData(cfg *config.Config, exch gctexchange.IBotExchange, fPair currency.Pair, a asset.Item, resultLimit uint64, dataType int64) (*kline.DataFromKline, error) {
|
||||
if cfg.DataSettings.Interval <= 0 {
|
||||
return nil, errIntervalUnset
|
||||
}
|
||||
|
||||
@@ -31,39 +31,29 @@ func LoadStrategyByName(name string, useSimultaneousProcessing bool) (Handler, e
|
||||
|
||||
func createNewStrategy(name string, useSimultaneousProcessing bool, h Handler) (Handler, error) {
|
||||
if h == nil {
|
||||
return nil, fmt.Errorf("cannot load %v supported strategies contains %w", name, common.ErrNilPointer)
|
||||
return nil, fmt.Errorf("cannot load strategy %q: %w", name, common.ErrNilPointer)
|
||||
}
|
||||
|
||||
if !strings.EqualFold(name, h.Name()) {
|
||||
return nil, nil
|
||||
}
|
||||
// create new instance so strategy is not shared across all tasks
|
||||
|
||||
strategyValue := reflect.ValueOf(h)
|
||||
if strategyValue.IsNil() {
|
||||
return nil, fmt.Errorf("cannot load %v supported strategies element is a %w", name, common.ErrNilPointer)
|
||||
if strategyValue.Kind() != reflect.Ptr || strategyValue.IsNil() {
|
||||
return nil, fmt.Errorf("cannot load strategy %q: handler must be a non-nil pointer, got %T", name, h)
|
||||
}
|
||||
strategyElement := strategyValue.Elem()
|
||||
if !strategyElement.IsValid() {
|
||||
return nil, fmt.Errorf("cannot load %v strategy element is invalid %w", name, common.ErrTypeAssertFailure)
|
||||
}
|
||||
strategyType := strategyElement.Type()
|
||||
if strategyType == nil {
|
||||
return nil, fmt.Errorf("cannot load %v strategy type is a %w", name, common.ErrNilPointer)
|
||||
}
|
||||
newStrategy := reflect.New(strategyType)
|
||||
if newStrategy.IsNil() {
|
||||
return nil, fmt.Errorf("cannot load %v new instance of strategy is a %w", name, common.ErrNilPointer)
|
||||
}
|
||||
strategyInterface := newStrategy.Interface()
|
||||
if strategyInterface == nil {
|
||||
return nil, fmt.Errorf("cannot load %v new instance of strategy is not an interface. %w", name, common.ErrTypeAssertFailure)
|
||||
}
|
||||
strategy, ok := strategyInterface.(Handler)
|
||||
|
||||
// create new instance so strategy is not shared across all tasks
|
||||
strategy, ok := reflect.New(strategyValue.Elem().Type()).Interface().(Handler)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot load %v new instance of strategy is not a Handler interface. %w", name, common.ErrTypeAssertFailure)
|
||||
return nil, fmt.Errorf("cannot load strategy %q: type %T doesn't implement Handler interface: %w",
|
||||
name, strategy, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
if useSimultaneousProcessing && !strategy.SupportsSimultaneousProcessing() {
|
||||
return nil, base.ErrSimultaneousProcessingNotSupported
|
||||
}
|
||||
|
||||
strategy.SetSimultaneousProcessing(useSimultaneousProcessing)
|
||||
return strategy, nil
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/data"
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/portfolio"
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/base"
|
||||
@@ -82,35 +83,33 @@ func TestCreateNewStrategy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// invalid Handler
|
||||
resp, err := createNewStrategy(dollarcostaverage.Name, false, nil)
|
||||
if !errors.Is(err, common.ErrNilPointer) {
|
||||
t.Errorf("received '%v' expected '%v'", err, common.ErrNilPointer)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Errorf("received '%v' expected '%v'", resp, nil)
|
||||
}
|
||||
_, err := createNewStrategy(dollarcostaverage.Name, false, nil)
|
||||
assert.ErrorIs(t, err, common.ErrNilPointer)
|
||||
|
||||
// mismatched name
|
||||
resp, err = createNewStrategy(dollarcostaverage.Name, false, &customStrategy{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Errorf("received '%v' expected '%v'", resp, nil)
|
||||
}
|
||||
resp, err := createNewStrategy(dollarcostaverage.Name, false, &customStrategy{})
|
||||
assert.NoError(t, err, "createNewStrategy should not error")
|
||||
assert.Nil(t, resp)
|
||||
|
||||
// nil Handler
|
||||
var h Handler = (*customStrategy)(nil)
|
||||
_, err = createNewStrategy("custom-strategy", false, h)
|
||||
assert.ErrorContains(t, err, "must be a non-nil pointer")
|
||||
|
||||
// valid
|
||||
h := new(dollarcostaverage.Strategy)
|
||||
resp, err = createNewStrategy(dollarcostaverage.Name, false, h)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v' expected '%v'", err, nil)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Errorf("received '%v' expected '%v'", resp, h)
|
||||
}
|
||||
h = new(dollarcostaverage.Strategy)
|
||||
resp, err = createNewStrategy(dollarcostaverage.Name, true, h)
|
||||
assert.NoError(t, err, "createNewStrategy should not error")
|
||||
assert.NotSame(t, h, resp, "createNewStrategy should return a new pointer")
|
||||
|
||||
// simultaneous processing desired but not supported
|
||||
h = &customStrategy{allowSimultaneousProcessing: false}
|
||||
_, err = createNewStrategy("custom-strategy", true, h)
|
||||
assert.ErrorIs(t, err, base.ErrSimultaneousProcessingNotSupported)
|
||||
}
|
||||
|
||||
type customStrategy struct {
|
||||
allowSimultaneousProcessing bool
|
||||
base.Strategy
|
||||
}
|
||||
|
||||
@@ -121,7 +120,7 @@ func (s *customStrategy) Description() string {
|
||||
return "this is a demonstration of loading strategies via custom plugins"
|
||||
}
|
||||
func (s *customStrategy) SupportsSimultaneousProcessing() bool {
|
||||
return true
|
||||
return s.allowSimultaneousProcessing
|
||||
}
|
||||
func (s *customStrategy) OnSignal(d data.Handler, _ funding.IFundingTransferer, _ portfolio.Handler) (signal.Event, error) {
|
||||
return s.createSignal(d)
|
||||
|
||||
Reference in New Issue
Block a user