|
|
@@ -14,9 +14,18 @@ const holdingHandler = async function(context, task, token, pair) {
|
|
|
const binanceSpot = context.binanceSpot
|
|
|
const accountAssetMap = context.accountAssetMap
|
|
|
|
|
|
+ const nowTimestamp = new Date().getTime()
|
|
|
// 这两个逻辑只有可能满足一个
|
|
|
- let isStopWin = token.BinancePrice > (token.orderPrice * (100 + config.stopWinPercentage) / 100)
|
|
|
- let isStopLoss = token.BinancePrice < (token.orderPrice * (100 - config.stopLossPercentage) / 100)
|
|
|
+ const isHardStopWin = token.BinancePrice > (token.orderPrice * (100 + config.hardStopWinPercentage) / 100)
|
|
|
+ const isTimeOverStopWin = token.BinancePrice > token.orderPrice && nowTimestamp > token.orderTime + config.stopWinTimeOverHours * TimeKit.ONE_HOUR
|
|
|
+
|
|
|
+ const isHardStopLoss = token.BinancePrice < (token.orderPrice * (100 - config.hardStopLossPercentage) / 100)
|
|
|
+ const isTimeOverStopLoss = token.BinancePrice < token.orderPrice && nowTimestamp < token.orderTime + config.stopLossTimeOverHours * TimeKit.ONE_HOUR
|
|
|
+
|
|
|
+ const isStopWin = isHardStopWin || isTimeOverStopWin
|
|
|
+ const isStopLoss = isHardStopLoss || isTimeOverStopLoss
|
|
|
+
|
|
|
+ const isTimeOverStop = isTimeOverStopWin || isTimeOverStopLoss
|
|
|
|
|
|
assert.notEqual(isStopWin && isStopLoss, true, '止盈止损逻辑错误,请认真检查。')
|
|
|
|
|
|
@@ -26,7 +35,7 @@ const holdingHandler = async function(context, task, token, pair) {
|
|
|
|
|
|
token.orderPrice = undefined
|
|
|
token.orderAmount = undefined
|
|
|
- token.nextHandleTime = new Date().getTime() + config.stopLossHandleSpaceHours * (60 * 60 * 1000)
|
|
|
+ token.nextHandleTime = nowTimestamp + config.stopLossHandleSpaceHours * TimeKit.ONE_HOUR
|
|
|
|
|
|
try {
|
|
|
const sellMarketRst = await binanceSpot.sellMarket(pair, orderAmount)
|
|
|
@@ -37,11 +46,11 @@ const holdingHandler = async function(context, task, token, pair) {
|
|
|
// 交易数据持久化
|
|
|
await token.save()
|
|
|
|
|
|
- fileLogger.info(`[${isStopWin ? '盈+' : '损-'}]${pair}, `
|
|
|
+ fileLogger.info(`[${isTimeOverStop ? '时' : '强'}${isStopWin ? '盈+' : '损-'}]${pair}, `
|
|
|
.concat(`成交额${cummulativeQuoteQty}, 均价${orderPrice}->${price}, 卖出${orderAmount}个.`)
|
|
|
)
|
|
|
} catch (e) {
|
|
|
- fileLogger.error(`[止${isStopWin ? '盈' : '损'}失败]${pair}, ${e}`)
|
|
|
+ fileLogger.error(`[${isTimeOverStop ? '时' : '强'}止${isStopWin ? '盈' : '损'}失败]${pair}, ${e}`)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -52,13 +61,15 @@ const noHoldingHandler = async function(context, task, token, pair) {
|
|
|
const binanceSpot = context.binanceSpot
|
|
|
const accountAssetMap = context.accountAssetMap
|
|
|
|
|
|
+ const nowTimestamp = new Date().getTime()
|
|
|
+
|
|
|
// 1. 获取base资产数量
|
|
|
const baseAssetAmount = accountAssetMap[config.baseIerc20Token.symbol]
|
|
|
|
|
|
// 2. 判断余额是否够下单
|
|
|
if (config.baseTokenAmount > baseAssetAmount) {
|
|
|
fileLogger.info(`[余额不足]${pair}, 需要: ${config.baseTokenAmount}, 剩余: ${baseAssetAmount}.`)
|
|
|
- token.nextHandleTime = new Date().getTime() + config.stopLossHandleSpaceHours * (60 * 60 * 1000)
|
|
|
+ token.nextHandleTime = nowTimestamp + config.stopLossHandleSpaceHours * TimeKit.ONE_HOUR
|
|
|
|
|
|
return
|
|
|
}
|
|
|
@@ -70,6 +81,7 @@ const noHoldingHandler = async function(context, task, token, pair) {
|
|
|
token.cummulativeQuoteQty = NumKit.getSubFloat(buyMarketRst.cummulativeQuoteQty, 6)
|
|
|
token.orderAmount = NumKit.getSubFloat(buyMarketRst.executedQty, token.exchange.lotSize)
|
|
|
token.orderPrice = NumKit.getSubFloat(buyMarketRst.avgPrice, token.exchange.priceTick)
|
|
|
+ token.orderTime = nowTimestamp
|
|
|
|
|
|
// 关键数据持久化
|
|
|
await token.save()
|
|
|
@@ -133,7 +145,7 @@ const showInfo = function(context, task) {
|
|
|
const rows = [pair.toString(), OneInchPrice.toString(), BinancePrice.toString(),
|
|
|
orderPrice.toString(), orderPercentage.toString(), nextTimeStr]
|
|
|
|
|
|
- // 识别到在拉盘
|
|
|
+ // 入场信号
|
|
|
token.isLong = (() => {
|
|
|
const percentageCondition = percentage > config.percentageLimit
|
|
|
|