add test case for volume calculator

This commit is contained in:
c9s 2020-06-19 00:07:05 +08:00
parent a5681b8371
commit 9099a4a61b
4 changed files with 115 additions and 18 deletions

View File

@ -22,14 +22,27 @@ func SellVolumeModifier(price float64) float64 {
return math.Min(2, math.Exp((price-targetPrice)/flatness))
}
func VolumeByPriceChange(currentPrice float64, change float64, side binance.SideType) float64 {
func VolumeByPriceChange(market Market, currentPrice float64, change float64, side binance.SideType) float64 {
volume := BaseVolumeByPriceChange(change)
if side == binance.SideTypeSell {
return volume * SellVolumeModifier(currentPrice)
volume *= SellVolumeModifier(currentPrice)
} else {
volume *= volume*BuyVolumeModifier(currentPrice)
}
return math.Max(MinQuantity, volume*BuyVolumeModifier(currentPrice))
// at least the minimal quantity
volume = math.Max(market.MinQuantity, volume)
// modify volume for the min amount
amount := currentPrice * volume
if amount < market.MinAmount {
ratio := market.MinAmount / amount
volume *= ratio
}
volume = math.Trunc(volume * math.Pow10(market.VolumePrecision)) / math.Pow10(market.VolumePrecision)
return volume
}
func BaseVolumeByPriceChange(change float64) float64 {

78
bbgo/calc_test.go Normal file
View File

@ -0,0 +1,78 @@
package bbgo
import (
"github.com/adshao/go-binance"
"testing"
)
func TestVolumeByPriceChange(t *testing.T) {
type args struct {
market Market
currentPrice float64
change float64
side binance.SideType
}
tests := []struct {
name string
args args
want float64
}{
{
name: "buy-change-50-at-9400",
args: args{
market: MarketBTCUSDT,
currentPrice: 9400,
change: 50,
side: binance.SideTypeBuy,
},
want: 0.00106382,
},
{
name: "buy-change-100-at-9200",
args: args{
market: MarketBTCUSDT,
currentPrice: 9200,
change: 100,
side: binance.SideTypeBuy,
},
want: 0.00108695,
},
{
name: "sell-change-100-at-9500",
args: args{
market: MarketBTCUSDT,
currentPrice: 9500,
change: 100,
side: binance.SideTypeSell,
},
want: 0.00249052,
},
{
name: "sell-change-200-at-9600",
args: args{
market: MarketBTCUSDT,
currentPrice: 9500,
change: 200,
side: binance.SideTypeSell,
},
want: 0.00265114,
},
{
name: "sell-change-500-at-9600",
args: args{
market: MarketBTCUSDT,
currentPrice: 9600,
change: 500,
side: binance.SideTypeSell,
},
want: 0.00390591,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := VolumeByPriceChange(tt.args.market, tt.args.currentPrice, tt.args.change, tt.args.side); got != tt.want {
t.Errorf("VolumeByPriceChange() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -65,7 +65,7 @@ func (d *KLineDetector) NewOrder(e *KLineEvent, tradingCtx *TradingContext) Orde
side = binance.SideTypeSell
}
var volume = tradingCtx.Market.FormatVolume(VolumeByPriceChange(kline.GetClose(), kline.GetChange(), side))
var volume = tradingCtx.Market.FormatVolume(VolumeByPriceChange(tradingCtx.Market, kline.GetClose(), kline.GetChange(), side))
return Order{
Symbol: e.KLine.Symbol,
Type: binance.OrderTypeMarket,
@ -140,4 +140,3 @@ func (d *KLineDetector) Detect(e *KLineEvent, tradingCtx *TradingContext) (reaso
return "", true
}

View File

@ -6,6 +6,8 @@ type Market struct {
Symbol string
PricePrecision int
VolumePrecision int
MinQuantity float64
MinAmount float64
}
func (m Market) FormatPrice(val float64) string {
@ -16,24 +18,29 @@ func (m Market) FormatVolume(val float64) string {
return strconv.FormatFloat(val, 'f', m.VolumePrecision, 64)
}
// Binance Markets, this should be defined per exchange
var Markets = map[string]Market{
"BNBUSDT": {
Symbol: "BNBUSDT",
PricePrecision: 4,
VolumePrecision: 2,
},
"BTCUSDT": {
var MarketBTCUSDT = Market{
Symbol: "BTCUSDT",
PricePrecision: 2,
VolumePrecision: 8,
},
MinQuantity: 0.00000100,
MinAmount: 10.0,
}
var MarketBNBUSDT = Market{
Symbol: "BNBUSDT",
PricePrecision: 4,
VolumePrecision: 2,
MinQuantity: 0.01,
MinAmount: 10.0,
}
func FindMarket(symbol string) (m Market, ok bool) {
m , ok = Markets[symbol]
var Markets = map[string]Market{
"BNBUSDT": MarketBNBUSDT,
"BTCUSDT": MarketBTCUSDT,
}
func FindMarket(symbol string) (m Market, ok bool) {
m, ok = Markets[symbol]
return m, ok
}