forked from thrasher-corp/gocryptotrader
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
backtester: standalone application (thrasher-corp#988)
* Ramshackle early leads to GRPC backtester * Adds GRPC server, default config generation * Partial support for GRPC backtester config * Update to use Buf, merge fixes * Full config for GRPC * Adds new commands, causes big panic * Fixes panics * Setup for the future * Docs update * test * grpc tests * Fix merge issues. Lint and test * minor fixes after rebase * Docs, formatting and main fixes * Change buf owner * shazNits * test-123 * rpc fixes * string fixes * Removes --singlerun flag and just relies on --singlerunstrategypath * fixes test * initial post merge compatability fixes * this actually all seems to work? unexpected * adds pluginpath to config * rm unused func. add gitignore * rm unused func. add gitignore * lintle * tITLE cASE lOG fIX,rm auth package, gitignore, tmpdir fix * buf updates + gen. go mod tidy * x2 * Update default port, update error text
- Loading branch information
1 parent
8a68a1d
commit 1461cba
Showing
76 changed files
with
7,930 additions
and
2,191 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# GoCryptoTrader Backtester: Btcli package | ||
|
||
<img src="/backtester/common/backtester.png?raw=true" width="350px" height="350px" hspace="70"> | ||
|
||
|
||
[![Build Status](https://github.com/thrasher-corp/gocryptotrader/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/thrasher-corp/gocryptotrader/actions/workflows/tests.yml) | ||
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE) | ||
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/backtester/btcli) | ||
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader) | ||
|
||
|
||
This btcli package is part of the GoCryptoTrader codebase. | ||
|
||
## This is still in active development | ||
|
||
You can track ideas, planned features and what's in progress on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader). | ||
|
||
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://join.slack.com/t/gocryptotrader/shared_invite/enQtNTQ5NDAxMjA2Mjc5LTc5ZDE1ZTNiOGM3ZGMyMmY1NTAxYWZhODE0MWM5N2JlZDk1NDU0YTViYzk4NTk3OTRiMDQzNGQ1YTc4YmRlMTk) | ||
|
||
## Btcli overview | ||
|
||
This folder contains the GoCryptoTrader Backtester CMD CLI application. It can be used to interact | ||
with the GoCryptoTrader Backtester's GRPC server and send commands to be processed server-side. | ||
|
||
For a list of commands, you can run the following | ||
|
||
``` | ||
go run . | ||
``` | ||
|
||
### Please click GoDocs chevron above to view current GoDoc information for this package | ||
|
||
## Contribution | ||
|
||
Please feel free to submit any pull requests or suggest any desired features to be added. | ||
|
||
When submitting a PR, please abide by our coding guidelines: | ||
|
||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). | ||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines. | ||
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md). | ||
+ Pull requests need to be based on and opened against the `master` branch. | ||
|
||
## Donations | ||
|
||
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70"> | ||
|
||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to: | ||
|
||
***bc1qk0jareu4jytc0cfrhr5wgshsq8282awpavfahc*** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"path/filepath" | ||
|
||
"github.com/thrasher-corp/gocryptotrader/backtester/btrpc" | ||
"github.com/thrasher-corp/gocryptotrader/backtester/config" | ||
"github.com/urfave/cli/v2" | ||
"google.golang.org/protobuf/types/known/timestamppb" | ||
) | ||
|
||
var executeStrategyFromFileCommand = &cli.Command{ | ||
Name: "executestrategyfromfile", | ||
Usage: "runs the strategy from a config file", | ||
ArgsUsage: "<path>", | ||
Action: executeStrategyFromFile, | ||
Flags: []cli.Flag{ | ||
&cli.StringFlag{ | ||
Name: "path", | ||
Aliases: []string{"p"}, | ||
Usage: "the filepath to a strategy to execute", | ||
}, | ||
}, | ||
} | ||
|
||
func executeStrategyFromFile(c *cli.Context) error { | ||
conn, cancel, err := setupClient(c) | ||
if err != nil { | ||
return err | ||
} | ||
defer closeConn(conn, cancel) | ||
|
||
if c.NArg() == 0 && c.NumFlags() == 0 { | ||
return cli.ShowCommandHelp(c, "executestrategyfromfile") | ||
} | ||
|
||
var path string | ||
if c.IsSet("path") { | ||
path = c.String("path") | ||
} else { | ||
path = c.Args().First() | ||
} | ||
|
||
client := btrpc.NewBacktesterServiceClient(conn) | ||
result, err := client.ExecuteStrategyFromFile( | ||
c.Context, | ||
&btrpc.ExecuteStrategyFromFileRequest{ | ||
StrategyFilePath: path, | ||
}, | ||
) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
jsonOutput(result) | ||
return nil | ||
} | ||
|
||
var executeStrategyFromConfigCommand = &cli.Command{ | ||
Name: "executestrategyfromconfig", | ||
Usage: "runs the default strategy config but via passing in as a struct instead of a filepath - this is a proof-of-concept implementation", | ||
Description: "the cli is not a good place to manage this type of command with n variables to pass in from a command line", | ||
Action: executeStrategyFromConfig, | ||
} | ||
|
||
// executeStrategyFromConfig this is a proof of concept command | ||
// it demonstrates that a user can send complex strategies via GRPC | ||
// and have them execute. The ultimate goal is to allow a user to continuously | ||
// tweak values and send them via GRPC and determine the best returns then test them across | ||
// large ranges of data to avoid over fitting | ||
func executeStrategyFromConfig(c *cli.Context) error { | ||
conn, cancel, err := setupClient(c) | ||
if err != nil { | ||
return err | ||
} | ||
defer closeConn(conn, cancel) | ||
defaultPath := filepath.Join( | ||
"..", | ||
"config", | ||
"strategyexamples", | ||
"ftx-cash-carry.strat") | ||
defaultConfig, err := config.ReadStrategyConfigFromFile(defaultPath) | ||
if err != nil { | ||
return err | ||
} | ||
customSettings := make([]*btrpc.CustomSettings, len(defaultConfig.StrategySettings.CustomSettings)) | ||
x := 0 | ||
for k, v := range defaultConfig.StrategySettings.CustomSettings { | ||
customSettings[x] = &btrpc.CustomSettings{ | ||
KeyField: k, | ||
KeyValue: fmt.Sprintf("%v", v), | ||
} | ||
x++ | ||
} | ||
|
||
currencySettings := make([]*btrpc.CurrencySettings, len(defaultConfig.CurrencySettings)) | ||
for i := range defaultConfig.CurrencySettings { | ||
var sd *btrpc.SpotDetails | ||
if defaultConfig.CurrencySettings[i].SpotDetails != nil { | ||
sd.InitialBaseFunds = defaultConfig.CurrencySettings[i].SpotDetails.InitialBaseFunds.String() | ||
sd.InitialQuoteFunds = defaultConfig.CurrencySettings[i].SpotDetails.InitialQuoteFunds.String() | ||
} | ||
var fd *btrpc.FuturesDetails | ||
if defaultConfig.CurrencySettings[i].FuturesDetails != nil { | ||
fd.Leverage = &btrpc.Leverage{ | ||
CanUseLeverage: defaultConfig.CurrencySettings[i].FuturesDetails.Leverage.CanUseLeverage, | ||
MaximumOrdersWithLeverageRatio: defaultConfig.CurrencySettings[i].FuturesDetails.Leverage.MaximumOrdersWithLeverageRatio.String(), | ||
MaximumLeverageRate: defaultConfig.CurrencySettings[i].FuturesDetails.Leverage.MaximumOrderLeverageRate.String(), | ||
MaximumCollateralLeverageRate: defaultConfig.CurrencySettings[i].FuturesDetails.Leverage.MaximumCollateralLeverageRate.String(), | ||
} | ||
} | ||
currencySettings[i] = &btrpc.CurrencySettings{ | ||
ExchangeName: defaultConfig.CurrencySettings[i].ExchangeName, | ||
Asset: defaultConfig.CurrencySettings[i].Asset.String(), | ||
Base: defaultConfig.CurrencySettings[i].Base.String(), | ||
Quote: defaultConfig.CurrencySettings[i].Quote.String(), | ||
BuySide: &btrpc.PurchaseSide{ | ||
MinimumSize: defaultConfig.CurrencySettings[i].BuySide.MinimumSize.String(), | ||
MaximumSize: defaultConfig.CurrencySettings[i].BuySide.MaximumSize.String(), | ||
MaximumTotal: defaultConfig.CurrencySettings[i].BuySide.MaximumTotal.String(), | ||
}, | ||
SellSide: &btrpc.PurchaseSide{ | ||
MinimumSize: defaultConfig.CurrencySettings[i].SellSide.MinimumSize.String(), | ||
MaximumSize: defaultConfig.CurrencySettings[i].SellSide.MaximumSize.String(), | ||
MaximumTotal: defaultConfig.CurrencySettings[i].SellSide.MaximumTotal.String(), | ||
}, | ||
MinSlippagePercent: defaultConfig.CurrencySettings[i].MinimumSlippagePercent.String(), | ||
MaxSlippagePercent: defaultConfig.CurrencySettings[i].MaximumSlippagePercent.String(), | ||
MakerFeeOverride: defaultConfig.CurrencySettings[i].MakerFee.String(), | ||
TakerFeeOverride: defaultConfig.CurrencySettings[i].TakerFee.String(), | ||
MaximumHoldingsRatio: defaultConfig.CurrencySettings[i].MaximumHoldingsRatio.String(), | ||
SkipCandleVolumeFitting: defaultConfig.CurrencySettings[i].SkipCandleVolumeFitting, | ||
UseExchangeOrderLimits: defaultConfig.CurrencySettings[i].CanUseExchangeLimits, | ||
UseExchangePnlCalculation: defaultConfig.CurrencySettings[i].UseExchangePNLCalculation, | ||
SpotDetails: sd, | ||
FuturesDetails: fd, | ||
} | ||
} | ||
|
||
exchangeLevelFunding := make([]*btrpc.ExchangeLevelFunding, len(defaultConfig.FundingSettings.ExchangeLevelFunding)) | ||
for i := range defaultConfig.FundingSettings.ExchangeLevelFunding { | ||
exchangeLevelFunding[i] = &btrpc.ExchangeLevelFunding{ | ||
ExchangeName: defaultConfig.FundingSettings.ExchangeLevelFunding[i].ExchangeName, | ||
Asset: defaultConfig.FundingSettings.ExchangeLevelFunding[i].Asset.String(), | ||
Currency: defaultConfig.FundingSettings.ExchangeLevelFunding[i].Currency.String(), | ||
InitialFunds: defaultConfig.FundingSettings.ExchangeLevelFunding[i].InitialFunds.String(), | ||
TransferFee: defaultConfig.FundingSettings.ExchangeLevelFunding[i].TransferFee.String(), | ||
} | ||
} | ||
|
||
dataSettings := &btrpc.DataSettings{ | ||
Interval: uint64(defaultConfig.DataSettings.Interval.Duration().Nanoseconds()), | ||
Datatype: defaultConfig.DataSettings.DataType, | ||
} | ||
if defaultConfig.DataSettings.APIData != nil { | ||
dataSettings.ApiData = &btrpc.ApiData{ | ||
StartDate: timestamppb.New(defaultConfig.DataSettings.APIData.StartDate), | ||
EndDate: timestamppb.New(defaultConfig.DataSettings.APIData.EndDate), | ||
InclusiveEndDate: defaultConfig.DataSettings.APIData.InclusiveEndDate, | ||
} | ||
} | ||
if defaultConfig.DataSettings.LiveData != nil { | ||
dataSettings.LiveData = &btrpc.LiveData{ | ||
ApiKeyOverride: defaultConfig.DataSettings.LiveData.APIKeyOverride, | ||
ApiSecretOverride: defaultConfig.DataSettings.LiveData.APISecretOverride, | ||
ApiClientIdOverride: defaultConfig.DataSettings.LiveData.APIClientIDOverride, | ||
Api_2FaOverride: defaultConfig.DataSettings.LiveData.API2FAOverride, | ||
ApiSubAccountOverride: defaultConfig.DataSettings.LiveData.APISubAccountOverride, | ||
UseRealOrders: defaultConfig.DataSettings.LiveData.RealOrders, | ||
} | ||
} | ||
if defaultConfig.DataSettings.CSVData != nil { | ||
dataSettings.CsvData = &btrpc.CSVData{ | ||
Path: defaultConfig.DataSettings.CSVData.FullPath, | ||
} | ||
} | ||
if defaultConfig.DataSettings.DatabaseData != nil { | ||
dbConnectionDetails := &btrpc.DatabaseConnectionDetails{ | ||
Host: defaultConfig.DataSettings.DatabaseData.Config.Host, | ||
Port: uint32(defaultConfig.DataSettings.DatabaseData.Config.Port), | ||
Password: defaultConfig.DataSettings.DatabaseData.Config.Password, | ||
Database: defaultConfig.DataSettings.DatabaseData.Config.Database, | ||
SslMode: defaultConfig.DataSettings.DatabaseData.Config.SSLMode, | ||
UserName: defaultConfig.DataSettings.DatabaseData.Config.Username, | ||
} | ||
dbConfig := &btrpc.DatabaseConfig{ | ||
Config: dbConnectionDetails, | ||
} | ||
dataSettings.DatabaseData = &btrpc.DatabaseData{ | ||
StartDate: timestamppb.New(defaultConfig.DataSettings.DatabaseData.StartDate), | ||
EndDate: timestamppb.New(defaultConfig.DataSettings.DatabaseData.EndDate), | ||
Config: dbConfig, | ||
Path: defaultConfig.DataSettings.DatabaseData.Path, | ||
InclusiveEndDate: defaultConfig.DataSettings.DatabaseData.InclusiveEndDate, | ||
} | ||
} | ||
|
||
cfg := &btrpc.Config{ | ||
Nickname: defaultConfig.Nickname, | ||
Goal: defaultConfig.Goal, | ||
StrategySettings: &btrpc.StrategySettings{ | ||
Name: defaultConfig.StrategySettings.Name, | ||
UseSimultaneousSignalProcessing: defaultConfig.StrategySettings.SimultaneousSignalProcessing, | ||
DisableUsdTracking: defaultConfig.StrategySettings.DisableUSDTracking, | ||
CustomSettings: customSettings, | ||
}, | ||
FundingSettings: &btrpc.FundingSettings{ | ||
UseExchangeLevelFunding: defaultConfig.FundingSettings.UseExchangeLevelFunding, | ||
ExchangeLevelFunding: exchangeLevelFunding, | ||
}, | ||
CurrencySettings: currencySettings, | ||
DataSettings: dataSettings, | ||
PortfolioSettings: &btrpc.PortfolioSettings{ | ||
Leverage: &btrpc.Leverage{ | ||
CanUseLeverage: defaultConfig.PortfolioSettings.Leverage.CanUseLeverage, | ||
MaximumOrdersWithLeverageRatio: defaultConfig.PortfolioSettings.Leverage.MaximumOrdersWithLeverageRatio.String(), | ||
MaximumLeverageRate: defaultConfig.PortfolioSettings.Leverage.MaximumOrderLeverageRate.String(), | ||
MaximumCollateralLeverageRate: defaultConfig.PortfolioSettings.Leverage.MaximumCollateralLeverageRate.String(), | ||
}, | ||
BuySide: &btrpc.PurchaseSide{ | ||
MinimumSize: defaultConfig.PortfolioSettings.BuySide.MinimumSize.String(), | ||
MaximumSize: defaultConfig.PortfolioSettings.BuySide.MaximumSize.String(), | ||
MaximumTotal: defaultConfig.PortfolioSettings.BuySide.MaximumTotal.String(), | ||
}, | ||
SellSide: &btrpc.PurchaseSide{ | ||
MinimumSize: defaultConfig.PortfolioSettings.SellSide.MinimumSize.String(), | ||
MaximumSize: defaultConfig.PortfolioSettings.SellSide.MaximumSize.String(), | ||
MaximumTotal: defaultConfig.PortfolioSettings.SellSide.MaximumTotal.String(), | ||
}, | ||
}, | ||
StatisticSettings: &btrpc.StatisticSettings{ | ||
RiskFreeRate: defaultConfig.StatisticSettings.RiskFreeRate.String(), | ||
}, | ||
} | ||
|
||
client := btrpc.NewBacktesterServiceClient(conn) | ||
result, err := client.ExecuteStrategyFromConfig( | ||
c.Context, | ||
&btrpc.ExecuteStrategyFromConfigRequest{ | ||
Config: cfg, | ||
}, | ||
) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
jsonOutput(result) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"google.golang.org/grpc" | ||
) | ||
|
||
func closeConn(conn *grpc.ClientConn, cancel context.CancelFunc) { | ||
if err := conn.Close(); err != nil { | ||
fmt.Println(err) | ||
} | ||
if cancel != nil { | ||
cancel() | ||
} | ||
} |
Oops, something went wrong.