-
Notifications
You must be signed in to change notification settings - Fork 0
/
position_test.go
118 lines (109 loc) · 3.33 KB
/
position_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package riskcontrol
import (
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
"github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/bbgo/mocks"
"github.com/c9s/bbgo/pkg/core"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)
func Test_ModifiedQuantity(t *testing.T) {
pos := &types.Position{
Market: types.Market{
Symbol: "BTCUSDT",
PricePrecision: 8,
VolumePrecision: 8,
QuoteCurrency: "USDT",
BaseCurrency: "BTC",
},
}
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, "BTCUSDT", "strategy", "strategy-1", pos)
riskControl := NewPositionRiskControl(orderExecutor, fixedpoint.NewFromInt(10), fixedpoint.NewFromInt(2))
cases := []struct {
name string
position fixedpoint.Value
buyQuantity fixedpoint.Value
sellQuantity fixedpoint.Value
}{
{
name: "BuyOverHardLimit",
position: fixedpoint.NewFromInt(9),
buyQuantity: fixedpoint.NewFromInt(1),
sellQuantity: fixedpoint.NewFromInt(2),
},
{
name: "SellOverHardLimit",
position: fixedpoint.NewFromInt(-9),
buyQuantity: fixedpoint.NewFromInt(2),
sellQuantity: fixedpoint.NewFromInt(1),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
buyQuantity, sellQuantity := riskControl.ModifiedQuantity(tc.position)
assert.Equal(t, tc.buyQuantity, buyQuantity)
assert.Equal(t, tc.sellQuantity, sellQuantity)
})
}
}
func TestReleasePositionCallbacks(t *testing.T) {
cases := []struct {
name string
position fixedpoint.Value
resultPosition fixedpoint.Value
}{
{
name: "PositivePositionWithinLimit",
position: fixedpoint.NewFromInt(8),
resultPosition: fixedpoint.NewFromInt(8),
},
{
name: "NegativePositionWithinLimit",
position: fixedpoint.NewFromInt(-8),
resultPosition: fixedpoint.NewFromInt(-8),
},
{
name: "PositivePositionOverLimit",
position: fixedpoint.NewFromInt(11),
resultPosition: fixedpoint.NewFromInt(10),
},
{
name: "NegativePositionOverLimit",
position: fixedpoint.NewFromInt(-11),
resultPosition: fixedpoint.NewFromInt(-10),
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
pos := &types.Position{
Base: tc.position,
Market: types.Market{
Symbol: "BTCUSDT",
PricePrecision: 8,
VolumePrecision: 8,
QuoteCurrency: "USDT",
BaseCurrency: "BTC",
},
}
tradeCollector := &core.TradeCollector{}
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
orderExecutor := mocks.NewMockOrderExecutorExtended(mockCtrl)
orderExecutor.EXPECT().TradeCollector().Return(tradeCollector).AnyTimes()
orderExecutor.EXPECT().Position().Return(pos).AnyTimes()
orderExecutor.EXPECT().SubmitOrders(gomock.Any(), gomock.Any()).AnyTimes()
riskControl := NewPositionRiskControl(orderExecutor, fixedpoint.NewFromInt(10), fixedpoint.NewFromInt(2))
riskControl.OnReleasePosition(func(quantity fixedpoint.Value, side types.SideType) {
if side == types.SideTypeBuy {
pos.Base = pos.Base.Add(quantity)
} else {
pos.Base = pos.Base.Sub(quantity)
}
})
orderExecutor.TradeCollector().EmitPositionUpdate(&types.Position{Base: tc.position})
assert.Equal(t, tc.resultPosition, pos.Base)
})
}
}