forked from nntaoli-project/goex
-
Notifications
You must be signed in to change notification settings - Fork 4
/
APIUtils.go
149 lines (123 loc) · 3.03 KB
/
APIUtils.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
139
140
141
142
143
144
145
146
147
148
149
package goex
import (
"errors"
"fmt"
"github.com/nntaoli-project/goex/internal/logger"
"reflect"
"time"
)
/**
本函数只适合,返回两个参数的API重试调用,其中一个参数必须是error
@retry 重试次数
@delay 每次重试延迟时间间隔
@method 调用的函数,比如: api.GetTicker ,注意:不是api.GetTicker(...)
@params 参数,顺序一定要按照实际调用函数入参顺序一样
@return 返回
*/
func RE(retry int, delay time.Duration, method interface{}, params ...interface{}) interface{} {
invokeM := reflect.ValueOf(method)
if invokeM.Kind() != reflect.Func {
return errors.New("method not a function")
}
var value []reflect.Value = make([]reflect.Value, len(params))
var i int = 0
for ; i < len(params); i++ {
value[i] = reflect.ValueOf(params[i])
}
var retV interface{}
var retryC int = 0
_CALL:
if retryC > 0 {
logger.Log.Info("sleep ", delay, " after re call")
time.Sleep(delay)
}
retValues := invokeM.Call(value)
for _, vl := range retValues {
if vl.Type().String() == "error" {
if vl.IsNil() {
continue
}
logger.Log.Error("[api error]", vl)
retryC++
if retryC <= retry-1 {
logger.Log.Infof("Invoke Method[%s] Error , Begin Retry Call [%d] ...", invokeM.String(), retryC)
goto _CALL
} else {
logger.Log.Error("Invoke Method Fail ???" + invokeM.String())
return vl.Interface()
}
} else {
retV = vl.Interface()
}
}
return retV
}
/**
* call all unfinished orders
*/
func CancelAllUnfinishedOrders(api API, currencyPair CurrencyPair) int {
if api == nil {
logger.Log.Error("api instance is nil ??? , please new a api instance")
return -1
}
c := 0
for {
ret := RE(2, 200*time.Millisecond, api.GetUnfinishOrders, currencyPair)
if err, isok := ret.(error); isok {
logger.Log.Error("[api error]", err)
break
}
if ret == nil {
break
}
orders, isok := ret.([]Order)
if !isok || len(orders) == 0 {
break
}
for _, ord := range orders {
_, err := api.CancelOrder(ord.OrderID2, currencyPair)
if err != nil {
logger.Log.Error(err)
} else {
c++
}
time.Sleep(120 * time.Millisecond) //控制频率
}
}
return c
}
/**
* call all unfinished future orders
* @return c 成功撤单数量
*/
func CancelAllUnfinishedFutureOrders(api FutureRestAPI, contractType string, currencyPair CurrencyPair) int {
if api == nil {
logger.Log.Error("api instance is nil ??? , please new a api instance")
return 0
}
c := 0
for {
ret := RE(10, 200*time.Millisecond, api.GetUnfinishFutureOrders, currencyPair, contractType)
if err, isOk := ret.(error); isOk {
logger.Log.Error("[api error]", err)
break
}
if ret == nil {
break
}
orders, isOk := ret.([]FutureOrder)
if !isOk || len(orders) == 0 {
break
}
for _, ord := range orders {
_, err := api.FutureCancelOrder(currencyPair, contractType, fmt.Sprintf("%s", ord.OrderID2))
if err != nil {
logger.Log.Error(err)
} else {
c++
}
time.Sleep(120 * time.Millisecond) //控制频率
}
}
return c
}