package trade import ( "sig-pub/pkg/types" "sig-pub/pkg/types/decimals" ) type ICloseStrategy interface { OnKline(k types.Kline, pos *Position) (closePos bool, cause Cause) OnPrice(price float64, pos *Position) (closePos bool, cause Cause) OnSigStrategySingal(sigSide types.Side, pos *Position) (closePos bool, cause Cause) } // 平仓策略参数 type CloseStrategyParam struct { StopLossPct float64 `json:"stopLossPct"` // 固定止损 static stoploss TakeProfitPct float64 `json:"takeProfitPct"` // 固定止盈 static take profit TrailMinProfit float64 `json:"trailMinProfit"` // 启动移动止损的最小盈利阈值(例如达到 1% 后才开始追踪) minimum profit (fraction) before trailing activates (e.g. 0.01 = 1%); TrailingPct float64 `json:"trailingPct"` // 移动止损百分比(例如 0.02 表示从最高价回撤 2% 时触发追踪止损) trailing stop percent (e.g. 0.02 = 2%); ProfitRetracePct float64 `json:"profitRetracePct"` // close when profit retraces more than this fraction of peak profit;基于最高利润回撤触发平仓(例如从最高利润回撤超过 30% 则平仓)。 CloseOnSideReverse bool `json:"closeOnSideReverse"` // 交易信号和持单方向相反时是否进行平仓 Fee bool `json:"fee"` // 计算止盈止损时是否包含手续费 } // CloseStrategy 平仓策略 type CloseStrategy struct { CloseStrategyParam } func NewCloseStrategy(param CloseStrategyParam) *CloseStrategy { return &CloseStrategy{ CloseStrategyParam: param, } } // Update 当k线更新判断是否关闭仓位 func (s *CloseStrategy) OnKline(k types.Kline, pos *Position) (closePos bool, cause Cause) { closePrice := decimals.MustToFloat64(k.Close) // update peak px if pos.Side == types.SideLong && closePrice > pos.PeakPx { pos.PeakPx = closePrice } if pos.Side == types.SideShort && closePrice < pos.PeakPx { pos.PeakPx = closePrice } return s.OnPrice(closePrice, pos) } // OnPrice 当k线更新判断是否关闭仓位 func (s *CloseStrategy) OnPrice(price float64, pos *Position) (closePos bool, cause Cause) { if !pos.Side.IsValid() { return } // side long: if pos.Side == types.SideLong { // 固定止损 if s.StopLossPct > 0 && price <= pos.EntryPx*(1-s.StopLossPct) { return true, CauseStoploss } // 固定止盈 if s.TakeProfitPct > 0 && price >= pos.EntryPx*(1+s.TakeProfitPct) { return true, CauseTakeprofit } // todo dynamic trailing return } // side short: if s.StopLossPct > 0 && price >= pos.EntryPx*(1+s.StopLossPct) { return true, CauseStoploss } if s.TakeProfitPct > 0 && price <= pos.EntryPx*(1-s.TakeProfitPct) { return true, CauseTakeprofit } return } // OnSigStrategySingal 根据策略信号尝试平掉相反方向的仓位。例如策略返回 SELL 时,平掉 BUY 持仓 func (s *CloseStrategy) OnSigStrategySingal(sigSide types.Side, pos *Position) (closePos bool, cause Cause) { if !s.CloseOnSideReverse { return } return sigSide != pos.Side, CauseStoploss }