129 lines
3.1 KiB
Go
129 lines
3.1 KiB
Go
package ccinr
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"git.qtrade.icu/lychiyu/qbtrade/pkg/exchange/binance"
|
||
"git.qtrade.icu/lychiyu/qbtrade/pkg/qbtrade"
|
||
"git.qtrade.icu/lychiyu/qbtrade/pkg/strategy/common"
|
||
"git.qtrade.icu/lychiyu/qbtrade/pkg/types"
|
||
log "github.com/sirupsen/logrus"
|
||
"sync"
|
||
)
|
||
|
||
const ID = "ccinr"
|
||
|
||
func init() {
|
||
qbtrade.RegisterStrategy(ID, &Strategy{})
|
||
}
|
||
|
||
type Strategy struct {
|
||
*common.Strategy
|
||
|
||
Symbol string `json:"symbol"`
|
||
Interval types.Interval `json:"interval"`
|
||
|
||
ExchangeSession *qbtrade.ExchangeSession
|
||
}
|
||
|
||
func (s *Strategy) ID() string {
|
||
return ID
|
||
}
|
||
|
||
func (s *Strategy) Subscribe(session *qbtrade.ExchangeSession) {
|
||
session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.Interval})
|
||
if !qbtrade.IsBackTesting {
|
||
session.Subscribe(types.MarketTradeChannel, s.Symbol, types.SubscribeOptions{})
|
||
}
|
||
}
|
||
|
||
func (s *Strategy) Initialize() error {
|
||
if s.Strategy == nil {
|
||
s.Strategy = &common.Strategy{}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor, session *qbtrade.ExchangeSession) error {
|
||
s.ExchangeSession = session
|
||
|
||
nr := session.Indicators(s.Symbol).NR(s.Interval, 4, true)
|
||
nr.OnUpdate(func(v float64) {
|
||
msg := fmt.Sprintf("交易信号:时间: %s, 最高价:%f,最低价:%f", nr.NrKLine.GetStartTime(), nr.NrKLine.High.Float64(), nr.NrKLine.Low.Float64())
|
||
qbtrade.Notify(msg)
|
||
fmt.Println(v)
|
||
})
|
||
|
||
//session.MarketDataStream.OnKLineClosed(func(k types.KLine) {
|
||
// if k.Symbol != s.Symbol || k.Interval != s.Interval {
|
||
// return
|
||
// }
|
||
// fmt.Println(k)
|
||
//})
|
||
//
|
||
//session.MarketDataStream.OnMarketTrade(func(trade types.Trade) {
|
||
// // handle market trade event here
|
||
// fmt.Println(trade)
|
||
//})
|
||
|
||
b, ok := s.getBalance(ctx)
|
||
fmt.Println(b, ok)
|
||
session.UserDataStream.OnOrderUpdate(func(order types.Order) {
|
||
if order.Status == types.OrderStatusFilled {
|
||
log.Infof("your order is filled: %+v", order)
|
||
}
|
||
})
|
||
|
||
session.UserDataStream.OnTradeUpdate(func(trade types.Trade) {
|
||
log.Infof("trade price %f, fee %f %s", trade.Price.Float64(), trade.Fee.Float64(), trade.FeeCurrency)
|
||
})
|
||
|
||
qbtrade.OnShutdown(ctx, func(ctx context.Context, wg *sync.WaitGroup) {
|
||
defer wg.Done()
|
||
|
||
if err := s.Strategy.OrderExecutor.GracefulCancel(ctx); err != nil {
|
||
log.WithError(err).Error("unable to cancel open orders...")
|
||
}
|
||
|
||
qbtrade.Sync(ctx, s)
|
||
})
|
||
|
||
return nil
|
||
}
|
||
|
||
func (s *Strategy) handleBalanceUpdate(balances types.BalanceMap) {
|
||
for _, b := range balances {
|
||
if b.Available.IsZero() && b.Borrowed.IsZero() {
|
||
continue
|
||
}
|
||
}
|
||
}
|
||
|
||
func (s *Strategy) handleBinanceBalanceUpdateEvent(event *binance.BalanceUpdateEvent) {
|
||
qbtrade.Notify(event)
|
||
|
||
account := s.ExchangeSession.GetAccount()
|
||
|
||
fmt.Println(account)
|
||
delta := event.Delta
|
||
|
||
// ignore outflow
|
||
if delta.Sign() < 0 {
|
||
return
|
||
}
|
||
}
|
||
|
||
// getBalance 获取账户余额
|
||
func (s *Strategy) getBalance(ctx context.Context) (balance types.Balance, ok bool) {
|
||
// 更新并获取account信息
|
||
account, err := s.ExchangeSession.UpdateAccount(ctx)
|
||
if err != nil {
|
||
log.WithError(err).Error("unable to update account")
|
||
return
|
||
}
|
||
|
||
// 获取balance信息
|
||
return account.Balance("USDT")
|
||
}
|