ccxt-go/exchange_generic.go
zhangkun9038@dingtalk.com 1a2ce7046a first add
2025-02-28 10:33:20 +08:00

526 lines
13 KiB
Go

package ccxt
import (
"fmt"
"reflect"
"sort"
"strconv"
)
func (this *Exchange) SortBy(array interface{}, value1 interface{}, desc2 ...interface{}) []interface{} {
var desc bool
var defaultValue interface{} = "a"
if len(desc2) > 0 {
desc = desc2[0].(bool)
}
list := array.([]interface{})
if str, ok := value1.(string); ok {
sort.Slice(list, func(i, j int) bool {
a := list[i].(map[string]interface{})[str]
b := list[j].(map[string]interface{})[str]
return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b)
})
if desc {
for i := len(list)/2 - 1; i >= 0; i-- {
opp := len(list) - 1 - i
list[i], list[opp] = list[opp], list[i]
}
}
return list
} else {
value := value1.(int)
sort.Slice(list, func(i, j int) bool {
var a, b interface{}
if reflect.TypeOf(list[i]).Kind() == reflect.Slice {
a = list[i].([]interface{})[value]
} else {
a = defaultValue
}
if reflect.TypeOf(list[j]).Kind() == reflect.Slice {
b = list[j].([]interface{})[value]
} else {
b = defaultValue
}
// return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b)
switch aVal := a.(type) {
case int:
if bVal, ok := b.(int); ok {
return aVal < bVal
}
case float64:
if bVal, ok := b.(float64); ok {
return aVal < bVal
}
case string:
if bVal, ok := b.(string); ok {
return aVal < bVal
}
}
// Fallback to string comparison
return fmt.Sprintf("%v", a) < fmt.Sprintf("%v", b)
})
if desc {
// for i := len(list)/2 - 1; i >= 0; i-- {
// opp := len(list) - 1 - i
// list[i], list[opp] = list[opp], list[i]
// }
for i := 0; i < len(list)/2; i++ {
opp := len(list) - 1 - i
list[i], list[opp] = list[opp], list[i]
}
}
return list
}
}
func (this *Exchange) SortBy2(array interface{}, key1 interface{}, key2 interface{}, desc2 ...interface{}) []interface{} {
var desc bool
if len(desc2) > 0 {
desc = desc2[0].(bool)
}
list := array.([]interface{})
if str, ok := key1.(string); ok {
key2Str, _ := key2.(string)
sort.Slice(list, func(i, j int) bool {
a1 := list[i].(map[string]interface{})[str]
a2 := list[i].(map[string]interface{})[key2Str]
b1 := list[j].(map[string]interface{})[str]
b2 := list[j].(map[string]interface{})[key2Str]
if a1 == b1 {
return fmt.Sprintf("%v", a2) < fmt.Sprintf("%v", b2)
}
return fmt.Sprintf("%v", a1) < fmt.Sprintf("%v", b1)
})
if desc {
for i := len(list)/2 - 1; i >= 0; i-- {
opp := len(list) - 1 - i
list[i], list[opp] = list[opp], list[i]
}
}
return list
}
return nil
}
func (this *Exchange) FilterBy(aa interface{}, key interface{}, value interface{}) []interface{} {
var targetA []interface{}
if aaArr, ok := aa.([]interface{}); ok {
targetA = aaArr
} else {
for _, v := range aa.(map[string]interface{}) {
targetA = append(targetA, v)
}
}
var outList []interface{}
for _, elem := range targetA {
if elem.(map[string]interface{})[key.(string)] == value {
outList = append(outList, elem)
}
}
return outList
}
func (this *Exchange) Extend(aa interface{}, bb ...interface{}) map[string]interface{} {
return ExtendMap(aa, bb...)
}
func ExtendMap(aa interface{}, bb ...interface{}) map[string]interface{} {
a := aa.(map[string]interface{})
outDict := make(map[string]interface{})
for key, value := range a {
outDict[key] = value
}
if len(bb) > 0 {
b, ok := bb[0].(map[string]interface{})
if ok {
for key, value := range b {
outDict[key] = value
}
}
}
return outDict
}
func (this *Exchange) DeepExtend2(objs ...interface{}) interface{} {
outDict := make(map[string]interface{})
for _, obj := range objs {
if obj == nil {
obj = make(map[string]interface{})
}
if reflect.TypeOf(obj).Kind() == reflect.Map {
for key, value := range obj.(map[string]interface{}) {
if value != nil && reflect.TypeOf(value).Kind() == reflect.Map {
if _, exists := outDict[key]; exists {
outDict[key] = this.DeepExtend2(outDict[key], value)
} else {
outDict[key] = this.DeepExtend2(value)
}
} else {
outDict[key] = value
}
}
} else {
outDict = obj.(map[string]interface{})
}
}
return outDict
}
func (this *Exchange) DeepExtend(objs ...interface{}) map[string]interface{} {
var outObj interface{}
for _, x := range objs {
if x == nil {
continue
}
if reflect.TypeOf(x).Kind() == reflect.Map {
if outObj == nil || reflect.TypeOf(outObj).Kind() != reflect.Map {
outObj = make(map[string]interface{})
}
dictX := x.(map[string]interface{})
for k, _ := range dictX {
arg1 := outObj.(map[string]interface{})[k]
arg2 := dictX[k]
if arg1 != nil && arg2 != nil && reflect.TypeOf(arg1).Kind() == reflect.Map && reflect.TypeOf(arg2).Kind() == reflect.Map {
outObj.(map[string]interface{})[k] = this.DeepExtend(arg1, arg2)
} else {
if arg2 != nil {
outObj.(map[string]interface{})[k] = arg2
} else {
outObj.(map[string]interface{})[k] = arg1
}
}
}
} else {
outObj = x
}
}
return outObj.(map[string]interface{})
}
// func (this *Exchange) DeepExtend(objs ...interface{}) map[string]interface{} {
// var outObj map[string]interface{}
// for _, x := range objs {
// if x == nil {
// continue
// }
// dictX, ok := x.(map[string]interface{})
// if !ok {
// continue
// }
// if outObj == nil {
// outObj = make(map[string]interface{})
// }
// for k, v := range dictX {
// if existingVal, exists := outObj[k]; exists {
// if existingMap, ok1 := existingVal.(map[string]interface{}); ok1 {
// if vMap, ok2 := v.(map[string]interface{}); ok2 {
// // Recursively merge maps
// outObj[k] = this.DeepExtend(existingMap, vMap)
// continue
// }
// }
// }
// // Directly assign the value if no deep merging is needed
// outObj[k] = v
// }
// }
// return outObj
// }
// func (this *Exchange) DeepExtend(objs ...interface{}) map[string]interface{} {
// var outObj interface{}
// for _, x := range objs {
// if x == nil {
// continue
// }
// // if xMap, ok := x.(map[string]interface{}); ok {
// if xMap, ok := x.(map[string]interface{}); ok {
// if outObj == nil {
// outObj = make(map[string]interface{})
// } else if _, ok := x.(map[string]interface{}); !ok {
// // || reflect.TypeOf(outObj).Kind() != reflect.Map
// outObj = make(map[string]interface{})
// }
// dictX := xMap
// for k, _ := range dictX {
// arg1 := outObj.(map[string]interface{})[k]
// arg2 := dictX[k]
// if arg1 != nil && arg2 != nil {
// _, arg1IsMap := arg1.(map[string]interface{})
// _, arg2IsMap := arg2.(map[string]interface{})
// if arg1IsMap && arg2IsMap {
// outObj.(map[string]interface{})[k] = this.DeepExtend(arg1, arg2)
// }
// } else {
// if arg2 != nil {
// outObj.(map[string]interface{})[k] = arg2
// } else {
// outObj.(map[string]interface{})[k] = arg1
// }
// }
// }
// } else {
// outObj = x
// }
// }
// return outObj.(map[string]interface{})
// }
// func (this *Exchange) DeepExtend(objs ...interface{}) map[string]interface{} {
// var outObj interface{}
// for _, x := range objs {
// if x == nil {
// continue
// }
// // if xMap, ok := x.(map[string]interface{}); ok {
// if xMap, ok := x.(map[string]interface{}); ok {
// if outObj == nil {
// outObj = make(map[string]interface{})
// } else if _, ok := x.(map[string]interface{}); !ok {
// // || reflect.TypeOf(outObj).Kind() != reflect.Map
// outObj = make(map[string]interface{})
// }
// dictX := xMap
// for k, _ := range dictX {
// arg1 := outObj.(map[string]interface{})[k]
// arg2 := dictX[k]
// if arg1 != nil && arg2 != nil {
// _, arg1IsMap := arg1.(map[string]interface{})
// _, arg2IsMap := arg2.(map[string]interface{})
// if arg1IsMap && arg2IsMap {
// outObj.(map[string]interface{})[k] = this.DeepExtend(arg1, arg2)
// }
// } else {
// if arg2 != nil {
// outObj.(map[string]interface{})[k] = arg2
// } else {
// outObj.(map[string]interface{})[k] = arg1
// }
// }
// }
// } else {
// outObj = x
// }
// }
// return outObj.(map[string]interface{})
// }
// func (this *Exchange) InArray(elem interface{}, list2 interface{}) bool {
// if list2 == nil {
// return false
// }
// if reflect.TypeOf(list2).Kind() == reflect.Slice {
// list := list2.([]interface{})
// for _, v := range list {
// if v == elem {
// return true
// }
// }
// }
// return false
// }
func (this *Exchange) InArray(elem interface{}, list interface{}) bool {
// Ensure the list is not nil and is of a slice type
if list == nil || reflect.TypeOf(list).Kind() != reflect.Slice {
return false
}
// Use reflection to iterate over the slice
listValue := reflect.ValueOf(list)
for i := 0; i < listValue.Len(); i++ {
listElem := listValue.Index(i).Interface()
// Handle number comparison
switch e := elem.(type) {
case int, int8, int16, int32, int64, float32, float64:
switch l := listElem.(type) {
case int, int8, int16, int32, int64, float32, float64:
// Convert both to float64 for comparison
if ToFloat64(e) == ToFloat64(l) {
return true
}
}
default:
// For non-numeric values, use DeepEqual
if reflect.DeepEqual(listElem, elem) {
return true
}
}
}
return false
}
// func (this *Exchange) InArray(elem interface{}, list interface{}) bool {
// // Ensure the list is not nil and is of a slice type
// if list == nil || reflect.TypeOf(list).Kind() != reflect.Slice {
// return false
// }
// // Use reflection to iterate over the slice
// listValue := reflect.ValueOf(list)
// for i := 0; i < listValue.Len(); i++ {
// if reflect.DeepEqual(listValue.Index(i).Interface(), elem) {
// return true
// }
// }
// return false
// }
func (this *Exchange) IsArray(a interface{}) bool {
// return reflect.TypeOf(a).Kind() == reflect.Slice
switch a.(type) {
case []interface{}:
return true
case []string:
return true
case []int:
return true
case []int64:
return true
case []float64:
return true
case []map[string]interface{}:
return true
}
return false
}
func (this *Exchange) IndexBy(a interface{}, key interface{}) map[string]interface{} {
outDict := make(map[string]interface{})
var targetX []interface{}
// Check if `a` is a slice of `[]interface{}` or a map
if aArr, ok := a.([]interface{}); ok {
targetX = aArr
} else if aMap, ok := a.(map[string]interface{}); ok {
for _, v := range aMap {
targetX = append(targetX, v)
}
} else {
return outDict // Unsupported type
}
// Process the slice `targetX`
for _, elem := range targetX {
switch v := elem.(type) {
case map[string]interface{}:
// Handle map entries
if val, ok := v[ToString(key)]; ok {
outDict[ToString(val)] = v
}
case []interface{}:
// Handle slices of []interface{}
if idx, ok := key.(int); ok && idx >= 0 && idx < len(v) {
if keyStr, ok := v[idx].(string); ok {
outDict[keyStr] = v
}
}
case []string:
// Handle slices of []string
if idx, ok := key.(int); ok && idx >= 0 && idx < len(v) {
outDict[v[idx]] = v
}
case []int:
// Handle slices of []int
if idx, ok := key.(int); ok && idx >= 0 && idx < len(v) {
outDict[fmt.Sprintf("%d", v[idx])] = v
}
}
}
return outDict
}
// func (this *Exchange) IndexBy(a interface{}, key2 interface{}) map[string]interface{} {
// outDict := make(map[string]interface{})
// var targetX []interface{}
// if aArr, ok := a.([]interface{}); ok {
// targetX = aArr
// } else {
// for _, v := range a.(map[string]interface{}) {
// targetX = append(targetX, v)
// }
// }
// for _, elem := range targetX {
// if reflect.TypeOf(elem).Kind() == reflect.Map {
// elem2 := elem.(map[string]interface{})
// if val, ok := elem2[ToString(key2)]; ok {
// outDict[ToString(val)] = elem2
// }
// } else if reflect.TypeOf(elem).Kind() == reflect.Slice {
// index := key2.(int)
// elem2 := elem.([]interface{})
// if len(elem2) > index {
// outDict[elem2[index].(string)] = elem2
// }
// }
// }
// return outDict
// }
func (this *Exchange) GroupBy(trades interface{}, key2 interface{}) map[string]interface{} {
key := key2.(string)
outDict := make(map[string]interface{})
list := trades.([]interface{})
for _, elem := range list {
elemDict := elem.(map[string]interface{})
if val, ok := elemDict[key]; ok {
elem2 := val.(string)
if list2, exists := outDict[elem2]; exists {
list2 = append(list2.([]interface{}), elem)
outDict[elem2] = list2
} else {
outDict[elem2] = []interface{}{elem}
}
}
}
return outDict
}
func (this *Exchange) OmitZero(value interface{}) interface{} {
switch v := value.(type) {
case float64:
if v == 0.0 {
return nil
}
case int64:
if v == 0 {
return nil
}
case string:
// Attempt to parse the string as a float64
parsed, err := strconv.ParseFloat(v, 64)
if err == nil {
// If parsed value is zero, return nil
if parsed == 0 {
return nil
}
}
// If parsing fails or value is non-zero, return the original string
}
return value
}
func (this *Exchange) Sum(args ...interface{}) interface{} {
var res interface{} = 0.0
for _, arg := range args {
res = this.sumValues(res, arg)
}
return res
}
func (this *Exchange) sumValues(a, b interface{}) interface{} {
return Add(a, b)
}