-
-
Notifications
You must be signed in to change notification settings - Fork 273
/
exit.go
138 lines (110 loc) · 3.8 KB
/
exit.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package bbgo
import (
"bytes"
"encoding/json"
"reflect"
"github.com/pkg/errors"
"github.com/c9s/bbgo/pkg/dynamic"
)
type ExitMethodSet []ExitMethod
func (s *ExitMethodSet) SetAndSubscribe(session *ExchangeSession, parent interface{}) {
for i := range *s {
m := (*s)[i]
// manually inherit configuration from strategy
m.Inherit(parent)
m.Subscribe(session)
}
}
func (s *ExitMethodSet) Bind(session *ExchangeSession, orderExecutor *GeneralOrderExecutor) {
for _, method := range *s {
method.Bind(session, orderExecutor)
}
}
type ExitMethod struct {
RoiStopLoss *RoiStopLoss `json:"roiStopLoss"`
ProtectiveStopLoss *ProtectiveStopLoss `json:"protectiveStopLoss"`
RoiTakeProfit *RoiTakeProfit `json:"roiTakeProfit"`
TrailingStop *TrailingStop2 `json:"trailingStop"`
// Exit methods for short positions
// =================================================
LowerShadowTakeProfit *LowerShadowTakeProfit `json:"lowerShadowTakeProfit"`
CumulatedVolumeTakeProfit *CumulatedVolumeTakeProfit `json:"cumulatedVolumeTakeProfit"`
SupportTakeProfit *SupportTakeProfit `json:"supportTakeProfit"`
}
func (e ExitMethod) String() string {
var buf bytes.Buffer
if e.RoiStopLoss != nil {
b, _ := json.Marshal(e.RoiStopLoss)
buf.WriteString("roiStopLoss: " + string(b) + ", ")
}
if e.ProtectiveStopLoss != nil {
b, _ := json.Marshal(e.ProtectiveStopLoss)
buf.WriteString("protectiveStopLoss: " + string(b) + ", ")
}
if e.RoiTakeProfit != nil {
b, _ := json.Marshal(e.RoiTakeProfit)
buf.WriteString("rioTakeProft: " + string(b) + ", ")
}
if e.LowerShadowTakeProfit != nil {
b, _ := json.Marshal(e.LowerShadowTakeProfit)
buf.WriteString("lowerShadowTakeProft: " + string(b) + ", ")
}
if e.CumulatedVolumeTakeProfit != nil {
b, _ := json.Marshal(e.CumulatedVolumeTakeProfit)
buf.WriteString("cumulatedVolumeTakeProfit: " + string(b) + ", ")
}
if e.TrailingStop != nil {
b, _ := json.Marshal(e.TrailingStop)
buf.WriteString("trailingStop: " + string(b) + ", ")
}
if e.SupportTakeProfit != nil {
b, _ := json.Marshal(e.SupportTakeProfit)
buf.WriteString("supportTakeProfit: " + string(b) + ", ")
}
return buf.String()
}
// Inherit is used for inheriting properties from the given strategy struct
// for example, some exit method requires the default interval and symbol name from the strategy param object
func (m *ExitMethod) Inherit(parent interface{}) {
// we need to pass some information from the strategy configuration to the exit methods, like symbol, interval and window
rt := reflect.TypeOf(m).Elem()
rv := reflect.ValueOf(m).Elem()
for j := 0; j < rv.NumField(); j++ {
if !rt.Field(j).IsExported() {
continue
}
fieldValue := rv.Field(j)
if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
continue
}
dynamic.InheritStructValues(fieldValue.Interface(), parent)
}
}
func (m *ExitMethod) Subscribe(session *ExchangeSession) {
if err := dynamic.CallStructFieldsMethod(m, "Subscribe", session); err != nil {
panic(errors.Wrap(err, "dynamic Subscribe call failed"))
}
}
func (m *ExitMethod) Bind(session *ExchangeSession, orderExecutor *GeneralOrderExecutor) {
if m.ProtectiveStopLoss != nil {
m.ProtectiveStopLoss.Bind(session, orderExecutor)
}
if m.RoiStopLoss != nil {
m.RoiStopLoss.Bind(session, orderExecutor)
}
if m.RoiTakeProfit != nil {
m.RoiTakeProfit.Bind(session, orderExecutor)
}
if m.LowerShadowTakeProfit != nil {
m.LowerShadowTakeProfit.Bind(session, orderExecutor)
}
if m.CumulatedVolumeTakeProfit != nil {
m.CumulatedVolumeTakeProfit.Bind(session, orderExecutor)
}
if m.SupportTakeProfit != nil {
m.SupportTakeProfit.Bind(session, orderExecutor)
}
if m.TrailingStop != nil {
m.TrailingStop.Bind(session, orderExecutor)
}
}