步长值,求和和排序在一起,以便对对象数组进行订单簿分组"/>
Lodash分组依据,步长值,求和和排序在一起,以便对对象数组进行订单簿分组
我有如下对象数组
var orders={
'8549.5': { side: 'Sell', size: 380210 },
'8549.0': { side: 'Sell', size: 51700 },
'8548.5': { side: 'Sell', size: 14136 },
'8547.5': { side: 'Sell', size: 1108 },
'8547': { side: 'Sell', size: 84190 },
'8544.5': { side: 'Sell', size: 65800 },
'8543.5': { side: 'Sell', size: 24755 },
'8542.5': { side: 'Sell', size: 6233 },
'8541.5': { side: 'Sell', size: 10206 },
'8540.5': { side: 'Sell', size: 228742 },
'8539.5': { side: 'Buy', size: 4001 },
'8538.5': { side: 'Buy', size: 50001 },
'8537.5': { side: 'Buy', size: 75000 },
'8536.5': { side: 'Buy', size: 77367 },
'8535.5': { side: 'Buy', size: 75000 }}
我想实现以下目标:
- 如果分组索引为1-所有订单价格都需要按1进行分组(8549、8548、8557等)。
- 大小需要加总
- 每边所有大小的总和
我已经尝试了常规的循环方法,但是它确实很慢,并且对象的大小约为50000至250000个键。
我目前在分组1中获得的最终结果是:
Sell: [{"price": 8549, "size": 431910, "total": 431910},
{"price": 8548, "size": 14136, "total": 446046},
{"price": 8547, "size": 85298, "total": 531344 }
...
and similar for sell
有没有lodash的实现可以解决分组索引,总和和总和?
这是当前的最小代码
var realTimelastPrice=null;
var lastPriceSide=null;
var bid=null; var ask=null;
var order={};
var orderBook={};
var orderSell={};
var orderBuy={};
function setBids(gapPrice)
{
var lastPrice = this.realTimelastPrice
var startBuyPrice = this.bid
gapPrice=parseFloat(gapPrice)
var showMaximum = 10
var startBuyViewPrice = Math.floor(startBuyPrice/gapPrice)*gapPrice
var tmpOrder = {
price:null,
size:null,
total: null
}
var currentBuyViewPrice = startBuyViewPrice
var totalBuy=0;
var buys;
var cntShow = 0
for(var price = startBuyPrice;cntShow<=showMaximum;price -= 0.5)
{
if(this.orderBook[price]==undefined)
continue
var tmpSize = this.orderBook[price].size;
if(currentBuyViewPrice>price)
{
currentBuyViewPrice -= gapPrice
tmpOrder['size'] = new Intl.NumberFormat('en-US').format(tmpOrder['size'])
tmpOrder['total'] = new Intl.NumberFormat('en-US').format(totalBuy)
tmpOrder['price'] = new Intl.NumberFormat('en-US').format(tmpOrder['price'].toFixed(1))
buys+='<tr><td style="color:white !important;">'+tmpOrder['total']+'</td><td style="color:white !important;">'+commaNumber(tmpOrder['size'])+'</td><td>'+tmpOrder['price']+'</td></tr>'
tmpOrder = {
price:null,
size:null,
total: null
}
cntShow += 1
}
totalBuy+=tmpSize;
if(tmpOrder['price']==null)
{
tmpOrder['price'] = currentBuyViewPrice
tmpOrder['size'] = tmpSize
}
else
{
tmpOrder['size'] += tmpSize
}
if(showMaximum==cntShow) break
}
$(".orderbook-table-bids tbody").html(buys)
}
function setAsks(gapPrice)
{
var startSellPrice = this.ask
gapPrice=parseFloat(gapPrice)
var showMaximum = 12
var startSellViewPrice = Math.ceil(startSellPrice/gapPrice)*gapPrice
var tmpOrder = {
price:null,
size:null,
total:null
}
var totalSell=0;
var currentSellViewPrice = startSellViewPrice
var sells;
var cntShow = 0
for(var price = startSellPrice;cntShow<=showMaximum;price += 0.5)
{
var tmpViewPrice = currentSellViewPrice
if(this.orderBook[price]==undefined)
continue
var tmpSize = this.orderBook[price].size;
if(currentSellViewPrice<price)
{
currentSellViewPrice += gapPrice
tmpOrder['total'] = new Intl.NumberFormat('en-US').format(totalSell)
tmpOrder['size'] = new Intl.NumberFormat('en-US').format(tmpOrder['size'])
tmpOrder['price'] = new Intl.NumberFormat('en-US').format(tmpOrder['price'].toFixed(1))
sells+='<tr><td >'+tmpOrder['price']+'</td><td style="color:white !important;">'+commaNumber(tmpOrder['size'])+'</td><td style="color:white !important;">'+tmpOrder['total']+'<td></tr>'
tmpOrder = {
price:null,
size:null,
total: null
}
cntShow += 1
}
totalSell += tmpSize
if(tmpOrder['price']==null)
{
tmpOrder['price'] = currentSellViewPrice
tmpOrder['size'] = tmpSize
}
else
{
tmpOrder['size'] += tmpSize
}
if(showMaximum==cntShow) break
}
$(".orderbook-table-asks tbody").html(sells)
}
async function appendOrderbooks(res)
{
var data = res.data
var action = res.action
if(action==='partial')
{
data.forEach(async ($element) => {
if($element.side == 'Sell' && realTimelastPrice <= $element.price && ask > $element.price)
{
ask = $element.price
}
if($element.side == 'Buy' && realTimelastPrice >= $element.price && bid < $element.price)
{
bid = $element.price
}
order[$element.id] = $element
orderBook[$element.price] = {
side:$element.side,
size:$element.size
}
})
}
if(action==='insert')
{
data.forEach(async ($element) => {
if($element.side == 'Sell' && realTimelastPrice <= $element.price && ask > $element.price)
{
ask = $element.price
}
if($element.side == 'Buy' && realTimelastPrice >= $element.price && bid < $element.price)
{
bid = $element.price
}
order[$element.id] = $element
orderBook[$element.price] = {
side:$element.side,
size:$element.size
}
})
}
if(action==='update')
{
data.forEach(async ($element) => {
if($element.side == 'Sell' && realTimelastPrice <= $element.price && ask > $element.price)
{
ask = $element.price
}
if($element.side == 'Buy' && realTimelastPrice >= $element.price && bid < $element.price)
{
bid = $element.price
}
var tmpPrice = order[$element.id].price
orderBook[tmpPrice] = {side:$element.side,size: $element.size}
})
}
if(action==='delete')
{
data.forEach(async ($element) => {
delete order[$element.id]
})
}
var gapPrice = 1
var debounceCalculate = _.debounce(setBids, 0, false);
debounceCalculate(gapPrice);
debounceCalculate = _.debounce(setAsks, 0, false);
debounceCalculate(gapPrice);
}
var ws = new WebSocket("wss://www.bitmex/realtime?");
ws.onmessage = function(e) {
if(e.table=="orderBookL2")
{
appendOrderbooks(e)
}
if(e.table=="instrument")
{
if('lastPrice' in e.data[0])
realTimelastPrice=data[0].lastPrice
if('bidPrice' in e.data[0])
{
bid=data[0].bidPrice;
}
if('askPrice' in e.data[0])
{
ask=data[0].askPrice;
}
}
}
基本上是bitmex订单簿上可用的分组功能。
回答如下:您可以从数据中获取条目,按键的整数值分组,并创建具有所需面的对象的对象。
第二部分使用临时对象,获取键,对键进行降序排序,并将新条目与所需总数进行映射。最后创建一个新对象。
var orders = { 8549.5: { side: 'Sell', size: 380210 }, 8549.0: { side: 'Sell', size: 51700 }, 8548.5: { side: 'Sell', size: 14136 }, 8547.5: { side: 'Sell', size: 1108 }, 8547: { side: 'Sell', size: 84190 }, 8544.5: { side: 'Sell', size: 65800 }, 8543.5: { side: 'Sell', size: 24755 }, 8542.5: { side: 'Sell', size: 6233 }, 8541.5: { side: 'Sell', size: 10206 }, 8540.5: { side: 'Sell', size: 228742 }, 8539.5: { side: 'Buy', size: 4001 }, 8538.5: { side: 'Buy', size: 50001 }, 8537.5: { side: 'Buy', size: 75000 }, 8536.5: { side: 'Buy', size: 77367 }, 8535.5: { side: 'Buy', size: 75000 } },
temp = Object
.entries(orders)
.reduce((r, [k, { side, size }]) => {
const price = Math.floor(k);
r[side][price] = r[side][price] || { price, size: 0 };
r[side][price].size += size;
return r;
}, { Sell: {}, Buy: {} }),
result = Object.fromEntries(
Object
.entries(temp)
.map(([k, o]) => [
k,
Object
.keys(o)
.sort((a, b) => b - a)
.map((total => k => ({ ...o[k], total: total += o[k].size }))(0))
])
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
更多推荐
Lodash分组依据,步长值,求和和排序在一起,以便对对象数组进行订单簿分组
发布评论