snapshots and pnls
配置项如下
function randInt(range) {
return parseInt(range * Math.random());
}
function genData(origin, step, length) {
const res = [];
for (let i = 0; i < length; i ++) {
origin += step[randInt(step.length)];
origin = Math.abs(origin);
res.push([i, origin]);
}
return res;
}
function calcPnlAndPos(orders, price) {
return orders.reduce(
(prev, cur) => [
prev[0] + cur[2] * (price - cur[1]),
prev[1] + cur[2]
],
[0, 0]
);
}
const data = {};
const length = 600;
data.price = genData(3210, [-5, 0, 5], length);
data.vol = genData(20, [-1, 0, 1], length);
data.bidVol = genData(20, [-1, 0, 1], length);
data.askVol = genData(20, [-1, 0, 1], length);
data.bidPrice = data.price.map(
([time, value]) => [time, value + 5 * randInt(2)]
);
data.askPrice = data.price.map(
([time, value]) => [time, value - 5 * randInt(2)]
);
let com = 0;
const comRate = 0.001;
data.com = [[0, 0]];
data.orders = [];
data.pnl = [[0, 0]];
data.npnl = [[0, 0]];
data.pos = [[0, 0]];
for (let i = 1; i < length; i ++) {
if (data.price[i][1] > data.price[i - 1][1]) {
data.orders.push([data.price[i][0], data.price[i][1], 1]);
com += data.price[i][1] * comRate;
} else if (data.price[i][1] < data.price[i - 1][1]) {
data.orders.push([data.price[i][0], data.price[i][1], -1]);
com += data.price[i][1] * comRate;
}
data.com.push([i, com]);
let [pnl, pos] = calcPnlAndPos(data.orders, data.price[i][1]);
data.pnl.push([i, pnl]);
data.npnl.push([i, pnl - com]);
data.pos.push([i, pos]);
}
option = {
title: {
text: 'Intraday Chart',
x: 'center',
y: 0
},
dataZoom: [
{
id: 'dataZoomX',
type: 'slider',
xAxisIndex: [0, 1, 2],
filterMode: 'filter',
start: 0,
end: 100,
zoomLock: false,
}, {
type: 'inside',
},
],
tooltip : {
trigger: 'axis',
axisPointer: {
animation: false,
},
},
grid: [
{x: '7%', y: '7%', width: '85%', height: '20%'},
{x: '7%', y: '32%', width: '85%', height: '30%'},
{x: '7%', y: '67%', width: '85%', height: '25%'}
],
xAxis: [
{gridIndex: 0},
{gridIndex: 1},
{gridIndex: 2},
],
yAxis: [
{gridIndex: 0, boundaryGap: ['10%', '10%']},
{gridIndex: 0, boundaryGap: ['10%', '10%']},
{gridIndex: 1, boundaryGap: ['10%', '10%'], scale: true},
{gridIndex: 2, min: 0, max: 100},
{gridIndex: 2, min: -100, max: 50},
{gridIndex: 2, min: -50, max: 100, inverse: true, show: false}
],
series: [
{
name: 'pnl',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
showSymbol: false,
hoverAnimation: false,
data: data.pnl
},
{
name: 'commission',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
showSymbol: false,
hoverAnimation: false,
data: data.com
},
{
name: 'net pnl',
type: 'line',
xAxisIndex: 0,
yAxisIndex: 0,
showSymbol: false,
hoverAnimation: false,
data: data.npnl
},
{
name: 'position',
type: 'bar',
xAxisIndex: 0,
yAxisIndex: 1,
data: data.pos
},
{
name: 'orders',
type: 'scatter',
xAxisIndex: 1,
yAxisIndex: 2,
symbolSize: (value, params) => Math.abs(value[2]) * 4,
itemStyle: {
normal: {
color: ({ data }) => data[2] > 0 ? 'red' : 'green'
}
},
hoverAnimation: false,
data: data.orders
},
{
name: 'price',
type: 'line',
xAxisIndex: 1,
yAxisIndex: 2,
showSymbol: false,
hoverAnimation: false,
data: data.price
},
{
name: 'bid price',
type: 'line',
xAxisIndex: 1,
yAxisIndex: 2,
showSymbol: false,
hoverAnimation: false,
data: data.bidPrice,
},
{
name: 'ask price',
type: 'line',
xAxisIndex: 1,
yAxisIndex: 2,
showSymbol: false,
hoverAnimation: false,
data: data.askPrice,
},
{
name: 'volume',
type: 'bar',
xAxisIndex: 2,
yAxisIndex: 3,
data: data.vol
},
{
name: 'bid volume',
type: 'bar',
xAxisIndex: 2,
yAxisIndex: 4,
data: data.bidVol
},
{
name: 'ask volume',
type: 'bar',
xAxisIndex: 2,
yAxisIndex: 5,
data: data.askVol
}
]
};