查询机构品种盈利情况
This commit is contained in:
parent
f2a18522f8
commit
24a72bfd3f
@ -1,5 +1,9 @@
|
|||||||
import type { PositionRow, PositionsData, TopTwentySum } from '../../types'
|
import type { PositionRow, PositionsData, ProfitRow, TopTwentySum } from '../../types'
|
||||||
import type { JqkaDealPositionData, JqkaPositionItem } from './types'
|
import type {
|
||||||
|
JqkaDealPositionData,
|
||||||
|
JqkaPositionItem,
|
||||||
|
JqkaPositionProfitData,
|
||||||
|
} from './types'
|
||||||
|
|
||||||
const TOP_N = 20
|
const TOP_N = 20
|
||||||
|
|
||||||
@ -91,7 +95,74 @@ export function mapJqkaDealPosition(data: JqkaDealPositionData): PositionsData {
|
|||||||
volume,
|
volume,
|
||||||
netLong,
|
netLong,
|
||||||
netShort,
|
netShort,
|
||||||
|
profitGain: [],
|
||||||
|
profitLoss: [],
|
||||||
topTwentySum,
|
topTwentySum,
|
||||||
updatedAt,
|
updatedAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function withProfitPercent(list: ProfitRow[]): ProfitRow[] {
|
||||||
|
const total = list.reduce((s, x) => s + Math.abs(x.profit), 0)
|
||||||
|
if (total <= 0) {
|
||||||
|
return list.map((x) => ({ ...x, percent: 0 }))
|
||||||
|
}
|
||||||
|
return list.map((x) => ({
|
||||||
|
...x,
|
||||||
|
percent: Number(((Math.abs(x.profit) / total) * 100).toFixed(2)),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将机构盈利接口映射为盈利 / 亏损前 20。
|
||||||
|
* day_profit 为盈利金额;顺带保留净持仓与增减。
|
||||||
|
*/
|
||||||
|
export function mapJqkaPositionProfit(data: JqkaPositionProfitData): {
|
||||||
|
profitGain: ProfitRow[]
|
||||||
|
profitLoss: ProfitRow[]
|
||||||
|
updatedAt: string
|
||||||
|
} {
|
||||||
|
const list = (data.profit_detail_list ?? [])
|
||||||
|
.map((item) => ({
|
||||||
|
name: item.company,
|
||||||
|
profit: Number(item.day_profit) || 0,
|
||||||
|
netQty: item.f024n,
|
||||||
|
change: item.f025n,
|
||||||
|
date: item.date,
|
||||||
|
}))
|
||||||
|
.filter((x) => x.profit !== 0)
|
||||||
|
|
||||||
|
const gainRaw = [...list]
|
||||||
|
.filter((x) => x.profit > 0)
|
||||||
|
.sort((a, b) => b.profit - a.profit)
|
||||||
|
.slice(0, TOP_N)
|
||||||
|
.map((x, i) => ({
|
||||||
|
rank: i + 1,
|
||||||
|
name: x.name,
|
||||||
|
profit: x.profit,
|
||||||
|
netQty: x.netQty,
|
||||||
|
change: x.change,
|
||||||
|
date: x.date,
|
||||||
|
percent: 0,
|
||||||
|
}))
|
||||||
|
|
||||||
|
const lossRaw = [...list]
|
||||||
|
.filter((x) => x.profit < 0)
|
||||||
|
.sort((a, b) => a.profit - b.profit)
|
||||||
|
.slice(0, TOP_N)
|
||||||
|
.map((x, i) => ({
|
||||||
|
rank: i + 1,
|
||||||
|
name: x.name,
|
||||||
|
profit: x.profit,
|
||||||
|
netQty: x.netQty,
|
||||||
|
change: x.change,
|
||||||
|
date: x.date,
|
||||||
|
percent: 0,
|
||||||
|
}))
|
||||||
|
|
||||||
|
return {
|
||||||
|
profitGain: withProfitPercent(gainRaw),
|
||||||
|
profitLoss: withProfitPercent(lossRaw),
|
||||||
|
updatedAt: data.date || new Date().toISOString().slice(0, 10),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,16 @@
|
|||||||
import { jqkaHttp } from '../http'
|
import { jqkaHttp } from '../http'
|
||||||
import type { JqkaDealPositionData, JqkaDealPositionResponse } from './types'
|
import type {
|
||||||
import { extractVariety, getPreviousTradingDate } from '../../utils/tradingDate'
|
JqkaDealPositionData,
|
||||||
|
JqkaDealPositionResponse,
|
||||||
|
JqkaPositionProfitData,
|
||||||
|
JqkaPositionProfitRequest,
|
||||||
|
JqkaPositionProfitResponse,
|
||||||
|
} from './types'
|
||||||
|
import {
|
||||||
|
extractVariety,
|
||||||
|
getPreviousTradingDate,
|
||||||
|
getRecentMonthRange,
|
||||||
|
} from '../../utils/tradingDate'
|
||||||
|
|
||||||
export interface GetDealPositionParams {
|
export interface GetDealPositionParams {
|
||||||
/** 合约代码,如 FG609 */
|
/** 合约代码,如 FG609 */
|
||||||
@ -42,3 +52,56 @@ export async function getDealPosition(
|
|||||||
|
|
||||||
return data.data
|
return data.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetPositionProfitRankParams {
|
||||||
|
/** 品种代码;缺省时可从 contract 推导 */
|
||||||
|
variety?: string
|
||||||
|
contract?: string
|
||||||
|
/** 默认最近一个月 */
|
||||||
|
startDate?: string
|
||||||
|
endDate?: string
|
||||||
|
/** type=company 时使用;variety 查询可不传 */
|
||||||
|
company?: string
|
||||||
|
type?: 'variety' | 'company'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同花顺 — 机构盈利排行(按品种查看最近盈利)
|
||||||
|
* POST /futgwapi/api/market/dragon_tiger/v1/position_profit_rank
|
||||||
|
*/
|
||||||
|
export async function getPositionProfitRank(
|
||||||
|
params: GetPositionProfitRankParams = {},
|
||||||
|
): Promise<JqkaPositionProfitData> {
|
||||||
|
const variety =
|
||||||
|
params.variety ??
|
||||||
|
(params.contract ? extractVariety(params.contract) : undefined)
|
||||||
|
if (!variety) {
|
||||||
|
throw new Error('盈利接口需要 variety 或 contract')
|
||||||
|
}
|
||||||
|
|
||||||
|
const range = getRecentMonthRange()
|
||||||
|
const body: JqkaPositionProfitRequest = {
|
||||||
|
variety,
|
||||||
|
type: params.type ?? 'variety',
|
||||||
|
start_date: params.startDate ?? range.startDate,
|
||||||
|
end_date: params.endDate ?? range.endDate,
|
||||||
|
}
|
||||||
|
if (params.company) {
|
||||||
|
body.company = params.company
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await jqkaHttp.post<JqkaPositionProfitResponse>(
|
||||||
|
'/futgwapi/api/market/dragon_tiger/v1/position_profit_rank',
|
||||||
|
body,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (data.code !== 0) {
|
||||||
|
throw new Error(`盈利接口失败: code=${data.code}, msg=${data.msg}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.data?.profit_detail_list) {
|
||||||
|
throw new Error('盈利接口返回空 profit_detail_list')
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.data
|
||||||
|
}
|
||||||
|
|||||||
@ -41,3 +41,39 @@ export interface JqkaDealPositionResponse {
|
|||||||
msg: string
|
msg: string
|
||||||
data: JqkaDealPositionData
|
data: JqkaDealPositionData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 机构盈利排行明细行 */
|
||||||
|
export interface JqkaProfitDetailItem {
|
||||||
|
variety: string
|
||||||
|
company: string
|
||||||
|
/** 净持仓 */
|
||||||
|
f024n: number
|
||||||
|
/** 净持仓增减 */
|
||||||
|
f025n: number
|
||||||
|
date: string
|
||||||
|
variety_name: string
|
||||||
|
/** 盈利金额(字符串数字) */
|
||||||
|
day_profit: string
|
||||||
|
year_profit: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JqkaPositionProfitData {
|
||||||
|
date: string
|
||||||
|
profit_detail_list: JqkaProfitDetailItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JqkaPositionProfitResponse {
|
||||||
|
code: number
|
||||||
|
msg: string
|
||||||
|
data: JqkaPositionProfitData
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface JqkaPositionProfitRequest {
|
||||||
|
/** 品种代码,如 FG;type=variety 时必填 */
|
||||||
|
variety: string
|
||||||
|
type: 'variety' | 'company'
|
||||||
|
start_date: string
|
||||||
|
end_date: string
|
||||||
|
/** type=company 时必填;variety 查询可省略 */
|
||||||
|
company?: string
|
||||||
|
}
|
||||||
|
|||||||
@ -5,11 +5,11 @@
|
|||||||
<el-tab-pane label="总持仓" name="total" />
|
<el-tab-pane label="总持仓" name="total" />
|
||||||
<el-tab-pane label="成交量" name="volume" />
|
<el-tab-pane label="成交量" name="volume" />
|
||||||
<el-tab-pane label="净持仓" name="net" />
|
<el-tab-pane label="净持仓" name="net" />
|
||||||
|
<el-tab-pane label="机构盈利" name="profit" />
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<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'">
|
<div v-if="tab === 'total'">
|
||||||
<PositionSumBar
|
<PositionSumBar
|
||||||
v-if="data.topTwentySum?.length"
|
v-if="data.topTwentySum?.length"
|
||||||
@ -29,7 +29,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 成交量:单列 -->
|
|
||||||
<div v-else-if="tab === 'volume'" class="cols single">
|
<div v-else-if="tab === 'volume'" class="cols single">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h3 class="volume-title">成交量前20名</h3>
|
<h3 class="volume-title">成交量前20名</h3>
|
||||||
@ -38,8 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 净持仓:净多 / 净空 -->
|
<div v-else-if="tab === 'net'" class="cols">
|
||||||
<div v-else class="cols">
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h3 class="long-title">净多持仓前20名</h3>
|
<h3 class="long-title">净多持仓前20名</h3>
|
||||||
<PositionDonut :list="data.netLong" />
|
<PositionDonut :list="data.netLong" />
|
||||||
@ -51,21 +49,50 @@
|
|||||||
<PositionTable :list="data.netShort" qty-label="净持仓" />
|
<PositionTable :list="data.netShort" qty-label="净持仓" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="cols">
|
||||||
|
<div class="col">
|
||||||
|
<h3 class="long-title">盈利机构前20名</h3>
|
||||||
|
<PositionDonut :list="profitGainAsRows" />
|
||||||
|
<ProfitTable :list="data.profitGain" />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<h3 class="short-title">亏损机构前20名</h3>
|
||||||
|
<PositionDonut :list="profitLossAsRows" />
|
||||||
|
<ProfitTable :list="data.profitLoss" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import type { PositionsData } from '../../types'
|
import type { PositionRow, 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'
|
import PositionSumBar from './PositionSumBar.vue'
|
||||||
|
import ProfitTable from './ProfitTable.vue'
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
data: PositionsData
|
data: PositionsData
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const tab = ref('total')
|
const tab = ref('total')
|
||||||
|
|
||||||
|
function toDonutRows(
|
||||||
|
list: PositionsData['profitGain'],
|
||||||
|
): PositionRow[] {
|
||||||
|
return (list ?? []).map((x) => ({
|
||||||
|
rank: x.rank,
|
||||||
|
name: x.name,
|
||||||
|
qty: Math.abs(x.profit),
|
||||||
|
change: x.change,
|
||||||
|
percent: x.percent,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const profitGainAsRows = computed(() => toDonutRows(props.data.profitGain))
|
||||||
|
const profitLossAsRows = computed(() => toDonutRows(props.data.profitLoss))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
57
src/components/position/ProfitTable.vue
Normal file
57
src/components/position/ProfitTable.vue
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<el-table :data="list" size="small" stripe class="profit-table" max-height="360">
|
||||||
|
<el-table-column prop="rank" label="名次" width="56" />
|
||||||
|
<el-table-column prop="name" label="会员简称" min-width="110" />
|
||||||
|
<el-table-column label="盈利金额" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="row.profit >= 0 ? 'price-up' : 'price-down'">
|
||||||
|
{{ formatProfit(row.profit) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="净持仓" min-width="90">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.netQty }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="增减" min-width="80">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="row.change >= 0 ? 'price-up' : 'chg-down'">
|
||||||
|
{{ row.change > 0 ? '+' : '' }}{{ row.change }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="date" label="日期" width="110" />
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ProfitRow } from '../../types'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
list: ProfitRow[]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
/** 盈利金额格式化:≥1万用「万」,≥1亿用「亿」 */
|
||||||
|
function formatProfit(n: number): string {
|
||||||
|
const sign = n > 0 ? '+' : n < 0 ? '-' : ''
|
||||||
|
const abs = Math.abs(n)
|
||||||
|
if (abs >= 1e8) {
|
||||||
|
return `${sign}${(abs / 1e8).toFixed(2)}亿`
|
||||||
|
}
|
||||||
|
if (abs >= 1e4) {
|
||||||
|
return `${sign}${(abs / 1e4).toFixed(2)}万`
|
||||||
|
}
|
||||||
|
return `${sign}${abs.toFixed(0)}`
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.profit-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chg-down {
|
||||||
|
color: var(--short);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import type { PositionRow, PositionsData } from '../types'
|
import type { PositionRow, PositionsData, ProfitRow } from '../types'
|
||||||
|
|
||||||
function makeList(names: string[], base: number): PositionRow[] {
|
function makeList(names: string[], base: number): PositionRow[] {
|
||||||
return names.map((name, i) => {
|
return names.map((name, i) => {
|
||||||
@ -22,6 +22,30 @@ function withPercent(list: PositionRow[]): PositionRow[] {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeProfit(
|
||||||
|
names: string[],
|
||||||
|
base: number,
|
||||||
|
sign: 1 | -1,
|
||||||
|
): ProfitRow[] {
|
||||||
|
const list = names.map((name, i) => {
|
||||||
|
const profit = sign * Math.floor(base * (0.2 - i * 0.01) + Math.random() * 5e6)
|
||||||
|
return {
|
||||||
|
rank: i + 1,
|
||||||
|
name,
|
||||||
|
profit,
|
||||||
|
netQty: Math.floor((Math.random() - 0.5) * 80000),
|
||||||
|
change: Math.floor((Math.random() - 0.5) * 2000),
|
||||||
|
date: '2026-07-21',
|
||||||
|
percent: 0,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const total = list.reduce((s, x) => s + Math.abs(x.profit), 0)
|
||||||
|
return list.map((x) => ({
|
||||||
|
...x,
|
||||||
|
percent: total > 0 ? Number(((Math.abs(x.profit) / total) * 100).toFixed(2)) : 0,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
const longNames = [
|
const longNames = [
|
||||||
'中财期货',
|
'中财期货',
|
||||||
'东证期货',
|
'东证期货',
|
||||||
@ -73,6 +97,8 @@ const short = withPercent(makeList(shortNames, 640000))
|
|||||||
const volume = withPercent(makeList(longNames, 480000))
|
const volume = withPercent(makeList(longNames, 480000))
|
||||||
const netLong = withPercent(makeList(longNames.slice(0, 12), 120000))
|
const netLong = withPercent(makeList(longNames.slice(0, 12), 120000))
|
||||||
const netShort = withPercent(makeList(shortNames.slice(0, 12), 110000))
|
const netShort = withPercent(makeList(shortNames.slice(0, 12), 110000))
|
||||||
|
const profitGain = makeProfit(longNames.slice(0, 12), 2e8, 1)
|
||||||
|
const profitLoss = makeProfit(shortNames.slice(0, 12), 1.5e8, -1)
|
||||||
|
|
||||||
export const positionsMock: PositionsData = {
|
export const positionsMock: PositionsData = {
|
||||||
long,
|
long,
|
||||||
@ -80,6 +106,8 @@ export const positionsMock: PositionsData = {
|
|||||||
volume,
|
volume,
|
||||||
netLong,
|
netLong,
|
||||||
netShort,
|
netShort,
|
||||||
|
profitGain,
|
||||||
|
profitLoss,
|
||||||
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 },
|
||||||
|
|||||||
@ -11,8 +11,8 @@ import { mapBaiduQuotationToQuote } from '../api/baidu/mapQuote'
|
|||||||
import { mapBaiduKlineToCandles } from '../api/baidu/mapKline'
|
import { mapBaiduKlineToCandles } from '../api/baidu/mapKline'
|
||||||
import { mapBaiduNewsToItems } from '../api/baidu/mapNews'
|
import { mapBaiduNewsToItems } from '../api/baidu/mapNews'
|
||||||
import type { BaiduKlineType } from '../api/baidu/types'
|
import type { BaiduKlineType } from '../api/baidu/types'
|
||||||
import { getDealPosition } from '../api/jqka/position'
|
import { getDealPosition, getPositionProfitRank } from '../api/jqka/position'
|
||||||
import { mapJqkaDealPosition } from '../api/jqka/mapPosition'
|
import { mapJqkaDealPosition, mapJqkaPositionProfit } from '../api/jqka/mapPosition'
|
||||||
import {
|
import {
|
||||||
extractVariety,
|
extractVariety,
|
||||||
getPreviousTradingDate,
|
getPreviousTradingDate,
|
||||||
@ -128,7 +128,9 @@ export const useQuotaStore = defineStore('quota', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拉取会员持仓。日期默认上一交易日;若遇节假日空数据则再往前最多试 5 个交易日。
|
* 拉取会员持仓 + 机构盈利。
|
||||||
|
* 持仓日期默认上一交易日;若遇节假日空数据则再往前最多试 5 个交易日。
|
||||||
|
* 盈利默认最近一个月、按当前品种查询。
|
||||||
*/
|
*/
|
||||||
async function fetchPositions() {
|
async function fetchPositions() {
|
||||||
positionsLoading.value = true
|
positionsLoading.value = true
|
||||||
@ -153,6 +155,16 @@ export const useQuotaStore = defineStore('quota', () => {
|
|||||||
if (!mapped) {
|
if (!mapped) {
|
||||||
throw new Error(`持仓无数据(已回溯至 ${date})`)
|
throw new Error(`持仓无数据(已回溯至 ${date})`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const profitRaw = await getPositionProfitRank({ variety, contract })
|
||||||
|
const profit = mapJqkaPositionProfit(profitRaw)
|
||||||
|
mapped.profitGain = profit.profitGain
|
||||||
|
mapped.profitLoss = profit.profitLoss
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[quota] 拉取机构盈利失败', e)
|
||||||
|
}
|
||||||
|
|
||||||
positions.value = mapped
|
positions.value = mapped
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
positionsError.value = e
|
positionsError.value = e
|
||||||
|
|||||||
@ -82,6 +82,20 @@ export interface PositionRow {
|
|||||||
percent: number
|
percent: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 机构盈利排行行(day_profit) */
|
||||||
|
export interface ProfitRow {
|
||||||
|
rank: number
|
||||||
|
name: string
|
||||||
|
/** 盈利金额(可正可负) */
|
||||||
|
profit: number
|
||||||
|
/** 净持仓 f024n */
|
||||||
|
netQty: number
|
||||||
|
/** 净持仓增减 f025n */
|
||||||
|
change: number
|
||||||
|
date: string
|
||||||
|
percent: number
|
||||||
|
}
|
||||||
|
|
||||||
/** 前 20 多空持仓汇总(按交易日) */
|
/** 前 20 多空持仓汇总(按交易日) */
|
||||||
export interface TopTwentySum {
|
export interface TopTwentySum {
|
||||||
tradeDate: string
|
tradeDate: string
|
||||||
@ -100,6 +114,10 @@ export interface PositionsData {
|
|||||||
netLong: PositionRow[]
|
netLong: PositionRow[]
|
||||||
/** 净空持仓(f024n < 0,qty 取绝对值) */
|
/** 净空持仓(f024n < 0,qty 取绝对值) */
|
||||||
netShort: PositionRow[]
|
netShort: PositionRow[]
|
||||||
|
/** 盈利机构前 20(day_profit > 0) */
|
||||||
|
profitGain: ProfitRow[]
|
||||||
|
/** 亏损机构前 20(day_profit < 0) */
|
||||||
|
profitLoss: ProfitRow[]
|
||||||
/** 前 20 持仓量汇总 */
|
/** 前 20 持仓量汇总 */
|
||||||
topTwentySum: TopTwentySum[]
|
topTwentySum: TopTwentySum[]
|
||||||
updatedAt: string
|
updatedAt: string
|
||||||
|
|||||||
@ -33,3 +33,19 @@ export function extractVariety(contract: string): string {
|
|||||||
const m = contract.match(/^([A-Za-z]+)/)
|
const m = contract.match(/^([A-Za-z]+)/)
|
||||||
return m ? m[1] : contract
|
return m ? m[1] : contract
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近一个月日期区间(含起止日),用于机构盈利等按区间查询的接口。
|
||||||
|
*/
|
||||||
|
export function getRecentMonthRange(from: Date = new Date()): {
|
||||||
|
startDate: string
|
||||||
|
endDate: string
|
||||||
|
} {
|
||||||
|
const end = new Date(from.getFullYear(), from.getMonth(), from.getDate())
|
||||||
|
const start = new Date(end)
|
||||||
|
start.setMonth(start.getMonth() - 1)
|
||||||
|
return {
|
||||||
|
startDate: formatDateYmd(start),
|
||||||
|
endDate: formatDateYmd(end),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user