add pause trade
This commit is contained in:
parent
d973d95121
commit
a07d255d77
|
@ -7,13 +7,13 @@
|
|||
# db: 0
|
||||
|
||||
sessions:
|
||||
binance_futures:
|
||||
binance:
|
||||
exchange: binance
|
||||
envVarPrefix: BINANCE
|
||||
futures: true
|
||||
|
||||
exchangeStrategies:
|
||||
- on: binance_futures
|
||||
- on: binance
|
||||
ccinr:
|
||||
symbols:
|
||||
- ARUSDT
|
||||
|
@ -24,17 +24,17 @@ exchangeStrategies:
|
|||
- DYDXUSDT
|
||||
- XRPUSDT
|
||||
- PEOPLEUSDT
|
||||
# - STXUSDT
|
||||
# - WLDUSDT
|
||||
# - FILUSDT
|
||||
# - DOGEUSDT
|
||||
# - MKRUSDT
|
||||
# - NOTUSDT
|
||||
# - ENSUSDT
|
||||
# - BNBUSDT
|
||||
# - BTCUSDT
|
||||
# - ETHUSDT
|
||||
# - SOLUSDT
|
||||
# - STXUSDT
|
||||
# - WLDUSDT
|
||||
# - FILUSDT
|
||||
# - DOGEUSDT
|
||||
# - MKRUSDT
|
||||
# - NOTUSDT
|
||||
# - ENSUSDT
|
||||
# - BNBUSDT
|
||||
# - BTCUSDT
|
||||
# - ETHUSDT
|
||||
# - SOLUSDT
|
||||
|
||||
interval: 1m
|
||||
nrInterval: 1m
|
||||
|
@ -55,9 +55,33 @@ exchangeStrategies:
|
|||
placePriceType: 2
|
||||
lossType: 1
|
||||
profitOrderType: 0
|
||||
atrProfitRange: 0.8
|
||||
atrLossRange: 1.0
|
||||
atrProfitRange: 1.0
|
||||
atrLossRange: 2.0
|
||||
tradeStartHour: 0
|
||||
tradeEndHour: 8
|
||||
pauseTradeLoss: -10.0
|
||||
# recalculate: false
|
||||
# dry_run: false
|
||||
# # quantity: 3
|
||||
# strict_mode: true
|
||||
|
||||
backtest:
|
||||
startTime: "2023-10-15"
|
||||
endTime: "2024-08-02"
|
||||
symbols:
|
||||
- ARUSDT
|
||||
- ORDIUSDT
|
||||
- OPUSDT
|
||||
- OMUSDT
|
||||
- WIFUSDT
|
||||
- DYDXUSDT
|
||||
- XRPUSDT
|
||||
- PEOPLEUSDT
|
||||
sessions: [ binance ]
|
||||
syncSecKLines: true
|
||||
accounts:
|
||||
binance:
|
||||
takerFeeRate: 0.0002
|
||||
makerFeeRate: 0.0005
|
||||
balances:
|
||||
USDT: 200
|
BIN
otp.png
BIN
otp.png
Binary file not shown.
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.9 KiB |
|
@ -174,7 +174,8 @@ func (n *Notifier) NotifyTo(channel string, obj interface{}, args ...interface{}
|
|||
message = fmt.Sprintf(a, args...)
|
||||
|
||||
default:
|
||||
log.Errorf("unsupported notification format: %T %+v", a, a)
|
||||
//log.Errorf("unsupported notification format: %T %+v", a, a)
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const ID = "ccinr"
|
||||
|
@ -49,6 +50,9 @@ type Strategy struct {
|
|||
LossRange fixedpoint.Value `json:"lossRange"`
|
||||
AtrProfitRange float64 `json:"atrProfitRange"`
|
||||
AtrLossRange float64 `json:"atrLossRange"`
|
||||
TradeStartHour int `json:"tradeStartHour"`
|
||||
TradeEndHour int `json:"tradeEndHour"`
|
||||
PauseTradeLoss fixedpoint.Value `json:"pauseTradeLoss"`
|
||||
|
||||
qbtrade.QuantityOrAmount
|
||||
|
||||
|
@ -89,6 +93,10 @@ type Strategy struct {
|
|||
TotalOrderCount int
|
||||
TotalProfitCount int
|
||||
TotalLossCount int
|
||||
// 累计暂停交易的次数
|
||||
PauseTradeCount fixedpoint.Value
|
||||
// 最近一次暂停交易的时间
|
||||
PauseTradeTime time.Time
|
||||
}
|
||||
|
||||
func (s *Strategy) ID() string {
|
||||
|
@ -101,8 +109,11 @@ func (s *Strategy) Subscribe(session *qbtrade.ExchangeSession) {
|
|||
session.Subscribe(types.KLineChannel, symbol, types.SubscribeOptions{Interval: s.CCIInterval})
|
||||
session.Subscribe(types.KLineChannel, symbol, types.SubscribeOptions{Interval: s.ATRInterval})
|
||||
session.Subscribe(types.KLineChannel, symbol, types.SubscribeOptions{Interval: s.NRInterval})
|
||||
|
||||
if !qbtrade.IsBackTesting {
|
||||
session.Subscribe(types.MarketTradeChannel, symbol, types.SubscribeOptions{})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Strategy) Initialize() error {
|
||||
|
@ -114,7 +125,7 @@ func (s *Strategy) Initialize() error {
|
|||
}
|
||||
|
||||
func (s *Strategy) InstanceID() string {
|
||||
return fmt.Sprintf("%s:%s:%s", ID, strings.Join(s.Symbols, "-"), s.Interval)
|
||||
return fmt.Sprintf("%s:%s", ID, s.Interval)
|
||||
}
|
||||
|
||||
func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Value) error {
|
||||
|
@ -206,10 +217,17 @@ func (s *Strategy) generateOrders(ctx context.Context, kline types.KLine) ([]typ
|
|||
|
||||
// 止盈订单类型
|
||||
profitOrderType := types.OrderTypeTakeProfitMarket
|
||||
// 止损订单类型
|
||||
lossOrderType := types.OrderTypeStopMarket
|
||||
if s.ProfitOrderType == 1 {
|
||||
profitOrderType = types.OrderTypeStopMarket
|
||||
}
|
||||
|
||||
if qbtrade.IsBackTesting {
|
||||
profitOrderType = types.OrderTypeStopLimit
|
||||
lossOrderType = types.OrderTypeStopLimit
|
||||
}
|
||||
|
||||
// 计算止损止盈价格,以ATR为基准或者固定百分比
|
||||
lossPrice := fixedpoint.Zero
|
||||
profitPrice := fixedpoint.Zero
|
||||
|
@ -267,7 +285,7 @@ func (s *Strategy) generateOrders(ctx context.Context, kline types.KLine) ([]typ
|
|||
s.ShortLossOrder[symbol] = types.SubmitOrder{
|
||||
Symbol: symbol,
|
||||
Side: types.SideTypeBuy,
|
||||
Type: types.OrderTypeStopMarket,
|
||||
Type: lossOrderType,
|
||||
PositionSide: types.PositionSideTypeShort,
|
||||
StopPrice: lossPrice,
|
||||
TimeInForce: types.TimeInForceGTC,
|
||||
|
@ -300,7 +318,7 @@ func (s *Strategy) generateOrders(ctx context.Context, kline types.KLine) ([]typ
|
|||
s.LongLossOrder[symbol] = types.SubmitOrder{
|
||||
Symbol: symbol,
|
||||
Side: types.SideTypeSell,
|
||||
Type: types.OrderTypeStopMarket,
|
||||
Type: lossOrderType,
|
||||
PositionSide: types.PositionSideTypeLong,
|
||||
StopPrice: lossPrice,
|
||||
TimeInForce: types.TimeInForceGTC,
|
||||
|
@ -394,6 +412,38 @@ func (s *Strategy) notifyProfit(ctx context.Context, symbol string) {
|
|||
qbtrade.Notify(fmt.Sprintf("总交易次数:%v, 总收益:%v, 总手续费:%v, 盈利次数:%v, 亏损次数:%v",
|
||||
s.TotalOrderCount, s.TotalProfit.Float64(), s.TotalFree.Float64(), s.TotalProfitCount, s.TotalLossCount))
|
||||
}
|
||||
|
||||
// isTradeTime 是否交易时间
|
||||
func (s *Strategy) isTradeTime(ctx context.Context) bool {
|
||||
// 如果时间一致则表示不限制交易时间
|
||||
if s.TradeEndHour == s.TradeStartHour {
|
||||
return true
|
||||
}
|
||||
location, err := time.LoadLocation("Asia/Shanghai")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
now := time.Now().In(location)
|
||||
|
||||
hour := now.Hour()
|
||||
return hour >= s.TradeStartHour && hour < s.TradeEndHour
|
||||
}
|
||||
|
||||
func (s *Strategy) isPauseTrade(ctx context.Context) bool {
|
||||
// 被暂停次数不为0,且最近一次的暂停时间和今天一致,则表示暂停
|
||||
if s.PauseTradeCount != fixedpoint.Zero && s.PauseTradeTime.Day() == time.Now().Day() {
|
||||
return true
|
||||
}
|
||||
// 总收益大于(暂停次数+1)*暂停亏损,则表示暂停
|
||||
if s.TotalProfit < s.PauseTradeLoss.Mul(s.PauseTradeCount.Add(fixedpoint.One)) {
|
||||
s.PauseTradeCount.Add(fixedpoint.One)
|
||||
s.PauseTradeTime = time.Now()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor, session *qbtrade.ExchangeSession) error {
|
||||
|
||||
s.ExchangeSession = session
|
||||
|
@ -427,6 +477,8 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor,
|
|||
s.TotalOrderCount = 0
|
||||
s.TotalProfitCount = 0
|
||||
s.TotalLossCount = 0
|
||||
s.PauseTradeCount = fixedpoint.Zero
|
||||
s.PauseTradeTime = time.Now().Add(-24 * time.Hour)
|
||||
|
||||
for _, symbol := range s.Symbols {
|
||||
s.Positions[symbol] = types.NewPositionFromMarket(s.markets[symbol])
|
||||
|
@ -481,6 +533,15 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor,
|
|||
if s.Traded[sym] {
|
||||
return
|
||||
}
|
||||
|
||||
if !s.isTradeTime(ctx) || s.isPauseTrade(ctx) {
|
||||
pauseMsg := fmt.Sprintf("暂停交易:总收益:%v, 暂停次数:%v, 暂停时间:%v; 暂停时间段:[%v, %v)",
|
||||
s.TotalProfit.Float64(), s.PauseTradeCount.Float64(), s.PauseTradeTime, s.TradeStartHour,
|
||||
s.TradeEndHour)
|
||||
qbtrade.Notify(pauseMsg)
|
||||
return
|
||||
}
|
||||
|
||||
cciV := s.cci[sym].Last(0)
|
||||
if cciV <= s.LongCCI.Float64() {
|
||||
s.TradeType[sym] = "long"
|
||||
|
|
Loading…
Reference in New Issue
Block a user