backtester: custom strategy plugins (#989)

* Adds custom strategy

* docs and structure

* docs

* rn

* Documents plugins, adds custom strat config

* mini fixes. Fleshes strategy test

* docgen

* Updates plugins to allow for multiple strategies to be loaded

* docs

* docs regen

* fix doc accuracy

* why did I add the word custom?
This commit is contained in:
Scott
2022-08-23 14:22:06 +10:00
committed by GitHub
parent ae02f168a9
commit 10f7ff3236
17 changed files with 829 additions and 86 deletions

View File

@@ -0,0 +1,71 @@
# GoCryptoTrader Backtester: Example 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/plugins/strategies/example)
[![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 example 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)
## Example package overview
This is a custom strategy for the GoCryptoTrader Backtester. It is a simple example of a strategy that trades a pair of assets and is used to highlight how strategies can be loaded from external sources.
### Designing a strategy
- File must contain `main` package.
- Custom strategy plugins must adhere to the strategy.Handler interface. See the [strategy.Handler interface documentation](./backtester/eventhandlers/strategies/README.md) for more information.
- Must contain function `func GetStrategies() []strategy.Handler` to return a slice of implemented `strategy.Handler`.
- If only using one custom strategy, can simply `return []strategy.Handler{&customStrategy{}}`.
### Building
See [here](./backtester/plugins/README.md) for details on how to build the plugin file.
### Running
Plugins can only be loaded via Linux, macOS and WSL. Windows itself is not supported.
To run this strategy you will need to use the following flags when running the GoCryptoTrader Backtester:
```bash
./backtester -strategypluginpath="path/to/strategy/example.so"
```
To run this specific example strategy, use:
```bash
./backtester --strategypluginpath="./plugins/strategies/example/example.so"
```
Upon startup, the GoCryptoTrader Backtester will load the strategy and run it for all events.
### 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***

View File

@@ -0,0 +1,89 @@
package main
import (
"github.com/thrasher-corp/gocryptotrader/backtester/data"
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/portfolio"
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies"
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/base"
"github.com/thrasher-corp/gocryptotrader/backtester/eventtypes/signal"
"github.com/thrasher-corp/gocryptotrader/backtester/funding"
gctorder "github.com/thrasher-corp/gocryptotrader/exchanges/order"
)
func main() {
// required for plugin system
}
// CustomStrategy the type used to define custom strategy functions
type CustomStrategy struct {
base.Strategy
}
// GetStrategies is required to load the strategy or strategies into the GoCryptoTrader Backtester
func GetStrategies() []strategies.Handler {
return []strategies.Handler{&CustomStrategy{}}
}
// Name returns the name of the strategy
func (s *CustomStrategy) Name() string {
return "custom-strategy"
}
// Description describes the strategy
func (s *CustomStrategy) Description() string {
return "this is a demonstration of loading strategies via custom plugins"
}
// SupportsSimultaneousProcessing this strategy only supports simultaneous signal processing
func (s *CustomStrategy) SupportsSimultaneousProcessing() bool {
return true
}
// OnSignal handles a data event and returns what action the strategy believes should occur
func (s *CustomStrategy) OnSignal(d data.Handler, _ funding.IFundingTransferer, _ portfolio.Handler) (signal.Event, error) {
return s.createSignal(d)
}
// OnSimultaneousSignals analyses multiple data points simultaneously, allowing flexibility
// in allowing a strategy to only place an order for X currency if Y currency's price is Z
func (s *CustomStrategy) OnSimultaneousSignals(d []data.Handler, f funding.IFundingTransferer, p portfolio.Handler) ([]signal.Event, error) {
response := make([]signal.Event, len(d))
for i := range d {
sig, err := s.createSignal(d[i])
if err != nil {
return nil, err
}
response[i] = sig
}
return response, nil
}
func (s *CustomStrategy) createSignal(d data.Handler) (*signal.Signal, error) {
es, err := s.GetBaseData(d)
if err != nil {
return nil, err
}
sig := &signal.Signal{
Base: es.Base,
OpenPrice: es.OpenPrice,
HighPrice: es.HighPrice,
LowPrice: es.LowPrice,
ClosePrice: es.ClosePrice,
Volume: es.Volume,
BuyLimit: es.BuyLimit,
SellLimit: es.SellLimit,
Amount: es.Amount,
Direction: gctorder.Buy,
}
sig.AppendReasonf("Signalling purchase of %s", es.Base.Pair())
return sig, nil
}
// SetCustomSettings can override default settings
func (s *CustomStrategy) SetCustomSettings(map[string]interface{}) error {
return base.ErrCustomSettingsUnsupported
}
// SetDefaults sets default values for overridable custom settings
func (s *CustomStrategy) SetDefaults() {}