package trade import ( "fmt" "math" "git.apinb.com/quant/strategy/types" "github.com/markcheno/go-talib" "github.com/shopspring/decimal" ) // 计算合约的利润:多头 func CalculateProfit_Long(openPrice decimal.Decimal, currentPrice decimal.Decimal, quantity decimal.Decimal) decimal.Decimal { // 多头头寸:利润 = (当前价 - 开仓价) * 数量 return (currentPrice.Sub(openPrice)).Mul(quantity) } // 计算合约的利润:空头 func CalculateProfit_Short(openPrice decimal.Decimal, currentPrice decimal.Decimal, quantity decimal.Decimal) decimal.Decimal { // 空头头寸:利润 = (开仓价 - 当前价) * 数量 return (openPrice.Sub(currentPrice)).Mul(quantity) } // 这个方法的逻辑是合理的:它对输入的 value 进行“降噪”处理,只有当绝对值大于等于 threshold 时才认为有意义,否则视为 0。 // 然后根据降噪后的值判断正负性。 // threshold 由调用方传入,灵活性较高。 // 但注释有误,应该是“输入值绝对值小于 threshold 时视为0”,而不是 0.03。 // 返回值语义清晰:1 表示正,-1 表示负,0 表示零。 func DenoiseAndJudge(value, threshold float64) int { if math.Abs(value) < threshold { return 0 } if value > 0 { return 1 } if value < 0 { return -1 } return 0 } // isOutOfRange 判断传入的 float64 是否大于 0.001 或小于 -0.001 func IsOutOfRange(f float64) int { if f >= 0.001 { return 1 } if f <= -0.001 { return -1 } return 0 } func EMA(inReal []float64, inTimePeriod int, round int) []float64 { var newResult []float64 emaResult := talib.Ema(inReal, inTimePeriod) for _, val := range emaResult { if val == 0 { continue } newResult = append(newResult, FloatRound(val, round)) } return newResult } func ATR(k []*types.KLine, period int) float64 { high := make([]float64, len(k)) low := make([]float64, len(k)) closes := make([]float64, len(k)) for _, line := range k { high = append(high, line.High) low = append(low, line.Low) closes = append(closes, line.Close) } atr := talib.Atr(high, low, closes, period) return atr[len(atr)-1] } func CheckCross(emaFast, emaSlow []float64, MinCrossStrength float64) (bool, string, string) { if len(emaFast) != 2 || len(emaSlow) != 2 { return false, "", "参数错误,emaFast或emaSlow长度必须为2" } // 检查是否有交叉 prevDiff := emaFast[0] - emaSlow[0] // 前一个点的差值 currentDiff := emaFast[1] - emaSlow[1] // 当前点的差值 // 检查是否有交叉(从负到正或从正到负) if prevDiff*currentDiff >= 0 { return false, "", "无交叉:" + fmt.Sprintf("prevDiff: %f, currentDiff: %f", prevDiff, currentDiff) } // 降噪:检查交叉强度是否足够大 diffChange := currentDiff - prevDiff if abs(diffChange) < MinCrossStrength { return false, "", "交叉强度太小,可能是噪音:" + fmt.Sprintf("diffChange: %f, MinCrossStrength: %f", diffChange, MinCrossStrength) } // 简化的趋势判断 - 放宽过于严格的条件 var trend string if currentDiff > 0 { // 快线上穿慢线,判断为上升趋势 // 不再要求快线和慢线都必须同时上升,因为EMA交叉本身就表明趋势变化 trend = "UP" } else { // 快线下穿慢线,判断为下降趋势 // 不再要求快线和慢线都必须同时下降,因为EMA交叉本身就表明趋势变化 trend = "DOWN" } return true, trend, "" } // 辅助函数:计算绝对值 func abs(x float64) float64 { if x < 0 { return -x } return x }