package indicators import ( "errors" "fmt" "strings" objects "github.com/d5/tengo/v2" "github.com/thrasher-corp/gct-ta/indicators" "github.com/thrasher-corp/gocryptotrader/gctscript/modules" "github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/validator" ) // MfiModule index indicator commands var MfiModule = map[string]objects.Object{ "calculate": &objects.UserFunction{Name: "calculate", Value: mfi}, } // MoneyFlowIndex is the string constant const MoneyFlowIndex = "Money Flow Index" // MFI defines a custom Money Flow Index tengo indicator object type type MFI struct { objects.Array Period int } // TypeName returns the name of the custom type. func (o *MFI) TypeName() string { return MoneyFlowIndex } func mfi(args ...objects.Object) (objects.Object, error) { if len(args) != 2 { return nil, objects.ErrWrongNumArguments } r := new(MFI) if validator.IsTestExecution.Load() == true { return r, nil } ohlcvInput := objects.ToInterface(args[0]) ohlcvInputData, valid := ohlcvInput.([]interface{}) if !valid { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, OHLCV) } ohlcvData := make([][]float64, 6) var allErrors []string for x := range ohlcvInputData { t := ohlcvInputData[x].([]interface{}) value, err := toFloat64(t[2]) if err != nil { allErrors = append(allErrors, err.Error()) } ohlcvData[2] = append(ohlcvData[2], value) value, err = toFloat64(t[3]) if err != nil { allErrors = append(allErrors, err.Error()) } ohlcvData[3] = append(ohlcvData[3], value) value, err = toFloat64(t[4]) if err != nil { allErrors = append(allErrors, err.Error()) } ohlcvData[4] = append(ohlcvData[4], value) value, err = toFloat64(t[5]) if err != nil { allErrors = append(allErrors, err.Error()) } ohlcvData[5] = append(ohlcvData[5], value) } if len(allErrors) > 0 { return nil, errors.New(strings.Join(allErrors, ", ")) } inTimePeriod, ok := objects.ToInt(args[1]) if !ok { return nil, fmt.Errorf(modules.ErrParameterConvertFailed, inTimePeriod) } r.Period = inTimePeriod ret := indicators.MFI(ohlcvData[2], ohlcvData[3], ohlcvData[4], ohlcvData[5], inTimePeriod) for x := range ret { r.Value = append(r.Value, &objects.Float{Value: ret[x]}) } return r, nil }