https://github.com/grinply/kate-backtester
A fast and simple backtest implementation for algorithmic trading in golang
https://github.com/grinply/kate-backtester
algorithmic-trading backtesting-engine backtesting-frameworks backtesting-trading-strategies backtests crypto-trading cryptocurrency finance financial-analysis forex forex-trading go golang investing trading-simulation trading-strategies
Last synced: 3 months ago
JSON representation
A fast and simple backtest implementation for algorithmic trading in golang
- Host: GitHub
- URL: https://github.com/grinply/kate-backtester
- Owner: grinply
- License: mit
- Created: 2021-04-06T20:47:38.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2021-08-19T21:35:16.000Z (almost 5 years ago)
- Last Synced: 2024-06-20T12:46:54.729Z (almost 2 years ago)
- Topics: algorithmic-trading, backtesting-engine, backtesting-frameworks, backtesting-trading-strategies, backtests, crypto-trading, cryptocurrency, finance, financial-analysis, forex, forex-trading, go, golang, investing, trading-simulation, trading-strategies
- Language: Go
- Homepage:
- Size: 3.12 MB
- Stars: 16
- Watchers: 1
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://goreportcard.com/report/github.com/victorl2/kate-backtester)
[](https://sonarcloud.io/dashboard?id=victorl2_quick-backtest)
[](/LICENSE.md)
[](https://pkg.go.dev/github.com/victorl2/kate-backtester)
# Kate Backtester
A fast and simple backtest implementation for **algorithmic trading** focused on [cryptocurrencies](https://en.wikipedia.org/wiki/Cryptocurrency#:~:text=A%20cryptocurrency%2C%20crypto%20currency%20or,creation%20of%20additional%20coins%2C%20and) written in [GoLang](https://golang.org/).
## Data
The price data used to run the backtests can be from any time interval, but it must contain a [**OHLCV**](https://en.wikipedia.org/wiki/Open-high-low-close_chart) structure _(**O**pen **H**igh **L**ow **C**lose **V**olume)_. It is possible to load data from **csv** files with the following format:
| open | high | low | close | volume
|:---------:|:---------:|:---------:|:---------:|:----------
| 7922.0700 | 7924.9900 | 7920.1600 | 7924.7500 | 9.90606700
| 7923.4300 | 7929.1400 | 7920.8000 | 7922.9000 | 15.83760800
| 7923.1300 | 7934.0900 | 7922.9000 | 7932.2600 | 9.98577900
## Usage
To start using **kate backtester** you will need to implement the [**Strategy interface**](https://github.com/victorl2/kate-backtester/blob/main/pkg/strategy.go) and provide a **csv** a dataset for execution. The Strategy interface contains 4 functions that describe how/when to trade: **PreProcessIndicators**, **OpenNewPosition**, **SetStoploss** and **SetTakeProfit**.
### PreProcessIndicators
Allows the strategy to pre calculate the indicators and values for reuse in the other functions, making the execution faster and less redundant. This pre processing step is the **first** function called with every new price data avaliable.
### OpenNewPosition
This function is responsible for opening new trade positions when there are none open already, the function is called with every new price data to check, a nil return denotes that no positions should be open yet. When opening a position a OpenPositionEvt is returned containing the **Direction** for the trade _(LONG/SHORT)_ and the desired [leverage](https://blog.earn2trade.com/leverage-trading/), a possible return would be `return &kate.OpenPositionEvt{Direction: kate.LONG, Leverage: 30}`
### SetStoploss
As the name already implies this function is responsible for setting the stoploss price for the **already open position**, the function is called when new price data is avaliable and a position is open. This function makes possible changing the **stoploss** dynamically as the position evolves, the updated PNL is avaliable for checking. A nil return denotes that no changes should be made, a example return would be `return &kate.StoplossEvt{Price: openPosition.EntryPrice * 0.995}`
### SetTakeProfit
This function has the same behavior as **SetStoploss** but instead it manipulates the take profit price. A example return would be `return &kate.TakeProfitEvt{Price: openPosition.EntryPrice * 1.005}`
A [basic implementation](https://github.com/victorl2/kate-backtester/blob/main/examples/basic/main.go) where a strategy opens a long position every time the latest [close price](https://www.dailyfx.com/education/candlestick-patterns/how-to-read-candlestick-charts.html#:~:text=Close%20Price%3A,depends%20on%20the%20chart%20settings) is higher than the last close is:
```go
package main
import (
"fmt"
"github.com/victorl2/kate-backtester/kate"
)
type SimpleStrategy struct{
lastPrice *kate.DataPoint
currentPrice *kate.DataPoint
}
func main() {
data, err := kate.PricesFromCSV("../../testdata/ETHUSD5.csv")
if err != nil {
panic("could`t load data." + err.Error())
}
kate.NewBacktester(&SimpleStrategy{}, data)
backtester := kate.NewBacktester(&SimpleStrategy{}, data)
fmt.Println(backtester.Run())
}
//PreProcessIndicators allows the pre processing of indicators
func (stg *SimpleStrategy) PreProcessIndicators(latestPrice kate.DataPoint) {
stg.lastPrice = strategy.currentPrice
stg.currentPrice = &latestPrice
}
//OpenNewPosition process the next data point and checks if a position should be opened
func (stg *SimpleStrategy) OpenNewPosition(latestPrice kate.DataPoint) *kate.OpenPositionEvt {
if stg.lastPrice != nil && stg.currentPrice.Close() > stg.lastPrice.Close() {
return &kate.OpenPositionEvt{Direction: kate.LONG, Leverage: 30}
}
return nil
}
//SetStoploss defines a stoploss for the current open position
func (stg *SimpleStrategy) SetStoploss(openPosition kate.Position) *kate.StoplossEvt {
if openPosition.Direction == kate.LONG && openPosition.Stoploss <= 0 {
return &kate.StoplossEvt{Price: openPosition.EntryPrice * 0.995}
}
return nil
}
//SetTakeProfit defines a takeprofit for the current open position
func (stg *SimpleStrategy) SetTakeProfit(openPosition kate.Position) *kate.TakeProfitEvt {
if openPosition.Direction == kate.LONG && openPosition.TakeProfit <= 0 {
return &kate.TakeProfitEvt{Price: openPosition.EntryPrice * 1.005}
}
return nil
}
```