持仓数据的 前20名总持仓汇总
This commit is contained in:
parent
249be8d882
commit
7728061d00
@ -9,17 +9,23 @@
|
|||||||
<span v-if="data.updatedAt" class="updated">数据日期 {{ data.updatedAt }}</span>
|
<span v-if="data.updatedAt" class="updated">数据日期 {{ data.updatedAt }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 总持仓:多 / 空 -->
|
<!-- 总持仓:多空汇总柱状图 + 多 / 空前20 -->
|
||||||
<div v-if="tab === 'total'" class="cols">
|
<div v-if="tab === 'total'">
|
||||||
<div class="col">
|
<PositionSumBar
|
||||||
<h3 class="long-title">多单持仓前20名</h3>
|
v-if="data.topTwentySum?.length"
|
||||||
<PositionDonut :list="data.long" />
|
:list="data.topTwentySum"
|
||||||
<PositionTable :list="data.long" qty-label="多单" />
|
/>
|
||||||
</div>
|
<div class="cols">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h3 class="short-title">空单持仓前20名</h3>
|
<h3 class="long-title">多单持仓前20名</h3>
|
||||||
<PositionDonut :list="data.short" />
|
<PositionDonut :list="data.long" />
|
||||||
<PositionTable :list="data.short" qty-label="空单" />
|
<PositionTable :list="data.long" qty-label="多单" />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<h3 class="short-title">空单持仓前20名</h3>
|
||||||
|
<PositionDonut :list="data.short" />
|
||||||
|
<PositionTable :list="data.short" qty-label="空单" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -53,6 +59,7 @@ import { ref } from 'vue'
|
|||||||
import type { PositionsData } from '../../types'
|
import type { PositionsData } from '../../types'
|
||||||
import PositionDonut from './PositionDonut.vue'
|
import PositionDonut from './PositionDonut.vue'
|
||||||
import PositionTable from './PositionTable.vue'
|
import PositionTable from './PositionTable.vue'
|
||||||
|
import PositionSumBar from './PositionSumBar.vue'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
data: PositionsData
|
data: PositionsData
|
||||||
|
|||||||
103
src/components/position/PositionSumBar.vue
Normal file
103
src/components/position/PositionSumBar.vue
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<div class="sum-bar">
|
||||||
|
<h3 class="title">前20多空总持仓</h3>
|
||||||
|
<v-chart class="chart" :option="option" autoresize />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { use } from 'echarts/core'
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers'
|
||||||
|
import { BarChart } from 'echarts/charts'
|
||||||
|
import {
|
||||||
|
GridComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
LegendComponent,
|
||||||
|
} from 'echarts/components'
|
||||||
|
import type { EChartsOption } from 'echarts'
|
||||||
|
import VChart from 'vue-echarts'
|
||||||
|
import type { TopTwentySum } from '../../types'
|
||||||
|
|
||||||
|
use([CanvasRenderer, BarChart, GridComponent, TooltipComponent, LegendComponent])
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
list: TopTwentySum[]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const option = computed((): EChartsOption => {
|
||||||
|
// 接口通常新→旧,图表按时间从左到右
|
||||||
|
const sorted = [...props.list].sort((a, b) =>
|
||||||
|
a.tradeDate.localeCompare(b.tradeDate),
|
||||||
|
)
|
||||||
|
const dates = sorted.map((x) => x.tradeDate)
|
||||||
|
const longData = sorted.map((x) => x.longSum)
|
||||||
|
const shortData = sorted.map((x) => x.shortSum)
|
||||||
|
|
||||||
|
return {
|
||||||
|
color: ['#e54545', '#0ea5a0'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: { type: 'shadow' },
|
||||||
|
valueFormatter: (v) =>
|
||||||
|
typeof v === 'number' ? v.toLocaleString('zh-CN') : String(v ?? ''),
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['多总持仓', '空总持仓'],
|
||||||
|
top: 0,
|
||||||
|
right: 8,
|
||||||
|
textStyle: { fontSize: 12 },
|
||||||
|
},
|
||||||
|
grid: { left: 56, right: 16, top: 36, bottom: 28 },
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: dates,
|
||||||
|
axisLabel: { fontSize: 11 },
|
||||||
|
axisTick: { alignWithLabel: true },
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
scale: true,
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 10,
|
||||||
|
formatter: (v: number) =>
|
||||||
|
v >= 10000 ? `${(v / 10000).toFixed(0)}万` : String(v),
|
||||||
|
},
|
||||||
|
splitLine: { lineStyle: { type: 'dashed', color: '#eee' } },
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '多总持仓',
|
||||||
|
type: 'bar',
|
||||||
|
data: longData,
|
||||||
|
barMaxWidth: 36,
|
||||||
|
itemStyle: { color: '#e54545', borderRadius: [2, 2, 0, 0] },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '空总持仓',
|
||||||
|
type: 'bar',
|
||||||
|
data: shortData,
|
||||||
|
barMaxWidth: 36,
|
||||||
|
itemStyle: { color: '#0ea5a0', borderRadius: [2, 2, 0, 0] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.sum-bar {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 0 0 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--text-primary, #303133);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart {
|
||||||
|
height: 240px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -83,6 +83,7 @@ export const positionsMock: PositionsData = {
|
|||||||
topTwentySum: [
|
topTwentySum: [
|
||||||
{ tradeDate: '2026-07-15', longSum: 1073446, shortSum: 1502020 },
|
{ tradeDate: '2026-07-15', longSum: 1073446, shortSum: 1502020 },
|
||||||
{ tradeDate: '2026-07-14', longSum: 1094199, shortSum: 1519906 },
|
{ tradeDate: '2026-07-14', longSum: 1094199, shortSum: 1519906 },
|
||||||
|
{ tradeDate: '2026-07-13', longSum: 1095204, shortSum: 1537419 },
|
||||||
],
|
],
|
||||||
updatedAt: '2026-07-15',
|
updatedAt: '2026-07-15',
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user