You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

95 lines
3.1 KiB

package trade
import (
"fmt"
"sig-pub/pkg/strategy"
"sig-pub/pkg/types"
"sig-pub/pkg/types/decimals"
"time"
"github.com/govalues/decimal"
)
const (
PriceDriverInterval = types.Interval1m // 价格更新使用1分钟k线
)
type SigTradeStrategy struct {
closeParam *CloseStrategyInput
}
func NewSigTradeStrategy() *SigTradeStrategy {
return &SigTradeStrategy{}
}
func (s *SigTradeStrategy) New() strategy.ISigStrategy {
return &SigTradeStrategy{}
}
func (s *SigTradeStrategy) Meta() strategy.StrategyMeta {
return strategy.StrategyMeta{
Name: "SigTradeStrategy",
Desc: "默认交易策略",
Input: []types.InputArg{
// 交易参数
{Name: "maxPosPct", Type: types.InputTypeUFloat, Desc: "单笔交易最大仓位占比"},
{Name: "maxExposurePct", Type: types.InputTypeUFloat, Desc: "最大总敞口占比"},
{Name: "maxLots", Type: types.InputTypeUInt, Desc: "最大手数/数量"},
// 平仓止损参数
{Name: "stopLossPct", Type: types.InputTypeUFloat, Desc: "固定止损比例"},
{Name: "takeProfitPct", Type: types.InputTypeUFloat, Desc: "固定止盈比例"},
{Name: "profitRetracePcts", Type: types.InputTypeUFloats2D, Desc: "基于最高利润回撤触发平仓 (例如 [[0.01, 0.3], [0.02, 0.2]] 最高利润超过1%时30%回撤则触发平仓, 最高利润超过2%时20%回撤就触发平仓)"},
{Name: "closeOnSideReverse", Type: types.InputTypeBool, Desc: "交易信号和持单方向相反时是否进行平仓"},
{Name: "fee", Type: types.InputTypeBool, Desc: "计算止盈止损时是否包含手续费"},
// 风险评估参数...
},
}
}
// 校验参数, 并根据参数初始化策略
func (s *SigTradeStrategy) Init(input types.Input) (err error) {
s.closeParam = new(CloseStrategyInput)
input.DecodeInput(s.closeParam)
if s.closeParam.StopLossPct < 0 {
err = fmt.Errorf("stopLossPct can't less zero")
return
}
return
}
// 需要的各周期最小数据k线数
func (s *SigTradeStrategy) CandlePeriods(ctx strategy.IInstanceIntervalSigStrategyContext) (tradeInsts []string, iPeriods *types.IntervalState[int16]) {
iPeriods = types.NewIntervalState[int16]()
iPeriods.Set(PriceDriverInterval, 1)
return
}
// EntryAnalysis 生成下单参数(交易量/方向/杠杆)
// 控制滑点, 仓位管理
// 持仓中币种不能改变杠杆
func (s *SigTradeStrategy) EntryAnalysis(ctx strategy.IInstanceIntervalSigStrategyContext, account ITradeAccount, sigInstId string, sigSide types.Side) (tickets []TradeTicket, skipCause Cause, err error) {
// todo 买卖信号交易风险分析
if pos := account.GetPosition(sigInstId); pos != nil {
// 已持仓不能下反方向单, todo 副账户做反方向单,对冲(viceAccount)
if pos.Side != sigSide {
return
}
}
k := ctx.Get(sigInstId, PriceDriverInterval, 0)
price := decimals.MustToFloat64(k.Close)
ta := TradeTicket{
TradeType: TradeTypeOpen,
InstId: sigInstId,
Side: sigSide,
Price: price,
Leverage: 1,
Qty: decimal.MustParse("0.02"),
Interval: string(k.Interval),
Ktime: k.Interval.MustAddMul(k.Ts, 1),
Ctime: time.Now().UnixMilli(),
}
tickets = append(tickets, ta)
return
}