atr计算止盈止损价格
This commit is contained in:
parent
f83998420f
commit
13481332fe
|
@ -17,14 +17,14 @@ exchangeStrategies:
|
||||||
ccinr:
|
ccinr:
|
||||||
symbols:
|
symbols:
|
||||||
- ARUSDT
|
- ARUSDT
|
||||||
# - BNBUSDT
|
|
||||||
# - BTCUSDT
|
|
||||||
# - ETHUSDT
|
|
||||||
- ORDIUSDT
|
- ORDIUSDT
|
||||||
- OPUSDT
|
- OPUSDT
|
||||||
- OMUSDT
|
- OMUSDT
|
||||||
# - SOLUSDT
|
|
||||||
- WIFUSDT
|
- WIFUSDT
|
||||||
|
# - BNBUSDT
|
||||||
|
# - BTCUSDT
|
||||||
|
# - ETHUSDT
|
||||||
|
# - SOLUSDT
|
||||||
# - DYDXUSDT
|
# - DYDXUSDT
|
||||||
# - XRPUSDT
|
# - XRPUSDT
|
||||||
# - PEOPLEUSDT
|
# - PEOPLEUSDT
|
||||||
|
@ -36,18 +36,23 @@ exchangeStrategies:
|
||||||
# - NOTUSDT
|
# - NOTUSDT
|
||||||
# - ENSUSDT
|
# - ENSUSDT
|
||||||
interval: 1m
|
interval: 1m
|
||||||
|
nrInterval: 5m
|
||||||
|
cciInterval: 15m
|
||||||
|
atrInterval: 1h
|
||||||
|
nrCount: 4
|
||||||
|
cciWindow: 20
|
||||||
|
atrWindow: 14
|
||||||
symbol: ARUSDT
|
symbol: ARUSDT
|
||||||
dryRun: false
|
dryRun: false
|
||||||
nrCount: 4
|
|
||||||
strictMode: true
|
strictMode: true
|
||||||
cciWindow: 20
|
longCCI: -180.0
|
||||||
longCCI: -150.0
|
shortCCI: 180.0
|
||||||
shortCCI: 150.0
|
|
||||||
leverage: 5.0
|
leverage: 5.0
|
||||||
profitRange: 0.4%
|
profitRange: 5%
|
||||||
lossRange: 1%
|
lossRange: 1%
|
||||||
amount: 20
|
amount: 20
|
||||||
placePriceType: 0
|
placePriceType: 2
|
||||||
|
lossType: 1
|
||||||
# recalculate: false
|
# recalculate: false
|
||||||
# dry_run: false
|
# dry_run: false
|
||||||
# # quantity: 3
|
# # quantity: 3
|
||||||
|
|
|
@ -30,11 +30,16 @@ type Strategy struct {
|
||||||
|
|
||||||
Symbols []string `json:"symbols"`
|
Symbols []string `json:"symbols"`
|
||||||
Interval types.Interval `json:"interval"`
|
Interval types.Interval `json:"interval"`
|
||||||
|
NRInterval types.Interval `json:"nrInterval"`
|
||||||
|
CCIInterval types.Interval `json:"cciInterval"`
|
||||||
|
ATRInterval types.Interval `json:"atrInterval"`
|
||||||
NrCount int `json:"nrCount"`
|
NrCount int `json:"nrCount"`
|
||||||
StrictMode bool `json:"strictMode"`
|
StrictMode bool `json:"strictMode"`
|
||||||
PlacePriceType int `json:"placePriceType"`
|
PlacePriceType int `json:"placePriceType"`
|
||||||
|
LossType int `json:"lossType"`
|
||||||
DryRun bool `json:"dryRun"`
|
DryRun bool `json:"dryRun"`
|
||||||
CCIWindow int `json:"cciWindow"`
|
CCIWindow int `json:"cciWindow"`
|
||||||
|
ATRWindow int `json:"atrWindow"`
|
||||||
LongCCI fixedpoint.Value `json:"longCCI"`
|
LongCCI fixedpoint.Value `json:"longCCI"`
|
||||||
ShortCCI fixedpoint.Value `json:"shortCCI"`
|
ShortCCI fixedpoint.Value `json:"shortCCI"`
|
||||||
Leverage fixedpoint.Value `json:"leverage"`
|
Leverage fixedpoint.Value `json:"leverage"`
|
||||||
|
@ -73,10 +78,13 @@ type Strategy struct {
|
||||||
|
|
||||||
nr map[string]*indicatorv2.NRStrean
|
nr map[string]*indicatorv2.NRStrean
|
||||||
cci map[string]*indicatorv2.CCIStream
|
cci map[string]*indicatorv2.CCIStream
|
||||||
|
atr map[string]*indicatorv2.ATRStream
|
||||||
|
|
||||||
TotalProfit fixedpoint.Value
|
TotalProfit fixedpoint.Value
|
||||||
TotalFree fixedpoint.Value
|
TotalFree fixedpoint.Value
|
||||||
TotalOrderCount int
|
TotalOrderCount int
|
||||||
|
TotalProfitCount int
|
||||||
|
TotalLossCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) ID() string {
|
func (s *Strategy) ID() string {
|
||||||
|
@ -86,6 +94,9 @@ func (s *Strategy) ID() string {
|
||||||
func (s *Strategy) Subscribe(session *qbtrade.ExchangeSession) {
|
func (s *Strategy) Subscribe(session *qbtrade.ExchangeSession) {
|
||||||
for _, symbol := range s.Symbols {
|
for _, symbol := range s.Symbols {
|
||||||
session.Subscribe(types.KLineChannel, symbol, types.SubscribeOptions{Interval: s.Interval})
|
session.Subscribe(types.KLineChannel, symbol, types.SubscribeOptions{Interval: s.Interval})
|
||||||
|
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})
|
||||||
session.Subscribe(types.MarketTradeChannel, symbol, types.SubscribeOptions{})
|
session.Subscribe(types.MarketTradeChannel, symbol, types.SubscribeOptions{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,10 +200,32 @@ func (s *Strategy) generateOrders(ctx context.Context, kline types.KLine) ([]typ
|
||||||
// 获取下单价格
|
// 获取下单价格
|
||||||
placePrice := s.getPlacePrice(ctx, kline)
|
placePrice := s.getPlacePrice(ctx, kline)
|
||||||
|
|
||||||
|
// 计算止损止盈价格,以ATR为基准或者固定百分比
|
||||||
|
lossPrice := fixedpoint.Value(0)
|
||||||
|
profitPrice := fixedpoint.Value(0)
|
||||||
|
lastATR := s.atr[symbol].Last(0)
|
||||||
|
if s.TradeType[symbol] == "long" {
|
||||||
|
if s.LossType == 0 {
|
||||||
|
lossPrice = placePrice.Sub(placePrice.Mul(s.LossRange))
|
||||||
|
profitPrice = placePrice.Add(placePrice.Mul(s.ProfitRange))
|
||||||
|
} else if s.LossType == 1 {
|
||||||
|
lossPrice = placePrice.Sub(fixedpoint.Value(lastATR))
|
||||||
|
profitPrice = placePrice.Add(fixedpoint.Value(lastATR * 2))
|
||||||
|
}
|
||||||
|
} else if s.TradeType[symbol] == "short" {
|
||||||
|
if s.LossType == 0 {
|
||||||
|
lossPrice = placePrice.Add(placePrice.Mul(s.LossRange))
|
||||||
|
profitPrice = placePrice.Sub(placePrice.Mul(s.ProfitRange))
|
||||||
|
} else if s.LossType == 1 {
|
||||||
|
lossPrice = placePrice.Add(fixedpoint.Value(lastATR))
|
||||||
|
profitPrice = placePrice.Sub(fixedpoint.Value(lastATR * 2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 下单数量
|
// 下单数量
|
||||||
placeQuantity := s.QuantityOrAmount.CalculateQuantity(placePrice).Mul(s.Leverage)
|
placeQuantity := s.QuantityOrAmount.CalculateQuantity(placePrice).Mul(s.Leverage)
|
||||||
log.Infof(fmt.Sprintf("will place order, price %v, quantity %v", placePrice.Float64(),
|
log.Infof(fmt.Sprintf("will place order, price %v, quantity %v, lossprice %v, profitprice: %v",
|
||||||
placeQuantity.Float64()))
|
placePrice.Float64(), placeQuantity.Float64(), lossPrice.Float64(), profitPrice.Float64()))
|
||||||
|
|
||||||
s.ShortOrder[symbol] = types.SubmitOrder{
|
s.ShortOrder[symbol] = types.SubmitOrder{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
|
@ -208,9 +241,9 @@ func (s *Strategy) generateOrders(ctx context.Context, kline types.KLine) ([]typ
|
||||||
s.ShortProfitOrder[symbol] = types.SubmitOrder{
|
s.ShortProfitOrder[symbol] = types.SubmitOrder{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
Side: types.SideTypeBuy,
|
Side: types.SideTypeBuy,
|
||||||
Type: types.OrderTypeTakeProfitMarket,
|
Type: types.OrderTypeStopMarket,
|
||||||
PositionSide: types.PositionSideTypeShort,
|
PositionSide: types.PositionSideTypeShort,
|
||||||
StopPrice: placePrice.Sub(placePrice.Mul(s.ProfitRange)),
|
StopPrice: profitPrice,
|
||||||
TimeInForce: types.TimeInForceGTC,
|
TimeInForce: types.TimeInForceGTC,
|
||||||
Market: s.Market,
|
Market: s.Market,
|
||||||
ClosePosition: true,
|
ClosePosition: true,
|
||||||
|
@ -221,7 +254,7 @@ func (s *Strategy) generateOrders(ctx context.Context, kline types.KLine) ([]typ
|
||||||
Side: types.SideTypeBuy,
|
Side: types.SideTypeBuy,
|
||||||
Type: types.OrderTypeStopMarket,
|
Type: types.OrderTypeStopMarket,
|
||||||
PositionSide: types.PositionSideTypeShort,
|
PositionSide: types.PositionSideTypeShort,
|
||||||
StopPrice: placePrice.Add(placePrice.Mul(s.LossRange)),
|
StopPrice: lossPrice,
|
||||||
TimeInForce: types.TimeInForceGTC,
|
TimeInForce: types.TimeInForceGTC,
|
||||||
Market: s.Market,
|
Market: s.Market,
|
||||||
ClosePosition: true,
|
ClosePosition: true,
|
||||||
|
@ -241,9 +274,9 @@ func (s *Strategy) generateOrders(ctx context.Context, kline types.KLine) ([]typ
|
||||||
s.LongProfitOrder[symbol] = types.SubmitOrder{
|
s.LongProfitOrder[symbol] = types.SubmitOrder{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
Side: types.SideTypeSell,
|
Side: types.SideTypeSell,
|
||||||
Type: types.OrderTypeTakeProfitMarket,
|
Type: types.OrderTypeStopMarket,
|
||||||
PositionSide: types.PositionSideTypeLong,
|
PositionSide: types.PositionSideTypeLong,
|
||||||
StopPrice: placePrice.Add(placePrice.Mul(s.ProfitRange)),
|
StopPrice: profitPrice,
|
||||||
TimeInForce: types.TimeInForceGTC,
|
TimeInForce: types.TimeInForceGTC,
|
||||||
Market: s.Market,
|
Market: s.Market,
|
||||||
ClosePosition: true,
|
ClosePosition: true,
|
||||||
|
@ -254,7 +287,7 @@ func (s *Strategy) generateOrders(ctx context.Context, kline types.KLine) ([]typ
|
||||||
Side: types.SideTypeSell,
|
Side: types.SideTypeSell,
|
||||||
Type: types.OrderTypeStopMarket,
|
Type: types.OrderTypeStopMarket,
|
||||||
PositionSide: types.PositionSideTypeLong,
|
PositionSide: types.PositionSideTypeLong,
|
||||||
StopPrice: placePrice.Sub(placePrice.Mul(s.LossRange)),
|
StopPrice: lossPrice,
|
||||||
TimeInForce: types.TimeInForceGTC,
|
TimeInForce: types.TimeInForceGTC,
|
||||||
Market: s.Market,
|
Market: s.Market,
|
||||||
ClosePosition: true,
|
ClosePosition: true,
|
||||||
|
@ -325,6 +358,11 @@ func (s *Strategy) notifyProfit(ctx context.Context, symbol string) {
|
||||||
s.TotalProfit = s.TotalProfit.Add(profit)
|
s.TotalProfit = s.TotalProfit.Add(profit)
|
||||||
s.TotalFree = s.TotalFree.Add(free)
|
s.TotalFree = s.TotalFree.Add(free)
|
||||||
s.TotalOrderCount += 1
|
s.TotalOrderCount += 1
|
||||||
|
if profit > fixedpoint.Value(0) {
|
||||||
|
s.TotalProfitCount += 1
|
||||||
|
} else {
|
||||||
|
s.TotalLossCount += 1
|
||||||
|
}
|
||||||
|
|
||||||
log.Infof(msg)
|
log.Infof(msg)
|
||||||
qbtrade.Notify(msg)
|
qbtrade.Notify(msg)
|
||||||
|
@ -338,7 +376,8 @@ func (s *Strategy) notifyProfit(ctx context.Context, symbol string) {
|
||||||
// 记得取消订单
|
// 记得取消订单
|
||||||
s.cancelOrders(ctx, symbol)
|
s.cancelOrders(ctx, symbol)
|
||||||
|
|
||||||
qbtrade.Notify(fmt.Sprintf("总开仓:%v, 总收益:%v, 总手续费:%v", s.TotalOrderCount, s.TotalProfit.Float64(), s.TotalFree.Float64()))
|
qbtrade.Notify(fmt.Sprintf("总交易次数:%v, 总收益:%v, 总手续费:%v, 盈利次数:%v, 亏损次数:%v",
|
||||||
|
s.TotalOrderCount, s.TotalProfit.Float64(), s.TotalFree.Float64(), s.TotalProfitCount, s.TotalLossCount))
|
||||||
}
|
}
|
||||||
func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor, session *qbtrade.ExchangeSession) error {
|
func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor, session *qbtrade.ExchangeSession) error {
|
||||||
|
|
||||||
|
@ -366,10 +405,13 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor,
|
||||||
|
|
||||||
s.nr = make(map[string]*indicatorv2.NRStrean)
|
s.nr = make(map[string]*indicatorv2.NRStrean)
|
||||||
s.cci = make(map[string]*indicatorv2.CCIStream)
|
s.cci = make(map[string]*indicatorv2.CCIStream)
|
||||||
|
s.atr = make(map[string]*indicatorv2.ATRStream)
|
||||||
|
|
||||||
s.TotalProfit = fixedpoint.Value(0)
|
s.TotalProfit = fixedpoint.Value(0)
|
||||||
s.TotalFree = fixedpoint.Value(0)
|
s.TotalFree = fixedpoint.Value(0)
|
||||||
s.TotalOrderCount = 0
|
s.TotalOrderCount = 0
|
||||||
|
s.TotalProfitCount = 0
|
||||||
|
s.TotalLossCount = 0
|
||||||
|
|
||||||
for _, symbol := range s.Symbols {
|
for _, symbol := range s.Symbols {
|
||||||
s.Positions[symbol] = types.NewPositionFromMarket(s.markets[symbol])
|
s.Positions[symbol] = types.NewPositionFromMarket(s.markets[symbol])
|
||||||
|
@ -392,18 +434,19 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor,
|
||||||
qbtrade.Notify("CCINR策略开始执行...")
|
qbtrade.Notify("CCINR策略开始执行...")
|
||||||
|
|
||||||
for _, symbol := range s.Symbols {
|
for _, symbol := range s.Symbols {
|
||||||
s.nr[symbol] = session.Indicators(symbol).NR(s.Interval, s.NrCount, s.StrictMode)
|
s.nr[symbol] = session.Indicators(symbol).NR(s.NRInterval, s.NrCount, s.StrictMode)
|
||||||
s.cci[symbol] = session.Indicators(symbol).CCI(s.Interval, s.CCIWindow)
|
s.cci[symbol] = session.Indicators(symbol).CCI(s.CCIInterval, s.CCIWindow)
|
||||||
|
s.atr[symbol] = session.Indicators(symbol).ATR(s.ATRInterval, s.ATRWindow)
|
||||||
s.TradeRetry[symbol] = 0
|
s.TradeRetry[symbol] = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
session.MarketDataStream.OnKLineClosed(func(k types.KLine) {
|
session.MarketDataStream.OnKLineClosed(func(k types.KLine) {
|
||||||
for _, symbol := range s.Symbols {
|
for _, symbol := range s.Symbols {
|
||||||
if k.Symbol != symbol || k.Interval != s.Interval {
|
if k.Symbol != symbol {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.Traded[symbol] {
|
if !s.Traded[symbol] && k.Interval == s.NRInterval {
|
||||||
// 如若在下一根k线未成交 则取消订单
|
// 如若在下一根k线未成交 则取消订单
|
||||||
if s.TradeType[symbol] != "" && s.TradeRetry[symbol] > 1 {
|
if s.TradeType[symbol] != "" && s.TradeRetry[symbol] > 1 {
|
||||||
qbtrade.Notify(fmt.Sprintf("交易信号未成交,取消订单: %s", symbol))
|
qbtrade.Notify(fmt.Sprintf("交易信号未成交,取消订单: %s", symbol))
|
||||||
|
@ -431,9 +474,9 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor,
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
msg := fmt.Sprintf("交易信号:币种:%s, 方向 %s, 时间: %s, 最高价:%f,最低价:%f, CCI: %v",
|
msg := fmt.Sprintf("交易信号:币种:%s, 方向 %s, 时间: %s, 最高价:%f,最低价:%f, CCI: %v, ATR: %v",
|
||||||
sym, s.TradeType[sym], s.nr[sym].NrKLine.GetStartTime(), s.nr[sym].NrKLine.High.Float64(),
|
sym, s.TradeType[sym], s.nr[sym].NrKLine.GetStartTime(), s.nr[sym].NrKLine.High.Float64(),
|
||||||
s.nr[sym].NrKLine.Low.Float64(), cciV)
|
s.nr[sym].NrKLine.Low.Float64(), cciV, s.atr[sym].Last(0))
|
||||||
qbtrade.Notify(msg)
|
qbtrade.Notify(msg)
|
||||||
tk := s.nr[sym].NrKLine
|
tk := s.nr[sym].NrKLine
|
||||||
s.placeOrders(ctx, tk)
|
s.placeOrders(ctx, tk)
|
||||||
|
@ -479,6 +522,8 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor qbtrade.OrderExecutor,
|
||||||
log.Infof("the order is: %+v,id is %d, symbol is %s, type is %s, status is %s",
|
log.Infof("the order is: %+v,id is %d, symbol is %s, type is %s, status is %s",
|
||||||
order, order.OrderID, orderSymbol, order.Type, order.Status)
|
order, order.OrderID, orderSymbol, order.Type, order.Status)
|
||||||
}
|
}
|
||||||
|
} else if order.Status == types.OrderStatusCanceled {
|
||||||
|
log.Infof("canceled order %+v", order)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user