Skip to content

Commit

Permalink
Merge pull request c9s#890 from zenixls2/feature/wdrift
Browse files Browse the repository at this point in the history
weighted drift
  • Loading branch information
zenixls2 authored Aug 24, 2022
2 parents 0509f61 + 6b6a24a commit 3a98ae0
Show file tree
Hide file tree
Showing 12 changed files with 432 additions and 68 deletions.
26 changes: 15 additions & 11 deletions config/drift.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,32 @@ exchangeStrategies:
# kline interval for indicators
interval: 15m
window: 2
stoploss: 0.3%
stoploss: 4.3%
source: close
predictOffset: 2
noTrailingStopLoss: false
noTrailingStopLoss: true
trailingStopLossType: kline
# stddev on high/low-source
hlVarianceMultiplier: 0.23
hlVarianceMultiplier: 0.1
hlRangeWindow: 5
window1m: 24
smootherWindow1m: 24
fisherTransformWindow1m: 162
smootherWindow: 1
fisherTransformWindow: 9
window1m: 49
smootherWindow1m: 80
fisherTransformWindow1m: 74
smootherWindow: 3
fisherTransformWindow: 160
atrWindow: 14
# orders not been traded will be canceled after `pendingMinutes` minutes
pendingMinutes: 3
pendingMinutes: 10
noRebalance: true
trendWindow: 12
rebalanceFilter: 1.5

trailingActivationRatio: [0.004]
trailingCallbackRate: [0.001]
trailingActivationRatio: [0.003]
trailingCallbackRate: [0.0006]
driftFilterPos: 1.2
driftFilterNeg: -1.2
ddriftFilterPos: 0.4
ddriftFilterNeg: -0.4

generateGraph: true
graphPNLDeductFee: true
Expand Down
40 changes: 23 additions & 17 deletions config/driftBTC.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,45 +27,51 @@ exchangeStrategies:
symbol: BTCUSDT
# kline interval for indicators
interval: 15m
window: 2
stoploss: 0.2%
window: 1
stoploss: 1.2%
source: close
predictOffset: 2
noTrailingStopLoss: false
trailingStopLossType: kline
# stddev on high/low-source
hlVarianceMultiplier: 0.22
hlVarianceMultiplier: 0.1
hlRangeWindow: 5
smootherWindow: 1
fisherTransformWindow: 9
window1m: 22
smootherWindow1m: 18
fisherTransformWindow1m: 162
fisherTransformWindow: 34
window1m: 58
smootherWindow1m: 118
fisherTransformWindow1m: 319
atrWindow: 14
# orders not been traded will be canceled after `pendingMinutes` minutes
pendingMinutes: 5
pendingMinutes: 10
noRebalance: true
trendWindow: 576
rebalanceFilter: 0
driftFilterPos: 1.8
driftFilterNeg: -1.8
ddriftFilterPos: 0.5
ddriftFilterNeg: -0.5 #-1.6

# ActivationRatio should be increasing order
# when farest price from entry goes over that ratio, start using the callback ratio accordingly to do trailingstop
#trailingActivationRatio: [0.01, 0.016, 0.05]
trailingActivationRatio: [0.0012, 0.002, 0.01, 0.016]
#trailingActivationRatio: [0.001, 0.0081, 0.022]
trailingActivationRatio: [0.0029, 0.028]
#trailingActivationRatio: []
#trailingCallbackRate: []
#trailingCallbackRate: [0.002, 0.01, 0.1]
trailingCallbackRate: [0.0004, 0.0008, 0.002, 0.01]
#trailingCallbackRate: [0.0004, 0.0009, 0.018]
trailingCallbackRate: [0.0005, 0.0149]

generateGraph: true
graphPNLDeductFee: false
graphPNLPath: "./pnl.png"
graphCumPNLPath: "./cumpnl.png"
#exits:
#- roiStopLoss:
# percentage: 0.35%
# - roiStopLoss:
# percentage: 0.35%
#- roiTakeProfit:
#percentage: 0.7%
# percentage: 0.7%
#- protectiveStopLoss:
# activationRatio: 0.5%
# stopLossRatio: 0.2%
Expand Down Expand Up @@ -118,8 +124,8 @@ sync:
- BTCUSDT

backtest:
startTime: "2022-01-01"
endTime: "2022-08-30"
startTime: "2022-08-01"
endTime: "2022-08-31"
symbols:
- BTCUSDT
sessions: [binance]
Expand All @@ -128,5 +134,5 @@ backtest:
makerFeeRate: 0.000
#takerFeeRate: 0.000
balances:
BTC: 1
USDT: 5000
BTC: 0
USDT: 21
8 changes: 4 additions & 4 deletions pkg/backtest/matching.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty

