diff --git a/pkg/bbgo/position.go b/pkg/bbgo/position.go new file mode 100644 index 000000000..fc17b4533 --- /dev/null +++ b/pkg/bbgo/position.go @@ -0,0 +1,41 @@ +package bbgo + +import ( + "github.com/c9s/bbgo/pkg/fixedpoint" + "github.com/c9s/bbgo/pkg/types" +) + +type Position struct { + Base fixedpoint.Value + Quote fixedpoint.Value + AverageCost fixedpoint.Value +} + +func (p *Position) AddTrade(t types.Trade) (fixedpoint.Value, bool) { + price := fixedpoint.NewFromFloat(t.Price) + quantity := fixedpoint.NewFromFloat(t.Quantity) + + switch t.Side { + + case types.SideTypeBuy: + + if p.AverageCost == 0 { + p.AverageCost = price + } else { + p.AverageCost = (p.AverageCost.Mul(p.Base) + price.Mul(quantity)).Div(p.Base + quantity) + } + + p.Base += quantity + p.Quote -= fixedpoint.NewFromFloat(t.QuoteQuantity) + + return 0, false + + case types.SideTypeSell: + p.Base -= quantity + p.Quote += fixedpoint.NewFromFloat(t.QuoteQuantity) + + return price - p.AverageCost, true + } + + return 0, false +} diff --git a/pkg/bbgo/position_test.go b/pkg/bbgo/position_test.go new file mode 100644 index 000000000..4eae3b04b --- /dev/null +++ b/pkg/bbgo/position_test.go @@ -0,0 +1,33 @@ +package bbgo + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/c9s/bbgo/pkg/fixedpoint" + "github.com/c9s/bbgo/pkg/types" +) + +func TestPosition(t *testing.T) { + trades := []types.Trade{ + { + Side: types.SideTypeBuy, + Price: 1000.0, + Quantity: 0.01, + }, + { + Side: types.SideTypeBuy, + Price: 2000.0, + Quantity: 0.03, + }, + } + + pos := Position{} + for _, trade := range trades { + pos.AddTrade(trade) + } + + assert.Equal(t, fixedpoint.NewFromFloat(0.04), pos.Base) + assert.Equal(t, fixedpoint.NewFromFloat((1000.0*0.01+2000.0*0.03)/0.04), pos.AverageCost) +}