Selaa lähdekoodia

上线测试买入卖出

龚成明 2 vuotta sitten
vanhempi
commit
49cdac3f87
4 muutettua tiedostoa jossa 82 lisäystä ja 23 poistoa
  1. 4 4
      libs/binance/binance-spot.js
  2. 1 0
      libs/context.js
  3. 2 0
      libs/one-task.js
  4. 75 19
      scripts/one-pro.js

+ 4 - 4
libs/binance/binance-spot.js

@@ -143,9 +143,9 @@ class BinanceSpot {
     return rst
   }
 
-  async buy(symbol, price, quoteOrderQty, type=BinanceSpot.TRADE_TYPE.MARKET) {
+  async buy(pair, price, quoteOrderQty, type=BinanceSpot.TRADE_TYPE.MARKET) {
     return await this.takeOrder(
-      symbol,
+      pair,
       price,
       BinanceSpot.TRADE_SIDE.BUY,
       0,
@@ -153,9 +153,9 @@ class BinanceSpot {
       type)
   }
 
-  async sell(symbol, price, quantity, type=BinanceSpot.TRADE_TYPE.MARKET) {
+  async sell(pair, price, quantity, type=BinanceSpot.TRADE_TYPE.MARKET) {
     return await this.takeOrder(
-      symbol,
+      pair,
       price,
       BinanceSpot.TRADE_SIDE.SELL,
       quantity,

+ 1 - 0
libs/context.js

@@ -1,4 +1,5 @@
 module.exports = class Context {
   tokenMap
   accountAssetMap
+  binanceSpot
 }

+ 2 - 0
libs/one-task.js

@@ -4,9 +4,11 @@ const Config = require("../config/config");
 const BinanceSpot = require("./binance/binance-spot");
 const IERC20 = require("./web3/ierc20-token");
 const Token = require("./token");
+const PrivateConfig = require("../PrivateConfig")
 
 OneTask.baseInit = async function() {
   this.context = new Context()
+  this.context.binanceSpot = new BinanceSpot(PrivateConfig.binanceAPIKey, PrivateConfig.binanceSecretKey)
 
   const pairs = Object.values(Config.tokenMapping).map(coin => `${coin}${Config.baseIerc20Token.symbol}` )
   const exchangeInfo = await BinanceSpot.exchangeInfo(pairs)

+ 75 - 19
scripts/one-pro.js

@@ -5,52 +5,101 @@ const Config = require('../config/config')
 const NumKit = require('../kit/num-kit')
 const TimeKit = require('../kit/time-kit')
 const TableKit = require('../kit/table-kit')
+const BinanceKit = require("../libs/binance/binance-kit");
 
-const orderHandler = function(context, task) {
+const orderHandler = async function(context, task) {
   const fileLogger = task.fileLogger
   const tokenMap = context.tokenMap
+  const binanceSpot = context.binanceSpot
+  const accountAssetMap = context.accountAssetMap
 
   // 逐对处理交易信息
-  Object.keys(tokenMap).forEach((tokenHash) => {
+  for (const tokenHash of Object.keys(tokenMap)) {
     const token = tokenMap[tokenHash]
     const pair = token.exchange.pair
 
     // 价格非法判定
-    if (!token.BinancePrice || !token.OneInchPrice) return
+    if (!token.BinancePrice || !token.OneInchPrice) continue;
 
     // 卖出逻辑判定
     if (token.orderPrice) {
-      // TODO 对接卖出交易
       if (token.BinancePrice > token.orderPrice) {
         // 止盈逻辑
         const isStopWin = token.BinancePrice > (token.orderPrice * (100 + Config.stopWinPercentage) / 100)
         if (isStopWin) {
-          fileLogger.info(`[止盈]${pair}, price: ${token.orderPrice}->${token.BinancePrice}, amount: ${token.orderAmount}.`)
-          token.orderPrice = undefined
-          token.nextHandleTime = new Date().getTime() + Config.stopWinHandleSpaceHours * (60 * 60 * 1000)
+          const sellRst = await binanceSpot.sell(pair, -1, token.orderAmount)
+
+          if (sellRst.executedQty) {
+            const cummulativeQuoteQty = NumKit.getSubFloat(sellRst.cummulativeQuoteQty, 6)
+            const executedQty = NumKit.getSubFloat(sellRst.executedQty, token.exchange.lotSize)
+            const price = cummulativeQuoteQty / executedQty
+
+            fileLogger.info(`[止盈]${pair}, price: ${token.orderPrice}->${price}, amount: ${token.orderAmount}.`)
+            token.orderPrice = undefined
+            token.nextHandleTime = new Date().getTime() + Config.stopWinHandleSpaceHours * (60 * 60 * 1000)
+
+            fileLogger.info(`[订单]${pair}, volume:${cummulativeQuoteQty}, 买入${executedQty}, 均价${token.orderPrice}.`)
+          } else {
+            token.orderPrice = undefined
+            token.nextHandleTime = new Date().getTime() + Config.stopWinHandleSpaceHours * (60 * 60 * 1000)
+
+            fileLogger.error(`[止盈失败]${pair}, ${JSON.stringify(sellRst)}`)
+          }
         }
       } else {
         // 止损逻辑
         const isStopLoss = token.BinancePrice < (token.orderPrice * (100 - Config.stopLossPercentage) / 100)
         if (isStopLoss) {
-          fileLogger.info(`[止损]${pair}, price: ${token.orderPrice}->${token.BinancePrice}, amount: ${token.orderAmount}.`)
-          token.orderPrice = undefined
-          token.nextHandleTime = new Date().getTime() + Config.stopLossHandleSpaceHours * (60 * 60 * 1000)
+          const sellRst = await binanceSpot.sell(pair, -1, token.orderAmount)
+
+          if (sellRst.executedQty) {
+            const cummulativeQuoteQty = NumKit.getSubFloat(sellRst.cummulativeQuoteQty, 6)
+            const executedQty = NumKit.getSubFloat(sellRst.executedQty, token.exchange.lotSize)
+            const price = cummulativeQuoteQty / executedQty
+
+            fileLogger.info(`[止损]${pair}, price: ${token.orderPrice}->${price}, amount: ${token.orderAmount}.`)
+            token.orderPrice = undefined
+            token.nextHandleTime = new Date().getTime() + Config.stopLossHandleSpaceHours * (60 * 60 * 1000)
+
+            fileLogger.info(`[订单]${pair}, volume:${cummulativeQuoteQty}, 买入${executedQty}, 均价${token.orderPrice}.`)
+          } else {
+            token.orderPrice = undefined
+            token.nextHandleTime = new Date().getTime() + Config.stopLossHandleSpaceHours * (60 * 60 * 1000)
+
+            fileLogger.error(`[止损失败]${pair}, ${JSON.stringify(sellRst)}`)
+          }
         }
       }
     } else if (token.isLong) {
-      // TODO 对接买入交易
-      token.orderBaseAmount = Config.baseTokenAmount
-
       // 1. 获取base资产数量
+      const baseAssetAmount = accountAssetMap[Config.baseIerc20Token.symbol]
+
+      // 判断余额是否够下单
+      if (Config.baseTokenAmount > baseAssetAmount) {
+        fileLogger.info(`[下单失败]${pair}, volume: ${Config.baseTokenAmount}, asset: ${baseAssetAmount}.`)
+        token.nextHandleTime = new Date().getTime() + Config.stopLossHandleSpaceHours * (60 * 60 * 1000)
+
+        continue;
+      }
+
       // 2. 下单获取成交数量以及平均价格
-      token.orderPrice = token.BinancePrice
-      token.orderAmount = NumKit.getSubFloat(Config.baseTokenAmount / token.orderPrice, token.exchange.lotSize)
+      const buyRst = await binanceSpot.buy(pair, -1, Config.baseTokenAmount)
+
+      if (buyRst.executedQty) {
+        const cummulativeQuoteQty = NumKit.getSubFloat(buyRst.cummulativeQuoteQty, 6)
+        const executedQty = NumKit.getSubFloat(buyRst.executedQty, token.exchange.lotSize)
 
-      // 3. 下单成功后打印日志
-      fileLogger.info(`[订单]${pair}, volume: ${Config.baseTokenAmount}, price: ${token.orderPrice}, amount: ${token.orderAmount}.`)
+        token.orderAmount = executedQty
+        token.orderPrice = cummulativeQuoteQty / executedQty
+
+        fileLogger.info(`[订单]${pair}, volume:${cummulativeQuoteQty}, 买入${executedQty}, 均价${token.orderPrice}.`)
+
+        accountAssetMap[Config.baseIerc20Token.symbol] = accountAssetMap[Config.baseIerc20Token.symbol] - cummulativeQuoteQty
+      } else {
+        fileLogger.error(`[下单失败]${JSON.stringify(buyRst)}`)
+      }
     }
-  })
+  }
 }
 
 const table = new TableKit(['pair', '1inch', 'binance', 'order price', 'profit(%)', 'next time'], 20)
@@ -123,16 +172,23 @@ const priceHandler = async function(context, task) {
   }
 }
 
+const accountHandler = async function(context, task) {
+  const accountInfoRst = await context.binanceSpot.accountInfo()
+  context.accountAssetMap = BinanceKit.parseBalancesToAccountAssetMap(accountInfoRst.balances)
+}
+
 const onTickFun = async function() {
   const task = this
   const context = task.context
 
   // 搜集所有价格数据
   await priceHandler(context, task)
+  // 获取账户数据
+  await accountHandler(context, task)
   // 展示关键信息
   showInfo(context, task)
   // 交易、订单处理
-  orderHandler(context, task)
+  await orderHandler(context, task)
 }
 
 const onePro = new OneTask('OnePro', Config.delay, OneTask.baseInit, onTickFun)