switch o.Type {
case types.OrderTypeMarket:
price = m.LastPrice
price = m.Market.TruncatePrice(m.LastPrice)

case types.OrderTypeStopMarket:
// the actual price might be different.
Expand Down Expand Up @@ -181,9 +181,9 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty

if isTaker {
if order.Type == types.OrderTypeMarket {
order.Price = m.LastPrice
order.Price = m.Market.TruncatePrice(m.LastPrice)
} else if order.Type == types.OrderTypeLimit {
order.AveragePrice = m.LastPrice
order.AveragePrice = m.Market.TruncatePrice(m.LastPrice)
}

// emit the order update for Status:New
Expand All @@ -193,7 +193,7 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty
var order2 = order

// emit trade before we publish order
trade := m.newTradeFromOrder(&order2, false, m.LastPrice)
trade := m.newTradeFromOrder(&order2, false, m.Market.TruncatePrice(m.LastPrice))
m.executeTrade(trade)

// unlock the rest balances for limit taker
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/strategy/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
_ "github.com/c9s/bbgo/pkg/strategy/bollgrid"
_ "github.com/c9s/bbgo/pkg/strategy/bollmaker"
_ "github.com/c9s/bbgo/pkg/strategy/dca"
_ "github.com/c9s/bbgo/pkg/strategy/drift"
_ "github.com/c9s/bbgo/pkg/strategy/emastop"
_ "github.com/c9s/bbgo/pkg/strategy/etf"
_ "github.com/c9s/bbgo/pkg/strategy/ewoDgtrd"
Expand Down Expand Up @@ -33,5 +34,4 @@ import (
_ "github.com/c9s/bbgo/pkg/strategy/xmaker"
_ "github.com/c9s/bbgo/pkg/strategy/xnav"
_ "github.com/c9s/bbgo/pkg/strategy/xpuremaker"
_ "github.com/c9s/bbgo/pkg/strategy/drift"
)
72 changes: 72 additions & 0 deletions pkg/indicator/gma.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package indicator

import (
"math"

"github.com/c9s/bbgo/pkg/types"
)

// Geometric Moving Average
//go:generate callbackgen -type GMA
type GMA struct {
types.SeriesBase
types.IntervalWindow
SMA *SMA
UpdateCallbacks []func(value float64)
}

func (inc *GMA) Last() float64 {
if inc.SMA == nil {
return 0.0
}
return math.Exp(inc.SMA.Last())
}

func (inc *GMA) Index(i int) float64 {
if inc.SMA == nil {
return 0.0
}
return math.Exp(inc.SMA.Index(i))
}

func (inc *GMA) Length() int {
return inc.SMA.Length()
}

func (inc *GMA) Update(value float64) {
if inc.SMA == nil {
inc.SMA = &SMA{IntervalWindow: inc.IntervalWindow}
}
inc.SMA.Update(math.Log(value))
}

func (inc *GMA) Clone() (out *GMA) {
out = &GMA{
IntervalWindow: inc.IntervalWindow,
SMA: inc.SMA.Clone().(*SMA),
}
out.SeriesBase.Series = out
return out
}

func (inc *GMA) TestUpdate(value float64) *GMA {
out := inc.Clone()
out.Update(value)
return out
}

var _ types.SeriesExtend = &GMA{}

func (inc *GMA) PushK(k types.KLine) {
inc.Update(k.Close.Float64())
}

func (inc *GMA) LoadK(allKLines []types.KLine) {
for _, k := range allKLines {
inc.PushK(k)
}
}

func (inc *GMA) BindK(target KLineClosedEmitter, symbol string, interval types.Interval) {
target.OnKLineClosed(types.KLineWith(symbol, interval, inc.PushK))
}
15 changes: 15 additions & 0 deletions pkg/indicator/gma_callbacks.go

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

61 changes: 61 additions & 0 deletions pkg/indicator/gma_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package indicator

import (
"encoding/json"
"testing"

"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
"github.com/stretchr/testify/assert"
)

/*
python:
import pandas as pd
from scipy.stats.mstats import gmean
data = pd.Series([1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9])
gmean(data[-5:])
gmean(data[-6:-1])
gmean(pd.concat(data[-4:], pd.Series([1.3])))
*/
func Test_GMA(t *testing.T) {
var randomPrices = []byte(`[1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9]`)
var input []fixedpoint.Value
if err := json.Unmarshal(randomPrices, &input); err != nil {
panic(err)
}
tests := []struct {
name string
kLines []types.KLine
want float64
next float64
update float64
updateResult float64
all int
}{
{
name: "test",
kLines: buildKLines(input),
want: 1.6940930229200213,
next: 1.5937204331251167,
update: 1.3,
updateResult: 1.6462950504034335,
all: 24,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gma := GMA{IntervalWindow: types.IntervalWindow{Window: 5}}
for _, k := range tt.kLines {
gma.PushK(k)
}
assert.InDelta(t, tt.want, gma.Last(), Delta)
assert.InDelta(t, tt.next, gma.Index(1), Delta)
gma.Update(tt.update)
assert.InDelta(t, tt.updateResult, gma.Last(), Delta)
assert.Equal(t, tt.all, gma.Length())
})
}
}
Loading

0 comments on commit 3a98ae0

Please sign in to comment.