Skip to content

Commit

Permalink
feat(backtesting): include OCO/Limit order support (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigo-brito authored Jun 4, 2021
1 parent 9b7c13e commit 6b4b9b8
Show file tree
Hide file tree
Showing 27 changed files with 1,004 additions and 329 deletions.
1 change: 1 addition & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ archives:
windows: Windows
386: i386
amd64: x86_64
format: zip

checksum:
name_template: 'checksums.txt'
Expand Down
9 changes: 4 additions & 5 deletions example/backtesting/main.go → examples/backtesting/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ package main
import (
"context"

"github.com/rodrigo-brito/ninjabot/pkg/plot"

"github.com/rodrigo-brito/ninjabot"
"github.com/rodrigo-brito/ninjabot/example"
"github.com/rodrigo-brito/ninjabot/examples/strategies"
"github.com/rodrigo-brito/ninjabot/pkg/exchange"
"github.com/rodrigo-brito/ninjabot/pkg/model"
"github.com/rodrigo-brito/ninjabot/pkg/plot"
"github.com/rodrigo-brito/ninjabot/pkg/storage"

log "github.com/sirupsen/logrus"
Expand All @@ -24,7 +23,7 @@ func main() {
},
}

strategy := new(example.MyStrategy)
strategy := new(strategies.CrossEMA)

csvFeed, err := exchange.NewCSVFeed(
strategy.Timeframe(),
Expand Down Expand Up @@ -66,7 +65,7 @@ func main() {
ninjabot.WithCandleSubscription(wallet),
ninjabot.WithCandleSubscription(chart),
ninjabot.WithOrderSubscription(chart),
ninjabot.WithLogLevel(log.ErrorLevel),
ninjabot.WithLogLevel(log.InfoLevel),
)
if err != nil {
log.Fatal(err)
Expand Down
5 changes: 2 additions & 3 deletions example/binance/main.go → examples/binance/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import (
"log"
"os"

"github.com/rodrigo-brito/ninjabot/example"

"github.com/rodrigo-brito/ninjabot"
"github.com/rodrigo-brito/ninjabot/examples/strategies"
"github.com/rodrigo-brito/ninjabot/pkg/exchange"
"github.com/rodrigo-brito/ninjabot/pkg/model"
"github.com/rodrigo-brito/ninjabot/pkg/notification"
Expand Down Expand Up @@ -39,7 +38,7 @@ func main() {
// (Optional) Telegram notifier
notifier := notification.NewTelegram(telegramID, telegramKey, telegramChannel)

strategy := &example.MyStrategy{}
strategy := &strategies.CrossEMA{}
bot, err := ninjabot.NewBot(ctx, settings, binance, strategy)
if err != nil {
log.Fatalln(err)
Expand Down
4 changes: 2 additions & 2 deletions example/paperwallet/main.go → examples/paperwallet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"os"

"github.com/rodrigo-brito/ninjabot"
"github.com/rodrigo-brito/ninjabot/example"
"github.com/rodrigo-brito/ninjabot/examples/strategies"
"github.com/rodrigo-brito/ninjabot/pkg/exchange"
"github.com/rodrigo-brito/ninjabot/pkg/model"
"github.com/rodrigo-brito/ninjabot/pkg/notification"
Expand Down Expand Up @@ -51,7 +51,7 @@ func main() {
exchange.WithDataFeed(binance),
)

strategy := new(example.MyStrategy)
strategy := new(strategies.CrossEMA)
bot, err := ninjabot.NewBot(
ctx,
settings,
Expand Down
14 changes: 7 additions & 7 deletions example/strategy.go → examples/strategies/emacross.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package example
package strategies

import (
"github.com/rodrigo-brito/ninjabot/pkg/exchange"
Expand All @@ -8,23 +8,23 @@ import (
log "github.com/sirupsen/logrus"
)

type MyStrategy struct{}
type CrossEMA struct{}

func (e MyStrategy) Init(settings model.Settings) {}
func (e CrossEMA) Init(settings model.Settings) {}

func (e MyStrategy) Timeframe() string {
func (e CrossEMA) Timeframe() string {
return "1d"
}

func (e MyStrategy) WarmupPeriod() int {
func (e CrossEMA) WarmupPeriod() int {
return 9
}

func (e MyStrategy) Indicators(df *model.Dataframe) {
func (e CrossEMA) Indicators(df *model.Dataframe) {
df.Metadata["ema9"] = talib.Ema(df.Close, 9)
}

func (e *MyStrategy) OnCandle(df *model.Dataframe, broker exchange.Broker) {
func (e *CrossEMA) OnCandle(df *model.Dataframe, broker exchange.Broker) {
closePrice := df.Close.Last(0)
log.Info("New Candle = ", df.Pair, df.LastUpdate, closePrice)

Expand Down
72 changes: 72 additions & 0 deletions examples/strategies/ocosell.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package strategies

import (
"github.com/rodrigo-brito/ninjabot/pkg/exchange"
"github.com/rodrigo-brito/ninjabot/pkg/model"

"github.com/markcheno/go-talib"
log "github.com/sirupsen/logrus"
)

type OCOSell struct{}

func (e OCOSell) Init(settings model.Settings) {}

func (e OCOSell) Timeframe() string {
return "1d"
}

func (e OCOSell) WarmupPeriod() int {
return 9
}

func (e OCOSell) Indicators(df *model.Dataframe) {
df.Metadata["stoch"], df.Metadata["stoch_signal"] = talib.Stoch(
df.High,
df.Low,
df.Close,
8,
3,
talib.SMA,
3,
talib.SMA,
)
}

func (e *OCOSell) OnCandle(df *model.Dataframe, broker exchange.Broker) {
closePrice := df.Close.Last(0)
log.Info("New Candle = ", df.Pair, df.LastUpdate, closePrice)

assetPosition, quotePosition, err := broker.Position(df.Pair)
if err != nil {
log.Error(err)
}

buyAmount := 4000.0
if quotePosition > buyAmount && df.Metadata["stoch"].Crossover(df.Metadata["stoch_signal"]) {
size := buyAmount / closePrice
_, err := broker.OrderMarket(model.SideTypeBuy, df.Pair, size)
if err != nil {
log.WithFields(map[string]interface{}{
"pair": df.Pair,
"side": model.SideTypeBuy,
"close": closePrice,
"asset": assetPosition,
"quote": quotePosition,
"size": size,
}).Error(err)
}

_, err = broker.OrderOCO(model.SideTypeSell, df.Pair, size, closePrice*1.05, closePrice*0.95, closePrice*0.95)
if err != nil {
log.WithFields(map[string]interface{}{
"pair": df.Pair,
"side": model.SideTypeBuy,
"close": closePrice,
"asset": assetPosition,
"quote": quotePosition,
"size": size,
}).Error(err)
}
}
}
1 change: 1 addition & 0 deletions ninjabot.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ func (n *NinjaBot) Run(ctx context.Context) error {

n.orderFeed.Start()
n.orderController.Start()
defer n.orderController.Stop()
n.dataFeed.Start()
return nil
}
3 changes: 2 additions & 1 deletion pkg/ent/migrate/schema.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 81 additions & 27 deletions pkg/ent/mutation.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6b4b9b8

Please sign in to comment.