|
|
|
|
@ -4,6 +4,7 @@ import (
|
|
|
|
|
"fmt" |
|
|
|
|
"sig-pub/api/pb" |
|
|
|
|
"sig-pub/pkg/client" |
|
|
|
|
"sig-pub/pkg/data" |
|
|
|
|
"sig-pub/pkg/data/entity" |
|
|
|
|
"sig-pub/pkg/indicator" |
|
|
|
|
"sig-pub/pkg/publish" |
|
|
|
|
@ -11,6 +12,8 @@ import (
|
|
|
|
|
"sig-pub/pkg/types" |
|
|
|
|
"sig-pub/pkg/utils/collect" |
|
|
|
|
"sig-pub/pkg/zlog" |
|
|
|
|
|
|
|
|
|
"github.com/bytedance/sonic" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type TradingService struct { |
|
|
|
|
@ -20,8 +23,8 @@ type TradingService struct {
|
|
|
|
|
klineStore *KlineStore |
|
|
|
|
indicatorReg *indicator.IndicatorRegistry // 注册窗口指标
|
|
|
|
|
strategyReg *strategy.SigStrategyRegistry // 注册信号策略
|
|
|
|
|
publisher *publish.Publisher[int64, *TradingPlanRunner] |
|
|
|
|
tradingPlan chan *TradingPlanRunner |
|
|
|
|
signalPublisher *publish.Publisher[int64, strategy.StrategyType] // planId -> strategyType
|
|
|
|
|
tradingPlans *collect.SyncMap[int64, *TradingPlan] // 运行中交易计划
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func NewTradingService( |
|
|
|
|
@ -34,7 +37,8 @@ func NewTradingService(
|
|
|
|
|
klineStore: NewKlineSeriesStore(exchangeClient), |
|
|
|
|
indicatorReg: indicator.NewIndicatorRegistry(), |
|
|
|
|
strategyReg: strategy.NewSigStrategyRegistry(), |
|
|
|
|
publisher: publish.NewPublisher[int64, *TradingPlanRunner](8), |
|
|
|
|
signalPublisher: publish.NewPublisher[int64, strategy.StrategyType](16), |
|
|
|
|
tradingPlans: collect.NewSyncMap[int64, *TradingPlan](), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -52,6 +56,8 @@ func (svc *TradingService) Init() (err error) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
go svc.consumerKlineSignal() |
|
|
|
|
|
|
|
|
|
// todo loading trading plan
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -61,24 +67,80 @@ func (svc *TradingService) consumerKlineSignal() {
|
|
|
|
|
for { |
|
|
|
|
signalKey := <-c |
|
|
|
|
zlog.Debugf("signal: %s", signalKey) |
|
|
|
|
_, plans := svc.publisher.Publisher(signalKey) |
|
|
|
|
for _, plan := range plans { |
|
|
|
|
plan.Update(signalKey) |
|
|
|
|
planIds, strategyTypes := svc.signalPublisher.Publisher(signalKey) |
|
|
|
|
for i, strategyType := range strategyTypes { |
|
|
|
|
planId := planIds[i] |
|
|
|
|
plan, ok := svc.tradingPlans.Load(planId) |
|
|
|
|
if !ok { |
|
|
|
|
zlog.Warningf("plan not running: id=%d", planId) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
if plan.Status.Load() == int32(data.StatusOk) { |
|
|
|
|
plan.Update(strategyType) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// RunStrategy 运行策略
|
|
|
|
|
// todo 止盈止损...
|
|
|
|
|
func (svc *TradingService) RunQuantPlan(plan *entity.TradePlan) (err error) { |
|
|
|
|
strategy, ok := svc.strategyReg.NewSigStrategy(plan.SigStrategy) |
|
|
|
|
// runTradingPlan 运行交易计划
|
|
|
|
|
// todo 止盈止损策略, 下单策略...
|
|
|
|
|
func (svc *TradingService) runTradingPlan(plan *entity.TradePlan) (err error) { |
|
|
|
|
var planId = plan.Id |
|
|
|
|
var instId = plan.InstId |
|
|
|
|
var exchange pb.ExchangeType |
|
|
|
|
var sigInterval types.Interval |
|
|
|
|
|
|
|
|
|
exchange = pb.ExchangeType(plan.Exchange) |
|
|
|
|
if !types.IsSupportExchange(exchange) { |
|
|
|
|
err = fmt.Errorf("unsupport exchange %d", plan.Exchange) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tradingPlan := NewTradingPlan(*plan, svc.indicatorReg) |
|
|
|
|
if _, load := svc.tradingPlans.LoadOrStore(planId, tradingPlan); load { |
|
|
|
|
err = fmt.Errorf("plan already running: planId=%d", planId) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
tradingPlan.Status.Store(int32(data.StatusProcessing)) |
|
|
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
if err != nil { |
|
|
|
|
svc.tradingPlans.Delete(planId) |
|
|
|
|
} else { |
|
|
|
|
// 订阅交易信号策略k线周期
|
|
|
|
|
sigSubKey := strategy.DriverIntervalKey(instId, []types.Interval{sigInterval}, exchange) |
|
|
|
|
svc.signalPublisher.Subscribe(sigSubKey, planId, strategy.StrategyTypeSig) |
|
|
|
|
|
|
|
|
|
tradingPlan.Status.Store(int32(data.StatusOk)) |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
// sigStrategy
|
|
|
|
|
sigStrategyParam := new(strategy.SigStrategyParam) |
|
|
|
|
if err = sonic.UnmarshalString(plan.SigStrategyParam, sigStrategyParam); err != nil { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
sigInterval = types.Interval(sigStrategyParam.Interval) |
|
|
|
|
if _, ok := types.SupportedIntervals[sigInterval]; !ok { |
|
|
|
|
err = fmt.Errorf("unsupport interval %d", plan.Exchange) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
sigStrategy, ok := svc.strategyReg.NewSigStrategy(plan.SigStrategy) |
|
|
|
|
if !ok { |
|
|
|
|
err = fmt.Errorf("strategy %s not exists", plan.SigStrategy) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
runner := strategy.New() |
|
|
|
|
_ = runner |
|
|
|
|
runner.Update(nil) |
|
|
|
|
sigKlineSeries, err := svc.klineStore.GetKlineSeires(exchange, instId, sigInterval) |
|
|
|
|
if err != nil { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err = tradingPlan.Init(); err != nil { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if err = tradingPlan.InitSigStrategy(sigStrategy, *sigStrategyParam, sigKlineSeries); err != nil { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|