Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
T
ts-api-demo
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wmvm
ts-api-demo
Commits
5395fe73
Commit
5395fe73
authored
Oct 23, 2024
by
ml
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
统计项目方做市商成交量信息,并设置费率
parent
9c7aa18f
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
532 additions
and
3 deletions
+532
-3
task.market.maker.statis.service.ts
cron/service/task.market.maker.statis.service.ts
+530
-0
task_market_maker_statis.ts
cron/task/task_market_maker_statis.ts
+2
-3
No files found.
cron/service/
marketMakerMgr
.service.ts
→
cron/service/
task.market.maker.statis
.service.ts
View file @
5395fe73
/*
// 每日定时统计项目方 指定交易对做市信息, 并根据成交量信息进行费率分档优惠;
import
{
ormDB
,
commonUserFeeSetting
,
feeRateSpotLog
,
userInfoSon
,
spotPairs
,
contractPairs
,
userInfo
}
from
"@madex/ex-ts-dao"
;
//
import
{
FEE_RATE_LOG_STATUS
}
from
"../../src/constant/feeRateLogConst"
;
// 做市商 信息管理
//
import {
ormDB,
userInfoSon,
feeRateContractLog,
feeRateSpotLog,
commonUserFeeSetting,
contractPairs,
userInfo
} from "@madex/ex-ts-dao";
const Op = ormDB.Op;
let { resUtils, logger, datetimeUtils }= require('@madex/ex-js-public');
const user_info = userInfo.prototype;
let
Op
=
ormDB
.
Op
;
const market_maker = marketMaker.prototype;
let
{
tickerUtils
,
redisUtilsCommon
}
=
require
(
'@madex/ex-js-common'
);
const user_daily_trade = DAO.userDailyTrade.prototype;
let
user_info_son
=
userInfoSon
.
prototype
;
const contract_daily_fee = DAO.contractDailyFee.prototype;
let
user_info
=
userInfo
.
prototype
;
const ex_trade_detail_spot = DAO.exTradeDetailSpot.prototype;
const ex_kline = DAO.exKlineSpot.prototype;
const pairType = DAO.exPair.PAIR_TYPE;
const user_info_son = userInfoSon.prototype;
const
SonStatus
=
userInfoSon
.
STATUS
;
const
SonStatus
=
userInfoSon
.
STATUS
;
let feeRateSpotSer = require('./feeRateSpotLog.service');
let redis = require('../../redis/redis-client');
let redisUtilsCommon = require('../../redis/redis.utils');
let ticker = require('../../utils/ticker.utils.js')
const pairMgr = require('../../utils/expair.mgr');
const
logger
=
require
(
'@madex/ex-js-public'
).
logger
;
let
feeRateCheckStatus
=
FEE_RATE_LOG_STATUS
;
//对btc价格,缓存 {coinSymbol: priceInfo}
var
price2BTC
=
{};
//价格缓存时间 2分钟
const
CACHE_TIMEOUT
=
2
*
60
*
1000
;
const
DAY
=
24
*
3600
*
1000
;
const
DAY
=
24
*
3600
*
1000
;
const
FEE_MODEL
=
{
const
FEE_MODEL
=
{
"fixedingain"
:
"fixedingain"
"fixedingain"
:
"fixedingain"
}
}
const
BTC_AMOUNT
=
{
const
BTC_AMOUNT
=
{
"BTC30": 30,
"BTC30"
:
30
,
"BTC5": 5,
"BTC5"
:
5
,
"BTC0": 0,
"BTC0"
:
0
,
},
},
FEE_RATE = {
FEE_RATE
=
{
"Wan1"
:
0.0001
,
"Wan1"
:
0.0001
,
"Wan2"
:
0.0002
,
"Wan2"
:
0.0002
,
"Default"
:
0.001
,
"Default"
:
0.001
,
"maker_default":0.0008,
"maker_default"
:
0.0008
,
"Free"
:
0
,
"Free"
:
0
,
},
},
Market_Maker_FEE = {
Market_Maker_FEE
=
{
init_taker: 0.0002,
init_taker
:
0.0002
,
init_maker: 0,
init_maker
:
0
,
}
}
;
//对btc价格,缓存 {coinSymbol: priceInfo}
var price2BTC = {};
//价格缓存时间 2分钟
const CACHE_TIMEOUT = 2 * 60 * 1000;
/!**
* 与btc价格折算
*!/
let marketMakerService = {};
module.exports = marketMakerService;
const marketTypes = Object.values(marketMaker.MAKER_TYPE);
async
function
delayPromise
(
time
)
{
async
function
delayPromise
(
time
)
{
return
new
Promise
((
resolve
)
=>
setTimeout
(
resolve
,
time
));
return
new
Promise
((
resolve
)
=>
setTimeout
(
resolve
,
time
));
}
}
marketMakerService.add = async function (body) {
let _func_name = "marketMakerService.add";
let { user_id, maker_type, maker_name, maker_mgr } = body;
try {
let maker = await market_maker.findOne({
where: {
user_id: user_id,
maker_type: maker_type,
},
raw: true,
});
if (maker) {
return maker; // 存在该做市商 直接返回
}
let user = await user_info.findOne({
attributes: ['user_id'],
where: {
user_id: user_id
},
raw: true,
})
if (!user) throw '13215';
if (!marketTypes.includes(Number(maker_type))) {
throw '3000'
}
if (maker_name && maker_name.length > 250 || maker_mgr && maker_mgr.length > 250) {
throw '3000'
}
let res = await market_maker.create({
user_id: user_id,
maker_type: Number(maker_type),
maker_name,
maker_mgr
});
return res;
// resUtils.
} catch (error) {
logger.warn(_func_name, error)
throw error;
}
};
marketMakerService.update = async function (body) {
let _func_name = "marketMakerService.update";
let { user_id, maker_type, maker_name, maker_mgr } = body;
try {
if (!marketTypes.includes(maker_type)) {
throw '3000'
}
if (maker_name && maker_name.length > 250 || maker_mgr && maker_mgr.length > 250) {
throw '3000'
}
let maker = await market_maker.findOne({
where: {
user_id: user_id,
},
raw: true,
});
if (maker) {
await market_maker.update({
maker_type: maker_type,
maker_name,
maker_mgr
}, {
where: {
user_id: user_id
}
});
return "ok"
} else {
throw "1002"
}
} catch (error) {
logger.warn(_func_name, error)
throw error;
}
};
// 修改项目方做市交易对
marketMakerService.addProjectMakerPair = async function (body) {
let _func_name = "marketMakerService.updateProjectMaker";
let { user_id, pairArr, amount_require_btc, amount_require_usdt, statis_period } = body;
try {
if (!user_id || !Array.isArray(pairArr)) {
throw '3000'
}
amount_require_btc = parseFloat(amount_require_btc);
amount_require_usdt = parseFloat(amount_require_usdt);
statis_period = parseInt(statis_period);
if (isNaN(amount_require_btc) || amount_require_btc <= 0 || isNaN(amount_require_usdt) || amount_require_usdt <= 0 || isNaN(statis_period) || statis_period <= 0 || statis_period > 30) {
throw '3000';
}
let maker = await market_maker.findOne({
where: {
user_id: user_id,
},
raw: true,
});
let makerPairs = await marketMakerPair.prototype.findAll({
attributes: ['user_id', 'pair'],
where: {
user_id: user_id,
},
raw: true,
});
let hasPairs = [];
if (makerPairs.length > 0) {
for (let i = 0; i < makerPairs.length; i++) {
hasPairs.push(makerPairs[i].pair);
}
}
if (maker) {
if (maker.maker_type != marketMaker.MAKER_TYPE.PROJECT_MAKER) {
throw '3000'
}
let items = [], feeSetItems = [];
for (let i = 0; i < pairArr.length; i++) {
let pairObj = await pairMgr.getPair(pairArr[i]);
let { pair, pair_type } = pairObj;
if (pair_type != pairType.MAIN && pair_type != pairType.NEW) {
throw "3016"
}
if (hasPairs.includes(pair)) continue; //跳过已经添加对交易对;
let [coin_symbol, currency_symbol] = pair.split('_');
items.push({
user_id,
pair: pair,
coin_symbol: coin_symbol,
currency_symbol: currency_symbol,
status: 1,
amount_require_btc,
amount_require_usdt,
statis_period,
});
feeSetItems.push({
user_id, pair,
fee_model: "fixedingain",
maker_fee: 0,
taker_fee: 0,
beginAt: new Date(),
expireAt: new Date(Date.now() + statis_period * DAY),
is_check: 0,
comment: '项目上线项目方做市商费率设置',
}, {
user_id, pair,
fee_model: "fixedingain",
maker_fee: Market_Maker_FEE.init_maker,
taker_fee: Market_Maker_FEE.init_taker, //
beginAt: new Date(Date.now() + statis_period * DAY),
expireAt: new Date(Date.now() + 365 * DAY),
is_check: 0,
comment: '项目上线项目方做市商费率设置_到期配置',
});
}
if (items.length > 0) {
let mkps = await await marketMakerPair.prototype.bulkCreate(items);
await feeRateSpotLog.prototype.bulkCreate(feeSetItems);
return mkps;
} else {
throw '3000'
}
} else {
throw "1002"
}
} catch (error) {
logger.warn(_func_name, error)
throw error;
}
};
// 修改项目方做市交易对
marketMakerService.updateProjectMakePairStatus = async function (body) {
let _func_name = "marketMakerService.updateProjectMakePairStatus";
let { user_id, pair, status } = body;
try {
if (!user_id || !pair) {
throw '3000'
}
status = Number(status);
if(![0, 1].includes(status)){ //
throw '3000'
}
let makerPairs = await marketMakerPair.prototype.findOne({
attributes: ['id','user_id', 'pair'],
where: {
user_id: user_id,
pair: pair
},
raw: true,
});
if(!makerPairs) {
throw '1002';
}
await marketMakerPair.prototype.update({
status: status,
},{
where: {
id: makerPairs.id,
user_id: user_id,
pair: pair
}
});
return 'OK';
} catch (error) {
logger.warn(_func_name, error)
throw error;
}
};
// 删除 交易对
marketMakerService.removeMakerPair = async function (body) {
let {id, user_id, pair } = body;
if(!id || !user_id || !pair) {
throw '3000';
}
let condition = {
id: id,
user_id,
pair,
};
let one = await marketMakerPair.prototype.findOne({
attributes: ['user_id'],
where: condition,
raw: true,
})
if(one) {
return marketMakerPair.prototype.destroy({ where: condition });
} else {
throw '1002';
}
}
marketMakerService.findMarker = async function (user_id) {
let _func_name = "marketMakerService.add";
try {
let res = await market_maker.findOne({
where: {
user_id: user_id,
},
raw: true,
});
if (res) {
res.spotDiscount = [];
res.contractDiscount = [];
res.contractMakerDiscount = 0;
res.contractTakerDiscount = 0;
res.contractExpireAt = 0;
let [spotDiscount, contractDiscount] = await Promise.all([getSpotFeeRate(user_id), getContractFeeRate(user_id)]);
if (spotDiscount) {
res.spotDiscount = spotDiscount;
} if (contractDiscount) {
res.contractDiscount = contractDiscount;
// res.contractMakerDiscount = contractDiscount.maker_fee || 0;
// res.contractTakerDiscount = contractDiscount.taker_fee || 0;
// res.contractExpireAt = contractDiscount.expireAt;
}
} else {
throw '1002';
}
return res;
} catch (error) {
logger.warn(_func_name, error)
throw error;
}
};
marketMakerService.findMarkerList = async function (user_id, maker_type, page, size, callBack) {
let _func_name_ = "marketMakerService.findMarkerList";
let queryObj = {};
if(user_id) {
queryObj['user_id'] = user_id;
}
if(maker_type && marketTypes.includes(maker_type)) {
queryObj['maker_type'] = maker_type;
}
marketMaker.queryPage(queryObj, page, size, [["createdAt", "DESC"]], callBack, err => {
resUtils.dbFail1(err, _func_name_, 'findMarkerList', 'findMarkerList', callBack);
});
};
// 所有做市商成交量排行榜, 先按日期
marketMakerService.findMarkerDeals = async function (begin_time, end_time, makerType) {
let _func_name_ = 'marketMakerService.findMarkerDeals';
let redisKey = [];
if (!datetimeUtils.valid(end_time)) {
end_time = Date.now();
begin_time = end_time - DAY * 7;
}
begin_time = new Date(begin_time).getTime();
end_time = new Date(end_time).getTime();
if (end_time - begin_time >= DAY * 7) {
// throw '2083'; // 超过7天
begin_time = end_time - DAY * 7
}
let begin = begin_time - begin_time % DAY;//获取当天开始时间
let end = end_time - end_time % DAY;//获取当天开始时间
redisKey.push(begin, end);
let userIds = [];
if(Object.values(marketMaker.MAKER_TYPE).includes(makerType)) {
userIds = await getMakerUserID([makerType]);
} else {
userIds = await getMakerUserID();
}
redisKey = 'deal_' + redisKey.join('_');
let resultCache = await redisUtilsCommon.getSync(redisKey);
if (resultCache) {
return resultCache
}
return await Promise.race([delayPromise(5000), getMakerDeals(userIds, begin, end)]).then(dt => {
if (dt && dt.length > 0) {
redisUtilsCommon.writeSync(redisKey, JSON.stringify(dt), 60 * 60 * 4);
return dt;
} else {
throw '2116';
}
}).catch(err => {
logger.error('%s 错误 %s', _func_name_, err);
throw err;
});
};
// 获取指定做市商成交量排行榜, 先按日期
marketMakerService.findOneMarkerDeals = async function (user_id, begin_time, end_time) {
let _func_name_ = 'marketMakerService.findMarkerDeals';
let redisKey = [];
if (!datetimeUtils.valid(end_time)) {
end_time = Date.now();
begin_time = end_time - DAY * 7;
}
begin_time = new Date(begin_time).getTime();
end_time = new Date(end_time).getTime();
if (end_time - begin_time >= DAY * 31) {
// throw '2083'; // 超过7天
begin_time = end_time - DAY * 31
}
let begin = begin_time - begin_time % DAY;//获取当天开始时间
let end = end_time - end_time % DAY;//获取当天开始时间
let res = await market_maker.findOne({
where: {
user_id: user_id,
},
raw: true,
});
if (!res) {
throw "12200";
}
redisKey.push(user_id, begin, end);
redisKey = 'deal_one_' + redisKey.join('_');
let resultCache = await redisUtilsCommon.getSync(redisKey);
if (resultCache) {
return resultCache
}
return await Promise.race([delayPromise(5000), getMakerDeals([user_id], begin, end)]).then(dt => {
if (dt && dt.length > 0) {
let total = calcTotal(dt);
redisUtilsCommon.writeSync(redisKey, JSON.stringify(total), 60 * 60 * 12);
return total;
} else {
throw '2116';
}
}).catch(err => {
logger.error('%s 错误 %s', _func_name_, err);
throw err;
});
};
// 移除不活跃交易对, 将下线币种相关交易对删除
marketMakerService.removeOffLinePair = async function () {
let coin = new Set();
let allCoins = await marketMakerPair.prototype.findAll({
attributes: ['coin_symbol'],
raw: true,
group: ['coin_symbol'],
});
if(allCoins.length === 0) return 0;
for(let i = 0; i < allCoins.length; i++) {
coin.add(allCoins[i] && allCoins[i].coin_symbol);
}
if(coin.size < 1) return 0;
let activeCoin = await coinType.prototype.findAll({
attributes: ['is_active', 'symbol'],
where: {
symbol: {
[Op.in]: [...coin]
},
is_active: 1,
},
raw: true,
});
for(let i = 0; i < activeCoin.length; i++) {
let { symbol }= activeCoin[i];
if(coin.has(symbol)) {
coin.delete(symbol);
}
}
if(coin.size) {
return await marketMakerPair.prototype.destroy({ where: {
coin_symbol: {
[Op.in]: [...coin],
}
}});
} else {
return 0;
}
}
/!**
* 如果用户设置前7日>30BTC并且享受免费, 则一直为免费
* @param {*} user_id
* @param {*} pair
* @param {*} time
*!/
async function getProjectSpotFeeRate(user_id, pair, time) {
let maker = FEE_RATE.maker_default, taker = FEE_RATE.Default;
try {
let res = await feeRateSpotLog.prototype.findOne({
attributes: ['maker_fee', 'taker_fee'],
where: {
user_id: user_id,
pair: pair,
is_check: 1,
beginAt: {[Op.lt]: new Date(time),},
expireAt: {[Op.gte]: new Date(time),}
},
raw: true,
});
if(res && Number(res.maker_fee) >= 0 && Number(res.taker_fee) >= 0 ) {
maker = Number(res.maker_fee);
taker = Number(res.taker_fee);
}
} catch (error) {
logger.warn(' marketMarkerMgr.service ', error);
}
return {
taker,
maker,
}
}
// 每日定时统计项目方 指定交易对做市信息, 并根据成交量信息进行费率分档优惠;
export
const
statisProjectMakerDeals
=
async
function
(
now
=
Date
.
now
())
{
export
const
statisProjectMakerDeals
=
async
function
(
now
=
Date
.
now
())
{
try
{
try
{
//TODO:按之前代码来看,只有现货相关的,这里怎么做
let
users
=
await
projectMaker
();
let
users
=
await
projectMaker
();
let
startTime
=
now
-
now
%
DAY
-
DAY
;
// 当前统计昨天的成交数据
let
startTime
=
now
-
now
%
DAY
-
DAY
;
// 当前统计昨天的成交数据
let
btc2usdt
=
await
getDealOneDayInUSDT
(
startTime
,
startTime
+
DAY
);
let
btc2usdt
=
await
getDealOneDayInUSDT
(
startTime
,
startTime
+
DAY
);
let
fatherFeeObj
=
{};
// { fatherid_pair: {maker, taker}}
let
fatherFeeObj
=
{};
// { fatherid_pair: {maker, taker}}
for
(
let
i
=
0
;
i
<
users
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
users
.
length
;
i
++
)
{
let { user_id, pair, status, statis_period, amount_require_usdt} = users[i]; //status 1 激活时才统计
let
{
user_id
,
pair
,
status
,
statis_period
,
amount_require_usdt
,
type
}
=
users
[
i
];
//status 2 生效时才统计
if (user_id && pair) {
let
pairs
=
pair
==
'all'
?
await
getPairsByType
(
type
)
:
[
pair
];
for
(
let
onePair
of
pairs
)
{
let redisKey = user_id +"_" + pair + "_projectMaker_FeeRate";
if
(
user_id
&&
onePair
)
{
await delayPromise(100);
let
redisKey
=
user_id
+
"_"
+
onePair
+
"_projectMaker_FeeRate"
;
let [statis, statisUsdt] = await statisUserPairSpot(user_id, pair, startTime, btc2usdt);
await
delayPromise
(
100
);
let feeObjBtc = getUserFeeRateFromStatis(statis); // old
let
[
statis
,
statisUsdt
]
=
await
statisUserPairSpot
(
user_id
,
onePair
,
startTime
,
btc2usdt
);
let feeObjUsdt = getUserFeeRateFromUsdtStatis(statisUsdt, statis_period, amount_require_usdt)
let
feeObjBtc
=
getUserFeeRateFromStatis
(
statis
);
// old
await adjustMakerFeeRate(now, user_id, pair, status, feeObjBtc, feeObjUsdt, fatherFeeObj);
let
feeObjUsdt
=
getUserFeeRateFromUsdtStatis
(
statisUsdt
,
statis_period
,
amount_require_usdt
)
redisUtilsCommon.write(redisKey, JSON.stringify(Object.assign({}, feeObjUsdt, feeObjBtc)), 0, () => { });
await
adjustMakerFeeRate
(
now
,
user_id
,
onePair
,
status
,
feeObjBtc
,
feeObjUsdt
,
fatherFeeObj
);
redisUtilsCommon
.
write
(
redisKey
,
JSON
.
stringify
(
Object
.
assign
({},
feeObjUsdt
,
feeObjBtc
)),
0
,
()
=>
{
});
}
}
}
}
}
now
=
Date
.
now
();
now
=
Date
.
now
();
let
expired
=
now
+
DAY
-
30000
;
let
expired
=
now
+
DAY
-
30000
;
for(let key in fatherFeeObj) {
for
(
let
key
in
fatherFeeObj
)
{
let [user_id, pair] = key.split('@');
let
[
user_id
,
pair
]
=
key
.
split
(
'@'
);
let faterFee = fatherFeeObj[key];
let
faterFee
=
fatherFeeObj
[
key
];
if(faterFee) {
if
(
faterFee
)
{
let { maker_fee, taker_fee } = faterFee;
let
{
maker_fee
,
taker_fee
}
=
faterFee
;
await setExpiredFeeSettingActiveOver(user_id, pair);
await feeRateSpotSer.add(user_id, pair, FEE_MODEL.fixedingain, maker_fee, taker_fee, now, expired, Market_Maker_FEE.init_maker, Market_Maker_FEE.init_taker, "项目方做市商策略根据子账户交易量设置父账户费率");
}
}
} catch (error) {
logger.warn(' statisProjectMakerDeals error ', error);
}
}
// 获取项目方做市商成交信息
marketMakerService.findProjectMakerInfo = async function (user_id) {
let res = [];
try {
let projectMakers = await marketMakerPair.prototype.findAll({
where: {
user_id: user_id,
},
raw: true,
});
let redisPro = []
for (let i = 0; i < projectMakers.length; i++) {
let maker = projectMakers[i];
if (maker) {
let { user_id, pair } = maker;
if (user_id && pair) {
let redisKey = user_id + "_" + pair + "_projectMaker_FeeRate";
let redisDt = await redisUtilsCommon.getSync(redisKey);
res.push(Object.assign({}, redisDt || {}, maker));
}
}
}
} catch (error) {
logger.warn(' findProjectMakerInfo error', error);
}
return res;
}
// 调整做市商费率最佳
async function adjustMakerFeeRate(now, user_id, pair, enableAjustFee, feeObjBtc = {}, feeObjUsdt = {}, fatherFeeObj = {}) {
// let now = Date.now();
let expired = new Date(now).getTime() + DAY - 30000; // 有效期提前30s,早于新费率开始时间
console.error(' 执行项目做市商 uid %s , %s 费率调整 ', user_id, pair);
let maker_fee = Market_Maker_FEE.init_maker, taker_fee = Market_Maker_FEE.init_taker;
let {maker, taker} = await getProjectSpotFeeRate(user_id, pair, now - 3600000);// 查询费率变更前的费率 0 则继续免费
if(enableAjustFee) {
if(feeObjUsdt && feeObjUsdt.canAjustFeeRateUsdt) { // 新版usdt计量策略优先
console.error(' 新做市策略 ', JSON.stringify(feeObjUsdt));
if(taker_fee > feeObjUsdt.taker_rate ) { // taker_rate, maker_rate,
taker_fee = feeObjUsdt.taker_rate;
}
if(maker_fee > feeObjUsdt.maker_rate) {
maker_fee = feeObjUsdt.maker_rate;
}
await storeFatherFeeSet(user_id, pair, maker_fee, taker_fee, fatherFeeObj);
await setExpiredFeeSettingActiveOver(user_id, pair);
return await feeRateSpotSer.add(user_id, pair, FEE_MODEL.fixedingain, maker_fee, taker_fee, now, expired, Market_Maker_FEE.init_maker, Market_Maker_FEE.init_taker, "项目方做市商根据usdt成交量自动调整");
} else if(feeObjBtc && feeObjBtc.canAjustFeeRateBTC) { // 执行老版 btc 计量策略
console.error(' 早期做市策略 ', JSON.stringify(feeObjBtc));
if(maker==FEE_RATE.Free && taker == FEE_RATE.Free && feeObjBtc.feeRate == FEE_RATE.Wan1) {//手动设置,默认免手续费;若项目单个交易对连续7天日均交易量达到30BTC以上,该交易对手续费保持免费;(运营加需求)
await storeFatherFeeSet(user_id, pair, FEE_RATE.Free, FEE_RATE.Free, fatherFeeObj);
await
setExpiredFeeSettingActiveOver
(
user_id
,
pair
);
await
setExpiredFeeSettingActiveOver
(
user_id
,
pair
);
return await feeRateSpotSer.add(user_id, pair, FEE_MODEL.fixedingain, FEE_RATE.Free, FEE_RATE.Free, now, expired, Market_Maker_FEE.init_maker, Market_Maker_FEE.init_taker, "项目方做市商根据btc成交量自动调整");
await
addFeeRate
(
user_id
,
pair
,
FEE_MODEL
.
fixedingain
,
maker_fee
,
taker_fee
,
now
,
expired
,
Market_Maker_FEE
.
init_maker
,
Market_Maker_FEE
.
init_taker
,
"项目方做市商策略根据子账户交易量设置父账户费率"
);
}
else {
console.error(' 早期做市策略 ', JSON.stringify(feeObjBtc));
// maker_fee = feeObjBtc.feeRate, taker_fee = feeObjBtc.feeRate;
maker_fee = Math.min(maker_fee, feeObjBtc.feeRate), taker_fee = Math.min(taker_fee, feeObjBtc.feeRate);
await storeFatherFeeSet(user_id, pair, maker_fee, taker_fee, fatherFeeObj);
await setExpiredFeeSettingActiveOver(user_id, pair);
return await feeRateSpotSer.add(user_id, pair, FEE_MODEL.fixedingain, maker_fee, taker_fee, now, expired, Market_Maker_FEE.init_maker, Market_Maker_FEE.init_taker, "项目方做市商策略根据btc成交量自动调整");
}
}
}
}
async function storeFatherFeeSet(user_id, pair, maker_fee, taker_fee, fatherFeeObj = {}) {
let faterObj = await getFaterUID(user_id);
if(faterObj && faterObj.father_id) {
let key = faterObj.father_id +"@"+ pair;
if(!fatherFeeObj[key]) {
fatherFeeObj[key] = {
pair,
maker_fee,
taker_fee
}
} else {
fatherFeeObj[key] = {
pair,
maker_fee: Math.min(maker_fee, fatherFeeObj[key].maker_fee),
taker_fee: Math.min(taker_fee, fatherFeeObj[key].taker_fee),
}
}
}
}
}
}
logger.info(' father fee setting ', JSON.stringify(fatherFeeObj));
catch
(
error
)
{
logger
.
warn
(
' statisProjectMakerDeals error '
,
error
);
}
}
}
// 将即过期默认为生效的置为生效完成, 防止覆盖新的费率
// 统计 项目方 7日, 15日 指定币种对 做市
async function setExpiredFeeSettingActiveOver(user_id, pair ) {
async
function
projectMaker
()
{
let
res
:
any
=
[];
try
{
try
{
let now = new Date();
res
=
await
commonUserFeeSetting
.
prototype
.
findAll
({
// console.log(' 更新做市商即将到期生效的费率', user_id, pair);
let res = await feeRateSpotLog.prototype.update({
is_check: feeRateSpotLog.IS_CHECK.ActiveOver,
},{
where
:
{
where
:
{
user_id: user_id,
user_channel
:
2
,
pair: pair,
type
:
1
,
is_check: feeRateSpotLog.IS_CHECK.Uncheck,
},
beginAt: {
order
:
[[
'id'
,
'asc'
]],
[Op.gte]: now,
raw
:
[Op.lt]: new Date(now.getTime() + 3600*1000)
true
,
},
})
}
;
});
}
// console.error(' 使当前未生效过期 res ', JSON.stringify(res));
catch
(
error
)
{
} catch (error) {
logger
.
warn
(
' 获取项目方做市商 projectMaker error'
,
error
);
logger.error(' make expried fee setting active_over: error ', error);
}
}
}
async function getSpotFeeRate(user_id) {
let order = [['beginAt', 'desc']];
let res = await feeRateSpotLog.prototype.findAll({
where: {
user_id: user_id,
is_check: 1,//已经生效
},
order,
raw: true,
});
return res;
}
// 获取合约费率
async function getContractFeeRate(user_id) {
let order = [['beginAt', 'desc']];
let res = await feeRateContractLog.prototype.findAll({
where: {
user_id: user_id,
is_check: 1,//已经生效
},
order,
raw: true,
});
return
res
;
return
res
;
}
}
// 获取某个子账户的父账户
// 获取交易对USDT交易量
async function getFaterUID(user_id) {
async
function
getDealOneDayInUSDT
(
startTime
,
endTime
)
{
return user_info_son.findOne({
let
price
=
await
tickerUtils
.
rateCoin2USDT
(
'BTC'
);
attributes: ['father_id'],
//TODO:查哪里???
/*let priceRes = await ex_kline.find({
attributes: [[ormDBSpot.literal('AVG(close)'), 'closePrice']],
where: {
where: {
user_id,
pair: "BTC_USDT",
status: SonStatus.NORMAL,
period: '1hour',
createdAt: {
[Op.gte]: new Date(startTime),
[Op.lt]: new Date(endTime),
}
},
},
raw: true,
raw: true,
});
});
if(priceRes && Number(priceRes.closePrice) > 0) {
price = Number(priceRes.closePrice).toFixed(4);
}*/
return
Number
(
price
);
}
}
async function getMakerDeals(userIds, start, end) {
// 统计币币成交量信息
let res = [];
async
function
statisUserPairSpot
(
user_id
,
pair
,
timestamp
,
btc2usdt
)
{
try {
let
redisKey
=
user_id
+
"_"
+
pair
+
'_projectMaker_spot'
;
if (userIds.length === 0) return [];
let
redisKeyUsdt
=
user_id
+
"_"
+
pair
+
'_projectMaker_spot_usdt'
;
let [spot, contract] = await Promise.all([getSpotDeals(userIds, start, end), getUserContractDeals(userIds, start, end)]);
let
resultCache
=
{},
resultCacheInUsdt
=
{};
for (let tm = end; tm >= start; tm -= DAY) { // 按时间倒叙排列
for (let id = 0; id < userIds.length; id++) {
let tkey = tm + "_" + userIds[id] + "_taker";
let mkey = tm + "_" + userIds[id] + "_maker";
let obj = {
time: tm,
user_id: userIds[id],
spotTaker: (Number(spot[tkey]) || 0).toFixed(4), // usdt 计价
spotMaker: (Number(spot[mkey]) || 0).toFixed(4), // usdt 计价
contractTaker: (Number(contract[tkey]) || 0).toFixed(4), // btc 计价
contractMaker: (Number(contract[mkey]) || 0).toFixed(4), // btc计价
}
res.push(obj);
}
}
} catch (error) {
logger.warn('getMakerDeals error', error);
}
return res;
}
function calcTotal(dt) {
try {
let spot_taker = 0, spot_maker = 0, contract_taker = 0, contract_maker = 0;
for (let i = 0; i < dt.length; i++) {
let { spotTaker, spotMaker, contractTaker, contractMaker } = dt[i];
spot_taker += Number(spotTaker),
spot_maker += Number(spotMaker),
contract_taker += Number(contractTaker),
contract_maker += Number(contractMaker);
}
return {
items: dt,
spot_taker,
spot_maker,
contract_taker,
contract_maker
}
} catch (error) {
logger.warn('calcTotal error', error);
}
}
async function getMakerUserID(makerTypes = [marketMaker.MAKER_TYPE.NORMAL, marketMaker.MAKER_TYPE.PLATFORM_MAKER, marketMaker.MAKER_TYPE.PROJECT_MAKER]) {
let userId = [];
try
{
try
{
let user = await market_maker.findAll({
[
resultCache
,
resultCacheInUsdt
]
=
await
Promise
.
all
([
redisUtilsCommon
.
getSync
(
redisKey
),
redisUtilsCommon
.
getSync
(
redisKeyUsdt
)]);
attributes: ['user_id'],
let
userDeals
=
await
getDealOneDay
(
pair
,
new
Date
(
timestamp
),
timestamp
+
DAY
);
where: {
resultCache
=
updateCache
(
resultCache
,
timestamp
,
userDeals
);
maker_type: { [Op.in]: makerTypes} //平台做市商与项目方做市商
let
usdtAmount
=
Number
(
userDeals
)
*
btc2usdt
},
resultCacheInUsdt
=
updateCache
(
resultCacheInUsdt
,
timestamp
,
usdtAmount
);
raw: true,
redisUtilsCommon
.
write
(
redisKey
,
JSON
.
stringify
(
resultCache
),
0
,
()
=>
{
});
});
for (let i = 0; i < user.length; i++) {
redisUtilsCommon
.
write
(
redisKeyUsdt
,
JSON
.
stringify
(
resultCacheInUsdt
),
0
,
()
=>
{
if (user[i] && user[i].user_id) {
userId.push(user[i].user_id)
}
}
} catch (error) {
logger.warn("getMakerUserID 获取做市商用户ID异常", error)
}
return userId;
};
//
async function getSpotDeals(userids, startTime, endTime) {
let resObj = {};
try {
let spotdels = await user_daily_trade.findAll({
attributes: ['equal_usdt', 'equal_btc_maker', 'equal_btc_taker', 'trade_date', 'user_id'],
where: {
user_id: {
[Op.in]: userids
},
trade_date: {
[Op.gte]: startTime,
[Op.lt]: endTime,
}
},
order: [['trade_date', 'desc'], ['equal_usdt', 'desc']]
});
});
for (let i = 0; i < spotdels.length; i++) {
let { equal_btc_maker, equal_btc_taker, user_id, trade_date, equal_usdt } = spotdels[i];
if (equal_usdt > 0) {
let Key = new Date(trade_date).getTime() + "_" + user_id;
// let maker_usdt = equal_usdt * equal_btc_maker / equal_btc;
// spotdels[i]['maker_usdt'] = maker_usdt;
// spotdels[i]['taker_usdt'] = equal_usdt - maker_usdt;
// resObj[Key] = spotdels[i];
resObj[Key + "_maker"] = equal_btc_maker;
resObj[Key + "_taker"] = equal_btc_taker;
}
}
} catch (error) {
logger.warn("getSpotDeals error", error);
}
return resObj;
}
/!**
* 用户成交记录详情 maker taker 量
* @param {*} userids
*!/
async function getUserContractDeals(userids, startTime, endTime) {
// 获取用户
let objAll = {};
try {
let order_detail = await contract_daily_fee.findAll({
attributes: [
'user_id',
'createdAt',
[ormDBCon.literal('sum(equal_btc_amount_maker)'), 'equal_btc_amount_maker'],
[ormDBCon.literal('sum(equal_btc_amount_taker)'), 'equal_btc_amount_taker'],
],
where: {
user_id: {
[Op.in]: userids
},
createdAt: {
[Op.gte]: startTime,
[Op.lt]: endTime,
},
},
group: ['createdAt', 'user_id'],
raw: true,
});
for (let i = 0; i < order_detail.length; i++) {
let order = order_detail[i];
let { user_id, createdAt, equal_btc_amount_maker, equal_btc_amount_taker } = order;
let key = new Date(createdAt).getTime() + "_" + user_id;
objAll[key + "_maker"] = equal_btc_amount_maker;
objAll[key + "_taker"] = equal_btc_amount_taker;
}
}
}
catch
(
error
)
{
catch
(
error
)
{
logger.warn('getUserContractDeals error', error);
logger
.
warn
(
' 统计项目做市上成交总和 error '
,
error
);
}
return objAll;
}
// 统计 项目方 7日, 15日 指定币种对 做市
async function projectMaker() {
let res = [];
try {
res = await marketMakerPair.prototype.findAll({
// where: { // 统计全部交易对, status = 1时才设置费率
// status: 1, // 激活
// },
order: [['id','asc']],
raw: true,
});
} catch (error) {
logger.warn(' 获取项目方做市商 projectMaker error', error);
}
}
return
res
;
return
[
resultCache
,
resultCacheInUsdt
]
;
}
}
// 获取昨天一天的的统计交易量
// 获取昨天一天的的统计交易量
// 该交易对对所有交易量都归该做市帐号
// 该交易对对所有交易量都归该做市帐号
async
function
getDealOneDay
(
pair
,
startTime
,
endTime
)
{
async
function
getDealOneDay
(
pair
,
startTime
,
endTime
)
{
let
resCountInBTC
=
0
;
let
resCountInBTC
=
0
;
try
{
try
{
let tradeDetail = await ex_trade_detail_spot.find({
//查哪里
/*let tradeDetail = await ex_trade_detail_spot.find({
attributes: ['currency_symbol', [ormDBSpot.literal('SUM(deal_money)'), 'deal_money']],
attributes: ['currency_symbol', [ormDBSpot.literal('SUM(deal_money)'), 'deal_money']],
where: {
where: {
pair: pair,
pair: pair,
...
@@ -892,33 +175,40 @@ async function getDealOneDay(pair, startTime, endTime) {
...
@@ -892,33 +175,40 @@ async function getDealOneDay(pair, startTime, endTime) {
if (equalBTC >= 0.00000001) {
if (equalBTC >= 0.00000001) {
resCountInBTC = equalBTC;
resCountInBTC = equalBTC;
}
}
}
}*/
} catch (error) {
}
catch
(
error
)
{
logger
.
error
(
" 查询用户每天做市量出错 "
,
error
);
logger
.
error
(
" 查询用户每天做市量出错 "
,
error
);
}
}
return
resCountInBTC
;
return
resCountInBTC
;
}
}
async
function
coinPriceInBTC
(
coinSymbol
,
startTime
,
endTime
)
{
async
function
coinPriceInBTC
(
coinSymbol
,
startTime
,
endTime
)
{
let
time
=
Date
.
now
();
let
time
=
Date
.
now
();
if(!coinSymbol) {
if
(
!
coinSymbol
)
{
logger.error(' coinSymbol illegal, coinSymbol is: ',coinSymbol);
logger
.
error
(
' coinSymbol illegal, coinSymbol is: '
,
coinSymbol
);
}
}
let
priceInfo
=
price2BTC
[
coinSymbol
];
let
priceInfo
=
price2BTC
[
coinSymbol
];
if
(
coinSymbol
===
'BTC'
)
{
if
(
coinSymbol
===
'BTC'
)
{
//BTC无转换
//BTC无转换
return
1
;
return
1
;
} else if (priceInfo && (time - priceInfo.updatedTime) <= CACHE_TIMEOUT) {
}
else
if
(
priceInfo
&&
(
time
-
priceInfo
.
updatedTime
)
<=
CACHE_TIMEOUT
)
{
return
priceInfo
.
price
;
return
priceInfo
.
price
;
} else {
}
else
{
//拉取24小时平均价格
//拉取24小时平均价格
let
tickerPair
,
lastPrice
=
0
;
let
tickerPair
,
lastPrice
=
0
;
if
(
coinSymbol
===
'USDT'
||
coinSymbol
===
'DAI'
||
coinSymbol
===
'GUSD'
)
{
if
(
coinSymbol
===
'USDT'
||
coinSymbol
===
'DAI'
||
coinSymbol
===
'GUSD'
)
{
tickerPair
=
'BTC_'
+
coinSymbol
;
tickerPair
=
'BTC_'
+
coinSymbol
;
} else {
}
else
{
tickerPair
=
coinSymbol
+
'_BTC'
;
tickerPair
=
coinSymbol
+
'_BTC'
;
}
}
try
{
try
{
let priceRes = await ex_kline.find({
//TODO:查哪里
/*let priceRes = await ex_kline.find({
attributes: [[ormDBSpot.literal('AVG(close)'), 'closePrice']],
attributes: [[ormDBSpot.literal('AVG(close)'), 'closePrice']],
where: {
where: {
pair: tickerPair,
pair: tickerPair,
...
@@ -939,9 +229,10 @@ async function coinPriceInBTC(coinSymbol, startTime, endTime) {
...
@@ -939,9 +229,10 @@ async function coinPriceInBTC(coinSymbol, startTime, endTime) {
price2BTC[coinSymbol] = { updatedTime: Date.now(), price: lastPrice };
price2BTC[coinSymbol] = { updatedTime: Date.now(), price: lastPrice };
} else {
} else {
logger.warn(` 未查询到交易对${tickerPair} 24hour均值`, priceRes);
logger.warn(` 未查询到交易对${tickerPair} 24hour均值`, priceRes);
}
}
*/
return
lastPrice
;
return
lastPrice
;
} catch (error) {
}
catch
(
error
)
{
logger
.
warn
(
` 查询到交易对
${
tickerPair
}
24hour均值出错 `
,
error
);
logger
.
warn
(
` 查询到交易对
${
tickerPair
}
24hour均值出错 `
,
error
);
price2BTC
[
coinSymbol
]
=
{
updatedTime
:
Date
.
now
(),
price
:
0
};
price2BTC
[
coinSymbol
]
=
{
updatedTime
:
Date
.
now
(),
price
:
0
};
return
0
;
return
0
;
...
@@ -949,46 +240,6 @@ async function coinPriceInBTC(coinSymbol, startTime, endTime) {
...
@@ -949,46 +240,6 @@ async function coinPriceInBTC(coinSymbol, startTime, endTime) {
}
}
}
}
marketMakerService.getDealOneDayInUSDT = getDealOneDayInUSDT;
// 获取交易对USDT交易量
async function getDealOneDayInUSDT(startTime, endTime) {
let price = await ticker.rateCoin2USDT('BTC');
let priceRes = await ex_kline.find({
attributes: [[ormDBSpot.literal('AVG(close)'), 'closePrice']],
where: {
pair: "BTC_USDT",
period: '1hour',
createdAt: {
[Op.gte]: new Date(startTime),
[Op.lt]: new Date(endTime),
}
},
raw: true,
});
if(priceRes && Number(priceRes.closePrice) > 0) {
price = Number(priceRes.closePrice).toFixed(4);
}
return Number(price);
}
// 统计币币成交量信息
async function statisUserPairSpot(user_id, pair, timestamp, btc2usdt) {
let redisKey = user_id + "_" + pair + '_projectMaker_spot';
let redisKeyUsdt = user_id + "_" + pair + '_projectMaker_spot_usdt';
let resultCache = {}, resultCacheInUsdt = {} ;
try {
[resultCache, resultCacheInUsdt] = await Promise.all([redisUtilsCommon.getSync(redisKey), redisUtilsCommon.getSync(redisKeyUsdt)]) ;
let userDeals = await getDealOneDay(pair, new Date(timestamp), timestamp + DAY);
resultCache = updateCache(resultCache, timestamp, userDeals);
let usdtAmount = Number(userDeals) * btc2usdt
resultCacheInUsdt = updateCache(resultCacheInUsdt, timestamp, usdtAmount);
redisUtilsCommon.write(redisKey, JSON.stringify(resultCache), 0, () => { });
redisUtilsCommon.write(redisKeyUsdt, JSON.stringify(resultCacheInUsdt), 0, () => { });
} catch (error) {
logger.warn(' 统计项目做市上成交总和 error ', error);
}
return [resultCache, resultCacheInUsdt];
}
function
updateCache
(
resultCache
,
timestamp
,
userDeals
)
{
function
updateCache
(
resultCache
,
timestamp
,
userDeals
)
{
if
(
resultCache
)
{
if
(
resultCache
)
{
...
@@ -1003,7 +254,8 @@ function updateCache(resultCache, timestamp, userDeals) {
...
@@ -1003,7 +254,8 @@ function updateCache(resultCache, timestamp, userDeals) {
}
}
}
}
}
}
} else { // 无缓存数据
}
else
{
// 无缓存数据
if
(
userDeals
>
0
)
{
if
(
userDeals
>
0
)
{
resultCache
=
{
resultCache
=
{
[
timestamp
]:
userDeals
[
timestamp
]:
userDeals
...
@@ -1013,14 +265,15 @@ function updateCache(resultCache, timestamp, userDeals) {
...
@@ -1013,14 +265,15 @@ function updateCache(resultCache, timestamp, userDeals) {
return
Object
.
assign
({},
resultCache
);
return
Object
.
assign
({},
resultCache
);
}
}
// 从统计结果中获取用户费率, 旧btc交易量统计会逐渐改为usdt统计
// 从统计结果中获取用户费率, 旧btc交易量统计会逐渐改为usdt统计
function
getUserFeeRateFromStatis
(
dealAmountCache
)
{
function
getUserFeeRateFromStatis
(
dealAmountCache
)
{
let
feeRate = FEE_RATE.Default, avg7 = 0, avg15 = 0, canAjustFeeRateBTC = false;
let
feeRate
=
FEE_RATE
.
Default
,
avg7
=
0
,
avg15
=
0
,
canAjustFeeRateBTC
=
false
;
try
{
try
{
const
day7
=
7
,
day15
=
15
;
const
day7
=
7
,
day15
=
15
;
let
timeArr
=
Object
.
keys
(
dealAmountCache
),
len
=
timeArr
.
length
,
sum
;
let
timeArr
=
Object
.
keys
(
dealAmountCache
),
len
=
timeArr
.
length
,
sum
;
let
feeRate7
=
FEE_RATE
.
Default
,
feeRate15
=
FEE_RATE
.
Default
;
let
feeRate7
=
FEE_RATE
.
Default
,
feeRate15
=
FEE_RATE
.
Default
;
if(len > 0 && len < day7) {// 低于 7 天
if
(
len
>
0
&&
len
<
day7
)
{
// 低于 7 天
sum
=
0
;
sum
=
0
;
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
let
ts
=
timeArr
[
i
];
let
ts
=
timeArr
[
i
];
...
@@ -1038,9 +291,11 @@ function getUserFeeRateFromStatis(dealAmountCache) {
...
@@ -1038,9 +291,11 @@ function getUserFeeRateFromStatis(dealAmountCache) {
avg7
=
sum
/
day7
;
avg7
=
sum
/
day7
;
if
(
avg7
>=
BTC_AMOUNT
.
BTC30
)
{
if
(
avg7
>=
BTC_AMOUNT
.
BTC30
)
{
feeRate7
=
FEE_RATE
.
Wan1
;
feeRate7
=
FEE_RATE
.
Wan1
;
} else if (avg7 >= BTC_AMOUNT.BTC5) {
}
else
if
(
avg7
>=
BTC_AMOUNT
.
BTC5
)
{
feeRate7
=
FEE_RATE
.
Wan2
;
feeRate7
=
FEE_RATE
.
Wan2
;
} else if (avg7 > BTC_AMOUNT.BTC0) {
}
else
if
(
avg7
>
BTC_AMOUNT
.
BTC0
)
{
feeRate7
=
FEE_RATE
.
Default
;
feeRate7
=
FEE_RATE
.
Default
;
}
}
}
}
...
@@ -1054,30 +309,35 @@ function getUserFeeRateFromStatis(dealAmountCache) {
...
@@ -1054,30 +309,35 @@ function getUserFeeRateFromStatis(dealAmountCache) {
avg15
=
sum
/
day15
;
avg15
=
sum
/
day15
;
if
(
avg15
>=
BTC_AMOUNT
.
BTC30
)
{
if
(
avg15
>=
BTC_AMOUNT
.
BTC30
)
{
feeRate15
=
FEE_RATE
.
Free
;
feeRate15
=
FEE_RATE
.
Free
;
} else if (avg15 >= BTC_AMOUNT.BTC5) {
}
else
if
(
avg15
>=
BTC_AMOUNT
.
BTC5
)
{
feeRate15
=
FEE_RATE
.
Wan2
;
feeRate15
=
FEE_RATE
.
Wan2
;
} else if (avg15 > BTC_AMOUNT.BTC0) {
}
else
if
(
avg15
>
BTC_AMOUNT
.
BTC0
)
{
feeRate15
=
FEE_RATE
.
Default
;
feeRate15
=
FEE_RATE
.
Default
;
}
}
}
}
feeRate
=
Math
.
min
(
feeRate7
,
feeRate15
);
feeRate
=
Math
.
min
(
feeRate7
,
feeRate15
);
} catch (error) {
}
catch
(
error
)
{
logger
.
warn
(
' getUserFeeRateFromStatis error'
,
error
);
logger
.
warn
(
' getUserFeeRateFromStatis error'
,
error
);
}
}
return { feeRate, avg7, avg15, canAjustFeeRateBTC};
return
{
feeRate
,
avg7
,
avg15
,
canAjustFeeRateBTC
};
}
}
// 增加usdt统计需求,
// 增加usdt统计需求,
function
getUserFeeRateFromUsdtStatis
(
dealAmount
,
statis_period
,
requireAmount
=
100000
)
{
function
getUserFeeRateFromUsdtStatis
(
dealAmount
,
statis_period
,
requireAmount
=
100000
)
{
let
timeArr
=
Object
.
keys
(
dealAmount
),
len
=
timeArr
.
length
,
canAjustFeeRateUsdt
=
false
,
sum
=
0
,
avg
=
0
;
let
timeArr
=
Object
.
keys
(
dealAmount
),
len
=
timeArr
.
length
,
canAjustFeeRateUsdt
=
false
,
sum
=
0
,
avg
=
0
;
let
taker_rate
=
0.0002
,
maker_rate
=
0
;
// 新项目做市商需求,如果<100K, taker 0.02%, maker = 0;
let
taker_rate
=
0.0002
,
maker_rate
=
0
;
// 新项目做市商需求,如果<100K, taker 0.02%, maker = 0;
if(len > 0 && len < statis_period) {
if
(
len
>
0
&&
len
<
statis_period
)
{
for(let i = 0; i < len; i++) {
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
let
ts
=
timeArr
[
i
];
let
ts
=
timeArr
[
i
];
sum
+=
Number
(
dealAmount
[
ts
])
||
0
;
sum
+=
Number
(
dealAmount
[
ts
])
||
0
;
}
}
avg
=
sum
/
len
;
avg
=
sum
/
len
;
} else if(len >= statis_period) {
}
else
if
(
len
>=
statis_period
)
{
canAjustFeeRateUsdt
=
true
;
canAjustFeeRateUsdt
=
true
;
sum
=
0
;
sum
=
0
;
for
(
let
i
=
len
-
1
,
stopIndex
=
len
-
statis_period
;
i
>=
stopIndex
;
i
--
)
{
for
(
let
i
=
len
-
1
,
stopIndex
=
len
-
statis_period
;
i
>=
stopIndex
;
i
--
)
{
...
@@ -1085,10 +345,186 @@ function getUserFeeRateFromUsdtStatis(dealAmount, statis_period, requireAmount =
...
@@ -1085,10 +345,186 @@ function getUserFeeRateFromUsdtStatis(dealAmount, statis_period, requireAmount =
sum
+=
Number
(
dealAmount
[
ts
])
||
0
;
sum
+=
Number
(
dealAmount
[
ts
])
||
0
;
}
}
avg
=
sum
/
statis_period
;
avg
=
sum
/
statis_period
;
if(avg >= requireAmount) {
if
(
avg
>=
requireAmount
)
{
taker_rate
=
0
;
taker_rate
=
0
;
}
}
}
}
return { taker_rate, maker_rate, avg_usdt: avg, canAjustFeeRateUsdt};
return
{
taker_rate
,
maker_rate
,
avg_usdt
:
avg
,
canAjustFeeRateUsdt
};
}
// 调整做市商费率最佳
async
function
adjustMakerFeeRate
(
now
,
user_id
,
pair
,
enableAjustFee
,
feeObjBtc
:
any
=
{},
feeObjUsdt
:
any
=
{},
fatherFeeObj
:
any
=
{})
{
// let now = Date.now();
let
expired
=
new
Date
(
now
).
getTime
()
+
DAY
-
30000
;
// 有效期提前30s,早于新费率开始时间
console
.
error
(
' 执行项目做市商 uid %s , %s 费率调整 '
,
user_id
,
pair
);
let
maker_fee
=
Market_Maker_FEE
.
init_maker
,
taker_fee
=
Market_Maker_FEE
.
init_taker
;
let
{
maker
,
taker
}
=
await
getProjectSpotFeeRate
(
user_id
,
pair
,
now
-
3600000
);
// 查询费率变更前的费率 0 则继续免费
if
(
enableAjustFee
)
{
if
(
feeObjUsdt
&&
feeObjUsdt
.
canAjustFeeRateUsdt
)
{
// 新版usdt计量策略优先
console
.
error
(
' 新做市策略 '
,
JSON
.
stringify
(
feeObjUsdt
));
if
(
taker_fee
>
feeObjUsdt
.
taker_rate
)
{
// taker_rate, maker_rate,
taker_fee
=
feeObjUsdt
.
taker_rate
;
}
if
(
maker_fee
>
feeObjUsdt
.
maker_rate
)
{
maker_fee
=
feeObjUsdt
.
maker_rate
;
}
await
storeFatherFeeSet
(
user_id
,
pair
,
maker_fee
,
taker_fee
,
fatherFeeObj
);
await
setExpiredFeeSettingActiveOver
(
user_id
,
pair
);
return
await
addFeeRate
(
user_id
,
pair
,
FEE_MODEL
.
fixedingain
,
maker_fee
,
taker_fee
,
now
,
expired
,
Market_Maker_FEE
.
init_maker
,
Market_Maker_FEE
.
init_taker
,
"项目方做市商根据usdt成交量自动调整"
);
}
else
if
(
feeObjBtc
&&
feeObjBtc
.
canAjustFeeRateBTC
)
{
// 执行老版 btc 计量策略
console
.
error
(
' 早期做市策略 '
,
JSON
.
stringify
(
feeObjBtc
));
if
(
maker
==
FEE_RATE
.
Free
&&
taker
==
FEE_RATE
.
Free
&&
feeObjBtc
.
feeRate
==
FEE_RATE
.
Wan1
)
{
//手动设置,默认免手续费;若项目单个交易对连续7天日均交易量达到30BTC以上,该交易对手续费保持免费;(运营加需求)
await
storeFatherFeeSet
(
user_id
,
pair
,
FEE_RATE
.
Free
,
FEE_RATE
.
Free
,
fatherFeeObj
);
await
setExpiredFeeSettingActiveOver
(
user_id
,
pair
);
return
await
addFeeRate
(
user_id
,
pair
,
FEE_MODEL
.
fixedingain
,
FEE_RATE
.
Free
,
FEE_RATE
.
Free
,
now
,
expired
,
Market_Maker_FEE
.
init_maker
,
Market_Maker_FEE
.
init_taker
,
"项目方做市商根据btc成交量自动调整"
);
}
else
{
console
.
error
(
' 早期做市策略 '
,
JSON
.
stringify
(
feeObjBtc
));
// maker_fee = feeObjBtc.feeRate, taker_fee = feeObjBtc.feeRate;
maker_fee
=
Math
.
min
(
maker_fee
,
feeObjBtc
.
feeRate
),
taker_fee
=
Math
.
min
(
taker_fee
,
feeObjBtc
.
feeRate
);
await
storeFatherFeeSet
(
user_id
,
pair
,
maker_fee
,
taker_fee
,
fatherFeeObj
);
await
setExpiredFeeSettingActiveOver
(
user_id
,
pair
);
return
await
addFeeRate
(
user_id
,
pair
,
FEE_MODEL
.
fixedingain
,
maker_fee
,
taker_fee
,
now
,
expired
,
Market_Maker_FEE
.
init_maker
,
Market_Maker_FEE
.
init_taker
,
"项目方做市商策略根据btc成交量自动调整"
);
}
}
}
}
/**
* 如果用户设置前7日>30BTC并且享受免费, 则一直为免费
* @param {*} user_id
* @param {*} pair
* @param {*} time
*/
async
function
getProjectSpotFeeRate
(
user_id
,
pair
,
time
)
{
let
maker
=
FEE_RATE
.
maker_default
,
taker
=
FEE_RATE
.
Default
;
try
{
let
res
=
await
feeRateSpotLog
.
prototype
.
findOne
({
attributes
:
[
'maker_fee'
,
'taker_fee'
],
where
:
{
user_id
:
user_id
,
pair
:
pair
,
is_check
:
1
,
beginAt
:
{
[
Op
.
lt
]:
new
Date
(
time
),
},
expireAt
:
{
[
Op
.
gte
]:
new
Date
(
time
),
}
},
raw
:
true
,
});
if
(
res
&&
Number
(
res
.
maker_fee
)
>=
0
&&
Number
(
res
.
taker_fee
)
>=
0
)
{
maker
=
Number
(
res
.
maker_fee
);
taker
=
Number
(
res
.
taker_fee
);
}
}
catch
(
error
)
{
logger
.
warn
(
' marketMarkerMgr.service '
,
error
);
}
return
{
taker
,
maker
,
}
}
async
function
storeFatherFeeSet
(
user_id
,
pair
,
maker_fee
,
taker_fee
,
fatherFeeObj
=
{})
{
let
faterObj
=
await
getFaterUID
(
user_id
);
if
(
faterObj
&&
faterObj
.
father_id
)
{
let
key
=
faterObj
.
father_id
+
"@"
+
pair
;
if
(
!
fatherFeeObj
[
key
])
{
fatherFeeObj
[
key
]
=
{
pair
,
maker_fee
,
taker_fee
}
}
else
{
fatherFeeObj
[
key
]
=
{
pair
,
maker_fee
:
Math
.
min
(
maker_fee
,
fatherFeeObj
[
key
].
maker_fee
),
taker_fee
:
Math
.
min
(
taker_fee
,
fatherFeeObj
[
key
].
taker_fee
),
}
}
}
logger
.
info
(
' father fee setting '
,
JSON
.
stringify
(
fatherFeeObj
));
}
// 获取某个子账户的父账户
async
function
getFaterUID
(
user_id
)
{
return
user_info_son
.
findOne
({
attributes
:
[
'father_id'
],
where
:
{
user_id
,
status
:
SonStatus
.
NORMAL
,
},
raw
:
true
,
});
}
// 将即过期默认为生效的置为生效完成, 防止覆盖新的费率
async
function
setExpiredFeeSettingActiveOver
(
user_id
,
pair
)
{
try
{
let
now
=
new
Date
();
// console.log(' 更新做市商即将到期生效的费率', user_id, pair);
let
res
=
await
feeRateSpotLog
.
prototype
.
update
({
is_check
:
feeRateSpotLog
.
IS_CHECK
.
ActiveOver
,
},
{
where
:
{
user_id
:
user_id
,
pair
:
pair
,
is_check
:
feeRateSpotLog
.
IS_CHECK
.
Uncheck
,
beginAt
:
{
[
Op
.
gte
]:
now
,
[
Op
.
lt
]:
new
Date
(
now
.
getTime
()
+
3600
*
1000
)
},
}
});
// console.error(' 使当前未生效过期 res ', JSON.stringify(res));
}
catch
(
error
)
{
logger
.
error
(
' make expried fee setting active_over: error '
,
error
);
}
}
async
function
getPairsByType
(
type
:
number
)
{
let
dbList
:
any
;
//现货
if
(
type
==
1
)
{
dbList
=
await
spotPairs
.
prototype
.
findAll
({
where
:
{
status
:
2
},
raw
:
true
});
}
else
{
dbList
=
await
contractPairs
.
prototype
.
findAll
({
where
:
{
status
:
2
},
raw
:
true
});
}
return
dbList
.
map
(
item
=>
item
.
symbol
);
}
}
*/
async
function
addFeeRate
(
user_id
,
pair
,
fee_model
,
maker_fee
,
taker_fee
,
beginAt
,
expireAt
,
maker_fee_late
,
taker_fee_late
,
comment
=
''
)
{
if
(
comment
&&
String
(
comment
).
length
>
512
)
{
throw
'3000'
;
}
let
dbinfo
=
await
user_info
.
findOne
({
where
:
{
user_id
:
Number
(
user_id
),
},
raw
:
true
,
});
if
(
!
dbinfo
)
{
throw
'3000'
;
}
let
insertOne
=
{
user_id
,
pair
,
fee_model
,
maker_fee
,
taker_fee
,
beginAt
,
expireAt
,
is_check
:
feeRateCheckStatus
.
CHECK_STATUS_UNCHECK
,
comment
:
String
(
comment
),
}
await
feeRateSpotLog
.
prototype
.
create
(
insertOne
);
}
\ No newline at end of file
cron/task/task_market_maker_statis.ts
View file @
5395fe73
/*
import
{
statisProjectMakerDeals
}
from
"../service/task.market.maker.statis.service"
;
import { statisProjectMakerDeals } from "../service/marketMakerMgr.service";
const
schedule
=
require
(
'node-schedule'
);
const
schedule
=
require
(
'node-schedule'
);
const
logger
=
require
(
'@madex/ex-js-public'
).
logger
;
const
logger
=
require
(
'@madex/ex-js-public'
).
logger
;
...
@@ -21,4 +20,4 @@ let setFeeRateJob = schedule.scheduleJob('0 10 0 * * *', async function () {
...
@@ -21,4 +20,4 @@ let setFeeRateJob = schedule.scheduleJob('0 10 0 * * *', async function () {
inJob
=
false
;
inJob
=
false
;
logger
.
warn
(
' 统计项目方做市商成交量 error'
,
error
);
logger
.
warn
(
' 统计项目方做市商成交量 error'
,
error
);
}
}
});
*/
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment